do not set window size from rlogin as rlogind promises to handle it;
[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
a489fe8e 14static char sccsid[] = "@(#)rlogind.c 5.6 (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
bb933cc2
MK
59 fromlen = sizeof (from);
60 if (getpeername(0, &from, &fromlen) < 0) {
61 fprintf(stderr, "%s: ", argv[0]);
62 perror("getpeername");
63 _exit(1);
92e31018 64 }
bcb894cb 65 if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {
3f99c0f7
RC
66 openlog(argv[0], LOG_PID, 0);
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
66feb14c 79
a10a364d
BJ
80doit(f, fromp)
81 int f;
82 struct sockaddr_in *fromp;
83{
6632767b 84 int i, p, t, pid, on = 1;
3f5b52bc 85 register struct hostent *hp;
43368533 86 struct hostent hostent;
6632767b 87 char c;
a10a364d
BJ
88
89 alarm(60);
90 read(f, &c, 1);
91 if (c != 0)
92 exit(1);
93 alarm(0);
1227078b 94 fromp->sin_port = ntohs((u_short)fromp->sin_port);
3f5b52bc
SL
95 hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr),
96 fromp->sin_family);
8de87e4f 97 if (hp == 0) {
43368533
KM
98 /*
99 * Only the name is used below.
100 */
101 hp = &hostent;
102 hp->h_name = inet_ntoa(fromp->sin_addr);
8de87e4f 103 }
a10a364d 104 if (fromp->sin_family != AF_INET ||
1227078b 105 fromp->sin_port >= IPPORT_RESERVED)
82c973f2 106 fatal(f, "Permission denied");
a10a364d
BJ
107 write(f, "", 1);
108 for (c = 'p'; c <= 's'; c++) {
109 struct stat stb;
110 line = "/dev/ptyXX";
111 line[strlen("/dev/pty")] = c;
112 line[strlen("/dev/ptyp")] = '0';
113 if (stat(line, &stb) < 0)
114 break;
115 for (i = 0; i < 16; i++) {
116 line[strlen("/dev/ptyp")] = "0123456789abcdef"[i];
117 p = open(line, 2);
118 if (p > 0)
119 goto gotpty;
120 }
121 }
66feb14c 122 fatal(f, "Out of ptys");
82c973f2 123 /*NOTREACHED*/
a10a364d 124gotpty:
1227078b 125 netf = f;
a10a364d
BJ
126 line[strlen("/dev/")] = 't';
127#ifdef DEBUG
128 { int tt = open("/dev/tty", 2);
129 if (tt > 0) {
130 ioctl(tt, TIOCNOTTY, 0);
131 close(tt);
132 }
133 }
134#endif
135 t = open(line, 2);
82c973f2
SL
136 if (t < 0)
137 fatalperror(f, line, errno);
a10a364d
BJ
138 { struct sgttyb b;
139 gtty(t, &b); b.sg_flags = RAW|ANYP; stty(t, &b);
140 }
82c973f2
SL
141 pid = fork();
142 if (pid < 0)
143 fatalperror(f, "", errno);
6632767b
SL
144 if (pid == 0) {
145 close(f), close(p);
146 dup2(t, 0), dup2(t, 1), dup2(t, 2);
1227078b 147 close(t);
6632767b
SL
148 execl("/bin/login", "login", "-r", hp->h_name, 0);
149 fatalperror(2, "/bin/login", errno);
150 /*NOTREACHED*/
151 }
152 close(t);
153 ioctl(f, FIONBIO, &on);
154 ioctl(p, FIONBIO, &on);
155 ioctl(p, TIOCPKT, &on);
156 signal(SIGTSTP, SIG_IGN);
157 signal(SIGCHLD, cleanup);
ad5d2c7f 158 setpgrp(0, 0);
6632767b
SL
159 protocol(f, p);
160 cleanup();
161}
82c973f2 162
6632767b
SL
163char magic[2] = { 0377, 0377 };
164
165/*
166 * Handle a "control" request (signaled by magic being present)
167 * in the data stream. For now, we are only willing to handle
168 * window size changes.
169 */
170control(pty, cp, n)
171 int pty;
172 char *cp;
173 int n;
174{
175 struct winsize *wp;
176
177 if (n < 4+sizeof (*wp) || cp[2] != 's' || cp[3] != 's')
178 return (0);
179 wp = (struct winsize *)(cp+4);
180 wp->ws_row = ntohs(wp->ws_row);
181 wp->ws_col = ntohs(wp->ws_col);
182 wp->ws_xpixel = ntohs(wp->ws_xpixel);
183 wp->ws_ypixel = ntohs(wp->ws_ypixel);
184 (void)ioctl(pty, TIOCSWINSZ, wp);
185 return (4+sizeof (*wp));
186}
187
188/*
189 * rlogin "protocol" machine.
190 */
191protocol(f, p)
192 int f, p;
193{
194 char pibuf[1024], fibuf[1024], *pbp, *fbp;
195 register pcc = 0, fcc = 0;
66feb14c
KM
196 int cc, stop = TIOCPKT_DOSTOP, wsize;
197 static char oob[] = {TIOCPKT_WINDOW};
6632767b 198
ffaf1c0b 199 /*
9ee4d121
SL
200 * Must ignore SIGTTOU, otherwise we'll stop
201 * when we try and set slave pty's window shape
202 * (our pgrp is that of the master pty).
ffaf1c0b 203 */
9ee4d121 204 (void) signal(SIGTTOU, SIG_IGN);
66feb14c 205 send(f, oob, 1, MSG_OOB); /* indicate new rlogin */
6632767b
SL
206 for (;;) {
207 int ibits = 0, obits = 0;
208
209 if (fcc)
210 obits |= (1<<p);
211 else
212 ibits |= (1<<f);
213 if (pcc >= 0)
214 if (pcc)
215 obits |= (1<<f);
82c973f2 216 else
6632767b
SL
217 ibits |= (1<<p);
218 if (select(16, &ibits, &obits, 0, 0) < 0) {
219 if (errno == EINTR)
a10a364d 220 continue;
6632767b
SL
221 fatalperror(f, "select", errno);
222 }
223 if (ibits == 0 && obits == 0) {
224 /* shouldn't happen... */
225 sleep(5);
226 continue;
227 }
228 if (ibits & (1<<f)) {
229 fcc = read(f, fibuf, sizeof (fibuf));
230 if (fcc < 0 && errno == EWOULDBLOCK)
231 fcc = 0;
232 else {
233 register char *cp;
234 int left, n;
235
236 if (fcc <= 0)
1227078b 237 break;
6632767b 238 fbp = fibuf;
66feb14c 239
6632767b
SL
240 top:
241 for (cp = fibuf; cp < fibuf+fcc; cp++)
242 if (cp[0] == magic[0] &&
243 cp[1] == magic[1]) {
244 left = fcc - (cp-fibuf);
245 n = control(p, cp, left);
246 if (n) {
247 left -= n;
248 if (left > 0)
249 bcopy(cp, cp+n, left);
250 fcc -= n;
251 goto top; /* n^2 */
66feb14c
KM
252 } /* if (n) */
253 } /* for (cp = ) */
254 } /* else */
255 } /* if (ibits & (1<<f)) */
256
257 if ((obits & (1<<p)) && fcc > 0) {
258 wsize = fcc;
259 do {
260 cc = write(p, fbp, wsize);
261 wsize /= 2;
262 } while (cc<0 && errno==EWOULDBLOCK && wsize);
263 if (cc > 0) {
264 fcc -= cc;
265 fbp += cc;
a10a364d 266 }
6632767b 267 }
66feb14c 268
6632767b
SL
269 if (ibits & (1<<p)) {
270 pcc = read(p, pibuf, sizeof (pibuf));
271 pbp = pibuf;
272 if (pcc < 0 && errno == EWOULDBLOCK)
273 pcc = 0;
274 else if (pcc <= 0)
275 break;
276 else if (pibuf[0] == 0)
277 pbp++, pcc--;
278 else {
279#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
66feb14c
KM
280 int out = FREAD;
281
6632767b
SL
282 if (pkcontrol(pibuf[0])) {
283 /* The following 3 lines do nothing. */
284 int nstop = pibuf[0] &
285 (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP);
286
287 if (nstop)
288 stop = nstop;
289 pibuf[0] |= nstop;
290 send(f, &pibuf[0], 1, MSG_OOB);
66feb14c
KM
291 if (pibuf[0] & TIOCPKT_FLUSHWRITE)
292 ioctl(p, TIOCFLUSH, (char *)&out);
293
a10a364d 294 }
6632767b 295 pcc = 0;
a10a364d 296 }
6632767b
SL
297 }
298 if ((obits & (1<<f)) && pcc > 0) {
66feb14c
KM
299 wsize = pcc;
300 do {
301 cc = write(f, pbp, wsize);
302 wsize /= 2;
303 } while (cc<0 && errno==EWOULDBLOCK && wsize);
6632767b
SL
304 if (cc > 0) {
305 pcc -= cc;
306 pbp += cc;
307 }
308 }
a10a364d 309 }
a10a364d
BJ
310}
311
312cleanup()
313{
a10a364d
BJ
314
315 rmut();
dd83e8ac 316 vhangup(); /* XXX */
ff24c640 317 shutdown(netf, 2);
a10a364d
BJ
318 kill(0, SIGKILL);
319 exit(1);
320}
321
82c973f2
SL
322fatal(f, msg)
323 int f;
324 char *msg;
325{
326 char buf[BUFSIZ];
327
328 buf[0] = '\01'; /* error indicator */
560a8855 329 (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg);
82c973f2
SL
330 (void) write(f, buf, strlen(buf));
331 exit(1);
332}
333
334fatalperror(f, msg, errno)
335 int f;
336 char *msg;
337 int errno;
338{
339 char buf[BUFSIZ];
1227078b 340 extern int sys_nerr;
82c973f2
SL
341 extern char *sys_errlist[];
342
6632767b 343 if ((unsigned)errno < sys_nerr)
1227078b
MK
344 (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]);
345 else
346 (void) sprintf(buf, "%s: Error %d", msg, errno);
82c973f2
SL
347 fatal(f, buf);
348}
349
a10a364d
BJ
350#include <utmp.h>
351
352struct utmp wtmp;
353char wtmpf[] = "/usr/adm/wtmp";
0675fdb1 354char utmpf[] = "/etc/utmp";
a10a364d
BJ
355#define SCPYN(a, b) strncpy(a, b, sizeof(a))
356#define SCMPN(a, b) strncmp(a, b, sizeof(a))
357
358rmut()
359{
360 register f;
361 int found = 0;
0675fdb1
JB
362 struct utmp *u, *utmp;
363 int nutmp;
364 struct stat statbf;
a10a364d 365
0675fdb1 366 f = open(utmpf, O_RDWR);
a10a364d 367 if (f >= 0) {
0675fdb1
JB
368 fstat(f, &statbf);
369 utmp = (struct utmp *)malloc(statbf.st_size);
370 if (!utmp)
371 syslog(LOG_ERR, "utmp malloc failed");
372 if (statbf.st_size && utmp) {
373 nutmp = read(f, utmp, statbf.st_size);
374 nutmp /= sizeof(struct utmp);
375
376 for (u = utmp ; u < &utmp[nutmp] ; u++) {
377 if (SCMPN(u->ut_line, line+5) ||
378 u->ut_name[0]==0)
379 continue;
380 lseek(f, ((long)u)-((long)utmp), L_SET);
381 SCPYN(u->ut_name, "");
382 SCPYN(u->ut_host, "");
383 time(&u->ut_time);
384 write(f, (char *)u, sizeof(wtmp));
385 found++;
386 }
a10a364d
BJ
387 }
388 close(f);
389 }
390 if (found) {
0675fdb1 391 f = open(wtmpf, O_WRONLY|O_APPEND);
a10a364d
BJ
392 if (f >= 0) {
393 SCPYN(wtmp.ut_line, line+5);
394 SCPYN(wtmp.ut_name, "");
9b3ee53c 395 SCPYN(wtmp.ut_host, "");
a10a364d 396 time(&wtmp.ut_time);
a10a364d
BJ
397 write(f, (char *)&wtmp, sizeof(wtmp));
398 close(f);
399 }
400 }
401 chmod(line, 0666);
402 chown(line, 0, 0);
403 line[strlen("/dev/")] = 'p';
404 chmod(line, 0666);
405 chown(line, 0, 0);
406}