1 /* $NetBSD: rsh.c,v 1.38 2014/11/26 23:44:21 enami Exp $ */
4 * Copyright (c) 1983, 1990, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
34 __COPYRIGHT("@(#) Copyright (c) 1983, 1990, 1993, 1994\
35 The Regents of the University of California. All rights reserved.");
40 static char sccsid
[] = "@(#)rsh.c 8.4 (Berkeley) 4/29/95";
42 __RCSID("$NetBSD: rsh.c,v 1.38 2014/11/26 23:44:21 enami Exp $");
46 #include <sys/types.h>
47 #include <sys/socket.h>
48 #include <sys/ioctl.h>
52 #include <netinet/in.h>
53 #include <netinet/tcp.h>
67 #include "pathnames.h"
76 static int sigs
[] = { SIGINT
, SIGTERM
, SIGQUIT
};
78 static char *copyargs(char **);
79 static void sendsig(int);
80 static int checkfd(struct pollfd
*, int);
81 static void talk(int, sigset_t
*, pid_t
, int);
82 __dead
static void usage(void);
84 int orcmd(char **, int, const char *,
85 const char *, const char *, int *);
86 int orcmd_af(char **, int, const char *,
87 const char *, const char *, int *, int);
88 static int relay_signal
;
92 main(int argc
, char **argv
)
97 struct protoent
*proto
;
100 char *locuser
= 0, *loop
, *relay
;
102 int argoff
, asrsh
, ch
, dflag
, nflag
, one
, rem
;
104 int family
= AF_UNSPEC
;
107 char *args
, *host
, *p
, *user
, *name
;
109 argoff
= asrsh
= dflag
= nflag
= 0;
116 * If called as something other than "rsh" use it as the host name,
119 if (strcmp(getprogname(), "rsh") == 0)
122 host
= strdup(getprogname());
128 /* handle "rsh host flags" */
129 if (!host
&& argc
> 2 && argv
[1][0] != '-') {
135 if ((relay
= getenv("RCMD_RELAY_SIGNAL")) && strcmp(relay
, "YES") == 0)
137 if ((loop
= getenv("RCMD_LOOP")) && strcmp(loop
, "YES") == 0)
138 warnx("rcmd appears to be looping!");
140 setenv("RCMD_LOOP", "YES", 1);
142 # define OPTIONS "468KLdel:np:u:w"
146 # define OPTIONS "468KLdel:np:w"
150 if (!(pw
= getpwuid(uid
= getuid())))
151 errx(1, "unknown user id");
153 if ((name
= strdup(pw
->pw_name
)) == NULL
)
155 while ((ch
= getopt(argc
- argoff
, argv
+ argoff
, OPTIONS
)) != -1)
165 case 'L': /* -8Lew are ignored to allow rlogin aliases */
180 sp
= getport(optarg
, "tcp");
184 if (getuid() != 0 && optarg
&& name
&&
185 strcmp(name
, optarg
) != 0)
186 errx(1,"only super user can use the -u option");
196 /* if haven't gotten a host yet, do so */
197 if (!host
&& !(host
= argv
[optind
++]))
200 /* if no further arguments, must have been called as rlogin. */
206 *argv
= __UNCONST("rlogin");
208 execv(_PATH_RLOGIN
, argv
);
209 err(1, "can't exec %s", _PATH_RLOGIN
);
216 /* Accept user1@host format, though "-l user2" overrides user1 */
217 p
= strchr(host
, '@');
220 if (!user
&& p
> host
)
230 args
= copyargs(argv
);
233 sp
= getservbyname("shell", "tcp");
235 errx(1, "shell/tcp: unknown service");
239 rem
= orcmd_af(&host
, sp
->s_port
, locuser
? locuser
:
241 rem
= rcmd_af(&host
, sp
->s_port
,
243 name
, user
, args
, &remerr
, family
);
250 errx(1, "can't establish stderr");
252 if (setsockopt(rem
, SOL_SOCKET
, SO_DEBUG
, &one
,
254 warn("setsockopt remote");
255 if (setsockopt(remerr
, SOL_SOCKET
, SO_DEBUG
, &one
,
257 warn("setsockopt stderr");
259 proto
= getprotobyname("tcp");
260 setsockopt(rem
, proto
->p_proto
, TCP_NODELAY
, &one
, sizeof(one
));
261 setsockopt(remerr
, proto
->p_proto
, TCP_NODELAY
, &one
, sizeof(one
));
266 (void)sigemptyset(&nset
);
267 for (i
= 0; i
< sizeof(sigs
) / sizeof(sigs
[0]); i
++)
268 (void)sigaddset(&nset
, sigs
[i
]);
270 (void)sigprocmask(SIG_BLOCK
, &nset
, &oset
);
275 for (i
= 0; i
< sizeof(sigs
) / sizeof(sigs
[0]); i
++) {
278 if (sa
.sa_handler
!= SIG_IGN
) {
279 sa
.sa_handler
= sendsig
;
280 (void)sigaction(sigs
[i
], &sa
, NULL
);
292 (void)ioctl(remerr
, FIONBIO
, &one
);
293 (void)ioctl(rem
, FIONBIO
, &one
);
295 talk(nflag
, &oset
, pid
, rem
);
298 (void)kill(pid
, SIGKILL
);
303 checkfd(struct pollfd
*fdp
, int outfd
)
308 if (fdp
->revents
& (POLLNVAL
|POLLERR
|POLLHUP
))
311 if ((fdp
->revents
& POLLIN
) == 0)
315 nr
= read(fdp
->fd
, buf
, sizeof buf
);
326 if ((nw
= write(outfd
, bc
, nr
)) <= 0)
336 talk(int nflag
, sigset_t
*oset
, __pid_t pid
, int rem
)
339 struct pollfd fds
[3], *fdp
= &fds
[0];
340 char *bp
, buf
[BUFSIZ
];
342 if (!nflag
&& pid
== 0) {
345 fdp
->events
= POLLOUT
|POLLNVAL
|POLLERR
|POLLHUP
;
354 if ((nr
= read(0, buf
, sizeof buf
)) == 0)
359 if (errno
== EINTR
) {
368 rewrite
: if (poll(fdp
, 1, INFTIM
) == -1) {
374 if (fdp
->revents
& (POLLNVAL
|POLLERR
|POLLHUP
))
377 if ((fdp
->revents
& POLLOUT
) == 0)
380 nw
= write(rem
, bp
, nr
);
391 (void)shutdown(rem
, 1);
402 fds
[0].events
= POLLIN
|POLLNVAL
|POLLERR
|POLLHUP
;
406 (void)sigprocmask(SIG_SETMASK
, oset
, NULL
);
407 fds
[1].events
= fds
[2].events
= POLLIN
|POLLNVAL
|POLLERR
|POLLHUP
;
411 if (poll(fdp
, nfds
, INFTIM
) == -1) {
416 if ((fds
[1].events
!= 0 && checkfd(&fds
[1], 2) == -1)
418 || (fds
[0].events
!= 0 && checkfd(&fds
[0], remerr
) == -1)
431 if (fds
[2].events
!= 0 && checkfd(&fds
[2], 1) == -1) {
445 (void)write(remerr
, &signo
, 1);
449 copyargs(char **argv
)
452 char **ap
, *args
, *p
, *ep
;
455 for (ap
= argv
; *ap
; ++ap
)
456 cc
+= strlen(*ap
) + 1;
457 if (!(args
= malloc((u_int
)cc
)))
460 for (p
= args
, *p
= '\0', ap
= argv
; *ap
; ++ap
) {
461 (void)strlcpy(p
, *ap
, ep
- p
);
474 (void)fprintf(stderr
,
475 "usage: %s [-46dn] [-l login] [-p port]%s [login@]host command\n",