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