summaryrefslogtreecommitdiff
path: root/usr.bin/rsh
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
commitd6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch)
treeece253b876159b39c620e62b6c9b1174642e070e /usr.bin/rsh
initial import of NetBSD tree
Diffstat (limited to 'usr.bin/rsh')
-rw-r--r--usr.bin/rsh/Makefile10
-rw-r--r--usr.bin/rsh/pathnames.h37
-rw-r--r--usr.bin/rsh/rsh.1182
-rw-r--r--usr.bin/rsh/rsh.c481
4 files changed, 710 insertions, 0 deletions
diff --git a/usr.bin/rsh/Makefile b/usr.bin/rsh/Makefile
new file mode 100644
index 00000000000..8528f50bed5
--- /dev/null
+++ b/usr.bin/rsh/Makefile
@@ -0,0 +1,10 @@
+# from: @(#)Makefile 5.6 (Berkeley) 9/27/90
+# $Id: Makefile,v 1.1 1995/10/18 08:46:03 deraadt Exp $
+
+PROG= rsh
+SRCS= rsh.c
+BINOWN= root
+BINMODE=4555
+.PATH: ${.CURDIR}/../rlogin
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/rsh/pathnames.h b/usr.bin/rsh/pathnames.h
new file mode 100644
index 00000000000..0e2d92d36ce
--- /dev/null
+++ b/usr.bin/rsh/pathnames.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)pathnames.h 5.2 (Berkeley) 4/9/90
+ * $Id: pathnames.h,v 1.1 1995/10/18 08:46:03 deraadt Exp $
+ */
+
+#define _PATH_RLOGIN "/usr/bin/rlogin"
diff --git a/usr.bin/rsh/rsh.1 b/usr.bin/rsh/rsh.1
new file mode 100644
index 00000000000..4e9adce263c
--- /dev/null
+++ b/usr.bin/rsh/rsh.1
@@ -0,0 +1,182 @@
+.\" Copyright (c) 1983, 1990 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" from: @(#)rsh.1 6.10 (Berkeley) 7/24/91
+.\" $Id: rsh.1,v 1.1 1995/10/18 08:46:03 deraadt Exp $
+.\"
+.Dd July 24, 1991
+.Dt RSH 1
+.Os BSD 4.2
+.Sh NAME
+.Nm rsh
+.Nd remote shell
+.Sh SYNOPSIS
+.Nm rsh
+.Op Fl Kdnx
+.Op Fl k Ar realm
+.Op Fl l Ar username
+.Ar host
+.Op command
+.Sh DESCRIPTION
+.Nm Rsh
+executes
+.Ar command
+on
+.Ar host .
+.Pp
+.Nm Rsh
+copies its standard input to the remote command, the standard
+output of the remote command to its standard output, and the
+standard error of the remote command to its standard error.
+Interrupt, quit and terminate signals are propagated to the remote
+command;
+.Nm rsh
+normally terminates when the remote command does.
+The options are as follows:
+.Bl -tag -width flag
+.It Fl K
+The
+.Fl K
+option turns off all Kerberos authentication.
+.It Fl d
+The
+.Fl d
+option turns on socket debugging (using
+.Xr setsockopt 2 )
+on the
+.Tn TCP
+sockets used for communication with the remote host.
+.It Fl k
+The
+.Fl k
+option causes
+.Nm rsh
+to obtain tickets for the remote host in
+.Ar realm
+instead of the remote host's realm as determined by
+.Xr krb_realmofhost 3 .
+.It Fl l
+By default, the remote username is the same as the local username.
+The
+.Fl l
+option allows the remote name to be specified.
+Kerberos authentication is used, and authorization is determined
+as in
+.Xr rlogin 1 .
+.It Fl n
+The
+.Fl n
+option redirects input from the special device
+.Pa /dev/null
+(see the
+.Sx BUGS
+section of this manual page).
+.It Fl x
+The
+.Fl x
+option turns on
+.Tn DES
+encryption for all data exchange.
+This may introduce a significant delay in response time.
+.El
+.Pp
+If no
+.Ar command
+is specified, you will be logged in on the remote host using
+.Xr rlogin 1 .
+.Pp
+Shell metacharacters which are not quoted are interpreted on local machine,
+while quoted metacharacters are interpreted on the remote machine.
+For example, the command
+.Pp
+.Dl rsh otherhost cat remotefile >> localfile
+.Pp
+appends the remote file
+.Ar remotefile
+to the local file
+.Ar localfile ,
+while
+.Pp
+.Dl rsh otherhost cat remotefile \&">>\&" other_remotefile
+.Pp
+appends
+.Ar remotefile
+to
+.Ar other_remotefile .
+.\" .Pp
+.\" Many sites specify a large number of host names as commands in the
+.\" directory /usr/hosts.
+.\" If this directory is included in your search path, you can use the
+.\" shorthand ``host command'' for the longer form ``rsh host command''.
+.Sh FILES
+.Bl -tag -width /etc/hosts -compact
+.It Pa /etc/hosts
+.El
+.Sh SEE ALSO
+.Xr rlogin 1 ,
+.Xr kerberos 3 ,
+.Xr krb_sendauth 3 ,
+.Xr krb_realmofhost 3
+.Sh HISTORY
+The
+.Nm rsh
+command appeared in
+.Bx 4.2 .
+.Sh BUGS
+If you are using
+.Xr csh 1
+and put a
+.Nm rsh
+in the background without redirecting its input away from the terminal,
+it will block even if no reads are posted by the remote command.
+If no input is desired you should redirect the input of
+.Nm rsh
+to
+.Pa /dev/null
+using the
+.Fl n
+option.
+.Pp
+You cannot run an interactive command
+(like
+.Xr rogue 6
+or
+.Xr vi 1 )
+using
+.Nm rsh ;
+use
+.Xr rlogin 1
+instead.
+.Pp
+Stop signals stop the local
+.Nm rsh
+process only; this is arguably wrong, but currently hard to fix for reasons
+too complicated to explain here.
diff --git a/usr.bin/rsh/rsh.c b/usr.bin/rsh/rsh.c
new file mode 100644
index 00000000000..ad7ff8e56cd
--- /dev/null
+++ b/usr.bin/rsh/rsh.c
@@ -0,0 +1,481 @@
+/*-
+ * Copyright (c) 1983, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+/*static char sccsid[] = "from: @(#)rsh.c 5.24 (Berkeley) 7/1/91";*/
+static char rcsid[] = "$Id: rsh.c,v 1.1 1995/10/18 08:46:03 deraadt Exp $";
+#endif /* not lint */
+
+/*
+ * $Source: /cvs/OpenBSD/src/usr.bin/rsh/rsh.c,v $
+ * $Header: /cvs/OpenBSD/src/usr.bin/rsh/rsh.c,v 1.1 1995/10/18 08:46:03 deraadt Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <varargs.h>
+#include "pathnames.h"
+
+#ifdef KERBEROS
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+
+CREDENTIALS cred;
+Key_schedule schedule;
+int use_kerberos = 1, doencrypt;
+char dst_realm_buf[REALM_SZ], *dest_realm;
+extern char *krb_realmofhost();
+#endif
+
+/*
+ * rsh - remote shell
+ */
+extern int errno;
+int rfd2;
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ extern char *optarg;
+ extern int optind;
+ struct passwd *pw;
+ struct servent *sp;
+ long omask;
+ int argoff, asrsh, ch, dflag, nflag, one, pid, rem, uid;
+ register char *p;
+ char *args, *host, *user, *copyargs();
+ void sendsig();
+
+ argoff = asrsh = dflag = nflag = 0;
+ one = 1;
+ host = user = NULL;
+
+ /* if called as something other than "rsh", use it as the host name */
+ if (p = rindex(argv[0], '/'))
+ ++p;
+ else
+ p = argv[0];
+ if (strcmp(p, "rsh"))
+ host = p;
+ else
+ asrsh = 1;
+
+ /* handle "rsh host flags" */
+ if (!host && argc > 2 && argv[1][0] != '-') {
+ host = argv[1];
+ argoff = 1;
+ }
+
+#ifdef KERBEROS
+#ifdef CRYPT
+#define OPTIONS "8KLdek:l:nwx"
+#else
+#define OPTIONS "8KLdek:l:nw"
+#endif
+#else
+#define OPTIONS "8KLdel:nw"
+#endif
+ while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
+ switch(ch) {
+ case 'K':
+#ifdef KERBEROS
+ use_kerberos = 0;
+#endif
+ break;
+ case 'L': /* -8Lew are ignored to allow rlogin aliases */
+ case 'e':
+ case 'w':
+ case '8':
+ break;
+ case 'd':
+ dflag = 1;
+ break;
+ case 'l':
+ user = optarg;
+ break;
+#ifdef KERBEROS
+ case 'k':
+ dest_realm = dst_realm_buf;
+ strncpy(dest_realm, optarg, REALM_SZ);
+ break;
+#endif
+ case 'n':
+ nflag = 1;
+ break;
+#ifdef KERBEROS
+#ifdef CRYPT
+ case 'x':
+ doencrypt = 1;
+ des_set_key(cred.session, schedule);
+ break;
+#endif
+#endif
+ case '?':
+ default:
+ usage();
+ }
+ optind += argoff;
+
+ /* if haven't gotten a host yet, do so */
+ if (!host && !(host = argv[optind++]))
+ usage();
+
+ /* if no further arguments, must have been called as rlogin. */
+ if (!argv[optind]) {
+ if (asrsh)
+ *argv = "rlogin";
+ execv(_PATH_RLOGIN, argv);
+ (void)fprintf(stderr, "rsh: can't exec %s.\n", _PATH_RLOGIN);
+ exit(1);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (!(pw = getpwuid(uid = getuid()))) {
+ (void)fprintf(stderr, "rsh: unknown user id.\n");
+ exit(1);
+ }
+ if (!user)
+ user = pw->pw_name;
+
+#ifdef KERBEROS
+#ifdef CRYPT
+ /* -x turns off -n */
+ if (doencrypt)
+ nflag = 0;
+#endif
+#endif
+
+ args = copyargs(argv);
+
+ sp = NULL;
+#ifdef KERBEROS
+ if (use_kerberos) {
+ sp = getservbyname((doencrypt ? "ekshell" : "kshell"), "tcp");
+ if (sp == NULL) {
+ use_kerberos = 0;
+ warning("can't get entry for %s/tcp service",
+ doencrypt ? "ekshell" : "kshell");
+ }
+ }
+#endif
+ if (sp == NULL)
+ sp = getservbyname("shell", "tcp");
+ if (sp == NULL) {
+ (void)fprintf(stderr, "rsh: shell/tcp: unknown service.\n");
+ exit(1);
+ }
+
+#ifdef KERBEROS
+try_connect:
+ if (use_kerberos) {
+ rem = KSUCCESS;
+ errno = 0;
+ if (dest_realm == NULL)
+ dest_realm = krb_realmofhost(host);
+
+#ifdef CRYPT
+ if (doencrypt)
+ rem = krcmd_mutual(&host, sp->s_port, user, args,
+ &rfd2, dest_realm, &cred, schedule);
+ else
+#endif
+ rem = krcmd(&host, sp->s_port, user, args, &rfd2,
+ dest_realm);
+ if (rem < 0) {
+ use_kerberos = 0;
+ sp = getservbyname("shell", "tcp");
+ if (sp == NULL) {
+ (void)fprintf(stderr,
+ "rsh: unknown service shell/tcp.\n");
+ exit(1);
+ }
+ if (errno == ECONNREFUSED)
+ warning("remote host doesn't support Kerberos");
+ if (errno == ENOENT)
+ warning("can't provide Kerberos auth data");
+ goto try_connect;
+ }
+ } else {
+ if (doencrypt) {
+ (void)fprintf(stderr,
+ "rsh: the -x flag requires Kerberos authentication.\n");
+ exit(1);
+ }
+ rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
+ }
+#else
+ rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
+#endif
+
+ if (rem < 0)
+ exit(1);
+
+ if (rfd2 < 0) {
+ (void)fprintf(stderr, "rsh: can't establish stderr.\n");
+ exit(1);
+ }
+ if (dflag) {
+ if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one,
+ sizeof(one)) < 0)
+ (void)fprintf(stderr, "rsh: setsockopt: %s.\n",
+ strerror(errno));
+ if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one,
+ sizeof(one)) < 0)
+ (void)fprintf(stderr, "rsh: setsockopt: %s.\n",
+ strerror(errno));
+ }
+
+ (void)setuid(uid);
+ omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM));
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ (void)signal(SIGINT, sendsig);
+ if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
+ (void)signal(SIGQUIT, sendsig);
+ if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
+ (void)signal(SIGTERM, sendsig);
+
+ if (!nflag) {
+ pid = fork();
+ if (pid < 0) {
+ (void)fprintf(stderr,
+ "rsh: fork: %s.\n", strerror(errno));
+ exit(1);
+ }
+ }
+
+#ifdef KERBEROS
+#ifdef CRYPT
+ if (!doencrypt)
+#endif
+#endif
+ {
+ (void)ioctl(rfd2, FIONBIO, &one);
+ (void)ioctl(rem, FIONBIO, &one);
+ }
+
+ talk(nflag, omask, pid, rem);
+
+ if (!nflag)
+ (void)kill(pid, SIGKILL);
+ exit(0);
+}
+
+talk(nflag, omask, pid, rem)
+ int nflag, pid;
+ long omask;
+ register int rem;
+{
+ register int cc, wc;
+ register char *bp;
+ int readfrom, ready, rembits;
+ char buf[BUFSIZ];
+
+ if (!nflag && pid == 0) {
+ (void)close(rfd2);
+
+reread: errno = 0;
+ if ((cc = read(0, buf, sizeof buf)) <= 0)
+ goto done;
+ bp = buf;
+
+rewrite: rembits = 1 << rem;
+ if (select(16, 0, &rembits, 0, 0) < 0) {
+ if (errno != EINTR) {
+ (void)fprintf(stderr,
+ "rsh: select: %s.\n", strerror(errno));
+ exit(1);
+ }
+ goto rewrite;
+ }
+ if ((rembits & (1 << rem)) == 0)
+ goto rewrite;
+#ifdef KERBEROS
+#ifdef CRYPT
+ if (doencrypt)
+ wc = des_write(rem, bp, cc);
+ else
+#endif
+#endif
+ wc = write(rem, bp, cc);
+ if (wc < 0) {
+ if (errno == EWOULDBLOCK)
+ goto rewrite;
+ goto done;
+ }
+ bp += wc;
+ cc -= wc;
+ if (cc == 0)
+ goto reread;
+ goto rewrite;
+done:
+ (void)shutdown(rem, 1);
+ exit(0);
+ }
+
+ (void)sigsetmask(omask);
+ readfrom = (1 << rfd2) | (1 << rem);
+ do {
+ ready = readfrom;
+ if (select(16, &ready, 0, 0, 0) < 0) {
+ if (errno != EINTR) {
+ (void)fprintf(stderr,
+ "rsh: select: %s.\n", strerror(errno));
+ exit(1);
+ }
+ continue;
+ }
+ if (ready & (1 << rfd2)) {
+ errno = 0;
+#ifdef KERBEROS
+#ifdef CRYPT
+ if (doencrypt)
+ cc = des_read(rfd2, buf, sizeof buf);
+ else
+#endif
+#endif
+ cc = read(rfd2, buf, sizeof buf);
+ if (cc <= 0) {
+ if (errno != EWOULDBLOCK)
+ readfrom &= ~(1 << rfd2);
+ } else
+ (void)write(2, buf, cc);
+ }
+ if (ready & (1 << rem)) {
+ errno = 0;
+#ifdef KERBEROS
+#ifdef CRYPT
+ if (doencrypt)
+ cc = des_read(rem, buf, sizeof buf);
+ else
+#endif
+#endif
+ cc = read(rem, buf, sizeof buf);
+ if (cc <= 0) {
+ if (errno != EWOULDBLOCK)
+ readfrom &= ~(1 << rem);
+ } else
+ (void)write(1, buf, cc);
+ }
+ } while (readfrom);
+}
+
+void
+sendsig(signo)
+ char signo;
+{
+#ifdef KERBEROS
+#ifdef CRYPT
+ if (doencrypt)
+ (void)des_write(rfd2, &signo, 1);
+ else
+#endif
+#endif
+ (void)write(rfd2, &signo, 1);
+}
+
+#ifdef KERBEROS
+/* VARARGS */
+warning(va_alist)
+va_dcl
+{
+ va_list ap;
+ char *fmt;
+
+ (void)fprintf(stderr, "rsh: warning, using standard rsh: ");
+ va_start(ap);
+ fmt = va_arg(ap, char *);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ (void)fprintf(stderr, ".\n");
+}
+#endif
+
+char *
+copyargs(argv)
+ char **argv;
+{
+ register int cc;
+ register char **ap, *p;
+ char *args, *malloc();
+
+ cc = 0;
+ for (ap = argv; *ap; ++ap)
+ cc += strlen(*ap) + 1;
+ if (!(args = malloc((u_int)cc))) {
+ (void)fprintf(stderr, "rsh: %s.\n", strerror(ENOMEM));
+ exit(1);
+ }
+ for (p = args, ap = argv; *ap; ++ap) {
+ (void)strcpy(p, *ap);
+ for (p = strcpy(p, *ap); *p; ++p);
+ if (ap[1])
+ *p++ = ' ';
+ }
+ return(args);
+}
+
+usage()
+{
+ (void)fprintf(stderr,
+ "usage: rsh [-nd%s]%s[-l login] host [command]\n",
+#ifdef KERBEROS
+#ifdef CRYPT
+ "x", " [-k realm] ");
+#else
+ "", " [-k realm] ");
+#endif
+#else
+ "", " ");
+#endif
+ exit(1);
+}