fixes from Kirk Smith for line numbers
[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
d9b06a2d 14static char sccsid[] = "@(#)rlogind.c 5.8 (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
SL
166char magic[2] = { 0377, 0377 };
167
168/*
169 * Handle a "control" request (signaled by magic being present)
170 * in the data stream. For now, we are only willing to handle
171 * window size changes.
172 */
173control(pty, cp, n)
174 int pty;
175 char *cp;
176 int n;
177{
178 struct winsize *wp;
179
180 if (n < 4+sizeof (*wp) || cp[2] != 's' || cp[3] != 's')
181 return (0);
182 wp = (struct winsize *)(cp+4);
183 wp->ws_row = ntohs(wp->ws_row);
184 wp->ws_col = ntohs(wp->ws_col);
185 wp->ws_xpixel = ntohs(wp->ws_xpixel);
186 wp->ws_ypixel = ntohs(wp->ws_ypixel);
187 (void)ioctl(pty, TIOCSWINSZ, wp);
188 return (4+sizeof (*wp));
189}
190
191/*
192 * rlogin "protocol" machine.
193 */
194protocol(f, p)
195 int f, p;
196{
197 char pibuf[1024], fibuf[1024], *pbp, *fbp;
198 register pcc = 0, fcc = 0;
66feb14c
KM
199 int cc, stop = TIOCPKT_DOSTOP, wsize;
200 static char oob[] = {TIOCPKT_WINDOW};
6632767b 201
ffaf1c0b 202 /*
9ee4d121
SL
203 * Must ignore SIGTTOU, otherwise we'll stop
204 * when we try and set slave pty's window shape
205 * (our pgrp is that of the master pty).
ffaf1c0b 206 */
9ee4d121 207 (void) signal(SIGTTOU, SIG_IGN);
66feb14c 208 send(f, oob, 1, MSG_OOB); /* indicate new rlogin */
6632767b
SL
209 for (;;) {
210 int ibits = 0, obits = 0;
211
212 if (fcc)
213 obits |= (1<<p);
214 else
215 ibits |= (1<<f);
216 if (pcc >= 0)
217 if (pcc)
218 obits |= (1<<f);
82c973f2 219 else
6632767b
SL
220 ibits |= (1<<p);
221 if (select(16, &ibits, &obits, 0, 0) < 0) {
222 if (errno == EINTR)
a10a364d 223 continue;
6632767b
SL
224 fatalperror(f, "select", errno);
225 }
226 if (ibits == 0 && obits == 0) {
227 /* shouldn't happen... */
228 sleep(5);
229 continue;
230 }
231 if (ibits & (1<<f)) {
232 fcc = read(f, fibuf, sizeof (fibuf));
233 if (fcc < 0 && errno == EWOULDBLOCK)
234 fcc = 0;
235 else {
236 register char *cp;
237 int left, n;
238
239 if (fcc <= 0)
1227078b 240 break;
6632767b 241 fbp = fibuf;
66feb14c 242
6632767b
SL
243 top:
244 for (cp = fibuf; cp < fibuf+fcc; cp++)
245 if (cp[0] == magic[0] &&
246 cp[1] == magic[1]) {
247 left = fcc - (cp-fibuf);
248 n = control(p, cp, left);
249 if (n) {
250 left -= n;
251 if (left > 0)
252 bcopy(cp, cp+n, left);
253 fcc -= n;
254 goto top; /* n^2 */
66feb14c
KM
255 } /* if (n) */
256 } /* for (cp = ) */
257 } /* else */
258 } /* if (ibits & (1<<f)) */
259
260 if ((obits & (1<<p)) && fcc > 0) {
261 wsize = fcc;
262 do {
263 cc = write(p, fbp, wsize);
264 wsize /= 2;
265 } while (cc<0 && errno==EWOULDBLOCK && wsize);
266 if (cc > 0) {
267 fcc -= cc;
268 fbp += cc;
a10a364d 269 }
6632767b 270 }
66feb14c 271
6632767b
SL
272 if (ibits & (1<<p)) {
273 pcc = read(p, pibuf, sizeof (pibuf));
274 pbp = pibuf;
275 if (pcc < 0 && errno == EWOULDBLOCK)
276 pcc = 0;
277 else if (pcc <= 0)
278 break;
279 else if (pibuf[0] == 0)
280 pbp++, pcc--;
281 else {
282#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
66feb14c
KM
283 int out = FREAD;
284
6632767b
SL
285 if (pkcontrol(pibuf[0])) {
286 /* The following 3 lines do nothing. */
287 int nstop = pibuf[0] &
288 (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP);
289
290 if (nstop)
291 stop = nstop;
8210fa73 292 pibuf[0] |= nstop | oob[0];
6632767b 293 send(f, &pibuf[0], 1, MSG_OOB);
66feb14c
KM
294 if (pibuf[0] & TIOCPKT_FLUSHWRITE)
295 ioctl(p, TIOCFLUSH, (char *)&out);
296
a10a364d 297 }
6632767b 298 pcc = 0;
a10a364d 299 }
6632767b
SL
300 }
301 if ((obits & (1<<f)) && pcc > 0) {
66feb14c
KM
302 wsize = pcc;
303 do {
304 cc = write(f, pbp, wsize);
305 wsize /= 2;
306 } while (cc<0 && errno==EWOULDBLOCK && wsize);
6632767b
SL
307 if (cc > 0) {
308 pcc -= cc;
309 pbp += cc;
310 }
311 }
a10a364d 312 }
a10a364d
BJ
313}
314
315cleanup()
316{
a10a364d
BJ
317
318 rmut();
dd83e8ac 319 vhangup(); /* XXX */
ff24c640 320 shutdown(netf, 2);
a10a364d
BJ
321 exit(1);
322}
323
82c973f2
SL
324fatal(f, msg)
325 int f;
326 char *msg;
327{
328 char buf[BUFSIZ];
329
330 buf[0] = '\01'; /* error indicator */
560a8855 331 (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg);
82c973f2
SL
332 (void) write(f, buf, strlen(buf));
333 exit(1);
334}
335
336fatalperror(f, msg, errno)
337 int f;
338 char *msg;
339 int errno;
340{
341 char buf[BUFSIZ];
1227078b 342 extern int sys_nerr;
82c973f2
SL
343 extern char *sys_errlist[];
344
6632767b 345 if ((unsigned)errno < sys_nerr)
1227078b
MK
346 (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]);
347 else
348 (void) sprintf(buf, "%s: Error %d", msg, errno);
82c973f2
SL
349 fatal(f, buf);
350}
351
a10a364d
BJ
352#include <utmp.h>
353
354struct utmp wtmp;
355char wtmpf[] = "/usr/adm/wtmp";
0675fdb1 356char utmpf[] = "/etc/utmp";
a10a364d
BJ
357#define SCPYN(a, b) strncpy(a, b, sizeof(a))
358#define SCMPN(a, b) strncmp(a, b, sizeof(a))
359
360rmut()
361{
362 register f;
363 int found = 0;
0675fdb1
JB
364 struct utmp *u, *utmp;
365 int nutmp;
366 struct stat statbf;
a10a364d 367
0675fdb1 368 f = open(utmpf, O_RDWR);
a10a364d 369 if (f >= 0) {
0675fdb1
JB
370 fstat(f, &statbf);
371 utmp = (struct utmp *)malloc(statbf.st_size);
372 if (!utmp)
373 syslog(LOG_ERR, "utmp malloc failed");
374 if (statbf.st_size && utmp) {
375 nutmp = read(f, utmp, statbf.st_size);
376 nutmp /= sizeof(struct utmp);
377
378 for (u = utmp ; u < &utmp[nutmp] ; u++) {
379 if (SCMPN(u->ut_line, line+5) ||
380 u->ut_name[0]==0)
381 continue;
382 lseek(f, ((long)u)-((long)utmp), L_SET);
383 SCPYN(u->ut_name, "");
384 SCPYN(u->ut_host, "");
385 time(&u->ut_time);
386 write(f, (char *)u, sizeof(wtmp));
387 found++;
388 }
a10a364d
BJ
389 }
390 close(f);
391 }
392 if (found) {
0675fdb1 393 f = open(wtmpf, O_WRONLY|O_APPEND);
a10a364d
BJ
394 if (f >= 0) {
395 SCPYN(wtmp.ut_line, line+5);
396 SCPYN(wtmp.ut_name, "");
9b3ee53c 397 SCPYN(wtmp.ut_host, "");
a10a364d 398 time(&wtmp.ut_time);
a10a364d
BJ
399 write(f, (char *)&wtmp, sizeof(wtmp));
400 close(f);
401 }
402 }
403 chmod(line, 0666);
404 chown(line, 0, 0);
405 line[strlen("/dev/")] = 'p';
406 chmod(line, 0666);
407 chown(line, 0, 0);
408}