no more SIOCDONE
[unix-history] / usr / src / libexec / rexecd / rexecd.c
CommitLineData
f0d0adca 1#ifndef lint
ff24c640 2static char sccsid[] = "@(#)rexecd.c 4.6 83/01/07";
f0d0adca
BJ
3#endif
4
f0d0adca
BJ
5#include <sys/ioctl.h>
6#include <sys/param.h>
7#include <sys/socket.h>
94a2d2a7
SL
8
9#include <netinet/in.h>
10
11#include <stdio.h>
f0d0adca
BJ
12#include <errno.h>
13#include <pwd.h>
14#include <wait.h>
15#include <signal.h>
94a2d2a7 16#include <netdb.h>
f0d0adca
BJ
17
18extern errno;
94a2d2a7 19struct sockaddr_in sin = { AF_INET };
f0d0adca
BJ
20struct passwd *getpwnam();
21char *crypt(), *rindex(), *sprintf();
f0d0adca
BJ
22/* VARARGS 1 */
23int error();
24/*
25 * remote execute server:
26 * username\0
27 * password\0
28 * command\0
29 * data
30 */
31main(argc, argv)
32 int argc;
33 char **argv;
34{
35 union wait status;
36 int f;
37 struct sockaddr_in from;
94a2d2a7 38 struct servent *sp;
f0d0adca 39
94a2d2a7
SL
40 sp = getservbyname("exec", "tcp");
41 if (sp == 0) {
42 fprintf(stderr, "tcp/exec: unknown service\n");
43 exit(1);
44 }
5458e392 45 sin.sin_port = sp->s_port;
f0d0adca
BJ
46#ifndef DEBUG
47 if (fork())
48 exit(0);
49 for (f = 0; f < 10; f++)
50 (void) close(f);
51 (void) open("/", 0);
52 (void) dup2(0, 1);
53 (void) dup2(0, 2);
54 { int t = open("/dev/tty", 2);
55 if (t >= 0) {
56 ioctl(t, TIOCNOTTY, (char *)0);
57 (void) close(t);
58 }
59 }
f0d0adca
BJ
60#endif
61 argc--, argv++;
36a969c5 62 f = socket(AF_INET, SOCK_STREAM, 0, 0);
94a2d2a7
SL
63 if (f < 0) {
64 perror("rexecd: socket");
65 exit(1);
66 }
67 if (bind(f, &sin, sizeof (sin), 0) < 0) {
68 perror("rexecd: bind:");
69 exit(1);
70 }
71 listen(f, 10);
f0d0adca 72 for (;;) {
94a2d2a7
SL
73 int s, len = sizeof (from);
74
75 s = accept(f, &from, &len, 0);
76 if (s < 0) {
77 perror("rexecd: accept");
f0d0adca
BJ
78 sleep(1);
79 continue;
80 }
81 if (fork() == 0)
94a2d2a7
SL
82 doit(s, &from);
83 (void) close(s);
84 while (wait3(status, WNOHANG, 0) > 0)
f0d0adca
BJ
85 continue;
86 }
87}
88
89char username[20] = "USER=";
90char homedir[64] = "HOME=";
91char shell[64] = "SHELL=";
92char *envinit[] =
93 {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", username, 0};
94char **environ;
95
96struct sockaddr_in asin = { AF_INET };
97
98doit(f, fromp)
99 int f;
100 struct sockaddr_in *fromp;
101{
102 char cmdbuf[NCARGS+1], *cp, *namep;
103 char user[16], pass[16];
104 struct passwd *pwd;
105 int s;
106 short port;
107 int pv[2], pid, ready, readfrom, cc;
108 char buf[BUFSIZ], sig;
109 int one = 1;
110
111 (void) signal(SIGINT, SIG_DFL);
112 (void) signal(SIGQUIT, SIG_DFL);
113 (void) signal(SIGTERM, SIG_DFL);
114#ifdef DEBUG
115 { int t = open("/dev/tty", 2);
116 if (t >= 0) {
117 ioctl(t, TIOCNOTTY, (char *)0);
118 (void) close(t);
119 }
120 }
121#endif
122 dup2(f, 0);
123 dup2(f, 1);
124 dup2(f, 2);
f0d0adca
BJ
125 (void) alarm(60);
126 port = 0;
127 for (;;) {
128 char c;
129 if (read(f, &c, 1) != 1)
130 exit(1);
131 if (c == 0)
132 break;
133 port = port * 10 + c - '0';
134 }
135 (void) alarm(0);
136 if (port != 0) {
36a969c5 137 s = socket(AF_INET, SOCK_STREAM, 0, 0);
f0d0adca
BJ
138 if (s < 0)
139 exit(1);
36a969c5
SL
140 if (bind(s, &asin, sizeof (asin), 0) < 0)
141 exit(1);
f0d0adca 142 (void) alarm(60);
36a969c5 143 fromp->sin_port = htons((u_short)port);
94a2d2a7 144 if (connect(s, fromp, sizeof (*fromp), 0) < 0)
f0d0adca
BJ
145 exit(1);
146 (void) alarm(0);
147 }
148 getstr(user, sizeof(user), "username");
149 getstr(pass, sizeof(pass), "password");
150 getstr(cmdbuf, sizeof(cmdbuf), "command");
151 setpwent();
152 pwd = getpwnam(user);
153 if (pwd == NULL) {
154 error("Login incorrect.\n");
155 exit(1);
156 }
157 endpwent();
158 if (*pwd->pw_passwd != '\0') {
159 namep = crypt(pass, pwd->pw_passwd);
160 if (strcmp(namep, pwd->pw_passwd)) {
161 error("Password incorrect.\n");
162 exit(1);
163 }
164 }
165 if (chdir(pwd->pw_dir) < 0) {
166 error("No remote directory.\n");
167 exit(1);
168 }
169 (void) write(2, "\0", 1);
170 if (port) {
171 (void) pipe(pv);
172 pid = fork();
173 if (pid == -1) {
174 error("Try again.\n");
175 exit(1);
176 }
177 if (pid) {
178 (void) close(0); (void) close(1); (void) close(2);
179 (void) close(f); (void) close(pv[1]);
180 readfrom = (1<<s) | (1<<pv[0]);
181 ioctl(pv[1], FIONBIO, (char *)&one);
182 /* should set s nbio! */
183 do {
184 ready = readfrom;
94a2d2a7 185 (void) select(16, &ready, 0, 0, 0);
f0d0adca
BJ
186 if (ready & (1<<s)) {
187 if (read(s, &sig, 1) <= 0)
188 readfrom &= ~(1<<s);
189 else
190 killpg(pid, sig);
191 }
192 if (ready & (1<<pv[0])) {
193 cc = read(pv[0], buf, sizeof (buf));
194 if (cc <= 0) {
ff24c640 195 shutdown(s, 1+1);
f0d0adca
BJ
196 readfrom &= ~(1<<pv[0]);
197 } else
198 (void) write(s, buf, cc);
199 }
200 } while (readfrom);
201 exit(0);
202 }
203 setpgrp(0, getpid());
204 (void) close(s); (void)close(pv[0]);
205 dup2(pv[1], 2);
206 }
207 if (*pwd->pw_shell == '\0')
208 pwd->pw_shell = "/bin/sh";
209 (void) close(f);
94a2d2a7 210 initgroups(pwd->pw_name, pwd->pw_gid);
f0d0adca
BJ
211 (void) setuid(pwd->pw_uid);
212 (void) setgid(pwd->pw_gid);
213 environ = envinit;
214 strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
215 strncat(shell, pwd->pw_shell, sizeof(shell)-7);
216 strncat(username, pwd->pw_name, sizeof(username)-6);
217 cp = rindex(pwd->pw_shell, '/');
218 if (cp)
219 cp++;
220 else
221 cp = pwd->pw_shell;
222 execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
223 perror(pwd->pw_shell);
224 exit(1);
225}
226
227/* VARARGS 1 */
228error(fmt, a1, a2, a3)
229 char *fmt;
230 int a1, a2, a3;
231{
232 char buf[BUFSIZ];
233
234 buf[0] = 1;
235 (void) sprintf(buf+1, fmt, a1, a2, a3);
236 (void) write(2, buf, strlen(buf));
237}
238
239getstr(buf, cnt, err)
240 char *buf;
241 int cnt;
242 char *err;
243{
244 char c;
245
246 do {
247 if (read(0, &c, 1) != 1)
248 exit(1);
249 *buf++ = c;
250 if (--cnt == 0) {
251 error("%s too long\n", err);
252 exit(1);
253 }
254 } while (c != 0);
255}