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