138905Sborman /* 238905Sborman * Copyright (c) 1989 Regents of the University of California. 338905Sborman * All rights reserved. 438905Sborman * 542673Sbostic * %sccs.include.redist.c% 638905Sborman */ 738905Sborman 838905Sborman #ifndef lint 9*57212Sdab static char sccsid[] = "@(#)sys_term.c 5.17 (Berkeley) 12/18/92"; 1038905Sborman #endif /* not lint */ 1138905Sborman 1238905Sborman #include "telnetd.h" 1338905Sborman #include "pathnames.h" 1438905Sborman 15*57212Sdab #if defined(AUTHENTICATION) 1646809Sdab #include <libtelnet/auth.h> 1746809Sdab #endif 1846809Sdab 1938905Sborman #ifdef NEWINIT 2038905Sborman #include <initreq.h> 2138905Sborman #else /* NEWINIT*/ 22*57212Sdab # ifdef UTMPX 23*57212Sdab # include <utmpx.h> 24*57212Sdab # else 25*57212Sdab # include <utmp.h> 26*57212Sdab # endif /* UTMPX */ 2738905Sborman struct utmp wtmp; 2838905Sborman 29*57212Sdab int utmp_len = sizeof(wtmp.ut_host); 3038905Sborman # ifndef CRAY 3138905Sborman char wtmpf[] = "/usr/adm/wtmp"; 3238905Sborman char utmpf[] = "/etc/utmp"; 3338905Sborman # else /* CRAY */ 3438905Sborman char wtmpf[] = "/etc/wtmp"; 3546809Sdab #include <tmpdir.h> 3646809Sdab #include <sys/wait.h> 37*57212Sdab # if defined(_SC_CRAY_SECURE_SYS) 38*57212Sdab #include <sys/sysv.h> 39*57212Sdab #include <sys/secstat.h> 40*57212Sdab extern int secflag; 41*57212Sdab extern struct sysv sysv; 42*57212Sdab # endif /* _SC_CRAY_SECURE_SYS */ 4338905Sborman # endif /* CRAY */ 4438905Sborman #endif /* NEWINIT */ 4538905Sborman 46*57212Sdab #ifdef STREAMSPTY 47*57212Sdab #include <sac.h> 48*57212Sdab #include <sys/stropts.h> 49*57212Sdab #endif 50*57212Sdab 5138905Sborman #define SCPYN(a, b) (void) strncpy(a, b, sizeof(a)) 5238905Sborman #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 5338905Sborman 5444364Sborman #ifdef STREAMS 5544364Sborman #include <sys/stream.h> 5644364Sborman #endif 5738905Sborman #include <sys/tty.h> 5838905Sborman #ifdef t_erase 5938905Sborman #undef t_erase 6038905Sborman #undef t_kill 6138905Sborman #undef t_intrc 6238905Sborman #undef t_quitc 6338905Sborman #undef t_startc 6438905Sborman #undef t_stopc 6538905Sborman #undef t_eofc 6638905Sborman #undef t_brkc 6738905Sborman #undef t_suspc 6838905Sborman #undef t_dsuspc 6938905Sborman #undef t_rprntc 7038905Sborman #undef t_flushc 7138905Sborman #undef t_werasc 7238905Sborman #undef t_lnextc 7338905Sborman #endif 7438905Sborman 7544364Sborman #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC) 7644364Sborman # define EXTPROC 0400 7744364Sborman #endif 7844364Sborman 7938905Sborman #ifndef USE_TERMIO 8038905Sborman struct termbuf { 8138905Sborman struct sgttyb sg; 8238905Sborman struct tchars tc; 8338905Sborman struct ltchars ltc; 8438905Sborman int state; 8538905Sborman int lflags; 8638905Sborman } termbuf, termbuf2; 8745234Sborman # define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val) 8845234Sborman # define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val) 8946809Sdab # define cfgetospeed(tp) (tp)->sg.sg_ospeed 9046809Sdab # define cfgetispeed(tp) (tp)->sg.sg_ispeed 9138905Sborman #else /* USE_TERMIO */ 9238905Sborman # ifdef SYSV_TERMIO 9338905Sborman # define termios termio 9438905Sborman # endif 9545234Sborman # ifndef TCSANOW 9644364Sborman # ifdef TCSETS 9745234Sborman # define TCSANOW TCSETS 9845234Sborman # define TCSADRAIN TCSETSW 9946809Sdab # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) 10044364Sborman # else 10145234Sborman # ifdef TCSETA 10245234Sborman # define TCSANOW TCSETA 10345234Sborman # define TCSADRAIN TCSETAW 10446809Sdab # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) 10545234Sborman # else 10645234Sborman # define TCSANOW TIOCSETA 10745234Sborman # define TCSADRAIN TIOCSETAW 10846809Sdab # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) 10945234Sborman # endif 11044364Sborman # endif 11145234Sborman # define tcsetattr(f, a, t) ioctl(f, a, t) 11245234Sborman # define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 11345234Sborman (tp)->c_cflag |= (val) 11446809Sdab # define cfgetospeed(tp) ((tp)->c_cflag & CBAUD) 11545234Sborman # ifdef CIBAUD 11645234Sborman # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \ 11745234Sborman (tp)->c_cflag |= ((val)<<IBSHIFT) 11846809Sdab # define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT) 11945234Sborman # else 12045234Sborman # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 12145234Sborman (tp)->c_cflag |= (val) 12246809Sdab # define cfgetispeed(tp) ((tp)->c_cflag & CBAUD) 12345234Sborman # endif 12445234Sborman # endif /* TCSANOW */ 12538905Sborman struct termios termbuf, termbuf2; /* pty control structure */ 126*57212Sdab int ttyfd = -1; 12738905Sborman #endif /* USE_TERMIO */ 12838905Sborman 12938905Sborman /* 13038905Sborman * init_termbuf() 13138905Sborman * copy_termbuf(cp) 13238905Sborman * set_termbuf() 13338905Sborman * 13438905Sborman * These three routines are used to get and set the "termbuf" structure 13538905Sborman * to and from the kernel. init_termbuf() gets the current settings. 13638905Sborman * copy_termbuf() hands in a new "termbuf" to write to the kernel, and 13738905Sborman * set_termbuf() writes the structure into the kernel. 13838905Sborman */ 13938905Sborman 14046809Sdab void 14138905Sborman init_termbuf() 14238905Sborman { 14338905Sborman #ifndef USE_TERMIO 14438905Sborman (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg); 14538905Sborman (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc); 14638905Sborman (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc); 14738905Sborman # ifdef TIOCGSTATE 14838905Sborman (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state); 14938905Sborman # endif 15038905Sborman #else 151*57212Sdab (void) tcgetattr(ttyfd, &termbuf); 15238905Sborman #endif 15338905Sborman termbuf2 = termbuf; 15438905Sborman } 15538905Sborman 15638905Sborman #if defined(LINEMODE) && defined(TIOCPKT_IOCTL) 15746809Sdab void 15838905Sborman copy_termbuf(cp, len) 15946809Sdab char *cp; 16046809Sdab int len; 16138905Sborman { 16238905Sborman if (len > sizeof(termbuf)) 16338905Sborman len = sizeof(termbuf); 16438905Sborman bcopy(cp, (char *)&termbuf, len); 16538905Sborman termbuf2 = termbuf; 16638905Sborman } 16738905Sborman #endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ 16838905Sborman 16946809Sdab void 17038905Sborman set_termbuf() 17138905Sborman { 17238905Sborman /* 17338905Sborman * Only make the necessary changes. 17438905Sborman */ 17538905Sborman #ifndef USE_TERMIO 17638905Sborman if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg))) 17745234Sborman (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg); 17838905Sborman if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc))) 17938905Sborman (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc); 18038905Sborman if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc, 18138905Sborman sizeof(termbuf.ltc))) 18238905Sborman (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc); 18338905Sborman if (termbuf.lflags != termbuf2.lflags) 18438905Sborman (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags); 18538905Sborman #else /* USE_TERMIO */ 18638905Sborman if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) 187*57212Sdab (void) tcsetattr(ttyfd, TCSANOW, &termbuf); 188*57212Sdab # if defined(CRAY2) && defined(UNICOS5) 18938905Sborman needtermstat = 1; 19038905Sborman # endif 19138905Sborman #endif /* USE_TERMIO */ 19238905Sborman } 19338905Sborman 19438905Sborman 19538905Sborman /* 19638905Sborman * spcset(func, valp, valpp) 19738905Sborman * 19838905Sborman * This function takes various special characters (func), and 19938905Sborman * sets *valp to the current value of that character, and 20038905Sborman * *valpp to point to where in the "termbuf" structure that 20138905Sborman * value is kept. 20238905Sborman * 20338905Sborman * It returns the SLC_ level of support for this function. 20438905Sborman */ 20538905Sborman 20638905Sborman #ifndef USE_TERMIO 20746809Sdab int 20838905Sborman spcset(func, valp, valpp) 20946809Sdab int func; 21046809Sdab cc_t *valp; 21146809Sdab cc_t **valpp; 21238905Sborman { 21338905Sborman switch(func) { 21438905Sborman case SLC_EOF: 21538905Sborman *valp = termbuf.tc.t_eofc; 21640242Sborman *valpp = (cc_t *)&termbuf.tc.t_eofc; 21738905Sborman return(SLC_VARIABLE); 21838905Sborman case SLC_EC: 21938905Sborman *valp = termbuf.sg.sg_erase; 22040242Sborman *valpp = (cc_t *)&termbuf.sg.sg_erase; 22138905Sborman return(SLC_VARIABLE); 22238905Sborman case SLC_EL: 22338905Sborman *valp = termbuf.sg.sg_kill; 22440242Sborman *valpp = (cc_t *)&termbuf.sg.sg_kill; 22538905Sborman return(SLC_VARIABLE); 22638905Sborman case SLC_IP: 22738905Sborman *valp = termbuf.tc.t_intrc; 22840242Sborman *valpp = (cc_t *)&termbuf.tc.t_intrc; 22938905Sborman return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 23038905Sborman case SLC_ABORT: 23138905Sborman *valp = termbuf.tc.t_quitc; 23240242Sborman *valpp = (cc_t *)&termbuf.tc.t_quitc; 23338905Sborman return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 23438905Sborman case SLC_XON: 23538905Sborman *valp = termbuf.tc.t_startc; 23640242Sborman *valpp = (cc_t *)&termbuf.tc.t_startc; 23738905Sborman return(SLC_VARIABLE); 23838905Sborman case SLC_XOFF: 23938905Sborman *valp = termbuf.tc.t_stopc; 24040242Sborman *valpp = (cc_t *)&termbuf.tc.t_stopc; 24138905Sborman return(SLC_VARIABLE); 24238905Sborman case SLC_AO: 24338905Sborman *valp = termbuf.ltc.t_flushc; 24440242Sborman *valpp = (cc_t *)&termbuf.ltc.t_flushc; 24538905Sborman return(SLC_VARIABLE); 24638905Sborman case SLC_SUSP: 24738905Sborman *valp = termbuf.ltc.t_suspc; 24840242Sborman *valpp = (cc_t *)&termbuf.ltc.t_suspc; 24938905Sborman return(SLC_VARIABLE); 25038905Sborman case SLC_EW: 25138905Sborman *valp = termbuf.ltc.t_werasc; 25240242Sborman *valpp = (cc_t *)&termbuf.ltc.t_werasc; 25338905Sborman return(SLC_VARIABLE); 25438905Sborman case SLC_RP: 25538905Sborman *valp = termbuf.ltc.t_rprntc; 25640242Sborman *valpp = (cc_t *)&termbuf.ltc.t_rprntc; 25738905Sborman return(SLC_VARIABLE); 25838905Sborman case SLC_LNEXT: 25938905Sborman *valp = termbuf.ltc.t_lnextc; 26040242Sborman *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 26138905Sborman return(SLC_VARIABLE); 26240242Sborman case SLC_FORW1: 26340242Sborman *valp = termbuf.tc.t_brkc; 26440242Sborman *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 26540242Sborman return(SLC_VARIABLE); 26638905Sborman case SLC_BRK: 26738905Sborman case SLC_SYNCH: 26838905Sborman case SLC_AYT: 26938905Sborman case SLC_EOR: 27040242Sborman *valp = (cc_t)0; 27140242Sborman *valpp = (cc_t *)0; 27238905Sborman return(SLC_DEFAULT); 27338905Sborman default: 27440242Sborman *valp = (cc_t)0; 27540242Sborman *valpp = (cc_t *)0; 27638905Sborman return(SLC_NOSUPPORT); 27738905Sborman } 27838905Sborman } 27938905Sborman 28038905Sborman #else /* USE_TERMIO */ 28138905Sborman 28246809Sdab int 28338905Sborman spcset(func, valp, valpp) 28446809Sdab int func; 28546809Sdab cc_t *valp; 28646809Sdab cc_t **valpp; 28738905Sborman { 28839503Sborman 28939503Sborman #define setval(a, b) *valp = termbuf.c_cc[a]; \ 29039503Sborman *valpp = &termbuf.c_cc[a]; \ 29139503Sborman return(b); 29240242Sborman #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); 29339503Sborman 29438905Sborman switch(func) { 29538905Sborman case SLC_EOF: 29639503Sborman setval(VEOF, SLC_VARIABLE); 29738905Sborman case SLC_EC: 29839503Sborman setval(VERASE, SLC_VARIABLE); 29938905Sborman case SLC_EL: 30039503Sborman setval(VKILL, SLC_VARIABLE); 30138905Sborman case SLC_IP: 30239503Sborman setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 30338905Sborman case SLC_ABORT: 30439503Sborman setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 30538905Sborman case SLC_XON: 30639503Sborman #ifdef VSTART 30739503Sborman setval(VSTART, SLC_VARIABLE); 30839503Sborman #else 30939503Sborman defval(0x13); 31039503Sborman #endif 31138905Sborman case SLC_XOFF: 31239503Sborman #ifdef VSTOP 31339503Sborman setval(VSTOP, SLC_VARIABLE); 31439503Sborman #else 31539503Sborman defval(0x11); 31639503Sborman #endif 31738905Sborman case SLC_EW: 31839503Sborman #ifdef VWERASE 31939503Sborman setval(VWERASE, SLC_VARIABLE); 32039503Sborman #else 32139503Sborman defval(0); 32239503Sborman #endif 32338905Sborman case SLC_RP: 32439503Sborman #ifdef VREPRINT 32539503Sborman setval(VREPRINT, SLC_VARIABLE); 32639503Sborman #else 32739503Sborman defval(0); 32839503Sborman #endif 32938905Sborman case SLC_LNEXT: 33039503Sborman #ifdef VLNEXT 33139503Sborman setval(VLNEXT, SLC_VARIABLE); 33239503Sborman #else 33339503Sborman defval(0); 33439503Sborman #endif 33539503Sborman case SLC_AO: 33645234Sborman #if !defined(VDISCARD) && defined(VFLUSHO) 33745234Sborman # define VDISCARD VFLUSHO 33845234Sborman #endif 33945234Sborman #ifdef VDISCARD 34045234Sborman setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); 34139503Sborman #else 34239503Sborman defval(0); 34339503Sborman #endif 34439503Sborman case SLC_SUSP: 34539503Sborman #ifdef VSUSP 34639503Sborman setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); 34739503Sborman #else 34839503Sborman defval(0); 34939503Sborman #endif 35040242Sborman #ifdef VEOL 35140242Sborman case SLC_FORW1: 35240242Sborman setval(VEOL, SLC_VARIABLE); 35340242Sborman #endif 35440242Sborman #ifdef VEOL2 35540242Sborman case SLC_FORW2: 35640242Sborman setval(VEOL2, SLC_VARIABLE); 35740242Sborman #endif 35845234Sborman case SLC_AYT: 35945234Sborman #ifdef VSTATUS 36045234Sborman setval(VSTATUS, SLC_VARIABLE); 36145234Sborman #else 36245234Sborman defval(0); 36345234Sborman #endif 36439503Sborman 36538905Sborman case SLC_BRK: 36638905Sborman case SLC_SYNCH: 36738905Sborman case SLC_EOR: 36839503Sborman defval(0); 36939503Sborman 37038905Sborman default: 37138905Sborman *valp = 0; 37238905Sborman *valpp = 0; 37338905Sborman return(SLC_NOSUPPORT); 37438905Sborman } 37538905Sborman } 37638905Sborman #endif /* USE_TERMIO */ 37738905Sborman 37840242Sborman #ifdef CRAY 37938905Sborman /* 38040242Sborman * getnpty() 38140242Sborman * 38240242Sborman * Return the number of pty's configured into the system. 38340242Sborman */ 38446809Sdab int 38540242Sborman getnpty() 38640242Sborman { 38740242Sborman #ifdef _SC_CRAY_NPTY 38846809Sdab int numptys; 38946809Sdab 39046809Sdab if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) 39146809Sdab return numptys; 39246809Sdab else 39340242Sborman #endif /* _SC_CRAY_NPTY */ 39446809Sdab return 128; 39540242Sborman } 39640242Sborman #endif /* CRAY */ 39740242Sborman 39845234Sborman #ifndef convex 39940242Sborman /* 40038905Sborman * getpty() 40138905Sborman * 40238905Sborman * Allocate a pty. As a side effect, the external character 40338905Sborman * array "line" contains the name of the slave side. 40438905Sborman * 40538905Sborman * Returns the file descriptor of the opened pty. 40638905Sborman */ 40745234Sborman #ifndef __GNUC__ 40838905Sborman char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 40945234Sborman #else 41045234Sborman static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 41145234Sborman char *line = Xline; 41245234Sborman #endif 41345234Sborman #ifdef CRAY 41445234Sborman char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 41545234Sborman #endif /* CRAY */ 41638905Sborman 41746809Sdab int 41838905Sborman getpty() 41938905Sborman { 42038905Sborman register int p; 421*57212Sdab #ifdef STREAMSPTY 422*57212Sdab int t; 423*57212Sdab char *ptsname(); 424*57212Sdab 425*57212Sdab p = open("/dev/ptmx", 2); 426*57212Sdab if (p > 0) { 427*57212Sdab grantpt(p); 428*57212Sdab unlockpt(p); 429*57212Sdab strcpy(line, ptsname(p)); 430*57212Sdab return(p); 431*57212Sdab } 432*57212Sdab 433*57212Sdab #else /* ! STREAMSPTY */ 43438905Sborman #ifndef CRAY 435*57212Sdab register char *cp, *p1, *p2; 43638905Sborman register int i; 437*57212Sdab #if defined(sun) && defined(TIOCGPGRP) 438*57212Sdab int dummy; 439*57212Sdab #endif 44038905Sborman 44138905Sborman (void) sprintf(line, "/dev/ptyXX"); 44238905Sborman p1 = &line[8]; 44338905Sborman p2 = &line[9]; 44438905Sborman 445*57212Sdab for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) { 44638905Sborman struct stat stb; 44738905Sborman 448*57212Sdab *p1 = *cp; 44938905Sborman *p2 = '0'; 450*57212Sdab /* 451*57212Sdab * This stat() check is just to keep us from 452*57212Sdab * looping through all 256 combinations if there 453*57212Sdab * aren't that many ptys available. 454*57212Sdab */ 45538905Sborman if (stat(line, &stb) < 0) 45638905Sborman break; 45738905Sborman for (i = 0; i < 16; i++) { 45838905Sborman *p2 = "0123456789abcdef"[i]; 45938905Sborman p = open(line, 2); 46038905Sborman if (p > 0) { 46138905Sborman line[5] = 't'; 462*57212Sdab chown(line, 0, 0); 463*57212Sdab chmod(line, 0600); 464*57212Sdab #if defined(sun) && defined(TIOCGPGRP) 465*57212Sdab if (ioctl(p, TIOCGPGRP, &dummy) == 0 466*57212Sdab || errno != EIO) { 467*57212Sdab chmod(line, 0666); 468*57212Sdab close(p); 469*57212Sdab line[5] = 'p'; 470*57212Sdab } else 471*57212Sdab #endif /* defined(sun) && defined(TIOCGPGRP) */ 472*57212Sdab return(p); 47338905Sborman } 47438905Sborman } 47538905Sborman } 47638905Sborman #else /* CRAY */ 47738905Sborman register int npty; 47838905Sborman extern lowpty, highpty; 47945234Sborman struct stat sb; 48038905Sborman 48138905Sborman for (npty = lowpty; npty <= highpty; npty++) { 48245234Sborman (void) sprintf(myline, "/dev/pty/%03d", npty); 48345234Sborman p = open(myline, 2); 48438905Sborman if (p < 0) 48538905Sborman continue; 48638905Sborman (void) sprintf(line, "/dev/ttyp%03d", npty); 48745234Sborman /* 48845234Sborman * Here are some shenanigans to make sure that there 48945234Sborman * are no listeners lurking on the line. 49045234Sborman */ 49145234Sborman if(stat(line, &sb) < 0) { 49245234Sborman (void) close(p); 49345234Sborman continue; 49445234Sborman } 49545234Sborman if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { 49645234Sborman chown(line, 0, 0); 49745234Sborman chmod(line, 0600); 49845234Sborman (void)close(p); 49945234Sborman p = open(myline, 2); 50045234Sborman if (p < 0) 50145234Sborman continue; 50245234Sborman } 50345234Sborman /* 50445234Sborman * Now it should be safe...check for accessability. 50545234Sborman */ 50638905Sborman if (access(line, 6) == 0) 50738905Sborman return(p); 50838905Sborman else { 50938905Sborman /* no tty side to pty so skip it */ 51038905Sborman (void) close(p); 51138905Sborman } 51238905Sborman } 51338905Sborman #endif /* CRAY */ 514*57212Sdab #endif /* STREAMSPTY */ 51538905Sborman return(-1); 51638905Sborman } 51745234Sborman #endif /* convex */ 51838905Sborman 51938905Sborman #ifdef LINEMODE 52038905Sborman /* 52138905Sborman * tty_flowmode() Find out if flow control is enabled or disabled. 52238905Sborman * tty_linemode() Find out if linemode (external processing) is enabled. 52338905Sborman * tty_setlinemod(on) Turn on/off linemode. 52438905Sborman * tty_isecho() Find out if echoing is turned on. 52538905Sborman * tty_setecho(on) Enable/disable character echoing. 52638905Sborman * tty_israw() Find out if terminal is in RAW mode. 52738905Sborman * tty_binaryin(on) Turn on/off BINARY on input. 52838905Sborman * tty_binaryout(on) Turn on/off BINARY on output. 52938905Sborman * tty_isediting() Find out if line editing is enabled. 53038905Sborman * tty_istrapsig() Find out if signal trapping is enabled. 53138905Sborman * tty_setedit(on) Turn on/off line editing. 53238905Sborman * tty_setsig(on) Turn on/off signal trapping. 53344364Sborman * tty_issofttab() Find out if tab expansion is enabled. 53444364Sborman * tty_setsofttab(on) Turn on/off soft tab expansion. 53544364Sborman * tty_islitecho() Find out if typed control chars are echoed literally 53644364Sborman * tty_setlitecho() Turn on/off literal echo of control chars 53738905Sborman * tty_tspeed(val) Set transmit speed to val. 53838905Sborman * tty_rspeed(val) Set receive speed to val. 53938905Sborman */ 54038905Sborman 54146809Sdab int 54238905Sborman tty_flowmode() 54338905Sborman { 54438905Sborman #ifndef USE_TERMIO 54546809Sdab return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0); 54638905Sborman #else 54738905Sborman return(termbuf.c_iflag & IXON ? 1 : 0); 54838905Sborman #endif 54938905Sborman } 55038905Sborman 551*57212Sdab int 552*57212Sdab tty_restartany() 553*57212Sdab { 554*57212Sdab #ifndef USE_TERMIO 555*57212Sdab # ifdef DECCTQ 556*57212Sdab return((termbuf.lflags & DECCTQ) ? 0 : 1); 557*57212Sdab # else 558*57212Sdab return(-1); 559*57212Sdab # endif 560*57212Sdab #else 561*57212Sdab return(termbuf.c_iflag & IXANY ? 1 : 0); 562*57212Sdab #endif 563*57212Sdab } 564*57212Sdab 56545234Sborman #ifdef convex 56645234Sborman static int linestate; 56745234Sborman #endif 56845234Sborman 56946809Sdab int 57038905Sborman tty_linemode() 57138905Sborman { 57245234Sborman #ifndef convex 57338905Sborman #ifndef USE_TERMIO 57438905Sborman return(termbuf.state & TS_EXTPROC); 57538905Sborman #else 57638905Sborman return(termbuf.c_lflag & EXTPROC); 57738905Sborman #endif 57845234Sborman #else 57945234Sborman return(linestate); 58045234Sborman #endif 58138905Sborman } 58238905Sborman 58346809Sdab void 58438905Sborman tty_setlinemode(on) 58546809Sdab int on; 58638905Sborman { 58738905Sborman #ifdef TIOCEXT 58845234Sborman # ifndef convex 58945234Sborman set_termbuf(); 59045234Sborman # else 59145234Sborman linestate = on; 59245234Sborman # endif 59338905Sborman (void) ioctl(pty, TIOCEXT, (char *)&on); 59445234Sborman # ifndef convex 59545234Sborman init_termbuf(); 59645234Sborman # endif 59738905Sborman #else /* !TIOCEXT */ 59845234Sborman # ifdef EXTPROC 59938905Sborman if (on) 60038905Sborman termbuf.c_lflag |= EXTPROC; 60138905Sborman else 60238905Sborman termbuf.c_lflag &= ~EXTPROC; 60345234Sborman # endif 60438905Sborman #endif /* TIOCEXT */ 60538905Sborman } 60638905Sborman 60746809Sdab int 60838905Sborman tty_isecho() 60938905Sborman { 61038905Sborman #ifndef USE_TERMIO 61138905Sborman return (termbuf.sg.sg_flags & ECHO); 61238905Sborman #else 61338905Sborman return (termbuf.c_lflag & ECHO); 61438905Sborman #endif 61538905Sborman } 61638905Sborman #endif /* LINEMODE */ 61738905Sborman 61846809Sdab void 61938905Sborman tty_setecho(on) 62046809Sdab int on; 62138905Sborman { 62238905Sborman #ifndef USE_TERMIO 62338905Sborman if (on) 62438905Sborman termbuf.sg.sg_flags |= ECHO|CRMOD; 62538905Sborman else 62638905Sborman termbuf.sg.sg_flags &= ~(ECHO|CRMOD); 62738905Sborman #else 62838905Sborman if (on) 62938905Sborman termbuf.c_lflag |= ECHO; 63038905Sborman else 63138905Sborman termbuf.c_lflag &= ~ECHO; 63238905Sborman #endif 63338905Sborman } 63438905Sborman 63538905Sborman #if defined(LINEMODE) && defined(KLUDGELINEMODE) 63646809Sdab int 63738905Sborman tty_israw() 63838905Sborman { 63938905Sborman #ifndef USE_TERMIO 64038905Sborman return(termbuf.sg.sg_flags & RAW); 64138905Sborman #else 64238905Sborman return(!(termbuf.c_lflag & ICANON)); 64338905Sborman #endif 64438905Sborman } 64538905Sborman #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 64638905Sborman 64746809Sdab void 64838905Sborman tty_binaryin(on) 64946809Sdab int on; 65038905Sborman { 65138905Sborman #ifndef USE_TERMIO 65238905Sborman if (on) 65338905Sborman termbuf.lflags |= LPASS8; 65438905Sborman else 65538905Sborman termbuf.lflags &= ~LPASS8; 65638905Sborman #else 65738905Sborman if (on) { 65846809Sdab termbuf.c_iflag &= ~ISTRIP; 65938905Sborman } else { 66046809Sdab termbuf.c_iflag |= ISTRIP; 66138905Sborman } 66238905Sborman #endif 66338905Sborman } 66438905Sborman 66546809Sdab void 66638905Sborman tty_binaryout(on) 66746809Sdab int on; 66838905Sborman { 66938905Sborman #ifndef USE_TERMIO 67038905Sborman if (on) 67138905Sborman termbuf.lflags |= LLITOUT; 67238905Sborman else 67338905Sborman termbuf.lflags &= ~LLITOUT; 67438905Sborman #else 67538905Sborman if (on) { 67638905Sborman termbuf.c_cflag &= ~(CSIZE|PARENB); 67738905Sborman termbuf.c_cflag |= CS8; 67838905Sborman termbuf.c_oflag &= ~OPOST; 67938905Sborman } else { 68038905Sborman termbuf.c_cflag &= ~CSIZE; 68138905Sborman termbuf.c_cflag |= CS7|PARENB; 68238905Sborman termbuf.c_oflag |= OPOST; 68338905Sborman } 68438905Sborman #endif 68538905Sborman } 68638905Sborman 68746809Sdab int 68838905Sborman tty_isbinaryin() 68938905Sborman { 69038905Sborman #ifndef USE_TERMIO 69138905Sborman return(termbuf.lflags & LPASS8); 69238905Sborman #else 69339503Sborman return(!(termbuf.c_iflag & ISTRIP)); 69438905Sborman #endif 69538905Sborman } 69638905Sborman 69746809Sdab int 69838905Sborman tty_isbinaryout() 69938905Sborman { 70038905Sborman #ifndef USE_TERMIO 70138905Sborman return(termbuf.lflags & LLITOUT); 70238905Sborman #else 70339503Sborman return(!(termbuf.c_oflag&OPOST)); 70438905Sborman #endif 70538905Sborman } 70638905Sborman 70738905Sborman #ifdef LINEMODE 70846809Sdab int 70938905Sborman tty_isediting() 71038905Sborman { 71138905Sborman #ifndef USE_TERMIO 71238905Sborman return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); 71338905Sborman #else 71438905Sborman return(termbuf.c_lflag & ICANON); 71538905Sborman #endif 71638905Sborman } 71738905Sborman 71846809Sdab int 71938905Sborman tty_istrapsig() 72038905Sborman { 72138905Sborman #ifndef USE_TERMIO 72238905Sborman return(!(termbuf.sg.sg_flags&RAW)); 72338905Sborman #else 72438905Sborman return(termbuf.c_lflag & ISIG); 72538905Sborman #endif 72638905Sborman } 72738905Sborman 72846809Sdab void 72938905Sborman tty_setedit(on) 73046809Sdab int on; 73138905Sborman { 73238905Sborman #ifndef USE_TERMIO 73338905Sborman if (on) 73438905Sborman termbuf.sg.sg_flags &= ~CBREAK; 73538905Sborman else 73638905Sborman termbuf.sg.sg_flags |= CBREAK; 73738905Sborman #else 73838905Sborman if (on) 73938905Sborman termbuf.c_lflag |= ICANON; 74038905Sborman else 74138905Sborman termbuf.c_lflag &= ~ICANON; 74238905Sborman #endif 74338905Sborman } 74438905Sborman 74546809Sdab void 74638905Sborman tty_setsig(on) 74746809Sdab int on; 74838905Sborman { 74938905Sborman #ifndef USE_TERMIO 75038905Sborman if (on) 75138905Sborman ; 75238905Sborman #else 75338905Sborman if (on) 75438905Sborman termbuf.c_lflag |= ISIG; 75538905Sborman else 75638905Sborman termbuf.c_lflag &= ~ISIG; 75738905Sborman #endif 75838905Sborman } 75938905Sborman #endif /* LINEMODE */ 76038905Sborman 76146809Sdab int 76244364Sborman tty_issofttab() 76344364Sborman { 76444364Sborman #ifndef USE_TERMIO 76544364Sborman return (termbuf.sg.sg_flags & XTABS); 76644364Sborman #else 76744364Sborman # ifdef OXTABS 76844364Sborman return (termbuf.c_oflag & OXTABS); 76944364Sborman # endif 77044364Sborman # ifdef TABDLY 77144364Sborman return ((termbuf.c_oflag & TABDLY) == TAB3); 77244364Sborman # endif 77344364Sborman #endif 77444364Sborman } 77544364Sborman 77646809Sdab void 77744364Sborman tty_setsofttab(on) 77846809Sdab int on; 77944364Sborman { 78044364Sborman #ifndef USE_TERMIO 78144364Sborman if (on) 78244364Sborman termbuf.sg.sg_flags |= XTABS; 78344364Sborman else 78444364Sborman termbuf.sg.sg_flags &= ~XTABS; 78544364Sborman #else 78644364Sborman if (on) { 78744364Sborman # ifdef OXTABS 78844364Sborman termbuf.c_oflag |= OXTABS; 78944364Sborman # endif 79044364Sborman # ifdef TABDLY 79144364Sborman termbuf.c_oflag &= ~TABDLY; 79244364Sborman termbuf.c_oflag |= TAB3; 79344364Sborman # endif 79444364Sborman } else { 79544364Sborman # ifdef OXTABS 79644364Sborman termbuf.c_oflag &= ~OXTABS; 79744364Sborman # endif 79844364Sborman # ifdef TABDLY 79944364Sborman termbuf.c_oflag &= ~TABDLY; 80044364Sborman termbuf.c_oflag |= TAB0; 80144364Sborman # endif 80244364Sborman } 80344364Sborman #endif 80444364Sborman } 80544364Sborman 80646809Sdab int 80744364Sborman tty_islitecho() 80844364Sborman { 80944364Sborman #ifndef USE_TERMIO 81046809Sdab return (!(termbuf.lflags & LCTLECH)); 81144364Sborman #else 81244364Sborman # ifdef ECHOCTL 81344364Sborman return (!(termbuf.c_lflag & ECHOCTL)); 81444364Sborman # endif 81544364Sborman # ifdef TCTLECH 81644364Sborman return (!(termbuf.c_lflag & TCTLECH)); 81744364Sborman # endif 81844364Sborman # if !defined(ECHOCTL) && !defined(TCTLECH) 81944364Sborman return (0); /* assumes ctl chars are echoed '^x' */ 82044364Sborman # endif 82144364Sborman #endif 82244364Sborman } 82344364Sborman 82446809Sdab void 82544364Sborman tty_setlitecho(on) 82646809Sdab int on; 82744364Sborman { 82844364Sborman #ifndef USE_TERMIO 82944364Sborman if (on) 83046809Sdab termbuf.lflags &= ~LCTLECH; 83144364Sborman else 83246809Sdab termbuf.lflags |= LCTLECH; 83344364Sborman #else 83444364Sborman # ifdef ECHOCTL 83544364Sborman if (on) 83644364Sborman termbuf.c_lflag &= ~ECHOCTL; 83744364Sborman else 83844364Sborman termbuf.c_lflag |= ECHOCTL; 83944364Sborman # endif 84044364Sborman # ifdef TCTLECH 84144364Sborman if (on) 84244364Sborman termbuf.c_lflag &= ~TCTLECH; 84344364Sborman else 84444364Sborman termbuf.c_lflag |= TCTLECH; 84544364Sborman # endif 84644364Sborman #endif 84744364Sborman } 84844364Sborman 84946809Sdab int 85046809Sdab tty_iscrnl() 85146809Sdab { 85246809Sdab #ifndef USE_TERMIO 85346809Sdab return (termbuf.sg.sg_flags & CRMOD); 85446809Sdab #else 85546809Sdab return (termbuf.c_iflag & ICRNL); 85646809Sdab #endif 85746809Sdab } 85846809Sdab 85938905Sborman /* 86038905Sborman * A table of available terminal speeds 86138905Sborman */ 86238905Sborman struct termspeeds { 86338905Sborman int speed; 86438905Sborman int value; 86538905Sborman } termspeeds[] = { 86638905Sborman { 0, B0 }, { 50, B50 }, { 75, B75 }, 86738905Sborman { 110, B110 }, { 134, B134 }, { 150, B150 }, 86838905Sborman { 200, B200 }, { 300, B300 }, { 600, B600 }, 86938905Sborman { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 87038905Sborman { 4800, B4800 }, { 9600, B9600 }, { 19200, B9600 }, 87138905Sborman { 38400, B9600 }, { -1, B9600 } 87238905Sborman }; 87338905Sborman 87446809Sdab void 87538905Sborman tty_tspeed(val) 87646809Sdab int val; 87738905Sborman { 87838905Sborman register struct termspeeds *tp; 87938905Sborman 88038905Sborman for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 88138905Sborman ; 88245234Sborman cfsetospeed(&termbuf, tp->value); 88338905Sborman } 88438905Sborman 88546809Sdab void 88638905Sborman tty_rspeed(val) 88746809Sdab int val; 88838905Sborman { 88938905Sborman register struct termspeeds *tp; 89038905Sborman 89138905Sborman for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 89238905Sborman ; 89345234Sborman cfsetispeed(&termbuf, tp->value); 89438905Sborman } 89538905Sborman 89640242Sborman #if defined(CRAY2) && defined(UNICOS5) 89746809Sdab int 89838905Sborman tty_isnewmap() 89938905Sborman { 90038905Sborman return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) && 90138905Sborman !(termbuf.c_oflag & ONLRET)); 90238905Sborman } 90338905Sborman #endif 90438905Sborman 90538905Sborman #ifdef CRAY 90638905Sborman # ifndef NEWINIT 90738905Sborman extern struct utmp wtmp; 90838905Sborman extern char wtmpf[]; 90938905Sborman # else /* NEWINIT */ 91038905Sborman int gotalarm; 91146809Sdab 91246809Sdab /* ARGSUSED */ 91346809Sdab void 91440242Sborman nologinproc(sig) 91546809Sdab int sig; 91638905Sborman { 91738905Sborman gotalarm++; 91838905Sborman } 91938905Sborman # endif /* NEWINIT */ 92038905Sborman #endif /* CRAY */ 92138905Sborman 92246809Sdab #ifndef NEWINIT 92346809Sdab # ifdef CRAY 92446809Sdab extern void utmp_sig_init P((void)); 92546809Sdab extern void utmp_sig_reset P((void)); 92646809Sdab extern void utmp_sig_wait P((void)); 92746809Sdab extern void utmp_sig_notify P((int)); 92846809Sdab # endif 92946809Sdab #endif 93046809Sdab 93138905Sborman /* 93238905Sborman * getptyslave() 93338905Sborman * 93438905Sborman * Open the slave side of the pty, and do any initialization 93538905Sborman * that is necessary. The return value is a file descriptor 93638905Sborman * for the slave side. 93738905Sborman */ 93846809Sdab int 93938905Sborman getptyslave() 94038905Sborman { 94138905Sborman register int t = -1; 94238905Sborman 94345234Sborman #if !defined(CRAY) || !defined(NEWINIT) 94445234Sborman # ifdef LINEMODE 94546809Sdab int waslm; 94646809Sdab # endif 94746809Sdab # ifdef TIOCGWINSZ 94846809Sdab struct winsize ws; 94946809Sdab extern int def_row, def_col; 95046809Sdab # endif 95146809Sdab extern int def_tspeed, def_rspeed; 95238905Sborman /* 95345234Sborman * Opening the slave side may cause initilization of the 95446809Sdab * kernel tty structure. We need remember the state of 95546809Sdab * if linemode was turned on 95646809Sdab * terminal window size 95746809Sdab * terminal speed 95846809Sdab * so that we can re-set them if we need to. 95938905Sborman */ 96046809Sdab # ifdef LINEMODE 96146809Sdab waslm = tty_linemode(); 96245234Sborman # endif 96345234Sborman 96445234Sborman 96545234Sborman /* 96645234Sborman * Make sure that we don't have a controlling tty, and 96745234Sborman * that we are the session (process group) leader. 96845234Sborman */ 96945234Sborman # ifdef TIOCNOTTY 97038905Sborman t = open(_PATH_TTY, O_RDWR); 97138905Sborman if (t >= 0) { 97238905Sborman (void) ioctl(t, TIOCNOTTY, (char *)0); 97338905Sborman (void) close(t); 97438905Sborman } 97545234Sborman # endif 97638905Sborman 97745234Sborman 97845234Sborman # ifdef CRAY 97945234Sborman /* 98045234Sborman * Wait for our parent to get the utmp stuff to get done. 98145234Sborman */ 98245234Sborman utmp_sig_wait(); 98345234Sborman # endif 98445234Sborman 98545234Sborman t = cleanopen(line); 98638905Sborman if (t < 0) 98738905Sborman fatalperror(net, line); 98838905Sborman 989*57212Sdab #ifdef USE_TERMIO 990*57212Sdab ttyfd = t; 991*57212Sdab #endif 992*57212Sdab #ifdef STREAMSPTY 993*57212Sdab if (ioctl(t, I_PUSH, "ptem") < 0) 994*57212Sdab fatal(net, "I_PUSH ptem"); 995*57212Sdab if (ioctl(t, I_PUSH, "ldterm") < 0) 996*57212Sdab fatal(net, "I_PUSH ldterm"); 997*57212Sdab if (ioctl(t, I_PUSH, "ttcompat") < 0) 998*57212Sdab fatal(net, "I_PUSH ttcompat"); 999*57212Sdab if (ioctl(pty, I_PUSH, "pckt") < 0) 1000*57212Sdab fatal(net, "I_PUSH pckt"); 1001*57212Sdab #endif 1002*57212Sdab 100345234Sborman /* 100445234Sborman * set up the tty modes as we like them to be. 100545234Sborman */ 100638905Sborman init_termbuf(); 100746809Sdab # ifdef TIOCGWINSZ 100846809Sdab if (def_row || def_col) { 100946809Sdab bzero((char *)&ws, sizeof(ws)); 101046809Sdab ws.ws_col = def_col; 101146809Sdab ws.ws_row = def_row; 101246809Sdab (void)ioctl(t, TIOCSWINSZ, (char *)&ws); 101346809Sdab } 101446809Sdab # endif 101545234Sborman 101645234Sborman /* 101745234Sborman * Settings for sgtty based systems 101845234Sborman */ 101945234Sborman # ifndef USE_TERMIO 102040242Sborman termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; 102145234Sborman # endif /* USE_TERMIO */ 102245234Sborman 102345234Sborman /* 102445234Sborman * Settings for UNICOS 102545234Sborman */ 102645234Sborman # ifdef CRAY 102745234Sborman termbuf.c_oflag = OPOST|ONLCR|TAB3; 102845234Sborman termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; 102945234Sborman termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; 103045234Sborman termbuf.c_cflag = EXTB|HUPCL|CS8; 103145234Sborman # endif 103245234Sborman 103345234Sborman /* 103445234Sborman * Settings for all other termios/termio based 103545234Sborman * systems, other than 4.4BSD. In 4.4BSD the 103645234Sborman * kernel does the initial terminal setup. 103745234Sborman */ 103845234Sborman # if defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) 103945234Sborman # ifndef OXTABS 104045234Sborman # define OXTABS 0 104145234Sborman # endif 104238905Sborman termbuf.c_lflag |= ECHO; 104338905Sborman termbuf.c_oflag |= ONLCR|OXTABS; 104438905Sborman termbuf.c_iflag |= ICRNL; 104538905Sborman termbuf.c_iflag &= ~IXOFF; 104645234Sborman # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */ 104746996Sdab tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); 104846996Sdab tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); 104946809Sdab # ifdef LINEMODE 105046809Sdab if (waslm) 105146809Sdab tty_setlinemode(1); 105246809Sdab # endif /* LINEMODE */ 105345234Sborman 105445234Sborman /* 105545234Sborman * Set the tty modes, and make this our controlling tty. 105645234Sborman */ 105745234Sborman set_termbuf(); 105845234Sborman if (login_tty(t) == -1) 105945234Sborman fatalperror(net, "login_tty"); 106045234Sborman #endif /* !defined(CRAY) || !defined(NEWINIT) */ 106145234Sborman if (net > 2) 106245234Sborman (void) close(net); 106345234Sborman if (pty > 2) 106445234Sborman (void) close(pty); 106545234Sborman } 106645234Sborman 106745234Sborman #if !defined(CRAY) || !defined(NEWINIT) 106845234Sborman #ifndef O_NOCTTY 106945234Sborman #define O_NOCTTY 0 107038905Sborman #endif 107145234Sborman /* 107245234Sborman * Open the specified slave side of the pty, 107345234Sborman * making sure that we have a clean tty. 107445234Sborman */ 107546809Sdab int 107645234Sborman cleanopen(line) 107746809Sdab char *line; 107845234Sborman { 107945234Sborman register int t; 1080*57212Sdab #if defined(_SC_CRAY_SECURE_SYS) 1081*57212Sdab struct secstat secbuf; 1082*57212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 108345234Sborman 1084*57212Sdab #ifndef STREAMSPTY 108545234Sborman /* 108645234Sborman * Make sure that other people can't open the 108745234Sborman * slave side of the connection. 108845234Sborman */ 108938905Sborman (void) chown(line, 0, 0); 109038905Sborman (void) chmod(line, 0600); 1091*57212Sdab #endif 109245234Sborman 109345234Sborman # if !defined(CRAY) && (BSD > 43) 109445234Sborman (void) revoke(line); 109545234Sborman # endif 1096*57212Sdab #if defined(_SC_CRAY_SECURE_SYS) 1097*57212Sdab if (secflag) { 1098*57212Sdab if (secstat(line, &secbuf) < 0) 1099*57212Sdab return(-1); 1100*57212Sdab if (setulvl(secbuf.st_slevel) < 0) 1101*57212Sdab return(-1); 1102*57212Sdab if (setucmp(secbuf.st_compart) < 0) 1103*57212Sdab return(-1); 1104*57212Sdab } 1105*57212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 1106*57212Sdab 110745234Sborman t = open(line, O_RDWR|O_NOCTTY); 1108*57212Sdab 1109*57212Sdab #if defined(_SC_CRAY_SECURE_SYS) 1110*57212Sdab if (secflag) { 1111*57212Sdab if (setulvl(sysv.sy_minlvl) < 0) 1112*57212Sdab return(-1); 1113*57212Sdab if (setucmp(0) < 0) 1114*57212Sdab return(-1); 1115*57212Sdab } 1116*57212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 1117*57212Sdab 111845234Sborman if (t < 0) 111945234Sborman return(-1); 112045234Sborman 112145234Sborman /* 112245234Sborman * Hangup anybody else using this ttyp, then reopen it for 112345234Sborman * ourselves. 112445234Sborman */ 1125*57212Sdab # if !defined(CRAY) && (BSD <= 43) && !defined(STREAMSPTY) 112645234Sborman (void) signal(SIGHUP, SIG_IGN); 112745234Sborman vhangup(); 112845234Sborman (void) signal(SIGHUP, SIG_DFL); 112945234Sborman t = open(line, O_RDWR|O_NOCTTY); 113045234Sborman if (t < 0) 113145234Sborman return(-1); 113245234Sborman # endif 113345234Sborman # if defined(CRAY) && defined(TCVHUP) 113445234Sborman { 113545234Sborman register int i; 113645234Sborman (void) signal(SIGHUP, SIG_IGN); 113745234Sborman (void) ioctl(t, TCVHUP, (char *)0); 113845234Sborman (void) signal(SIGHUP, SIG_DFL); 113945234Sborman setpgrp(); 1140*57212Sdab 1141*57212Sdab #if defined(_SC_CRAY_SECURE_SYS) 1142*57212Sdab if (secflag) { 1143*57212Sdab if (secstat(line, &secbuf) < 0) 1144*57212Sdab return(-1); 1145*57212Sdab if (setulvl(secbuf.st_slevel) < 0) 1146*57212Sdab return(-1); 1147*57212Sdab if (setucmp(secbuf.st_compart) < 0) 1148*57212Sdab return(-1); 1149*57212Sdab } 1150*57212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 1151*57212Sdab 115245234Sborman i = open(line, O_RDWR); 1153*57212Sdab 1154*57212Sdab #if defined(_SC_CRAY_SECURE_SYS) 1155*57212Sdab if (secflag) { 1156*57212Sdab if (setulvl(sysv.sy_minlvl) < 0) 1157*57212Sdab return(-1); 1158*57212Sdab if (setucmp(0) < 0) 1159*57212Sdab return(-1); 1160*57212Sdab } 1161*57212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 1162*57212Sdab 116345234Sborman if (i < 0) 116446809Sdab return(-1); 116545234Sborman (void) close(t); 116645234Sborman t = i; 116745234Sborman } 116845234Sborman # endif /* defined(CRAY) && defined(TCVHUP) */ 116938905Sborman return(t); 117038905Sborman } 117145234Sborman #endif /* !defined(CRAY) || !defined(NEWINIT) */ 117238905Sborman 117345234Sborman #if BSD <= 43 117446809Sdab int 117545234Sborman login_tty(t) 117646809Sdab int t; 117745234Sborman { 117845234Sborman if (setsid() < 0) 117945234Sborman fatalperror(net, "setsid()"); 118045234Sborman # ifdef TIOCSCTTY 118145234Sborman if (ioctl(t, TIOCSCTTY, (char *)0) < 0) 118245234Sborman fatalperror(net, "ioctl(sctty)"); 1183*57212Sdab # if defined(CRAY) 118447613Sdab /* 118547613Sdab * Close the hard fd to /dev/ttypXXX, and re-open through 118647613Sdab * the indirect /dev/tty interface. 118747613Sdab */ 118847613Sdab close(t); 118947613Sdab if ((t = open("/dev/tty", O_RDWR)) < 0) 119047613Sdab fatalperror(net, "open(/dev/tty)"); 119147613Sdab # endif 119245234Sborman # else 119345234Sborman close(open(line, O_RDWR)); 119445234Sborman # endif 119547613Sdab if (t != 0) 119647613Sdab (void) dup2(t, 0); 119747613Sdab if (t != 1) 119847613Sdab (void) dup2(t, 1); 119947613Sdab if (t != 2) 120047613Sdab (void) dup2(t, 2); 120147613Sdab if (t > 2) 120247613Sdab close(t); 120346809Sdab return(0); 120445234Sborman } 120545234Sborman #endif /* BSD <= 43 */ 120645234Sborman 120738905Sborman #ifdef NEWINIT 120838905Sborman char *gen_id = "fe"; 120938905Sborman #endif 121038905Sborman 121138905Sborman /* 121245234Sborman * startslave(host) 121338905Sborman * 121445234Sborman * Given a hostname, do whatever 121538905Sborman * is necessary to startup the login process on the slave side of the pty. 121638905Sborman */ 121738905Sborman 121838905Sborman /* ARGSUSED */ 121946809Sdab void 122046809Sdab startslave(host, autologin, autoname) 122146809Sdab char *host; 122246809Sdab int autologin; 122346809Sdab char *autoname; 122438905Sborman { 122538905Sborman register int i; 122638905Sborman long time(); 122746809Sdab char name[256]; 122846809Sdab #ifdef NEWINIT 122946809Sdab extern char *ptyip; 123046809Sdab struct init_request request; 123146809Sdab void nologinproc(); 123246809Sdab register int n; 123346809Sdab #endif /* NEWINIT */ 123438905Sborman 1235*57212Sdab #if defined(AUTHENTICATION) 123646809Sdab if (!autoname || !autoname[0]) 123746809Sdab autologin = 0; 123846809Sdab 123946809Sdab if (autologin < auth_level) { 124046809Sdab fatal(net, "Authorization failed"); 124146809Sdab exit(1); 124246809Sdab } 124346809Sdab #endif 124446809Sdab 124538905Sborman #ifndef NEWINIT 124638905Sborman # ifdef CRAY 124738905Sborman utmp_sig_init(); 124838905Sborman # endif /* CRAY */ 124938905Sborman 125038905Sborman if ((i = fork()) < 0) 125138905Sborman fatalperror(net, "fork"); 125238905Sborman if (i) { 125338905Sborman # ifdef CRAY 125438905Sborman /* 125538905Sborman * Cray parent will create utmp entry for child and send 125638905Sborman * signal to child to tell when done. Child waits for signal 125738905Sborman * before doing anything important. 125838905Sborman */ 125938905Sborman register int pid = i; 126046809Sdab void sigjob P((int)); 126138905Sborman 126238905Sborman setpgrp(); 126344364Sborman utmp_sig_reset(); /* reset handler to default */ 126438905Sborman /* 126538905Sborman * Create utmp entry for child 126638905Sborman */ 126738905Sborman (void) time(&wtmp.ut_time); 126838905Sborman wtmp.ut_type = LOGIN_PROCESS; 126938905Sborman wtmp.ut_pid = pid; 127038905Sborman SCPYN(wtmp.ut_user, "LOGIN"); 127138905Sborman SCPYN(wtmp.ut_host, host); 127238905Sborman SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); 127338905Sborman SCPYN(wtmp.ut_id, wtmp.ut_line+3); 127438905Sborman pututline(&wtmp); 127538905Sborman endutent(); 127638905Sborman if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { 127738905Sborman (void) write(i, (char *)&wtmp, sizeof(struct utmp)); 127838905Sborman (void) close(i); 127938905Sborman } 128046809Sdab (void) signal(WJSIGNAL, sigjob); 128138905Sborman utmp_sig_notify(pid); 128238905Sborman # endif /* CRAY */ 128338905Sborman } else { 128445234Sborman getptyslave(); 128546809Sdab start_login(host, autologin, autoname); 128638905Sborman /*NOTREACHED*/ 128738905Sborman } 128838905Sborman #else /* NEWINIT */ 128938905Sborman 129038905Sborman /* 129138905Sborman * Init will start up login process if we ask nicely. We only wait 129238905Sborman * for it to start up and begin normal telnet operation. 129338905Sborman */ 129438905Sborman if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { 129538905Sborman char tbuf[128]; 129638905Sborman (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO); 129738905Sborman fatalperror(net, tbuf); 129838905Sborman } 129938905Sborman memset((char *)&request, 0, sizeof(request)); 130038905Sborman request.magic = INIT_MAGIC; 130138905Sborman SCPYN(request.gen_id, gen_id); 130238905Sborman SCPYN(request.tty_id, &line[8]); 130338905Sborman SCPYN(request.host, host); 130446809Sdab SCPYN(request.term_type, terminaltype ? terminaltype : "network"); 130544364Sborman #if !defined(UNICOS5) 130640242Sborman request.signal = SIGCLD; 130740242Sborman request.pid = getpid(); 130840242Sborman #endif 130944364Sborman #ifdef BFTPDAEMON 131044364Sborman /* 131144364Sborman * Are we working as the bftp daemon? 131244364Sborman */ 131344364Sborman if (bftpd) { 131444364Sborman SCPYN(request.exec_name, BFTPPATH); 131544364Sborman } 131644364Sborman #endif /* BFTPDAEMON */ 131738905Sborman if (write(i, (char *)&request, sizeof(request)) < 0) { 131838905Sborman char tbuf[128]; 131938905Sborman (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO); 132038905Sborman fatalperror(net, tbuf); 132138905Sborman } 132238905Sborman (void) close(i); 132338905Sborman (void) signal(SIGALRM, nologinproc); 132438905Sborman for (i = 0; ; i++) { 132540242Sborman char tbuf[128]; 132638905Sborman alarm(15); 132738905Sborman n = read(pty, ptyip, BUFSIZ); 132838905Sborman if (i == 3 || n >= 0 || !gotalarm) 132938905Sborman break; 133038905Sborman gotalarm = 0; 133140242Sborman sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line); 133240242Sborman (void) write(net, tbuf, strlen(tbuf)); 133338905Sborman } 133438905Sborman if (n < 0 && gotalarm) 133538905Sborman fatal(net, "/etc/init didn't start login process"); 133638905Sborman pcc += n; 133738905Sborman alarm(0); 133838905Sborman (void) signal(SIGALRM, SIG_DFL); 133938905Sborman 134038905Sborman return; 134138905Sborman #endif /* NEWINIT */ 134238905Sborman } 134338905Sborman 134438905Sborman char *envinit[3]; 134544364Sborman extern char **environ; 134638905Sborman 134746809Sdab void 134844364Sborman init_env() 134944364Sborman { 135044364Sborman extern char *getenv(); 135144364Sborman char **envp; 135244364Sborman 135344364Sborman envp = envinit; 135444364Sborman if (*envp = getenv("TZ")) 135544364Sborman *envp++ -= 3; 135644364Sborman #ifdef CRAY 135744364Sborman else 135844364Sborman *envp++ = "TZ=GMT0"; 135944364Sborman #endif 136044364Sborman *envp = 0; 136144364Sborman environ = envinit; 136244364Sborman } 136344364Sborman 136444364Sborman #ifndef NEWINIT 136544364Sborman 136644364Sborman /* 136745234Sborman * start_login(host) 136838905Sborman * 136938905Sborman * Assuming that we are now running as a child processes, this 137038905Sborman * function will turn us into the login process. 137138905Sborman */ 137238905Sborman 137346809Sdab void 137446809Sdab start_login(host, autologin, name) 137546809Sdab char *host; 137646809Sdab int autologin; 137746809Sdab char *name; 137838905Sborman { 137944364Sborman register char *cp; 138044364Sborman register char **argv; 138144364Sborman char **addarg(); 1382*57212Sdab #ifdef UTMPX 1383*57212Sdab register int pid = getpid(); 1384*57212Sdab struct utmpx utmpx; 1385*57212Sdab #endif 1386*57212Sdab #ifdef __svr4__ 1387*57212Sdab char *term; 1388*57212Sdab char termbuf[64]; 1389*57212Sdab #endif 139038905Sborman 1391*57212Sdab #ifdef UTMPX 139238905Sborman /* 1393*57212Sdab * Create utmp entry for child 1394*57212Sdab */ 1395*57212Sdab 1396*57212Sdab bzero(&utmpx, sizeof(utmpx)); 1397*57212Sdab SCPYN(utmpx.ut_user, ".telnet"); 1398*57212Sdab SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); 1399*57212Sdab utmpx.ut_pid = pid; 1400*57212Sdab utmpx.ut_id[0] = 't'; 1401*57212Sdab utmpx.ut_id[1] = 'n'; 1402*57212Sdab utmpx.ut_id[2] = SC_WILDC; 1403*57212Sdab utmpx.ut_id[3] = SC_WILDC; 1404*57212Sdab utmpx.ut_type = LOGIN_PROCESS; 1405*57212Sdab (void) time(&utmpx.ut_tv.tv_sec); 1406*57212Sdab if (makeutx(&utmpx) == NULL) 1407*57212Sdab fatal(net, "makeutx failed"); 1408*57212Sdab #endif 1409*57212Sdab 1410*57212Sdab /* 141138905Sborman * -h : pass on name of host. 141238905Sborman * WARNING: -h is accepted by login if and only if 141338905Sborman * getuid() == 0. 141438905Sborman * -p : don't clobber the environment (so terminal type stays set). 141546809Sdab * 141646809Sdab * -f : force this login, he has already been authenticated 141738905Sborman */ 141844364Sborman argv = addarg(0, "login"); 141944364Sborman argv = addarg(argv, "-h"); 142044364Sborman argv = addarg(argv, host); 1421*57212Sdab #ifdef __svr4__ 1422*57212Sdab /* 1423*57212Sdab * SVR4 version of -h takes TERM= as second arg, or - 1424*57212Sdab */ 1425*57212Sdab term = getenv("TERM"); 1426*57212Sdab if (term == NULL || term[0] == 0) { 1427*57212Sdab term = "-"; 1428*57212Sdab } else { 1429*57212Sdab strcpy(termbuf, "TERM="); 1430*57212Sdab strncat(termbuf, term, sizeof(termbuf) - 6); 1431*57212Sdab term = termbuf; 1432*57212Sdab } 1433*57212Sdab argv = addarg(argv, term); 1434*57212Sdab #endif 143546809Sdab #if !defined(NO_LOGIN_P) 143644364Sborman argv = addarg(argv, "-p"); 143738905Sborman #endif 143844364Sborman #ifdef BFTPDAEMON 143944364Sborman /* 144044364Sborman * Are we working as the bftp daemon? If so, then ask login 144144364Sborman * to start bftp instead of shell. 144244364Sborman */ 144344364Sborman if (bftpd) { 144444364Sborman argv = addarg(argv, "-e"); 144544364Sborman argv = addarg(argv, BFTPPATH); 144644364Sborman } else 144744364Sborman #endif 144846809Sdab #if defined (SecurID) 144946809Sdab /* 145046809Sdab * don't worry about the -f that might get sent. 145146809Sdab * A -s is supposed to override it anyhow. 145246809Sdab */ 145346809Sdab if (require_SecurID) 145446809Sdab argv = addarg(argv, "-s"); 145546809Sdab #endif 1456*57212Sdab #if defined (AUTHENTICATION) 145746809Sdab if (auth_level >= 0 && autologin == AUTH_VALID) { 145846809Sdab # if !defined(NO_LOGIN_F) 145946809Sdab argv = addarg(argv, "-f"); 146046809Sdab # endif 146146809Sdab argv = addarg(argv, name); 146246809Sdab } else 146346809Sdab #endif 146444364Sborman if (getenv("USER")) { 146544364Sborman argv = addarg(argv, getenv("USER")); 146646809Sdab #if defined(CRAY) && defined(NO_LOGIN_P) 146746809Sdab { 146846809Sdab register char **cpp; 146946809Sdab for (cpp = environ; *cpp; cpp++) 147046809Sdab argv = addarg(argv, *cpp); 147146809Sdab } 147246809Sdab #endif 1473*57212Sdab /* 1474*57212Sdab * Assume that login will set the USER variable 1475*57212Sdab * correctly. For SysV systems, this means that 1476*57212Sdab * USER will no longer be set, just LOGNAME by 1477*57212Sdab * login. (The problem is that if the auto-login 1478*57212Sdab * fails, and the user then specifies a different 1479*57212Sdab * account name, he can get logged in with both 1480*57212Sdab * LOGNAME and USER in his environment, but the 1481*57212Sdab * USER value will be wrong. 1482*57212Sdab */ 1483*57212Sdab unsetenv("USER"); 148444364Sborman } 148546809Sdab closelog(); 148644364Sborman execv(_PATH_LOGIN, argv); 148744364Sborman 148838905Sborman syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN); 148938905Sborman fatalperror(net, _PATH_LOGIN); 149038905Sborman /*NOTREACHED*/ 149138905Sborman } 149244364Sborman 149346809Sdab char ** 149444364Sborman addarg(argv, val) 149546809Sdab register char **argv; 149646809Sdab register char *val; 149744364Sborman { 149844364Sborman register char **cpp; 149944364Sborman 150044364Sborman if (argv == NULL) { 150144364Sborman /* 150244364Sborman * 10 entries, a leading length, and a null 150344364Sborman */ 150444364Sborman argv = (char **)malloc(sizeof(*argv) * 12); 150544364Sborman if (argv == NULL) 150644364Sborman return(NULL); 150744364Sborman *argv++ = (char *)10; 150844364Sborman *argv = (char *)0; 150944364Sborman } 151044364Sborman for (cpp = argv; *cpp; cpp++) 151144364Sborman ; 151244364Sborman if (cpp == &argv[(int)argv[-1]]) { 151344364Sborman --argv; 151444364Sborman *argv = (char *)((int)(*argv) + 10); 151544364Sborman argv = (char **)realloc(argv, (int)(*argv) + 2); 151644364Sborman if (argv == NULL) 151744364Sborman return(NULL); 151844364Sborman argv++; 151944364Sborman cpp = &argv[(int)argv[-1] - 10]; 152044364Sborman } 152144364Sborman *cpp++ = val; 152244364Sborman *cpp = 0; 152344364Sborman return(argv); 152444364Sborman } 152546809Sdab #endif /* NEWINIT */ 152638905Sborman 152738905Sborman /* 152838905Sborman * cleanup() 152938905Sborman * 153038905Sborman * This is the routine to call when we are all through, to 153138905Sborman * clean up anything that needs to be cleaned up. 153238905Sborman */ 153346809Sdab /* ARGSUSED */ 153446809Sdab void 153546809Sdab cleanup(sig) 153646809Sdab int sig; 153738905Sborman { 153838905Sborman #ifndef CRAY 153945234Sborman # if (BSD > 43) || defined(convex) 154038905Sborman char *p; 154138905Sborman 154238905Sborman p = line + sizeof("/dev/") - 1; 154338905Sborman if (logout(p)) 154438905Sborman logwtmp(p, "", ""); 154538905Sborman (void)chmod(line, 0666); 154638905Sborman (void)chown(line, 0, 0); 154738905Sborman *p = 'p'; 154838905Sborman (void)chmod(line, 0666); 154938905Sborman (void)chown(line, 0, 0); 155046809Sdab (void) shutdown(net, 2); 155146809Sdab exit(1); 155238905Sborman # else 155346809Sdab void rmut(); 155446809Sdab 155538905Sborman rmut(); 155638905Sborman vhangup(); /* XXX */ 155746809Sdab (void) shutdown(net, 2); 155846809Sdab exit(1); 155938905Sborman # endif 156038905Sborman #else /* CRAY */ 156146809Sdab # ifdef NEWINIT 156238905Sborman (void) shutdown(net, 2); 156346809Sdab exit(1); 156438905Sborman # else /* NEWINIT */ 156546809Sdab static int incleanup = 0; 156646809Sdab register int t; 156746809Sdab 156846809Sdab /* 156946809Sdab * 1: Pick up the zombie, if we are being called 157046809Sdab * as the signal handler. 157146809Sdab * 2: If we are a nested cleanup(), return. 157246809Sdab * 3: Try to clean up TMPDIR. 157346809Sdab * 4: Fill in utmp with shutdown of process. 157446809Sdab * 5: Close down the network and pty connections. 157546809Sdab * 6: Finish up the TMPDIR cleanup, if needed. 157646809Sdab */ 157746809Sdab if (sig == SIGCHLD) 157846809Sdab while (waitpid(-1, 0, WNOHANG) > 0) 157946809Sdab ; /* VOID */ 158046809Sdab t = sigblock(sigmask(SIGCHLD)); 158146809Sdab if (incleanup) { 158246809Sdab sigsetmask(t); 158346809Sdab return; 158446809Sdab } 158546809Sdab incleanup = 1; 158646809Sdab sigsetmask(t); 158746809Sdab 158846809Sdab t = cleantmp(&wtmp); 158946809Sdab setutent(); /* just to make sure */ 159046809Sdab rmut(line); 159146809Sdab close(pty); 159238905Sborman (void) shutdown(net, 2); 159346809Sdab if (t == 0) 159446809Sdab cleantmp(&wtmp); 159546809Sdab exit(1); 159638905Sborman # endif /* NEWINT */ 159738905Sborman #endif /* CRAY */ 159838905Sborman } 159938905Sborman 160038905Sborman #if defined(CRAY) && !defined(NEWINIT) 160138905Sborman /* 160238905Sborman * _utmp_sig_rcv 160338905Sborman * utmp_sig_init 160438905Sborman * utmp_sig_wait 160538905Sborman * These three functions are used to coordinate the handling of 160638905Sborman * the utmp file between the server and the soon-to-be-login shell. 160738905Sborman * The server actually creates the utmp structure, the child calls 160838905Sborman * utmp_sig_wait(), until the server calls utmp_sig_notify() and 160938905Sborman * signals the future-login shell to proceed. 161038905Sborman */ 161138905Sborman static int caught=0; /* NZ when signal intercepted */ 161238905Sborman static void (*func)(); /* address of previous handler */ 161338905Sborman 161446809Sdab void 161538905Sborman _utmp_sig_rcv(sig) 161646809Sdab int sig; 161738905Sborman { 161838905Sborman caught = 1; 161938905Sborman (void) signal(SIGUSR1, func); 162038905Sborman } 162138905Sborman 162246809Sdab void 162338905Sborman utmp_sig_init() 162438905Sborman { 162538905Sborman /* 162638905Sborman * register signal handler for UTMP creation 162738905Sborman */ 162838905Sborman if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) 162938905Sborman fatalperror(net, "telnetd/signal"); 163038905Sborman } 163138905Sborman 163246809Sdab void 163344364Sborman utmp_sig_reset() 163444364Sborman { 163544364Sborman (void) signal(SIGUSR1, func); /* reset handler to default */ 163644364Sborman } 163744364Sborman 163846809Sdab void 163938905Sborman utmp_sig_wait() 164038905Sborman { 164138905Sborman /* 164238905Sborman * Wait for parent to write our utmp entry. 164338905Sborman */ 164438905Sborman sigoff(); 164538905Sborman while (caught == 0) { 164638905Sborman pause(); /* wait until we get a signal (sigon) */ 164738905Sborman sigoff(); /* turn off signals while we check caught */ 164838905Sborman } 164938905Sborman sigon(); /* turn on signals again */ 165038905Sborman } 165138905Sborman 165246809Sdab void 165338905Sborman utmp_sig_notify(pid) 165438905Sborman { 165538905Sborman kill(pid, SIGUSR1); 165638905Sborman } 165746809Sdab 165846809Sdab static int gotsigjob = 0; 165946809Sdab 166046809Sdab /*ARGSUSED*/ 166146809Sdab void 166246809Sdab sigjob(sig) 166346809Sdab int sig; 166446809Sdab { 166546809Sdab register int jid; 166646809Sdab register struct jobtemp *jp; 166746809Sdab 166846809Sdab while ((jid = waitjob(NULL)) != -1) { 166946809Sdab if (jid == 0) { 167046809Sdab return; 167146809Sdab } 167246809Sdab gotsigjob++; 167346809Sdab jobend(jid, NULL, NULL); 167446809Sdab } 167546809Sdab } 167646809Sdab 167746809Sdab /* 167846809Sdab * Clean up the TMPDIR that login created. 167946809Sdab * The first time this is called we pick up the info 168046809Sdab * from the utmp. If the job has already gone away, 168146809Sdab * then we'll clean up and be done. If not, then 168246809Sdab * when this is called the second time it will wait 168346809Sdab * for the signal that the job is done. 168446809Sdab */ 168546809Sdab int 168646809Sdab cleantmp(wtp) 168746809Sdab register struct utmp *wtp; 168846809Sdab { 168946809Sdab struct utmp *utp; 169046809Sdab static int first = 1; 169146809Sdab register int mask, omask, ret; 169246809Sdab extern struct utmp *getutid P((struct utmp *)); 169346809Sdab 169446809Sdab mask = sigmask(WJSIGNAL); 169546809Sdab 169646809Sdab if (first == 0) { 169746809Sdab omask = sigblock(mask); 169846809Sdab while (gotsigjob == 0) 169946809Sdab sigpause(omask); 170046809Sdab return(1); 170146809Sdab } 170246809Sdab first = 0; 170346809Sdab setutent(); /* just to make sure */ 170446809Sdab 170546809Sdab utp = getutid(wtp); 170646809Sdab if (utp == 0) { 170746809Sdab syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); 170846809Sdab return(-1); 170946809Sdab } 171046809Sdab /* 171146809Sdab * Nothing to clean up if the user shell was never started. 171246809Sdab */ 171346809Sdab if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) 171446809Sdab return(1); 171546809Sdab 171646809Sdab /* 171746809Sdab * Block the WJSIGNAL while we are in jobend(). 171846809Sdab */ 171946809Sdab omask = sigblock(mask); 172046809Sdab ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); 172146809Sdab sigsetmask(omask); 172246809Sdab return(ret); 172346809Sdab } 172446809Sdab 172546809Sdab int 172646809Sdab jobend(jid, path, user) 172746809Sdab register int jid; 172846809Sdab register char *path; 172946809Sdab register char *user; 173046809Sdab { 173146809Sdab static int saved_jid = 0; 173246809Sdab static char saved_path[sizeof(wtmp.ut_tpath)+1]; 173346809Sdab static char saved_user[sizeof(wtmp.ut_user)+1]; 173446809Sdab 173546809Sdab if (path) { 173646809Sdab strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); 173746809Sdab strncpy(saved_user, user, sizeof(wtmp.ut_user)); 173846809Sdab saved_path[sizeof(saved_path)] = '\0'; 173946809Sdab saved_user[sizeof(saved_user)] = '\0'; 174046809Sdab } 174146809Sdab if (saved_jid == 0) { 174246809Sdab saved_jid = jid; 174346809Sdab return(0); 174446809Sdab } 174546809Sdab cleantmpdir(jid, saved_path, saved_user); 174646809Sdab return(1); 174746809Sdab } 174846809Sdab 174946809Sdab /* 175046809Sdab * Fork a child process to clean up the TMPDIR 175146809Sdab */ 175246809Sdab cleantmpdir(jid, tpath, user) 175346809Sdab register int jid; 175446809Sdab register char *tpath; 175546809Sdab register char *user; 175646809Sdab { 175746809Sdab switch(fork()) { 175846809Sdab case -1: 175946809Sdab syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n", 176046809Sdab tpath); 176146809Sdab break; 176246809Sdab case 0: 176346809Sdab execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); 176446809Sdab syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", 176546809Sdab tpath, CLEANTMPCMD); 176646809Sdab exit(1); 176746809Sdab default: 176846809Sdab /* 176946809Sdab * Forget about child. We will exit, and 177046809Sdab * /etc/init will pick it up. 177146809Sdab */ 177246809Sdab break; 177346809Sdab } 177446809Sdab } 177538905Sborman #endif /* defined(CRAY) && !defined(NEWINIT) */ 177638905Sborman 177738905Sborman /* 177838905Sborman * rmut() 177938905Sborman * 178038905Sborman * This is the function called by cleanup() to 178138905Sborman * remove the utmp entry for this person. 178238905Sborman */ 178338905Sborman 1784*57212Sdab #ifdef UTMPX 1785*57212Sdab rmut() 1786*57212Sdab { 1787*57212Sdab register f; 1788*57212Sdab int found = 0; 1789*57212Sdab struct utmp *u, *utmp; 1790*57212Sdab int nutmp; 1791*57212Sdab struct stat statbf; 1792*57212Sdab 1793*57212Sdab struct utmpx *utxp, utmpx; 1794*57212Sdab 1795*57212Sdab /* 1796*57212Sdab * This updates the utmpx and utmp entries and make a wtmp/x entry 1797*57212Sdab */ 1798*57212Sdab 1799*57212Sdab SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); 1800*57212Sdab utxp = getutxline(&utmpx); 1801*57212Sdab if (utxp) { 1802*57212Sdab utxp->ut_type = DEAD_PROCESS; 1803*57212Sdab utxp->ut_exit.e_termination = 0; 1804*57212Sdab utxp->ut_exit.e_exit = 0; 1805*57212Sdab (void) time(&utmpx.ut_tv.tv_sec); 1806*57212Sdab utmpx.ut_tv.tv_usec = 0; 1807*57212Sdab modutx(utxp); 1808*57212Sdab } 1809*57212Sdab endutxent(); 1810*57212Sdab } /* end of rmut */ 1811*57212Sdab #endif 1812*57212Sdab 1813*57212Sdab #if !defined(UTMPX) && !defined(CRAY) && BSD <= 43 181446809Sdab void 181538905Sborman rmut() 181638905Sborman { 181738905Sborman register f; 181838905Sborman int found = 0; 181938905Sborman struct utmp *u, *utmp; 182038905Sborman int nutmp; 182138905Sborman struct stat statbf; 182238905Sborman 182338905Sborman f = open(utmpf, O_RDWR); 182438905Sborman if (f >= 0) { 182538905Sborman (void) fstat(f, &statbf); 182638905Sborman utmp = (struct utmp *)malloc((unsigned)statbf.st_size); 182738905Sborman if (!utmp) 182838905Sborman syslog(LOG_ERR, "utmp malloc failed"); 182938905Sborman if (statbf.st_size && utmp) { 183038905Sborman nutmp = read(f, (char *)utmp, (int)statbf.st_size); 183138905Sborman nutmp /= sizeof(struct utmp); 183238905Sborman 183338905Sborman for (u = utmp ; u < &utmp[nutmp] ; u++) { 183438905Sborman if (SCMPN(u->ut_line, line+5) || 183538905Sborman u->ut_name[0]==0) 183638905Sborman continue; 183738905Sborman (void) lseek(f, ((long)u)-((long)utmp), L_SET); 183838905Sborman SCPYN(u->ut_name, ""); 183938905Sborman SCPYN(u->ut_host, ""); 184038905Sborman (void) time(&u->ut_time); 184138905Sborman (void) write(f, (char *)u, sizeof(wtmp)); 184238905Sborman found++; 184338905Sborman } 184438905Sborman } 184538905Sborman (void) close(f); 184638905Sborman } 184738905Sborman if (found) { 184838905Sborman f = open(wtmpf, O_WRONLY|O_APPEND); 184938905Sborman if (f >= 0) { 185038905Sborman SCPYN(wtmp.ut_line, line+5); 185138905Sborman SCPYN(wtmp.ut_name, ""); 185238905Sborman SCPYN(wtmp.ut_host, ""); 185338905Sborman (void) time(&wtmp.ut_time); 185438905Sborman (void) write(f, (char *)&wtmp, sizeof(wtmp)); 185538905Sborman (void) close(f); 185638905Sborman } 185738905Sborman } 185838905Sborman (void) chmod(line, 0666); 185938905Sborman (void) chown(line, 0, 0); 186038905Sborman line[strlen("/dev/")] = 'p'; 186138905Sborman (void) chmod(line, 0666); 186238905Sborman (void) chown(line, 0, 0); 186338905Sborman } /* end of rmut */ 186438905Sborman #endif /* CRAY */ 1865