make sleep spin-wait during autoconfiguration
[unix-history] / usr / src / libexec / rlogind / rlogind.c
CommitLineData
8c5eec2f
DF
1/*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
8char copyright[] =
9"@(#) Copyright (c) 1983 Regents of the University of California.\n\
10 All rights reserved.\n";
11#endif not lint
12
a10a364d 13#ifndef lint
cfafdcf2 14static char sccsid[] = "@(#)rlogind.c 5.11 (Berkeley) %G%";
8c5eec2f 15#endif not lint
a10a364d 16
bb933cc2
MK
17/*
18 * remote login server:
19 * remuser\0
20 * locuser\0
6632767b 21 * terminal info\0
bb933cc2
MK
22 * data
23 */
24
a10a364d
BJ
25#include <stdio.h>
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <sys/socket.h>
560a8855 29#include <sys/wait.h>
6632767b 30#include <sys/file.h>
c6c678f1
SL
31
32#include <netinet/in.h>
33
a10a364d
BJ
34#include <errno.h>
35#include <pwd.h>
a10a364d
BJ
36#include <signal.h>
37#include <sgtty.h>
38#include <stdio.h>
3f5b52bc 39#include <netdb.h>
3f99c0f7 40#include <syslog.h>
6632767b 41#include <strings.h>
a10a364d 42
66feb14c
KM
43# ifndef TIOCPKT_WINDOW
44# define TIOCPKT_WINDOW 0x80
45# endif TIOCPKT_WINDOW
46
a10a364d 47extern errno;
92e31018 48int reapchild();
a10a364d 49struct passwd *getpwnam();
66feb14c 50char *malloc();
bb933cc2 51
a10a364d
BJ
52main(argc, argv)
53 int argc;
54 char **argv;
55{
bcb894cb 56 int on = 1, options = 0, fromlen;
a10a364d
BJ
57 struct sockaddr_in from;
58
076ae92c 59 openlog("rlogind", LOG_PID | LOG_AUTH, LOG_AUTH);
bb933cc2
MK
60 fromlen = sizeof (from);
61 if (getpeername(0, &from, &fromlen) < 0) {
62 fprintf(stderr, "%s: ", argv[0]);
63 perror("getpeername");
64 _exit(1);
92e31018 65 }
bcb894cb 66 if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {
3f99c0f7 67 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
c6c678f1 68 }
bb933cc2 69 doit(0, &from);
92e31018
SL
70}
71
a10a364d
BJ
72int child;
73int cleanup();
74int netf;
75extern errno;
76char *line;
43368533 77extern char *inet_ntoa();
a10a364d 78
8210fa73
KM
79struct winsize win = { 0, 0, 0, 0 };
80
66feb14c 81
a10a364d
BJ
82doit(f, fromp)
83 int f;
84 struct sockaddr_in *fromp;
85{
6632767b 86 int i, p, t, pid, on = 1;
3f5b52bc 87 register struct hostent *hp;
43368533 88 struct hostent hostent;
6632767b 89 char c;
a10a364d
BJ
90
91 alarm(60);
92 read(f, &c, 1);
93 if (c != 0)
94 exit(1);
95 alarm(0);
1227078b 96 fromp->sin_port = ntohs((u_short)fromp->sin_port);
3f5b52bc
SL
97 hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr),
98 fromp->sin_family);
8de87e4f 99 if (hp == 0) {
43368533
KM
100 /*
101 * Only the name is used below.
102 */
103 hp = &hostent;
104 hp->h_name = inet_ntoa(fromp->sin_addr);
8de87e4f 105 }
a10a364d 106 if (fromp->sin_family != AF_INET ||
1227078b 107 fromp->sin_port >= IPPORT_RESERVED)
82c973f2 108 fatal(f, "Permission denied");
a10a364d
BJ
109 write(f, "", 1);
110 for (c = 'p'; c <= 's'; c++) {
111 struct stat stb;
112 line = "/dev/ptyXX";
113 line[strlen("/dev/pty")] = c;
114 line[strlen("/dev/ptyp")] = '0';
115 if (stat(line, &stb) < 0)
116 break;
117 for (i = 0; i < 16; i++) {
118 line[strlen("/dev/ptyp")] = "0123456789abcdef"[i];
119 p = open(line, 2);
120 if (p > 0)
121 goto gotpty;
122 }
123 }
66feb14c 124 fatal(f, "Out of ptys");
82c973f2 125 /*NOTREACHED*/
a10a364d 126gotpty:
8210fa73 127 (void) ioctl(p, TIOCSWINSZ, &win);
1227078b 128 netf = f;
a10a364d
BJ
129 line[strlen("/dev/")] = 't';
130#ifdef DEBUG
131 { int tt = open("/dev/tty", 2);
132 if (tt > 0) {
133 ioctl(tt, TIOCNOTTY, 0);
134 close(tt);
135 }
136 }
137#endif
138 t = open(line, 2);
82c973f2
SL
139 if (t < 0)
140 fatalperror(f, line, errno);
a10a364d
BJ
141 { struct sgttyb b;
142 gtty(t, &b); b.sg_flags = RAW|ANYP; stty(t, &b);
143 }
82c973f2
SL
144 pid = fork();
145 if (pid < 0)
146 fatalperror(f, "", errno);
6632767b
SL
147 if (pid == 0) {
148 close(f), close(p);
149 dup2(t, 0), dup2(t, 1), dup2(t, 2);
1227078b 150 close(t);
6632767b
SL
151 execl("/bin/login", "login", "-r", hp->h_name, 0);
152 fatalperror(2, "/bin/login", errno);
153 /*NOTREACHED*/
154 }
155 close(t);
156 ioctl(f, FIONBIO, &on);
157 ioctl(p, FIONBIO, &on);
158 ioctl(p, TIOCPKT, &on);
159 signal(SIGTSTP, SIG_IGN);
160 signal(SIGCHLD, cleanup);
ad5d2c7f 161 setpgrp(0, 0);
6632767b
SL
162 protocol(f, p);
163 cleanup();
164}
82c973f2 165
6632767b 166char magic[2] = { 0377, 0377 };
87e80234 167char oobdata[] = {TIOCPKT_WINDOW};
6632767b
SL
168
169/*
170 * Handle a "control" request (signaled by magic being present)
171 * in the data stream. For now, we are only willing to handle
172 * window size changes.
173 */
174control(pty, cp, n)
175 int pty;
176 char *cp;
177 int n;
178{
cfafdcf2 179 struct winsize w;
6632767b 180
cfafdcf2 181 if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's')
6632767b 182 return (0);
87e80234 183 oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */
cfafdcf2
KM
184 bcopy(cp+4, (char *)&w, sizeof(w));
185 w.ws_row = ntohs(w.ws_row);
186 w.ws_col = ntohs(w.ws_col);
187 w.ws_xpixel = ntohs(w.ws_xpixel);
188 w.ws_ypixel = ntohs(w.ws_ypixel);
189 (void)ioctl(pty, TIOCSWINSZ, &w);
190 return (4+sizeof (w));
6632767b
SL
191}
192
193/*
194 * rlogin "protocol" machine.
195 */
196protocol(f, p)
197 int f, p;
198{
199 char pibuf[1024], fibuf[1024], *pbp, *fbp;
200 register pcc = 0, fcc = 0;
87e80234 201 int cc;
2c360ad3 202 char cntl;
6632767b 203
ffaf1c0b 204 /*
9ee4d121
SL
205 * Must ignore SIGTTOU, otherwise we'll stop
206 * when we try and set slave pty's window shape
87e80234 207 * (our controlling tty is the master pty).
ffaf1c0b 208 */
9ee4d121 209 (void) signal(SIGTTOU, SIG_IGN);
87e80234 210 send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */
6632767b 211 for (;;) {
2c360ad3 212 int ibits, obits, ebits;
6632767b 213
2c360ad3
MK
214 ibits = 0;
215 obits = 0;
6632767b
SL
216 if (fcc)
217 obits |= (1<<p);
218 else
219 ibits |= (1<<f);
220 if (pcc >= 0)
221 if (pcc)
222 obits |= (1<<f);
82c973f2 223 else
6632767b 224 ibits |= (1<<p);
2c360ad3
MK
225 ebits = (1<<p);
226 if (select(16, &ibits, &obits, &ebits, 0) < 0) {
6632767b 227 if (errno == EINTR)
a10a364d 228 continue;
6632767b
SL
229 fatalperror(f, "select", errno);
230 }
2c360ad3 231 if (ibits == 0 && obits == 0 && ebits == 0) {
6632767b
SL
232 /* shouldn't happen... */
233 sleep(5);
234 continue;
235 }
2c360ad3
MK
236#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
237 if (ebits & (1<<p)) {
238 cc = read(p, &cntl, 1);
239 if (cc == 1 && pkcontrol(cntl)) {
240 cntl |= oobdata[0];
241 send(f, &cntl, 1, MSG_OOB);
242 if (cntl & TIOCPKT_FLUSHWRITE) {
243 pcc = 0;
244 ibits &= ~(1<<p);
245 }
246 }
247 }
6632767b
SL
248 if (ibits & (1<<f)) {
249 fcc = read(f, fibuf, sizeof (fibuf));
250 if (fcc < 0 && errno == EWOULDBLOCK)
251 fcc = 0;
252 else {
253 register char *cp;
254 int left, n;
255
256 if (fcc <= 0)
1227078b 257 break;
6632767b 258 fbp = fibuf;
66feb14c 259
6632767b 260 top:
87e80234 261 for (cp = fibuf; cp < fibuf+fcc-1; cp++)
6632767b
SL
262 if (cp[0] == magic[0] &&
263 cp[1] == magic[1]) {
264 left = fcc - (cp-fibuf);
265 n = control(p, cp, left);
266 if (n) {
267 left -= n;
268 if (left > 0)
87e80234 269 bcopy(cp+n, cp, left);
6632767b
SL
270 fcc -= n;
271 goto top; /* n^2 */
87e80234
MK
272 }
273 }
274 }
275 }
66feb14c
KM
276
277 if ((obits & (1<<p)) && fcc > 0) {
87e80234 278 cc = write(p, fbp, fcc);
66feb14c
KM
279 if (cc > 0) {
280 fcc -= cc;
281 fbp += cc;
a10a364d 282 }
6632767b 283 }
66feb14c 284
6632767b
SL
285 if (ibits & (1<<p)) {
286 pcc = read(p, pibuf, sizeof (pibuf));
287 pbp = pibuf;
288 if (pcc < 0 && errno == EWOULDBLOCK)
289 pcc = 0;
290 else if (pcc <= 0)
291 break;
292 else if (pibuf[0] == 0)
293 pbp++, pcc--;
294 else {
6632767b 295 if (pkcontrol(pibuf[0])) {
87e80234 296 pibuf[0] |= oobdata[0];
6632767b 297 send(f, &pibuf[0], 1, MSG_OOB);
a10a364d 298 }
6632767b 299 pcc = 0;
a10a364d 300 }
6632767b
SL
301 }
302 if ((obits & (1<<f)) && pcc > 0) {
87e80234
MK
303 cc = write(f, pbp, pcc);
304 if (cc < 0 && errno == EWOULDBLOCK) {
305 /* also shouldn't happen */
306 sleep(5);
307 continue;
308 }
6632767b
SL
309 if (cc > 0) {
310 pcc -= cc;
311 pbp += cc;
312 }
313 }
a10a364d 314 }
a10a364d
BJ
315}
316
317cleanup()
318{
a10a364d
BJ
319
320 rmut();
dd83e8ac 321 vhangup(); /* XXX */
ff24c640 322 shutdown(netf, 2);
a10a364d
BJ
323 exit(1);
324}
325
82c973f2
SL
326fatal(f, msg)
327 int f;
328 char *msg;
329{
330 char buf[BUFSIZ];
331
332 buf[0] = '\01'; /* error indicator */
560a8855 333 (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg);
82c973f2
SL
334 (void) write(f, buf, strlen(buf));
335 exit(1);
336}
337
338fatalperror(f, msg, errno)
339 int f;
340 char *msg;
341 int errno;
342{
343 char buf[BUFSIZ];
1227078b 344 extern int sys_nerr;
82c973f2
SL
345 extern char *sys_errlist[];
346
6632767b 347 if ((unsigned)errno < sys_nerr)
1227078b
MK
348 (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]);
349 else
350 (void) sprintf(buf, "%s: Error %d", msg, errno);
82c973f2
SL
351 fatal(f, buf);
352}
353
a10a364d
BJ
354#include <utmp.h>
355
356struct utmp wtmp;
357char wtmpf[] = "/usr/adm/wtmp";
0675fdb1 358char utmpf[] = "/etc/utmp";
a10a364d
BJ
359#define SCPYN(a, b) strncpy(a, b, sizeof(a))
360#define SCMPN(a, b) strncmp(a, b, sizeof(a))
361
362rmut()
363{
364 register f;
365 int found = 0;
0675fdb1
JB
366 struct utmp *u, *utmp;
367 int nutmp;
368 struct stat statbf;
a10a364d 369
0675fdb1 370 f = open(utmpf, O_RDWR);
a10a364d 371 if (f >= 0) {
0675fdb1
JB
372 fstat(f, &statbf);
373 utmp = (struct utmp *)malloc(statbf.st_size);
374 if (!utmp)
375 syslog(LOG_ERR, "utmp malloc failed");
376 if (statbf.st_size && utmp) {
377 nutmp = read(f, utmp, statbf.st_size);
378 nutmp /= sizeof(struct utmp);
379
380 for (u = utmp ; u < &utmp[nutmp] ; u++) {
381 if (SCMPN(u->ut_line, line+5) ||
382 u->ut_name[0]==0)
383 continue;
384 lseek(f, ((long)u)-((long)utmp), L_SET);
385 SCPYN(u->ut_name, "");
386 SCPYN(u->ut_host, "");
387 time(&u->ut_time);
388 write(f, (char *)u, sizeof(wtmp));
389 found++;
390 }
a10a364d
BJ
391 }
392 close(f);
393 }
394 if (found) {
0675fdb1 395 f = open(wtmpf, O_WRONLY|O_APPEND);
a10a364d
BJ
396 if (f >= 0) {
397 SCPYN(wtmp.ut_line, line+5);
398 SCPYN(wtmp.ut_name, "");
9b3ee53c 399 SCPYN(wtmp.ut_host, "");
a10a364d 400 time(&wtmp.ut_time);
a10a364d
BJ
401 write(f, (char *)&wtmp, sizeof(wtmp));
402 close(f);
403 }
404 }
405 chmod(line, 0666);
406 chown(line, 0, 0);
407 line[strlen("/dev/")] = 'p';
408 chmod(line, 0666);
409 chown(line, 0, 0);
410}