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