no more SIOCDONE
[unix-history] / usr / src / libexec / rlogind / rlogind.c
CommitLineData
a10a364d 1#ifndef lint
ff24c640 2static char sccsid[] = "@(#)rlogind.c 4.8 83/01/07";
a10a364d
BJ
3#endif
4
5#include <stdio.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <sys/socket.h>
c6c678f1
SL
9
10#include <netinet/in.h>
11
a10a364d
BJ
12#include <errno.h>
13#include <pwd.h>
14#include <wait.h>
15#include <signal.h>
16#include <sgtty.h>
17#include <stdio.h>
3f5b52bc 18#include <netdb.h>
a10a364d
BJ
19
20extern errno;
21struct passwd *getpwnam();
3f5b52bc 22char *crypt(), *rindex(), *index(), *malloc();
a10a364d 23int options = SO_ACCEPTCONN|SO_KEEPALIVE;
3f5b52bc 24struct sockaddr_in sin = { AF_INET };
a10a364d
BJ
25/*
26 * remote login server:
27 * remuser\0
28 * locuser\0
29 * terminal type\0
30 * data
31 */
32main(argc, argv)
33 int argc;
34 char **argv;
35{
36 union wait status;
37 int f, debug = 0;
38 struct sockaddr_in from;
3f5b52bc 39 struct servent *sp;
a10a364d 40
3f5b52bc
SL
41 sp = getservbyname("login", "tcp");
42 if (sp == 0) {
43 fprintf(stderr, "rlogind: tcp/rlogin: unknown service\n");
44 exit(1);
45 }
a10a364d
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 tt = open("/dev/tty", 2);
55 if (tt > 0) {
56 ioctl(tt, TIOCNOTTY, 0);
57 close(tt);
58 }
59 }
60#endif
cb2d476f 61 sin.sin_port = sp->s_port;
a10a364d 62 argc--, argv++;
c6c678f1 63 if (argc > 0 && !strcmp(argv[0], "-d")) {
3f5b52bc
SL
64 int port = atoi(argv[0]);
65
66 if (port < 0) {
67 fprintf(stderr, "%s: bad port #\n", argv[0]);
68 exit(1);
69 }
cb2d476f 70 sin.sin_port = htons((u_short)port);
3f5b52bc
SL
71 argv++, argc--;
72 }
85b11450 73 f = socket(AF_INET, SOCK_STREAM, 0, 0);
c6c678f1
SL
74 if (f < 0) {
75 perror("rlogind: socket");
76 exit(1);
77 }
78 if (bind(f, &sin, sizeof (sin), 0) < 0) {
79 perror("rlogind: bind");
80 exit(1);
81 }
82 listen(f, 10);
a10a364d 83 for (;;) {
c6c678f1
SL
84 int s, len = sizeof (from);
85
86 s = accept(f, &from, &len, 0);
87 if (s < 0) {
82c973f2 88 perror("rlogind: accept");
a10a364d
BJ
89 sleep(1);
90 continue;
91 }
92 if (fork() == 0)
c6c678f1
SL
93 doit(s, &from);
94 close(s);
a10a364d
BJ
95 while (wait3(status, WNOHANG, 0) > 0)
96 continue;
97 }
98}
99
100char locuser[32], remuser[32];
101char buf[BUFSIZ];
102int child;
103int cleanup();
104int netf;
105extern errno;
106char *line;
107
108doit(f, fromp)
109 int f;
110 struct sockaddr_in *fromp;
111{
3f5b52bc 112 char c;
82c973f2 113 int i, p, cc, t, pid;
a10a364d 114 int stop = TIOCPKT_DOSTOP;
3f5b52bc 115 register struct hostent *hp;
a10a364d
BJ
116
117 alarm(60);
118 read(f, &c, 1);
119 if (c != 0)
120 exit(1);
121 alarm(0);
cb2d476f 122 fromp->sin_port = htons((u_short)fromp->sin_port);
3f5b52bc
SL
123 hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr),
124 fromp->sin_family);
82c973f2
SL
125 if (hp == 0)
126 fatal(f, "Host name for your address unknown");
a10a364d
BJ
127 if (fromp->sin_family != AF_INET ||
128 fromp->sin_port >= IPPORT_RESERVED ||
82c973f2
SL
129 hp == 0)
130 fatal(f, "Permission denied");
a10a364d
BJ
131 write(f, "", 1);
132 for (c = 'p'; c <= 's'; c++) {
133 struct stat stb;
134 line = "/dev/ptyXX";
135 line[strlen("/dev/pty")] = c;
136 line[strlen("/dev/ptyp")] = '0';
137 if (stat(line, &stb) < 0)
138 break;
139 for (i = 0; i < 16; i++) {
140 line[strlen("/dev/ptyp")] = "0123456789abcdef"[i];
141 p = open(line, 2);
142 if (p > 0)
143 goto gotpty;
144 }
145 }
82c973f2
SL
146 fatal(f, "All network ports in use");
147 /*NOTREACHED*/
a10a364d
BJ
148gotpty:
149 dup2(f, 0);
150 line[strlen("/dev/")] = 't';
151#ifdef DEBUG
152 { int tt = open("/dev/tty", 2);
153 if (tt > 0) {
154 ioctl(tt, TIOCNOTTY, 0);
155 close(tt);
156 }
157 }
158#endif
159 t = open(line, 2);
82c973f2
SL
160 if (t < 0)
161 fatalperror(f, line, errno);
a10a364d
BJ
162 { struct sgttyb b;
163 gtty(t, &b); b.sg_flags = RAW|ANYP; stty(t, &b);
164 }
82c973f2
SL
165 pid = fork();
166 if (pid < 0)
167 fatalperror(f, "", errno);
168 if (pid) {
a10a364d
BJ
169 char pibuf[1024], fibuf[1024], *pbp, *fbp;
170 int pcc = 0, fcc = 0, on = 1;
171/* FILE *console = fopen("/dev/console", "w"); */
172/* setbuf(console, 0); */
173
174/* fprintf(console, "f %d p %d\r\n", f, p); */
175 ioctl(f, FIONBIO, &on);
176 ioctl(p, FIONBIO, &on);
177 ioctl(p, TIOCPKT, &on);
178 signal(SIGTSTP, SIG_IGN);
179 sigset(SIGCHLD, cleanup);
180 for (;;) {
181 int ibits = 0, obits = 0;
82c973f2
SL
182
183 if (fcc)
184 obits |= (1<<p);
185 else
186 ibits |= (1<<f);
a10a364d 187 if (pcc >= 0)
82c973f2
SL
188 if (pcc)
189 obits |= (1<<f);
190 else
191 ibits |= (1<<p);
192 if (fcc < 0 && pcc < 0)
193 break;
a10a364d 194/* fprintf(console, "ibits from %d obits from %d\r\n", ibits, obits); */
c6c678f1 195 select(16, &ibits, &obits, 0, 0, 0);
a10a364d
BJ
196/* fprintf(console, "ibits %d obits %d\r\n", ibits, obits); */
197 if (ibits == 0 && obits == 0) {
198 sleep(5);
199 continue;
200 }
201 if (ibits & (1<<f)) {
202 fcc = read(f, fibuf, sizeof (fibuf));
203/* fprintf(console, "%d from f\r\n", fcc); */
204 if (fcc < 0 && errno == EWOULDBLOCK)
205 fcc = 0;
206 else {
207 if (fcc <= 0)
208 break;
209 fbp = fibuf;
210 }
211 }
212 if (ibits & (1<<p)) {
213 pcc = read(p, pibuf, sizeof (pibuf));
214/* fprintf(console, "%d from p, buf[0] %x, errno %d\r\n", pcc, buf[0], errno); */
215 pbp = pibuf;
216 if (pcc < 0 && errno == EWOULDBLOCK)
217 pcc = 0;
218 else if (pcc <= 0)
219 pcc = -1;
220 else if (pibuf[0] == 0)
221 pbp++, pcc--;
222 else {
223 if (pibuf[0]&(TIOCPKT_FLUSHWRITE|
224 TIOCPKT_NOSTOP|
225 TIOCPKT_DOSTOP)) {
226 int nstop = pibuf[0] &
227 (TIOCPKT_NOSTOP|
228 TIOCPKT_DOSTOP);
229 if (nstop)
230 stop = nstop;
231 pibuf[0] |= nstop;
c6c678f1 232 send(f,&pibuf[0],1,SOF_OOB);
a10a364d
BJ
233 }
234 pcc = 0;
235 }
236 }
237 if ((obits & (1<<f)) && pcc > 0) {
238 cc = write(f, pbp, pcc);
239/* fprintf(console, "%d of %d to f\r\n", cc, pcc); */
240 if (cc > 0) {
241 pcc -= cc;
242 pbp += cc;
243 }
244 }
245 if ((obits & (1<<p)) && fcc > 0) {
246 cc = write(p, fbp, fcc);
247/* fprintf(console, "%d of %d to p\r\n", cc, fcc); */
248 if (cc > 0) {
249 fcc -= cc;
250 fbp += cc;
251 }
252 }
253 }
254 cleanup();
255 }
256 close(f);
257 close(p);
258 dup2(t, 0);
259 dup2(t, 1);
260 dup2(t, 2);
261 close(t);
3f5b52bc 262 execl("/bin/login", "login", "-r", hp->h_name, 0);
82c973f2
SL
263 fatalperror(2, "/bin/login", errno);
264 /*NOTREACHED*/
a10a364d
BJ
265}
266
267cleanup()
268{
a10a364d
BJ
269
270 rmut();
dd83e8ac 271 vhangup(); /* XXX */
ff24c640 272 shutdown(netf, 2);
a10a364d
BJ
273 kill(0, SIGKILL);
274 exit(1);
275}
276
82c973f2
SL
277fatal(f, msg)
278 int f;
279 char *msg;
280{
281 char buf[BUFSIZ];
282
283 buf[0] = '\01'; /* error indicator */
284 (void) sprintf(buf + 1, "rlogind: %s.\n", msg);
285 (void) write(f, buf, strlen(buf));
286 exit(1);
287}
288
289fatalperror(f, msg, errno)
290 int f;
291 char *msg;
292 int errno;
293{
294 char buf[BUFSIZ];
295 extern char *sys_errlist[];
296
297 (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]);
298 fatal(f, buf);
299}
300
a10a364d
BJ
301#include <utmp.h>
302
303struct utmp wtmp;
304char wtmpf[] = "/usr/adm/wtmp";
305char utmp[] = "/etc/utmp";
306#define SCPYN(a, b) strncpy(a, b, sizeof(a))
307#define SCMPN(a, b) strncmp(a, b, sizeof(a))
308
309rmut()
310{
311 register f;
312 int found = 0;
313
314 f = open(utmp, 2);
315 if (f >= 0) {
316 while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) {
317 if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0)
318 continue;
319 lseek(f, -(long)sizeof(wtmp), 1);
320 SCPYN(wtmp.ut_name, "");
321 time(&wtmp.ut_time);
322 write(f, (char *)&wtmp, sizeof(wtmp));
323 found++;
324 }
325 close(f);
326 }
327 if (found) {
328 f = open(wtmpf, 1);
329 if (f >= 0) {
330 SCPYN(wtmp.ut_line, line+5);
331 SCPYN(wtmp.ut_name, "");
332 time(&wtmp.ut_time);
333 lseek(f, (long)0, 2);
334 write(f, (char *)&wtmp, sizeof(wtmp));
335 close(f);
336 }
337 }
338 chmod(line, 0666);
339 chown(line, 0, 0);
340 line[strlen("/dev/")] = 'p';
341 chmod(line, 0666);
342 chown(line, 0, 0);
343}