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*57592Sdab static char sccsid[] = "@(#)sys_term.c 5.18 (Berkeley) 01/18/93"; 1038905Sborman #endif /* not lint */ 1138905Sborman 1238905Sborman #include "telnetd.h" 1338905Sborman #include "pathnames.h" 1438905Sborman 1557212Sdab #if defined(AUTHENTICATION) 1646809Sdab #include <libtelnet/auth.h> 1746809Sdab #endif 1846809Sdab 1938905Sborman #ifdef NEWINIT 2038905Sborman #include <initreq.h> 2138905Sborman #else /* NEWINIT*/ 2257212Sdab # ifdef UTMPX 2357212Sdab # include <utmpx.h> 2457212Sdab # else 2557212Sdab # include <utmp.h> 2657212Sdab # endif /* UTMPX */ 2738905Sborman struct utmp wtmp; 2838905Sborman 2957212Sdab 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> 3757212Sdab # if defined(_SC_CRAY_SECURE_SYS) 3857212Sdab #include <sys/sysv.h> 3957212Sdab #include <sys/secstat.h> 4057212Sdab extern int secflag; 4157212Sdab extern struct sysv sysv; 4257212Sdab # endif /* _SC_CRAY_SECURE_SYS */ 4338905Sborman # endif /* CRAY */ 4438905Sborman #endif /* NEWINIT */ 4538905Sborman 4657212Sdab #ifdef STREAMSPTY 4757212Sdab #include <sac.h> 4857212Sdab #include <sys/stropts.h> 4957212Sdab #endif 5057212Sdab 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*57592Sdab # ifdef STREAMSPTY 12757212Sdab int ttyfd = -1; 128*57592Sdab # endif 12938905Sborman #endif /* USE_TERMIO */ 13038905Sborman 13138905Sborman /* 13238905Sborman * init_termbuf() 13338905Sborman * copy_termbuf(cp) 13438905Sborman * set_termbuf() 13538905Sborman * 13638905Sborman * These three routines are used to get and set the "termbuf" structure 13738905Sborman * to and from the kernel. init_termbuf() gets the current settings. 13838905Sborman * copy_termbuf() hands in a new "termbuf" to write to the kernel, and 13938905Sborman * set_termbuf() writes the structure into the kernel. 14038905Sborman */ 14138905Sborman 14246809Sdab void 14338905Sborman init_termbuf() 14438905Sborman { 14538905Sborman #ifndef USE_TERMIO 14638905Sborman (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg); 14738905Sborman (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc); 14838905Sborman (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc); 14938905Sborman # ifdef TIOCGSTATE 15038905Sborman (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state); 15138905Sborman # endif 15238905Sborman #else 153*57592Sdab # ifdef STREAMSPTY 15457212Sdab (void) tcgetattr(ttyfd, &termbuf); 155*57592Sdab # else 156*57592Sdab (void) tcgetattr(pty, &termbuf); 157*57592Sdab # endif 15838905Sborman #endif 15938905Sborman termbuf2 = termbuf; 16038905Sborman } 16138905Sborman 16238905Sborman #if defined(LINEMODE) && defined(TIOCPKT_IOCTL) 16346809Sdab void 16438905Sborman copy_termbuf(cp, len) 16546809Sdab char *cp; 16646809Sdab int len; 16738905Sborman { 16838905Sborman if (len > sizeof(termbuf)) 16938905Sborman len = sizeof(termbuf); 17038905Sborman bcopy(cp, (char *)&termbuf, len); 17138905Sborman termbuf2 = termbuf; 17238905Sborman } 17338905Sborman #endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ 17438905Sborman 17546809Sdab void 17638905Sborman set_termbuf() 17738905Sborman { 17838905Sborman /* 17938905Sborman * Only make the necessary changes. 18038905Sborman */ 18138905Sborman #ifndef USE_TERMIO 18238905Sborman if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg))) 18345234Sborman (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg); 18438905Sborman if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc))) 18538905Sborman (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc); 18638905Sborman if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc, 18738905Sborman sizeof(termbuf.ltc))) 18838905Sborman (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc); 18938905Sborman if (termbuf.lflags != termbuf2.lflags) 19038905Sborman (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags); 19138905Sborman #else /* USE_TERMIO */ 19238905Sborman if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) 193*57592Sdab # ifdef STREAMSPTY 19457212Sdab (void) tcsetattr(ttyfd, TCSANOW, &termbuf); 195*57592Sdab # else 196*57592Sdab (void) tcsetattr(pty, TCSANOW, &termbuf); 197*57592Sdab # endif 19857212Sdab # if defined(CRAY2) && defined(UNICOS5) 19938905Sborman needtermstat = 1; 20038905Sborman # endif 20138905Sborman #endif /* USE_TERMIO */ 20238905Sborman } 20338905Sborman 20438905Sborman 20538905Sborman /* 20638905Sborman * spcset(func, valp, valpp) 20738905Sborman * 20838905Sborman * This function takes various special characters (func), and 20938905Sborman * sets *valp to the current value of that character, and 21038905Sborman * *valpp to point to where in the "termbuf" structure that 21138905Sborman * value is kept. 21238905Sborman * 21338905Sborman * It returns the SLC_ level of support for this function. 21438905Sborman */ 21538905Sborman 21638905Sborman #ifndef USE_TERMIO 21746809Sdab int 21838905Sborman spcset(func, valp, valpp) 21946809Sdab int func; 22046809Sdab cc_t *valp; 22146809Sdab cc_t **valpp; 22238905Sborman { 22338905Sborman switch(func) { 22438905Sborman case SLC_EOF: 22538905Sborman *valp = termbuf.tc.t_eofc; 22640242Sborman *valpp = (cc_t *)&termbuf.tc.t_eofc; 22738905Sborman return(SLC_VARIABLE); 22838905Sborman case SLC_EC: 22938905Sborman *valp = termbuf.sg.sg_erase; 23040242Sborman *valpp = (cc_t *)&termbuf.sg.sg_erase; 23138905Sborman return(SLC_VARIABLE); 23238905Sborman case SLC_EL: 23338905Sborman *valp = termbuf.sg.sg_kill; 23440242Sborman *valpp = (cc_t *)&termbuf.sg.sg_kill; 23538905Sborman return(SLC_VARIABLE); 23638905Sborman case SLC_IP: 23738905Sborman *valp = termbuf.tc.t_intrc; 23840242Sborman *valpp = (cc_t *)&termbuf.tc.t_intrc; 23938905Sborman return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 24038905Sborman case SLC_ABORT: 24138905Sborman *valp = termbuf.tc.t_quitc; 24240242Sborman *valpp = (cc_t *)&termbuf.tc.t_quitc; 24338905Sborman return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 24438905Sborman case SLC_XON: 24538905Sborman *valp = termbuf.tc.t_startc; 24640242Sborman *valpp = (cc_t *)&termbuf.tc.t_startc; 24738905Sborman return(SLC_VARIABLE); 24838905Sborman case SLC_XOFF: 24938905Sborman *valp = termbuf.tc.t_stopc; 25040242Sborman *valpp = (cc_t *)&termbuf.tc.t_stopc; 25138905Sborman return(SLC_VARIABLE); 25238905Sborman case SLC_AO: 25338905Sborman *valp = termbuf.ltc.t_flushc; 25440242Sborman *valpp = (cc_t *)&termbuf.ltc.t_flushc; 25538905Sborman return(SLC_VARIABLE); 25638905Sborman case SLC_SUSP: 25738905Sborman *valp = termbuf.ltc.t_suspc; 25840242Sborman *valpp = (cc_t *)&termbuf.ltc.t_suspc; 25938905Sborman return(SLC_VARIABLE); 26038905Sborman case SLC_EW: 26138905Sborman *valp = termbuf.ltc.t_werasc; 26240242Sborman *valpp = (cc_t *)&termbuf.ltc.t_werasc; 26338905Sborman return(SLC_VARIABLE); 26438905Sborman case SLC_RP: 26538905Sborman *valp = termbuf.ltc.t_rprntc; 26640242Sborman *valpp = (cc_t *)&termbuf.ltc.t_rprntc; 26738905Sborman return(SLC_VARIABLE); 26838905Sborman case SLC_LNEXT: 26938905Sborman *valp = termbuf.ltc.t_lnextc; 27040242Sborman *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 27138905Sborman return(SLC_VARIABLE); 27240242Sborman case SLC_FORW1: 27340242Sborman *valp = termbuf.tc.t_brkc; 27440242Sborman *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 27540242Sborman return(SLC_VARIABLE); 27638905Sborman case SLC_BRK: 27738905Sborman case SLC_SYNCH: 27838905Sborman case SLC_AYT: 27938905Sborman case SLC_EOR: 28040242Sborman *valp = (cc_t)0; 28140242Sborman *valpp = (cc_t *)0; 28238905Sborman return(SLC_DEFAULT); 28338905Sborman default: 28440242Sborman *valp = (cc_t)0; 28540242Sborman *valpp = (cc_t *)0; 28638905Sborman return(SLC_NOSUPPORT); 28738905Sborman } 28838905Sborman } 28938905Sborman 29038905Sborman #else /* USE_TERMIO */ 29138905Sborman 29246809Sdab int 29338905Sborman spcset(func, valp, valpp) 29446809Sdab int func; 29546809Sdab cc_t *valp; 29646809Sdab cc_t **valpp; 29738905Sborman { 29839503Sborman 29939503Sborman #define setval(a, b) *valp = termbuf.c_cc[a]; \ 30039503Sborman *valpp = &termbuf.c_cc[a]; \ 30139503Sborman return(b); 30240242Sborman #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); 30339503Sborman 30438905Sborman switch(func) { 30538905Sborman case SLC_EOF: 30639503Sborman setval(VEOF, SLC_VARIABLE); 30738905Sborman case SLC_EC: 30839503Sborman setval(VERASE, SLC_VARIABLE); 30938905Sborman case SLC_EL: 31039503Sborman setval(VKILL, SLC_VARIABLE); 31138905Sborman case SLC_IP: 31239503Sborman setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 31338905Sborman case SLC_ABORT: 31439503Sborman setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 31538905Sborman case SLC_XON: 31639503Sborman #ifdef VSTART 31739503Sborman setval(VSTART, SLC_VARIABLE); 31839503Sborman #else 31939503Sborman defval(0x13); 32039503Sborman #endif 32138905Sborman case SLC_XOFF: 32239503Sborman #ifdef VSTOP 32339503Sborman setval(VSTOP, SLC_VARIABLE); 32439503Sborman #else 32539503Sborman defval(0x11); 32639503Sborman #endif 32738905Sborman case SLC_EW: 32839503Sborman #ifdef VWERASE 32939503Sborman setval(VWERASE, SLC_VARIABLE); 33039503Sborman #else 33139503Sborman defval(0); 33239503Sborman #endif 33338905Sborman case SLC_RP: 33439503Sborman #ifdef VREPRINT 33539503Sborman setval(VREPRINT, SLC_VARIABLE); 33639503Sborman #else 33739503Sborman defval(0); 33839503Sborman #endif 33938905Sborman case SLC_LNEXT: 34039503Sborman #ifdef VLNEXT 34139503Sborman setval(VLNEXT, SLC_VARIABLE); 34239503Sborman #else 34339503Sborman defval(0); 34439503Sborman #endif 34539503Sborman case SLC_AO: 34645234Sborman #if !defined(VDISCARD) && defined(VFLUSHO) 34745234Sborman # define VDISCARD VFLUSHO 34845234Sborman #endif 34945234Sborman #ifdef VDISCARD 35045234Sborman setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); 35139503Sborman #else 35239503Sborman defval(0); 35339503Sborman #endif 35439503Sborman case SLC_SUSP: 35539503Sborman #ifdef VSUSP 35639503Sborman setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); 35739503Sborman #else 35839503Sborman defval(0); 35939503Sborman #endif 36040242Sborman #ifdef VEOL 36140242Sborman case SLC_FORW1: 36240242Sborman setval(VEOL, SLC_VARIABLE); 36340242Sborman #endif 36440242Sborman #ifdef VEOL2 36540242Sborman case SLC_FORW2: 36640242Sborman setval(VEOL2, SLC_VARIABLE); 36740242Sborman #endif 36845234Sborman case SLC_AYT: 36945234Sborman #ifdef VSTATUS 37045234Sborman setval(VSTATUS, SLC_VARIABLE); 37145234Sborman #else 37245234Sborman defval(0); 37345234Sborman #endif 37439503Sborman 37538905Sborman case SLC_BRK: 37638905Sborman case SLC_SYNCH: 37738905Sborman case SLC_EOR: 37839503Sborman defval(0); 37939503Sborman 38038905Sborman default: 38138905Sborman *valp = 0; 38238905Sborman *valpp = 0; 38338905Sborman return(SLC_NOSUPPORT); 38438905Sborman } 38538905Sborman } 38638905Sborman #endif /* USE_TERMIO */ 38738905Sborman 38840242Sborman #ifdef CRAY 38938905Sborman /* 39040242Sborman * getnpty() 39140242Sborman * 39240242Sborman * Return the number of pty's configured into the system. 39340242Sborman */ 39446809Sdab int 39540242Sborman getnpty() 39640242Sborman { 39740242Sborman #ifdef _SC_CRAY_NPTY 39846809Sdab int numptys; 39946809Sdab 40046809Sdab if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) 40146809Sdab return numptys; 40246809Sdab else 40340242Sborman #endif /* _SC_CRAY_NPTY */ 40446809Sdab return 128; 40540242Sborman } 40640242Sborman #endif /* CRAY */ 40740242Sborman 40845234Sborman #ifndef convex 40940242Sborman /* 41038905Sborman * getpty() 41138905Sborman * 41238905Sborman * Allocate a pty. As a side effect, the external character 41338905Sborman * array "line" contains the name of the slave side. 41438905Sborman * 41538905Sborman * Returns the file descriptor of the opened pty. 41638905Sborman */ 41745234Sborman #ifndef __GNUC__ 41838905Sborman char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 41945234Sborman #else 42045234Sborman static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 42145234Sborman char *line = Xline; 42245234Sborman #endif 42345234Sborman #ifdef CRAY 42445234Sborman char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 42545234Sborman #endif /* CRAY */ 42638905Sborman 42746809Sdab int 42838905Sborman getpty() 42938905Sborman { 43038905Sborman register int p; 43157212Sdab #ifdef STREAMSPTY 43257212Sdab int t; 43357212Sdab char *ptsname(); 43457212Sdab 43557212Sdab p = open("/dev/ptmx", 2); 43657212Sdab if (p > 0) { 43757212Sdab grantpt(p); 43857212Sdab unlockpt(p); 43957212Sdab strcpy(line, ptsname(p)); 44057212Sdab return(p); 44157212Sdab } 44257212Sdab 44357212Sdab #else /* ! STREAMSPTY */ 44438905Sborman #ifndef CRAY 44557212Sdab register char *cp, *p1, *p2; 44638905Sborman register int i; 44757212Sdab #if defined(sun) && defined(TIOCGPGRP) 44857212Sdab int dummy; 44957212Sdab #endif 45038905Sborman 45138905Sborman (void) sprintf(line, "/dev/ptyXX"); 45238905Sborman p1 = &line[8]; 45338905Sborman p2 = &line[9]; 45438905Sborman 45557212Sdab for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) { 45638905Sborman struct stat stb; 45738905Sborman 45857212Sdab *p1 = *cp; 45938905Sborman *p2 = '0'; 46057212Sdab /* 46157212Sdab * This stat() check is just to keep us from 46257212Sdab * looping through all 256 combinations if there 46357212Sdab * aren't that many ptys available. 46457212Sdab */ 46538905Sborman if (stat(line, &stb) < 0) 46638905Sborman break; 46738905Sborman for (i = 0; i < 16; i++) { 46838905Sborman *p2 = "0123456789abcdef"[i]; 46938905Sborman p = open(line, 2); 47038905Sborman if (p > 0) { 47138905Sborman line[5] = 't'; 47257212Sdab chown(line, 0, 0); 47357212Sdab chmod(line, 0600); 47457212Sdab #if defined(sun) && defined(TIOCGPGRP) 47557212Sdab if (ioctl(p, TIOCGPGRP, &dummy) == 0 47657212Sdab || errno != EIO) { 47757212Sdab chmod(line, 0666); 47857212Sdab close(p); 47957212Sdab line[5] = 'p'; 48057212Sdab } else 48157212Sdab #endif /* defined(sun) && defined(TIOCGPGRP) */ 48257212Sdab return(p); 48338905Sborman } 48438905Sborman } 48538905Sborman } 48638905Sborman #else /* CRAY */ 48738905Sborman register int npty; 48838905Sborman extern lowpty, highpty; 48945234Sborman struct stat sb; 49038905Sborman 49138905Sborman for (npty = lowpty; npty <= highpty; npty++) { 49245234Sborman (void) sprintf(myline, "/dev/pty/%03d", npty); 49345234Sborman p = open(myline, 2); 49438905Sborman if (p < 0) 49538905Sborman continue; 49638905Sborman (void) sprintf(line, "/dev/ttyp%03d", npty); 49745234Sborman /* 49845234Sborman * Here are some shenanigans to make sure that there 49945234Sborman * are no listeners lurking on the line. 50045234Sborman */ 50145234Sborman if(stat(line, &sb) < 0) { 50245234Sborman (void) close(p); 50345234Sborman continue; 50445234Sborman } 50545234Sborman if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { 50645234Sborman chown(line, 0, 0); 50745234Sborman chmod(line, 0600); 50845234Sborman (void)close(p); 50945234Sborman p = open(myline, 2); 51045234Sborman if (p < 0) 51145234Sborman continue; 51245234Sborman } 51345234Sborman /* 51445234Sborman * Now it should be safe...check for accessability. 51545234Sborman */ 51638905Sborman if (access(line, 6) == 0) 51738905Sborman return(p); 51838905Sborman else { 51938905Sborman /* no tty side to pty so skip it */ 52038905Sborman (void) close(p); 52138905Sborman } 52238905Sborman } 52338905Sborman #endif /* CRAY */ 52457212Sdab #endif /* STREAMSPTY */ 52538905Sborman return(-1); 52638905Sborman } 52745234Sborman #endif /* convex */ 52838905Sborman 52938905Sborman #ifdef LINEMODE 53038905Sborman /* 53138905Sborman * tty_flowmode() Find out if flow control is enabled or disabled. 53238905Sborman * tty_linemode() Find out if linemode (external processing) is enabled. 53338905Sborman * tty_setlinemod(on) Turn on/off linemode. 53438905Sborman * tty_isecho() Find out if echoing is turned on. 53538905Sborman * tty_setecho(on) Enable/disable character echoing. 53638905Sborman * tty_israw() Find out if terminal is in RAW mode. 53738905Sborman * tty_binaryin(on) Turn on/off BINARY on input. 53838905Sborman * tty_binaryout(on) Turn on/off BINARY on output. 53938905Sborman * tty_isediting() Find out if line editing is enabled. 54038905Sborman * tty_istrapsig() Find out if signal trapping is enabled. 54138905Sborman * tty_setedit(on) Turn on/off line editing. 54238905Sborman * tty_setsig(on) Turn on/off signal trapping. 54344364Sborman * tty_issofttab() Find out if tab expansion is enabled. 54444364Sborman * tty_setsofttab(on) Turn on/off soft tab expansion. 54544364Sborman * tty_islitecho() Find out if typed control chars are echoed literally 54644364Sborman * tty_setlitecho() Turn on/off literal echo of control chars 54738905Sborman * tty_tspeed(val) Set transmit speed to val. 54838905Sborman * tty_rspeed(val) Set receive speed to val. 54938905Sborman */ 55038905Sborman 55146809Sdab int 55238905Sborman tty_flowmode() 55338905Sborman { 55438905Sborman #ifndef USE_TERMIO 55546809Sdab return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0); 55638905Sborman #else 55738905Sborman return(termbuf.c_iflag & IXON ? 1 : 0); 55838905Sborman #endif 55938905Sborman } 56038905Sborman 56157212Sdab int 56257212Sdab tty_restartany() 56357212Sdab { 56457212Sdab #ifndef USE_TERMIO 56557212Sdab # ifdef DECCTQ 56657212Sdab return((termbuf.lflags & DECCTQ) ? 0 : 1); 56757212Sdab # else 56857212Sdab return(-1); 56957212Sdab # endif 57057212Sdab #else 57157212Sdab return(termbuf.c_iflag & IXANY ? 1 : 0); 57257212Sdab #endif 57357212Sdab } 57457212Sdab 57545234Sborman #ifdef convex 57645234Sborman static int linestate; 57745234Sborman #endif 57845234Sborman 57946809Sdab int 58038905Sborman tty_linemode() 58138905Sborman { 58245234Sborman #ifndef convex 58338905Sborman #ifndef USE_TERMIO 58438905Sborman return(termbuf.state & TS_EXTPROC); 58538905Sborman #else 58638905Sborman return(termbuf.c_lflag & EXTPROC); 58738905Sborman #endif 58845234Sborman #else 58945234Sborman return(linestate); 59045234Sborman #endif 59138905Sborman } 59238905Sborman 59346809Sdab void 59438905Sborman tty_setlinemode(on) 59546809Sdab int on; 59638905Sborman { 59738905Sborman #ifdef TIOCEXT 59845234Sborman # ifndef convex 59945234Sborman set_termbuf(); 60045234Sborman # else 60145234Sborman linestate = on; 60245234Sborman # endif 60338905Sborman (void) ioctl(pty, TIOCEXT, (char *)&on); 60445234Sborman # ifndef convex 60545234Sborman init_termbuf(); 60645234Sborman # endif 60738905Sborman #else /* !TIOCEXT */ 60845234Sborman # ifdef EXTPROC 60938905Sborman if (on) 61038905Sborman termbuf.c_lflag |= EXTPROC; 61138905Sborman else 61238905Sborman termbuf.c_lflag &= ~EXTPROC; 61345234Sborman # endif 61438905Sborman #endif /* TIOCEXT */ 61538905Sborman } 61638905Sborman 61746809Sdab int 61838905Sborman tty_isecho() 61938905Sborman { 62038905Sborman #ifndef USE_TERMIO 62138905Sborman return (termbuf.sg.sg_flags & ECHO); 62238905Sborman #else 62338905Sborman return (termbuf.c_lflag & ECHO); 62438905Sborman #endif 62538905Sborman } 62638905Sborman #endif /* LINEMODE */ 62738905Sborman 62846809Sdab void 62938905Sborman tty_setecho(on) 63046809Sdab int on; 63138905Sborman { 63238905Sborman #ifndef USE_TERMIO 63338905Sborman if (on) 63438905Sborman termbuf.sg.sg_flags |= ECHO|CRMOD; 63538905Sborman else 63638905Sborman termbuf.sg.sg_flags &= ~(ECHO|CRMOD); 63738905Sborman #else 63838905Sborman if (on) 63938905Sborman termbuf.c_lflag |= ECHO; 64038905Sborman else 64138905Sborman termbuf.c_lflag &= ~ECHO; 64238905Sborman #endif 64338905Sborman } 64438905Sborman 64538905Sborman #if defined(LINEMODE) && defined(KLUDGELINEMODE) 64646809Sdab int 64738905Sborman tty_israw() 64838905Sborman { 64938905Sborman #ifndef USE_TERMIO 65038905Sborman return(termbuf.sg.sg_flags & RAW); 65138905Sborman #else 65238905Sborman return(!(termbuf.c_lflag & ICANON)); 65338905Sborman #endif 65438905Sborman } 65538905Sborman #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 65638905Sborman 65746809Sdab void 65838905Sborman tty_binaryin(on) 65946809Sdab int on; 66038905Sborman { 66138905Sborman #ifndef USE_TERMIO 66238905Sborman if (on) 66338905Sborman termbuf.lflags |= LPASS8; 66438905Sborman else 66538905Sborman termbuf.lflags &= ~LPASS8; 66638905Sborman #else 66738905Sborman if (on) { 66846809Sdab termbuf.c_iflag &= ~ISTRIP; 66938905Sborman } else { 67046809Sdab termbuf.c_iflag |= ISTRIP; 67138905Sborman } 67238905Sborman #endif 67338905Sborman } 67438905Sborman 67546809Sdab void 67638905Sborman tty_binaryout(on) 67746809Sdab int on; 67838905Sborman { 67938905Sborman #ifndef USE_TERMIO 68038905Sborman if (on) 68138905Sborman termbuf.lflags |= LLITOUT; 68238905Sborman else 68338905Sborman termbuf.lflags &= ~LLITOUT; 68438905Sborman #else 68538905Sborman if (on) { 68638905Sborman termbuf.c_cflag &= ~(CSIZE|PARENB); 68738905Sborman termbuf.c_cflag |= CS8; 68838905Sborman termbuf.c_oflag &= ~OPOST; 68938905Sborman } else { 69038905Sborman termbuf.c_cflag &= ~CSIZE; 69138905Sborman termbuf.c_cflag |= CS7|PARENB; 69238905Sborman termbuf.c_oflag |= OPOST; 69338905Sborman } 69438905Sborman #endif 69538905Sborman } 69638905Sborman 69746809Sdab int 69838905Sborman tty_isbinaryin() 69938905Sborman { 70038905Sborman #ifndef USE_TERMIO 70138905Sborman return(termbuf.lflags & LPASS8); 70238905Sborman #else 70339503Sborman return(!(termbuf.c_iflag & ISTRIP)); 70438905Sborman #endif 70538905Sborman } 70638905Sborman 70746809Sdab int 70838905Sborman tty_isbinaryout() 70938905Sborman { 71038905Sborman #ifndef USE_TERMIO 71138905Sborman return(termbuf.lflags & LLITOUT); 71238905Sborman #else 71339503Sborman return(!(termbuf.c_oflag&OPOST)); 71438905Sborman #endif 71538905Sborman } 71638905Sborman 71738905Sborman #ifdef LINEMODE 71846809Sdab int 71938905Sborman tty_isediting() 72038905Sborman { 72138905Sborman #ifndef USE_TERMIO 72238905Sborman return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); 72338905Sborman #else 72438905Sborman return(termbuf.c_lflag & ICANON); 72538905Sborman #endif 72638905Sborman } 72738905Sborman 72846809Sdab int 72938905Sborman tty_istrapsig() 73038905Sborman { 73138905Sborman #ifndef USE_TERMIO 73238905Sborman return(!(termbuf.sg.sg_flags&RAW)); 73338905Sborman #else 73438905Sborman return(termbuf.c_lflag & ISIG); 73538905Sborman #endif 73638905Sborman } 73738905Sborman 73846809Sdab void 73938905Sborman tty_setedit(on) 74046809Sdab int on; 74138905Sborman { 74238905Sborman #ifndef USE_TERMIO 74338905Sborman if (on) 74438905Sborman termbuf.sg.sg_flags &= ~CBREAK; 74538905Sborman else 74638905Sborman termbuf.sg.sg_flags |= CBREAK; 74738905Sborman #else 74838905Sborman if (on) 74938905Sborman termbuf.c_lflag |= ICANON; 75038905Sborman else 75138905Sborman termbuf.c_lflag &= ~ICANON; 75238905Sborman #endif 75338905Sborman } 75438905Sborman 75546809Sdab void 75638905Sborman tty_setsig(on) 75746809Sdab int on; 75838905Sborman { 75938905Sborman #ifndef USE_TERMIO 76038905Sborman if (on) 76138905Sborman ; 76238905Sborman #else 76338905Sborman if (on) 76438905Sborman termbuf.c_lflag |= ISIG; 76538905Sborman else 76638905Sborman termbuf.c_lflag &= ~ISIG; 76738905Sborman #endif 76838905Sborman } 76938905Sborman #endif /* LINEMODE */ 77038905Sborman 77146809Sdab int 77244364Sborman tty_issofttab() 77344364Sborman { 77444364Sborman #ifndef USE_TERMIO 77544364Sborman return (termbuf.sg.sg_flags & XTABS); 77644364Sborman #else 77744364Sborman # ifdef OXTABS 77844364Sborman return (termbuf.c_oflag & OXTABS); 77944364Sborman # endif 78044364Sborman # ifdef TABDLY 78144364Sborman return ((termbuf.c_oflag & TABDLY) == TAB3); 78244364Sborman # endif 78344364Sborman #endif 78444364Sborman } 78544364Sborman 78646809Sdab void 78744364Sborman tty_setsofttab(on) 78846809Sdab int on; 78944364Sborman { 79044364Sborman #ifndef USE_TERMIO 79144364Sborman if (on) 79244364Sborman termbuf.sg.sg_flags |= XTABS; 79344364Sborman else 79444364Sborman termbuf.sg.sg_flags &= ~XTABS; 79544364Sborman #else 79644364Sborman if (on) { 79744364Sborman # ifdef OXTABS 79844364Sborman termbuf.c_oflag |= OXTABS; 79944364Sborman # endif 80044364Sborman # ifdef TABDLY 80144364Sborman termbuf.c_oflag &= ~TABDLY; 80244364Sborman termbuf.c_oflag |= TAB3; 80344364Sborman # endif 80444364Sborman } else { 80544364Sborman # ifdef OXTABS 80644364Sborman termbuf.c_oflag &= ~OXTABS; 80744364Sborman # endif 80844364Sborman # ifdef TABDLY 80944364Sborman termbuf.c_oflag &= ~TABDLY; 81044364Sborman termbuf.c_oflag |= TAB0; 81144364Sborman # endif 81244364Sborman } 81344364Sborman #endif 81444364Sborman } 81544364Sborman 81646809Sdab int 81744364Sborman tty_islitecho() 81844364Sborman { 81944364Sborman #ifndef USE_TERMIO 82046809Sdab return (!(termbuf.lflags & LCTLECH)); 82144364Sborman #else 82244364Sborman # ifdef ECHOCTL 82344364Sborman return (!(termbuf.c_lflag & ECHOCTL)); 82444364Sborman # endif 82544364Sborman # ifdef TCTLECH 82644364Sborman return (!(termbuf.c_lflag & TCTLECH)); 82744364Sborman # endif 82844364Sborman # if !defined(ECHOCTL) && !defined(TCTLECH) 82944364Sborman return (0); /* assumes ctl chars are echoed '^x' */ 83044364Sborman # endif 83144364Sborman #endif 83244364Sborman } 83344364Sborman 83446809Sdab void 83544364Sborman tty_setlitecho(on) 83646809Sdab int on; 83744364Sborman { 83844364Sborman #ifndef USE_TERMIO 83944364Sborman if (on) 84046809Sdab termbuf.lflags &= ~LCTLECH; 84144364Sborman else 84246809Sdab termbuf.lflags |= LCTLECH; 84344364Sborman #else 84444364Sborman # ifdef ECHOCTL 84544364Sborman if (on) 84644364Sborman termbuf.c_lflag &= ~ECHOCTL; 84744364Sborman else 84844364Sborman termbuf.c_lflag |= ECHOCTL; 84944364Sborman # endif 85044364Sborman # ifdef TCTLECH 85144364Sborman if (on) 85244364Sborman termbuf.c_lflag &= ~TCTLECH; 85344364Sborman else 85444364Sborman termbuf.c_lflag |= TCTLECH; 85544364Sborman # endif 85644364Sborman #endif 85744364Sborman } 85844364Sborman 85946809Sdab int 86046809Sdab tty_iscrnl() 86146809Sdab { 86246809Sdab #ifndef USE_TERMIO 86346809Sdab return (termbuf.sg.sg_flags & CRMOD); 86446809Sdab #else 86546809Sdab return (termbuf.c_iflag & ICRNL); 86646809Sdab #endif 86746809Sdab } 86846809Sdab 86938905Sborman /* 87038905Sborman * A table of available terminal speeds 87138905Sborman */ 87238905Sborman struct termspeeds { 87338905Sborman int speed; 87438905Sborman int value; 87538905Sborman } termspeeds[] = { 87638905Sborman { 0, B0 }, { 50, B50 }, { 75, B75 }, 87738905Sborman { 110, B110 }, { 134, B134 }, { 150, B150 }, 87838905Sborman { 200, B200 }, { 300, B300 }, { 600, B600 }, 87938905Sborman { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 88038905Sborman { 4800, B4800 }, { 9600, B9600 }, { 19200, B9600 }, 88138905Sborman { 38400, B9600 }, { -1, B9600 } 88238905Sborman }; 88338905Sborman 88446809Sdab void 88538905Sborman tty_tspeed(val) 88646809Sdab int val; 88738905Sborman { 88838905Sborman register struct termspeeds *tp; 88938905Sborman 89038905Sborman for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 89138905Sborman ; 89245234Sborman cfsetospeed(&termbuf, tp->value); 89338905Sborman } 89438905Sborman 89546809Sdab void 89638905Sborman tty_rspeed(val) 89746809Sdab int val; 89838905Sborman { 89938905Sborman register struct termspeeds *tp; 90038905Sborman 90138905Sborman for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 90238905Sborman ; 90345234Sborman cfsetispeed(&termbuf, tp->value); 90438905Sborman } 90538905Sborman 90640242Sborman #if defined(CRAY2) && defined(UNICOS5) 90746809Sdab int 90838905Sborman tty_isnewmap() 90938905Sborman { 91038905Sborman return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) && 91138905Sborman !(termbuf.c_oflag & ONLRET)); 91238905Sborman } 91338905Sborman #endif 91438905Sborman 91538905Sborman #ifdef CRAY 91638905Sborman # ifndef NEWINIT 91738905Sborman extern struct utmp wtmp; 91838905Sborman extern char wtmpf[]; 91938905Sborman # else /* NEWINIT */ 92038905Sborman int gotalarm; 92146809Sdab 92246809Sdab /* ARGSUSED */ 92346809Sdab void 92440242Sborman nologinproc(sig) 92546809Sdab int sig; 92638905Sborman { 92738905Sborman gotalarm++; 92838905Sborman } 92938905Sborman # endif /* NEWINIT */ 93038905Sborman #endif /* CRAY */ 93138905Sborman 93246809Sdab #ifndef NEWINIT 93346809Sdab # ifdef CRAY 93446809Sdab extern void utmp_sig_init P((void)); 93546809Sdab extern void utmp_sig_reset P((void)); 93646809Sdab extern void utmp_sig_wait P((void)); 93746809Sdab extern void utmp_sig_notify P((int)); 93846809Sdab # endif 93946809Sdab #endif 94046809Sdab 94138905Sborman /* 94238905Sborman * getptyslave() 94338905Sborman * 94438905Sborman * Open the slave side of the pty, and do any initialization 94538905Sborman * that is necessary. The return value is a file descriptor 94638905Sborman * for the slave side. 94738905Sborman */ 94846809Sdab int 94938905Sborman getptyslave() 95038905Sborman { 95138905Sborman register int t = -1; 95238905Sborman 95345234Sborman #if !defined(CRAY) || !defined(NEWINIT) 95445234Sborman # ifdef LINEMODE 95546809Sdab int waslm; 95646809Sdab # endif 95746809Sdab # ifdef TIOCGWINSZ 95846809Sdab struct winsize ws; 95946809Sdab extern int def_row, def_col; 96046809Sdab # endif 96146809Sdab extern int def_tspeed, def_rspeed; 96238905Sborman /* 96345234Sborman * Opening the slave side may cause initilization of the 96446809Sdab * kernel tty structure. We need remember the state of 96546809Sdab * if linemode was turned on 96646809Sdab * terminal window size 96746809Sdab * terminal speed 96846809Sdab * so that we can re-set them if we need to. 96938905Sborman */ 97046809Sdab # ifdef LINEMODE 97146809Sdab waslm = tty_linemode(); 97245234Sborman # endif 97345234Sborman 97445234Sborman 97545234Sborman /* 97645234Sborman * Make sure that we don't have a controlling tty, and 97745234Sborman * that we are the session (process group) leader. 97845234Sborman */ 97945234Sborman # ifdef TIOCNOTTY 98038905Sborman t = open(_PATH_TTY, O_RDWR); 98138905Sborman if (t >= 0) { 98238905Sborman (void) ioctl(t, TIOCNOTTY, (char *)0); 98338905Sborman (void) close(t); 98438905Sborman } 98545234Sborman # endif 98638905Sborman 98745234Sborman 98845234Sborman # ifdef CRAY 98945234Sborman /* 99045234Sborman * Wait for our parent to get the utmp stuff to get done. 99145234Sborman */ 99245234Sborman utmp_sig_wait(); 99345234Sborman # endif 99445234Sborman 99545234Sborman t = cleanopen(line); 99638905Sborman if (t < 0) 99738905Sborman fatalperror(net, line); 99838905Sborman 999*57592Sdab #ifdef STREAMSPTY 100057212Sdab #ifdef USE_TERMIO 100157212Sdab ttyfd = t; 100257212Sdab #endif 100357212Sdab if (ioctl(t, I_PUSH, "ptem") < 0) 100457212Sdab fatal(net, "I_PUSH ptem"); 100557212Sdab if (ioctl(t, I_PUSH, "ldterm") < 0) 100657212Sdab fatal(net, "I_PUSH ldterm"); 100757212Sdab if (ioctl(t, I_PUSH, "ttcompat") < 0) 100857212Sdab fatal(net, "I_PUSH ttcompat"); 100957212Sdab if (ioctl(pty, I_PUSH, "pckt") < 0) 101057212Sdab fatal(net, "I_PUSH pckt"); 101157212Sdab #endif 101257212Sdab 101345234Sborman /* 101445234Sborman * set up the tty modes as we like them to be. 101545234Sborman */ 101638905Sborman init_termbuf(); 101746809Sdab # ifdef TIOCGWINSZ 101846809Sdab if (def_row || def_col) { 101946809Sdab bzero((char *)&ws, sizeof(ws)); 102046809Sdab ws.ws_col = def_col; 102146809Sdab ws.ws_row = def_row; 102246809Sdab (void)ioctl(t, TIOCSWINSZ, (char *)&ws); 102346809Sdab } 102446809Sdab # endif 102545234Sborman 102645234Sborman /* 102745234Sborman * Settings for sgtty based systems 102845234Sborman */ 102945234Sborman # ifndef USE_TERMIO 103040242Sborman termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; 103145234Sborman # endif /* USE_TERMIO */ 103245234Sborman 103345234Sborman /* 103445234Sborman * Settings for UNICOS 103545234Sborman */ 103645234Sborman # ifdef CRAY 103745234Sborman termbuf.c_oflag = OPOST|ONLCR|TAB3; 103845234Sborman termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; 103945234Sborman termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; 104045234Sborman termbuf.c_cflag = EXTB|HUPCL|CS8; 104145234Sborman # endif 104245234Sborman 104345234Sborman /* 104445234Sborman * Settings for all other termios/termio based 104545234Sborman * systems, other than 4.4BSD. In 4.4BSD the 104645234Sborman * kernel does the initial terminal setup. 104745234Sborman */ 104845234Sborman # if defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) 104945234Sborman # ifndef OXTABS 105045234Sborman # define OXTABS 0 105145234Sborman # endif 105238905Sborman termbuf.c_lflag |= ECHO; 105338905Sborman termbuf.c_oflag |= ONLCR|OXTABS; 105438905Sborman termbuf.c_iflag |= ICRNL; 105538905Sborman termbuf.c_iflag &= ~IXOFF; 105645234Sborman # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */ 105746996Sdab tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); 105846996Sdab tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); 105946809Sdab # ifdef LINEMODE 106046809Sdab if (waslm) 106146809Sdab tty_setlinemode(1); 106246809Sdab # endif /* LINEMODE */ 106345234Sborman 106445234Sborman /* 106545234Sborman * Set the tty modes, and make this our controlling tty. 106645234Sborman */ 106745234Sborman set_termbuf(); 106845234Sborman if (login_tty(t) == -1) 106945234Sborman fatalperror(net, "login_tty"); 107045234Sborman #endif /* !defined(CRAY) || !defined(NEWINIT) */ 107145234Sborman if (net > 2) 107245234Sborman (void) close(net); 107345234Sborman if (pty > 2) 107445234Sborman (void) close(pty); 107545234Sborman } 107645234Sborman 107745234Sborman #if !defined(CRAY) || !defined(NEWINIT) 107845234Sborman #ifndef O_NOCTTY 107945234Sborman #define O_NOCTTY 0 108038905Sborman #endif 108145234Sborman /* 108245234Sborman * Open the specified slave side of the pty, 108345234Sborman * making sure that we have a clean tty. 108445234Sborman */ 108546809Sdab int 108645234Sborman cleanopen(line) 108746809Sdab char *line; 108845234Sborman { 108945234Sborman register int t; 109057212Sdab #if defined(_SC_CRAY_SECURE_SYS) 109157212Sdab struct secstat secbuf; 109257212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 109345234Sborman 109457212Sdab #ifndef STREAMSPTY 109545234Sborman /* 109645234Sborman * Make sure that other people can't open the 109745234Sborman * slave side of the connection. 109845234Sborman */ 109938905Sborman (void) chown(line, 0, 0); 110038905Sborman (void) chmod(line, 0600); 110157212Sdab #endif 110245234Sborman 110345234Sborman # if !defined(CRAY) && (BSD > 43) 110445234Sborman (void) revoke(line); 110545234Sborman # endif 110657212Sdab #if defined(_SC_CRAY_SECURE_SYS) 110757212Sdab if (secflag) { 110857212Sdab if (secstat(line, &secbuf) < 0) 110957212Sdab return(-1); 111057212Sdab if (setulvl(secbuf.st_slevel) < 0) 111157212Sdab return(-1); 111257212Sdab if (setucmp(secbuf.st_compart) < 0) 111357212Sdab return(-1); 111457212Sdab } 111557212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 111657212Sdab 111745234Sborman t = open(line, O_RDWR|O_NOCTTY); 111857212Sdab 111957212Sdab #if defined(_SC_CRAY_SECURE_SYS) 112057212Sdab if (secflag) { 112157212Sdab if (setulvl(sysv.sy_minlvl) < 0) 112257212Sdab return(-1); 112357212Sdab if (setucmp(0) < 0) 112457212Sdab return(-1); 112557212Sdab } 112657212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 112757212Sdab 112845234Sborman if (t < 0) 112945234Sborman return(-1); 113045234Sborman 113145234Sborman /* 113245234Sborman * Hangup anybody else using this ttyp, then reopen it for 113345234Sborman * ourselves. 113445234Sborman */ 113557212Sdab # if !defined(CRAY) && (BSD <= 43) && !defined(STREAMSPTY) 113645234Sborman (void) signal(SIGHUP, SIG_IGN); 113745234Sborman vhangup(); 113845234Sborman (void) signal(SIGHUP, SIG_DFL); 113945234Sborman t = open(line, O_RDWR|O_NOCTTY); 114045234Sborman if (t < 0) 114145234Sborman return(-1); 114245234Sborman # endif 114345234Sborman # if defined(CRAY) && defined(TCVHUP) 114445234Sborman { 114545234Sborman register int i; 114645234Sborman (void) signal(SIGHUP, SIG_IGN); 114745234Sborman (void) ioctl(t, TCVHUP, (char *)0); 114845234Sborman (void) signal(SIGHUP, SIG_DFL); 114945234Sborman setpgrp(); 115057212Sdab 115157212Sdab #if defined(_SC_CRAY_SECURE_SYS) 115257212Sdab if (secflag) { 115357212Sdab if (secstat(line, &secbuf) < 0) 115457212Sdab return(-1); 115557212Sdab if (setulvl(secbuf.st_slevel) < 0) 115657212Sdab return(-1); 115757212Sdab if (setucmp(secbuf.st_compart) < 0) 115857212Sdab return(-1); 115957212Sdab } 116057212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 116157212Sdab 116245234Sborman i = open(line, O_RDWR); 116357212Sdab 116457212Sdab #if defined(_SC_CRAY_SECURE_SYS) 116557212Sdab if (secflag) { 116657212Sdab if (setulvl(sysv.sy_minlvl) < 0) 116757212Sdab return(-1); 116857212Sdab if (setucmp(0) < 0) 116957212Sdab return(-1); 117057212Sdab } 117157212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 117257212Sdab 117345234Sborman if (i < 0) 117446809Sdab return(-1); 117545234Sborman (void) close(t); 117645234Sborman t = i; 117745234Sborman } 117845234Sborman # endif /* defined(CRAY) && defined(TCVHUP) */ 117938905Sborman return(t); 118038905Sborman } 118145234Sborman #endif /* !defined(CRAY) || !defined(NEWINIT) */ 118238905Sborman 118345234Sborman #if BSD <= 43 118446809Sdab int 118545234Sborman login_tty(t) 118646809Sdab int t; 118745234Sborman { 118845234Sborman if (setsid() < 0) 118945234Sborman fatalperror(net, "setsid()"); 119045234Sborman # ifdef TIOCSCTTY 119145234Sborman if (ioctl(t, TIOCSCTTY, (char *)0) < 0) 119245234Sborman fatalperror(net, "ioctl(sctty)"); 119357212Sdab # if defined(CRAY) 119447613Sdab /* 119547613Sdab * Close the hard fd to /dev/ttypXXX, and re-open through 119647613Sdab * the indirect /dev/tty interface. 119747613Sdab */ 119847613Sdab close(t); 119947613Sdab if ((t = open("/dev/tty", O_RDWR)) < 0) 120047613Sdab fatalperror(net, "open(/dev/tty)"); 120147613Sdab # endif 120245234Sborman # else 120345234Sborman close(open(line, O_RDWR)); 120445234Sborman # endif 120547613Sdab if (t != 0) 120647613Sdab (void) dup2(t, 0); 120747613Sdab if (t != 1) 120847613Sdab (void) dup2(t, 1); 120947613Sdab if (t != 2) 121047613Sdab (void) dup2(t, 2); 121147613Sdab if (t > 2) 121247613Sdab close(t); 121346809Sdab return(0); 121445234Sborman } 121545234Sborman #endif /* BSD <= 43 */ 121645234Sborman 121738905Sborman #ifdef NEWINIT 121838905Sborman char *gen_id = "fe"; 121938905Sborman #endif 122038905Sborman 122138905Sborman /* 122245234Sborman * startslave(host) 122338905Sborman * 122445234Sborman * Given a hostname, do whatever 122538905Sborman * is necessary to startup the login process on the slave side of the pty. 122638905Sborman */ 122738905Sborman 122838905Sborman /* ARGSUSED */ 122946809Sdab void 123046809Sdab startslave(host, autologin, autoname) 123146809Sdab char *host; 123246809Sdab int autologin; 123346809Sdab char *autoname; 123438905Sborman { 123538905Sborman register int i; 123638905Sborman long time(); 123746809Sdab char name[256]; 123846809Sdab #ifdef NEWINIT 123946809Sdab extern char *ptyip; 124046809Sdab struct init_request request; 124146809Sdab void nologinproc(); 124246809Sdab register int n; 124346809Sdab #endif /* NEWINIT */ 124438905Sborman 124557212Sdab #if defined(AUTHENTICATION) 124646809Sdab if (!autoname || !autoname[0]) 124746809Sdab autologin = 0; 124846809Sdab 124946809Sdab if (autologin < auth_level) { 125046809Sdab fatal(net, "Authorization failed"); 125146809Sdab exit(1); 125246809Sdab } 125346809Sdab #endif 125446809Sdab 125538905Sborman #ifndef NEWINIT 125638905Sborman # ifdef CRAY 125738905Sborman utmp_sig_init(); 125838905Sborman # endif /* CRAY */ 125938905Sborman 126038905Sborman if ((i = fork()) < 0) 126138905Sborman fatalperror(net, "fork"); 126238905Sborman if (i) { 126338905Sborman # ifdef CRAY 126438905Sborman /* 126538905Sborman * Cray parent will create utmp entry for child and send 126638905Sborman * signal to child to tell when done. Child waits for signal 126738905Sborman * before doing anything important. 126838905Sborman */ 126938905Sborman register int pid = i; 127046809Sdab void sigjob P((int)); 127138905Sborman 127238905Sborman setpgrp(); 127344364Sborman utmp_sig_reset(); /* reset handler to default */ 127438905Sborman /* 127538905Sborman * Create utmp entry for child 127638905Sborman */ 127738905Sborman (void) time(&wtmp.ut_time); 127838905Sborman wtmp.ut_type = LOGIN_PROCESS; 127938905Sborman wtmp.ut_pid = pid; 128038905Sborman SCPYN(wtmp.ut_user, "LOGIN"); 128138905Sborman SCPYN(wtmp.ut_host, host); 128238905Sborman SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); 128338905Sborman SCPYN(wtmp.ut_id, wtmp.ut_line+3); 128438905Sborman pututline(&wtmp); 128538905Sborman endutent(); 128638905Sborman if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { 128738905Sborman (void) write(i, (char *)&wtmp, sizeof(struct utmp)); 128838905Sborman (void) close(i); 128938905Sborman } 129046809Sdab (void) signal(WJSIGNAL, sigjob); 129138905Sborman utmp_sig_notify(pid); 129238905Sborman # endif /* CRAY */ 129338905Sborman } else { 129445234Sborman getptyslave(); 129546809Sdab start_login(host, autologin, autoname); 129638905Sborman /*NOTREACHED*/ 129738905Sborman } 129838905Sborman #else /* NEWINIT */ 129938905Sborman 130038905Sborman /* 130138905Sborman * Init will start up login process if we ask nicely. We only wait 130238905Sborman * for it to start up and begin normal telnet operation. 130338905Sborman */ 130438905Sborman if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { 130538905Sborman char tbuf[128]; 130638905Sborman (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO); 130738905Sborman fatalperror(net, tbuf); 130838905Sborman } 130938905Sborman memset((char *)&request, 0, sizeof(request)); 131038905Sborman request.magic = INIT_MAGIC; 131138905Sborman SCPYN(request.gen_id, gen_id); 131238905Sborman SCPYN(request.tty_id, &line[8]); 131338905Sborman SCPYN(request.host, host); 131446809Sdab SCPYN(request.term_type, terminaltype ? terminaltype : "network"); 131544364Sborman #if !defined(UNICOS5) 131640242Sborman request.signal = SIGCLD; 131740242Sborman request.pid = getpid(); 131840242Sborman #endif 131944364Sborman #ifdef BFTPDAEMON 132044364Sborman /* 132144364Sborman * Are we working as the bftp daemon? 132244364Sborman */ 132344364Sborman if (bftpd) { 132444364Sborman SCPYN(request.exec_name, BFTPPATH); 132544364Sborman } 132644364Sborman #endif /* BFTPDAEMON */ 132738905Sborman if (write(i, (char *)&request, sizeof(request)) < 0) { 132838905Sborman char tbuf[128]; 132938905Sborman (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO); 133038905Sborman fatalperror(net, tbuf); 133138905Sborman } 133238905Sborman (void) close(i); 133338905Sborman (void) signal(SIGALRM, nologinproc); 133438905Sborman for (i = 0; ; i++) { 133540242Sborman char tbuf[128]; 133638905Sborman alarm(15); 133738905Sborman n = read(pty, ptyip, BUFSIZ); 133838905Sborman if (i == 3 || n >= 0 || !gotalarm) 133938905Sborman break; 134038905Sborman gotalarm = 0; 134140242Sborman sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line); 134240242Sborman (void) write(net, tbuf, strlen(tbuf)); 134338905Sborman } 134438905Sborman if (n < 0 && gotalarm) 134538905Sborman fatal(net, "/etc/init didn't start login process"); 134638905Sborman pcc += n; 134738905Sborman alarm(0); 134838905Sborman (void) signal(SIGALRM, SIG_DFL); 134938905Sborman 135038905Sborman return; 135138905Sborman #endif /* NEWINIT */ 135238905Sborman } 135338905Sborman 135438905Sborman char *envinit[3]; 135544364Sborman extern char **environ; 135638905Sborman 135746809Sdab void 135844364Sborman init_env() 135944364Sborman { 136044364Sborman extern char *getenv(); 136144364Sborman char **envp; 136244364Sborman 136344364Sborman envp = envinit; 136444364Sborman if (*envp = getenv("TZ")) 136544364Sborman *envp++ -= 3; 136644364Sborman #ifdef CRAY 136744364Sborman else 136844364Sborman *envp++ = "TZ=GMT0"; 136944364Sborman #endif 137044364Sborman *envp = 0; 137144364Sborman environ = envinit; 137244364Sborman } 137344364Sborman 137444364Sborman #ifndef NEWINIT 137544364Sborman 137644364Sborman /* 137745234Sborman * start_login(host) 137838905Sborman * 137938905Sborman * Assuming that we are now running as a child processes, this 138038905Sborman * function will turn us into the login process. 138138905Sborman */ 138238905Sborman 138346809Sdab void 138446809Sdab start_login(host, autologin, name) 138546809Sdab char *host; 138646809Sdab int autologin; 138746809Sdab char *name; 138838905Sborman { 138944364Sborman register char *cp; 139044364Sborman register char **argv; 139144364Sborman char **addarg(); 139257212Sdab #ifdef UTMPX 139357212Sdab register int pid = getpid(); 139457212Sdab struct utmpx utmpx; 139557212Sdab #endif 139657212Sdab #ifdef __svr4__ 139757212Sdab char *term; 139857212Sdab char termbuf[64]; 139957212Sdab #endif 140038905Sborman 140157212Sdab #ifdef UTMPX 140238905Sborman /* 140357212Sdab * Create utmp entry for child 140457212Sdab */ 140557212Sdab 140657212Sdab bzero(&utmpx, sizeof(utmpx)); 140757212Sdab SCPYN(utmpx.ut_user, ".telnet"); 140857212Sdab SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); 140957212Sdab utmpx.ut_pid = pid; 141057212Sdab utmpx.ut_id[0] = 't'; 141157212Sdab utmpx.ut_id[1] = 'n'; 141257212Sdab utmpx.ut_id[2] = SC_WILDC; 141357212Sdab utmpx.ut_id[3] = SC_WILDC; 141457212Sdab utmpx.ut_type = LOGIN_PROCESS; 141557212Sdab (void) time(&utmpx.ut_tv.tv_sec); 141657212Sdab if (makeutx(&utmpx) == NULL) 141757212Sdab fatal(net, "makeutx failed"); 141857212Sdab #endif 141957212Sdab 142057212Sdab /* 142138905Sborman * -h : pass on name of host. 142238905Sborman * WARNING: -h is accepted by login if and only if 142338905Sborman * getuid() == 0. 142438905Sborman * -p : don't clobber the environment (so terminal type stays set). 142546809Sdab * 142646809Sdab * -f : force this login, he has already been authenticated 142738905Sborman */ 142844364Sborman argv = addarg(0, "login"); 142944364Sborman argv = addarg(argv, "-h"); 143044364Sborman argv = addarg(argv, host); 143157212Sdab #ifdef __svr4__ 143257212Sdab /* 143357212Sdab * SVR4 version of -h takes TERM= as second arg, or - 143457212Sdab */ 143557212Sdab term = getenv("TERM"); 143657212Sdab if (term == NULL || term[0] == 0) { 143757212Sdab term = "-"; 143857212Sdab } else { 143957212Sdab strcpy(termbuf, "TERM="); 144057212Sdab strncat(termbuf, term, sizeof(termbuf) - 6); 144157212Sdab term = termbuf; 144257212Sdab } 144357212Sdab argv = addarg(argv, term); 144457212Sdab #endif 144546809Sdab #if !defined(NO_LOGIN_P) 144644364Sborman argv = addarg(argv, "-p"); 144738905Sborman #endif 144844364Sborman #ifdef BFTPDAEMON 144944364Sborman /* 145044364Sborman * Are we working as the bftp daemon? If so, then ask login 145144364Sborman * to start bftp instead of shell. 145244364Sborman */ 145344364Sborman if (bftpd) { 145444364Sborman argv = addarg(argv, "-e"); 145544364Sborman argv = addarg(argv, BFTPPATH); 145644364Sborman } else 145744364Sborman #endif 145846809Sdab #if defined (SecurID) 145946809Sdab /* 146046809Sdab * don't worry about the -f that might get sent. 146146809Sdab * A -s is supposed to override it anyhow. 146246809Sdab */ 146346809Sdab if (require_SecurID) 146446809Sdab argv = addarg(argv, "-s"); 146546809Sdab #endif 146657212Sdab #if defined (AUTHENTICATION) 146746809Sdab if (auth_level >= 0 && autologin == AUTH_VALID) { 146846809Sdab # if !defined(NO_LOGIN_F) 146946809Sdab argv = addarg(argv, "-f"); 147046809Sdab # endif 147146809Sdab argv = addarg(argv, name); 147246809Sdab } else 147346809Sdab #endif 147444364Sborman if (getenv("USER")) { 147544364Sborman argv = addarg(argv, getenv("USER")); 147646809Sdab #if defined(CRAY) && defined(NO_LOGIN_P) 147746809Sdab { 147846809Sdab register char **cpp; 147946809Sdab for (cpp = environ; *cpp; cpp++) 148046809Sdab argv = addarg(argv, *cpp); 148146809Sdab } 148246809Sdab #endif 148357212Sdab /* 148457212Sdab * Assume that login will set the USER variable 148557212Sdab * correctly. For SysV systems, this means that 148657212Sdab * USER will no longer be set, just LOGNAME by 148757212Sdab * login. (The problem is that if the auto-login 148857212Sdab * fails, and the user then specifies a different 148957212Sdab * account name, he can get logged in with both 149057212Sdab * LOGNAME and USER in his environment, but the 149157212Sdab * USER value will be wrong. 149257212Sdab */ 149357212Sdab unsetenv("USER"); 149444364Sborman } 149546809Sdab closelog(); 149644364Sborman execv(_PATH_LOGIN, argv); 149744364Sborman 149838905Sborman syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN); 149938905Sborman fatalperror(net, _PATH_LOGIN); 150038905Sborman /*NOTREACHED*/ 150138905Sborman } 150244364Sborman 150346809Sdab char ** 150444364Sborman addarg(argv, val) 150546809Sdab register char **argv; 150646809Sdab register char *val; 150744364Sborman { 150844364Sborman register char **cpp; 150944364Sborman 151044364Sborman if (argv == NULL) { 151144364Sborman /* 151244364Sborman * 10 entries, a leading length, and a null 151344364Sborman */ 151444364Sborman argv = (char **)malloc(sizeof(*argv) * 12); 151544364Sborman if (argv == NULL) 151644364Sborman return(NULL); 151744364Sborman *argv++ = (char *)10; 151844364Sborman *argv = (char *)0; 151944364Sborman } 152044364Sborman for (cpp = argv; *cpp; cpp++) 152144364Sborman ; 152244364Sborman if (cpp == &argv[(int)argv[-1]]) { 152344364Sborman --argv; 152444364Sborman *argv = (char *)((int)(*argv) + 10); 152544364Sborman argv = (char **)realloc(argv, (int)(*argv) + 2); 152644364Sborman if (argv == NULL) 152744364Sborman return(NULL); 152844364Sborman argv++; 152944364Sborman cpp = &argv[(int)argv[-1] - 10]; 153044364Sborman } 153144364Sborman *cpp++ = val; 153244364Sborman *cpp = 0; 153344364Sborman return(argv); 153444364Sborman } 153546809Sdab #endif /* NEWINIT */ 153638905Sborman 153738905Sborman /* 153838905Sborman * cleanup() 153938905Sborman * 154038905Sborman * This is the routine to call when we are all through, to 154138905Sborman * clean up anything that needs to be cleaned up. 154238905Sborman */ 154346809Sdab /* ARGSUSED */ 154446809Sdab void 154546809Sdab cleanup(sig) 154646809Sdab int sig; 154738905Sborman { 154838905Sborman #ifndef CRAY 154945234Sborman # if (BSD > 43) || defined(convex) 155038905Sborman char *p; 155138905Sborman 155238905Sborman p = line + sizeof("/dev/") - 1; 155338905Sborman if (logout(p)) 155438905Sborman logwtmp(p, "", ""); 155538905Sborman (void)chmod(line, 0666); 155638905Sborman (void)chown(line, 0, 0); 155738905Sborman *p = 'p'; 155838905Sborman (void)chmod(line, 0666); 155938905Sborman (void)chown(line, 0, 0); 156046809Sdab (void) shutdown(net, 2); 156146809Sdab exit(1); 156238905Sborman # else 156346809Sdab void rmut(); 156446809Sdab 156538905Sborman rmut(); 156638905Sborman vhangup(); /* XXX */ 156746809Sdab (void) shutdown(net, 2); 156846809Sdab exit(1); 156938905Sborman # endif 157038905Sborman #else /* CRAY */ 157146809Sdab # ifdef NEWINIT 157238905Sborman (void) shutdown(net, 2); 157346809Sdab exit(1); 157438905Sborman # else /* NEWINIT */ 157546809Sdab static int incleanup = 0; 157646809Sdab register int t; 157746809Sdab 157846809Sdab /* 157946809Sdab * 1: Pick up the zombie, if we are being called 158046809Sdab * as the signal handler. 158146809Sdab * 2: If we are a nested cleanup(), return. 158246809Sdab * 3: Try to clean up TMPDIR. 158346809Sdab * 4: Fill in utmp with shutdown of process. 158446809Sdab * 5: Close down the network and pty connections. 158546809Sdab * 6: Finish up the TMPDIR cleanup, if needed. 158646809Sdab */ 158746809Sdab if (sig == SIGCHLD) 158846809Sdab while (waitpid(-1, 0, WNOHANG) > 0) 158946809Sdab ; /* VOID */ 159046809Sdab t = sigblock(sigmask(SIGCHLD)); 159146809Sdab if (incleanup) { 159246809Sdab sigsetmask(t); 159346809Sdab return; 159446809Sdab } 159546809Sdab incleanup = 1; 159646809Sdab sigsetmask(t); 159746809Sdab 159846809Sdab t = cleantmp(&wtmp); 159946809Sdab setutent(); /* just to make sure */ 160046809Sdab rmut(line); 160146809Sdab close(pty); 160238905Sborman (void) shutdown(net, 2); 160346809Sdab if (t == 0) 160446809Sdab cleantmp(&wtmp); 160546809Sdab exit(1); 160638905Sborman # endif /* NEWINT */ 160738905Sborman #endif /* CRAY */ 160838905Sborman } 160938905Sborman 161038905Sborman #if defined(CRAY) && !defined(NEWINIT) 161138905Sborman /* 161238905Sborman * _utmp_sig_rcv 161338905Sborman * utmp_sig_init 161438905Sborman * utmp_sig_wait 161538905Sborman * These three functions are used to coordinate the handling of 161638905Sborman * the utmp file between the server and the soon-to-be-login shell. 161738905Sborman * The server actually creates the utmp structure, the child calls 161838905Sborman * utmp_sig_wait(), until the server calls utmp_sig_notify() and 161938905Sborman * signals the future-login shell to proceed. 162038905Sborman */ 162138905Sborman static int caught=0; /* NZ when signal intercepted */ 162238905Sborman static void (*func)(); /* address of previous handler */ 162338905Sborman 162446809Sdab void 162538905Sborman _utmp_sig_rcv(sig) 162646809Sdab int sig; 162738905Sborman { 162838905Sborman caught = 1; 162938905Sborman (void) signal(SIGUSR1, func); 163038905Sborman } 163138905Sborman 163246809Sdab void 163338905Sborman utmp_sig_init() 163438905Sborman { 163538905Sborman /* 163638905Sborman * register signal handler for UTMP creation 163738905Sborman */ 163838905Sborman if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) 163938905Sborman fatalperror(net, "telnetd/signal"); 164038905Sborman } 164138905Sborman 164246809Sdab void 164344364Sborman utmp_sig_reset() 164444364Sborman { 164544364Sborman (void) signal(SIGUSR1, func); /* reset handler to default */ 164644364Sborman } 164744364Sborman 164846809Sdab void 164938905Sborman utmp_sig_wait() 165038905Sborman { 165138905Sborman /* 165238905Sborman * Wait for parent to write our utmp entry. 165338905Sborman */ 165438905Sborman sigoff(); 165538905Sborman while (caught == 0) { 165638905Sborman pause(); /* wait until we get a signal (sigon) */ 165738905Sborman sigoff(); /* turn off signals while we check caught */ 165838905Sborman } 165938905Sborman sigon(); /* turn on signals again */ 166038905Sborman } 166138905Sborman 166246809Sdab void 166338905Sborman utmp_sig_notify(pid) 166438905Sborman { 166538905Sborman kill(pid, SIGUSR1); 166638905Sborman } 166746809Sdab 166846809Sdab static int gotsigjob = 0; 166946809Sdab 167046809Sdab /*ARGSUSED*/ 167146809Sdab void 167246809Sdab sigjob(sig) 167346809Sdab int sig; 167446809Sdab { 167546809Sdab register int jid; 167646809Sdab register struct jobtemp *jp; 167746809Sdab 167846809Sdab while ((jid = waitjob(NULL)) != -1) { 167946809Sdab if (jid == 0) { 168046809Sdab return; 168146809Sdab } 168246809Sdab gotsigjob++; 168346809Sdab jobend(jid, NULL, NULL); 168446809Sdab } 168546809Sdab } 168646809Sdab 168746809Sdab /* 168846809Sdab * Clean up the TMPDIR that login created. 168946809Sdab * The first time this is called we pick up the info 169046809Sdab * from the utmp. If the job has already gone away, 169146809Sdab * then we'll clean up and be done. If not, then 169246809Sdab * when this is called the second time it will wait 169346809Sdab * for the signal that the job is done. 169446809Sdab */ 169546809Sdab int 169646809Sdab cleantmp(wtp) 169746809Sdab register struct utmp *wtp; 169846809Sdab { 169946809Sdab struct utmp *utp; 170046809Sdab static int first = 1; 170146809Sdab register int mask, omask, ret; 170246809Sdab extern struct utmp *getutid P((struct utmp *)); 170346809Sdab 170446809Sdab mask = sigmask(WJSIGNAL); 170546809Sdab 170646809Sdab if (first == 0) { 170746809Sdab omask = sigblock(mask); 170846809Sdab while (gotsigjob == 0) 170946809Sdab sigpause(omask); 171046809Sdab return(1); 171146809Sdab } 171246809Sdab first = 0; 171346809Sdab setutent(); /* just to make sure */ 171446809Sdab 171546809Sdab utp = getutid(wtp); 171646809Sdab if (utp == 0) { 171746809Sdab syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); 171846809Sdab return(-1); 171946809Sdab } 172046809Sdab /* 172146809Sdab * Nothing to clean up if the user shell was never started. 172246809Sdab */ 172346809Sdab if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) 172446809Sdab return(1); 172546809Sdab 172646809Sdab /* 172746809Sdab * Block the WJSIGNAL while we are in jobend(). 172846809Sdab */ 172946809Sdab omask = sigblock(mask); 173046809Sdab ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); 173146809Sdab sigsetmask(omask); 173246809Sdab return(ret); 173346809Sdab } 173446809Sdab 173546809Sdab int 173646809Sdab jobend(jid, path, user) 173746809Sdab register int jid; 173846809Sdab register char *path; 173946809Sdab register char *user; 174046809Sdab { 174146809Sdab static int saved_jid = 0; 174246809Sdab static char saved_path[sizeof(wtmp.ut_tpath)+1]; 174346809Sdab static char saved_user[sizeof(wtmp.ut_user)+1]; 174446809Sdab 174546809Sdab if (path) { 174646809Sdab strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); 174746809Sdab strncpy(saved_user, user, sizeof(wtmp.ut_user)); 174846809Sdab saved_path[sizeof(saved_path)] = '\0'; 174946809Sdab saved_user[sizeof(saved_user)] = '\0'; 175046809Sdab } 175146809Sdab if (saved_jid == 0) { 175246809Sdab saved_jid = jid; 175346809Sdab return(0); 175446809Sdab } 175546809Sdab cleantmpdir(jid, saved_path, saved_user); 175646809Sdab return(1); 175746809Sdab } 175846809Sdab 175946809Sdab /* 176046809Sdab * Fork a child process to clean up the TMPDIR 176146809Sdab */ 176246809Sdab cleantmpdir(jid, tpath, user) 176346809Sdab register int jid; 176446809Sdab register char *tpath; 176546809Sdab register char *user; 176646809Sdab { 176746809Sdab switch(fork()) { 176846809Sdab case -1: 176946809Sdab syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n", 177046809Sdab tpath); 177146809Sdab break; 177246809Sdab case 0: 177346809Sdab execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); 177446809Sdab syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", 177546809Sdab tpath, CLEANTMPCMD); 177646809Sdab exit(1); 177746809Sdab default: 177846809Sdab /* 177946809Sdab * Forget about child. We will exit, and 178046809Sdab * /etc/init will pick it up. 178146809Sdab */ 178246809Sdab break; 178346809Sdab } 178446809Sdab } 178538905Sborman #endif /* defined(CRAY) && !defined(NEWINIT) */ 178638905Sborman 178738905Sborman /* 178838905Sborman * rmut() 178938905Sborman * 179038905Sborman * This is the function called by cleanup() to 179138905Sborman * remove the utmp entry for this person. 179238905Sborman */ 179338905Sborman 179457212Sdab #ifdef UTMPX 179557212Sdab rmut() 179657212Sdab { 179757212Sdab register f; 179857212Sdab int found = 0; 179957212Sdab struct utmp *u, *utmp; 180057212Sdab int nutmp; 180157212Sdab struct stat statbf; 180257212Sdab 180357212Sdab struct utmpx *utxp, utmpx; 180457212Sdab 180557212Sdab /* 180657212Sdab * This updates the utmpx and utmp entries and make a wtmp/x entry 180757212Sdab */ 180857212Sdab 180957212Sdab SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); 181057212Sdab utxp = getutxline(&utmpx); 181157212Sdab if (utxp) { 181257212Sdab utxp->ut_type = DEAD_PROCESS; 181357212Sdab utxp->ut_exit.e_termination = 0; 181457212Sdab utxp->ut_exit.e_exit = 0; 181557212Sdab (void) time(&utmpx.ut_tv.tv_sec); 181657212Sdab utmpx.ut_tv.tv_usec = 0; 181757212Sdab modutx(utxp); 181857212Sdab } 181957212Sdab endutxent(); 182057212Sdab } /* end of rmut */ 182157212Sdab #endif 182257212Sdab 182357212Sdab #if !defined(UTMPX) && !defined(CRAY) && BSD <= 43 182446809Sdab void 182538905Sborman rmut() 182638905Sborman { 182738905Sborman register f; 182838905Sborman int found = 0; 182938905Sborman struct utmp *u, *utmp; 183038905Sborman int nutmp; 183138905Sborman struct stat statbf; 183238905Sborman 183338905Sborman f = open(utmpf, O_RDWR); 183438905Sborman if (f >= 0) { 183538905Sborman (void) fstat(f, &statbf); 183638905Sborman utmp = (struct utmp *)malloc((unsigned)statbf.st_size); 183738905Sborman if (!utmp) 183838905Sborman syslog(LOG_ERR, "utmp malloc failed"); 183938905Sborman if (statbf.st_size && utmp) { 184038905Sborman nutmp = read(f, (char *)utmp, (int)statbf.st_size); 184138905Sborman nutmp /= sizeof(struct utmp); 184238905Sborman 184338905Sborman for (u = utmp ; u < &utmp[nutmp] ; u++) { 184438905Sborman if (SCMPN(u->ut_line, line+5) || 184538905Sborman u->ut_name[0]==0) 184638905Sborman continue; 184738905Sborman (void) lseek(f, ((long)u)-((long)utmp), L_SET); 184838905Sborman SCPYN(u->ut_name, ""); 184938905Sborman SCPYN(u->ut_host, ""); 185038905Sborman (void) time(&u->ut_time); 185138905Sborman (void) write(f, (char *)u, sizeof(wtmp)); 185238905Sborman found++; 185338905Sborman } 185438905Sborman } 185538905Sborman (void) close(f); 185638905Sborman } 185738905Sborman if (found) { 185838905Sborman f = open(wtmpf, O_WRONLY|O_APPEND); 185938905Sborman if (f >= 0) { 186038905Sborman SCPYN(wtmp.ut_line, line+5); 186138905Sborman SCPYN(wtmp.ut_name, ""); 186238905Sborman SCPYN(wtmp.ut_host, ""); 186338905Sborman (void) time(&wtmp.ut_time); 186438905Sborman (void) write(f, (char *)&wtmp, sizeof(wtmp)); 186538905Sborman (void) close(f); 186638905Sborman } 186738905Sborman } 186838905Sborman (void) chmod(line, 0666); 186938905Sborman (void) chown(line, 0, 0); 187038905Sborman line[strlen("/dev/")] = 'p'; 187138905Sborman (void) chmod(line, 0666); 187238905Sborman (void) chown(line, 0, 0); 187338905Sborman } /* end of rmut */ 187438905Sborman #endif /* CRAY */ 1875