Annotation of src/libexec/telnetd/sys_term.c, Revision 1.13
1.13 ! perry 1: /* $NetBSD: sys_term.c,v 1.12 1998/04/01 15:02:47 kleink Exp $ */
1.8 thorpej 2:
1.1 cgd 3: /*
1.3 cgd 4: * Copyright (c) 1989, 1993
5: * The Regents of the University of California. All rights reserved.
1.1 cgd 6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
1.11 mrg 36: #include <sys/cdefs.h>
1.1 cgd 37: #ifndef lint
1.8 thorpej 38: #if 0
39: static char sccsid[] = "@(#)sys_term.c 8.4+1 (Berkeley) 5/30/95";
40: #else
1.13 ! perry 41: __RCSID("$NetBSD: sys_term.c,v 1.12 1998/04/01 15:02:47 kleink Exp $");
1.8 thorpej 42: #endif
1.1 cgd 43: #endif /* not lint */
44:
45: #include "telnetd.h"
46: #include "pathnames.h"
47:
1.11 mrg 48: #include <util.h>
49:
1.6 jtk 50: #include <sys/cdefs.h>
51: #define P __P
52:
1.3 cgd 53: #if defined(AUTHENTICATION)
1.1 cgd 54: #include <libtelnet/auth.h>
55: #endif
56:
1.3 cgd 57: #if defined(CRAY) || defined(__hpux)
58: # define PARENT_DOES_UTMP
59: #endif
60:
1.1 cgd 61: #ifdef NEWINIT
62: #include <initreq.h>
1.3 cgd 63: int utmp_len = MAXHOSTNAMELEN; /* sizeof(init_request.host) */
1.1 cgd 64: #else /* NEWINIT*/
1.3 cgd 65: # ifdef UTMPX
66: # include <utmpx.h>
67: struct utmpx wtmp;
68: # else
69: # include <utmp.h>
1.1 cgd 70: struct utmp wtmp;
1.3 cgd 71: # endif /* UTMPX */
1.1 cgd 72:
1.3 cgd 73: int utmp_len = sizeof(wtmp.ut_host);
74: # ifndef PARENT_DOES_UTMP
1.1 cgd 75: char wtmpf[] = "/usr/adm/wtmp";
76: char utmpf[] = "/etc/utmp";
1.3 cgd 77: # else /* PARENT_DOES_UTMP */
1.1 cgd 78: char wtmpf[] = "/etc/wtmp";
1.3 cgd 79: # endif /* PARENT_DOES_UTMP */
80:
81: # ifdef CRAY
1.1 cgd 82: #include <tmpdir.h>
83: #include <sys/wait.h>
1.6 jtk 84: # if (UNICOS_LVL == '7.0') || (UNICOS_LVL == '7.1')
85: # define UNICOS7x
1.3 cgd 86: # endif
87:
1.6 jtk 88: # ifdef UNICOS7x
1.3 cgd 89: #include <sys/sysv.h>
90: #include <sys/secstat.h>
91: extern int secflag;
92: extern struct sysv sysv;
1.6 jtk 93: # endif /* UNICOS7x */
1.1 cgd 94: # endif /* CRAY */
95: #endif /* NEWINIT */
96:
1.3 cgd 97: #ifdef STREAMSPTY
98: #include <sac.h>
99: #include <sys/stropts.h>
100: #endif
101:
1.1 cgd 102: #define SCPYN(a, b) (void) strncpy(a, b, sizeof(a))
103: #define SCMPN(a, b) strncmp(a, b, sizeof(a))
104:
105: #ifdef STREAMS
106: #include <sys/stream.h>
107: #endif
1.3 cgd 108: #ifdef __hpux
109: #include <sys/resource.h>
110: #include <sys/proc.h>
111: #endif
1.1 cgd 112: #ifdef t_erase
113: #undef t_erase
114: #undef t_kill
115: #undef t_intrc
116: #undef t_quitc
117: #undef t_startc
118: #undef t_stopc
119: #undef t_eofc
120: #undef t_brkc
121: #undef t_suspc
122: #undef t_dsuspc
123: #undef t_rprntc
124: #undef t_flushc
125: #undef t_werasc
126: #undef t_lnextc
127: #endif
128:
129: #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC)
130: # define EXTPROC 0400
131: #endif
132:
133: #ifndef USE_TERMIO
134: struct termbuf {
135: struct sgttyb sg;
136: struct tchars tc;
137: struct ltchars ltc;
138: int state;
139: int lflags;
140: } termbuf, termbuf2;
141: # define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val)
142: # define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val)
143: # define cfgetospeed(tp) (tp)->sg.sg_ospeed
144: # define cfgetispeed(tp) (tp)->sg.sg_ispeed
145: #else /* USE_TERMIO */
146: # ifdef SYSV_TERMIO
147: # define termios termio
148: # endif
149: # ifndef TCSANOW
150: # ifdef TCSETS
151: # define TCSANOW TCSETS
152: # define TCSADRAIN TCSETSW
153: # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
154: # else
155: # ifdef TCSETA
156: # define TCSANOW TCSETA
157: # define TCSADRAIN TCSETAW
158: # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
159: # else
160: # define TCSANOW TIOCSETA
161: # define TCSADRAIN TIOCSETAW
162: # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
163: # endif
164: # endif
165: # define tcsetattr(f, a, t) ioctl(f, a, t)
166: # define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \
167: (tp)->c_cflag |= (val)
168: # define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
169: # ifdef CIBAUD
170: # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \
171: (tp)->c_cflag |= ((val)<<IBSHIFT)
172: # define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT)
173: # else
174: # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \
175: (tp)->c_cflag |= (val)
176: # define cfgetispeed(tp) ((tp)->c_cflag & CBAUD)
177: # endif
178: # endif /* TCSANOW */
179: struct termios termbuf, termbuf2; /* pty control structure */
1.3 cgd 180: # ifdef STREAMSPTY
181: int ttyfd = -1;
182: # endif
1.1 cgd 183: #endif /* USE_TERMIO */
184:
1.11 mrg 185: void getptyslave __P((void));
186: int cleanopen __P((char *));
187: void init_env __P((void));
188: char **addarg __P((char **, char *));
189: void scrub_env __P((void));
190: int getent __P((char *, char *));
191: char *getstr __P((char *, char **));
192:
1.1 cgd 193: /*
194: * init_termbuf()
195: * copy_termbuf(cp)
196: * set_termbuf()
197: *
198: * These three routines are used to get and set the "termbuf" structure
199: * to and from the kernel. init_termbuf() gets the current settings.
200: * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
201: * set_termbuf() writes the structure into the kernel.
202: */
203:
204: void
205: init_termbuf()
206: {
207: #ifndef USE_TERMIO
208: (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg);
209: (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc);
210: (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc);
211: # ifdef TIOCGSTATE
212: (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state);
213: # endif
214: #else
1.3 cgd 215: # ifdef STREAMSPTY
216: (void) tcgetattr(ttyfd, &termbuf);
217: # else
1.1 cgd 218: (void) tcgetattr(pty, &termbuf);
1.3 cgd 219: # endif
1.1 cgd 220: #endif
221: termbuf2 = termbuf;
222: }
223:
224: #if defined(LINEMODE) && defined(TIOCPKT_IOCTL)
225: void
226: copy_termbuf(cp, len)
227: char *cp;
228: int len;
229: {
230: if (len > sizeof(termbuf))
231: len = sizeof(termbuf);
1.6 jtk 232: memmove((char *)&termbuf, cp, len);
1.1 cgd 233: termbuf2 = termbuf;
234: }
235: #endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
236:
237: void
238: set_termbuf()
239: {
240: /*
241: * Only make the necessary changes.
242: */
243: #ifndef USE_TERMIO
1.6 jtk 244: if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg,
245: sizeof(termbuf.sg)))
1.1 cgd 246: (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg);
1.6 jtk 247: if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc,
248: sizeof(termbuf.tc)))
1.1 cgd 249: (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc);
1.6 jtk 250: if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
1.1 cgd 251: sizeof(termbuf.ltc)))
252: (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc);
253: if (termbuf.lflags != termbuf2.lflags)
254: (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags);
255: #else /* USE_TERMIO */
1.6 jtk 256: if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf)))
1.3 cgd 257: # ifdef STREAMSPTY
258: (void) tcsetattr(ttyfd, TCSANOW, &termbuf);
259: # else
1.1 cgd 260: (void) tcsetattr(pty, TCSANOW, &termbuf);
1.3 cgd 261: # endif
262: # if defined(CRAY2) && defined(UNICOS5)
1.1 cgd 263: needtermstat = 1;
264: # endif
265: #endif /* USE_TERMIO */
266: }
267:
268:
269: /*
270: * spcset(func, valp, valpp)
271: *
272: * This function takes various special characters (func), and
273: * sets *valp to the current value of that character, and
274: * *valpp to point to where in the "termbuf" structure that
275: * value is kept.
276: *
277: * It returns the SLC_ level of support for this function.
278: */
279:
280: #ifndef USE_TERMIO
281: int
282: spcset(func, valp, valpp)
283: int func;
284: cc_t *valp;
285: cc_t **valpp;
286: {
287: switch(func) {
288: case SLC_EOF:
289: *valp = termbuf.tc.t_eofc;
290: *valpp = (cc_t *)&termbuf.tc.t_eofc;
291: return(SLC_VARIABLE);
292: case SLC_EC:
293: *valp = termbuf.sg.sg_erase;
294: *valpp = (cc_t *)&termbuf.sg.sg_erase;
295: return(SLC_VARIABLE);
296: case SLC_EL:
297: *valp = termbuf.sg.sg_kill;
298: *valpp = (cc_t *)&termbuf.sg.sg_kill;
299: return(SLC_VARIABLE);
300: case SLC_IP:
301: *valp = termbuf.tc.t_intrc;
302: *valpp = (cc_t *)&termbuf.tc.t_intrc;
303: return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
304: case SLC_ABORT:
305: *valp = termbuf.tc.t_quitc;
306: *valpp = (cc_t *)&termbuf.tc.t_quitc;
307: return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
308: case SLC_XON:
309: *valp = termbuf.tc.t_startc;
310: *valpp = (cc_t *)&termbuf.tc.t_startc;
311: return(SLC_VARIABLE);
312: case SLC_XOFF:
313: *valp = termbuf.tc.t_stopc;
314: *valpp = (cc_t *)&termbuf.tc.t_stopc;
315: return(SLC_VARIABLE);
316: case SLC_AO:
317: *valp = termbuf.ltc.t_flushc;
318: *valpp = (cc_t *)&termbuf.ltc.t_flushc;
319: return(SLC_VARIABLE);
320: case SLC_SUSP:
321: *valp = termbuf.ltc.t_suspc;
322: *valpp = (cc_t *)&termbuf.ltc.t_suspc;
323: return(SLC_VARIABLE);
324: case SLC_EW:
325: *valp = termbuf.ltc.t_werasc;
326: *valpp = (cc_t *)&termbuf.ltc.t_werasc;
327: return(SLC_VARIABLE);
328: case SLC_RP:
329: *valp = termbuf.ltc.t_rprntc;
330: *valpp = (cc_t *)&termbuf.ltc.t_rprntc;
331: return(SLC_VARIABLE);
332: case SLC_LNEXT:
333: *valp = termbuf.ltc.t_lnextc;
334: *valpp = (cc_t *)&termbuf.ltc.t_lnextc;
335: return(SLC_VARIABLE);
336: case SLC_FORW1:
337: *valp = termbuf.tc.t_brkc;
338: *valpp = (cc_t *)&termbuf.ltc.t_lnextc;
339: return(SLC_VARIABLE);
340: case SLC_BRK:
341: case SLC_SYNCH:
342: case SLC_AYT:
343: case SLC_EOR:
344: *valp = (cc_t)0;
345: *valpp = (cc_t *)0;
346: return(SLC_DEFAULT);
347: default:
348: *valp = (cc_t)0;
349: *valpp = (cc_t *)0;
350: return(SLC_NOSUPPORT);
351: }
352: }
353:
354: #else /* USE_TERMIO */
355:
356: int
357: spcset(func, valp, valpp)
358: int func;
359: cc_t *valp;
360: cc_t **valpp;
361: {
362:
363: #define setval(a, b) *valp = termbuf.c_cc[a]; \
364: *valpp = &termbuf.c_cc[a]; \
365: return(b);
366: #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
367:
368: switch(func) {
369: case SLC_EOF:
370: setval(VEOF, SLC_VARIABLE);
371: case SLC_EC:
372: setval(VERASE, SLC_VARIABLE);
373: case SLC_EL:
374: setval(VKILL, SLC_VARIABLE);
375: case SLC_IP:
376: setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
377: case SLC_ABORT:
378: setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
379: case SLC_XON:
380: #ifdef VSTART
381: setval(VSTART, SLC_VARIABLE);
382: #else
383: defval(0x13);
384: #endif
385: case SLC_XOFF:
386: #ifdef VSTOP
387: setval(VSTOP, SLC_VARIABLE);
388: #else
389: defval(0x11);
390: #endif
391: case SLC_EW:
392: #ifdef VWERASE
393: setval(VWERASE, SLC_VARIABLE);
394: #else
395: defval(0);
396: #endif
397: case SLC_RP:
398: #ifdef VREPRINT
399: setval(VREPRINT, SLC_VARIABLE);
400: #else
401: defval(0);
402: #endif
403: case SLC_LNEXT:
404: #ifdef VLNEXT
405: setval(VLNEXT, SLC_VARIABLE);
406: #else
407: defval(0);
408: #endif
409: case SLC_AO:
410: #if !defined(VDISCARD) && defined(VFLUSHO)
411: # define VDISCARD VFLUSHO
412: #endif
413: #ifdef VDISCARD
414: setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
415: #else
416: defval(0);
417: #endif
418: case SLC_SUSP:
419: #ifdef VSUSP
420: setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
421: #else
422: defval(0);
423: #endif
424: #ifdef VEOL
425: case SLC_FORW1:
426: setval(VEOL, SLC_VARIABLE);
427: #endif
428: #ifdef VEOL2
429: case SLC_FORW2:
430: setval(VEOL2, SLC_VARIABLE);
431: #endif
432: case SLC_AYT:
433: #ifdef VSTATUS
434: setval(VSTATUS, SLC_VARIABLE);
435: #else
436: defval(0);
437: #endif
438:
439: case SLC_BRK:
440: case SLC_SYNCH:
441: case SLC_EOR:
442: defval(0);
443:
444: default:
445: *valp = 0;
446: *valpp = 0;
447: return(SLC_NOSUPPORT);
448: }
449: }
450: #endif /* USE_TERMIO */
451:
452: #ifdef CRAY
453: /*
454: * getnpty()
455: *
456: * Return the number of pty's configured into the system.
457: */
458: int
459: getnpty()
460: {
461: #ifdef _SC_CRAY_NPTY
462: int numptys;
463:
464: if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1)
465: return numptys;
466: else
467: #endif /* _SC_CRAY_NPTY */
468: return 128;
469: }
470: #endif /* CRAY */
471:
472: #ifndef convex
473: /*
474: * getpty()
475: *
476: * Allocate a pty. As a side effect, the external character
477: * array "line" contains the name of the slave side.
478: *
479: * Returns the file descriptor of the opened pty.
480: */
481: #ifndef __GNUC__
482: char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
483: #else
484: static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
485: char *line = Xline;
486: #endif
487: #ifdef CRAY
488: char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
489: #endif /* CRAY */
490:
1.13 ! perry 491: #ifdef OPENPTY_PTY
! 492:
! 493: static int ptyslavefd; /* for cleanopen() */
! 494:
! 495: int
! 496: getpty(ptynum)
! 497: int *ptynum;
! 498: {
! 499: int ptyfd;
! 500:
! 501: ptyfd = openpty(ptynum, &ptyslavefd, line, NULL, NULL);
! 502: if (ptyfd == 0)
! 503: return *ptynum;
! 504: ptyslavefd = -1;
! 505: return (-1);
! 506: }
! 507: #else /* ! OPENPTY_PTY */
! 508:
1.1 cgd 509: int
1.3 cgd 510: getpty(ptynum)
511: int *ptynum;
1.1 cgd 512: {
513: register int p;
1.3 cgd 514: #ifdef STREAMSPTY
515: int t;
516: char *ptsname();
517:
518: p = open("/dev/ptmx", 2);
519: if (p > 0) {
520: grantpt(p);
521: unlockpt(p);
522: strcpy(line, ptsname(p));
523: return(p);
524: }
525:
526: #else /* ! STREAMSPTY */
1.1 cgd 527: #ifndef CRAY
1.3 cgd 528: register char *cp, *p1, *p2;
1.1 cgd 529: register int i;
1.3 cgd 530: #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
531: int dummy;
532: #endif
1.1 cgd 533:
1.3 cgd 534: #ifndef __hpux
1.1 cgd 535: (void) sprintf(line, "/dev/ptyXX");
536: p1 = &line[8];
537: p2 = &line[9];
1.3 cgd 538: #else
539: (void) sprintf(line, "/dev/ptym/ptyXX");
540: p1 = &line[13];
541: p2 = &line[14];
542: #endif
1.1 cgd 543:
1.3 cgd 544: for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) {
1.1 cgd 545: struct stat stb;
546:
1.3 cgd 547: *p1 = *cp;
1.1 cgd 548: *p2 = '0';
1.3 cgd 549: /*
550: * This stat() check is just to keep us from
551: * looping through all 256 combinations if there
552: * aren't that many ptys available.
553: */
1.1 cgd 554: if (stat(line, &stb) < 0)
555: break;
556: for (i = 0; i < 16; i++) {
557: *p2 = "0123456789abcdef"[i];
558: p = open(line, 2);
559: if (p > 0) {
1.3 cgd 560: #ifndef __hpux
1.1 cgd 561: line[5] = 't';
1.3 cgd 562: #else
563: for (p1 = &line[8]; *p1; p1++)
564: *p1 = *(p1+1);
565: line[9] = 't';
566: #endif
567: chown(line, 0, 0);
568: chmod(line, 0600);
569: #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207
570: if (ioctl(p, TIOCGPGRP, &dummy) == 0
571: || errno != EIO) {
572: chmod(line, 0666);
573: close(p);
574: line[5] = 'p';
575: } else
576: #endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */
577: return(p);
1.1 cgd 578: }
579: }
580: }
581: #else /* CRAY */
582: extern lowpty, highpty;
583: struct stat sb;
584:
1.3 cgd 585: for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) {
586: (void) sprintf(myline, "/dev/pty/%03d", *ptynum);
1.1 cgd 587: p = open(myline, 2);
588: if (p < 0)
589: continue;
1.3 cgd 590: (void) sprintf(line, "/dev/ttyp%03d", *ptynum);
1.1 cgd 591: /*
592: * Here are some shenanigans to make sure that there
593: * are no listeners lurking on the line.
594: */
595: if(stat(line, &sb) < 0) {
596: (void) close(p);
597: continue;
598: }
599: if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
600: chown(line, 0, 0);
601: chmod(line, 0600);
602: (void)close(p);
603: p = open(myline, 2);
604: if (p < 0)
605: continue;
606: }
607: /*
608: * Now it should be safe...check for accessability.
609: */
610: if (access(line, 6) == 0)
611: return(p);
612: else {
613: /* no tty side to pty so skip it */
614: (void) close(p);
615: }
616: }
617: #endif /* CRAY */
1.3 cgd 618: #endif /* STREAMSPTY */
1.1 cgd 619: return(-1);
620: }
1.13 ! perry 621: #endif /* OPENPTY_PTY */
1.1 cgd 622: #endif /* convex */
623:
624: #ifdef LINEMODE
625: /*
626: * tty_flowmode() Find out if flow control is enabled or disabled.
627: * tty_linemode() Find out if linemode (external processing) is enabled.
628: * tty_setlinemod(on) Turn on/off linemode.
629: * tty_isecho() Find out if echoing is turned on.
630: * tty_setecho(on) Enable/disable character echoing.
631: * tty_israw() Find out if terminal is in RAW mode.
632: * tty_binaryin(on) Turn on/off BINARY on input.
633: * tty_binaryout(on) Turn on/off BINARY on output.
634: * tty_isediting() Find out if line editing is enabled.
635: * tty_istrapsig() Find out if signal trapping is enabled.
636: * tty_setedit(on) Turn on/off line editing.
637: * tty_setsig(on) Turn on/off signal trapping.
638: * tty_issofttab() Find out if tab expansion is enabled.
639: * tty_setsofttab(on) Turn on/off soft tab expansion.
640: * tty_islitecho() Find out if typed control chars are echoed literally
641: * tty_setlitecho() Turn on/off literal echo of control chars
642: * tty_tspeed(val) Set transmit speed to val.
643: * tty_rspeed(val) Set receive speed to val.
644: */
645:
646: #ifdef convex
647: static int linestate;
648: #endif
649:
650: int
651: tty_linemode()
652: {
653: #ifndef convex
654: #ifndef USE_TERMIO
655: return(termbuf.state & TS_EXTPROC);
656: #else
657: return(termbuf.c_lflag & EXTPROC);
658: #endif
659: #else
660: return(linestate);
661: #endif
662: }
663:
664: void
665: tty_setlinemode(on)
666: int on;
667: {
668: #ifdef TIOCEXT
669: # ifndef convex
670: set_termbuf();
671: # else
672: linestate = on;
673: # endif
674: (void) ioctl(pty, TIOCEXT, (char *)&on);
675: # ifndef convex
676: init_termbuf();
677: # endif
678: #else /* !TIOCEXT */
679: # ifdef EXTPROC
680: if (on)
681: termbuf.c_lflag |= EXTPROC;
682: else
683: termbuf.c_lflag &= ~EXTPROC;
684: # endif
685: #endif /* TIOCEXT */
686: }
1.3 cgd 687: #endif /* LINEMODE */
1.1 cgd 688:
689: int
690: tty_isecho()
691: {
692: #ifndef USE_TERMIO
693: return (termbuf.sg.sg_flags & ECHO);
694: #else
695: return (termbuf.c_lflag & ECHO);
696: #endif
697: }
1.3 cgd 698:
699: int
700: tty_flowmode()
701: {
702: #ifndef USE_TERMIO
703: return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0);
704: #else
705: return((termbuf.c_iflag & IXON) ? 1 : 0);
706: #endif
707: }
708:
709: int
710: tty_restartany()
711: {
712: #ifndef USE_TERMIO
713: # ifdef DECCTQ
714: return((termbuf.lflags & DECCTQ) ? 0 : 1);
715: # else
716: return(-1);
717: # endif
718: #else
719: return((termbuf.c_iflag & IXANY) ? 1 : 0);
720: #endif
721: }
1.1 cgd 722:
723: void
724: tty_setecho(on)
725: int on;
726: {
727: #ifndef USE_TERMIO
728: if (on)
729: termbuf.sg.sg_flags |= ECHO|CRMOD;
730: else
731: termbuf.sg.sg_flags &= ~(ECHO|CRMOD);
732: #else
733: if (on)
734: termbuf.c_lflag |= ECHO;
735: else
736: termbuf.c_lflag &= ~ECHO;
737: #endif
738: }
739:
740: int
741: tty_israw()
742: {
743: #ifndef USE_TERMIO
744: return(termbuf.sg.sg_flags & RAW);
745: #else
746: return(!(termbuf.c_lflag & ICANON));
747: #endif
748: }
1.3 cgd 749:
750: #if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
751: int
752: tty_setraw(on)
753: {
754: # ifndef USE_TERMIO
755: if (on)
756: termbuf.sg.sg_flags |= RAW;
757: else
758: termbuf.sg.sg_flags &= ~RAW;
759: # else
760: if (on)
761: termbuf.c_lflag &= ~ICANON;
762: else
763: termbuf.c_lflag |= ICANON;
764: # endif
765: }
766: #endif
1.1 cgd 767:
768: void
769: tty_binaryin(on)
770: int on;
771: {
772: #ifndef USE_TERMIO
773: if (on)
774: termbuf.lflags |= LPASS8;
775: else
776: termbuf.lflags &= ~LPASS8;
777: #else
778: if (on) {
779: termbuf.c_iflag &= ~ISTRIP;
780: } else {
781: termbuf.c_iflag |= ISTRIP;
782: }
783: #endif
784: }
785:
786: void
787: tty_binaryout(on)
788: int on;
789: {
790: #ifndef USE_TERMIO
791: if (on)
792: termbuf.lflags |= LLITOUT;
793: else
794: termbuf.lflags &= ~LLITOUT;
795: #else
796: if (on) {
797: termbuf.c_cflag &= ~(CSIZE|PARENB);
798: termbuf.c_cflag |= CS8;
799: termbuf.c_oflag &= ~OPOST;
800: } else {
801: termbuf.c_cflag &= ~CSIZE;
802: termbuf.c_cflag |= CS7|PARENB;
803: termbuf.c_oflag |= OPOST;
804: }
805: #endif
806: }
807:
808: int
809: tty_isbinaryin()
810: {
811: #ifndef USE_TERMIO
812: return(termbuf.lflags & LPASS8);
813: #else
814: return(!(termbuf.c_iflag & ISTRIP));
815: #endif
816: }
817:
818: int
819: tty_isbinaryout()
820: {
821: #ifndef USE_TERMIO
822: return(termbuf.lflags & LLITOUT);
823: #else
824: return(!(termbuf.c_oflag&OPOST));
825: #endif
826: }
827:
828: #ifdef LINEMODE
829: int
830: tty_isediting()
831: {
832: #ifndef USE_TERMIO
833: return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
834: #else
835: return(termbuf.c_lflag & ICANON);
836: #endif
837: }
838:
839: int
840: tty_istrapsig()
841: {
842: #ifndef USE_TERMIO
843: return(!(termbuf.sg.sg_flags&RAW));
844: #else
845: return(termbuf.c_lflag & ISIG);
846: #endif
847: }
848:
849: void
850: tty_setedit(on)
851: int on;
852: {
853: #ifndef USE_TERMIO
854: if (on)
855: termbuf.sg.sg_flags &= ~CBREAK;
856: else
857: termbuf.sg.sg_flags |= CBREAK;
858: #else
859: if (on)
860: termbuf.c_lflag |= ICANON;
861: else
862: termbuf.c_lflag &= ~ICANON;
863: #endif
864: }
865:
866: void
867: tty_setsig(on)
868: int on;
869: {
870: #ifndef USE_TERMIO
871: if (on)
872: ;
873: #else
874: if (on)
875: termbuf.c_lflag |= ISIG;
876: else
877: termbuf.c_lflag &= ~ISIG;
878: #endif
879: }
880: #endif /* LINEMODE */
881:
882: int
883: tty_issofttab()
884: {
885: #ifndef USE_TERMIO
886: return (termbuf.sg.sg_flags & XTABS);
887: #else
888: # ifdef OXTABS
889: return (termbuf.c_oflag & OXTABS);
890: # endif
891: # ifdef TABDLY
892: return ((termbuf.c_oflag & TABDLY) == TAB3);
893: # endif
894: #endif
895: }
896:
897: void
898: tty_setsofttab(on)
899: int on;
900: {
901: #ifndef USE_TERMIO
902: if (on)
903: termbuf.sg.sg_flags |= XTABS;
904: else
905: termbuf.sg.sg_flags &= ~XTABS;
906: #else
907: if (on) {
908: # ifdef OXTABS
909: termbuf.c_oflag |= OXTABS;
910: # endif
911: # ifdef TABDLY
912: termbuf.c_oflag &= ~TABDLY;
913: termbuf.c_oflag |= TAB3;
914: # endif
915: } else {
916: # ifdef OXTABS
917: termbuf.c_oflag &= ~OXTABS;
918: # endif
919: # ifdef TABDLY
920: termbuf.c_oflag &= ~TABDLY;
921: termbuf.c_oflag |= TAB0;
922: # endif
923: }
924: #endif
925: }
926:
927: int
928: tty_islitecho()
929: {
930: #ifndef USE_TERMIO
931: return (!(termbuf.lflags & LCTLECH));
932: #else
933: # ifdef ECHOCTL
934: return (!(termbuf.c_lflag & ECHOCTL));
935: # endif
936: # ifdef TCTLECH
937: return (!(termbuf.c_lflag & TCTLECH));
938: # endif
939: # if !defined(ECHOCTL) && !defined(TCTLECH)
940: return (0); /* assumes ctl chars are echoed '^x' */
941: # endif
942: #endif
943: }
944:
945: void
946: tty_setlitecho(on)
947: int on;
948: {
949: #ifndef USE_TERMIO
950: if (on)
951: termbuf.lflags &= ~LCTLECH;
952: else
953: termbuf.lflags |= LCTLECH;
954: #else
955: # ifdef ECHOCTL
956: if (on)
957: termbuf.c_lflag &= ~ECHOCTL;
958: else
959: termbuf.c_lflag |= ECHOCTL;
960: # endif
961: # ifdef TCTLECH
962: if (on)
963: termbuf.c_lflag &= ~TCTLECH;
964: else
965: termbuf.c_lflag |= TCTLECH;
966: # endif
967: #endif
968: }
969:
970: int
971: tty_iscrnl()
972: {
973: #ifndef USE_TERMIO
974: return (termbuf.sg.sg_flags & CRMOD);
975: #else
976: return (termbuf.c_iflag & ICRNL);
977: #endif
978: }
979:
980: /*
1.6 jtk 981: * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
982: */
983: #if B4800 != 4800
984: #define DECODE_BAUD
985: #endif
986:
987: #ifdef DECODE_BAUD
988:
989: /*
1.1 cgd 990: * A table of available terminal speeds
991: */
992: struct termspeeds {
993: int speed;
994: int value;
995: } termspeeds[] = {
1.6 jtk 996: { 0, B0 }, { 50, B50 }, { 75, B75 },
997: { 110, B110 }, { 134, B134 }, { 150, B150 },
998: { 200, B200 }, { 300, B300 }, { 600, B600 },
999: { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 },
1000: { 4800, B4800 },
1001: #ifdef B7200
1002: { 7200, B7200 },
1003: #endif
1004: { 9600, B9600 },
1005: #ifdef B14400
1006: { 14400, B14400 },
1007: #endif
1008: #ifdef B19200
1009: { 19200, B19200 },
1010: #endif
1011: #ifdef B28800
1012: { 28800, B28800 },
1013: #endif
1014: #ifdef B38400
1015: { 38400, B38400 },
1016: #endif
1017: #ifdef B57600
1018: { 57600, B57600 },
1019: #endif
1020: #ifdef B115200
1021: { 115200, B115200 },
1022: #endif
1023: #ifdef B230400
1024: { 230400, B230400 },
1025: #endif
1026: { -1, 0 }
1.1 cgd 1027: };
1.6 jtk 1028: #endif /* DECODE_BUAD */
1.1 cgd 1029:
1030: void
1031: tty_tspeed(val)
1032: int val;
1033: {
1.6 jtk 1034: #ifdef DECODE_BAUD
1.1 cgd 1035: register struct termspeeds *tp;
1036:
1037: for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
1038: ;
1.6 jtk 1039: if (tp->speed == -1) /* back up to last valid value */
1040: --tp;
1.1 cgd 1041: cfsetospeed(&termbuf, tp->value);
1.6 jtk 1042: #else /* DECODE_BUAD */
1043: cfsetospeed(&termbuf, val);
1044: #endif /* DECODE_BUAD */
1.1 cgd 1045: }
1046:
1047: void
1048: tty_rspeed(val)
1049: int val;
1050: {
1.6 jtk 1051: #ifdef DECODE_BAUD
1.1 cgd 1052: register struct termspeeds *tp;
1053:
1054: for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
1055: ;
1.6 jtk 1056: if (tp->speed == -1) /* back up to last valid value */
1057: --tp;
1.1 cgd 1058: cfsetispeed(&termbuf, tp->value);
1.6 jtk 1059: #else /* DECODE_BAUD */
1060: cfsetispeed(&termbuf, val);
1061: #endif /* DECODE_BAUD */
1.1 cgd 1062: }
1063:
1064: #if defined(CRAY2) && defined(UNICOS5)
1065: int
1066: tty_isnewmap()
1067: {
1068: return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) &&
1069: !(termbuf.c_oflag & ONLRET));
1070: }
1071: #endif
1072:
1.3 cgd 1073: #ifdef PARENT_DOES_UTMP
1.1 cgd 1074: # ifndef NEWINIT
1075: extern struct utmp wtmp;
1076: extern char wtmpf[];
1077: # else /* NEWINIT */
1078: int gotalarm;
1079:
1080: /* ARGSUSED */
1081: void
1082: nologinproc(sig)
1083: int sig;
1084: {
1085: gotalarm++;
1086: }
1087: # endif /* NEWINIT */
1.3 cgd 1088: #endif /* PARENT_DOES_UTMP */
1.1 cgd 1089:
1090: #ifndef NEWINIT
1.3 cgd 1091: # ifdef PARENT_DOES_UTMP
1.1 cgd 1092: extern void utmp_sig_init P((void));
1093: extern void utmp_sig_reset P((void));
1094: extern void utmp_sig_wait P((void));
1095: extern void utmp_sig_notify P((int));
1.3 cgd 1096: # endif /* PARENT_DOES_UTMP */
1.1 cgd 1097: #endif
1098:
1099: /*
1100: * getptyslave()
1101: *
1102: * Open the slave side of the pty, and do any initialization
1103: * that is necessary. The return value is a file descriptor
1104: * for the slave side.
1105: */
1.11 mrg 1106: void
1.1 cgd 1107: getptyslave()
1108: {
1109: register int t = -1;
1110:
1111: #if !defined(CRAY) || !defined(NEWINIT)
1112: # ifdef LINEMODE
1113: int waslm;
1114: # endif
1115: # ifdef TIOCGWINSZ
1116: struct winsize ws;
1117: extern int def_row, def_col;
1118: # endif
1119: extern int def_tspeed, def_rspeed;
1120: /*
1121: * Opening the slave side may cause initilization of the
1122: * kernel tty structure. We need remember the state of
1123: * if linemode was turned on
1124: * terminal window size
1125: * terminal speed
1126: * so that we can re-set them if we need to.
1127: */
1128: # ifdef LINEMODE
1129: waslm = tty_linemode();
1130: # endif
1131:
1132:
1133: /*
1134: * Make sure that we don't have a controlling tty, and
1135: * that we are the session (process group) leader.
1136: */
1137: # ifdef TIOCNOTTY
1138: t = open(_PATH_TTY, O_RDWR);
1139: if (t >= 0) {
1140: (void) ioctl(t, TIOCNOTTY, (char *)0);
1141: (void) close(t);
1142: }
1143: # endif
1144:
1145:
1.3 cgd 1146: # ifdef PARENT_DOES_UTMP
1.1 cgd 1147: /*
1148: * Wait for our parent to get the utmp stuff to get done.
1149: */
1150: utmp_sig_wait();
1151: # endif
1152:
1153: t = cleanopen(line);
1154: if (t < 0)
1155: fatalperror(net, line);
1156:
1.3 cgd 1157: #ifdef STREAMSPTY
1158: #ifdef USE_TERMIO
1159: ttyfd = t;
1160: #endif
1.6 jtk 1161: if (ioctl(t, I_PUSH, "ptem") < 0)
1.3 cgd 1162: fatal(net, "I_PUSH ptem");
1163: if (ioctl(t, I_PUSH, "ldterm") < 0)
1164: fatal(net, "I_PUSH ldterm");
1165: if (ioctl(t, I_PUSH, "ttcompat") < 0)
1166: fatal(net, "I_PUSH ttcompat");
1167: if (ioctl(pty, I_PUSH, "pckt") < 0)
1168: fatal(net, "I_PUSH pckt");
1169: #endif
1170:
1.1 cgd 1171: /*
1172: * set up the tty modes as we like them to be.
1173: */
1174: init_termbuf();
1175: # ifdef TIOCGWINSZ
1176: if (def_row || def_col) {
1.6 jtk 1177: memset((char *)&ws, 0, sizeof(ws));
1.1 cgd 1178: ws.ws_col = def_col;
1179: ws.ws_row = def_row;
1180: (void)ioctl(t, TIOCSWINSZ, (char *)&ws);
1181: }
1182: # endif
1183:
1184: /*
1185: * Settings for sgtty based systems
1186: */
1187: # ifndef USE_TERMIO
1188: termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
1189: # endif /* USE_TERMIO */
1190:
1191: /*
1.3 cgd 1192: * Settings for UNICOS (and HPUX)
1.1 cgd 1193: */
1.3 cgd 1194: # if defined(CRAY) || defined(__hpux)
1.1 cgd 1195: termbuf.c_oflag = OPOST|ONLCR|TAB3;
1196: termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
1197: termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
1198: termbuf.c_cflag = EXTB|HUPCL|CS8;
1199: # endif
1200:
1201: /*
1202: * Settings for all other termios/termio based
1203: * systems, other than 4.4BSD. In 4.4BSD the
1204: * kernel does the initial terminal setup.
1205: */
1.3 cgd 1206: # if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43)
1.1 cgd 1207: # ifndef OXTABS
1208: # define OXTABS 0
1209: # endif
1210: termbuf.c_lflag |= ECHO;
1211: termbuf.c_oflag |= ONLCR|OXTABS;
1212: termbuf.c_iflag |= ICRNL;
1213: termbuf.c_iflag &= ~IXOFF;
1214: # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */
1215: tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
1216: tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
1217: # ifdef LINEMODE
1218: if (waslm)
1219: tty_setlinemode(1);
1220: # endif /* LINEMODE */
1221:
1222: /*
1223: * Set the tty modes, and make this our controlling tty.
1224: */
1225: set_termbuf();
1226: if (login_tty(t) == -1)
1227: fatalperror(net, "login_tty");
1228: #endif /* !defined(CRAY) || !defined(NEWINIT) */
1229: if (net > 2)
1230: (void) close(net);
1.3 cgd 1231: #if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
1232: /*
1233: * Leave the pty open so that we can write out the rlogin
1234: * protocol for /bin/login, if the authentication works.
1235: */
1236: #else
1237: if (pty > 2) {
1.1 cgd 1238: (void) close(pty);
1.3 cgd 1239: pty = -1;
1240: }
1241: #endif
1.1 cgd 1242: }
1243:
1244: #if !defined(CRAY) || !defined(NEWINIT)
1245: #ifndef O_NOCTTY
1246: #define O_NOCTTY 0
1247: #endif
1248: /*
1249: * Open the specified slave side of the pty,
1250: * making sure that we have a clean tty.
1251: */
1252: int
1253: cleanopen(line)
1254: char *line;
1255: {
1.13 ! perry 1256: #ifdef OPENPTY_PTY
! 1257: return ptyslavefd;
! 1258: #else /* ! OPENPTY_PTY */
1.1 cgd 1259: register int t;
1.6 jtk 1260: #ifdef UNICOS7x
1.3 cgd 1261: struct secstat secbuf;
1.6 jtk 1262: #endif /* UNICOS7x */
1.1 cgd 1263:
1.3 cgd 1264: #ifndef STREAMSPTY
1.1 cgd 1265: /*
1266: * Make sure that other people can't open the
1267: * slave side of the connection.
1268: */
1269: (void) chown(line, 0, 0);
1270: (void) chmod(line, 0600);
1.3 cgd 1271: #endif
1.1 cgd 1272:
1273: # if !defined(CRAY) && (BSD > 43)
1274: (void) revoke(line);
1275: # endif
1.6 jtk 1276: #ifdef UNICOS7x
1.3 cgd 1277: if (secflag) {
1278: if (secstat(line, &secbuf) < 0)
1279: return(-1);
1280: if (setulvl(secbuf.st_slevel) < 0)
1281: return(-1);
1282: if (setucmp(secbuf.st_compart) < 0)
1283: return(-1);
1284: }
1.6 jtk 1285: #endif /* UNICOS7x */
1.3 cgd 1286:
1.1 cgd 1287: t = open(line, O_RDWR|O_NOCTTY);
1.3 cgd 1288:
1.6 jtk 1289: #ifdef UNICOS7x
1.3 cgd 1290: if (secflag) {
1291: if (setulvl(sysv.sy_minlvl) < 0)
1292: return(-1);
1293: if (setucmp(0) < 0)
1294: return(-1);
1295: }
1.6 jtk 1296: #endif /* UNICOS7x */
1.3 cgd 1297:
1.1 cgd 1298: if (t < 0)
1299: return(-1);
1300:
1301: /*
1302: * Hangup anybody else using this ttyp, then reopen it for
1303: * ourselves.
1304: */
1.3 cgd 1305: # if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY)
1.1 cgd 1306: (void) signal(SIGHUP, SIG_IGN);
1307: vhangup();
1308: (void) signal(SIGHUP, SIG_DFL);
1309: t = open(line, O_RDWR|O_NOCTTY);
1310: if (t < 0)
1311: return(-1);
1312: # endif
1313: # if defined(CRAY) && defined(TCVHUP)
1314: {
1315: register int i;
1316: (void) signal(SIGHUP, SIG_IGN);
1317: (void) ioctl(t, TCVHUP, (char *)0);
1318: (void) signal(SIGHUP, SIG_DFL);
1.3 cgd 1319:
1.6 jtk 1320: #ifdef UNICOS7x
1.3 cgd 1321: if (secflag) {
1322: if (secstat(line, &secbuf) < 0)
1323: return(-1);
1324: if (setulvl(secbuf.st_slevel) < 0)
1325: return(-1);
1326: if (setucmp(secbuf.st_compart) < 0)
1327: return(-1);
1328: }
1.6 jtk 1329: #endif /* UNICOS7x */
1.3 cgd 1330:
1.1 cgd 1331: i = open(line, O_RDWR);
1.3 cgd 1332:
1.6 jtk 1333: #ifdef UNICOS7x
1.3 cgd 1334: if (secflag) {
1335: if (setulvl(sysv.sy_minlvl) < 0)
1336: return(-1);
1337: if (setucmp(0) < 0)
1338: return(-1);
1339: }
1.6 jtk 1340: #endif /* UNICOS7x */
1.3 cgd 1341:
1.1 cgd 1342: if (i < 0)
1343: return(-1);
1344: (void) close(t);
1345: t = i;
1346: }
1347: # endif /* defined(CRAY) && defined(TCVHUP) */
1348: return(t);
1.13 ! perry 1349: #endif /* OPENPTY_PTY */
1.1 cgd 1350: }
1351: #endif /* !defined(CRAY) || !defined(NEWINIT) */
1352:
1353: #if BSD <= 43
1.3 cgd 1354:
1.1 cgd 1355: int
1356: login_tty(t)
1357: int t;
1358: {
1.3 cgd 1359: if (setsid() < 0) {
1360: #ifdef ultrix
1361: /*
1362: * The setsid() may have failed because we
1363: * already have a pgrp == pid. Zero out
1364: * our pgrp and try again...
1365: */
1366: if ((setpgrp(0, 0) < 0) || (setsid() < 0))
1367: #endif
1368: fatalperror(net, "setsid()");
1369: }
1.1 cgd 1370: # ifdef TIOCSCTTY
1371: if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
1372: fatalperror(net, "ioctl(sctty)");
1.3 cgd 1373: # if defined(CRAY)
1.1 cgd 1374: /*
1375: * Close the hard fd to /dev/ttypXXX, and re-open through
1376: * the indirect /dev/tty interface.
1377: */
1378: close(t);
1379: if ((t = open("/dev/tty", O_RDWR)) < 0)
1380: fatalperror(net, "open(/dev/tty)");
1381: # endif
1382: # else
1.3 cgd 1383: /*
1384: * We get our controlling tty assigned as a side-effect
1385: * of opening up a tty device. But on BSD based systems,
1386: * this only happens if our process group is zero. The
1387: * setsid() call above may have set our pgrp, so clear
1388: * it out before opening the tty...
1389: */
1.6 jtk 1390: # ifndef SOLARIS
1.3 cgd 1391: (void) setpgrp(0, 0);
1.6 jtk 1392: # else
1393: (void) setpgrp();
1394: # endif
1.1 cgd 1395: close(open(line, O_RDWR));
1396: # endif
1397: if (t != 0)
1398: (void) dup2(t, 0);
1399: if (t != 1)
1400: (void) dup2(t, 1);
1401: if (t != 2)
1402: (void) dup2(t, 2);
1403: if (t > 2)
1404: close(t);
1405: return(0);
1406: }
1407: #endif /* BSD <= 43 */
1408:
1409: #ifdef NEWINIT
1410: char *gen_id = "fe";
1411: #endif
1412:
1413: /*
1414: * startslave(host)
1415: *
1416: * Given a hostname, do whatever
1417: * is necessary to startup the login process on the slave side of the pty.
1418: */
1419:
1420: /* ARGSUSED */
1421: void
1422: startslave(host, autologin, autoname)
1423: char *host;
1424: int autologin;
1425: char *autoname;
1426: {
1427: register int i;
1428: #ifdef NEWINIT
1429: extern char *ptyip;
1430: struct init_request request;
1431: void nologinproc();
1432: register int n;
1433: #endif /* NEWINIT */
1434:
1.3 cgd 1435: #if defined(AUTHENTICATION)
1.1 cgd 1436: if (!autoname || !autoname[0])
1437: autologin = 0;
1438:
1439: if (autologin < auth_level) {
1440: fatal(net, "Authorization failed");
1441: exit(1);
1442: }
1443: #endif
1444:
1445: #ifndef NEWINIT
1.3 cgd 1446: # ifdef PARENT_DOES_UTMP
1.1 cgd 1447: utmp_sig_init();
1.3 cgd 1448: # endif /* PARENT_DOES_UTMP */
1.1 cgd 1449:
1450: if ((i = fork()) < 0)
1451: fatalperror(net, "fork");
1452: if (i) {
1.3 cgd 1453: # ifdef PARENT_DOES_UTMP
1.1 cgd 1454: /*
1455: * Cray parent will create utmp entry for child and send
1456: * signal to child to tell when done. Child waits for signal
1457: * before doing anything important.
1458: */
1459: register int pid = i;
1460: void sigjob P((int));
1461:
1462: setpgrp();
1463: utmp_sig_reset(); /* reset handler to default */
1464: /*
1465: * Create utmp entry for child
1466: */
1467: (void) time(&wtmp.ut_time);
1468: wtmp.ut_type = LOGIN_PROCESS;
1469: wtmp.ut_pid = pid;
1470: SCPYN(wtmp.ut_user, "LOGIN");
1471: SCPYN(wtmp.ut_host, host);
1472: SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1);
1.3 cgd 1473: #ifndef __hpux
1.1 cgd 1474: SCPYN(wtmp.ut_id, wtmp.ut_line+3);
1.3 cgd 1475: #else
1476: SCPYN(wtmp.ut_id, wtmp.ut_line+7);
1477: #endif
1.1 cgd 1478: pututline(&wtmp);
1479: endutent();
1480: if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
1481: (void) write(i, (char *)&wtmp, sizeof(struct utmp));
1482: (void) close(i);
1483: }
1.3 cgd 1484: #ifdef CRAY
1.1 cgd 1485: (void) signal(WJSIGNAL, sigjob);
1.3 cgd 1486: #endif
1.1 cgd 1487: utmp_sig_notify(pid);
1.3 cgd 1488: # endif /* PARENT_DOES_UTMP */
1.1 cgd 1489: } else {
1.11 mrg 1490: getptyslave();
1.1 cgd 1491: start_login(host, autologin, autoname);
1492: /*NOTREACHED*/
1493: }
1494: #else /* NEWINIT */
1495:
1496: /*
1497: * Init will start up login process if we ask nicely. We only wait
1498: * for it to start up and begin normal telnet operation.
1499: */
1500: if ((i = open(INIT_FIFO, O_WRONLY)) < 0) {
1501: char tbuf[128];
1.11 mrg 1502:
1503: (void)snprintf(tbuf, sizeof tbuf, "Can't open %s\n", INIT_FIFO);
1.1 cgd 1504: fatalperror(net, tbuf);
1505: }
1506: memset((char *)&request, 0, sizeof(request));
1507: request.magic = INIT_MAGIC;
1508: SCPYN(request.gen_id, gen_id);
1509: SCPYN(request.tty_id, &line[8]);
1510: SCPYN(request.host, host);
1511: SCPYN(request.term_type, terminaltype ? terminaltype : "network");
1512: #if !defined(UNICOS5)
1513: request.signal = SIGCLD;
1514: request.pid = getpid();
1515: #endif
1516: #ifdef BFTPDAEMON
1517: /*
1518: * Are we working as the bftp daemon?
1519: */
1520: if (bftpd) {
1521: SCPYN(request.exec_name, BFTPPATH);
1522: }
1523: #endif /* BFTPDAEMON */
1524: if (write(i, (char *)&request, sizeof(request)) < 0) {
1525: char tbuf[128];
1.11 mrg 1526:
1527: (void)snprintf(tbuf, sizeof tbuf, "Can't write to %s\n", INIT_FIFO);
1.1 cgd 1528: fatalperror(net, tbuf);
1529: }
1530: (void) close(i);
1531: (void) signal(SIGALRM, nologinproc);
1532: for (i = 0; ; i++) {
1533: char tbuf[128];
1.11 mrg 1534:
1.1 cgd 1535: alarm(15);
1536: n = read(pty, ptyip, BUFSIZ);
1537: if (i == 3 || n >= 0 || !gotalarm)
1538: break;
1539: gotalarm = 0;
1.11 mrg 1540: (void)snprintf(tbuf, sizeof tbuf,
1541: "telnetd: waiting for /etc/init to start login process on %s\r\n", line);
1542: (void)write(net, tbuf, strlen(tbuf));
1.1 cgd 1543: }
1544: if (n < 0 && gotalarm)
1545: fatal(net, "/etc/init didn't start login process");
1546: pcc += n;
1547: alarm(0);
1548: (void) signal(SIGALRM, SIG_DFL);
1549:
1550: return;
1551: #endif /* NEWINIT */
1552: }
1553:
1554: char *envinit[3];
1555: extern char **environ;
1556:
1557: void
1558: init_env()
1559: {
1560: char **envp;
1561:
1562: envp = envinit;
1.11 mrg 1563: if ((*envp = getenv("TZ")))
1.1 cgd 1564: *envp++ -= 3;
1.3 cgd 1565: #if defined(CRAY) || defined(__hpux)
1.1 cgd 1566: else
1567: *envp++ = "TZ=GMT0";
1568: #endif
1569: *envp = 0;
1570: environ = envinit;
1571: }
1572:
1573: #ifndef NEWINIT
1574:
1575: /*
1576: * start_login(host)
1577: *
1578: * Assuming that we are now running as a child processes, this
1579: * function will turn us into the login process.
1580: */
1581:
1582: void
1583: start_login(host, autologin, name)
1584: char *host;
1585: int autologin;
1586: char *name;
1587: {
1588: register char **argv;
1.9 tls 1589: extern char *gettyname;
1590: #define TABBUFSIZ 512
1591: char defent[TABBUFSIZ];
1592: char defstrs[TABBUFSIZ];
1593: #undef TABBUFSIZ
1.11 mrg 1594: char *loginprog = NULL;
1.3 cgd 1595: #ifdef UTMPX
1596: register int pid = getpid();
1597: struct utmpx utmpx;
1598: #endif
1599: #ifdef SOLARIS
1600: char *term;
1601: char termbuf[64];
1602: #endif
1603:
1604: #ifdef UTMPX
1605: /*
1606: * Create utmp entry for child
1607: */
1608:
1.6 jtk 1609: memset(&utmpx, 0, sizeof(utmpx));
1.3 cgd 1610: SCPYN(utmpx.ut_user, ".telnet");
1611: SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
1612: utmpx.ut_pid = pid;
1613: utmpx.ut_id[0] = 't';
1614: utmpx.ut_id[1] = 'n';
1615: utmpx.ut_id[2] = SC_WILDC;
1616: utmpx.ut_id[3] = SC_WILDC;
1617: utmpx.ut_type = LOGIN_PROCESS;
1618: (void) time(&utmpx.ut_tv.tv_sec);
1619: if (makeutx(&utmpx) == NULL)
1620: fatal(net, "makeutx failed");
1621: #endif
1.1 cgd 1622:
1.6 jtk 1623: scrub_env();
1624:
1.1 cgd 1625: /*
1626: * -h : pass on name of host.
1627: * WARNING: -h is accepted by login if and only if
1628: * getuid() == 0.
1629: * -p : don't clobber the environment (so terminal type stays set).
1630: *
1631: * -f : force this login, he has already been authenticated
1632: */
1633: argv = addarg(0, "login");
1.3 cgd 1634:
1635: #if !defined(NO_LOGIN_H)
1636:
1637: # if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
1638: /*
1639: * Don't add the "-h host" option if we are going
1640: * to be adding the "-r host" option down below...
1641: */
1642: if ((auth_level < 0) || (autologin != AUTH_VALID))
1643: # endif
1644: {
1645: argv = addarg(argv, "-h");
1646: argv = addarg(argv, host);
1647: #ifdef SOLARIS
1648: /*
1649: * SVR4 version of -h takes TERM= as second arg, or -
1650: */
1651: term = getenv("TERM");
1652: if (term == NULL || term[0] == 0) {
1653: term = "-";
1654: } else {
1655: strcpy(termbuf, "TERM=");
1656: strncat(termbuf, term, sizeof(termbuf) - 6);
1657: term = termbuf;
1658: }
1659: argv = addarg(argv, term);
1660: #endif
1661: }
1662: #endif
1.1 cgd 1663: #if !defined(NO_LOGIN_P)
1664: argv = addarg(argv, "-p");
1665: #endif
1.6 jtk 1666: #ifdef LINEMODE
1667: /*
1668: * Set the environment variable "LINEMODE" to either
1669: * "real" or "kludge" if we are operating in either
1670: * real or kludge linemode.
1671: */
1672: if (lmodetype == REAL_LINEMODE)
1673: setenv("LINEMODE", "real", 1);
1674: # ifdef KLUDGELINEMODE
1675: else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK)
1676: setenv("LINEMODE", "kludge", 1);
1677: # endif
1678: #endif
1.1 cgd 1679: #ifdef BFTPDAEMON
1680: /*
1681: * Are we working as the bftp daemon? If so, then ask login
1682: * to start bftp instead of shell.
1683: */
1684: if (bftpd) {
1685: argv = addarg(argv, "-e");
1686: argv = addarg(argv, BFTPPATH);
1.6 jtk 1687: } else
1.1 cgd 1688: #endif
1689: #if defined (SecurID)
1690: /*
1691: * don't worry about the -f that might get sent.
1692: * A -s is supposed to override it anyhow.
1693: */
1694: if (require_SecurID)
1695: argv = addarg(argv, "-s");
1696: #endif
1.3 cgd 1697: #if defined (AUTHENTICATION)
1.1 cgd 1698: if (auth_level >= 0 && autologin == AUTH_VALID) {
1699: # if !defined(NO_LOGIN_F)
1700: argv = addarg(argv, "-f");
1.5 mycroft 1701: argv = addarg(argv, "--");
1.3 cgd 1702: argv = addarg(argv, name);
1703: # else
1704: # if defined(LOGIN_R)
1705: /*
1706: * We don't have support for "login -f", but we
1707: * can fool /bin/login into thinking that we are
1708: * rlogind, and allow us to log in without a
1709: * password. The rlogin protocol expects
1710: * local-user\0remote-user\0term/speed\0
1711: */
1712:
1713: if (pty > 2) {
1714: register char *cp;
1715: char speed[128];
1716: int isecho, israw, xpty, len;
1717: extern int def_rspeed;
1718: # ifndef LOGIN_HOST
1719: /*
1720: * Tell login that we are coming from "localhost".
1721: * If we passed in the real host name, then the
1722: * user would have to allow .rhost access from
1723: * every machine that they want authenticated
1724: * access to work from, which sort of defeats
1725: * the purpose of an authenticated login...
1726: * So, we tell login that the session is coming
1727: * from "localhost", and the user will only have
1728: * to have "localhost" in their .rhost file.
1729: */
1730: # define LOGIN_HOST "localhost"
1731: # endif
1732: argv = addarg(argv, "-r");
1733: argv = addarg(argv, LOGIN_HOST);
1734:
1735: xpty = pty;
1736: # ifndef STREAMSPTY
1737: pty = 0;
1738: # else
1739: ttyfd = 0;
1.1 cgd 1740: # endif
1.3 cgd 1741: init_termbuf();
1742: isecho = tty_isecho();
1743: israw = tty_israw();
1744: if (isecho || !israw) {
1745: tty_setecho(0); /* Turn off echo */
1746: tty_setraw(1); /* Turn on raw */
1747: set_termbuf();
1748: }
1749: len = strlen(name)+1;
1750: write(xpty, name, len);
1751: write(xpty, name, len);
1752: sprintf(speed, "%s/%d", (cp = getenv("TERM")) ? cp : "",
1753: (def_rspeed > 0) ? def_rspeed : 9600);
1754: len = strlen(speed)+1;
1755: write(xpty, speed, len);
1756:
1757: if (isecho || !israw) {
1758: init_termbuf();
1759: tty_setecho(isecho);
1760: tty_setraw(israw);
1761: set_termbuf();
1762: if (!israw) {
1763: /*
1764: * Write a newline to ensure
1765: * that login will be able to
1766: * read the line...
1767: */
1768: write(xpty, "\n", 1);
1769: }
1770: }
1771: pty = xpty;
1772: }
1773: # else
1.5 mycroft 1774: argv = addarg(argv, "--");
1.1 cgd 1775: argv = addarg(argv, name);
1.3 cgd 1776: # endif
1777: # endif
1.1 cgd 1778: } else
1779: #endif
1780: if (getenv("USER")) {
1.5 mycroft 1781: argv = addarg(argv, "--");
1.1 cgd 1782: argv = addarg(argv, getenv("USER"));
1.3 cgd 1783: #if defined(LOGIN_ARGS) && defined(NO_LOGIN_P)
1.1 cgd 1784: {
1785: register char **cpp;
1786: for (cpp = environ; *cpp; cpp++)
1787: argv = addarg(argv, *cpp);
1788: }
1789: #endif
1.3 cgd 1790: /*
1791: * Assume that login will set the USER variable
1792: * correctly. For SysV systems, this means that
1793: * USER will no longer be set, just LOGNAME by
1794: * login. (The problem is that if the auto-login
1795: * fails, and the user then specifies a different
1796: * account name, he can get logged in with both
1797: * LOGNAME and USER in his environment, but the
1798: * USER value will be wrong.
1799: */
1800: unsetenv("USER");
1.1 cgd 1801: }
1.6 jtk 1802: #ifdef SOLARIS
1803: else {
1804: char **p;
1805:
1806: argv = addarg(argv, ""); /* no login name */
1807: for (p = environ; *p; p++) {
1808: argv = addarg(argv, *p);
1809: }
1810: }
1811: #endif /* SOLARIS */
1.3 cgd 1812: #if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R)
1813: if (pty > 2)
1814: close(pty);
1815: #endif
1.9 tls 1816: if (getent(defent, gettyname) == 1) {
1817: char *cp = defstrs;
1818:
1819: loginprog = getstr("lo", &cp);
1820: }
1821: if (loginprog == NULL)
1822: loginprog = _PATH_LOGIN;
1.1 cgd 1823: closelog();
1.6 jtk 1824: /*
1825: * This sleep(1) is in here so that telnetd can
1826: * finish up with the tty. There's a race condition
1827: * the login banner message gets lost...
1828: */
1829: sleep(1);
1.9 tls 1830: execv(loginprog, argv);
1.1 cgd 1831:
1.9 tls 1832: syslog(LOG_ERR, "%s: %m\n", loginprog);
1833: fatalperror(net, loginprog);
1.1 cgd 1834: /*NOTREACHED*/
1835: }
1836:
1837: char **
1838: addarg(argv, val)
1839: register char **argv;
1840: register char *val;
1841: {
1842: register char **cpp;
1843:
1844: if (argv == NULL) {
1845: /*
1846: * 10 entries, a leading length, and a null
1847: */
1848: argv = (char **)malloc(sizeof(*argv) * 12);
1849: if (argv == NULL)
1850: return(NULL);
1851: *argv++ = (char *)10;
1852: *argv = (char *)0;
1853: }
1854: for (cpp = argv; *cpp; cpp++)
1855: ;
1.7 jtk 1856: if (cpp == &argv[(long)argv[-1]]) {
1.1 cgd 1857: --argv;
1.7 jtk 1858: *argv = (char *)((long)(*argv) + 10);
1859: argv = (char **)realloc(argv, sizeof(*argv)*((long)(*argv) + 2));
1.1 cgd 1860: if (argv == NULL)
1861: return(NULL);
1862: argv++;
1.7 jtk 1863: cpp = &argv[(long)argv[-1] - 10];
1.1 cgd 1864: }
1865: *cpp++ = val;
1866: *cpp = 0;
1867: return(argv);
1868: }
1869: #endif /* NEWINIT */
1870:
1871: /*
1.6 jtk 1872: * scrub_env()
1873: *
1874: * Remove a few things from the environment that
1875: * don't need to be there.
1876: */
1.11 mrg 1877: void
1.6 jtk 1878: scrub_env()
1879: {
1880: register char **cpp, **cpp2;
1881:
1882: for (cpp2 = cpp = environ; *cpp; cpp++) {
1883: if (strncmp(*cpp, "LD_", 3) &&
1884: strncmp(*cpp, "_RLD_", 5) &&
1885: strncmp(*cpp, "LIBPATH=", 8) &&
1886: strncmp(*cpp, "IFS=", 4))
1887: *cpp2++ = *cpp;
1888: }
1889: *cpp2 = 0;
1890: }
1891:
1892: /*
1.1 cgd 1893: * cleanup()
1894: *
1895: * This is the routine to call when we are all through, to
1896: * clean up anything that needs to be cleaned up.
1897: */
1898: /* ARGSUSED */
1899: void
1900: cleanup(sig)
1901: int sig;
1902: {
1.3 cgd 1903: #ifndef PARENT_DOES_UTMP
1.1 cgd 1904: # if (BSD > 43) || defined(convex)
1905: char *p;
1906:
1907: p = line + sizeof("/dev/") - 1;
1908: if (logout(p))
1909: logwtmp(p, "", "");
1910: (void)chmod(line, 0666);
1911: (void)chown(line, 0, 0);
1912: *p = 'p';
1913: (void)chmod(line, 0666);
1914: (void)chown(line, 0, 0);
1915: (void) shutdown(net, 2);
1916: exit(1);
1917: # else
1918: void rmut();
1919:
1920: rmut();
1921: vhangup(); /* XXX */
1922: (void) shutdown(net, 2);
1923: exit(1);
1924: # endif
1.3 cgd 1925: #else /* PARENT_DOES_UTMP */
1.1 cgd 1926: # ifdef NEWINIT
1927: (void) shutdown(net, 2);
1928: exit(1);
1929: # else /* NEWINIT */
1.3 cgd 1930: # ifdef CRAY
1.1 cgd 1931: static int incleanup = 0;
1932: register int t;
1.6 jtk 1933: int child_status; /* status of child process as returned by waitpid */
1934: int flags = WNOHANG|WUNTRACED;
1.1 cgd 1935:
1936: /*
1937: * 1: Pick up the zombie, if we are being called
1938: * as the signal handler.
1939: * 2: If we are a nested cleanup(), return.
1940: * 3: Try to clean up TMPDIR.
1941: * 4: Fill in utmp with shutdown of process.
1942: * 5: Close down the network and pty connections.
1943: * 6: Finish up the TMPDIR cleanup, if needed.
1944: */
1.6 jtk 1945: if (sig == SIGCHLD) {
1946: while (waitpid(-1, &child_status, flags) > 0)
1.1 cgd 1947: ; /* VOID */
1.6 jtk 1948: /* Check if the child process was stopped
1949: * rather than exited. We want cleanup only if
1950: * the child has died.
1951: */
1952: if (WIFSTOPPED(child_status)) {
1953: return;
1954: }
1955: }
1.1 cgd 1956: t = sigblock(sigmask(SIGCHLD));
1957: if (incleanup) {
1958: sigsetmask(t);
1959: return;
1960: }
1961: incleanup = 1;
1962: sigsetmask(t);
1.6 jtk 1963: #ifdef UNICOS7x
1.3 cgd 1964: if (secflag) {
1965: /*
1966: * We need to set ourselves back to a null
1967: * label to clean up.
1968: */
1969:
1970: setulvl(sysv.sy_minlvl);
1971: setucmp((long)0);
1972: }
1.6 jtk 1973: #endif /* UNICOS7x */
1.1 cgd 1974:
1975: t = cleantmp(&wtmp);
1976: setutent(); /* just to make sure */
1.3 cgd 1977: # endif /* CRAY */
1.1 cgd 1978: rmut(line);
1979: close(pty);
1980: (void) shutdown(net, 2);
1.3 cgd 1981: # ifdef CRAY
1.1 cgd 1982: if (t == 0)
1983: cleantmp(&wtmp);
1.3 cgd 1984: # endif /* CRAY */
1.1 cgd 1985: exit(1);
1986: # endif /* NEWINT */
1.3 cgd 1987: #endif /* PARENT_DOES_UTMP */
1.1 cgd 1988: }
1989:
1.3 cgd 1990: #if defined(PARENT_DOES_UTMP) && !defined(NEWINIT)
1.1 cgd 1991: /*
1992: * _utmp_sig_rcv
1993: * utmp_sig_init
1994: * utmp_sig_wait
1995: * These three functions are used to coordinate the handling of
1996: * the utmp file between the server and the soon-to-be-login shell.
1997: * The server actually creates the utmp structure, the child calls
1998: * utmp_sig_wait(), until the server calls utmp_sig_notify() and
1999: * signals the future-login shell to proceed.
2000: */
2001: static int caught=0; /* NZ when signal intercepted */
2002: static void (*func)(); /* address of previous handler */
2003:
2004: void
2005: _utmp_sig_rcv(sig)
2006: int sig;
2007: {
2008: caught = 1;
2009: (void) signal(SIGUSR1, func);
2010: }
2011:
2012: void
2013: utmp_sig_init()
2014: {
2015: /*
2016: * register signal handler for UTMP creation
2017: */
2018: if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
2019: fatalperror(net, "telnetd/signal");
2020: }
2021:
2022: void
2023: utmp_sig_reset()
2024: {
2025: (void) signal(SIGUSR1, func); /* reset handler to default */
2026: }
2027:
1.3 cgd 2028: # ifdef __hpux
2029: # define sigoff() /* do nothing */
2030: # define sigon() /* do nothing */
2031: # endif
2032:
1.1 cgd 2033: void
2034: utmp_sig_wait()
2035: {
2036: /*
2037: * Wait for parent to write our utmp entry.
2038: */
2039: sigoff();
2040: while (caught == 0) {
2041: pause(); /* wait until we get a signal (sigon) */
2042: sigoff(); /* turn off signals while we check caught */
2043: }
2044: sigon(); /* turn on signals again */
2045: }
2046:
2047: void
2048: utmp_sig_notify(pid)
2049: {
2050: kill(pid, SIGUSR1);
2051: }
2052:
1.3 cgd 2053: # ifdef CRAY
1.1 cgd 2054: static int gotsigjob = 0;
2055:
2056: /*ARGSUSED*/
2057: void
2058: sigjob(sig)
2059: int sig;
2060: {
2061: register int jid;
2062: register struct jobtemp *jp;
2063:
2064: while ((jid = waitjob(NULL)) != -1) {
2065: if (jid == 0) {
2066: return;
2067: }
2068: gotsigjob++;
2069: jobend(jid, NULL, NULL);
2070: }
2071: }
2072:
2073: /*
1.6 jtk 2074: * jid_getutid:
2075: * called by jobend() before calling cleantmp()
2076: * to find the correct $TMPDIR to cleanup.
2077: */
2078:
2079: struct utmp *
2080: jid_getutid(jid)
2081: int jid;
2082: {
2083: struct utmp *cur = NULL;
2084:
2085: setutent(); /* just to make sure */
2086: while (cur = getutent()) {
2087: if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) {
2088: return(cur);
2089: }
2090: }
2091:
2092: return(0);
2093: }
2094:
2095: /*
1.1 cgd 2096: * Clean up the TMPDIR that login created.
2097: * The first time this is called we pick up the info
2098: * from the utmp. If the job has already gone away,
2099: * then we'll clean up and be done. If not, then
2100: * when this is called the second time it will wait
2101: * for the signal that the job is done.
2102: */
2103: int
2104: cleantmp(wtp)
2105: register struct utmp *wtp;
2106: {
2107: struct utmp *utp;
2108: static int first = 1;
2109: register int mask, omask, ret;
1.3 cgd 2110: extern struct utmp *getutid P((const struct utmp *_Id));
2111:
1.1 cgd 2112:
2113: mask = sigmask(WJSIGNAL);
2114:
2115: if (first == 0) {
2116: omask = sigblock(mask);
2117: while (gotsigjob == 0)
2118: sigpause(omask);
2119: return(1);
2120: }
2121: first = 0;
2122: setutent(); /* just to make sure */
2123:
2124: utp = getutid(wtp);
2125: if (utp == 0) {
2126: syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
2127: return(-1);
2128: }
2129: /*
2130: * Nothing to clean up if the user shell was never started.
2131: */
2132: if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0)
2133: return(1);
2134:
2135: /*
2136: * Block the WJSIGNAL while we are in jobend().
2137: */
2138: omask = sigblock(mask);
2139: ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user);
2140: sigsetmask(omask);
2141: return(ret);
2142: }
2143:
2144: int
2145: jobend(jid, path, user)
2146: register int jid;
2147: register char *path;
2148: register char *user;
2149: {
2150: static int saved_jid = 0;
1.6 jtk 2151: static int pty_saved_jid = 0;
1.1 cgd 2152: static char saved_path[sizeof(wtmp.ut_tpath)+1];
2153: static char saved_user[sizeof(wtmp.ut_user)+1];
2154:
1.6 jtk 2155: /*
2156: * this little piece of code comes into play
2157: * only when ptyreconnect is used to reconnect
2158: * to an previous session.
2159: *
2160: * this is the only time when the
2161: * "saved_jid != jid" code is executed.
2162: */
2163:
2164: if ( saved_jid && saved_jid != jid ) {
2165: if (!path) { /* called from signal handler */
2166: pty_saved_jid = jid;
2167: } else {
2168: pty_saved_jid = saved_jid;
2169: }
2170: }
2171:
1.1 cgd 2172: if (path) {
2173: strncpy(saved_path, path, sizeof(wtmp.ut_tpath));
2174: strncpy(saved_user, user, sizeof(wtmp.ut_user));
2175: saved_path[sizeof(saved_path)] = '\0';
2176: saved_user[sizeof(saved_user)] = '\0';
2177: }
2178: if (saved_jid == 0) {
2179: saved_jid = jid;
2180: return(0);
2181: }
1.6 jtk 2182:
2183: /* if the jid has changed, get the correct entry from the utmp file */
2184:
2185: if ( saved_jid != jid ) {
2186: struct utmp *utp = NULL;
2187: struct utmp *jid_getutid();
2188:
2189: utp = jid_getutid(pty_saved_jid);
2190:
2191: if (utp == 0) {
2192: syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
2193: return(-1);
2194: }
2195:
2196: cleantmpdir(jid, utp->ut_tpath, utp->ut_user);
2197: return(1);
2198: }
2199:
1.1 cgd 2200: cleantmpdir(jid, saved_path, saved_user);
2201: return(1);
2202: }
2203:
2204: /*
2205: * Fork a child process to clean up the TMPDIR
2206: */
2207: cleantmpdir(jid, tpath, user)
2208: register int jid;
2209: register char *tpath;
2210: register char *user;
2211: {
2212: switch(fork()) {
2213: case -1:
2214: syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n",
2215: tpath);
2216: break;
2217: case 0:
2218: execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0);
2219: syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n",
2220: tpath, CLEANTMPCMD);
2221: exit(1);
2222: default:
2223: /*
2224: * Forget about child. We will exit, and
2225: * /etc/init will pick it up.
2226: */
2227: break;
2228: }
2229: }
1.3 cgd 2230: # endif /* CRAY */
2231: #endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */
1.1 cgd 2232:
2233: /*
2234: * rmut()
2235: *
2236: * This is the function called by cleanup() to
2237: * remove the utmp entry for this person.
2238: */
2239:
1.3 cgd 2240: #ifdef UTMPX
2241: void
2242: rmut()
2243: {
2244: register f;
2245: int found = 0;
2246: struct utmp *u, *utmp;
2247: int nutmp;
2248: struct stat statbf;
2249:
2250: struct utmpx *utxp, utmpx;
2251:
2252: /*
2253: * This updates the utmpx and utmp entries and make a wtmp/x entry
2254: */
2255:
2256: SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1);
2257: utxp = getutxline(&utmpx);
2258: if (utxp) {
2259: utxp->ut_type = DEAD_PROCESS;
2260: utxp->ut_exit.e_termination = 0;
2261: utxp->ut_exit.e_exit = 0;
2262: (void) time(&utmpx.ut_tv.tv_sec);
2263: utmpx.ut_tv.tv_usec = 0;
2264: modutx(utxp);
2265: }
2266: endutxent();
2267: } /* end of rmut */
2268: #endif
2269:
2270: #if !defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43
1.1 cgd 2271: void
2272: rmut()
2273: {
2274: register f;
2275: int found = 0;
2276: struct utmp *u, *utmp;
2277: int nutmp;
2278: struct stat statbf;
2279:
2280: f = open(utmpf, O_RDWR);
2281: if (f >= 0) {
2282: (void) fstat(f, &statbf);
2283: utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
2284: if (!utmp)
2285: syslog(LOG_ERR, "utmp malloc failed");
2286: if (statbf.st_size && utmp) {
2287: nutmp = read(f, (char *)utmp, (int)statbf.st_size);
2288: nutmp /= sizeof(struct utmp);
1.6 jtk 2289:
1.1 cgd 2290: for (u = utmp ; u < &utmp[nutmp] ; u++) {
2291: if (SCMPN(u->ut_line, line+5) ||
2292: u->ut_name[0]==0)
2293: continue;
1.10 kleink 2294: (void)lseek(f, (off_t)((long)u)-((long)utmp),
2295: SEEK_SET);
1.1 cgd 2296: SCPYN(u->ut_name, "");
2297: SCPYN(u->ut_host, "");
2298: (void) time(&u->ut_time);
2299: (void) write(f, (char *)u, sizeof(wtmp));
2300: found++;
2301: }
2302: }
2303: (void) close(f);
2304: }
2305: if (found) {
2306: f = open(wtmpf, O_WRONLY|O_APPEND);
2307: if (f >= 0) {
2308: SCPYN(wtmp.ut_line, line+5);
2309: SCPYN(wtmp.ut_name, "");
2310: SCPYN(wtmp.ut_host, "");
2311: (void) time(&wtmp.ut_time);
2312: (void) write(f, (char *)&wtmp, sizeof(wtmp));
2313: (void) close(f);
2314: }
2315: }
2316: (void) chmod(line, 0666);
2317: (void) chown(line, 0, 0);
2318: line[strlen("/dev/")] = 'p';
2319: (void) chmod(line, 0666);
2320: (void) chown(line, 0, 0);
2321: } /* end of rmut */
2322: #endif /* CRAY */
1.3 cgd 2323:
2324: #ifdef __hpux
2325: rmut (line)
2326: char *line;
2327: {
2328: struct utmp utmp;
2329: struct utmp *utptr;
2330: int fd; /* for /etc/wtmp */
2331:
2332: utmp.ut_type = USER_PROCESS;
2333: (void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id));
2334: (void) setutent();
2335: utptr = getutid(&utmp);
2336: /* write it out only if it exists */
2337: if (utptr) {
2338: utptr->ut_type = DEAD_PROCESS;
2339: utptr->ut_time = time((long *) 0);
2340: (void) pututline(utptr);
2341: /* set wtmp entry if wtmp file exists */
2342: if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) {
2343: (void) write(fd, utptr, sizeof(utmp));
2344: (void) close(fd);
2345: }
2346: }
2347: (void) endutent();
2348:
2349: (void) chmod(line, 0666);
2350: (void) chown(line, 0, 0);
2351: line[14] = line[13];
2352: line[13] = line[12];
2353: line[8] = 'm';
2354: line[9] = '/';
2355: line[10] = 'p';
2356: line[11] = 't';
2357: line[12] = 'y';
2358: (void) chmod(line, 0666);
2359: (void) chown(line, 0, 0);
2360: }
2361: #endif
CVSweb <webmaster@jp.NetBSD.org>