[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[bug-inetutils] [PATCH] rexec client
From: |
Giuseppe Scrivano |
Subject: |
[bug-inetutils] [PATCH] rexec client |
Date: |
Tue, 28 Jul 2009 23:11:06 +0200 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/23.0.96 (gnu/linux) |
Hello,
I saw inetutils has a rexec server but it is missing a rexec client, so
I wrote one.
Regards,
Giuseppe
>From 0577ce495883b1a240c946602db2031783f37d23 Mon Sep 17 00:00:00 2001
From: Giuseppe Scrivano <address@hidden>
Date: Tue, 28 Jul 2009 17:43:45 +0200
Subject: [PATCH] rexec: new program
* configure.ac: Build rexec.
* Makefile.am: Ditto.
* doc/inetutils.texi: Document the new program.
* rexec/Makefile.am: New file.
* rexec/rexec.c: New file.
---
Makefile.am | 2 +-
configure.ac | 2 +
doc/inetutils.texi | 34 ++++++
rexec/Makefile.am | 34 ++++++
rexec/rexec.c | 328 ++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 399 insertions(+), 1 deletions(-)
create mode 100644 rexec/Makefile.am
create mode 100644 rexec/rexec.c
diff --git a/Makefile.am b/Makefile.am
index 061af2b..7d2d1b8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -25,7 +25,7 @@ EXTRA_DIST = README-alpha paths ChangeLog.0
SUBDIRS = lib headers libinetutils libtelnet \
hostname inetd telnetd libls ftpd rshd rlogind uucpd rexecd syslogd \
tftpd talkd telnet ftp rsh rcp rlogin tftp logger gwhois talk \
- libicmp ping doc ifconfig traceroute tests
+ libicmp ping doc ifconfig traceroute rexec tests
DISTCLEANFILES = pathdefs.make paths.defs
diff --git a/configure.ac b/configure.ac
index fdff8d3..0b8ebb5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -108,6 +108,7 @@ IU_ENABLE_CLIENT(hostname)
IU_ENABLE_CLIENT(ping)
IU_ENABLE_CLIENT(ping6)
IU_ENABLE_CLIENT(rcp)
+IU_ENABLE_CLIENT(rexec)
IU_ENABLE_CLIENT(rlogin)
IU_ENABLE_CLIENT(rsh)
IU_ENABLE_CLIENT(logger)
@@ -820,6 +821,7 @@ ftpd/Makefile
hostname/Makefile
inetd/Makefile
rcp/Makefile
+rexec/Makefile
rexecd/Makefile
rlogin/Makefile
rlogind/Makefile
diff --git a/doc/inetutils.texi b/doc/inetutils.texi
index 86360fd..555508f 100644
--- a/doc/inetutils.texi
+++ b/doc/inetutils.texi
@@ -34,6 +34,7 @@
* logger: (inetutils)logger invocation. Send messages to the system
log.
* ping: (inetutils)ping invocation. Packets to network hosts.
* rcp: (inetutils)rcp invocation. Remote copy
+* rexec: (inetutils)rexec invocation. Remote execution client.
* rexecd: (inetutils)rexecd invocation. Remote execution server.
* rlogin: (inetutils)rlogin invocation. Remote login.
* rlogind: (inetutils)rlogind invocation. Remote login server.
@@ -107,6 +108,7 @@ Clients
* tftp invocation:: TFTP client.
* rsh invocation:: Remote shell.
* rlogin invocation:: Remote login.
+* rexec invocation:: Remote execution client.
* rcp invocation:: Remote copy
* talk invocation:: Talk client.
* telnet invocation:: User interface to TELNET.
@@ -1751,6 +1753,38 @@ The destination user and hostname may have to be
specified as
@samp{rhost.rname} when the destination machine is running the 4.2BSD
version of @command{rcp}.
address@hidden rexec invocation
address@hidden @command{talk}: a remote execution program
address@hidden talk
+
address@hidden is a program that executes a program on another host.
+
address@hidden Invoking
+
+The command line arguments are as follows:
+
address@hidden @var
address@hidden --error
+Specify the TCP port to use for stderr redirection, in case it is not
+specified a random port will be used.
+
address@hidden --host
+Specify the host where connect to.
+
address@hidden --noerr
+If specified, an error stream will not be created.
+
address@hidden --password
+Specify the password for logging-in.
+
address@hidden --port
+Specify to which port connect to, if it is not specified by default
+use 512.
+
address@hidden --user
+Specify the user to log into the server.
address@hidden table
+
@node talk invocation
@chapter @command{talk}: a communication program
@cindex talk
diff --git a/rexec/Makefile.am b/rexec/Makefile.am
new file mode 100644
index 0000000..49a69cb
--- /dev/null
+++ b/rexec/Makefile.am
@@ -0,0 +1,34 @@
+# Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
+# This file is part of GNU Inetutils.
+#
+# GNU Inetutils is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Inetutils is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Inetutils; see the file COPYING. If not, write
+# to the Free Software Foundation, Inc., 51 Franklin Street,
+# Fifth Floor, Boston, MA 02110-1301 USA.
+
+bin_PROGRAMS = @rexec_BUILD@
+
+EXTRA_PROGRAMS = rexec
+
+rexec_SOURCES = rexec.c
+
+noinst_HEADERS =
+
address@hidden@
+
+INCLUDES = -I$(top_srcdir)/lib -I../lib -I$(top_srcdir)/libinetutils
+AM_CPPFLAGS = $(PATHDEF_DEFPATH) $(PATHDEF_BSHELL)
+
+LIBCRYPT = @LIBCRYPT@
+
+LDADD = -L../libinetutils -linetutils -L../lib -lgnu $(LIBCRYPT)
diff --git a/rexec/rexec.c b/rexec/rexec.c
new file mode 100644
index 0000000..3819af1
--- /dev/null
+++ b/rexec/rexec.c
@@ -0,0 +1,328 @@
+/*
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+ This file is part of GNU Inetutils.
+
+ GNU Inetutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ GNU Inetutils is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* Written by Giuseppe Scrivano <address@hidden>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_FILIO_H
+# include <sys/filio.h>
+#endif
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+
+#include <stdarg.h>
+#include <progname.h>
+#include <argp.h>
+#include <error.h>
+#include "libinetutils.h"
+
+#define MAX3(a, b, c) (MAX (MAX (a, b), c))
+
+const char doc[] = "remote execution client";
+static char args_doc[] = "COMMAND";
+
+const char *program_authors[] =
+ {
+ "Giuseppe Scrivano",
+ NULL
+ };
+
+static struct argp_option options[] = {
+ {"user", 'u', "user", 0, "Specify the user"},
+ {"host", 'h', "host", 0, "Specify the host"},
+ {"password", 'p', "password", 0, "Specify the password"},
+ {"port", 'P', "port", 0, "Specify the port to connect to"},
+ {"noerr", 'n', NULL, 0, "Disable the stderr stream"},
+ {"error", 'e', "error", 0, "Specify a TCP port to use for stderr"},
+ { 0 }
+};
+
+struct arguments
+{
+ const char *host;
+ const char *user;
+ const char *password;
+ const char *command;
+ int port;
+ int use_err;
+ int err_port;
+};
+
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+ struct arguments *arguments = state->input;
+
+ switch (key)
+ {
+ case 'u':
+ arguments->user = arg;
+ break;
+ case 'p':
+ arguments->password = arg;
+ break;
+ case 'P':
+ arguments->port = atoi (arg);
+ break;
+ case 'e':
+ arguments->err_port = atoi (arg);
+ break;
+ case 'h':
+ arguments->host = arg;
+ break;
+ case 'n':
+ arguments->use_err = 0;
+ break;
+ case ARGP_KEY_ARG:
+ arguments->command = arg;
+ state->next = state->argc;
+ }
+
+ return 0;
+}
+
+static struct argp argp = {options, parse_opt, args_doc, doc};
+
+static void do_rexec (struct arguments *arguments);
+
+int
+main (int argc, char **argv)
+{
+ struct arguments arguments;
+
+ set_program_name (argv[0]);
+
+ iu_argp_init ("rexec", program_authors);
+
+ arguments.user = NULL;
+ arguments.password = NULL;
+ arguments.host = NULL;
+ arguments.command = NULL;
+ arguments.err_port = 0;
+ arguments.use_err = 1;
+ arguments.port = 512;
+
+ argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, &arguments);
+
+ if (arguments.user == NULL)
+ error (EXIT_FAILURE, 0, "user not specified");
+
+ if (arguments.password == NULL)
+ error (EXIT_FAILURE, 0, "password not specified");
+
+ if (arguments.host == NULL)
+ error (EXIT_FAILURE, 0, "host not specified");
+
+ if (arguments.command == NULL)
+ error (EXIT_FAILURE, 0, "command not specified");
+
+ do_rexec (&arguments);
+
+ exit (0);
+}
+
+static void
+safe_write (int socket, const char *str, size_t len)
+{
+ if (write (socket, str, len) < 0)
+ error (EXIT_FAILURE, errno, "error sending data");
+}
+
+void
+do_rexec (struct arguments *arguments)
+{
+ int err;
+ char buffer[1024];
+ int sock;
+ char port_str[6];
+ struct sockaddr_in addr;
+ struct hostent *host;
+ int stdin = STDIN_FILENO;
+ int err_sock = -1;
+
+ sock = socket (AF_INET, SOCK_STREAM, 0);
+ if (sock < 0)
+ error (EXIT_FAILURE, errno, "cannot open socket");
+
+ host = gethostbyname (arguments->host);
+
+ if (host == NULL)
+ error (EXIT_FAILURE, errno, "cannot find host");
+
+ memset (&addr, 0, sizeof (addr));
+
+ addr.sin_family = AF_INET;
+ memmove ((caddr_t) &addr.sin_addr,
+#ifdef HAVE_STRUCT_HOSTENT_H_ADDR_LIST
+ host->h_addr_list[0],
+#else
+ host->h_addr,
+#endif
+ host->h_length);
+
+ addr.sin_port = htons ((short)arguments->port);
+
+ if (connect (sock, &addr, sizeof (addr)) < 0)
+ error (EXIT_FAILURE, errno, "cannot connect to the specified host");
+
+ if (!arguments->use_err)
+ {
+ port_str[0] = '0';
+ port_str[1] = '\0';
+ safe_write (sock, port_str, 2);
+ arguments->err_port = 0;
+ }
+ else
+ {
+ struct sockaddr_in serv_addr;
+ socklen_t len;
+ int serv_sock = socket (AF_INET, SOCK_STREAM, 0);
+
+ if (serv_sock < 0)
+ error (EXIT_FAILURE, errno, "cannot open socket");
+
+ memset (&serv_addr, 0, sizeof (serv_addr));
+
+ serv_addr.sin_port = arguments->err_port;
+ if (bind (serv_sock, &serv_addr, sizeof (serv_addr)) < 0)
+ error (EXIT_FAILURE, errno, "cannot bind socket");
+
+ len = sizeof (serv_addr);
+ if (getsockname (serv_sock, &serv_addr, &len))
+ error (EXIT_FAILURE, errno, "error reading socket port");
+
+ arguments->err_port = ntohs (serv_addr.sin_port);
+
+ if (listen (serv_sock, 1))
+ error (EXIT_FAILURE, errno, "error listening on socket");
+
+ sprintf (port_str, "%i", arguments->err_port);
+ safe_write (sock, port_str, strlen (port_str) + 1);
+
+ err_sock = accept (serv_sock, &serv_addr, &len);
+
+ if (err_sock < 0)
+ error (EXIT_FAILURE, errno, "error accepting connection");
+
+ shutdown (err_sock, SHUT_WR);
+
+ close (serv_sock);
+ }
+
+ safe_write (sock, arguments->user, strlen (arguments->user) + 1);
+ safe_write (sock, arguments->password, strlen (arguments->password) + 1);
+ safe_write (sock, arguments->command, strlen (arguments->command) + 1);
+
+ while (1)
+ {
+ int ret;
+ fd_set rsocks;
+
+ /* No other data to read. */
+ if (sock < 0 && err_sock < 0)
+ break;
+
+ FD_ZERO (&rsocks);
+ if (0 <= sock)
+ FD_SET (sock, &rsocks);
+ if (0 <= stdin)
+ FD_SET (stdin, &rsocks);
+ if (0 <= err_sock)
+ FD_SET (err_sock, &rsocks);
+
+ ret = select (MAX3 (sock, stdin, err_sock) + 1, &rsocks, NULL, NULL,
NULL);
+
+ if (ret == -1)
+ error (EXIT_FAILURE, errno, "error select");
+
+ if (0 <= stdin && FD_ISSET (stdin, &rsocks))
+ {
+ err = read (stdin, buffer, 1024);
+
+ if (err < 0)
+ error (EXIT_FAILURE, errno, "error reading stdin");
+
+ if (!err)
+ {
+ shutdown (sock, SHUT_WR);
+ close (stdin);
+ stdin = -1;
+ continue;
+ }
+
+ if (write (STDOUT_FILENO, buffer, err) < 0)
+ error (EXIT_FAILURE, errno, "error writing");
+ }
+
+ if (0 <= sock && FD_ISSET (sock, &rsocks))
+ {
+ err = read (sock, buffer, 1024);
+
+ if (err < 0)
+ error (EXIT_FAILURE, errno, "error reading out stream");
+
+ if (!err)
+ {
+ close (sock);
+ sock = -1;
+ continue;
+ }
+
+ if (write (STDOUT_FILENO, buffer, err) < 0)
+ error (EXIT_FAILURE, errno, "error writing");
+ }
+
+ if (0 <= err_sock && FD_ISSET (err_sock, &rsocks))
+ {
+ err = read (err_sock, buffer, 1024);
+
+ if (err < 0)
+ error (EXIT_FAILURE, errno, "error reading err stream");
+
+ if (!err)
+ {
+ close (err_sock);
+ err_sock = -1;
+ continue;
+ }
+
+ if (write (STDERR_FILENO, buffer, err) < 0)
+ error (EXIT_FAILURE, errno, "error writing");
+ }
+ }
+}
--
1.6.3.3
- [bug-inetutils] [PATCH] rexec client,
Giuseppe Scrivano <=