xref: /original-bsd/usr.bin/rsh/rsh.c (revision f0fd5f8a)
1 #ifndef lint
2 static char sccsid[] = "@(#)rsh.c	4.2 82/11/14";
3 #endif
4 
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <sys/ioctl.h>
8 #include <sys/file.h>
9 
10 #include <netinet/in.h>
11 
12 #include <stdio.h>
13 #include <errno.h>
14 #include <signal.h>
15 #include <pwd.h>
16 
17 /*
18  * rsh - remote shell
19  */
20 /* VARARGS */
21 int	error();
22 char	*index(), *rindex(), *malloc(), *getpass(), *sprintf(), *strcpy();
23 
24 struct	passwd *getpwuid();
25 
26 int	errno;
27 int	options;
28 int	rfd2;
29 int	sendsig();
30 
31 main(argc, argv0)
32 	int argc;
33 	char **argv0;
34 {
35 	int rem, pid;
36 	char *host, *cp, **ap, buf[BUFSIZ], *args, **argv = argv0, *user = 0;
37 	register int cc;
38 	int asrsh = 0;
39 	struct passwd *pwd;
40 	int readfrom, ready;
41 	int one = 1;
42 
43 	host = rindex(argv[0], '/');
44 	if (host)
45 		host++;
46 	else
47 		host = argv[0];
48 	argv++, --argc;
49 	if (!strcmp(host, "rsh")) {
50 		host = *argv++, --argc;
51 		asrsh = 1;
52 	}
53 another:
54 	if (!strcmp(*argv, "-l")) {
55 		argv++, argc--;
56 		if (argc > 0)
57 			user = *argv++, argc--;
58 		goto another;
59 	}
60 	if (!strcmp(*argv, "-n")) {
61 		argv++, argc--;
62 		(void) close(0);
63 		(void) open("/dev/null", 0);
64 		goto another;
65 	}
66 	if (!strcmp(*argv, "-d")) {
67 		argv++, argc--;
68 		options |= SO_DEBUG;
69 		goto another;
70 	}
71 	if (host == 0)
72 		goto usage;
73 	if (argv[0] == 0) {
74 		if (asrsh)
75 			*argv0 = "rlogin";
76 		execv("/usr/ucb/rlogin", argv0);
77 		perror("/usr/ucb/rlogin");
78 		exit(1);
79 	}
80 	pwd = getpwuid(getuid());
81 	if (pwd == 0) {
82 		fprintf(stderr, "who are you?\n");
83 		exit(1);
84 	}
85 	cc = 0;
86 	for (ap = argv; *ap; ap++)
87 		cc += strlen(*ap) + 1;
88 	cp = args = malloc(cc);
89 	for (ap = argv; *ap; ap++) {
90 		(void) strcpy(cp, *ap);
91 		while (*cp)
92 			cp++;
93 		if (ap[1])
94 			*cp++ = ' ';
95 	}
96         rem = rcmd(&host, IPPORT_CMDSERVER, pwd->pw_name,
97 	    user ? user : pwd->pw_name, args, &rfd2);
98         if (rem < 0)
99                 exit(1);
100 	(void) setuid(getuid());
101 	sigacts(SIG_HOLD);
102         pid = fork();
103         if (pid < 0) {
104 		perror("fork");
105                 exit(1);
106         }
107 	ioctl(rfd2, FIONBIO, &one);
108 	ioctl(rem, FIONBIO, &one);
109         if (pid == 0) {
110 		char *bp; int rembits, wc;
111 		(void) close(rfd2);
112 	reread:
113 		cc = read(0, buf, sizeof buf);
114 		if (cc <= 0)
115 			goto done;
116 		bp = buf;
117 	rewrite:
118 		rembits = 1<<rem;
119 		if (select(16, 0, &rembits, 0, 0) < 0) {
120 			if (errno != EINTR) {
121 				perror("select");
122 				exit(1);
123 			}
124 			goto rewrite;
125 		}
126 		if ((rembits & (1<<rem)) == 0)
127 			goto rewrite;
128 		wc = write(rem, bp, cc);
129 		if (wc < 0) {
130 			if (errno == EWOULDBLOCK)
131 				goto rewrite;
132 			goto done;
133 		}
134 		cc -= wc; bp += wc;
135 		if (cc == 0)
136 			goto reread;
137 		goto rewrite;
138 	done:
139 		{ int flags = 1; ioctl(rem, SIOCDONE, &flags); }
140 		exit(0);
141 	}
142 	sigacts(sendsig);
143 	readfrom = (1<<rfd2) | (1<<rem);
144 	do {
145 		ready = readfrom;
146 		if (select(16, &ready, 0, 0, 0) < 0) {
147 			if (errno != EINTR) {
148 				perror("select");
149 				exit(1);
150 			}
151 			continue;
152 		}
153 		if (ready & (1<<rfd2)) {
154 			errno = 0;
155 			cc = read(rfd2, buf, sizeof buf);
156 			if (cc <= 0) {
157 				if (errno != EWOULDBLOCK)
158 					readfrom &= ~(1<<rfd2);
159 			} else
160 				(void) write(2, buf, cc);
161 		}
162 		if (ready & (1<<rem)) {
163 			errno = 0;
164 			cc = read(rem, buf, sizeof buf);
165 			if (cc <= 0) {
166 				if (errno != EWOULDBLOCK)
167 					readfrom &= ~(1<<rem);
168 			} else
169 				(void) write(1, buf, cc);
170 		}
171         } while (readfrom);
172         (void) kill(pid, SIGKILL);
173 	exit(0);
174 usage:
175 	fprintf(stderr,
176 	    "usage: rsh host [ -l login ] [ -p passwd ] command\n");
177 	exit(1);
178 }
179 
180 sigacts(state)
181 	int (*state)();
182 {
183 
184 	sigset(SIGINT, state);
185 	sigset(SIGQUIT, state);
186 	sigset(SIGTERM, state);
187 }
188 
189 sendsig(signo)
190 	int signo;
191 {
192 
193 	(void) write(rfd2, (char *)&signo, 1);
194 }
195