Fix for Cray UNICOS sessions
[unix-history] / usr / src / libexec / telnetd / sys_term.c
CommitLineData
ea139302
PB
1/*
2 * Copyright (c) 1989 Regents of the University of California.
3 * All rights reserved.
4 *
836fe169 5 * %sccs.include.redist.c%
ea139302
PB
6 */
7
8#ifndef lint
0163123f 9static char sccsid[] = "@(#)sys_term.c 5.16 (Berkeley) %G%";
ea139302
PB
10#endif /* not lint */
11
12#include "telnetd.h"
13#include "pathnames.h"
14
1af3d848
DB
15#if defined(AUTHENTICATE)
16#include <libtelnet/auth.h>
17#endif
18
ea139302
PB
19#ifdef NEWINIT
20#include <initreq.h>
21#else /* NEWINIT*/
22#include <utmp.h>
23struct utmp wtmp;
24
25# ifndef CRAY
26char wtmpf[] = "/usr/adm/wtmp";
27char utmpf[] = "/etc/utmp";
28# else /* CRAY */
29char wtmpf[] = "/etc/wtmp";
1af3d848
DB
30#include <tmpdir.h>
31#include <sys/wait.h>
ea139302
PB
32# endif /* CRAY */
33#endif /* NEWINIT */
34
35#define SCPYN(a, b) (void) strncpy(a, b, sizeof(a))
36#define SCMPN(a, b) strncmp(a, b, sizeof(a))
37
4a8a7128
PB
38#ifdef STREAMS
39#include <sys/stream.h>
40#endif
ea139302
PB
41#include <sys/tty.h>
42#ifdef t_erase
43#undef t_erase
44#undef t_kill
45#undef t_intrc
46#undef t_quitc
47#undef t_startc
48#undef t_stopc
49#undef t_eofc
50#undef t_brkc
51#undef t_suspc
52#undef t_dsuspc
53#undef t_rprntc
54#undef t_flushc
55#undef t_werasc
56#undef t_lnextc
57#endif
58
4a8a7128
PB
59#if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC)
60# define EXTPROC 0400
61#endif
62
ea139302
PB
63#ifndef USE_TERMIO
64struct termbuf {
65 struct sgttyb sg;
66 struct tchars tc;
67 struct ltchars ltc;
68 int state;
69 int lflags;
70} termbuf, termbuf2;
2c9c7136
PB
71# define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val)
72# define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val)
1af3d848
DB
73# define cfgetospeed(tp) (tp)->sg.sg_ospeed
74# define cfgetispeed(tp) (tp)->sg.sg_ispeed
ea139302 75#else /* USE_TERMIO */
ea139302
PB
76# ifdef SYSV_TERMIO
77# define termios termio
78# endif
2c9c7136 79# ifndef TCSANOW
4a8a7128 80# ifdef TCSETS
2c9c7136
PB
81# define TCSANOW TCSETS
82# define TCSADRAIN TCSETSW
1af3d848 83# define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
4a8a7128 84# else
2c9c7136
PB
85# ifdef TCSETA
86# define TCSANOW TCSETA
87# define TCSADRAIN TCSETAW
1af3d848 88# define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
2c9c7136
PB
89# else
90# define TCSANOW TIOCSETA
91# define TCSADRAIN TIOCSETAW
1af3d848 92# define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
2c9c7136 93# endif
4a8a7128 94# endif
2c9c7136
PB
95# define tcsetattr(f, a, t) ioctl(f, a, t)
96# define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \
97 (tp)->c_cflag |= (val)
1af3d848 98# define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
2c9c7136
PB
99# ifdef CIBAUD
100# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \
101 (tp)->c_cflag |= ((val)<<IBSHIFT)
1af3d848 102# define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT)
2c9c7136
PB
103# else
104# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \
105 (tp)->c_cflag |= (val)
1af3d848 106# define cfgetispeed(tp) ((tp)->c_cflag & CBAUD)
2c9c7136
PB
107# endif
108# endif /* TCSANOW */
ea139302
PB
109struct termios termbuf, termbuf2; /* pty control structure */
110#endif /* USE_TERMIO */
111
112/*
113 * init_termbuf()
114 * copy_termbuf(cp)
115 * set_termbuf()
116 *
117 * These three routines are used to get and set the "termbuf" structure
118 * to and from the kernel. init_termbuf() gets the current settings.
119 * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
120 * set_termbuf() writes the structure into the kernel.
121 */
122
1af3d848 123 void
ea139302
PB
124init_termbuf()
125{
126#ifndef USE_TERMIO
127 (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
128 (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
129 (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
130# ifdef TIOCGSTATE
131 (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
132# endif
133#else
4f73d56c 134 (void) tcgetattr(pty, &termbuf);
ea139302
PB
135#endif
136 termbuf2 = termbuf;
137}
138
139#if defined(LINEMODE) && defined(TIOCPKT_IOCTL)
1af3d848 140 void
ea139302 141copy_termbuf(cp, len)
1af3d848
DB
142 char *cp;
143 int len;
ea139302
PB
144{
145 if (len > sizeof(termbuf))
146 len = sizeof(termbuf);
147 bcopy(cp, (char *)&termbuf, len);
148 termbuf2 = termbuf;
149}
150#endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
151
1af3d848 152 void
ea139302
PB
153set_termbuf()
154{
155 /*
156 * Only make the necessary changes.
157 */
158#ifndef USE_TERMIO
159 if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg)))
2c9c7136 160 (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg);
ea139302
PB
161 if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc)))
162 (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
163 if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
164 sizeof(termbuf.ltc)))
165 (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
166 if (termbuf.lflags != termbuf2.lflags)
167 (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
168#else /* USE_TERMIO */
169 if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
1af3d848 170 (void) tcsetattr(pty, TCSANOW, &termbuf);
ed8f31c1 171# if defined(CRAY2) && defined(UNCIOS5)
ea139302
PB
172 needtermstat = 1;
173# endif
174#endif /* USE_TERMIO */
175}
176
177
178/*
179 * spcset(func, valp, valpp)
180 *
181 * This function takes various special characters (func), and
182 * sets *valp to the current value of that character, and
183 * *valpp to point to where in the "termbuf" structure that
184 * value is kept.
185 *
186 * It returns the SLC_ level of support for this function.
187 */
188
189#ifndef USE_TERMIO
1af3d848 190 int
ea139302 191spcset(func, valp, valpp)
1af3d848
DB
192 int func;
193 cc_t *valp;
194 cc_t **valpp;
ea139302
PB
195{
196 switch(func) {
197 case SLC_EOF:
198 *valp = termbuf.tc.t_eofc;
ed8f31c1 199 *valpp = (cc_t *)&termbuf.tc.t_eofc;
ea139302
PB
200 return(SLC_VARIABLE);
201 case SLC_EC:
202 *valp = termbuf.sg.sg_erase;
ed8f31c1 203 *valpp = (cc_t *)&termbuf.sg.sg_erase;
ea139302
PB
204 return(SLC_VARIABLE);
205 case SLC_EL:
206 *valp = termbuf.sg.sg_kill;
ed8f31c1 207 *valpp = (cc_t *)&termbuf.sg.sg_kill;
ea139302
PB
208 return(SLC_VARIABLE);
209 case SLC_IP:
210 *valp = termbuf.tc.t_intrc;
ed8f31c1 211 *valpp = (cc_t *)&termbuf.tc.t_intrc;
ea139302
PB
212 return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
213 case SLC_ABORT:
214 *valp = termbuf.tc.t_quitc;
ed8f31c1 215 *valpp = (cc_t *)&termbuf.tc.t_quitc;
ea139302
PB
216 return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
217 case SLC_XON:
218 *valp = termbuf.tc.t_startc;
ed8f31c1 219 *valpp = (cc_t *)&termbuf.tc.t_startc;
ea139302
PB
220 return(SLC_VARIABLE);
221 case SLC_XOFF:
222 *valp = termbuf.tc.t_stopc;
ed8f31c1 223 *valpp = (cc_t *)&termbuf.tc.t_stopc;
ea139302
PB
224 return(SLC_VARIABLE);
225 case SLC_AO:
226 *valp = termbuf.ltc.t_flushc;
ed8f31c1 227 *valpp = (cc_t *)&termbuf.ltc.t_flushc;
ea139302
PB
228 return(SLC_VARIABLE);
229 case SLC_SUSP:
230 *valp = termbuf.ltc.t_suspc;
ed8f31c1 231 *valpp = (cc_t *)&termbuf.ltc.t_suspc;
ea139302
PB
232 return(SLC_VARIABLE);
233 case SLC_EW:
234 *valp = termbuf.ltc.t_werasc;
ed8f31c1 235 *valpp = (cc_t *)&termbuf.ltc.t_werasc;
ea139302
PB
236 return(SLC_VARIABLE);
237 case SLC_RP:
238 *valp = termbuf.ltc.t_rprntc;
ed8f31c1 239 *valpp = (cc_t *)&termbuf.ltc.t_rprntc;
ea139302
PB
240 return(SLC_VARIABLE);
241 case SLC_LNEXT:
242 *valp = termbuf.ltc.t_lnextc;
ed8f31c1
PB
243 *valpp = (cc_t *)&termbuf.ltc.t_lnextc;
244 return(SLC_VARIABLE);
245 case SLC_FORW1:
246 *valp = termbuf.tc.t_brkc;
247 *valpp = (cc_t *)&termbuf.ltc.t_lnextc;
ea139302
PB
248 return(SLC_VARIABLE);
249 case SLC_BRK:
250 case SLC_SYNCH:
251 case SLC_AYT:
252 case SLC_EOR:
ed8f31c1
PB
253 *valp = (cc_t)0;
254 *valpp = (cc_t *)0;
ea139302
PB
255 return(SLC_DEFAULT);
256 default:
ed8f31c1
PB
257 *valp = (cc_t)0;
258 *valpp = (cc_t *)0;
ea139302
PB
259 return(SLC_NOSUPPORT);
260 }
261}
262
263#else /* USE_TERMIO */
264
1af3d848 265 int
ea139302 266spcset(func, valp, valpp)
1af3d848
DB
267 int func;
268 cc_t *valp;
269 cc_t **valpp;
ea139302 270{
053fd49d
PB
271
272#define setval(a, b) *valp = termbuf.c_cc[a]; \
273 *valpp = &termbuf.c_cc[a]; \
274 return(b);
ed8f31c1 275#define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
053fd49d 276
ea139302
PB
277 switch(func) {
278 case SLC_EOF:
053fd49d 279 setval(VEOF, SLC_VARIABLE);
ea139302 280 case SLC_EC:
053fd49d 281 setval(VERASE, SLC_VARIABLE);
ea139302 282 case SLC_EL:
053fd49d 283 setval(VKILL, SLC_VARIABLE);
ea139302 284 case SLC_IP:
053fd49d 285 setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
ea139302 286 case SLC_ABORT:
053fd49d 287 setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
ea139302 288 case SLC_XON:
053fd49d
PB
289#ifdef VSTART
290 setval(VSTART, SLC_VARIABLE);
291#else
292 defval(0x13);
293#endif
ea139302 294 case SLC_XOFF:
053fd49d
PB
295#ifdef VSTOP
296 setval(VSTOP, SLC_VARIABLE);
297#else
298 defval(0x11);
299#endif
ea139302 300 case SLC_EW:
053fd49d
PB
301#ifdef VWERASE
302 setval(VWERASE, SLC_VARIABLE);
303#else
304 defval(0);
305#endif
ea139302 306 case SLC_RP:
053fd49d
PB
307#ifdef VREPRINT
308 setval(VREPRINT, SLC_VARIABLE);
309#else
310 defval(0);
311#endif
ea139302 312 case SLC_LNEXT:
053fd49d
PB
313#ifdef VLNEXT
314 setval(VLNEXT, SLC_VARIABLE);
315#else
316 defval(0);
317#endif
318 case SLC_AO:
2c9c7136
PB
319#if !defined(VDISCARD) && defined(VFLUSHO)
320# define VDISCARD VFLUSHO
321#endif
322#ifdef VDISCARD
323 setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
053fd49d
PB
324#else
325 defval(0);
326#endif
327 case SLC_SUSP:
328#ifdef VSUSP
329 setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
330#else
331 defval(0);
332#endif
ed8f31c1
PB
333#ifdef VEOL
334 case SLC_FORW1:
335 setval(VEOL, SLC_VARIABLE);
336#endif
337#ifdef VEOL2
338 case SLC_FORW2:
339 setval(VEOL2, SLC_VARIABLE);
340#endif
2c9c7136
PB
341 case SLC_AYT:
342#ifdef VSTATUS
343 setval(VSTATUS, SLC_VARIABLE);
344#else
345 defval(0);
346#endif
053fd49d 347
ea139302
PB
348 case SLC_BRK:
349 case SLC_SYNCH:
ea139302 350 case SLC_EOR:
053fd49d
PB
351 defval(0);
352
ea139302
PB
353 default:
354 *valp = 0;
355 *valpp = 0;
356 return(SLC_NOSUPPORT);
357 }
358}
359#endif /* USE_TERMIO */
360
ed8f31c1
PB
361#ifdef CRAY
362/*
363 * getnpty()
364 *
365 * Return the number of pty's configured into the system.
366 */
1af3d848 367 int
ed8f31c1
PB
368getnpty()
369{
370#ifdef _SC_CRAY_NPTY
1af3d848
DB
371 int numptys;
372
373 if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1)
374 return numptys;
375 else
ed8f31c1 376#endif /* _SC_CRAY_NPTY */
1af3d848 377 return 128;
ed8f31c1
PB
378}
379#endif /* CRAY */
380
2c9c7136 381#ifndef convex
ea139302
PB
382/*
383 * getpty()
384 *
385 * Allocate a pty. As a side effect, the external character
386 * array "line" contains the name of the slave side.
387 *
388 * Returns the file descriptor of the opened pty.
389 */
2c9c7136 390#ifndef __GNUC__
ea139302 391char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
2c9c7136
PB
392#else
393static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
394char *line = Xline;
395#endif
396#ifdef CRAY
397char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
398#endif /* CRAY */
ea139302 399
1af3d848 400 int
ea139302
PB
401getpty()
402{
403 register int p;
404#ifndef CRAY
405 register char c, *p1, *p2;
406 register int i;
407
408 (void) sprintf(line, "/dev/ptyXX");
409 p1 = &line[8];
410 p2 = &line[9];
411
412 for (c = 'p'; c <= 's'; c++) {
413 struct stat stb;
414
415 *p1 = c;
416 *p2 = '0';
417 if (stat(line, &stb) < 0)
418 break;
419 for (i = 0; i < 16; i++) {
420 *p2 = "0123456789abcdef"[i];
421 p = open(line, 2);
422 if (p > 0) {
423 line[5] = 't';
424 return(p);
425 }
426 }
427 }
428#else /* CRAY */
429 register int npty;
430 extern lowpty, highpty;
2c9c7136 431 struct stat sb;
ea139302
PB
432
433 for (npty = lowpty; npty <= highpty; npty++) {
2c9c7136
PB
434 (void) sprintf(myline, "/dev/pty/%03d", npty);
435 p = open(myline, 2);
ea139302
PB
436 if (p < 0)
437 continue;
438 (void) sprintf(line, "/dev/ttyp%03d", npty);
2c9c7136
PB
439 /*
440 * Here are some shenanigans to make sure that there
441 * are no listeners lurking on the line.
442 */
443 if(stat(line, &sb) < 0) {
444 (void) close(p);
445 continue;
446 }
447 if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
448 chown(line, 0, 0);
449 chmod(line, 0600);
450 (void)close(p);
451 p = open(myline, 2);
452 if (p < 0)
453 continue;
454 }
455 /*
456 * Now it should be safe...check for accessability.
457 */
ea139302
PB
458 if (access(line, 6) == 0)
459 return(p);
460 else {
461 /* no tty side to pty so skip it */
462 (void) close(p);
463 }
464 }
465#endif /* CRAY */
466 return(-1);
467}
2c9c7136 468#endif /* convex */
ea139302
PB
469
470#ifdef LINEMODE
471/*
472 * tty_flowmode() Find out if flow control is enabled or disabled.
473 * tty_linemode() Find out if linemode (external processing) is enabled.
474 * tty_setlinemod(on) Turn on/off linemode.
475 * tty_isecho() Find out if echoing is turned on.
476 * tty_setecho(on) Enable/disable character echoing.
477 * tty_israw() Find out if terminal is in RAW mode.
478 * tty_binaryin(on) Turn on/off BINARY on input.
479 * tty_binaryout(on) Turn on/off BINARY on output.
480 * tty_isediting() Find out if line editing is enabled.
481 * tty_istrapsig() Find out if signal trapping is enabled.
482 * tty_setedit(on) Turn on/off line editing.
483 * tty_setsig(on) Turn on/off signal trapping.
4a8a7128
PB
484 * tty_issofttab() Find out if tab expansion is enabled.
485 * tty_setsofttab(on) Turn on/off soft tab expansion.
486 * tty_islitecho() Find out if typed control chars are echoed literally
487 * tty_setlitecho() Turn on/off literal echo of control chars
ea139302
PB
488 * tty_tspeed(val) Set transmit speed to val.
489 * tty_rspeed(val) Set receive speed to val.
490 */
491
1af3d848 492 int
ea139302
PB
493tty_flowmode()
494{
495#ifndef USE_TERMIO
1af3d848 496 return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0);
ea139302
PB
497#else
498 return(termbuf.c_iflag & IXON ? 1 : 0);
499#endif
500}
501
2c9c7136
PB
502#ifdef convex
503static int linestate;
504#endif
505
1af3d848 506 int
ea139302
PB
507tty_linemode()
508{
2c9c7136 509#ifndef convex
ea139302
PB
510#ifndef USE_TERMIO
511 return(termbuf.state & TS_EXTPROC);
512#else
513 return(termbuf.c_lflag & EXTPROC);
514#endif
2c9c7136
PB
515#else
516 return(linestate);
517#endif
ea139302
PB
518}
519
1af3d848 520 void
ea139302 521tty_setlinemode(on)
1af3d848 522 int on;
ea139302
PB
523{
524#ifdef TIOCEXT
2c9c7136
PB
525# ifndef convex
526 set_termbuf();
527# else
528 linestate = on;
529# endif
ea139302 530 (void) ioctl(pty, TIOCEXT, (char *)&on);
2c9c7136
PB
531# ifndef convex
532 init_termbuf();
533# endif
ea139302 534#else /* !TIOCEXT */
2c9c7136 535# ifdef EXTPROC
ea139302
PB
536 if (on)
537 termbuf.c_lflag |= EXTPROC;
538 else
539 termbuf.c_lflag &= ~EXTPROC;
2c9c7136 540# endif
ea139302
PB
541#endif /* TIOCEXT */
542}
543
1af3d848 544 int
ea139302
PB
545tty_isecho()
546{
547#ifndef USE_TERMIO
548 return (termbuf.sg.sg_flags & ECHO);
549#else
550 return (termbuf.c_lflag & ECHO);
551#endif
552}
553#endif /* LINEMODE */
554
1af3d848 555 void
ea139302 556tty_setecho(on)
1af3d848 557 int on;
ea139302
PB
558{
559#ifndef USE_TERMIO
560 if (on)
561 termbuf.sg.sg_flags |= ECHO|CRMOD;
562 else
563 termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
564#else
565 if (on)
566 termbuf.c_lflag |= ECHO;
567 else
568 termbuf.c_lflag &= ~ECHO;
569#endif
570}
571
572#if defined(LINEMODE) && defined(KLUDGELINEMODE)
1af3d848 573 int
ea139302
PB
574tty_israw()
575{
576#ifndef USE_TERMIO
577 return(termbuf.sg.sg_flags & RAW);
578#else
579 return(!(termbuf.c_lflag & ICANON));
580#endif
581}
582#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
583
1af3d848 584 void
ea139302 585tty_binaryin(on)
1af3d848 586 int on;
ea139302
PB
587{
588#ifndef USE_TERMIO
589 if (on)
590 termbuf.lflags |= LPASS8;
591 else
592 termbuf.lflags &= ~LPASS8;
593#else
594 if (on) {
1af3d848 595 termbuf.c_iflag &= ~ISTRIP;
ea139302 596 } else {
1af3d848 597 termbuf.c_iflag |= ISTRIP;
ea139302
PB
598 }
599#endif
600}
601
1af3d848 602 void
ea139302 603tty_binaryout(on)
1af3d848 604 int on;
ea139302
PB
605{
606#ifndef USE_TERMIO
607 if (on)
608 termbuf.lflags |= LLITOUT;
609 else
610 termbuf.lflags &= ~LLITOUT;
611#else
612 if (on) {
613 termbuf.c_cflag &= ~(CSIZE|PARENB);
614 termbuf.c_cflag |= CS8;
615 termbuf.c_oflag &= ~OPOST;
616 } else {
617 termbuf.c_cflag &= ~CSIZE;
618 termbuf.c_cflag |= CS7|PARENB;
619 termbuf.c_oflag |= OPOST;
620 }
621#endif
622}
623
1af3d848 624 int
ea139302
PB
625tty_isbinaryin()
626{
627#ifndef USE_TERMIO
628 return(termbuf.lflags & LPASS8);
629#else
053fd49d 630 return(!(termbuf.c_iflag & ISTRIP));
ea139302
PB
631#endif
632}
633
1af3d848 634 int
ea139302
PB
635tty_isbinaryout()
636{
637#ifndef USE_TERMIO
638 return(termbuf.lflags & LLITOUT);
639#else
053fd49d 640 return(!(termbuf.c_oflag&OPOST));
ea139302
PB
641#endif
642}
643
644#ifdef LINEMODE
1af3d848 645 int
ea139302
PB
646tty_isediting()
647{
648#ifndef USE_TERMIO
649 return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
650#else
651 return(termbuf.c_lflag & ICANON);
652#endif
653}
654
1af3d848 655 int
ea139302
PB
656tty_istrapsig()
657{
658#ifndef USE_TERMIO
659 return(!(termbuf.sg.sg_flags&RAW));
660#else
661 return(termbuf.c_lflag & ISIG);
662#endif
663}
664
1af3d848 665 void
ea139302 666tty_setedit(on)
1af3d848 667 int on;
ea139302
PB
668{
669#ifndef USE_TERMIO
670 if (on)
671 termbuf.sg.sg_flags &= ~CBREAK;
672 else
673 termbuf.sg.sg_flags |= CBREAK;
674#else
675 if (on)
676 termbuf.c_lflag |= ICANON;
677 else
678 termbuf.c_lflag &= ~ICANON;
679#endif
680}
681
1af3d848 682 void
ea139302 683tty_setsig(on)
1af3d848 684 int on;
ea139302
PB
685{
686#ifndef USE_TERMIO
687 if (on)
688 ;
689#else
690 if (on)
691 termbuf.c_lflag |= ISIG;
692 else
693 termbuf.c_lflag &= ~ISIG;
694#endif
695}
696#endif /* LINEMODE */
697
1af3d848 698 int
4a8a7128
PB
699tty_issofttab()
700{
701#ifndef USE_TERMIO
702 return (termbuf.sg.sg_flags & XTABS);
703#else
704# ifdef OXTABS
705 return (termbuf.c_oflag & OXTABS);
706# endif
707# ifdef TABDLY
708 return ((termbuf.c_oflag & TABDLY) == TAB3);
709# endif
710#endif
711}
712
1af3d848 713 void
4a8a7128 714tty_setsofttab(on)
1af3d848 715 int on;
4a8a7128
PB
716{
717#ifndef USE_TERMIO
718 if (on)
719 termbuf.sg.sg_flags |= XTABS;
720 else
721 termbuf.sg.sg_flags &= ~XTABS;
722#else
723 if (on) {
724# ifdef OXTABS
725 termbuf.c_oflag |= OXTABS;
726# endif
727# ifdef TABDLY
728 termbuf.c_oflag &= ~TABDLY;
729 termbuf.c_oflag |= TAB3;
730# endif
731 } else {
732# ifdef OXTABS
733 termbuf.c_oflag &= ~OXTABS;
734# endif
735# ifdef TABDLY
736 termbuf.c_oflag &= ~TABDLY;
737 termbuf.c_oflag |= TAB0;
738# endif
739 }
740#endif
741}
742
1af3d848 743 int
4a8a7128
PB
744tty_islitecho()
745{
746#ifndef USE_TERMIO
1af3d848 747 return (!(termbuf.lflags & LCTLECH));
4a8a7128
PB
748#else
749# ifdef ECHOCTL
750 return (!(termbuf.c_lflag & ECHOCTL));
751# endif
752# ifdef TCTLECH
753 return (!(termbuf.c_lflag & TCTLECH));
754# endif
755# if !defined(ECHOCTL) && !defined(TCTLECH)
756 return (0); /* assumes ctl chars are echoed '^x' */
757# endif
758#endif
759}
760
1af3d848 761 void
4a8a7128 762tty_setlitecho(on)
1af3d848 763 int on;
4a8a7128
PB
764{
765#ifndef USE_TERMIO
766 if (on)
1af3d848 767 termbuf.lflags &= ~LCTLECH;
4a8a7128 768 else
1af3d848 769 termbuf.lflags |= LCTLECH;
4a8a7128
PB
770#else
771# ifdef ECHOCTL
772 if (on)
773 termbuf.c_lflag &= ~ECHOCTL;
774 else
775 termbuf.c_lflag |= ECHOCTL;
776# endif
777# ifdef TCTLECH
778 if (on)
779 termbuf.c_lflag &= ~TCTLECH;
780 else
781 termbuf.c_lflag |= TCTLECH;
782# endif
783#endif
1af3d848
DB
784}
785
786 int
787tty_iscrnl()
788{
789#ifndef USE_TERMIO
790 return (termbuf.sg.sg_flags & CRMOD);
791#else
792 return (termbuf.c_iflag & ICRNL);
793#endif
4a8a7128
PB
794}
795
ea139302
PB
796/*
797 * A table of available terminal speeds
798 */
799struct termspeeds {
800 int speed;
801 int value;
802} termspeeds[] = {
803 { 0, B0 }, { 50, B50 }, { 75, B75 },
804 { 110, B110 }, { 134, B134 }, { 150, B150 },
805 { 200, B200 }, { 300, B300 }, { 600, B600 },
806 { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 },
807 { 4800, B4800 }, { 9600, B9600 }, { 19200, B9600 },
808 { 38400, B9600 }, { -1, B9600 }
809};
810
1af3d848 811 void
ea139302 812tty_tspeed(val)
1af3d848 813 int val;
ea139302
PB
814{
815 register struct termspeeds *tp;
816
817 for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
818 ;
2c9c7136 819 cfsetospeed(&termbuf, tp->value);
ea139302
PB
820}
821
1af3d848 822 void
ea139302 823tty_rspeed(val)
1af3d848 824 int val;
ea139302
PB
825{
826 register struct termspeeds *tp;
827
828 for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
829 ;
2c9c7136 830 cfsetispeed(&termbuf, tp->value);
ea139302
PB
831}
832
ed8f31c1 833#if defined(CRAY2) && defined(UNICOS5)
1af3d848 834 int
ea139302
PB
835tty_isnewmap()
836{
837 return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
838 !(termbuf.c_oflag & ONLRET));
839}
840#endif
841
842#ifdef CRAY
843# ifndef NEWINIT
844extern struct utmp wtmp;
845extern char wtmpf[];
846# else /* NEWINIT */
847int gotalarm;
1af3d848
DB
848
849 /* ARGSUSED */
850 void
ed8f31c1 851nologinproc(sig)
1af3d848 852 int sig;
ea139302
PB
853{
854 gotalarm++;
855}
856# endif /* NEWINIT */
857#endif /* CRAY */
858
1af3d848
DB
859#ifndef NEWINIT
860# ifdef CRAY
861extern void utmp_sig_init P((void));
862extern void utmp_sig_reset P((void));
863extern void utmp_sig_wait P((void));
864extern void utmp_sig_notify P((int));
865# endif
866#endif
867
ea139302
PB
868/*
869 * getptyslave()
870 *
871 * Open the slave side of the pty, and do any initialization
872 * that is necessary. The return value is a file descriptor
873 * for the slave side.
874 */
1af3d848 875 int
ea139302
PB
876getptyslave()
877{
878 register int t = -1;
879
2c9c7136
PB
880#if !defined(CRAY) || !defined(NEWINIT)
881# ifdef LINEMODE
1af3d848
DB
882 int waslm;
883# endif
884# ifdef TIOCGWINSZ
885 struct winsize ws;
886 extern int def_row, def_col;
887# endif
888 extern int def_tspeed, def_rspeed;
ea139302 889 /*
2c9c7136 890 * Opening the slave side may cause initilization of the
1af3d848
DB
891 * kernel tty structure. We need remember the state of
892 * if linemode was turned on
893 * terminal window size
894 * terminal speed
895 * so that we can re-set them if we need to.
ea139302 896 */
1af3d848
DB
897# ifdef LINEMODE
898 waslm = tty_linemode();
2c9c7136
PB
899# endif
900
901
902 /*
903 * Make sure that we don't have a controlling tty, and
904 * that we are the session (process group) leader.
905 */
906# ifdef TIOCNOTTY
ea139302
PB
907 t = open(_PATH_TTY, O_RDWR);
908 if (t >= 0) {
909 (void) ioctl(t, TIOCNOTTY, (char *)0);
910 (void) close(t);
911 }
2c9c7136 912# endif
ea139302 913
2c9c7136
PB
914
915# ifdef CRAY
916 /*
917 * Wait for our parent to get the utmp stuff to get done.
918 */
919 utmp_sig_wait();
920# endif
921
922 t = cleanopen(line);
ea139302
PB
923 if (t < 0)
924 fatalperror(net, line);
925
2c9c7136
PB
926 /*
927 * set up the tty modes as we like them to be.
928 */
ea139302 929 init_termbuf();
1af3d848
DB
930# ifdef TIOCGWINSZ
931 if (def_row || def_col) {
932 bzero((char *)&ws, sizeof(ws));
933 ws.ws_col = def_col;
934 ws.ws_row = def_row;
935 (void)ioctl(t, TIOCSWINSZ, (char *)&ws);
936 }
937# endif
2c9c7136
PB
938
939 /*
940 * Settings for sgtty based systems
941 */
942# ifndef USE_TERMIO
ed8f31c1 943 termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
2c9c7136
PB
944# endif /* USE_TERMIO */
945
946 /*
947 * Settings for UNICOS
948 */
949# ifdef CRAY
950 termbuf.c_oflag = OPOST|ONLCR|TAB3;
951 termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
952 termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
953 termbuf.c_cflag = EXTB|HUPCL|CS8;
954# endif
955
956 /*
957 * Settings for all other termios/termio based
958 * systems, other than 4.4BSD. In 4.4BSD the
959 * kernel does the initial terminal setup.
960 */
961# if defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43)
962# ifndef OXTABS
963# define OXTABS 0
964# endif
ea139302
PB
965 termbuf.c_lflag |= ECHO;
966 termbuf.c_oflag |= ONLCR|OXTABS;
967 termbuf.c_iflag |= ICRNL;
968 termbuf.c_iflag &= ~IXOFF;
2c9c7136 969# endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */
4557054d
DB
970 tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
971 tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
1af3d848
DB
972# ifdef LINEMODE
973 if (waslm)
974 tty_setlinemode(1);
975# endif /* LINEMODE */
2c9c7136
PB
976
977 /*
978 * Set the tty modes, and make this our controlling tty.
979 */
ea139302 980 set_termbuf();
2c9c7136
PB
981 if (login_tty(t) == -1)
982 fatalperror(net, "login_tty");
983#endif /* !defined(CRAY) || !defined(NEWINIT) */
984 if (net > 2)
985 (void) close(net);
986 if (pty > 2)
987 (void) close(pty);
988}
989
990#if !defined(CRAY) || !defined(NEWINIT)
991#ifndef O_NOCTTY
992#define O_NOCTTY 0
993#endif
994/*
995 * Open the specified slave side of the pty,
996 * making sure that we have a clean tty.
997 */
1af3d848 998 int
2c9c7136 999cleanopen(line)
1af3d848 1000 char *line;
2c9c7136
PB
1001{
1002 register int t;
1003
1004 /*
1005 * Make sure that other people can't open the
1006 * slave side of the connection.
1007 */
ea139302
PB
1008 (void) chown(line, 0, 0);
1009 (void) chmod(line, 0600);
2c9c7136
PB
1010
1011# if !defined(CRAY) && (BSD > 43)
1012 (void) revoke(line);
1013# endif
1014 t = open(line, O_RDWR|O_NOCTTY);
1015 if (t < 0)
1016 return(-1);
1017
1018 /*
1019 * Hangup anybody else using this ttyp, then reopen it for
1020 * ourselves.
1021 */
1022# if !defined(CRAY) && (BSD <= 43)
1023 (void) signal(SIGHUP, SIG_IGN);
1024 vhangup();
1025 (void) signal(SIGHUP, SIG_DFL);
1026 t = open(line, O_RDWR|O_NOCTTY);
1027 if (t < 0)
1028 return(-1);
1029# endif
1030# if defined(CRAY) && defined(TCVHUP)
1031 {
1032 register int i;
1033 (void) signal(SIGHUP, SIG_IGN);
1034 (void) ioctl(t, TCVHUP, (char *)0);
1035 (void) signal(SIGHUP, SIG_DFL);
1036 setpgrp();
1037 i = open(line, O_RDWR);
1038 if (i < 0)
1af3d848 1039 return(-1);
2c9c7136
PB
1040 (void) close(t);
1041 t = i;
1042 }
1043# endif /* defined(CRAY) && defined(TCVHUP) */
ea139302
PB
1044 return(t);
1045}
2c9c7136
PB
1046#endif /* !defined(CRAY) || !defined(NEWINIT) */
1047
1048#if BSD <= 43
1af3d848 1049 int
2c9c7136 1050login_tty(t)
1af3d848 1051 int t;
2c9c7136 1052{
2c9c7136
PB
1053 if (setsid() < 0)
1054 fatalperror(net, "setsid()");
2c9c7136
PB
1055# ifdef TIOCSCTTY
1056 if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
1057 fatalperror(net, "ioctl(sctty)");
0163123f
DB
1058# if defined(CRAY) && defined(SESS_CTTY) /* SESS_CTTY is in param.h */
1059 /*
1060 * Close the hard fd to /dev/ttypXXX, and re-open through
1061 * the indirect /dev/tty interface.
1062 */
1063 close(t);
1064 if ((t = open("/dev/tty", O_RDWR)) < 0)
1065 fatalperror(net, "open(/dev/tty)");
1066# endif
2c9c7136
PB
1067# else
1068 close(open(line, O_RDWR));
1069# endif
0163123f
DB
1070 if (t != 0)
1071 (void) dup2(t, 0);
1072 if (t != 1)
1073 (void) dup2(t, 1);
1074 if (t != 2)
1075 (void) dup2(t, 2);
1076 if (t > 2)
1077 close(t);
1af3d848 1078 return(0);
2c9c7136
PB
1079}
1080#endif /* BSD <= 43 */
ea139302
PB
1081
1082#ifdef NEWINIT
1083char *gen_id = "fe";
1084#endif
1085
1086/*
2c9c7136 1087 * startslave(host)
ea139302 1088 *
2c9c7136 1089 * Given a hostname, do whatever
ea139302
PB
1090 * is necessary to startup the login process on the slave side of the pty.
1091 */
1092
1093/* ARGSUSED */
1af3d848
DB
1094 void
1095startslave(host, autologin, autoname)
1096 char *host;
1097 int autologin;
1098 char *autoname;
ea139302
PB
1099{
1100 register int i;
1101 long time();
1af3d848
DB
1102 char name[256];
1103#ifdef NEWINIT
1104 extern char *ptyip;
1105 struct init_request request;
1106 void nologinproc();
1107 register int n;
1108#endif /* NEWINIT */
1109
1110#if defined(AUTHENTICATE)
1111 if (!autoname || !autoname[0])
1112 autologin = 0;
1113
1114 if (autologin < auth_level) {
1115 fatal(net, "Authorization failed");
1116 exit(1);
1117 }
1118#endif
ea139302
PB
1119
1120#ifndef NEWINIT
1121# ifdef CRAY
1122 utmp_sig_init();
1123# endif /* CRAY */
1124
1125 if ((i = fork()) < 0)
1126 fatalperror(net, "fork");
1127 if (i) {
1128# ifdef CRAY
1129 /*
1130 * Cray parent will create utmp entry for child and send
1131 * signal to child to tell when done. Child waits for signal
1132 * before doing anything important.
1133 */
1134 register int pid = i;
1af3d848 1135 void sigjob P((int));
ea139302
PB
1136
1137 setpgrp();
4a8a7128 1138 utmp_sig_reset(); /* reset handler to default */
ea139302
PB
1139 /*
1140 * Create utmp entry for child
1141 */
1142 (void) time(&wtmp.ut_time);
1143 wtmp.ut_type = LOGIN_PROCESS;
1144 wtmp.ut_pid = pid;
1145 SCPYN(wtmp.ut_user, "LOGIN");
1146 SCPYN(wtmp.ut_host, host);
1147 SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
1148 SCPYN(wtmp.ut_id, wtmp.ut_line+3);
1149 pututline(&wtmp);
1150 endutent();
1151 if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
1152 (void) write(i, (char *)&wtmp, sizeof(struct utmp));
1153 (void) close(i);
1154 }
1af3d848 1155 (void) signal(WJSIGNAL, sigjob);
ea139302
PB
1156 utmp_sig_notify(pid);
1157# endif /* CRAY */
ea139302 1158 } else {
2c9c7136 1159 getptyslave();
1af3d848 1160 start_login(host, autologin, autoname);
ea139302
PB
1161 /*NOTREACHED*/
1162 }
1163#else /* NEWINIT */
1164
ea139302
PB
1165 /*
1166 * Init will start up login process if we ask nicely. We only wait
1167 * for it to start up and begin normal telnet operation.
1168 */
1169 if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
1170 char tbuf[128];
1171 (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO);
1172 fatalperror(net, tbuf);
1173 }
1174 memset((char *)&request, 0, sizeof(request));
1175 request.magic = INIT_MAGIC;
1176 SCPYN(request.gen_id, gen_id);
1177 SCPYN(request.tty_id, &line[8]);
1178 SCPYN(request.host, host);
1af3d848 1179 SCPYN(request.term_type, terminaltype ? terminaltype : "network");
4a8a7128 1180#if !defined(UNICOS5)
ed8f31c1
PB
1181 request.signal = SIGCLD;
1182 request.pid = getpid();
1183#endif
4a8a7128
PB
1184#ifdef BFTPDAEMON
1185 /*
1186 * Are we working as the bftp daemon?
1187 */
1188 if (bftpd) {
1189 SCPYN(request.exec_name, BFTPPATH);
1190 }
1191#endif /* BFTPDAEMON */
ea139302
PB
1192 if (write(i, (char *)&request, sizeof(request)) < 0) {
1193 char tbuf[128];
1194 (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO);
1195 fatalperror(net, tbuf);
1196 }
1197 (void) close(i);
1198 (void) signal(SIGALRM, nologinproc);
1199 for (i = 0; ; i++) {
ed8f31c1 1200 char tbuf[128];
ea139302
PB
1201 alarm(15);
1202 n = read(pty, ptyip, BUFSIZ);
1203 if (i == 3 || n >= 0 || !gotalarm)
1204 break;
1205 gotalarm = 0;
ed8f31c1
PB
1206 sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line);
1207 (void) write(net, tbuf, strlen(tbuf));
ea139302
PB
1208 }
1209 if (n < 0 && gotalarm)
1210 fatal(net, "/etc/init didn't start login process");
1211 pcc += n;
1212 alarm(0);
1213 (void) signal(SIGALRM, SIG_DFL);
1214
ea139302
PB
1215 return;
1216#endif /* NEWINIT */
1217}
1218
ea139302 1219char *envinit[3];
4a8a7128
PB
1220extern char **environ;
1221
1af3d848 1222 void
4a8a7128
PB
1223init_env()
1224{
1225 extern char *getenv();
1226 char **envp;
1227
1228 envp = envinit;
1229 if (*envp = getenv("TZ"))
1230 *envp++ -= 3;
1231#ifdef CRAY
1232 else
1233 *envp++ = "TZ=GMT0";
1234#endif
1235 *envp = 0;
1236 environ = envinit;
1237}
1238
4a8a7128 1239#ifndef NEWINIT
ea139302
PB
1240
1241/*
2c9c7136 1242 * start_login(host)
ea139302
PB
1243 *
1244 * Assuming that we are now running as a child processes, this
1245 * function will turn us into the login process.
1246 */
1247
1af3d848
DB
1248 void
1249start_login(host, autologin, name)
1250 char *host;
1251 int autologin;
1252 char *name;
ea139302 1253{
4a8a7128
PB
1254 register char *cp;
1255 register char **argv;
1256 char **addarg();
ea139302 1257
ea139302
PB
1258 /*
1259 * -h : pass on name of host.
1260 * WARNING: -h is accepted by login if and only if
1261 * getuid() == 0.
1262 * -p : don't clobber the environment (so terminal type stays set).
1af3d848
DB
1263 *
1264 * -f : force this login, he has already been authenticated
ea139302 1265 */
4a8a7128
PB
1266 argv = addarg(0, "login");
1267 argv = addarg(argv, "-h");
1268 argv = addarg(argv, host);
1af3d848 1269#if !defined(NO_LOGIN_P)
4a8a7128
PB
1270 argv = addarg(argv, "-p");
1271#endif
1272#ifdef BFTPDAEMON
1273 /*
1274 * Are we working as the bftp daemon? If so, then ask login
1275 * to start bftp instead of shell.
1276 */
1277 if (bftpd) {
1278 argv = addarg(argv, "-e");
1279 argv = addarg(argv, BFTPPATH);
1280 } else
1af3d848
DB
1281#endif
1282#if defined (SecurID)
1283 /*
1284 * don't worry about the -f that might get sent.
1285 * A -s is supposed to override it anyhow.
1286 */
1287 if (require_SecurID)
1288 argv = addarg(argv, "-s");
1289#endif
1290#if defined (AUTHENTICATE)
1291 if (auth_level >= 0 && autologin == AUTH_VALID) {
1292# if !defined(NO_LOGIN_F)
1293 argv = addarg(argv, "-f");
1294# endif
1295 argv = addarg(argv, name);
1296 } else
4a8a7128
PB
1297#endif
1298 if (getenv("USER")) {
1299 argv = addarg(argv, getenv("USER"));
1af3d848
DB
1300#if defined(CRAY) && defined(NO_LOGIN_P)
1301 {
1302 register char **cpp;
1303 for (cpp = environ; *cpp; cpp++)
1304 argv = addarg(argv, *cpp);
1305 }
ea139302 1306#endif
1af3d848
DB
1307 }
1308 closelog();
4a8a7128
PB
1309 execv(_PATH_LOGIN, argv);
1310
ea139302
PB
1311 syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN);
1312 fatalperror(net, _PATH_LOGIN);
1313 /*NOTREACHED*/
1314}
4a8a7128 1315
1af3d848 1316 char **
4a8a7128 1317addarg(argv, val)
1af3d848
DB
1318 register char **argv;
1319 register char *val;
4a8a7128
PB
1320{
1321 register char **cpp;
4a8a7128
PB
1322
1323 if (argv == NULL) {
1324 /*
1325 * 10 entries, a leading length, and a null
1326 */
1327 argv = (char **)malloc(sizeof(*argv) * 12);
1328 if (argv == NULL)
1329 return(NULL);
1330 *argv++ = (char *)10;
1331 *argv = (char *)0;
1332 }
1333 for (cpp = argv; *cpp; cpp++)
1334 ;
1335 if (cpp == &argv[(int)argv[-1]]) {
1336 --argv;
1337 *argv = (char *)((int)(*argv) + 10);
1338 argv = (char **)realloc(argv, (int)(*argv) + 2);
1339 if (argv == NULL)
1340 return(NULL);
1341 argv++;
1342 cpp = &argv[(int)argv[-1] - 10];
1343 }
1344 *cpp++ = val;
1345 *cpp = 0;
1346 return(argv);
1347}
1af3d848 1348#endif /* NEWINIT */
ea139302
PB
1349
1350/*
1351 * cleanup()
1352 *
1353 * This is the routine to call when we are all through, to
1354 * clean up anything that needs to be cleaned up.
1355 */
1af3d848
DB
1356 /* ARGSUSED */
1357 void
1358cleanup(sig)
1359 int sig;
ea139302 1360{
ea139302 1361#ifndef CRAY
2c9c7136 1362# if (BSD > 43) || defined(convex)
ea139302
PB
1363 char *p;
1364
1365 p = line + sizeof("/dev/") - 1;
1366 if (logout(p))
1367 logwtmp(p, "", "");
1368 (void)chmod(line, 0666);
1369 (void)chown(line, 0, 0);
1370 *p = 'p';
1371 (void)chmod(line, 0666);
1372 (void)chown(line, 0, 0);
1af3d848
DB
1373 (void) shutdown(net, 2);
1374 exit(1);
ea139302 1375# else
1af3d848
DB
1376 void rmut();
1377
ea139302
PB
1378 rmut();
1379 vhangup(); /* XXX */
ea139302 1380 (void) shutdown(net, 2);
1af3d848
DB
1381 exit(1);
1382# endif
ea139302 1383#else /* CRAY */
1af3d848 1384# ifdef NEWINIT
ea139302 1385 (void) shutdown(net, 2);
1af3d848 1386 exit(1);
ea139302 1387# else /* NEWINIT */
1af3d848
DB
1388 static int incleanup = 0;
1389 register int t;
1390
1391 /*
1392 * 1: Pick up the zombie, if we are being called
1393 * as the signal handler.
1394 * 2: If we are a nested cleanup(), return.
1395 * 3: Try to clean up TMPDIR.
1396 * 4: Fill in utmp with shutdown of process.
1397 * 5: Close down the network and pty connections.
1398 * 6: Finish up the TMPDIR cleanup, if needed.
1399 */
1400 if (sig == SIGCHLD)
1401 while (waitpid(-1, 0, WNOHANG) > 0)
1402 ; /* VOID */
1403 t = sigblock(sigmask(SIGCHLD));
1404 if (incleanup) {
1405 sigsetmask(t);
1406 return;
1407 }
1408 incleanup = 1;
1409 sigsetmask(t);
1410
1411 t = cleantmp(&wtmp);
1412 setutent(); /* just to make sure */
1413 rmut(line);
1414 close(pty);
ea139302 1415 (void) shutdown(net, 2);
1af3d848
DB
1416 if (t == 0)
1417 cleantmp(&wtmp);
1418 exit(1);
ea139302
PB
1419# endif /* NEWINT */
1420#endif /* CRAY */
ea139302
PB
1421}
1422
1423#if defined(CRAY) && !defined(NEWINIT)
1424/*
1425 * _utmp_sig_rcv
1426 * utmp_sig_init
1427 * utmp_sig_wait
1428 * These three functions are used to coordinate the handling of
1429 * the utmp file between the server and the soon-to-be-login shell.
1430 * The server actually creates the utmp structure, the child calls
1431 * utmp_sig_wait(), until the server calls utmp_sig_notify() and
1432 * signals the future-login shell to proceed.
1433 */
1434static int caught=0; /* NZ when signal intercepted */
1435static void (*func)(); /* address of previous handler */
1436
1af3d848 1437 void
ea139302 1438_utmp_sig_rcv(sig)
1af3d848 1439 int sig;
ea139302
PB
1440{
1441 caught = 1;
1442 (void) signal(SIGUSR1, func);
1443}
1444
1af3d848 1445 void
ea139302
PB
1446utmp_sig_init()
1447{
1448 /*
1449 * register signal handler for UTMP creation
1450 */
1451 if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
1452 fatalperror(net, "telnetd/signal");
1453}
1454
1af3d848 1455 void
4a8a7128
PB
1456utmp_sig_reset()
1457{
1458 (void) signal(SIGUSR1, func); /* reset handler to default */
1459}
1460
1af3d848 1461 void
ea139302
PB
1462utmp_sig_wait()
1463{
1464 /*
1465 * Wait for parent to write our utmp entry.
1466 */
1467 sigoff();
1468 while (caught == 0) {
1469 pause(); /* wait until we get a signal (sigon) */
1470 sigoff(); /* turn off signals while we check caught */
1471 }
1472 sigon(); /* turn on signals again */
1473}
1474
1af3d848 1475 void
ea139302
PB
1476utmp_sig_notify(pid)
1477{
1478 kill(pid, SIGUSR1);
1479}
1af3d848
DB
1480
1481static int gotsigjob = 0;
1482
1483 /*ARGSUSED*/
1484 void
1485sigjob(sig)
1486 int sig;
1487{
1488 register int jid;
1489 register struct jobtemp *jp;
1490
1491 while ((jid = waitjob(NULL)) != -1) {
1492 if (jid == 0) {
1493 return;
1494 }
1495 gotsigjob++;
1496 jobend(jid, NULL, NULL);
1497 }
1498}
1499
1500/*
1501 * Clean up the TMPDIR that login created.
1502 * The first time this is called we pick up the info
1503 * from the utmp. If the job has already gone away,
1504 * then we'll clean up and be done. If not, then
1505 * when this is called the second time it will wait
1506 * for the signal that the job is done.
1507 */
1508 int
1509cleantmp(wtp)
1510 register struct utmp *wtp;
1511{
1512 struct utmp *utp;
1513 static int first = 1;
1514 register int mask, omask, ret;
1515 extern struct utmp *getutid P((struct utmp *));
1516
1517 mask = sigmask(WJSIGNAL);
1518
1519 if (first == 0) {
1520 omask = sigblock(mask);
1521 while (gotsigjob == 0)
1522 sigpause(omask);
1523 return(1);
1524 }
1525 first = 0;
1526 setutent(); /* just to make sure */
1527
1528 utp = getutid(wtp);
1529 if (utp == 0) {
1530 syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
1531 return(-1);
1532 }
1533 /*
1534 * Nothing to clean up if the user shell was never started.
1535 */
1536 if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0)
1537 return(1);
1538
1539 /*
1540 * Block the WJSIGNAL while we are in jobend().
1541 */
1542 omask = sigblock(mask);
1543 ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user);
1544 sigsetmask(omask);
1545 return(ret);
1546}
1547
1548 int
1549jobend(jid, path, user)
1550 register int jid;
1551 register char *path;
1552 register char *user;
1553{
1554 static int saved_jid = 0;
1555 static char saved_path[sizeof(wtmp.ut_tpath)+1];
1556 static char saved_user[sizeof(wtmp.ut_user)+1];
1557
1558 if (path) {
1559 strncpy(saved_path, path, sizeof(wtmp.ut_tpath));
1560 strncpy(saved_user, user, sizeof(wtmp.ut_user));
1561 saved_path[sizeof(saved_path)] = '\0';
1562 saved_user[sizeof(saved_user)] = '\0';
1563 }
1564 if (saved_jid == 0) {
1565 saved_jid = jid;
1566 return(0);
1567 }
1568 cleantmpdir(jid, saved_path, saved_user);
1569 return(1);
1570}
1571
1572/*
1573 * Fork a child process to clean up the TMPDIR
1574 */
1575cleantmpdir(jid, tpath, user)
1576 register int jid;
1577 register char *tpath;
1578 register char *user;
1579{
1580 switch(fork()) {
1581 case -1:
1582 syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n",
1583 tpath);
1584 break;
1585 case 0:
1586 execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0);
1587 syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n",
1588 tpath, CLEANTMPCMD);
1589 exit(1);
1590 default:
1591 /*
1592 * Forget about child. We will exit, and
1593 * /etc/init will pick it up.
1594 */
1595 break;
1596 }
1597}
ea139302
PB
1598#endif /* defined(CRAY) && !defined(NEWINIT) */
1599
1600/*
1601 * rmut()
1602 *
1603 * This is the function called by cleanup() to
1604 * remove the utmp entry for this person.
1605 */
1606
1607#if !defined(CRAY) && BSD <= 43
1af3d848 1608 void
ea139302
PB
1609rmut()
1610{
1611 register f;
1612 int found = 0;
1613 struct utmp *u, *utmp;
1614 int nutmp;
1615 struct stat statbf;
ea139302
PB
1616
1617 f = open(utmpf, O_RDWR);
1618 if (f >= 0) {
1619 (void) fstat(f, &statbf);
1620 utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
1621 if (!utmp)
1622 syslog(LOG_ERR, "utmp malloc failed");
1623 if (statbf.st_size && utmp) {
1624 nutmp = read(f, (char *)utmp, (int)statbf.st_size);
1625 nutmp /= sizeof(struct utmp);
1626
1627 for (u = utmp ; u < &utmp[nutmp] ; u++) {
1628 if (SCMPN(u->ut_line, line+5) ||
1629 u->ut_name[0]==0)
1630 continue;
1631 (void) lseek(f, ((long)u)-((long)utmp), L_SET);
1632 SCPYN(u->ut_name, "");
1633 SCPYN(u->ut_host, "");
1634 (void) time(&u->ut_time);
1635 (void) write(f, (char *)u, sizeof(wtmp));
1636 found++;
1637 }
1638 }
1639 (void) close(f);
1640 }
1641 if (found) {
1642 f = open(wtmpf, O_WRONLY|O_APPEND);
1643 if (f >= 0) {
1644 SCPYN(wtmp.ut_line, line+5);
1645 SCPYN(wtmp.ut_name, "");
1646 SCPYN(wtmp.ut_host, "");
1647 (void) time(&wtmp.ut_time);
1648 (void) write(f, (char *)&wtmp, sizeof(wtmp));
1649 (void) close(f);
1650 }
1651 }
1652 (void) chmod(line, 0666);
1653 (void) chown(line, 0, 0);
1654 line[strlen("/dev/")] = 'p';
1655 (void) chmod(line, 0666);
1656 (void) chown(line, 0, 0);
1657} /* end of rmut */
1658#endif /* CRAY */