# @(#)Makefile 8.1 (Berkeley) 5/31/93
SUBDIR= cat chmod cp date dd df domainname echo ed expr hostname \
- kill ksh ln ls mkdir mv pax pwd rm rmdir sh \
+ kill ksh ln ls mkdir mv pax pwd rcp rcmd rm rmdir sh \
sleep stty sync test
.include <bsd.subdir.mk>
--- /dev/null
+# $NetBSD: Makefile,v 1.11 2007/05/28 12:06:17 tls Exp $
+
+.include <bsd.own.mk>
+
+USE_FORT?=yes # setuid
+# XXX Unsupported Kerberos options were removed from man page
+# XXX Don't forget to update the man page if you fix Kerberos
+PROG= rcmd
+SRCS= rsh.c getport.c
+CPPFLAGS+=-DIN_RCMD
+BINOWN= root
+BINMODE=4555
+.PATH: ${NETBSDSRCDIR}/usr.bin/rsh
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" $NetBSD: rcmd.1,v 1.21 2011/05/31 11:31:10 wiz Exp $
+.\"
+.\" Copyright (c) 1997 Matthew R. Green.
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+.\"
+.\" 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. 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
+.\" from: NetBSD: rsh.1,v 1.3 1997/01/09 20:21:14 tls Exp
+.\"
+.Dd May 31, 2011
+.Dt RCMD 1
+.Os
+.Sh NAME
+.Nm rcmd
+.Nd backend driver for
+.Xr rcmd 3
+.Sh SYNOPSIS
+.Nm
+.Op Fl 46dn
+.Op Fl l Ar username
+.Op Fl p Ar port
+.Op Fl u Ar localusername
+.Ar host
+.Ar command
+.Sh DESCRIPTION
+.Nm
+executes
+.Ar command
+on
+.Ar host .
+.Pp
+.Nm
+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
+normally terminates when the remote command does.
+The options are as follows:
+.Bl -tag -width flag
+.It Fl 4
+Use IPv4 addresses only.
+.It Fl 6
+Use IPv6 addresses only.
+.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 l
+By default, the remote username is the same as the local username.
+The
+.Fl l
+option allows the remote name to be specified.
+Another possible way to specify the remote username
+is the notation
+.Ar user@host .
+.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 p Ar port
+Uses the given
+.Pa port
+instead of the one assigned to the service
+.Dq shell .
+May be given either as symbolic name or as number.
+.It Fl u
+The
+.Fl u
+option allows the local username to be specified.
+Only the superuser is allowed to use this option.
+.El
+.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 rcmd otherhost cat remotefile \*[Gt]\*[Gt] localfile
+.Pp
+appends the remote file
+.Ar remotefile
+to the local file
+.Ar localfile ,
+while
+.Pp
+.Dl rcmd otherhost cat remotefile \&"\*[Gt]\*[Gt]\&" other_remotefile
+.Pp
+appends
+.Ar remotefile
+to
+.Ar other_remotefile .
+.Sh FILES
+.Bl -tag -width /etc/hosts -compact
+.It Pa /etc/hosts
+.El
+.Sh SEE ALSO
+.Xr rsh 1 ,
+.Xr rcmd 3 ,
+.Xr environ 7
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Nx 1.3
+and is primarily derived from
+.Xr rsh 1 .
+Its purpose was to create a backend driver for
+.Xr rcmd 3
+that would allow the users of
+.Xr rcmd 3
+to no longer require super-user privileges.
+.Sh BUGS
+If you are using
+.Xr csh 1
+and put a
+.Nm
+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
+to
+.Pa /dev/null
+using the
+.Fl n
+option.
+.Pp
+You cannot use
+.Nm rcmd
+to run an interactive command (like
+.Xr rogue 6
+or
+.Xr vi 1 ) .
+Use
+.Xr rlogin 1
+instead.
+.Pp
+The stop signal,
+.Dv SIGSTOP ,
+will stop the local
+.Nm
+process only.
+This is arguably wrong, but currently hard to fix for reasons
+too complicated to explain here.
--- /dev/null
+# $NetBSD: Makefile,v 1.25 2009/02/14 08:31:13 lukem Exp $
+# @(#)Makefile 8.1 (Berkeley) 7/19/93
+
+WARNS=3
+
+.include <bsd.own.mk>
+
+PROG= rcp
+SRCS= rcp.c util.c
+
+.include <bsd.prog.mk>
--- /dev/null
+/* $NetBSD: extern.h,v 1.6 2005/03/11 02:55:23 ginsbach Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * 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. 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.
+ *
+ * @(#)extern.h 8.1 (Berkeley) 5/31/93
+ */
+
+typedef struct {
+ int cnt;
+ char *buf;
+} BUF;
+
+extern int iamremote;
+
+BUF *allocbuf(BUF *, int, int);
+char *colon(char *);
+void lostconn(int);
+void nospace(void);
+int okname(char *);
+void run_err(const char *, ...);
+int susystem(char *);
+char *unbracket(char *);
+void verifydir(char *);
--- /dev/null
+/* $NetBSD: pathnames.h,v 1.7 2004/08/19 23:05:00 christos Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993
+ * 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. 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.
+ *
+ * @(#)pathnames.h 8.1 (Berkeley) 5/31/93
+ */
+
+#include <paths.h>
+
+#ifdef RESCUEDIR
+#define _PATH_CP RESCUEDIR "/cp"
+#define _PATH_RSH RESCUEDIR "/rsh"
+#else
+#define _PATH_CP "/bin/cp"
+#define _PATH_RSH "/usr/bin/rsh"
+#endif
--- /dev/null
+.\" $NetBSD: rcp.1,v 1.22 2012/03/22 07:58:17 wiz Exp $
+.\"
+.\" Copyright (c) 1983, 1990, 1993
+.\" 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. 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.
+.\"
+.\" @(#)rcp.1 8.1 (Berkeley) 5/31/93
+.\"
+.Dd March 8, 2005
+.Dt RCP 1
+.Os
+.Sh NAME
+.Nm rcp
+.Nd remote file copy
+.Sh SYNOPSIS
+.Nm
+.Op Fl 46p
+.Ar file1 file2
+.Nm
+.Op Fl 46pr
+.Ar file ...
+.Ar directory
+.Sh DESCRIPTION
+.Nm
+copies files between machines.
+Each
+.Ar file
+or
+.Ar directory
+argument is either a remote file name of the
+form
+.Dq rname@rhost:path ,
+or a local file name (containing no
+.Sq \&:
+(colon) characters,
+or a
+.Sq /
+(slash) before any
+.Sq \&:
+(colon) characters).
+.Pp
+The
+.Ar rhost
+can be an IPv4 or an IPv6 address string.
+Since IPv6 addresses already contain
+.Sq \&:
+(colon) characters,
+an IPv6 address string must be enclosed between
+.Sq \&[
+(left square bracket) and
+.Sq \&]
+(right square bracket) characters.
+Otherwise, the first occurrence of a
+.Sq \&:
+(colon) character would be
+interpreted as the separator between the
+.Ar rhost
+and the
+.Ar path .
+For example,
+.Pp
+.Dl [2001:DB8::800:200C:417A]:tmp/file
+.Pp
+Options:
+.Bl -tag -width flag
+.It Fl 4
+Use IPv4 addresses only.
+.It Fl 6
+Use IPv6 addresses only.
+.It Fl p
+The
+.Fl p
+option causes
+.Nm
+to attempt to preserve (duplicate) in its copies the modification
+times and modes of the source files, ignoring the
+.Ar umask .
+By default, the mode and owner of
+.Ar file2
+are preserved if it already existed; otherwise the mode of the source file
+modified by the
+.Xr umask 2
+on the destination host is used.
+.It Fl r
+If any of the source files are directories,
+.Nm
+copies each subtree rooted at that name; in this case
+the destination must be a directory.
+.El
+.Pp
+If
+.Ar path
+is not a full path name, it is interpreted relative to
+the login directory of the specified user
+.Ar ruser
+on
+.Ar rhost ,
+or your current user name if no other remote user name is specified.
+A
+.Ar path
+on a remote host may be quoted (using \e, ", or \(aa)
+so that the metacharacters are interpreted remotely.
+.Pp
+.Nm
+does not prompt for passwords; it performs remote execution
+via
+.Xr rsh 1 ,
+and requires the same authorization.
+.Pp
+.Nm
+handles third party copies, where neither source nor target files
+are on the current machine.
+.Sh SEE ALSO
+.Xr cp 1 ,
+.Xr ftp 1 ,
+.Xr rcmd 1 ,
+.Xr rlogin 1 ,
+.Xr rsh 1 ,
+.Xr rcmd 3 ,
+.Xr hosts.equiv 5 ,
+.Xr rhosts 5 ,
+.Xr environ 7
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Bx 4.2 .
+The version of
+.Nm
+described here
+has been reimplemented with Kerberos in
+.Bx 4.3 Reno .
+.Sh BUGS
+Doesn't detect all cases where the target of a copy might
+be a file in cases where only a directory should be legal.
+.Pp
+Is confused by any output generated by commands in a
+.Pa \&.login ,
+.Pa \&.profile ,
+or
+.Pa \&.cshrc
+file on the remote host.
+.Pp
+The destination user and hostname may have to be specified as
+.Dq rhost.rname
+when the destination machine is running the
+.Bx 4.2
+version of
+.Nm .
--- /dev/null
+/* $NetBSD: rcp.c,v 1.49 2012/05/07 15:22:54 chs Exp $ */
+
+/*
+ * Copyright (c) 1983, 1990, 1992, 1993
+ * 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. 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.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1983, 1990, 1992, 1993\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)rcp.c 8.2 (Berkeley) 4/2/94";
+#else
+__RCSID("$NetBSD: rcp.c,v 1.49 2012/05/07 15:22:54 chs Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <ctype.h>
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pathnames.h"
+#include "extern.h"
+
+#define OPTIONS "46dfprt"
+
+struct passwd *pwd;
+char *pwname;
+u_short port;
+uid_t userid;
+int errs, rem;
+int pflag, iamremote, iamrecursive, targetshouldbedirectory;
+int family = AF_UNSPEC;
+static char dot[] = ".";
+
+#define CMDNEEDS 64
+char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
+
+int response(void);
+void rsource(char *, struct stat *);
+void sink(int, char *[]);
+void source(int, char *[]);
+void tolocal(int, char *[]);
+void toremote(char *, int, char *[]);
+void usage(void);
+
+int
+main(int argc, char *argv[])
+{
+ struct servent *sp;
+ int ch, fflag, tflag;
+ char *targ;
+ const char *shell;
+
+ setprogname(argv[0]);
+ (void)setlocale(LC_ALL, "");
+
+ fflag = tflag = 0;
+ while ((ch = getopt(argc, argv, OPTIONS)) != -1)
+ switch(ch) { /* User-visible flags. */
+ case '4':
+ family = AF_INET;
+ break;
+ case '6':
+ family = AF_INET6;
+ break;
+ case 'K':
+ break;
+ case 'p':
+ pflag = 1;
+ break;
+ case 'r':
+ iamrecursive = 1;
+ break;
+ /* Server options. */
+ case 'd':
+ targetshouldbedirectory = 1;
+ break;
+ case 'f': /* "from" */
+ iamremote = 1;
+ fflag = 1;
+ break;
+ case 't': /* "to" */
+ iamremote = 1;
+ tflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ sp = getservbyname(shell = "shell", "tcp");
+ if (sp == NULL)
+ errx(1, "%s/tcp: unknown service", shell);
+ port = sp->s_port;
+
+ if ((pwd = getpwuid(userid = getuid())) == NULL)
+ errx(1, "unknown user %d", (int)userid);
+
+ if ((pwname = strdup(pwd->pw_name)) == NULL)
+ err(1, NULL);
+
+ rem = STDIN_FILENO; /* XXX */
+
+ if (fflag) { /* Follow "protocol", send data. */
+ (void)response();
+ source(argc, argv);
+ exit(errs);
+ }
+
+ if (tflag) { /* Receive data. */
+ sink(argc, argv);
+ exit(errs);
+ }
+
+ if (argc < 2)
+ usage();
+ if (argc > 2)
+ targetshouldbedirectory = 1;
+
+ rem = -1;
+ /* Command to be executed on remote system using "rsh". */
+ (void)snprintf(cmd, sizeof(cmd), "rcp%s%s%s",
+ iamrecursive ? " -r" : "", pflag ? " -p" : "",
+ targetshouldbedirectory ? " -d" : "");
+
+ (void)signal(SIGPIPE, lostconn);
+
+ if ((targ = colon(argv[argc - 1])) != NULL)/* Dest is remote host. */
+ toremote(targ, argc, argv);
+ else {
+ tolocal(argc, argv); /* Dest is local host. */
+ if (targetshouldbedirectory)
+ verifydir(argv[argc - 1]);
+ }
+ exit(errs);
+ /* NOTREACHED */
+}
+
+void
+toremote(char *targ, int argc, char *argv[])
+{
+ int i;
+ size_t len;
+ char *bp, *host, *src, *suser, *thost, *tuser;
+
+ *targ++ = 0;
+ if (*targ == 0)
+ targ = dot;
+
+ if ((thost = strchr(argv[argc - 1], '@')) != NULL) {
+ /* user@host */
+ *thost++ = 0;
+ tuser = argv[argc - 1];
+ if (*tuser == '\0')
+ tuser = NULL;
+ else if (!okname(tuser))
+ exit(1);
+ } else {
+ thost = argv[argc - 1];
+ tuser = NULL;
+ }
+ thost = unbracket(thost);
+
+ for (i = 0; i < argc - 1; i++) {
+ src = colon(argv[i]);
+ if (src) { /* remote to remote */
+ *src++ = 0;
+ if (*src == 0)
+ src = dot;
+ host = strchr(argv[i], '@');
+ len = strlen(_PATH_RSH) + strlen(argv[i]) +
+ strlen(src) + (tuser ? strlen(tuser) : 0) +
+ strlen(thost) + strlen(targ) + CMDNEEDS + 20;
+ if (!(bp = malloc(len)))
+ err(1, NULL);
+ if (host) {
+ *host++ = 0;
+ host = unbracket(host);
+ suser = argv[i];
+ if (*suser == '\0')
+ suser = pwname;
+ else if (!okname(suser)) {
+ (void)free(bp);
+ continue;
+ }
+ (void)snprintf(bp, len,
+ "%s %s -l %s -n %s %s '%s%s%s:%s'",
+ _PATH_RSH, host, suser, cmd, src,
+ tuser ? tuser : "", tuser ? "@" : "",
+ thost, targ);
+ } else {
+ host = unbracket(argv[i]);
+ (void)snprintf(bp, len,
+ "exec %s %s -n %s %s '%s%s%s:%s'",
+ _PATH_RSH, argv[i], cmd, src,
+ tuser ? tuser : "", tuser ? "@" : "",
+ thost, targ);
+ }
+ (void)susystem(bp);
+ (void)free(bp);
+ } else { /* local to remote */
+ if (rem == -1) {
+ len = strlen(targ) + CMDNEEDS + 20;
+ if (!(bp = malloc(len)))
+ err(1, NULL);
+ (void)snprintf(bp, len, "%s -t %s", cmd, targ);
+ host = thost;
+ rem = rcmd_af(&host, port, pwname,
+ tuser ? tuser : pwname,
+ bp, NULL, family);
+ if (rem < 0)
+ exit(1);
+ if (response() < 0)
+ exit(1);
+ (void)free(bp);
+ }
+ source(1, argv+i);
+ }
+ }
+}
+
+void
+tolocal(int argc, char *argv[])
+{
+ int i;
+ size_t len;
+ char *bp, *host, *src, *suser;
+
+ for (i = 0; i < argc - 1; i++) {
+ if (!(src = colon(argv[i]))) { /* Local to local. */
+ len = strlen(_PATH_CP) + strlen(argv[i]) +
+ strlen(argv[argc - 1]) + 20;
+ if (!(bp = malloc(len)))
+ err(1, NULL);
+ (void)snprintf(bp, len, "exec %s%s%s %s %s", _PATH_CP,
+ iamrecursive ? " -r" : "", pflag ? " -p" : "",
+ argv[i], argv[argc - 1]);
+ if (susystem(bp))
+ ++errs;
+ (void)free(bp);
+ continue;
+ }
+ *src++ = 0;
+ if (*src == 0)
+ src = dot;
+ if ((host = strchr(argv[i], '@')) == NULL) {
+ host = argv[i];
+ suser = pwname;
+ } else {
+ *host++ = 0;
+ suser = argv[i];
+ if (*suser == '\0')
+ suser = pwname;
+ else if (!okname(suser))
+ continue;
+ }
+ host = unbracket(host);
+ len = strlen(src) + CMDNEEDS + 20;
+ if ((bp = malloc(len)) == NULL)
+ err(1, NULL);
+ (void)snprintf(bp, len, "%s -f %s", cmd, src);
+ rem =
+ rcmd_af(&host, port, pwname, suser, bp, NULL, family);
+ (void)free(bp);
+ if (rem < 0) {
+ ++errs;
+ continue;
+ }
+ sink(1, argv + argc - 1);
+ (void)close(rem);
+ rem = -1;
+ }
+}
+
+void
+source(int argc, char *argv[])
+{
+ struct stat stb;
+ static BUF buffer;
+ BUF *bp;
+ off_t i;
+ off_t amt;
+ int fd, haderr, indx, result;
+ char *last, *name, buf[BUFSIZ];
+
+ for (indx = 0; indx < argc; ++indx) {
+ name = argv[indx];
+ if ((fd = open(name, O_RDONLY, 0)) < 0)
+ goto syserr;
+ if (fstat(fd, &stb)) {
+syserr: run_err("%s: %s", name, strerror(errno));
+ goto next;
+ }
+ switch (stb.st_mode & S_IFMT) {
+ case S_IFREG:
+ break;
+ case S_IFDIR:
+ if (iamrecursive) {
+ rsource(name, &stb);
+ goto next;
+ }
+ /* FALLTHROUGH */
+ default:
+ run_err("%s: not a regular file", name);
+ goto next;
+ }
+ if ((last = strrchr(name, '/')) == NULL)
+ last = name;
+ else
+ ++last;
+ if (pflag) {
+ /*
+ * Make it compatible with possible future
+ * versions expecting microseconds.
+ */
+ (void)snprintf(buf, sizeof(buf), "T%lld %ld %lld %ld\n",
+ (long long)stb.st_mtimespec.tv_sec,
+ (long)stb.st_mtimespec.tv_nsec / 1000,
+ (long long)stb.st_atimespec.tv_sec,
+ (long)stb.st_atimespec.tv_nsec / 1000);
+ (void)write(rem, buf, strlen(buf));
+ if (response() < 0)
+ goto next;
+ }
+#define RCPMODEMASK (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO)
+ (void)snprintf(buf, sizeof(buf), "C%04o %lld %s\n",
+ stb.st_mode & RCPMODEMASK, (long long)stb.st_size, last);
+ (void)write(rem, buf, strlen(buf));
+ if (response() < 0)
+ goto next;
+ if ((bp = allocbuf(&buffer, fd, BUFSIZ)) == NULL) {
+next: (void)close(fd);
+ continue;
+ }
+
+ /* Keep writing after an error so that we stay sync'd up. */
+ haderr = 0;
+ for (i = 0; i < stb.st_size; i += bp->cnt) {
+ amt = bp->cnt;
+ if (i + amt > stb.st_size)
+ amt = stb.st_size - i;
+ if (!haderr) {
+ result = read(fd, bp->buf, (size_t)amt);
+ if (result != amt)
+ haderr = result >= 0 ? EIO : errno;
+ }
+ if (haderr)
+ (void)write(rem, bp->buf, (size_t)amt);
+ else {
+ result = write(rem, bp->buf, (size_t)amt);
+ if (result != amt)
+ haderr = result >= 0 ? EIO : errno;
+ }
+ }
+ if (close(fd) && !haderr)
+ haderr = errno;
+ if (!haderr)
+ (void)write(rem, "", 1);
+ else
+ run_err("%s: %s", name, strerror(haderr));
+ (void)response();
+ }
+}
+
+void
+rsource(char *name, struct stat *statp)
+{
+ DIR *dirp;
+ struct dirent *dp;
+ char *last, *vect[1], path[MAXPATHLEN];
+
+ if (!(dirp = opendir(name))) {
+ run_err("%s: %s", name, strerror(errno));
+ return;
+ }
+ last = strrchr(name, '/');
+ if (last == 0)
+ last = name;
+ else
+ last++;
+ if (pflag) {
+ (void)snprintf(path, sizeof(path), "T%lld %ld %lld %ld\n",
+ (long long)statp->st_mtimespec.tv_sec,
+ (long)statp->st_mtimespec.tv_nsec / 1000,
+ (long long)statp->st_atimespec.tv_sec,
+ (long)statp->st_atimespec.tv_nsec / 1000);
+ (void)write(rem, path, strlen(path));
+ if (response() < 0) {
+ (void)closedir(dirp);
+ return;
+ }
+ }
+ (void)snprintf(path, sizeof(path),
+ "D%04o %d %s\n", statp->st_mode & RCPMODEMASK, 0, last);
+ (void)write(rem, path, strlen(path));
+ if (response() < 0) {
+ (void)closedir(dirp);
+ return;
+ }
+ while ((dp = readdir(dirp)) != NULL) {
+ if (dp->d_ino == 0)
+ continue;
+ if (!strcmp(dp->d_name, dot) || !strcmp(dp->d_name, ".."))
+ continue;
+ if (strlen(name) + 1 + strlen(dp->d_name) >= MAXPATHLEN - 1) {
+ run_err("%s/%s: name too long", name, dp->d_name);
+ continue;
+ }
+ (void)snprintf(path, sizeof(path), "%s/%s", name, dp->d_name);
+ vect[0] = path;
+ source(1, vect);
+ }
+ (void)closedir(dirp);
+ (void)write(rem, "E\n", 2);
+ (void)response();
+}
+
+void
+sink(int argc, char *argv[])
+{
+ static BUF buffer;
+ struct stat stb;
+ struct timeval tv[2];
+ enum { YES, NO, DISPLAYED } wrerr;
+ BUF *bp;
+ ssize_t j;
+ off_t i;
+ off_t amt;
+ off_t count;
+ int exists, first, ofd;
+ mode_t mask;
+ mode_t mode;
+ mode_t omode;
+ int setimes, targisdir;
+ int wrerrno = 0; /* pacify gcc */
+ char ch, *cp, *np, *targ, *vect[1], buf[BUFSIZ];
+ const char *why;
+ off_t size;
+ char *namebuf = NULL;
+ size_t cursize = 0;
+
+#define atime tv[0]
+#define mtime tv[1]
+#define SCREWUP(str) { why = str; goto screwup; }
+
+ setimes = targisdir = 0;
+ mask = umask(0);
+ if (!pflag)
+ (void)umask(mask);
+ if (argc != 1) {
+ run_err("ambiguous target");
+ exit(1);
+ }
+ targ = *argv;
+ if (targetshouldbedirectory)
+ verifydir(targ);
+ (void)write(rem, "", 1);
+ if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
+ targisdir = 1;
+ for (first = 1;; first = 0) {
+ cp = buf;
+ if (read(rem, cp, 1) <= 0)
+ goto out;
+ if (*cp++ == '\n')
+ SCREWUP("unexpected <newline>");
+ do {
+ if (read(rem, &ch, sizeof(ch)) != sizeof(ch))
+ SCREWUP("lost connection");
+ *cp++ = ch;
+ } while (cp < &buf[BUFSIZ - 1] && ch != '\n');
+ *cp = 0;
+
+ if (buf[0] == '\01' || buf[0] == '\02') {
+ if (iamremote == 0)
+ (void)write(STDERR_FILENO,
+ buf + 1, strlen(buf + 1));
+ if (buf[0] == '\02')
+ exit(1);
+ ++errs;
+ continue;
+ }
+ if (buf[0] == 'E') {
+ (void)write(rem, "", 1);
+ goto out;
+ }
+
+ if (ch == '\n')
+ *--cp = 0;
+
+#define getnum(t) (t) = 0; while (isdigit((unsigned char)*cp)) (t) = (t) * 10 + (*cp++ - '0');
+ cp = buf;
+ if (*cp == 'T') {
+ setimes++;
+ cp++;
+ getnum(mtime.tv_sec);
+ if (*cp++ != ' ')
+ SCREWUP("mtime.sec not delimited");
+ getnum(mtime.tv_usec);
+ if (*cp++ != ' ')
+ SCREWUP("mtime.usec not delimited");
+ getnum(atime.tv_sec);
+ if (*cp++ != ' ')
+ SCREWUP("atime.sec not delimited");
+ getnum(atime.tv_usec);
+ if (*cp++ != '\0')
+ SCREWUP("atime.usec not delimited");
+ (void)write(rem, "", 1);
+ continue;
+ }
+ if (*cp != 'C' && *cp != 'D') {
+ /*
+ * Check for the case "rcp remote:foo\* local:bar".
+ * In this case, the line "No match." can be returned
+ * by the shell before the rcp command on the remote is
+ * executed so the ^Aerror_message convention isn't
+ * followed.
+ */
+ if (first) {
+ run_err("%s", cp);
+ exit(1);
+ }
+ SCREWUP("expected control record");
+ }
+ mode = 0;
+ for (++cp; cp < buf + 5; cp++) {
+ if (*cp < '0' || *cp > '7')
+ SCREWUP("bad mode");
+ mode = (mode << 3) | (*cp - '0');
+ }
+ if (*cp++ != ' ')
+ SCREWUP("mode not delimited");
+
+ for (size = 0; isdigit((unsigned char)*cp);)
+ size = size * 10 + (*cp++ - '0');
+ if (*cp++ != ' ')
+ SCREWUP("size not delimited");
+ if (targisdir) {
+ char *newnamebuf;
+ size_t need;
+
+ need = strlen(targ) + strlen(cp) + 2;
+ if (need > cursize) {
+ need += 256;
+ newnamebuf = realloc(namebuf, need);
+ if (newnamebuf != NULL) {
+ namebuf = newnamebuf;
+ cursize = need;
+ } else {
+ run_err("%s", strerror(errno));
+ exit(1);
+ }
+ }
+ (void)snprintf(namebuf, cursize, "%s%s%s", targ,
+ *targ ? "/" : "", cp);
+ np = namebuf;
+ } else
+ np = targ;
+ exists = stat(np, &stb) == 0;
+ if (buf[0] == 'D') {
+ int mod_flag = pflag;
+ if (exists) {
+ if (!S_ISDIR(stb.st_mode)) {
+ errno = ENOTDIR;
+ goto bad;
+ }
+ if (pflag)
+ (void)chmod(np, mode);
+ } else {
+ /* Handle copying from a read-only directory */
+ mod_flag = 1;
+ if (mkdir(np, mode | S_IRWXU) < 0)
+ goto bad;
+ }
+ vect[0] = np;
+ sink(1, vect);
+ if (setimes) {
+ setimes = 0;
+ if (utimes(np, tv) < 0)
+ run_err("%s: set times: %s",
+ np, strerror(errno));
+ }
+ if (mod_flag)
+ (void)chmod(np, mode);
+ continue;
+ }
+ omode = mode;
+ mode |= S_IWRITE;
+ if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
+bad: run_err("%s: %s", np, strerror(errno));
+ continue;
+ }
+ (void)write(rem, "", 1);
+ if ((bp = allocbuf(&buffer, ofd, BUFSIZ)) == NULL) {
+ (void)close(ofd);
+ continue;
+ }
+ cp = bp->buf;
+ wrerr = NO;
+ count = 0;
+ for (i = 0; i < size; i += BUFSIZ) {
+ amt = BUFSIZ;
+ if (i + amt > size)
+ amt = size - i;
+ count += amt;
+ do {
+ j = read(rem, cp, (size_t)amt);
+ if (j == -1) {
+ run_err("%s", j ? strerror(errno) :
+ "dropped connection");
+ exit(1);
+ }
+ amt -= j;
+ cp += j;
+ } while (amt > 0);
+ if (count == bp->cnt) {
+ /* Keep reading so we stay sync'd up. */
+ if (wrerr == NO) {
+ j = write(ofd, bp->buf, (size_t)count);
+ if (j != count) {
+ wrerr = YES;
+ wrerrno = j >= 0 ? EIO : errno;
+ }
+ }
+ count = 0;
+ cp = bp->buf;
+ }
+ }
+ if (count != 0 && wrerr == NO &&
+ (j = write(ofd, bp->buf, (size_t)count)) != count) {
+ wrerr = YES;
+ wrerrno = j >= 0 ? EIO : errno;
+ }
+ if (ftruncate(ofd, size)) {
+ run_err("%s: truncate: %s", np, strerror(errno));
+ wrerr = DISPLAYED;
+ }
+ if (pflag) {
+ if (exists || omode != mode)
+ if (fchmod(ofd, omode))
+ run_err("%s: set mode: %s",
+ np, strerror(errno));
+ } else {
+ if (!exists && omode != mode)
+ if (fchmod(ofd, omode & ~mask))
+ run_err("%s: set mode: %s",
+ np, strerror(errno));
+ }
+#ifndef __SVR4
+ if (setimes && wrerr == NO) {
+ setimes = 0;
+ if (futimes(ofd, tv) < 0) {
+ run_err("%s: set times: %s",
+ np, strerror(errno));
+ wrerr = DISPLAYED;
+ }
+ }
+#endif
+ (void)close(ofd);
+#ifdef __SVR4
+ if (setimes && wrerr == NO) {
+ setimes = 0;
+ if (utimes(np, tv) < 0) {
+ run_err("%s: set times: %s",
+ np, strerror(errno));
+ wrerr = DISPLAYED;
+ }
+ }
+#endif
+ (void)response();
+ switch(wrerr) {
+ case YES:
+ run_err("%s: write: %s", np, strerror(wrerrno));
+ break;
+ case NO:
+ (void)write(rem, "", 1);
+ break;
+ case DISPLAYED:
+ break;
+ }
+ }
+
+out:
+ if (namebuf) {
+ free(namebuf);
+ }
+ return;
+
+screwup:
+ run_err("protocol error: %s", why);
+ exit(1);
+ /* NOTREACHED */
+}
+
+
+int
+response(void)
+{
+ char ch, *cp, resp, rbuf[BUFSIZ];
+
+ if (read(rem, &resp, sizeof(resp)) != sizeof(resp))
+ lostconn(0);
+
+ cp = rbuf;
+ switch(resp) {
+ case 0: /* ok */
+ return (0);
+ default:
+ *cp++ = resp;
+ /* FALLTHROUGH */
+ case 1: /* error, followed by error msg */
+ case 2: /* fatal error, "" */
+ do {
+ if (read(rem, &ch, sizeof(ch)) != sizeof(ch))
+ lostconn(0);
+ *cp++ = ch;
+ } while (cp < &rbuf[BUFSIZ] && ch != '\n');
+
+ if (!iamremote)
+ (void)write(STDERR_FILENO, rbuf, (size_t)(cp - rbuf));
+ ++errs;
+ if (resp == 1)
+ return (-1);
+ exit(1);
+ }
+ /* NOTREACHED */
+}
+
+void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "usage: rcp [-46p] f1 f2; or: rcp [-46pr] f1 ... fn directory\n");
+ exit(1);
+ /* NOTREACHED */
+}
+
+#include <stdarg.h>
+
+
+void
+run_err(const char *fmt, ...)
+{
+ static FILE *fp;
+ va_list ap;
+
+ ++errs;
+ if (fp == NULL && !(fp = fdopen(rem, "w")))
+ return;
+
+ va_start(ap, fmt);
+
+ (void)fprintf(fp, "%c", 0x01);
+ (void)fprintf(fp, "rcp: ");
+ (void)vfprintf(fp, fmt, ap);
+ (void)fprintf(fp, "\n");
+ (void)fflush(fp);
+ va_end(ap);
+
+ if (!iamremote) {
+ va_start(ap, fmt);
+ vwarnx(fmt, ap);
+ va_end(ap);
+ }
+}
--- /dev/null
+/* $NetBSD: util.c,v 1.11 2006/12/15 22:45:34 christos Exp $ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * 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. 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.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)util.c 8.2 (Berkeley) 4/2/94";
+#else
+__RCSID("$NetBSD: util.c,v 1.11 2006/12/15 22:45:34 christos Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+char *
+colon(char *cp)
+{
+ if (*cp == ':') /* Leading colon is part of file name. */
+ return (0);
+
+ for (; *cp; ++cp) {
+ if (*cp == ':')
+ return (cp);
+ if (*cp == '/')
+ return (0);
+ }
+ return (0);
+}
+
+char *
+unbracket(char *cp)
+{
+ char *ep;
+
+ if (*cp == '[') {
+ ep = cp + (strlen(cp) - 1);
+ if (*ep == ']') {
+ *ep = '\0';
+ ++cp;
+ }
+ }
+ return (cp);
+}
+
+void
+verifydir(char *cp)
+{
+ struct stat stb;
+
+ if (!stat(cp, &stb)) {
+ if (S_ISDIR(stb.st_mode))
+ return;
+ errno = ENOTDIR;
+ }
+ run_err("%s: %s", cp, strerror(errno));
+ exit(1);
+ /* NOTREACHED */
+}
+
+int
+okname(char *cp0)
+{
+ int c;
+ char *cp;
+
+ cp = cp0;
+ do {
+ c = *cp;
+ if (c & 0200)
+ goto bad;
+ if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
+ goto bad;
+ } while (*++cp);
+ return (1);
+
+bad: warnx("%s: invalid user name", cp0);
+ return (0);
+}
+
+int
+susystem(char *s)
+{
+ sig_t istat, qstat;
+ int status;
+ pid_t pid;
+
+ pid = vfork();
+ switch (pid) {
+ case -1:
+ return (127);
+
+ case 0:
+ (void)execl(_PATH_BSHELL, "sh", "-c", s, NULL);
+ _exit(127);
+ /* NOTREACHED */
+ }
+ istat = signal(SIGINT, SIG_IGN);
+ qstat = signal(SIGQUIT, SIG_IGN);
+ if (waitpid(pid, &status, 0) < 0)
+ status = -1;
+ (void)signal(SIGINT, istat);
+ (void)signal(SIGQUIT, qstat);
+ return (status);
+}
+
+BUF *
+allocbuf(BUF *bp, int fd, int blksize)
+{
+ struct stat stb;
+ size_t size;
+ char *nbuf;
+
+ if (fstat(fd, &stb) < 0) {
+ run_err("fstat: %s", strerror(errno));
+ return (0);
+ }
+ size = roundup(stb.st_blksize, blksize);
+ if (size == 0)
+ size = blksize;
+ if (bp->cnt >= size)
+ return (bp);
+ if ((nbuf = realloc(bp->buf, size)) == NULL) {
+ free(bp->buf);
+ bp->buf = NULL;
+ bp->cnt = 0;
+ run_err("%s", strerror(errno));
+ return (0);
+ }
+ bp->buf = nbuf;
+ bp->cnt = size;
+ return (bp);
+}
+
+void
+/*ARGSUSED*/
+lostconn(int signo __unused)
+{
+ if (!iamremote)
+ warnx("lost connection");
+ exit(1);
+ /* NOTREACHED */
+}
./bin/printconfig minix-sys
./bin/printroot minix-sys
./bin/pwd minix-sys
+./bin/rcmd minix-sys
+./bin/rcp minix-sys
./bin/read minix-sys obsolete
./bin/readclock minix-sys
./bin/rm minix-sys
./usr/bin/info minix-sys
./usr/bin/infocmp minix-sys
./usr/bin/infokey minix-sys
-./usr/bin/in.rshd minix-sys
+./usr/bin/in.rshd minix-sys obsolete
./usr/bin/install minix-sys
./usr/bin/install-info minix-sys
./usr/bin/in.telnetd minix-sys
./usr/bin/ranlib minix-sys binutils
./usr/bin/rarpd minix-sys
./usr/bin/rawspeed minix-sys
-./usr/bin/rcp minix-sys
+./usr/bin/rcp minix-sys obsolete
./usr/bin/readelf minix-sys binutils
./usr/bin/readlink minix-sys
./usr/bin/recwave minix-sys
./usr/libexec/kyua-plain-tester minix-sys kyua
./usr/libexec/ld.elf_so minix-sys
./usr/libexec/makewhatis minix-sys
+./usr/libexec/rshd minix-sys
./usr/libexec/virecover minix-sys
./usr/log minix-sys
./usr/log/messages minix-sys
./usr/man/man1/pwhash.1 minix-sys
./usr/man/man1/ranlib.1 minix-sys binutils
./usr/man/man1/rcp.1 minix-sys
+./usr/man/man1/rcmd.1 minix-sys
./usr/man/man1/read.1 minix-sys obsolete
./usr/man/man1/readelf.1 minix-sys binutils
./usr/man/man1/readlink.1 minix-sys
daemonize talkd
-daemonize tcpd shell in.rshd
+daemonize tcpd shell /usr/libexec/rshd
daemonize tcpd telnet in.telnetd
daemonize tcpd ftp /usr/libexec/ftpd
daemonize tcpd finger /usr/libexec/fingerd
SUBDIR= \
fingerd ftpd getty \
ld.elf_so \
- \
+ rshd \
--- /dev/null
+# $NetBSD: Makefile,v 1.19 2011/08/16 10:35:03 christos Exp $
+# from: @(#)Makefile 8.1 (Berkeley) 6/4/93
+
+.include <bsd.own.mk>
+
+PROG= rshd
+MAN= rshd.8
+
+DPADD+= ${LIBUTIL}
+LDADD+= -lutil
+
+CPPFLAGS+=-DLOGIN_CAP
+
+.if (${USE_INET6} != "no")
+CPPFLAGS+=-DINET6
+.endif
+
+.if (${USE_PAM} != "no")
+CPPFLAGS+=-DUSE_PAM
+DPADD+= ${LIBPAM} ${PAM_STATIC_DPADD}
+LDADD+= -lpam ${PAM_STATIC_LDADD}
+.endif
+
+COPTS.rshd.c = -Wno-format-nonliteral
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" $NetBSD: rshd.8,v 1.18 2005/03/09 16:42:49 wiz Exp $
+.\"
+.\" Copyright (c) 1983, 1989, 1991, 1993
+.\" 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. 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: @(#)rshd.8 8.1 (Berkeley) 6/4/93
+.\"
+.Dd March 9, 2005
+.Dt RSHD 8
+.Os
+.Sh NAME
+.Nm rshd
+.Nd remote shell server
+.Sh SYNOPSIS
+.Nm
+.Op Fl aLln
+.Sh DESCRIPTION
+The
+.Nm
+server is the server for the
+.Xr rcmd 3
+routine and, consequently, for the
+.Xr rsh 1
+program.
+The server provides remote execution facilities
+with authentication based on privileged port numbers from trusted hosts.
+.Pp
+The
+.Nm
+server listens for service requests at the port indicated in
+the
+.Dq cmd
+service specification; see
+.Xr services 5 .
+When a service request is received the following protocol
+is initiated:
+.Bl -enum
+.It
+The server checks the client's source port.
+If the port is not in the range 512-1023, the server
+aborts the connection.
+.It
+The server reads characters from the socket up
+to a null
+.Pq Sq \e0
+byte.
+The resultant string is interpreted as an
+.Tn ASCII
+number, base 10.
+.It
+If the number received in step 2 is non-zero,
+it is interpreted as the port number of a secondary
+stream to be used for the
+.Em stderr .
+A second connection is then created to the specified
+port on the client's machine.
+The source port of this
+second connection is also in the range 512-1023.
+.It
+The server checks the client's source address
+and requests the corresponding host name (see
+.Xr getnameinfo 3 ,
+.Xr hosts 5 ,
+and
+.Xr named 8 ) .
+If the hostname cannot be determined,
+the dot-notation representation of the host address is used.
+If the hostname is in the same domain as the server (according to
+the last two components of the domain name), or if the
+.Fl a
+option is given,
+the addresses for the hostname are requested,
+verifying that the name and address correspond.
+If address verification fails, the connection is aborted
+with the message
+.Dq Host address mismatch.
+.It
+A null terminated user name of at most 16 characters
+is retrieved on the initial socket.
+This user name is interpreted as the user identity on the
+.Em client Ns 's
+machine.
+.It
+A null terminated user name of at most 16 characters
+is retrieved on the initial socket.
+This user name is interpreted as a user identity to use on the
+.Sy server Ns 's
+machine.
+.It
+A null terminated command to be passed to a
+shell is retrieved on the initial socket.
+The length of the command is limited by the upper
+bound on the size of the system's argument list.
+.It
+.Nm
+then validates the user using
+.Xr ruserok 3 ,
+which uses the file
+.Pa /etc/hosts.equiv
+and the
+.Pa .rhosts
+file found in the user's home directory.
+The
+.Fl l
+option prevents
+.Xr ruserok 3
+from doing any validation based on the user's
+.Dq Pa .rhosts
+file, unless the user is the superuser.
+.It
+If the file
+.Pa /etc/nologin
+exists and the user is not the superuser,
+the connection is closed.
+.It
+A null byte is returned on the initial socket
+and the command line is passed to the normal login
+shell of the user.
+The shell inherits the network connections established by
+.Nm .
+.El
+.Pp
+Transport-level keepalive messages are enabled unless the
+.Fl n
+option is present.
+The use of keepalive messages allows sessions to be timed out
+if the client crashes or becomes unreachable.
+.Pp
+The
+.Fl L
+option causes all successful accesses to be logged to
+.Xr syslogd 8
+as
+.Li auth.info
+messages.
+.Sh DIAGNOSTICS
+Except for the last one listed below,
+all diagnostic messages
+are returned on the initial socket,
+after which any network connections are closed.
+An error is indicated by a leading byte with a value of
+1 (0 is returned in step 10 above upon successful completion
+of all the steps prior to the execution of the login shell).
+.Bl -tag -width indent
+.It Sy Locuser too long.
+The name of the user on the client's machine is
+longer than 16 characters.
+.It Sy Ruser too long.
+The name of the user on the remote machine is
+longer than 16 characters.
+.It Sy Command too long .
+The command line passed exceeds the size of the argument
+list (as configured into the system).
+.It Sy Login incorrect.
+No password file entry for the user name existed.
+.It Sy Remote directory.
+The
+.Xr chdir 2
+to the home directory failed.
+.It Sy Permission denied.
+The authentication procedure described above failed.
+.It Sy Can't make pipe.
+The pipe needed for the
+.Em stderr ,
+wasn't created.
+.It Sy Can't fork; try again.
+A
+.Xr fork 2
+by the server failed.
+.It Sy \*[Lt]shellname\*[Gt]: ...
+The user's login shell could not be started.
+This message is returned on the connection associated with the
+.Em stderr ,
+and is not preceded by a flag byte.
+.El
+.Sh SEE ALSO
+.Xr rsh 1 ,
+.Xr ssh 1 ,
+.Xr rcmd 3 ,
+.Xr ruserok 3 ,
+.Xr hosts_access 5 ,
+.Xr login.conf 5 ,
+.Xr sshd 8
+.Sh BUGS
+The authentication procedure used here assumes the integrity
+of every machine and every network that can reach the rshd/rlogind
+ports on the server.
+This is insecure, but is useful in an
+.Dq open
+environment.
+.Xr sshd 8
+or a Kerberized version of this server are much more secure.
+.Pp
+A facility to allow all data exchanges to be encrypted should be
+present.
+.Pp
+A more extensible protocol (such as Telnet) should be used.
+.Pp
+.Nm
+intentionally rejects accesses from IPv4 mapped address on top of
+.Dv AF_INET6
+socket, since IPv4 mapped address complicates
+host-address based authentication.
+If you would like to accept connections from IPv4 peers, you will
+need to run
+.Nm
+on top of an
+.Dv AF_INET
+socket, not an
+.Dv AF_INET6
+socket.
--- /dev/null
+/* $NetBSD: rshd.c,v 1.50 2012/07/14 15:06:26 darrenr Exp $ */
+
+/*
+ * Copyright (C) 1998 WIDE Project.
+ * 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 WIDE Project and
+ * its contributors.
+ * 4. Neither the name of the project 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 PROJECT 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 PROJECT 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.
+ */
+
+/*-
+ * Copyright (c) 1988, 1989, 1992, 1993, 1994
+ * 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. 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.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1992, 1993, 1994\
+ The Regents of the University of California. All rights reserved.");
+#if 0
+static char sccsid[] = "@(#)rshd.c 8.2 (Berkeley) 4/6/94";
+#else
+__RCSID("$NetBSD: rshd.c,v 1.50 2012/07/14 15:06:26 darrenr Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * remote shell server:
+ * [port]\0
+ * remuser\0
+ * locuser\0
+ * command\0
+ * data
+ */
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <poll.h>
+#ifdef LOGIN_CAP
+#include <login_cap.h>
+#endif
+
+#ifdef USE_PAM
+#include <security/pam_appl.h>
+#include <security/openpam.h>
+#include <sys/wait.h>
+
+static struct pam_conv pamc = { openpam_nullconv, NULL };
+static pam_handle_t *pamh;
+static int pam_err;
+
+#define PAM_END do { \
+ if ((pam_err = pam_setcred(pamh, PAM_DELETE_CRED)) != PAM_SUCCESS) \
+ syslog(LOG_ERR|LOG_AUTH, "pam_setcred(): %s", \
+ pam_strerror(pamh, pam_err)); \
+ if ((pam_err = pam_close_session(pamh,0)) != PAM_SUCCESS) \
+ syslog(LOG_ERR|LOG_AUTH, "pam_close_session(): %s", \
+ pam_strerror(pamh, pam_err)); \
+ if ((pam_err = pam_end(pamh, pam_err)) != PAM_SUCCESS) \
+ syslog(LOG_ERR|LOG_AUTH, "pam_end(): %s", \
+ pam_strerror(pamh, pam_err)); \
+} while (/*CONSTCOND*/0)
+#else
+#define PAM_END
+#endif
+
+static int keepalive = 1;
+static int check_all;
+static int log_success; /* If TRUE, log all successful accesses */
+static int sent_null;
+
+__dead static void doit(struct sockaddr *, struct sockaddr *);
+__dead static void rshd_errx(int, const char *, ...) __printflike(2, 3);
+static void getstr(char *, int, const char *);
+static int local_domain(char *);
+static char *topdomain(char *);
+__dead static void usage(void);
+
+#define OPTIONS "aLln"
+extern int __check_rhosts_file;
+extern char *__rcmd_errstr; /* syslog hook from libc/net/rcmd.c. */
+#ifdef USE_PAM
+static const char incorrect[] = "Login incorrect.";
+#endif
+
+int
+main(int argc, char *argv[])
+{
+ struct linger linger;
+ int ch, on = 1;
+ socklen_t fromlen;
+ socklen_t locallen;
+ struct sockaddr_storage from;
+ struct sockaddr_storage local;
+ struct protoent *proto;
+
+ openlog("rshd", LOG_PID, LOG_DAEMON);
+
+ opterr = 0;
+ while ((ch = getopt(argc, argv, OPTIONS)) != -1)
+ switch (ch) {
+ case 'a':
+ check_all = 1;
+ break;
+ case 'l':
+ __check_rhosts_file = 0;
+ break;
+ case 'n':
+ keepalive = 0;
+ break;
+ case 'L':
+ log_success = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ break;
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ fromlen = sizeof(from); /* xxx */
+ locallen = sizeof(local); /* xxx */
+ if (getpeername(STDIN_FILENO, (struct sockaddr *)&from, &fromlen) < 0) {
+ syslog(LOG_ERR, "getpeername: %m");
+ return EXIT_FAILURE;
+ }
+ if (getsockname(STDIN_FILENO, (struct sockaddr *)&local,
+ &locallen) < 0) {
+ syslog(LOG_ERR, "getsockname: %m");
+ return EXIT_FAILURE;
+ }
+#if 0
+ if (((struct sockaddr *)&from)->sa_family == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&from)->sin6_addr) &&
+ sizeof(struct sockaddr_in) <= sizeof(from)) {
+ struct sockaddr_in sin;
+ struct sockaddr_in6 *sin6;
+ const int off = sizeof(struct sockaddr_in6) -
+ sizeof(struct sockaddr_in);
+
+ sin6 = (struct sockaddr_in6 *)&from;
+ (void)memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(struct sockaddr_in);
+ (void)memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[off],
+ sizeof(sin.sin_addr));
+ (void)memcpy(&from, &sin, sizeof(sin));
+ fromlen = sin.sin_len;
+ }
+#else
+ if (((struct sockaddr *)&from)->sa_family == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&from)->sin6_addr)) {
+ char hbuf[NI_MAXHOST];
+ if (getnameinfo((struct sockaddr *)&from, fromlen, hbuf,
+ sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) {
+ strlcpy(hbuf, "invalid", sizeof(hbuf));
+ }
+ syslog(LOG_ERR, "malformed \"from\" address (v4 mapped, %s)",
+ hbuf);
+ return EXIT_FAILURE;
+ }
+#endif
+ if (keepalive &&
+ setsockopt(STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
+ sizeof(on)) < 0)
+ syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
+ linger.l_onoff = 1;
+ linger.l_linger = 60; /* XXX */
+ if (setsockopt(STDIN_FILENO, SOL_SOCKET, SO_LINGER, (char *)&linger,
+ sizeof (linger)) < 0)
+ syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m");
+ proto = getprotobyname("tcp");
+ (void)setsockopt(STDIN_FILENO, proto->p_proto, TCP_NODELAY, &on,
+ sizeof(on));
+ doit((struct sockaddr *)&from, (struct sockaddr *)&local);
+}
+
+extern char **environ;
+
+static void
+doit(struct sockaddr *fromp, struct sockaddr *localp)
+{
+ struct passwd *pwd, pwres;
+ in_port_t port;
+ struct pollfd set[2];
+ int cc, pv[2], pid, s = -1; /* XXX gcc */
+ int one = 1;
+ char *hostname, *errorhost = NULL; /* XXX gcc */
+ const char *cp;
+ char sig, buf[BUFSIZ];
+ char cmdbuf[NCARGS+1], locuser[16], remuser[16];
+ char remotehost[2 * MAXHOSTNAMELEN + 1];
+ char hostnamebuf[2 * MAXHOSTNAMELEN + 1];
+#ifdef LOGIN_CAP
+ login_cap_t *lc;
+#endif
+ char naddr[NI_MAXHOST];
+ char saddr[NI_MAXHOST];
+ char raddr[NI_MAXHOST];
+ char pbuf[NI_MAXSERV];
+ int af = fromp->sa_family;
+ u_int16_t *portp;
+ struct addrinfo hints, *res, *res0;
+ int gaierror;
+ const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
+ const char *errormsg = NULL, *errorstr = NULL;
+ char pwbuf[1024];
+
+ (void)signal(SIGINT, SIG_DFL);
+ (void)signal(SIGQUIT, SIG_DFL);
+ (void)signal(SIGTERM, SIG_DFL);
+#ifdef DEBUG
+ {
+ int t = open(_PATH_TTY, O_RDWR);
+ if (t >= 0) {
+ ioctl(t, TIOCNOTTY, NULL);
+ (void)close(t);
+ }
+ }
+#endif
+ switch (af) {
+ case AF_INET:
+ portp = &((struct sockaddr_in *)fromp)->sin_port;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ portp = &((struct sockaddr_in6 *)fromp)->sin6_port;
+ break;
+#endif
+ default:
+ syslog(LOG_ERR, "malformed \"from\" address (af %d)", af);
+ exit(EXIT_FAILURE);
+ }
+ if (getnameinfo(fromp, fromp->sa_len, naddr, sizeof(naddr),
+ pbuf, sizeof(pbuf), niflags) != 0) {
+ syslog(LOG_ERR, "malformed \"from\" address (af %d)", af);
+ exit(EXIT_FAILURE);
+ }
+#ifdef IP_OPTIONS
+ if (af == AF_INET) {
+
+ u_char optbuf[BUFSIZ/3];
+ socklen_t optsize = sizeof(optbuf);
+ int ipproto;
+ unsigned int i;
+ struct protoent *ip;
+
+ if ((ip = getprotobyname("ip")) != NULL)
+ ipproto = ip->p_proto;
+ else
+ ipproto = IPPROTO_IP;
+ if (!getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, &optsize) &&
+ optsize != 0) {
+ for (i = 0; i < optsize;) {
+ u_char c = optbuf[i];
+ if (c == IPOPT_LSRR || c == IPOPT_SSRR) {
+ syslog(LOG_NOTICE,
+ "Connection refused from %s "
+ "with IP option %s",
+ inet_ntoa((
+ (struct sockaddr_in *)fromp)->sin_addr),
+ c == IPOPT_LSRR ? "LSRR" : "SSRR");
+ exit(EXIT_FAILURE);
+ }
+ if (c == IPOPT_EOL)
+ break;
+ i += (c == IPOPT_NOP) ? 1 : optbuf[i + 1];
+ }
+ }
+ }
+#endif
+ if (ntohs(*portp) >= IPPORT_RESERVED
+ || ntohs(*portp) < IPPORT_RESERVED / 2) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "Connection from %s on illegal port %u",
+ naddr, ntohs(*portp));
+ exit(EXIT_FAILURE);
+ }
+
+ (void) alarm(60);
+ port = 0;
+ for (;;) {
+ char c;
+
+ if ((cc = read(STDIN_FILENO, &c, 1)) != 1) {
+ if (cc < 0)
+ syslog(LOG_ERR, "read: %m");
+ (void)shutdown(0, SHUT_RDWR);
+ exit(EXIT_FAILURE);
+ }
+ if (c == 0)
+ break;
+ port = port * 10 + c - '0';
+ }
+
+ (void) alarm(0);
+ if (port != 0) {
+ int lport = IPPORT_RESERVED - 1;
+ s = rresvport_af_addr(&lport, af, localp);
+ if (s < 0) {
+ syslog(LOG_ERR, "can't get stderr port: %m");
+ exit(EXIT_FAILURE);
+ }
+ if (port >= IPPORT_RESERVED) {
+ syslog(LOG_ERR, "2nd port not reserved");
+ exit(EXIT_FAILURE);
+ }
+ *portp = htons(port);
+ if (connect(s, fromp, fromp->sa_len) < 0) {
+ syslog(LOG_ERR, "connect second port %d: %m", port);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+
+#ifdef notdef
+ /* from inetd, socket is already on 0, 1, 2 */
+ (void)dup2(f, STDIN_FILENO);
+ (void)dup2(f, STDOUT_FILENO);
+ (void)dup2(f, STDERR_FILENO);
+#endif
+ if (getnameinfo(fromp, fromp->sa_len, saddr, sizeof(saddr),
+ NULL, 0, NI_NAMEREQD) == 0) {
+ /*
+ * If name returned by getnameinfo is in our domain,
+ * attempt to verify that we haven't been fooled by someone
+ * in a remote net; look up the name and check that this
+ * address corresponds to the name.
+ */
+ hostname = saddr;
+ res0 = NULL;
+ if (check_all || local_domain(saddr)) {
+ (void)strlcpy(remotehost, saddr, sizeof(remotehost));
+ errorhost = remotehost;
+ (void)memset(&hints, 0, sizeof(hints));
+ hints.ai_family = fromp->sa_family;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_CANONNAME;
+ gaierror = getaddrinfo(remotehost, pbuf, &hints, &res0);
+ if (gaierror) {
+ syslog(LOG_NOTICE,
+ "Couldn't look up address for %s: %s",
+ remotehost, gai_strerror(gaierror));
+ errorstr =
+ "Couldn't look up address for your host (%s)\n";
+ hostname = naddr;
+ } else {
+ for (res = res0; res; res = res->ai_next) {
+ if (res->ai_family != fromp->sa_family)
+ continue;
+ if (res->ai_addrlen != fromp->sa_len)
+ continue;
+ if (getnameinfo(res->ai_addr,
+ res->ai_addrlen,
+ raddr, sizeof(raddr), NULL, 0,
+ niflags) == 0
+ && strcmp(naddr, raddr) == 0) {
+ hostname = res->ai_canonname
+ ? res->ai_canonname
+ : saddr;
+ break;
+ }
+ }
+ if (res == NULL) {
+ syslog(LOG_NOTICE,
+ "Host addr %s not listed for host %s",
+ naddr, res0->ai_canonname
+ ? res0->ai_canonname
+ : saddr);
+ errorstr =
+ "Host address mismatch for %s\n";
+ hostname = naddr;
+ }
+ }
+ }
+ (void)strlcpy(hostnamebuf, hostname, sizeof(hostnamebuf));
+ hostname = hostnamebuf;
+ if (res0)
+ freeaddrinfo(res0);
+ } else {
+ (void)strlcpy(hostnamebuf, naddr, sizeof(hostnamebuf));
+ errorhost = hostname = hostnamebuf;
+ }
+
+ (void)alarm(60);
+ getstr(remuser, sizeof(remuser), "remuser");
+ getstr(locuser, sizeof(locuser), "locuser");
+ getstr(cmdbuf, sizeof(cmdbuf), "command");
+ (void)alarm(0);
+
+#ifdef USE_PAM
+ pam_err = pam_start("rsh", locuser, &pamc, &pamh);
+ if (pam_err != PAM_SUCCESS) {
+ syslog(LOG_ERR|LOG_AUTH, "pam_start(): %s",
+ pam_strerror(pamh, pam_err));
+ rshd_errx(EXIT_FAILURE, incorrect);
+ }
+
+ if ((pam_err = pam_set_item(pamh, PAM_RUSER, remuser)) != PAM_SUCCESS ||
+ (pam_err = pam_set_item(pamh, PAM_RHOST, hostname)) != PAM_SUCCESS){
+ syslog(LOG_ERR|LOG_AUTH, "pam_set_item(): %s",
+ pam_strerror(pamh, pam_err));
+ rshd_errx(EXIT_FAILURE, incorrect);
+ }
+
+ pam_err = pam_authenticate(pamh, 0);
+ if (pam_err == PAM_SUCCESS) {
+ if ((pam_err = pam_get_user(pamh, &cp, NULL)) == PAM_SUCCESS) {
+ (void)strlcpy(locuser, cp, sizeof(locuser));
+ /* XXX truncation! */
+ }
+ pam_err = pam_acct_mgmt(pamh, 0);
+ }
+ if (pam_err != PAM_SUCCESS) {
+ errorstr = incorrect;
+ errormsg = pam_strerror(pamh, pam_err);
+ goto badlogin;
+ }
+#endif /* USE_PAM */
+ setpwent();
+ if (getpwnam_r(locuser, &pwres, pwbuf, sizeof(pwbuf), &pwd) != 0 ||
+ pwd == NULL) {
+ syslog(LOG_INFO|LOG_AUTH,
+ "%s@%s as %s: unknown login. cmd='%.80s'",
+ remuser, hostname, locuser, cmdbuf);
+ if (errorstr == NULL)
+ errorstr = "Permission denied.";
+ rshd_errx(EXIT_FAILURE, errorstr, errorhost);
+ }
+#ifdef LOGIN_CAP
+ lc = login_getclass(pwd ? pwd->pw_class : NULL);
+#endif
+
+ if (chdir(pwd->pw_dir) < 0) {
+ if (chdir("/") < 0
+#ifdef LOGIN_CAP
+ || login_getcapbool(lc, "requirehome", pwd->pw_uid ? 1 : 0)
+#endif
+ ) {
+ syslog(LOG_INFO|LOG_AUTH,
+ "%s@%s as %s: no home directory. cmd='%.80s'",
+ remuser, hostname, locuser, cmdbuf);
+ rshd_errx(EXIT_SUCCESS, "No remote home directory.");
+ }
+ }
+
+#ifndef USE_PAM
+ if (errorstr ||
+ (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
+ iruserok_sa(fromp, fromp->sa_len, pwd->pw_uid == 0, remuser,
+ locuser) < 0)) {
+ errormsg = __rcmd_errstr ? __rcmd_errstr : "unknown error";
+ if (errorstr == NULL)
+ errorstr = "Permission denied.";
+ goto badlogin;
+ }
+
+ if (pwd->pw_uid && !access(_PATH_NOLOGIN, F_OK))
+ rshd_errx(EXIT_FAILURE, "Logins currently disabled.");
+#endif
+
+#ifdef LOGIN_CAP
+ /*
+ * PAM modules might add supplementary groups in
+ * pam_setcred(), so initialize them first.
+ * But we need to open the session as root.
+ */
+ if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETGROUP) != 0) {
+ syslog(LOG_ERR, "setusercontext: %m");
+ exit(EXIT_FAILURE);
+ }
+#else
+ initgroups(pwd->pw_name, pwd->pw_gid);
+#endif
+
+#ifdef USE_PAM
+ if ((pam_err = pam_open_session(pamh, 0)) != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_open_session: %s",
+ pam_strerror(pamh, pam_err));
+ } else if ((pam_err = pam_setcred(pamh, PAM_ESTABLISH_CRED))
+ != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, pam_err));
+ }
+#endif
+
+ (void)write(STDERR_FILENO, "\0", 1);
+ sent_null = 1;
+
+ if (port) {
+ if (pipe(pv) < 0)
+ rshd_errx(EXIT_FAILURE, "Can't make pipe. (%s)",
+ strerror(errno));
+ pid = fork();
+ if (pid == -1)
+ rshd_errx(EXIT_FAILURE, "Can't fork. (%s)",
+ strerror(errno));
+ if (pid) {
+ (void)close(STDIN_FILENO);
+ (void)close(STDOUT_FILENO);
+ (void)close(STDERR_FILENO);
+ (void)close(pv[1]);
+
+ set[0].fd = s;
+ set[0].events = POLLIN;
+ set[1].fd = pv[0];
+ set[1].events = POLLIN;
+ ioctl(pv[0], FIONBIO, (char *)&one);
+
+ /* should set s nbio! */
+ do {
+#ifdef __minix
+ if (set[0].events == 0 && set[1].events == 0)
+ break;
+#endif /* __minix */
+ if (poll(set, 2, INFTIM) < 0)
+ break;
+ if (set[0].revents & POLLIN) {
+ int ret;
+
+ ret = read(s, &sig, 1);
+ if (ret <= 0)
+ set[0].events = 0;
+ else
+ killpg(pid, sig);
+ }
+ if (set[1].revents & POLLIN) {
+ errno = 0;
+ cc = read(pv[0], buf, sizeof(buf));
+ if (cc <= 0) {
+ shutdown(s, SHUT_RDWR);
+ set[1].events = 0;
+ } else {
+ (void)write(s, buf, cc);
+ }
+ }
+
+ } while ((set[0].revents | set[1].revents) & POLLIN);
+ PAM_END;
+ exit(EXIT_SUCCESS);
+ }
+ (void)close(s);
+ (void)close(pv[0]);
+ (void)dup2(pv[1], STDERR_FILENO);
+ close(pv[1]);
+ }
+#ifdef USE_PAM
+ else {
+ pid = fork();
+ if (pid == -1)
+ rshd_errx(EXIT_FAILURE, "Can't fork. (%s)",
+ strerror(errno));
+ if (pid) {
+ pid_t xpid;
+ int status;
+ if ((xpid = waitpid(pid, &status, 0)) != pid) {
+ pam_err = pam_close_session(pamh, 0);
+ if (pam_err != PAM_SUCCESS) {
+ syslog(LOG_ERR,
+ "pam_close_session: %s",
+ pam_strerror(pamh, pam_err));
+ }
+ PAM_END;
+ if (xpid != -1)
+ syslog(LOG_WARNING,
+ "wrong PID: %d != %d", pid, xpid);
+ else
+ syslog(LOG_WARNING,
+ "wait pid=%d failed %m", pid);
+ exit(EXIT_FAILURE);
+ }
+ exit(EXIT_SUCCESS);
+ }
+ }
+#endif
+
+#ifdef F_CLOSEM
+ (void)fcntl(STDERR_FILENO + 1, F_CLOSEM, 0);
+#else
+ for (fd = getdtablesize(); fd > STDERR_FILENO; fd--)
+ (void)close(fd);
+#endif
+ if (setsid() == -1)
+ syslog(LOG_ERR, "setsid() failed: %m");
+#ifdef USE_PAM
+ if (setlogin(pwd->pw_name) < 0)
+ syslog(LOG_ERR, "setlogin() failed: %m");
+
+ if (*pwd->pw_shell == '\0')
+ pwd->pw_shell = __UNCONST(_PATH_BSHELL);
+
+ (void)pam_setenv(pamh, "HOME", pwd->pw_dir, 1);
+ (void)pam_setenv(pamh, "SHELL", pwd->pw_shell, 1);
+ (void)pam_setenv(pamh, "USER", pwd->pw_name, 1);
+ (void)pam_setenv(pamh, "PATH", _PATH_DEFPATH, 1);
+ environ = pam_getenvlist(pamh);
+ (void)pam_end(pamh, pam_err);
+#else
+#ifdef LOGIN_CAP
+ {
+ char *sh;
+ if ((sh = login_getcapstr(lc, "shell", NULL, NULL))) {
+ if(!(sh = strdup(sh))) {
+ syslog(LOG_ERR, "Cannot alloc mem");
+ exit(EXIT_FAILURE);
+ }
+ pwd->pw_shell = sh;
+ }
+ }
+#endif
+{
+ static char *envinit[] = { NULL };
+ environ = envinit;
+}
+ setenv("PATH", _PATH_DEFPATH, 1);
+ setenv("HOME", pwd->pw_dir, 1);
+ setenv("SHELL", pwd->pw_shell, 1);
+ setenv("USER", pwd->pw_name, 1);
+#endif
+
+ cp = strrchr(pwd->pw_shell, '/');
+ if (cp)
+ cp++;
+ else
+ cp = pwd->pw_shell;
+
+#ifdef LOGIN_CAP
+ if (setusercontext(lc, pwd, pwd->pw_uid,
+ LOGIN_SETALL & ~LOGIN_SETGROUP) < 0) {
+ syslog(LOG_ERR, "setusercontext(): %m");
+ exit(EXIT_FAILURE);
+ }
+ login_close(lc);
+#else
+ (void)setgid((gid_t)pwd->pw_gid);
+ (void)setuid((uid_t)pwd->pw_uid);
+#endif
+ endpwent();
+ if (log_success || pwd->pw_uid == 0) {
+ syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: cmd='%.80s'",
+ remuser, hostname, locuser, cmdbuf);
+ }
+ (void)execl(pwd->pw_shell, cp, "-c", cmdbuf, NULL);
+ rshd_errx(EXIT_FAILURE, "%s: %s", pwd->pw_shell, strerror(errno));
+badlogin:
+ syslog(LOG_INFO|LOG_AUTH,
+ "%s@%s as %s: permission denied (%s). cmd='%.80s'",
+ remuser, hostname, locuser, errormsg, cmdbuf);
+ rshd_errx(EXIT_FAILURE, errorstr, errorhost);
+}
+
+/*
+ * Report error to client. Note: can't be used until second socket has
+ * connected to client, or older clients will hang waiting for that
+ * connection first.
+ */
+
+#include <stdarg.h>
+
+static void
+rshd_errx(int error, const char *fmt, ...)
+{
+ va_list ap;
+ int len, rv;
+ char *bp, buf[BUFSIZ];
+ va_start(ap, fmt);
+ bp = buf;
+ if (sent_null == 0) {
+ *bp++ = 1;
+ len = 1;
+ } else
+ len = 0;
+ rv = vsnprintf(bp, sizeof(buf) - 2, fmt, ap);
+ bp[rv++] = '\n';
+ (void)write(STDERR_FILENO, buf, len + rv);
+ va_end(ap);
+ exit(error);
+}
+
+static void
+getstr(char *buf, int cnt, const char *err)
+{
+ char c;
+
+ do {
+ if (read(STDIN_FILENO, &c, 1) != 1)
+ exit(EXIT_FAILURE);
+ *buf++ = c;
+ if (--cnt == 0)
+ rshd_errx(EXIT_FAILURE, "%s too long", err);
+ } while (c != 0);
+}
+
+/*
+ * Check whether host h is in our local domain,
+ * defined as sharing the last two components of the domain part,
+ * or the entire domain part if the local domain has only one component.
+ * If either name is unqualified (contains no '.'),
+ * assume that the host is local, as it will be
+ * interpreted as such.
+ */
+static int
+local_domain(char *h)
+{
+ char localhost[MAXHOSTNAMELEN + 1];
+ char *p1, *p2;
+
+ localhost[0] = 0;
+ (void)gethostname(localhost, sizeof(localhost));
+ localhost[sizeof(localhost) - 1] = '\0';
+ p1 = topdomain(localhost);
+ p2 = topdomain(h);
+ if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2))
+ return (1);
+ return (0);
+}
+
+static char *
+topdomain(char *h)
+{
+ char *p, *maybe = NULL;
+ int dots = 0;
+
+ for (p = h + strlen(h); p >= h; p--) {
+ if (*p == '.') {
+ if (++dots == 2)
+ return (p);
+ maybe = p;
+ }
+ }
+ return (maybe);
+}
+
+static void
+usage(void)
+{
+
+ syslog(LOG_ERR, "Usage: %s [-%s]", getprogname(), OPTIONS);
+ exit(EXIT_FAILURE);
+}
nonamed \
postinstall prep printroot \
profile progressbar pr_routes ps pwdauth \
- ramdisk rarpd rawspeed rcp readclock \
+ ramdisk rarpd rawspeed readclock \
remsync rget rlogin \
- rotate rsh rshd service setup \
+ rotate service setup \
slip spell sprofalyze sprofdiff srccrc \
svclog svrctl swifi synctree sysenv \
tcpd tcpdp tcpstat telnet \
+++ /dev/null
-PROG= rcp
-MAN=
-
-.include <bsd.prog.mk>
+++ /dev/null
-/*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved. The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
- */
-
-#ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1983 Regents of the University of California.\n\
- All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)rcp.c 1.1 87/12/21 SMI"; /* from UCB 5.3 6/8/85"*/
-#endif
-#endif /* not lint */
-
-/*
- * rcp
- */
-
-#define NAMESERVER
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <utime.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-
-#include <dirent.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <signal.h>
-#include <unistd.h>
-
-#include <netdb.h>
-#include <net/netlib.h>
-
-#if __STDC__
-#define PROTO(func, args) func args
-#else
-#define PROTO(func, args) func ()
-#endif /* __STDC__ */
-
-PROTO (int main, (int argc, char *argv[]));
-PROTO (void lostconn, (int sig));
-PROTO (void error, (char *fmt, ...) );
-PROTO (int response, (void) );
-PROTO (void source, (int argc, char *argv[]) );
-PROTO (void sink, (int argc, char *argv[]) );
-PROTO (void usage, (void) );
-PROTO (char *colon, (char *cp) );
-PROTO (int okname, (char *cp0) );
-PROTO (int susystem, (char *s) );
-PROTO (void verifydir, (char *cp) );
-PROTO (void rsource, (char *name, struct stat *statp) );
-PROTO (struct buffer *allocbuf, (struct buffer *bp, int fd, int blksize) );
-
-#define vfork fork
-
-int rem;
-int errs;
-int errno;
-int iamremote, targetshouldbedirectory;
-int iamrecursive;
-int myuid; /* uid of invoker */
-int pflag;
-struct passwd *pwd;
-int userid;
-int port;
-
-struct buffer {
- int cnt;
- char *buf;
-};
-
-
-#define ga() (void) write(rem, "", 1)
-
-int main(argc, argv)
- int argc;
- char **argv;
-{
- char *targ, *host, *src;
-#ifndef NAMESERVER
- char *suser, *tuser;
-#else /* NAMESERVER */
- char *suser, *tuser, *thost;
-#endif /* NAMESERVER */
- int i;
- char buf[BUFSIZ], cmd[16];
- struct servent *sp;
-
- sp = getservbyname("shell", "tcp");
- if (sp == NULL) {
- fprintf(stderr, "rcp: shell/tcp: unknown service\n");
- exit(1);
- }
- port = sp->s_port;
- pwd = getpwuid(userid = getuid());
- if (pwd == 0) {
- fprintf(stderr, "who are you?\n");
- exit(1);
- }
-
-#ifdef NOT_DEF
- /*
- * This is a kludge to allow seteuid to user before touching
- * files and seteuid root before doing rcmd so we can open
- * the socket.
- */
- myuid = getuid();
- if (setruid(0) < 0) {
- perror("setruid root");
- exit(1);
- }
- seteuid(myuid);
-#endif
-
- for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) {
- (*argv)++;
- while (**argv) switch (*(*argv)++) {
-
- case 'r':
- iamrecursive++;
- break;
-
- case 'p': /* preserve mtimes and atimes */
- pflag++;
- break;
-
- /* The rest of these are not for users. */
- case 'd':
- targetshouldbedirectory = 1;
- break;
-
- case 'f': /* "from" */
- iamremote = 1;
- (void) response();
- source(--argc, ++argv);
- exit(errs);
-
- case 't': /* "to" */
- iamremote = 1;
- sink(--argc, ++argv);
- exit(errs);
-
- default:
- usage();
- exit(1);
- }
- }
-if (iamremote)
-{
- close(2);
- open("/dev/tty", 2);
-}
-
- if (argc < 2) {
- usage();
- exit(1);
- }
- rem = -1;
- if (argc > 2)
- targetshouldbedirectory = 1;
- (void) sprintf(cmd, "rcp%s%s%s",
- iamrecursive ? " -r" : "", pflag ? " -p" : "",
- targetshouldbedirectory ? " -d" : "");
- (void) signal(SIGPIPE, lostconn);
- targ = colon(argv[argc - 1]);
- if (targ) { /* ... to remote */
- *targ++ = 0;
- if (*targ == 0)
- targ = ".";
-#ifndef NAMESERVER
- tuser = strrchr(argv[argc - 1], '.');
- if (tuser) {
- *tuser++ = 0;
- if (!okname(tuser))
- exit(1);
- } else
- tuser = pwd->pw_name;
-#else /* NAMESERVER */
- thost = strchr(argv[argc - 1], '@');
- if (thost) {
- *thost++ = 0;
- tuser = argv[argc - 1];
- if (*tuser == '\0')
- tuser = pwd->pw_name;
- else if (!okname(tuser))
- exit(1);
- } else {
- thost = argv[argc - 1];
- tuser = pwd->pw_name;
- }
-#endif /* NAMESERVER */
- for (i = 0; i < argc - 1; i++) {
- src = colon(argv[i]);
- if (src) { /* remote to remote */
- *src++ = 0;
- if (*src == 0)
- src = ".";
-#ifndef NAMESERVER
- suser = strrchr(argv[i], '.');
- if (suser) {
- *suser++ = 0;
- if (!okname(suser))
-#else /* NAMESERVER */
- host = strchr(argv[i], '@');
- if (host) {
- *host++ = 0;
- suser = argv[i];
- if (*suser == '\0')
- suser = pwd->pw_name;
- else if (!okname(suser))
-#endif /* NAMESERVER */
- continue;
-#ifndef NAMESERVER
- (void) sprintf(buf, "rsh %s -l %s -n %s %s '%s.%s:%s'",
- argv[i], suser, cmd, src,
- argv[argc - 1], tuser, targ);
- } else
- (void) sprintf(buf, "rsh %s -n %s %s '%s.%s:%s'",
- argv[i], cmd, src,
- argv[argc - 1], tuser, targ);
-#else /* NAMESERVER */
- (void) sprintf(buf, "rsh %s -l %s -n %s %s '%s@%s:%s'",
- host, suser, cmd, src,
- tuser, thost, targ);
- } else
- (void) sprintf(buf, "rsh %s -n %s %s '%s@%s:%s'",
- argv[i], cmd, src,
- tuser, thost, targ);
-#endif /* NAMESERVER */
- (void) susystem(buf);
- } else { /* local to remote */
- if (rem == -1) {
- (void) sprintf(buf, "%s -t %s",
- cmd, targ);
-#ifndef NAMESERVER
- host = argv[argc - 1];
-#else /* NAMESERVER */
- host = thost;
-#endif /* NAMESERVER */
-#ifdef NOT_DEF
- if (seteuid(0) < 0) {
- perror("seteuid root");
- exit(1);
- }
-#endif
- rem = rcmd(&host, port, pwd->pw_name,
- tuser, buf, 0);
-#ifdef NO_DEF
- seteuid(myuid);
-#endif
- if (rem < 0)
- exit(1);
- if (response() < 0)
- exit(1);
- }
- source(1, argv+i);
- }
- }
- } else { /* ... to local */
- if (targetshouldbedirectory)
- verifydir(argv[argc - 1]);
- for (i = 0; i < argc - 1; i++) {
- src = colon(argv[i]);
- if (src == 0) { /* local to local */
- (void) sprintf(buf, "cp%s%s %s %s",
- iamrecursive ? " -r" : "",
- pflag ? " -p" : "",
- argv[i], argv[argc - 1]);
- (void) susystem(buf);
- } else { /* remote to local */
- *src++ = 0;
- if (*src == 0)
- src = ".";
-#ifndef NAMESERVER
- suser = strrchr(argv[i], '.');
- if (suser) {
- *suser++ = 0;
- if (!okname(suser))
-#else /* NAMESERVER */
- host = strchr(argv[i], '@');
- if (host) {
- *host++ = 0;
- suser = argv[i];
- if (*suser == '\0')
- suser = pwd->pw_name;
- else if (!okname(suser))
-#endif /* NAMESERVER */
- continue;
-#ifndef NAMESERVER
- } else
-#else /* NAMESERVER */
- } else {
- host = argv[i];
-#endif /* NAMESERVER */
- suser = pwd->pw_name;
-#ifdef NAMESERVER
- }
-#endif /* NAMESERVER */
- (void) sprintf(buf, "%s -f %s", cmd, src);
-#ifndef NAMESERVER
- host = argv[i];
-#endif /* NAMESERVER */
-#ifdef NOT_DEF
- if (seteuid(0) < 0) {
- perror("seteuid root");
- exit(1);
- }
-#endif
- rem = rcmd(&host, port, pwd->pw_name, suser,
- buf, 0);
-#ifdef NOT_DEF
- seteuid(myuid);
-#endif
- if (rem < 0) {
- errs++;
- continue;
- }
- sink(1, argv+argc-1);
- (void) close(rem);
- rem = -1;
- }
- }
- }
- exit(errs);
-}
-
-void
-verifydir(cp)
- char *cp;
-{
- struct stat stb;
-
- if (stat(cp, &stb) >= 0) {
- if ((stb.st_mode & S_IFMT) == S_IFDIR)
- return;
- errno = ENOTDIR;
- }
- error("rcp: %s: %s.\n", cp, strerror(errno));
- exit(1);
-}
-
-char *
-colon(cp)
- char *cp;
-{
-
- while (*cp) {
- if (*cp == ':')
- return (cp);
- if (*cp == '/')
- return (0);
- cp++;
- }
- return (0);
-}
-
-
-int
-okname(cp0)
- char *cp0;
-{
- register char *cp = cp0;
- register int c;
-
- do {
- c = *cp;
- if (c & 0200)
- goto bad;
- if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
- goto bad;
- cp++;
- } while (*cp);
- return (1);
-bad:
- fprintf(stderr, "rcp: invalid user name %s\n", cp0);
- return (0);
-}
-
-int
-susystem(s)
- char *s;
-{
- int status, pid, w;
- register void PROTO ((*istat), (int) ), PROTO ((*qstat), (int) );
-
- if ((pid = vfork()) == 0) {
-#ifdef NOT_DEF
- (void) setruid(myuid);
-#endif
- execl("/bin/sh", "sh", "-c", s, (char *)0);
- _exit(127);
- }
- istat = signal(SIGINT, SIG_IGN);
- qstat = signal(SIGQUIT, SIG_IGN);
- while ((w = wait(&status)) != pid && w != -1)
- ;
- if (w == -1)
- status = -1;
- (void) signal(SIGINT, istat);
- (void) signal(SIGQUIT, qstat);
- return (status);
-}
-
-void
-source(argc, argv)
- int argc;
- char **argv;
-{
- char *last, *name;
- struct stat stb;
- static struct buffer buffer;
- struct buffer *bp;
- int x, sizerr, f, amt;
- off_t i;
- char buf[BUFSIZ];
-
- for (x = 0; x < argc; x++) {
- name = argv[x];
- if ((f = open(name, 0)) < 0) {
- error("rcp: %s: %s\n", name, strerror(errno));
- continue;
- }
- if (fstat(f, &stb) < 0)
- goto notreg;
- switch (stb.st_mode&S_IFMT) {
-
- case S_IFREG:
- break;
-
- case S_IFDIR:
- if (iamrecursive) {
- (void) close(f);
- rsource(name, &stb);
- continue;
- }
- /* fall into ... */
- default:
-notreg:
- (void) close(f);
- error("rcp: %s: not a plain file\n", name);
- continue;
- }
- last = strrchr(name, '/');
- if (last == 0)
- last = name;
- else
- last++;
- if (pflag) {
- /*
- * Make it compatible with possible future
- * versions expecting microseconds.
- */
- (void) sprintf(buf, "T%d 0 %d 0\n",
- stb.st_mtime, stb.st_atime);
- (void) write(rem, buf, strlen(buf));
- if (response() < 0) {
- (void) close(f);
- continue;
- }
- }
- (void) sprintf(buf, "C%04o %lld %s\n",
- stb.st_mode&07777, stb.st_size, last);
- (void) write(rem, buf, strlen(buf));
- if (response() < 0) {
- (void) close(f);
- continue;
- }
- if ((bp = allocbuf(&buffer, f, BUFSIZ)) == 0) {
- (void) close(f);
- continue;
- }
- sizerr = 0;
- for (i = 0; i < stb.st_size; i += bp->cnt) {
- amt = bp->cnt;
- if (i + amt > stb.st_size)
- amt = stb.st_size - i;
- if (sizerr == 0 && read(f, bp->buf, amt) != amt)
- sizerr = 1;
- (void) write(rem, bp->buf, amt);
- }
- (void) close(f);
- if (sizerr == 0)
- ga();
- else
- error("rcp: %s: file changed size\n", name);
- (void) response();
- }
-}
-
-
-void
-rsource(name, statp)
- char *name;
- struct stat *statp;
-{
- DIR *d = opendir(name);
- char *last;
- struct dirent *dp;
- char buf[BUFSIZ];
- char *bufv[1];
-
- if (d == 0) {
- error("rcp: %s: %s\n", name, strerror(errno));
- return;
- }
- last = strrchr(name, '/');
- if (last == 0)
- last = name;
- else
- last++;
- if (pflag) {
- (void) sprintf(buf, "T%d 0 %d 0\n",
- statp->st_mtime, statp->st_atime);
- (void) write(rem, buf, strlen(buf));
- if (response() < 0) {
- closedir(d);
- return;
- }
- }
- (void) sprintf(buf, "D%04o %d %s\n", statp->st_mode&07777, 0, last);
- (void) write(rem, buf, strlen(buf));
- if (response() < 0) {
- closedir(d);
- return;
- }
- while ((dp = readdir(d))) {
- if (dp->d_ino == 0)
- continue;
- if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
- continue;
- if (strlen(name) + 1 + strlen(dp->d_name) >= BUFSIZ - 1) {
- error("%s/%s: Name too long.\n", name, dp->d_name);
- continue;
- }
- (void) sprintf(buf, "%s/%s", name, dp->d_name);
- bufv[0] = buf;
- source(1, bufv);
- }
- closedir(d);
- (void) write(rem, "E\n", 2);
- (void) response();
-}
-
-int
-response()
-{
- char resp, c, rbuf[BUFSIZ], *cp = rbuf;
-
- if (read(rem, &resp, 1) != 1)
- lostconn(0);
- switch (resp) {
-
- case 0: /* ok */
- return (0);
-
- default:
- *cp++ = resp;
- /* fall into... */
- case 1: /* error, followed by err msg */
- case 2: /* fatal error, "" */
- do {
- if (read(rem, &c, 1) != 1)
- lostconn(0);
- *cp++ = c;
- } while (cp < &rbuf[BUFSIZ] && c != '\n');
- if (iamremote == 0)
- (void) write(2, rbuf, cp - rbuf);
- errs++;
- if (resp == 1)
- return (-1);
- exit(1);
- }
- /*NOTREACHED*/
-}
-
-void
-lostconn(sig)
-int sig;
-{
-
- if (iamremote == 0)
- fprintf(stderr, "rcp: lost connection\n");
- exit(1);
-}
-
-void
-sink(argc, argv)
- int argc;
- char **argv;
-{
- off_t i, j, size;
- char *targ, *whopp, *cp;
- int of, mode, wrerr, exists, first, count, amt;
- struct buffer *bp;
- static struct buffer buffer;
- struct stat stb;
- int targisdir = 0;
- int mask = umask(0);
- char *myargv[1];
- char cmdbuf[BUFSIZ], nambuf[BUFSIZ];
- int setimes = 0;
- struct utimbuf utimbuf;
-#define atime utimbuf.actime
-#define mtime utimbuf.modtime
- time_t dummy;
-#define SCREWUP(str) { whopp = str; goto screwup; }
-
-#ifdef NOT_DEF
- seteuid(pwd->pw_uid);
-#endif
- if (!pflag)
- (void) umask(mask);
- if (argc != 1) {
- error("rcp: ambiguous target\n");
- exit(1);
- }
- targ = *argv;
- if (targetshouldbedirectory)
- verifydir(targ);
- ga();
- if (stat(targ, &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFDIR)
- targisdir = 1;
- for (first = 1; ; first = 0) {
- cp = cmdbuf;
- if (read(rem, cp, 1) <= 0)
- return;
- if (*cp++ == '\n')
- SCREWUP("unexpected '\\n'");
- do {
- if (read(rem, cp, 1) != 1)
- SCREWUP("lost connection");
- } while (*cp++ != '\n');
- *cp = 0;
- if (cmdbuf[0] == '\01' || cmdbuf[0] == '\02') {
- if (iamremote == 0)
- (void) write(2, cmdbuf+1, strlen(cmdbuf+1));
- if (cmdbuf[0] == '\02')
- exit(1);
- errs++;
- continue;
- }
- *--cp = 0;
- cp = cmdbuf;
- if (*cp == 'E') {
- ga();
- return;
- }
-
-#define getnum(t) (t) = 0; while (isdigit(*cp)) (t) = (t) * 10 + (*cp++ - '0');
- if (*cp == 'T') {
- setimes++;
- cp++;
- getnum(mtime);
- if (*cp++ != ' ')
- SCREWUP("mtime.sec not delimited");
- getnum(dummy);
- if (*cp++ != ' ')
- SCREWUP("mtime.usec not delimited");
- getnum(atime);
- if (*cp++ != ' ')
- SCREWUP("atime.sec not delimited");
- getnum(dummy);
- if (*cp++ != '\0')
- SCREWUP("atime.usec not delimited");
- ga();
- continue;
- }
- if (*cp != 'C' && *cp != 'D') {
- /*
- * Check for the case "rcp remote:foo\* local:bar".
- * In this case, the line "No match." can be returned
- * by the shell before the rcp command on the remote is
- * executed so the ^Aerror_message convention isn't
- * followed.
- */
- if (first) {
- error("%s\n", cp);
- exit(1);
- }
- SCREWUP("expected control record");
- }
- cp++;
- mode = 0;
- for (; cp < cmdbuf+5; cp++) {
- if (*cp < '0' || *cp > '7')
- SCREWUP("bad mode");
- mode = (mode << 3) | (*cp - '0');
- }
- if (*cp++ != ' ')
- SCREWUP("mode not delimited");
- size = 0;
- while (isdigit(*cp))
- size = size * 10 + (*cp++ - '0');
- if (*cp++ != ' ')
- SCREWUP("size not delimited");
- if (targisdir)
- (void) sprintf(nambuf, "%s%s%s", targ,
- *targ ? "/" : "", cp);
- else
- (void) strcpy(nambuf, targ);
- exists = stat(nambuf, &stb) == 0;
- if (cmdbuf[0] == 'D') {
- if (exists) {
- if ((stb.st_mode&S_IFMT) != S_IFDIR) {
- errno = ENOTDIR;
- goto bad;
- }
- if (pflag)
- (void) chmod(nambuf, mode);
- } else if (mkdir(nambuf, mode) < 0)
- goto bad;
- myargv[0] = nambuf;
- sink(1, myargv);
- if (setimes) {
- setimes = 0;
- if (utime(nambuf, &utimbuf) < 0)
- error("rcp: can't set times on %s: %s\n",
- nambuf, strerror(errno));
- }
- continue;
- }
- if ((of = creat(nambuf, mode)) < 0) {
- bad:
- error("rcp: %s: %s\n", nambuf, strerror(errno));
- continue;
- }
- if (exists && pflag)
- (void) chmod(nambuf, mode);
- ga();
- if ((bp = allocbuf(&buffer, of, BUFSIZ)) == 0) {
- (void) close(of);
- continue;
- }
- cp = bp->buf;
- count = 0;
- wrerr = 0;
- for (i = 0; i < size; i += BUFSIZ) {
- amt = BUFSIZ;
- if (i + amt > size)
- amt = size - i;
- count += amt;
- do {
- j = read(rem, cp, amt);
- if (j <= 0)
- exit(1);
- amt -= j;
- cp += j;
- } while (amt > 0);
- if (count == bp->cnt) {
- if (wrerr == 0 &&
- write(of, bp->buf, count) != count)
- wrerr++;
- count = 0;
- cp = bp->buf;
- }
- }
- if (count != 0 && wrerr == 0 &&
- write(of, bp->buf, count) != count)
- wrerr++;
- (void) close(of);
- (void) response();
- if (setimes) {
- setimes = 0;
- if (utime(nambuf, &utimbuf) < 0)
- error("rcp: can't set times on %s: %s\n",
- nambuf, strerror(errno));
- }
- if (wrerr)
- error("rcp: %s: %s\n", nambuf, strerror(errno));
- else
- ga();
- }
-screwup:
- error("rcp: protocol screwup: %s\n", whopp);
- exit(1);
-}
-
-struct buffer *
-allocbuf(bp, fd, blksize)
- struct buffer *bp;
- int fd, blksize;
-{
- struct stat stb;
- int size;
-
- if (fstat(fd, &stb) < 0) {
- error("rcp: fstat: %s\n", strerror(errno));
- return ((struct buffer *)0);
- }
- size= 0;
-#if NOT_DEF
- size = roundup(stb.st_blksize, blksize);
-#endif
- if (size == 0)
- size = blksize;
- if (bp->cnt < size) {
- if (bp->buf != 0)
- free(bp->buf);
- bp->buf = (char *)malloc((unsigned) size);
- if (bp->buf == 0) {
- error("rcp: malloc: out of memory\n");
- return ((struct buffer *)0);
- }
- }
- bp->cnt = size;
- return (bp);
-}
-
-/*VARARGS1*/
-#if __STDC__
-void
-error (char *fmt, ...)
-#else
-error(fmt)
-char *fmt;
-#endif
-{
- char buf[BUFSIZ], *cp = buf;
- va_list ap;
-
- va_start(ap, fmt);
-
- errs++;
- *cp++ = 1;
- (void) vsprintf(cp, fmt, ap);
- va_end(ap);
- (void) write(rem, buf, strlen(buf));
- if (iamremote == 0)
- (void) write(2, buf+1, strlen(buf+1));
-}
-
-void
-usage()
-{
- fprintf(stderr, "Usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn d2\n");
-}
+++ /dev/null
-PROG= rsh
-MAN=
-
-.include <bsd.prog.mk>
+++ /dev/null
-/*-
- * 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
-#if 0
-static char sccsid[] = "@(#)rsh.c 5.24 (Berkeley) 7/1/91";
-#endif
-#endif /* not lint */
-
-/*
- * $Source$
- * $Header$
- */
-
-#if defined(__minix)
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <pwd.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <net/netlib.h>
-#include <netdb.h>
-int main( int argc, char *argv[] );
-void usage( void );
-char *copyargs( char **argv );
-void sendsig( int signo );
-void talk( int nflag, long omask, int pid, int rem );
-
-#define _PATH_RLOGIN1 "/bin/rlogin"
-#define _PATH_RLOGIN2 "/usr/bin/rlogin"
-
-#else
-#include <sys/types.h>
-#include <sys/signal.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/file.h>
-
-#include <netinet/in.h>
-#include <netdb.h>
-
-#include <pwd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <varargs.h>
-#include "pathnames.h"
-#endif
-
-#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;
-
-int
-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;
-#if !defined(__minix)
- char *copyargs();
- void sendsig();
-#endif
-
- 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_RLOGIN1, argv);
- execv(_PATH_RLOGIN2, argv);
- (void)fprintf(stderr, "rsh: can't exec rlogin\n");
- 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 !defined(__minix)
- 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));
- }
-#endif
-
- (void)setuid(uid);
-#if !defined(__minix)
- omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM));
-#endif
- 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
- {
-#if defined(__minix)
- ;
-#else
- (void)ioctl(rfd2, FIONBIO, &one);
- (void)ioctl(rem, FIONBIO, &one);
-#endif
- }
-
- talk(nflag, omask, pid, rem);
-
- if (!nflag && pid)
- {
-#if DEBUG
- printf("killing %d with %d\n", pid, SIGKILL);
-#endif
- (void)kill(pid, SIGKILL);
- }
- exit(0);
-}
-
-void
-talk(nflag, omask, pid, rem)
- int nflag, pid;
- long omask;
- register int rem;
-{
- register int cc, wc;
- register char *bp;
-#if !defined(__minix)
- int readfrom, ready, rembits;
-#endif
- char buf[BUFSIZ];
-#if defined(__minix)
- int pid1;
-#endif
-
- if (!nflag && pid == 0) {
- (void)close(rfd2);
-
-reread: errno = 0;
- if ((cc = read(0, buf, sizeof buf)) <= 0)
- goto done;
- bp = buf;
-
-rewrite:
-#if !defined(__minix)
- 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;
-#endif
-#ifdef KERBEROS
-#ifdef CRYPT
- if (doencrypt)
- wc = des_write(rem, bp, cc);
- else
-#endif
-#endif
- wc = write(rem, bp, cc);
- if (wc < 0) {
-#if !defined(__minix)
- if (errno == EWOULDBLOCK)
- goto rewrite;
-#endif
- goto done;
- }
- bp += wc;
- cc -= wc;
- if (cc == 0)
- goto reread;
- goto rewrite;
-done:
-#if defined(__minix)
- ioctl(rem, NWIOTCPSHUTDOWN, NULL);
-#else
- (void)shutdown(rem, 1);
-#endif
- exit(0);
- }
-
-#if defined(__minix)
- pid1= fork();
- if (pid1 == -1)
- {
- (void)fprintf(stderr, "rsh: fork: %s.\n", strerror(errno));
- exit(1);
- }
- close (pid1 ? rfd2 : rem);
- for(;;)
- {
- errno = 0;
- cc = read(pid1 ? rem : rfd2, buf, sizeof buf);
- if (cc <= 0)
- {
- if (pid1)
- {
-#if DEBUG
- printf("killing %d with %d\n", pid1, SIGKILL);
-#endif
- kill(pid1, SIGKILL);
- return;
- }
- exit(0);
- }
- (void)write(pid1 ? 1 : 2, buf, cc);
- }
-#else
- (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);
-#endif
-}
-
-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;
-#if !defined(__minix)
- char *malloc();
-#endif
-
- 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);
-}
-
-void
-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);
-}
+++ /dev/null
-PROG= in.rshd
-SRCS= rshd.c
-MAN=
-
-.include <bsd.prog.mk>
+++ /dev/null
-/*
-in.rshd.c
-*/
-
-/*
- main channel:
-
- back channel\0
- remuser\0
- locuser\0
- command\0
- data
-
- back channel:
- signal\0
-
-*/
-
-#include <sys/types.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <pwd.h>
-#include <grp.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <net/gen/in.h>
-#include <net/gen/inet.h>
-#include <netdb.h>
-#include <net/gen/socket.h>
-#include <net/gen/tcp.h>
-#include <net/gen/tcp_io.h>
-#include <net/hton.h>
-#include <net/netlib.h>
-
-#define DEBUG 0
-
-#if DEBUG
-#define where() fprintf(stderr, "%s, %d: ", __FILE__, __LINE__)
-#endif
-
-char cmdbuf[_POSIX_ARG_MAX+1], locuser[16], remuser[16];
-extern char **environ;
-char username[20]="USER=";
-char homedir[64]="HOME=";
-char shell[64]="SHELL=";
-char tz[1024]="TZ=";
-char *envinit[]= {homedir, shell, username, tz, "PATH=:/bin:/usr/bin", 0};
-char *prog_name;
-char buffer[PIPE_BUF];
-
-#if __STDC__
-#define PROTO(func, args) func args
-#else
-#define PROTO(func, args) func ()
-#endif
-
-PROTO (int main, (int argc, char *argv[]));
-PROTO (void getstr, (char*buf, int cnt, char *err));
-PROTO (void close_on_exec, (int fd));
-
-int main(argc, argv)
-int argc;
-char *argv[];
-{
- int result, result1;
- nwio_tcpconf_t tcpconf, err_tcpconf;
- nwio_tcpcl_t tcpconnopt;
- nwio_tcpatt_t tcpattachopt;
- tcpport_t tcpport;
- tcpport_t err_port;
- int err_fd, pds[2];
- pid_t pid, pid1, new_pg;
-#if USEATTACH
- int err2_fd;
-#endif
- struct passwd *pwent;
- char *cp, *buff_ptr, *TZ;
- char sig;
-
- prog_name= argv[0];
- if (argc != 1)
- {
- fprintf(stderr, "%s: wrong number of arguments (%d)\n",
- prog_name, argc);
- exit(1);
- }
-
- signal(SIGINT, SIG_DFL);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
-
-#if DEBUG
- { where(); fprintf(stderr, "\n"); }
-#endif
- result= ioctl (0, NWIOGTCPCONF, &tcpconf);
- if (result<0)
- {
- fprintf(stderr, "%s: ioctl(NWIOGTCPCONF)= %d : %s\n",
- prog_name, errno, strerror(errno));
- exit(1);
- }
-#if DEBUG
- { where(); fprintf(stderr, "\n"); }
-#endif
-
- tcpport= ntohs(tcpconf.nwtc_remport);
- if (tcpport >= TCPPORT_RESERVED || tcpport < TCPPORT_RESERVED/2)
- {
- printf("\1%s: unprotected port (%d)\n", prog_name, tcpport);
- exit(1);
- }
- alarm(60);
- err_port= 0;
- for (;;)
- {
- char c;
- result= read(0, &c, 1);
- if (result <0)
- {
- fprintf(stderr, "%s: read= %d : %s\n", prog_name,
- errno, strerror(errno));
- }
- if (result<1)
- exit(1);
- if (c == 0)
- break;
- err_port= err_port*10 + c - '0';
- }
- alarm(0);
- if (err_port != 0)
- {
- int n, pid, lport;
-
- pid= getpid();
- lport= 1;
- do {
- lport= (lport << 1) | (pid & 1);
- pid >>= 1;
- } while (lport < TCPPORT_RESERVED/2);
-
- n= TCPPORT_RESERVED/2;
- do
- {
- if (--lport < TCPPORT_RESERVED/2)
- lport= TCPPORT_RESERVED-1;
- err_fd= open ("/dev/tcp", O_RDWR);
- if (err_fd<0)
- {
- fprintf(stderr, "%s: open= %d : %s\n",
- prog_name, errno, strerror(errno));
- exit(1);
- }
- close_on_exec(err_fd);
- err_tcpconf.nwtc_flags= NWTC_LP_SET | NWTC_SET_RA |
- NWTC_SET_RP | NWTC_EXCL;
- err_tcpconf.nwtc_locport= htons(lport);
- err_tcpconf.nwtc_remport= htons(err_port);
- err_tcpconf.nwtc_remaddr= tcpconf.nwtc_remaddr;
-
-#if DEBUG
- { where(); fprintf(stderr, "\n"); }
-#endif
- result= ioctl (err_fd, NWIOSTCPCONF, &err_tcpconf);
- if (result == 0) break;
- if (errno != EADDRINUSE)
- {
- fprintf(stderr,
- "%s: ioctl(NWIOSTCPCONF)= %d : %s\n",
- prog_name, errno, strerror(errno));
- exit(1);
- }
- close(err_fd);
- } while (--n > 0);
- if (n == 0)
- {
- printf("\1can't get stderr port\n");
- exit(1);
- }
-
- err_tcpconf.nwtc_flags= NWTC_SHARED;
-#if DEBUG
-{ where(); fprintf(stderr, "\n"); }
-#endif
- result= ioctl (err_fd, NWIOSTCPCONF, &err_tcpconf);
- if (result<0)
- {
- fprintf(stderr,
- "%s: ioctl(NWIOSTCPCONF)= %d : %s\n",
- prog_name, errno, strerror(errno));
- exit(1);
- }
-#if DEBUG
-{ where(); fprintf(stderr, "\n"); }
-#endif
- tcpconnopt.nwtcl_flags= 0;
-
- n= 20;
- for (;;)
- {
-#if DEBUG
-{ where(); fprintf(stderr, "\n"); }
-#endif
- result= ioctl (err_fd, NWIOTCPCONN, &tcpconnopt);
- if (result == 0) break;
- if (errno != EAGAIN && errno != ECONNREFUSED)
- {
- fprintf(stderr,
- "%s: ioctl(NWIOTCPCONN)= %d : %s\n",
- prog_name, errno, strerror(errno));
- exit(1);
- }
- if (--n == 0) break;
- sleep(1);
-#if DEBUG
-{ where(); fprintf(stderr, "\n"); }
-#endif
- }
-#if USEATTACH
- err2_fd= open ("/dev/tcp", O_RDWR);
- close_on_exec(err2_fd);
- if (err2_fd<0)
- {
- fprintf(stderr, "%s: open= %d : %s\n", errno,
- prog_name, strerror(errno));
- exit(1);
- }
-#if DEBUG
- { where(); fprintf(stderr, "\n"); }
-#endif
- result= ioctl (err2_fd, NWIOSTCPCONF, &err_tcpconf);
- if (result<0)
- {
- fprintf(stderr, "%s: ioctl(NWIOSTCPCONF)= %d : %s\n",
- prog_name, errno, strerror(errno));
- exit(1);
- }
-#if DEBUG
- { where(); fprintf(stderr, "\n"); }
-#endif
- tcpattachopt.nwta_flags= 0;
-#if DEBUG
- { where(); fprintf(stderr, "\n"); }
-#endif
- result= ioctl (err2_fd, NWIOTCPATTACH, &tcpattachopt);
- if (result<0)
- {
- fprintf(stderr, "%s: ioctl(NWIOTCPATTACH)= %d : %s\n",
- prog_name, errno, strerror(errno));
- exit(1);
- }
-#if DEBUG
- { where(); fprintf(stderr, "\n"); }
-#endif
-#endif
- }
- getstr(remuser, sizeof(remuser), "remuser");
- getstr(locuser, sizeof(locuser), "locuser");
- getstr(cmdbuf, sizeof(cmdbuf), "cmdbuf");
- setpwent();
- pwent= getpwnam(locuser);
- if (!pwent)
- {
- printf("\1Login incorrect.\n");
- exit(1);
- }
- endpwent();
- if (chdir(pwent->pw_dir) < 0)
- {
- chdir("/");
- }
-#if DEBUG
- { where(); fprintf(stderr, "calling iruserok(%s, %d, %s, %s)\n",
- inet_ntoa(tcpconf.nwtc_remaddr), 0, remuser, locuser); }
-#endif
- if (iruserok(tcpconf.nwtc_remaddr, 0, remuser, locuser) < 0)
- {
- printf("\1Permission denied.\n");
- exit(1);
- }
- if (err_port)
- {
- /* Let's go to a different process group. */
- new_pg= setsid();
- pid= fork();
- if (pid<0)
- {
- if (errno != EAGAIN)
- {
- fprintf(stderr, "%s: fork()= %d : %s\n",
- prog_name, errno, strerror(errno));
- }
- printf("\1Try again.\n");
- exit(1);
- }
- if (pid)
- {
- close(0); /* stdin */
- close(1); /* stdout */
-#if USEATTACH
- close(err_fd); /* stderr for shell */
-#endif
- dup2(2,0);
- dup2(2,1);
- for (;;)
- {
-#if !USEATTACH
- if (read(err_fd, &sig, 1) <= 0)
-#else
- if (read(err2_fd, &sig, 1) <= 0)
-#endif
- {
-#if 0
- printf("read failed: %d\n", errno);
-#endif
- exit(0);
- }
- pid= 0;
-#if 0
- printf("killing %d with %d\n", -new_pg, sig);
-#endif
- kill(-new_pg, sig);
- }
- }
-#if USEATTACH
- close(err2_fd); /* signal channel for parent */
-#endif
- result= pipe(pds);
- if (result<0)
- {
- printf("\1Can't make pipe\n");
- kill(getppid(), SIGTERM);
- exit(1);
- }
- pid1= fork();
- if (pid1<0)
- {
- if (errno != EAGAIN)
- {
- fprintf(stderr, "%s: fork()= %d : %s\n",
- prog_name, errno, strerror(errno));
- }
- printf("\1Try again.\n");
- kill(-new_pg, SIGTERM);
- exit(1);
- }
- if (pid1)
- {
- close(pds[1]); /* write side of pipe */
- for (;;)
- {
- result= read(pds[0], buffer, sizeof(buffer));
- if (result<=0)
- {
- kill(pid, SIGTERM);
- exit(0);
- }
- buff_ptr= buffer;
- while (result>0)
- {
- result1= write (err_fd, buff_ptr,
- result);
- if (result1 <= 0)
- {
- fprintf(stderr,
- "%s: write()= %d : %s\n",
- prog_name, errno,
- strerror(errno));
- kill(-new_pg, SIGTERM);
- exit(1);
- }
- result -= result1;
- }
- }
- }
- close(err_fd); /* file descriptor for error channel */
- close (pds[0]); /* read side of pipe */
- dup2(pds[1], 2);
- close (pds[1]); /* write side of pipe */
- }
- if (*pwent->pw_shell == '\0')
- pwent->pw_shell= "/bin/sh";
-#if __minix_vmd
- initgroups(pwent->pw_name, pwent->pw_gid);
-#endif
- setgid(pwent->pw_gid);
- setuid(pwent->pw_uid);
- TZ=getenv("TZ");
- environ= envinit;
- strncat(homedir, pwent->pw_dir, sizeof(homedir)-6);
- strncat(shell, pwent->pw_shell, sizeof(shell)-7);
- strncat(username, pwent->pw_name, sizeof(username)-6);
- if (TZ)
- strncat(tz, TZ, sizeof(tz)-4);
- else
- envinit[3]= NULL;
-
- cp= strrchr(pwent->pw_shell, '/');
- if (cp)
- cp++;
- else
- cp= pwent->pw_shell;
-
- if (!err_port)
- dup2(1, 2);
- write(1, "\0", 1);
-
- execl(pwent->pw_shell, cp, "-c", cmdbuf, 0);
- close(2);
- open("/dev/tty", O_RDWR);
- fprintf(stderr, "%s: execl(%s, %s, .., %s)= %d : %s\n", prog_name,
- pwent->pw_shell, cp, cmdbuf, errno, strerror(errno));
- kill(getppid(), SIGTERM);
- exit(1);
-}
-
-void getstr(buf, cnt, err)
-char *buf;
-int cnt;
-char *err;
-{
- char c;
-
- do
- {
- if (read(0, &c, 1) != 1)
- exit(1);
- *buf++ = c;
- if (--cnt == 0)
- {
- printf("\1%s too long", err);
- exit(1);
- }
- } while (c != 0);
-}
-
-void close_on_exec(fd)
-int fd;
-{
- (void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
-}
sigprocmask(SIG_SETMASK, &oldmask, NULL);
dup2(client_fd, 0);
dup2(client_fd, 1);
+ dup2(client_fd, 2);
close(client_fd);
execvp(progv[0], progv);
report(progv[0]);
mixer.1 \
mkproto.1 mount.1 mt.1 \
playwave.1 prep.1 \
- profile.1 ps.1 rcp.1 recwave.1 \
- remsync.1 rget.1 rlogin.1 rsh.1 rz.1 \
+ profile.1 ps.1 recwave.1 \
+ remsync.1 rget.1 rlogin.1 rz.1 \
spell.1 svc.1 svrctl.1 \
synctree.1 sysenv.1 sz.1 telnet.1 template.1 \
term.1 termcap.1 tget.1 time.1 \
+++ /dev/null
-.\" Copyright (c) 1983 Regents of the University of California.
-.\" All rights reserved. The Berkeley software License Agreement
-.\" specifies the terms and conditions for redistribution.
-.\"
-.\" @(#)rcp.1c 6.4 (Berkeley) 5/12/86
-.\"
-.TH RCP 1 "May 12, 1986"
-.UC 5
-.SH NAME
-rcp \- remote file copy
-.SH SYNOPSIS
-.B rcp
-.RB [ \-p ]
-.I file1 file2
-.br
-.B rcp
-.RB [ \-pr ]
-.I file
-\&...
-.I directory
-.SH DESCRIPTION
-.B Rcp
-copies files between machines. Each
-.I file
-or
-.I directory
-argument is either a remote file name of the
-form ``rhost:path'', or a local file name (containing no `:' characters,
-or a `/' before any `:'s).
-.PP
-If the
-.B \-r
-option
-is specified and any of the source files are directories,
-.B rcp
-copies each subtree rooted at that name; in this case
-the destination must be a directory.
-.PP
-By default, the mode and owner of
-.I file2
-are preserved if it already existed; otherwise the mode of the source file
-modified by the
-.BR umask (2)
-on the destination host is used.
-The
-.B \-p
-option causes
-.B rcp
-to attempt to preserve (duplicate) in its copies the modification
-times and modes of the source files, ignoring the
-.BR umask .
-.PP
-If
-.I path
-is not a full path name, it is interpreted relative to
-your login directory on
-.IR rhost .
-A
-.I path
-on a remote host may be quoted (using \e, ", or \(aa)
-so that the metacharacters are interpreted remotely.
-.PP
-.B Rcp
-does not prompt for passwords; your current local user name
-must exist on
-.I rhost
-and allow remote command execution via
-.BR rsh (1).
-.PP
-.B Rcp
-handles third party copies, where neither source nor target files
-are on the current machine.
-Hostnames may also take the form ``rname@rhost'' to use
-.I rname
-rather than the current user name on the remote host.
-The destination hostname may also take the form ``rhost.rname'' to
-support destination machines that are running 4.2BSD
-versions of
-.BR rcp .
-.SH SEE ALSO
-.BR cp (1),
-.BR ftp (1),
-.BR rsh (1),
-.BR rlogin (1).
-.SH BUGS
-Doesn't detect all cases where the target of a copy might
-be a file in cases where only a directory should be legal.
-.br
-Is confused by any output generated by commands in a
-\&.profile, or \&.*shrc file on the remote host.
+++ /dev/null
-.\" Copyright (c) 1983 Regents of the University of California.
-.\" All rights reserved. The Berkeley software License Agreement
-.\" specifies the terms and conditions for redistribution.
-.\"
-.\" @(#)rsh.1c 6.1 (Berkeley) 4/29/85
-.\"
-.TH RSH 1 "April 29, 1985"
-.UC 5
-.SH NAME
-rsh \- remote shell
-.SH SYNOPSIS
-.B rsh
-.RB [ \-n ]
-.RB [ \-l
-.IR username ]
-.I host
-.RI [ command ]
-.br
-.I host
-.RB [ \-n ]
-.RB [ \-l
-.IR username ]
-.RI [ command ]
-.SH DESCRIPTION
-.B Rsh
-connects to the specified
-.IR host ,
-and executes the specified \fIcommand\fR.
-.B 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; \fBrsh\fP normally terminates when the remote command does.
-.PP
-The remote username used is the same as your local username,
-unless you specify a different remote name with the
-.B \-l
-option.
-This remote name must be equivalent (in the sense of
-.BR rlogin (1))
-to the originating account; no provision
-is made for specifying a password with a command.
-.PP
-If you omit
-.IR command ,
-then instead of executing a single command, you will be logged in
-on the remote host using
-.BR rlogin (1).
-.PP
-Shell metacharacters which are not quoted are interpreted
-on local machine, while quoted metacharacters are interpreted on
-the remote machine.
-Thus the command
-.PP
-.RS
-rsh otherhost cat remotefile >> localfile
-.RE
-.PP
-appends the remote file
-.I remotefile
-to the localfile
-.IR localfile ,
-while
-.PP
-.RS
-rsh otherhost cat remotefile ">>" otherremotefile
-.RE
-.PP
-appends
-.I remotefile
-to
-.IR otherremotefile .
-.SH OPTIONS
-.TP
-.BI \-l " username"
-Specify the remote user name.
-.TP
-.B \-n
-Connect standard input of the remote command to /dev/null. Do this if
-.B rsh
-should not inadvertently read from standard input.
-.SH SEE ALSO
-.BR rcp (1),
-.BR rlogin (1),
-.BR rhosts (5).
-.SH BUGS
-You cannot run an interactive command
-(like
-.BR rogue (6)
-or
-.BR vi (1));
-use
-.BR rlogin (1).
ossdevlinks.8 part.8 partition.8 \
printroot.8 pr_routes.8 pwdauth.8 rarpd.8 \
readclock.8 repartition.8 \
- rshd.8 screendump.8 serial-ip.8 \
+ screendump.8 serial-ip.8 \
setup.8 shutdown.8 slip.8 srccrc.8 tcpd.8 \
unix.8 update.8 usage.8 vbfs.8
+++ /dev/null
-.\" Copyright (c) 1983 Regents of the University of California.
-.\" All rights reserved. The Berkeley software License Agreement
-.\" specifies the terms and conditions for redistribution.
-.\"
-.\" @(#)rshd.8c 6.3 (Berkeley) 5/24/86
-.\"
-.TH RSHD 8 "May 24, 1986"
-.UC 5
-.SH NAME
-rshd \- remote shell server
-.SH SYNOPSIS
-.B "shell stream tcp nowait root /usr/sbin/in.rshd in.rshd"
-.br
-.B "tcpd shell /usr/sbin/in.rshd"
-.SH DESCRIPTION
-.B Rshd
-is the server for the
-.BR rcmd (3)
-routine and, consequently, for the
-.BR rsh (1)
-program. The server provides remote execution facilities
-with authentication based on privileged port numbers from trusted hosts.
-.PP
-.B Rshd
-listens for service requests at the port indicated in
-the ``cmd'' service specification; see
-.BR services (5).
-When a service request is received the following protocol
-is initiated:
-.IP 1)
-The server checks the client's source port.
-If the port is not in the range 0-1023, the server
-aborts the connection.
-.IP 2)
-The server reads characters from the socket up
-to a null (`\e0') byte. The resultant string is
-interpreted as an ASCII number, base 10.
-.IP 3)
-If the number received in step 1 is non-zero,
-it is interpreted as the port number of a secondary
-stream to be used for the
-.BR stderr .
-A second connection is then created to the specified
-port on the client's machine. The source port of this
-second connection is also in the range 0-1023.
-.IP 4)
-The server checks the client's source address
-and requests the corresponding host name (see
-.BR gethostbyaddr (3N),
-.BR hosts (5)
-and
-.BR named (8)).
-If the hostname cannot be determined,
-the dot-notation representation of the host address is used.
-.IP 5)
-A null terminated user name of at most 16 characters
-is retrieved on the initial socket. This user name
-is interpreted as the user identity on the
-.BR client 's
-machine.
-.IP 6)
-A null terminated user name of at most 16 characters
-is retrieved on the initial socket. This user name
-is interpreted as a user identity to use on the
-.BR server 's
-machine.
-.IP 7)
-A null terminated command to be passed to a
-shell is retrieved on the initial socket. The length of
-the command is limited by the upper bound on the size of
-the system's argument list.
-.IP 8)
-.B Rshd
-then validates the user according to the following steps.
-The local (server-end) user name is looked up in the password file
-and a
-.B chdir
-is performed to the user's home directory. If either
-the lookup or
-.B chdir
-fail, the connection is terminated.
-If the user is not the super-user, (user id 0), the file
-.B /etc/hosts.equiv
-is consulted for a list of hosts considered ``equivalent''.
-If the client's host name is present in this file, the
-authentication is considered successful. If the lookup
-fails, or the user is the super-user, then the file
-.B .rhosts
-in the home directory of the remote user is checked for
-the machine name and identity of the user on the client's
-machine. If this lookup fails, the connection is terminated.
-.IP 9)
-A null byte is returned on the initial socket
-and the command line is passed to the normal login
-shell of the user. The
-shell inherits the network connections established
-by
-.IR rshd .
-.SH DIAGNOSTICS
-Except for the last one listed below,
-all diagnostic messages
-are returned on the initial socket,
-after which any network connections are closed.
-An error is indicated by a leading byte with a value of
-1 (0 is returned in step 9 above upon successful completion
-of all the steps prior to the execution of the login shell).
-.PP
-.B ``locuser too long''
-.br
-The name of the user on the client's machine is
-longer than 16 characters.
-.PP
-.B ``remuser too long''
-.br
-The name of the user on the remote machine is
-longer than 16 characters.
-.PP
-.B ``command too long ''
-.br
-The command line passed exceeds the size of the argument
-list (as configured into the system).
-.PP
-.B ``Login incorrect.''
-.br
-No password file entry for the user name existed.
-.PP
-.B ``No remote directory.''
-.br
-The
-.B chdir
-command to the home directory failed.
-.PP
-.B ``Permission denied.''
-.br
-The authentication procedure described above failed.
-.PP
-.B ``Can't make pipe.''
-.br
-The pipe needed for the
-.BR stderr ,
-wasn't created.
-.PP
-.B ``Try again.''
-.br
-A
-.B fork
-by the server failed.
-.PP
-.B ``<shellname>: ...''
-.br
-The user's login shell could not be started. This message is returned
-on the connection associated with the
-.BR stderr ,
-and is not preceded by a flag byte.
-.SH SEE ALSO
-.BR rsh (1),
-.BR rcmd (3).
-.SH BUGS
-The authentication procedure used here assumes the integrity
-of each client machine and the connecting medium. This is
-insecure, but is useful in an ``open'' environment.
-.PP
-A facility to allow all data exchanges to be encrypted should be
-present.
-.PP
-A more extensible protocol should be used.
nbperf newgrp nice nl nohup \
passwd paste patch pathchk pr \
printenv printf pwhash \
- renice rev \
+ renice rev rsh \
\
sdiff sed seq shar shlock \
shuffle sort split stat su \
--- /dev/null
+# $NetBSD: Makefile,v 1.20 2009/04/14 22:15:25 lukem Exp $
+# from: @(#)Makefile 8.1 (Berkeley) 7/19/93
+
+.include <bsd.own.mk>
+
+USE_FORT?=yes # network client
+
+PROG= rsh
+SRCS= rsh.c getport.c
+
+.PATH: ${NETBSDSRCDIR}/usr.bin/rlogin
+
+.include <bsd.prog.mk>
--- /dev/null
+/* $NetBSD: getport.c,v 1.2 2008/04/28 20:24:14 martin Exp $ */
+
+/*-
+ * Copyright (c) 2004 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: getport.c,v 1.2 2008/04/28 20:24:14 martin Exp $");
+
+#include <stdlib.h>
+#include <err.h>
+#include <netdb.h>
+#include <limits.h>
+#include <errno.h>
+#include <netinet/in.h>
+
+#include "getport.h"
+
+struct servent *
+getport(const char *service, const char *protocol)
+{
+ long port;
+ char *ep;
+ struct servent *sp = getservbyname(service, protocol);
+ if (sp != NULL)
+ return sp;
+
+ if ((sp = calloc(1, sizeof(*sp))) == NULL)
+ err(1, "malloc");
+ sp->s_name = __UNCONST(service);
+ sp->s_proto = __UNCONST(protocol);
+ port = strtol(service, &ep, 0);
+ if ((service[0] != '\0' && *ep != '\0') ||
+ (errno == ERANGE &&
+ (port == LONG_MAX || port == LONG_MIN)) ||
+ (port <= 0 || port >= IPPORT_ANONMAX))
+ errx(1,"port must be between 1 and %d",
+ IPPORT_ANONMAX);
+ sp->s_port = htons((uint16_t)port);
+ return sp;
+}
--- /dev/null
+/*-
+ * Copyright (c) 2004 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+extern struct servent *getport(const char *, const char *);
--- /dev/null
+/* $NetBSD: pathnames.h,v 1.5 2003/08/07 11:15:43 agc Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993
+ * 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. 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 8.1 (Berkeley) 6/6/93
+ * $NetBSD: pathnames.h,v 1.5 2003/08/07 11:15:43 agc Exp $
+ */
+
+#define _PATH_RLOGIN "/usr/bin/rlogin"
--- /dev/null
+.\" $NetBSD: rsh.1,v 1.20 2005/03/11 02:45:24 ginsbach Exp $
+.\"
+.\" Copyright (c) 1983, 1990, 1993
+.\" 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. 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.
+.\"
+.\" @(#)rsh.1 8.2 (Berkeley) 4/29/95
+.\"
+.Dd March 9, 2005
+.Dt RSH 1
+.Os
+.Sh NAME
+.Nm rsh
+.Nd remote shell
+.Sh SYNOPSIS
+.Nm
+.Op Fl 46dn
+.Op Fl l Ar username
+.Op Fl p Ar port
+.Ar host
+.Op command
+.Nm
+.Op Fl 46dn
+.Op Fl p Ar port
+.Ar username@host
+.Op command
+.Sh DESCRIPTION
+.Nm
+executes
+.Ar command
+on
+.Ar host .
+.Pp
+.Nm
+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
+normally terminates when the remote command does.
+The options are as follows:
+.Bl -tag -width XlXusernameX
+.It Fl 4
+Use IPv4 addresses only.
+.It Fl 6
+Use IPv6 addresses only.
+.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 l Ar username
+By default, the remote username is the same as the local username.
+The
+.Fl l
+option or the
+.Ar username@host
+format allow the remote name to be specified.
+.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 p Ar port
+Uses the given
+.Pa port
+instead of the one assigned to the service
+.Dq shell .
+May be given either as symbolic name or as number.
+If no command is given, note that
+.Xr rlogin 1
+is started, which may need a different daemon
+.No ( Xr rlogind 8
+instead of
+.Xr rshd 8 )
+running on the server; you want to pass the
+.Xr rshd 8
+port number in that case.
+.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 \*[Gt]\*[Gt] localfile
+.Pp
+appends the remote file
+.Ar remotefile
+to the local file
+.Ar localfile ,
+while
+.Pp
+.Dl rsh otherhost cat remotefile \&"\*[Gt]\*[Gt]\&" 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
+.\" .Pa /usr/hosts .
+.\" If this directory is included in your search path, you can use the
+.\" shorthand
+.\" .Dq host command
+.\" for the longer form
+.\" .Dq rsh host command .
+.Sh FILES
+.Bl -tag -width /etc/hosts -compact
+.It Pa /etc/hosts
+.El
+.Sh SEE ALSO
+.Xr rcmd 1 ,
+.Xr rlogin 1 ,
+.Xr rcmd 3 ,
+.Xr hosts.equiv 5 ,
+.Xr rhosts 5 ,
+.Xr environ 7
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
+.Sh BUGS
+If you are using
+.Xr csh 1
+and put a
+.Nm
+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
+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 ;
+use
+.Xr rlogin 1
+instead.
+.Pp
+Stop signals stop the local
+.Nm
+process only; this is arguably wrong, but currently hard to fix for reasons
+too complicated to explain here.
--- /dev/null
+/* $NetBSD: rsh.c,v 1.33 2011/08/29 14:22:46 joerg Exp $ */
+
+/*-
+ * Copyright (c) 1983, 1990, 1993, 1994
+ * 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. 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.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1983, 1990, 1993, 1994\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)rsh.c 8.4 (Berkeley) 4/29/95";
+#else
+__RCSID("$NetBSD: rsh.c,v 1.33 2011/08/29 14:22:46 joerg Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <poll.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pathnames.h"
+#include "getport.h"
+
+
+/*
+ * rsh - remote shell
+ */
+int remerr;
+
+static int sigs[] = { SIGINT, SIGTERM, SIGQUIT };
+
+static char *copyargs(char **);
+static void sendsig(int);
+static int checkfd(struct pollfd *, int);
+static void talk(int, sigset_t *, pid_t, int);
+__dead static void usage(void);
+#ifdef IN_RCMD
+int orcmd(char **, int, const char *,
+ const char *, const char *, int *);
+int orcmd_af(char **, int, const char *,
+ const char *, const char *, int *, int);
+#endif
+
+int
+main(int argc, char **argv)
+{
+ struct passwd *pw;
+ struct servent *sp;
+ sigset_t oset, nset;
+ struct protoent *proto;
+
+#ifdef IN_RCMD
+ char *locuser = 0, *loop;
+#endif /* IN_RCMD */
+ int argoff, asrsh, ch, dflag, nflag, one, rem;
+ size_t i;
+ int family = AF_UNSPEC;
+ pid_t pid;
+ uid_t uid;
+ char *args, *host, *p, *user, *name;
+
+ argoff = asrsh = dflag = nflag = 0;
+ one = 1;
+ host = user = NULL;
+ sp = NULL;
+
+#ifndef IN_RCMD
+ /*
+ * If called as something other than "rsh" use it as the host name,
+ * only for rsh.
+ */
+ if (strcmp(getprogname(), "rsh") == 0)
+ asrsh = 1;
+ else {
+ host = strdup(getprogname());
+ if (host == NULL)
+ err(1, NULL);
+ }
+#endif /* IN_RCMD */
+
+ /* handle "rsh host flags" */
+ if (!host && argc > 2 && argv[1][0] != '-') {
+ host = argv[1];
+ argoff = 1;
+ }
+
+#ifdef IN_RCMD
+ if ((loop = getenv("RCMD_LOOP")) && strcmp(loop, "YES") == 0)
+ warnx("rcmd appears to be looping!");
+
+ setenv("RCMD_LOOP", "YES", 1);
+
+# define OPTIONS "468KLdel:np:u:w"
+
+#else /* IN_RCMD */
+
+# define OPTIONS "468KLdel:np:w"
+
+#endif /* IN_RCMD */
+
+ if (!(pw = getpwuid(uid = getuid())))
+ errx(1, "unknown user id");
+
+ if ((name = strdup(pw->pw_name)) == NULL)
+ err(1, "malloc");
+ while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != -1)
+ switch(ch) {
+ case '4':
+ family = AF_INET;
+ break;
+ case '6':
+ family = AF_INET6;
+ break;
+ case 'K':
+ 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;
+ case 'n':
+ nflag = 1;
+ break;
+ case 'p':
+ sp = getport(optarg, "tcp");
+ break;
+#ifdef IN_RCMD
+ case 'u':
+ if (getuid() != 0 && optarg && name &&
+ strcmp(name, optarg) != 0)
+ errx(1,"only super user can use the -u option");
+ locuser = optarg;
+ break;
+#endif /* IN_RCMD */
+ 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]) {
+#ifdef IN_RCMD
+ usage();
+#else
+ if (asrsh)
+ *argv = __UNCONST("rlogin");
+ execv(_PATH_RLOGIN, argv);
+ err(1, "can't exec %s", _PATH_RLOGIN);
+#endif
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ /* Accept user1@host format, though "-l user2" overrides user1 */
+ p = strchr(host, '@');
+ if (p) {
+ *p = '\0';
+ if (!user && p > host)
+ user = host;
+ host = p + 1;
+ if (*host == '\0')
+ usage();
+ }
+ if (!user)
+ user = name;
+
+
+ args = copyargs(argv);
+
+ if (sp == NULL)
+ sp = getservbyname("shell", "tcp");
+ if (sp == NULL)
+ errx(1, "shell/tcp: unknown service");
+
+
+#ifdef IN_RCMD
+ rem = orcmd_af(&host, sp->s_port, locuser ? locuser :
+#else
+ rem = rcmd_af(&host, sp->s_port,
+#endif
+ name, user, args, &remerr, family);
+ (void)free(name);
+
+ if (rem < 0)
+ exit(1);
+
+ if (remerr < 0)
+ errx(1, "can't establish stderr");
+ if (dflag) {
+ if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one,
+ sizeof(one)) < 0)
+ warn("setsockopt remote");
+ if (setsockopt(remerr, SOL_SOCKET, SO_DEBUG, &one,
+ sizeof(one)) < 0)
+ warn("setsockopt stderr");
+ }
+ proto = getprotobyname("tcp");
+ setsockopt(rem, proto->p_proto, TCP_NODELAY, &one, sizeof(one));
+ setsockopt(remerr, proto->p_proto, TCP_NODELAY, &one, sizeof(one));
+
+
+ (void)setuid(uid);
+
+ (void)sigemptyset(&nset);
+ for (i = 0; i < sizeof(sigs) / sizeof(sigs[0]); i++)
+ (void)sigaddset(&nset, sigs[i]);
+
+ (void)sigprocmask(SIG_BLOCK, &nset, &oset);
+
+ for (i = 0; i < sizeof(sigs) / sizeof(sigs[0]); i++) {
+ struct sigaction sa;
+
+ if (sa.sa_handler != SIG_IGN) {
+ sa.sa_handler = sendsig;
+ (void)sigaction(sigs[i], &sa, NULL);
+ }
+ }
+
+ if (!nflag) {
+ pid = fork();
+ if (pid < 0)
+ err(1, "fork");
+ }
+ else
+ pid = -1;
+
+#if defined(KERBEROS) && defined(CRYPT)
+ if (!doencrypt)
+#endif
+ {
+ (void)ioctl(remerr, FIONBIO, &one);
+ (void)ioctl(rem, FIONBIO, &one);
+ }
+
+ talk(nflag, &oset, pid, rem);
+
+ if (!nflag)
+ (void)kill(pid, SIGKILL);
+ exit(0);
+}
+
+static int
+checkfd(struct pollfd *fdp, int outfd)
+{
+ int nr, nw;
+ char buf[BUFSIZ];
+
+ if (fdp->revents & (POLLNVAL|POLLERR|POLLHUP))
+ return -1;
+
+ if ((fdp->revents & POLLIN) == 0)
+ return 0;
+
+ errno = 0;
+#if defined(KERBEROS) && defined(CRYPT)
+ if (doencrypt)
+ nr = des_read(fdp->fd, buf, sizeof buf);
+ else
+#endif
+ nr = read(fdp->fd, buf, sizeof buf);
+
+ if (nr <= 0) {
+ if (errno != EAGAIN)
+ return -1;
+ else
+ return 0;
+ }
+ else {
+ char *bc = buf;
+ while (nr) {
+ if ((nw = write(outfd, bc, nr)) <= 0)
+ return -1;
+ nr -= nw;
+ bc += nw;
+ }
+ return 0;
+ }
+}
+
+static void
+talk(int nflag, sigset_t *oset, __pid_t pid, int rem)
+{
+ int nr, nw, nfds;
+ struct pollfd fds[2], *fdp = &fds[0];
+ char *bp, buf[BUFSIZ];
+
+ if (!nflag && pid == 0) {
+ (void)close(remerr);
+
+ fdp->events = POLLOUT|POLLNVAL|POLLERR|POLLHUP;
+ fdp->fd = rem;
+ nr = 0;
+ bp = buf;
+
+ for (;;) {
+ errno = 0;
+
+ if (nr == 0) {
+ if ((nr = read(0, buf, sizeof buf)) == 0)
+ goto done;
+ if (nr == -1) {
+ if (errno == EIO)
+ goto done;
+ if (errno == EINTR) {
+ nr = 0;
+ continue;
+ }
+ err(1, "read");
+ }
+ bp = buf;
+ }
+
+rewrite: if (poll(fdp, 1, INFTIM) == -1) {
+ if (errno != EINTR)
+ err(1, "poll");
+ goto rewrite;
+ }
+
+ if (fdp->revents & (POLLNVAL|POLLERR|POLLHUP))
+ err(1, "poll");
+
+ if ((fdp->revents & POLLOUT) == 0)
+ goto rewrite;
+
+#if defined(KERBEROS) && defined(CRYPT)
+ if (doencrypt)
+ nw = des_write(rem, bp, nr);
+ else
+#endif
+ nw = write(rem, bp, nr);
+
+ if (nw < 0) {
+ if (errno == EAGAIN)
+ continue;
+ err(1, "write");
+ }
+ bp += nw;
+ nr -= nw;
+ }
+done:
+ (void)shutdown(rem, 1);
+ exit(0);
+ }
+
+ (void)sigprocmask(SIG_SETMASK, oset, NULL);
+ fds[0].events = fds[1].events = POLLIN|POLLNVAL|POLLERR|POLLHUP;
+ fds[0].fd = remerr;
+ fds[1].fd = rem;
+ fdp = &fds[0];
+ nfds = 2;
+ do {
+ if (poll(fdp, nfds, INFTIM) == -1) {
+ if (errno != EINTR)
+ err(1, "poll");
+ continue;
+ }
+ if (fds[0].events != 0 && checkfd(&fds[0], 2) == -1) {
+ nfds--;
+ fds[0].events = 0;
+ fdp = &fds[1];
+ }
+ if (fds[1].events != 0 && checkfd(&fds[1], 1) == -1) {
+ nfds--;
+ fds[1].events = 0;
+ }
+ }
+ while (nfds);
+}
+
+static void
+sendsig(int sig)
+{
+ char signo;
+
+ signo = sig;
+ (void)write(remerr, &signo, 1);
+}
+
+
+static char *
+copyargs(char **argv)
+{
+ int cc;
+ char **ap, *args, *p, *ep;
+
+ cc = 0;
+ for (ap = argv; *ap; ++ap)
+ cc += strlen(*ap) + 1;
+ if (!(args = malloc((u_int)cc)))
+ err(1, "malloc");
+ ep = args + cc;
+ for (p = args, *p = '\0', ap = argv; *ap; ++ap) {
+ (void)strlcpy(p, *ap, ep - p);
+ p += strlen(p);
+ if (ap[1])
+ *p++ = ' ';
+ }
+ *p = '\0';
+ return (args);
+}
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr,
+ "usage: %s [-46dn] [-l login] [-p port]%s [login@]host command\n",
+ getprogname(),
+#ifdef IN_RCMD
+ " [-u locuser]"
+#else
+ ""
+#endif
+ );
+ exit(1);
+}