1 /* $NetBSD: rsh.c,v 1.30 2008/07/21 14:19:25 lukem 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.30 2008/07/21 14:19:25 lukem 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 char *copyargs(char **);
80 int checkfd(struct pollfd
*, int);
81 void talk(int, sigset_t
*, pid_t
, int);
83 int main(int, char **);
85 int orcmd(char **, int, const char *,
86 const char *, const char *, int *);
87 int orcmd_af(char **, int, const char *,
88 const char *, const char *, int *, int);
92 main(int argc
, char **argv
)
97 struct protoent
*proto
;
100 char *locuser
= 0, *loop
;
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 ((loop
= getenv("RCMD_LOOP")) && strcmp(loop
, "YES") == 0)
136 warnx("rcmd appears to be looping!");
138 putenv("RCMD_LOOP=YES");
140 # define OPTIONS "468KLdel:np:u:w"
144 # define OPTIONS "468KLdel:np:w"
148 if (!(pw
= getpwuid(uid
= getuid())))
149 errx(1, "unknown user id");
151 if ((name
= strdup(pw
->pw_name
)) == NULL
)
153 while ((ch
= getopt(argc
- argoff
, argv
+ argoff
, OPTIONS
)) != -1)
163 case 'L': /* -8Lew are ignored to allow rlogin aliases */
178 sp
= getport(optarg
, "tcp");
182 if (getuid() != 0 && optarg
&& name
&&
183 strcmp(name
, optarg
) != 0)
184 errx(1,"only super user can use the -u option");
194 /* if haven't gotten a host yet, do so */
195 if (!host
&& !(host
= argv
[optind
++]))
198 /* if no further arguments, must have been called as rlogin. */
204 *argv
= __UNCONST("rlogin");
205 execv(_PATH_RLOGIN
, argv
);
206 err(1, "can't exec %s", _PATH_RLOGIN
);
213 /* Accept user1@host format, though "-l user2" overrides user1 */
214 p
= strchr(host
, '@');
217 if (!user
&& p
> host
)
227 args
= copyargs(argv
);
230 sp
= getservbyname("shell", "tcp");
232 errx(1, "shell/tcp: unknown service");
236 rem
= orcmd_af(&host
, sp
->s_port
, locuser
? locuser
:
238 rem
= rcmd_af(&host
, sp
->s_port
,
240 name
, user
, args
, &remerr
, family
);
247 errx(1, "can't establish stderr");
249 if (setsockopt(rem
, SOL_SOCKET
, SO_DEBUG
, &one
,
251 warn("setsockopt remote");
252 if (setsockopt(remerr
, SOL_SOCKET
, SO_DEBUG
, &one
,
254 warn("setsockopt stderr");
256 proto
= getprotobyname("tcp");
257 setsockopt(rem
, proto
->p_proto
, TCP_NODELAY
, &one
, sizeof(one
));
258 setsockopt(remerr
, proto
->p_proto
, TCP_NODELAY
, &one
, sizeof(one
));
263 (void)sigemptyset(&nset
);
264 for (i
= 0; i
< sizeof(sigs
) / sizeof(sigs
[0]); i
++)
265 (void)sigaddset(&nset
, sigs
[i
]);
267 (void)sigprocmask(SIG_BLOCK
, &nset
, &oset
);
269 for (i
= 0; i
< sizeof(sigs
) / sizeof(sigs
[0]); i
++) {
272 if (sa
.sa_handler
!= SIG_IGN
) {
273 sa
.sa_handler
= sendsig
;
274 (void)sigaction(sigs
[i
], &sa
, NULL
);
286 #if defined(KERBEROS) && defined(CRYPT)
290 (void)ioctl(remerr
, FIONBIO
, &one
);
291 (void)ioctl(rem
, FIONBIO
, &one
);
294 talk(nflag
, &oset
, pid
, rem
);
297 (void)kill(pid
, SIGKILL
);
302 checkfd(struct pollfd
*fdp
, int outfd
)
307 if (fdp
->revents
& (POLLNVAL
|POLLERR
|POLLHUP
))
310 if ((fdp
->revents
& POLLIN
) == 0)
314 #if defined(KERBEROS) && defined(CRYPT)
316 nr
= des_read(fdp
->fd
, buf
, sizeof buf
);
319 nr
= read(fdp
->fd
, buf
, sizeof buf
);
330 if ((nw
= write(outfd
, bc
, nr
)) <= 0)
340 talk(int nflag
, sigset_t
*oset
, __pid_t pid
, int rem
)
343 struct pollfd fds
[2], *fdp
= &fds
[0];
344 char *bp
, buf
[BUFSIZ
];
346 if (!nflag
&& pid
== 0) {
349 fdp
->events
= POLLOUT
|POLLNVAL
|POLLERR
|POLLHUP
;
358 if ((nr
= read(0, buf
, sizeof buf
)) == 0)
363 if (errno
== EINTR
) {
372 rewrite
: if (poll(fdp
, 1, INFTIM
) == -1) {
378 if (fdp
->revents
& (POLLNVAL
|POLLERR
|POLLHUP
))
381 if ((fdp
->revents
& POLLOUT
) == 0)
384 #if defined(KERBEROS) && defined(CRYPT)
386 nw
= des_write(rem
, bp
, nr
);
389 nw
= write(rem
, bp
, nr
);
400 (void)shutdown(rem
, 1);
404 (void)sigprocmask(SIG_SETMASK
, oset
, NULL
);
405 fds
[0].events
= fds
[1].events
= POLLIN
|POLLNVAL
|POLLERR
|POLLHUP
;
411 if (poll(fdp
, nfds
, INFTIM
) == -1) {
416 if (fds
[0].events
!= 0 && checkfd(&fds
[0], 2) == -1) {
421 if (fds
[1].events
!= 0 && checkfd(&fds
[1], 1) == -1) {
435 (void)write(remerr
, &signo
, 1);
440 copyargs(char **argv
)
443 char **ap
, *args
, *p
, *ep
;
446 for (ap
= argv
; *ap
; ++ap
)
447 cc
+= strlen(*ap
) + 1;
448 if (!(args
= malloc((u_int
)cc
)))
451 for (p
= args
, *p
= '\0', ap
= argv
; *ap
; ++ap
) {
452 (void)strlcpy(p
, *ap
, ep
- p
);
465 (void)fprintf(stderr
,
466 "usage: %s [-46dn] [-l login] [-p port]%s [login@]host command\n",