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