|
|
1.1 root 1: /*
2: * Copyright (c) 1989 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted provided
6: * that: (1) source distributions retain this entire copyright notice and
7: * comment, and (2) distributions including binaries display the following
8: * acknowledgement: ``This product includes software developed by the
9: * University of California, Berkeley and its contributors'' in the
10: * documentation or other materials provided with the distribution and in
11: * all advertising materials mentioning features or use of this software.
12: * Neither the name of the University nor the names of its contributors may
13: * be used to endorse or promote products derived from this software without
14: * specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: static char sccsid[] = "@(#)sys_term.c 5.10 (Berkeley) 6/30/90";
22: #endif /* not lint */
23:
24: #include "telnetd.h"
25: #include "pathnames.h"
26:
27: #ifdef NEWINIT
28: #include <initreq.h>
29: #else /* NEWINIT*/
30: #include <utmp.h>
31: struct utmp wtmp;
32:
33: # ifndef CRAY
34: char wtmpf[] = "/usr/adm/wtmp";
35: char utmpf[] = "/etc/utmp";
36: # else /* CRAY */
37: char wtmpf[] = "/etc/wtmp";
38: # endif /* CRAY */
39: #endif /* NEWINIT */
40:
41: #define SCPYN(a, b) (void) strncpy(a, b, sizeof(a))
42: #define SCMPN(a, b) strncmp(a, b, sizeof(a))
43:
44: #ifdef STREAMS
45: #include <sys/stream.h>
46: #endif
47: #include <sys/tty.h>
48: #ifdef t_erase
49: #undef t_erase
50: #undef t_kill
51: #undef t_intrc
52: #undef t_quitc
53: #undef t_startc
54: #undef t_stopc
55: #undef t_eofc
56: #undef t_brkc
57: #undef t_suspc
58: #undef t_dsuspc
59: #undef t_rprntc
60: #undef t_flushc
61: #undef t_werasc
62: #undef t_lnextc
63: #endif
64:
65: #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC)
66: # define EXTPROC 0400
67: #endif
68:
69: #ifndef USE_TERMIO
70: struct termbuf {
71: struct sgttyb sg;
72: struct tchars tc;
73: struct ltchars ltc;
74: int state;
75: int lflags;
76: } termbuf, termbuf2;
77: #else /* USE_TERMIO */
78: # ifdef SYSV_TERMIO
79: # define termios termio
80: # endif
81: # ifndef TCSETA
82: # ifdef TCSETS
83: # define TCSETA TCSETS
84: # define TCGETA TCGETS
85: # else
86: # define TCSETA TIOCSETAW
87: # define TCGETA TIOCGETA
88: # endif
89: # endif /* 4.4BSD */
90: struct termios termbuf, termbuf2; /* pty control structure */
91: #endif /* USE_TERMIO */
92:
93: /*
94: * init_termbuf()
95: * copy_termbuf(cp)
96: * set_termbuf()
97: *
98: * These three routines are used to get and set the "termbuf" structure
99: * to and from the kernel. init_termbuf() gets the current settings.
100: * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
101: * set_termbuf() writes the structure into the kernel.
102: */
103:
104: init_termbuf()
105: {
106: #ifndef USE_TERMIO
107: (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
108: (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
109: (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
110: # ifdef TIOCGSTATE
111: (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
112: # endif
113: #else
114: (void) ioctl(pty, TCGETA, (char *)&termbuf);
115: #endif
116: termbuf2 = termbuf;
117: }
118:
119: #if defined(LINEMODE) && defined(TIOCPKT_IOCTL)
120: copy_termbuf(cp, len)
121: char *cp;
122: int len;
123: {
124: if (len > sizeof(termbuf))
125: len = sizeof(termbuf);
126: bcopy(cp, (char *)&termbuf, len);
127: termbuf2 = termbuf;
128: }
129: #endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
130:
131: set_termbuf()
132: {
133: /*
134: * Only make the necessary changes.
135: */
136: #ifndef USE_TERMIO
137: if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg)))
138: (void) ioctl(pty, TIOCSETP, (char *)&termbuf.sg);
139: if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc)))
140: (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
141: if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
142: sizeof(termbuf.ltc)))
143: (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
144: if (termbuf.lflags != termbuf2.lflags)
145: (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
146: #else /* USE_TERMIO */
147: if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
148: (void) ioctl(pty, TCSETA, (char *)&termbuf);
149: # if defined(CRAY2) && defined(UNCIOS5)
150: needtermstat = 1;
151: # endif
152: #endif /* USE_TERMIO */
153: }
154:
155:
156: /*
157: * spcset(func, valp, valpp)
158: *
159: * This function takes various special characters (func), and
160: * sets *valp to the current value of that character, and
161: * *valpp to point to where in the "termbuf" structure that
162: * value is kept.
163: *
164: * It returns the SLC_ level of support for this function.
165: */
166:
167: #ifndef USE_TERMIO
168: spcset(func, valp, valpp)
169: int func;
170: cc_t *valp;
171: cc_t **valpp;
172: {
173: switch(func) {
174: case SLC_EOF:
175: *valp = termbuf.tc.t_eofc;
176: *valpp = (cc_t *)&termbuf.tc.t_eofc;
177: return(SLC_VARIABLE);
178: case SLC_EC:
179: *valp = termbuf.sg.sg_erase;
180: *valpp = (cc_t *)&termbuf.sg.sg_erase;
181: return(SLC_VARIABLE);
182: case SLC_EL:
183: *valp = termbuf.sg.sg_kill;
184: *valpp = (cc_t *)&termbuf.sg.sg_kill;
185: return(SLC_VARIABLE);
186: case SLC_IP:
187: *valp = termbuf.tc.t_intrc;
188: *valpp = (cc_t *)&termbuf.tc.t_intrc;
189: return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
190: case SLC_ABORT:
191: *valp = termbuf.tc.t_quitc;
192: *valpp = (cc_t *)&termbuf.tc.t_quitc;
193: return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
194: case SLC_XON:
195: *valp = termbuf.tc.t_startc;
196: *valpp = (cc_t *)&termbuf.tc.t_startc;
197: return(SLC_VARIABLE);
198: case SLC_XOFF:
199: *valp = termbuf.tc.t_stopc;
200: *valpp = (cc_t *)&termbuf.tc.t_stopc;
201: return(SLC_VARIABLE);
202: case SLC_AO:
203: *valp = termbuf.ltc.t_flushc;
204: *valpp = (cc_t *)&termbuf.ltc.t_flushc;
205: return(SLC_VARIABLE);
206: case SLC_SUSP:
207: *valp = termbuf.ltc.t_suspc;
208: *valpp = (cc_t *)&termbuf.ltc.t_suspc;
209: return(SLC_VARIABLE);
210: case SLC_EW:
211: *valp = termbuf.ltc.t_werasc;
212: *valpp = (cc_t *)&termbuf.ltc.t_werasc;
213: return(SLC_VARIABLE);
214: case SLC_RP:
215: *valp = termbuf.ltc.t_rprntc;
216: *valpp = (cc_t *)&termbuf.ltc.t_rprntc;
217: return(SLC_VARIABLE);
218: case SLC_LNEXT:
219: *valp = termbuf.ltc.t_lnextc;
220: *valpp = (cc_t *)&termbuf.ltc.t_lnextc;
221: return(SLC_VARIABLE);
222: case SLC_FORW1:
223: *valp = termbuf.tc.t_brkc;
224: *valpp = (cc_t *)&termbuf.ltc.t_lnextc;
225: return(SLC_VARIABLE);
226: case SLC_BRK:
227: case SLC_SYNCH:
228: case SLC_AYT:
229: case SLC_EOR:
230: *valp = (cc_t)0;
231: *valpp = (cc_t *)0;
232: return(SLC_DEFAULT);
233: default:
234: *valp = (cc_t)0;
235: *valpp = (cc_t *)0;
236: return(SLC_NOSUPPORT);
237: }
238: }
239:
240: #else /* USE_TERMIO */
241:
242: spcset(func, valp, valpp)
243: int func;
244: cc_t *valp;
245: cc_t **valpp;
246: {
247:
248: #define setval(a, b) *valp = termbuf.c_cc[a]; \
249: *valpp = &termbuf.c_cc[a]; \
250: return(b);
251: #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
252:
253: switch(func) {
254: case SLC_EOF:
255: setval(VEOF, SLC_VARIABLE);
256: case SLC_EC:
257: setval(VERASE, SLC_VARIABLE);
258: case SLC_EL:
259: setval(VKILL, SLC_VARIABLE);
260: case SLC_IP:
261: setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
262: case SLC_ABORT:
263: setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
264: case SLC_XON:
265: #ifdef VSTART
266: setval(VSTART, SLC_VARIABLE);
267: #else
268: defval(0x13);
269: #endif
270: case SLC_XOFF:
271: #ifdef VSTOP
272: setval(VSTOP, SLC_VARIABLE);
273: #else
274: defval(0x11);
275: #endif
276: case SLC_EW:
277: #ifdef VWERASE
278: setval(VWERASE, SLC_VARIABLE);
279: #else
280: defval(0);
281: #endif
282: case SLC_RP:
283: #ifdef VREPRINT
284: setval(VREPRINT, SLC_VARIABLE);
285: #else
286: defval(0);
287: #endif
288: case SLC_LNEXT:
289: #ifdef VLNEXT
290: setval(VLNEXT, SLC_VARIABLE);
291: #else
292: defval(0);
293: #endif
294: case SLC_AO:
295: #ifdef VFLUSHO
296: setval(VFLUSHO, SLC_VARIABLE|SLC_FLUSHOUT);
297: #else
298: defval(0);
299: #endif
300: case SLC_SUSP:
301: #ifdef VSUSP
302: setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
303: #else
304: defval(0);
305: #endif
306: #ifdef VEOL
307: case SLC_FORW1:
308: setval(VEOL, SLC_VARIABLE);
309: #endif
310: #ifdef VEOL2
311: case SLC_FORW2:
312: setval(VEOL2, SLC_VARIABLE);
313: #endif
314:
315: case SLC_BRK:
316: case SLC_SYNCH:
317: case SLC_AYT:
318: case SLC_EOR:
319: defval(0);
320:
321: default:
322: *valp = 0;
323: *valpp = 0;
324: return(SLC_NOSUPPORT);
325: }
326: }
327: #endif /* USE_TERMIO */
328:
329: #ifdef CRAY
330: /*
331: * getnpty()
332: *
333: * Return the number of pty's configured into the system.
334: */
335: getnpty()
336: {
337: #ifdef _SC_CRAY_NPTY
338: return sysconf(_SC_CRAY_NPTY);
339: #else
340: return 128;
341: #endif /* _SC_CRAY_NPTY */
342: }
343: #endif /* CRAY */
344:
345: /*
346: * getpty()
347: *
348: * Allocate a pty. As a side effect, the external character
349: * array "line" contains the name of the slave side.
350: *
351: * Returns the file descriptor of the opened pty.
352: */
353: char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
354:
355: getpty()
356: {
357: register int p;
358: #ifndef CRAY
359: register char c, *p1, *p2;
360: register int i;
361:
362: (void) sprintf(line, "/dev/ptyXX");
363: p1 = &line[8];
364: p2 = &line[9];
365:
366: for (c = 'p'; c <= 's'; c++) {
367: struct stat stb;
368:
369: *p1 = c;
370: *p2 = '0';
371: if (stat(line, &stb) < 0)
372: break;
373: for (i = 0; i < 16; i++) {
374: *p2 = "0123456789abcdef"[i];
375: p = open(line, 2);
376: if (p > 0) {
377: line[5] = 't';
378: return(p);
379: }
380: }
381: }
382: #else /* CRAY */
383: register int npty;
384: extern lowpty, highpty;
385:
386: for (npty = lowpty; npty <= highpty; npty++) {
387: (void) sprintf(line, "/dev/pty/%03d", npty);
388: p = open(line, 2);
389: if (p < 0)
390: continue;
391: (void) sprintf(line, "/dev/ttyp%03d", npty);
392: if (access(line, 6) == 0)
393: return(p);
394: else {
395: /* no tty side to pty so skip it */
396: (void) close(p);
397: }
398: }
399: #endif /* CRAY */
400: return(-1);
401: }
402:
403: #ifdef LINEMODE
404: /*
405: * tty_flowmode() Find out if flow control is enabled or disabled.
406: * tty_linemode() Find out if linemode (external processing) is enabled.
407: * tty_setlinemod(on) Turn on/off linemode.
408: * tty_isecho() Find out if echoing is turned on.
409: * tty_setecho(on) Enable/disable character echoing.
410: * tty_israw() Find out if terminal is in RAW mode.
411: * tty_binaryin(on) Turn on/off BINARY on input.
412: * tty_binaryout(on) Turn on/off BINARY on output.
413: * tty_isediting() Find out if line editing is enabled.
414: * tty_istrapsig() Find out if signal trapping is enabled.
415: * tty_setedit(on) Turn on/off line editing.
416: * tty_setsig(on) Turn on/off signal trapping.
417: * tty_issofttab() Find out if tab expansion is enabled.
418: * tty_setsofttab(on) Turn on/off soft tab expansion.
419: * tty_islitecho() Find out if typed control chars are echoed literally
420: * tty_setlitecho() Turn on/off literal echo of control chars
421: * tty_tspeed(val) Set transmit speed to val.
422: * tty_rspeed(val) Set receive speed to val.
423: */
424:
425: tty_flowmode()
426: {
427: #ifndef USE_TERMIO
428: return((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0);
429: #else
430: return(termbuf.c_iflag & IXON ? 1 : 0);
431: #endif
432: }
433:
434: tty_linemode()
435: {
436: #ifndef USE_TERMIO
437: return(termbuf.state & TS_EXTPROC);
438: #else
439: return(termbuf.c_lflag & EXTPROC);
440: #endif
441: }
442:
443: tty_setlinemode(on)
444: int on;
445: {
446: #ifdef TIOCEXT
447: (void) ioctl(pty, TIOCEXT, (char *)&on);
448: #else /* !TIOCEXT */
449: #ifdef EXTPROC
450: if (on)
451: termbuf.c_lflag |= EXTPROC;
452: else
453: termbuf.c_lflag &= ~EXTPROC;
454: #endif
455: set_termbuf();
456: #endif /* TIOCEXT */
457: }
458:
459: tty_isecho()
460: {
461: #ifndef USE_TERMIO
462: return (termbuf.sg.sg_flags & ECHO);
463: #else
464: return (termbuf.c_lflag & ECHO);
465: #endif
466: }
467: #endif /* LINEMODE */
468:
469: tty_setecho(on)
470: {
471: #ifndef USE_TERMIO
472: if (on)
473: termbuf.sg.sg_flags |= ECHO|CRMOD;
474: else
475: termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
476: #else
477: if (on)
478: termbuf.c_lflag |= ECHO;
479: else
480: termbuf.c_lflag &= ~ECHO;
481: #endif
482: }
483:
484: #if defined(LINEMODE) && defined(KLUDGELINEMODE)
485: tty_israw()
486: {
487: #ifndef USE_TERMIO
488: return(termbuf.sg.sg_flags & RAW);
489: #else
490: return(!(termbuf.c_lflag & ICANON));
491: #endif
492: }
493: #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */
494:
495: tty_binaryin(on)
496: {
497: #ifndef USE_TERMIO
498: if (on)
499: termbuf.lflags |= LPASS8;
500: else
501: termbuf.lflags &= ~LPASS8;
502: #else
503: if (on) {
504: termbuf.c_lflag &= ~ISTRIP;
505: } else {
506: termbuf.c_lflag |= ISTRIP;
507: }
508: #endif
509: }
510:
511: tty_binaryout(on)
512: {
513: #ifndef USE_TERMIO
514: if (on)
515: termbuf.lflags |= LLITOUT;
516: else
517: termbuf.lflags &= ~LLITOUT;
518: #else
519: if (on) {
520: termbuf.c_cflag &= ~(CSIZE|PARENB);
521: termbuf.c_cflag |= CS8;
522: termbuf.c_oflag &= ~OPOST;
523: } else {
524: termbuf.c_cflag &= ~CSIZE;
525: termbuf.c_cflag |= CS7|PARENB;
526: termbuf.c_oflag |= OPOST;
527: }
528: #endif
529: }
530:
531: tty_isbinaryin()
532: {
533: #ifndef USE_TERMIO
534: return(termbuf.lflags & LPASS8);
535: #else
536: return(!(termbuf.c_iflag & ISTRIP));
537: #endif
538: }
539:
540: tty_isbinaryout()
541: {
542: #ifndef USE_TERMIO
543: return(termbuf.lflags & LLITOUT);
544: #else
545: return(!(termbuf.c_oflag&OPOST));
546: #endif
547: }
548:
549: #ifdef LINEMODE
550: tty_isediting()
551: {
552: #ifndef USE_TERMIO
553: return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
554: #else
555: return(termbuf.c_lflag & ICANON);
556: #endif
557: }
558:
559: tty_istrapsig()
560: {
561: #ifndef USE_TERMIO
562: return(!(termbuf.sg.sg_flags&RAW));
563: #else
564: return(termbuf.c_lflag & ISIG);
565: #endif
566: }
567:
568: tty_setedit(on)
569: int on;
570: {
571: #ifndef USE_TERMIO
572: if (on)
573: termbuf.sg.sg_flags &= ~CBREAK;
574: else
575: termbuf.sg.sg_flags |= CBREAK;
576: #else
577: if (on)
578: termbuf.c_lflag |= ICANON;
579: else
580: termbuf.c_lflag &= ~ICANON;
581: #endif
582: }
583:
584: tty_setsig(on)
585: int on;
586: {
587: #ifndef USE_TERMIO
588: if (on)
589: ;
590: #else
591: if (on)
592: termbuf.c_lflag |= ISIG;
593: else
594: termbuf.c_lflag &= ~ISIG;
595: #endif
596: }
597: #endif /* LINEMODE */
598:
599: tty_issofttab()
600: {
601: #ifndef USE_TERMIO
602: return (termbuf.sg.sg_flags & XTABS);
603: #else
604: # ifdef OXTABS
605: return (termbuf.c_oflag & OXTABS);
606: # endif
607: # ifdef TABDLY
608: return ((termbuf.c_oflag & TABDLY) == TAB3);
609: # endif
610: #endif
611: }
612:
613: tty_setsofttab(on)
614: int on;
615: {
616: #ifndef USE_TERMIO
617: if (on)
618: termbuf.sg.sg_flags |= XTABS;
619: else
620: termbuf.sg.sg_flags &= ~XTABS;
621: #else
622: if (on) {
623: # ifdef OXTABS
624: termbuf.c_oflag |= OXTABS;
625: # endif
626: # ifdef TABDLY
627: termbuf.c_oflag &= ~TABDLY;
628: termbuf.c_oflag |= TAB3;
629: # endif
630: } else {
631: # ifdef OXTABS
632: termbuf.c_oflag &= ~OXTABS;
633: # endif
634: # ifdef TABDLY
635: termbuf.c_oflag &= ~TABDLY;
636: termbuf.c_oflag |= TAB0;
637: # endif
638: }
639: #endif
640: }
641:
642: tty_islitecho()
643: {
644: #ifndef USE_TERMIO
645: return (!(termbuf.sg.sg_flags & CTLECH));
646: #else
647: # ifdef ECHOCTL
648: return (!(termbuf.c_lflag & ECHOCTL));
649: # endif
650: # ifdef TCTLECH
651: return (!(termbuf.c_lflag & TCTLECH));
652: # endif
653: # if !defined(ECHOCTL) && !defined(TCTLECH)
654: return (0); /* assumes ctl chars are echoed '^x' */
655: # endif
656: #endif
657: }
658:
659: tty_setlitecho(on)
660: int on;
661: {
662: #ifndef USE_TERMIO
663: if (on)
664: termbuf.sg.sg_flags &= ~CTLECH;
665: else
666: termbuf.sg.sg_flags |= CTLECH;
667: #else
668: # ifdef ECHOCTL
669: if (on)
670: termbuf.c_lflag &= ~ECHOCTL;
671: else
672: termbuf.c_lflag |= ECHOCTL;
673: # endif
674: # ifdef TCTLECH
675: if (on)
676: termbuf.c_lflag &= ~TCTLECH;
677: else
678: termbuf.c_lflag |= TCTLECH;
679: # endif
680: #endif
681: }
682:
683: /*
684: * A table of available terminal speeds
685: */
686: struct termspeeds {
687: int speed;
688: int value;
689: } termspeeds[] = {
690: { 0, B0 }, { 50, B50 }, { 75, B75 },
691: { 110, B110 }, { 134, B134 }, { 150, B150 },
692: { 200, B200 }, { 300, B300 }, { 600, B600 },
693: { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 },
694: { 4800, B4800 }, { 9600, B9600 }, { 19200, B9600 },
695: { 38400, B9600 }, { -1, B9600 }
696: };
697:
698: tty_tspeed(val)
699: {
700: register struct termspeeds *tp;
701:
702: for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
703: ;
704: #ifndef USE_TERMIO
705: termbuf.sg.sg_ospeed = tp->value;
706: #else
707: # ifdef CBAUD
708: termbuf.c_cflag &= ~CBAUD;
709: termbuf.c_cflag |= tp->value;
710: # else
711: termbuf.c_ospeed = tp->value;
712: # endif
713: #endif
714: }
715:
716: tty_rspeed(val)
717: {
718: register struct termspeeds *tp;
719:
720: for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
721: ;
722: #ifndef USE_TERMIO
723: termbuf.sg.sg_ispeed = tp->value;
724: #else
725: # ifdef CBAUD
726: termbuf.c_cflag &= ~CBAUD;
727: termbuf.c_cflag |= tp->value;
728: # else
729: termbuf.c_ispeed = tp->value;
730: # endif
731: #endif
732: }
733:
734: #if defined(CRAY2) && defined(UNICOS5)
735: tty_isnewmap()
736: {
737: return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
738: !(termbuf.c_oflag & ONLRET));
739: }
740: #endif
741:
742: #ifdef CRAY
743: # ifndef NEWINIT
744: extern struct utmp wtmp;
745: extern char wtmpf[];
746: # else /* NEWINIT */
747: int gotalarm;
748: /* ARGSUSED */
749: void
750: nologinproc(sig)
751: int sig;
752: {
753: gotalarm++;
754: }
755: # endif /* NEWINIT */
756: #endif /* CRAY */
757:
758: /*
759: * getptyslave()
760: *
761: * Open the slave side of the pty, and do any initialization
762: * that is necessary. The return value is a file descriptor
763: * for the slave side.
764: */
765: getptyslave()
766: {
767: register int t = -1;
768:
769: #ifndef CRAY
770: /*
771: * Disassociate self from control terminal and open ttyp side.
772: * Set important flags on ttyp and ptyp.
773: */
774: t = open(_PATH_TTY, O_RDWR);
775: if (t >= 0) {
776: (void) ioctl(t, TIOCNOTTY, (char *)0);
777: (void) close(t);
778: }
779:
780: t = open(line, O_RDWR);
781: if (t < 0)
782: fatalperror(net, line);
783: if (fchmod(t, 0))
784: fatalperror(net, line);
785: #if BSD <= 43
786: (void) signal(SIGHUP, SIG_IGN);
787: vhangup();
788: (void) signal(SIGHUP, SIG_DFL);
789: t = open(line, O_RDWR);
790: if (t < 0)
791: fatalperror(net, line);
792: #endif
793:
794: init_termbuf();
795: #ifndef USE_TERMIO
796: termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
797: termbuf.sg.sg_ospeed = termbuf.sg.sg_ispeed = B9600;
798: #else
799: termbuf.c_lflag |= ECHO;
800: #ifndef OXTABS
801: #define OXTABS 0
802: #endif
803: termbuf.c_oflag |= ONLCR|OXTABS;
804: termbuf.c_iflag |= ICRNL;
805: termbuf.c_iflag &= ~IXOFF;
806: # ifdef CBAUD
807: termbuf.c_cflag &= ~CBAUD;
808: termbuf.c_cflag |= B9600;
809: # else /* CBAUD */
810: termbuf.c_ospeed = termbuf.c_ispeed = B9600;
811: # endif /* CBAUD */
812: #endif
813: set_termbuf();
814: #else /* CRAY */
815: (void) chown(line, 0, 0);
816: (void) chmod(line, 0600);
817: #endif /* CRAY */
818: return(t);
819: }
820:
821: #ifdef NEWINIT
822: char *gen_id = "fe";
823: #endif
824:
825: /*
826: * startslave(t, host)
827: *
828: * Given a file descriptor (t) for a tty, and a hostname, do whatever
829: * is necessary to startup the login process on the slave side of the pty.
830: */
831:
832: /* ARGSUSED */
833: startslave(t, host)
834: int t;
835: char *host;
836: {
837: register int i;
838: long time();
839:
840: #ifndef NEWINIT
841: # ifdef CRAY
842: utmp_sig_init();
843: # endif /* CRAY */
844:
845: if ((i = fork()) < 0)
846: fatalperror(net, "fork");
847: if (i) {
848: # ifdef CRAY
849: /*
850: * Cray parent will create utmp entry for child and send
851: * signal to child to tell when done. Child waits for signal
852: * before doing anything important.
853: */
854: register int pid = i;
855:
856: setpgrp();
857: utmp_sig_reset(); /* reset handler to default */
858: /*
859: * Create utmp entry for child
860: */
861: (void) time(&wtmp.ut_time);
862: wtmp.ut_type = LOGIN_PROCESS;
863: wtmp.ut_pid = pid;
864: SCPYN(wtmp.ut_user, "LOGIN");
865: SCPYN(wtmp.ut_host, host);
866: SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
867: SCPYN(wtmp.ut_id, wtmp.ut_line+3);
868: pututline(&wtmp);
869: endutent();
870: if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
871: (void) write(i, (char *)&wtmp, sizeof(struct utmp));
872: (void) close(i);
873: }
874: utmp_sig_notify(pid);
875: # endif /* CRAY */
876: (void) close(t);
877: } else {
878: start_login(t, host);
879: /*NOTREACHED*/
880: }
881: #else /* NEWINIT */
882:
883: extern char *ptyip;
884: struct init_request request;
885: void nologinproc();
886: register int n;
887:
888: /*
889: * Init will start up login process if we ask nicely. We only wait
890: * for it to start up and begin normal telnet operation.
891: */
892: if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
893: char tbuf[128];
894: (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO);
895: fatalperror(net, tbuf);
896: }
897: memset((char *)&request, 0, sizeof(request));
898: request.magic = INIT_MAGIC;
899: SCPYN(request.gen_id, gen_id);
900: SCPYN(request.tty_id, &line[8]);
901: SCPYN(request.host, host);
902: SCPYN(request.term_type, terminaltype);
903: #if !defined(UNICOS5)
904: request.signal = SIGCLD;
905: request.pid = getpid();
906: #endif
907: #ifdef BFTPDAEMON
908: /*
909: * Are we working as the bftp daemon?
910: */
911: if (bftpd) {
912: SCPYN(request.exec_name, BFTPPATH);
913: }
914: #endif /* BFTPDAEMON */
915: if (write(i, (char *)&request, sizeof(request)) < 0) {
916: char tbuf[128];
917: (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO);
918: fatalperror(net, tbuf);
919: }
920: (void) close(i);
921: (void) signal(SIGALRM, nologinproc);
922: for (i = 0; ; i++) {
923: char tbuf[128];
924: alarm(15);
925: n = read(pty, ptyip, BUFSIZ);
926: if (i == 3 || n >= 0 || !gotalarm)
927: break;
928: gotalarm = 0;
929: sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line);
930: (void) write(net, tbuf, strlen(tbuf));
931: }
932: if (n < 0 && gotalarm)
933: fatal(net, "/etc/init didn't start login process");
934: pcc += n;
935: alarm(0);
936: (void) signal(SIGALRM, SIG_DFL);
937:
938: return;
939: #endif /* NEWINIT */
940: }
941:
942: char *envinit[3];
943: extern char **environ;
944:
945: init_env()
946: {
947: extern char *getenv();
948: char **envp;
949:
950: envp = envinit;
951: if (*envp = getenv("TZ"))
952: *envp++ -= 3;
953: #ifdef CRAY
954: else
955: *envp++ = "TZ=GMT0";
956: #endif
957: *envp = 0;
958: environ = envinit;
959: }
960:
961: #ifdef CRAY
962: /*
963: * These are environment variable that we
964: * don't put on the argument line.
965: */
966: char *invalid[] = {
967: "USER=", /* Set up by login */
968: "HOME=", /* Set up by login */
969: "LOGNAME=", /* Set up by login */
970: "TMPDIR=", /* Set up by login */
971: "SHELL=", /* Set up by login */
972: "PATH=", /* Set up by login */
973: "MAIL=", /* Set up by login */
974: "TZ=", /* Login gets it from the environment */
975: "TERM=", /* Login gets it from the environment */
976: 0
977: };
978: #endif
979:
980: #ifndef NEWINIT
981:
982: /*
983: * start_login(t, host)
984: *
985: * Assuming that we are now running as a child processes, this
986: * function will turn us into the login process.
987: */
988:
989: start_login(t, host)
990: int t;
991: char *host;
992: {
993: register char *cp;
994: register char **argv;
995: char **addarg();
996: #ifdef CRAY
997: register char **cpp, **cpp2;
998: utmp_sig_wait();
999: # ifndef TCVHUP
1000: setpgrp();
1001: # endif
1002: t = open(line, 2); /* open ttyp */
1003: if (t < 0)
1004: fatalperror(net, line);
1005: # ifdef TCVHUP
1006: /*
1007: * Hangup anybody else using this ttyp, then reopen it for
1008: * ourselves.
1009: */
1010: (void) chown(line, 0, 0);
1011: (void) chmod(line, 0600);
1012: (void) signal(SIGHUP, SIG_IGN);
1013: (void) ioctl(t, TCVHUP, (char *)0);
1014: (void) signal(SIGHUP, SIG_DFL);
1015: setpgrp();
1016: i = open(line, 2);
1017: if (i < 0)
1018: fatalperror(net, line);
1019: (void) close(t);
1020: t = i;
1021: # endif /* TCVHUP */
1022: /*
1023: * set ttyp modes as we like them to be
1024: */
1025: init_termbuf();
1026: termbuf.c_oflag = OPOST|ONLCR|TAB3;
1027: termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
1028: termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
1029: termbuf.c_cflag = EXTB|HUPCL|CS8;
1030: set_termbuf();
1031: #endif /* CRAY */
1032:
1033: /*
1034: * set up standard paths before forking to login
1035: */
1036: #if BSD > 43
1037: if (login_tty(t) == -1)
1038: fatalperror(net, "login_tty");
1039: #else
1040: (void) dup2(t, 0);
1041: (void) dup2(t, 1);
1042: (void) dup2(t, 2);
1043: (void) close(t);
1044: #endif
1045: if (net > 2)
1046: (void) close(net);
1047: if (pty > 2)
1048: (void) close(pty);
1049: /*
1050: * -h : pass on name of host.
1051: * WARNING: -h is accepted by login if and only if
1052: * getuid() == 0.
1053: * -p : don't clobber the environment (so terminal type stays set).
1054: */
1055: argv = addarg(0, "login");
1056: argv = addarg(argv, "-h");
1057: argv = addarg(argv, host);
1058: #if !defined(CRAY) && !defined(NO_LOGIN_P)
1059: argv = addarg(argv, "-p");
1060: #endif
1061: #ifdef BFTPDAEMON
1062: /*
1063: * Are we working as the bftp daemon? If so, then ask login
1064: * to start bftp instead of shell.
1065: */
1066: if (bftpd) {
1067: argv = addarg(argv, "-e");
1068: argv = addarg(argv, BFTPPATH);
1069: } else
1070: #endif
1071: if (getenv("USER")) {
1072: argv = addarg(argv, getenv("USER"));
1073: }
1074: #ifdef CRAY
1075: for (cpp = environ; *cpp; cpp++) {
1076: for (cpp2 = invalid; *cpp2; cpp2++)
1077: if (strncmp(*cpp2, *cpp, strlen(*cpp2)) == 0)
1078: break;
1079: if (*cpp2)
1080: continue;
1081: argv = addarg(argv, *cpp);
1082: }
1083: #endif
1084:
1085: execv(_PATH_LOGIN, argv);
1086:
1087: syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN);
1088: fatalperror(net, _PATH_LOGIN);
1089: /*NOTREACHED*/
1090: }
1091:
1092: char **
1093: addarg(argv, val)
1094: register char **argv;
1095: register char *val;
1096: {
1097: register char **cpp;
1098: char *malloc();
1099:
1100: if (argv == NULL) {
1101: /*
1102: * 10 entries, a leading length, and a null
1103: */
1104: argv = (char **)malloc(sizeof(*argv) * 12);
1105: if (argv == NULL)
1106: return(NULL);
1107: *argv++ = (char *)10;
1108: *argv = (char *)0;
1109: }
1110: for (cpp = argv; *cpp; cpp++)
1111: ;
1112: if (cpp == &argv[(int)argv[-1]]) {
1113: --argv;
1114: *argv = (char *)((int)(*argv) + 10);
1115: argv = (char **)realloc(argv, (int)(*argv) + 2);
1116: if (argv == NULL)
1117: return(NULL);
1118: argv++;
1119: cpp = &argv[(int)argv[-1] - 10];
1120: }
1121: *cpp++ = val;
1122: *cpp = 0;
1123: return(argv);
1124: }
1125: #endif NEWINIT
1126:
1127: /*
1128: * cleanup()
1129: *
1130: * This is the routine to call when we are all through, to
1131: * clean up anything that needs to be cleaned up.
1132: */
1133: cleanup()
1134: {
1135:
1136: #ifndef CRAY
1137: # if BSD > 43
1138: char *p;
1139:
1140: p = line + sizeof("/dev/") - 1;
1141: if (logout(p))
1142: logwtmp(p, "", "");
1143: (void)chmod(line, 0666);
1144: (void)chown(line, 0, 0);
1145: *p = 'p';
1146: (void)chmod(line, 0666);
1147: (void)chown(line, 0, 0);
1148: # else
1149: rmut();
1150: vhangup(); /* XXX */
1151: # endif
1152: (void) shutdown(net, 2);
1153: #else /* CRAY */
1154: # ifndef NEWINIT
1155: rmut(line);
1156: (void) shutdown(net, 2);
1157: kill(0, SIGHUP);
1158: # else /* NEWINIT */
1159: (void) shutdown(net, 2);
1160: # endif /* NEWINT */
1161: #endif /* CRAY */
1162: exit(1);
1163: }
1164:
1165: #if defined(CRAY) && !defined(NEWINIT)
1166: /*
1167: * _utmp_sig_rcv
1168: * utmp_sig_init
1169: * utmp_sig_wait
1170: * These three functions are used to coordinate the handling of
1171: * the utmp file between the server and the soon-to-be-login shell.
1172: * The server actually creates the utmp structure, the child calls
1173: * utmp_sig_wait(), until the server calls utmp_sig_notify() and
1174: * signals the future-login shell to proceed.
1175: */
1176: static int caught=0; /* NZ when signal intercepted */
1177: static void (*func)(); /* address of previous handler */
1178:
1179: void
1180: _utmp_sig_rcv(sig)
1181: int sig;
1182: {
1183: caught = 1;
1184: (void) signal(SIGUSR1, func);
1185: }
1186:
1187: utmp_sig_init()
1188: {
1189: /*
1190: * register signal handler for UTMP creation
1191: */
1192: if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
1193: fatalperror(net, "telnetd/signal");
1194: }
1195:
1196: utmp_sig_reset()
1197: {
1198: (void) signal(SIGUSR1, func); /* reset handler to default */
1199: }
1200:
1201: utmp_sig_wait()
1202: {
1203: /*
1204: * Wait for parent to write our utmp entry.
1205: */
1206: sigoff();
1207: while (caught == 0) {
1208: pause(); /* wait until we get a signal (sigon) */
1209: sigoff(); /* turn off signals while we check caught */
1210: }
1211: sigon(); /* turn on signals again */
1212: }
1213:
1214: utmp_sig_notify(pid)
1215: {
1216: kill(pid, SIGUSR1);
1217: }
1218: #endif /* defined(CRAY) && !defined(NEWINIT) */
1219:
1220: /*
1221: * rmut()
1222: *
1223: * This is the function called by cleanup() to
1224: * remove the utmp entry for this person.
1225: */
1226:
1227: #if !defined(CRAY) && BSD <= 43
1228: rmut()
1229: {
1230: register f;
1231: int found = 0;
1232: struct utmp *u, *utmp;
1233: int nutmp;
1234: struct stat statbf;
1235: char *malloc();
1236: long time();
1237: off_t lseek();
1238:
1239: f = open(utmpf, O_RDWR);
1240: if (f >= 0) {
1241: (void) fstat(f, &statbf);
1242: utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
1243: if (!utmp)
1244: syslog(LOG_ERR, "utmp malloc failed");
1245: if (statbf.st_size && utmp) {
1246: nutmp = read(f, (char *)utmp, (int)statbf.st_size);
1247: nutmp /= sizeof(struct utmp);
1248:
1249: for (u = utmp ; u < &utmp[nutmp] ; u++) {
1250: if (SCMPN(u->ut_line, line+5) ||
1251: u->ut_name[0]==0)
1252: continue;
1253: (void) lseek(f, ((long)u)-((long)utmp), L_SET);
1254: SCPYN(u->ut_name, "");
1255: SCPYN(u->ut_host, "");
1256: (void) time(&u->ut_time);
1257: (void) write(f, (char *)u, sizeof(wtmp));
1258: found++;
1259: }
1260: }
1261: (void) close(f);
1262: }
1263: if (found) {
1264: f = open(wtmpf, O_WRONLY|O_APPEND);
1265: if (f >= 0) {
1266: SCPYN(wtmp.ut_line, line+5);
1267: SCPYN(wtmp.ut_name, "");
1268: SCPYN(wtmp.ut_host, "");
1269: (void) time(&wtmp.ut_time);
1270: (void) write(f, (char *)&wtmp, sizeof(wtmp));
1271: (void) close(f);
1272: }
1273: }
1274: (void) chmod(line, 0666);
1275: (void) chown(line, 0, 0);
1276: line[strlen("/dev/")] = 'p';
1277: (void) chmod(line, 0666);
1278: (void) chown(line, 0, 0);
1279: } /* end of rmut */
1280: #endif /* CRAY */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.