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*46809Sdab static char sccsid[] = "@(#)sys_term.c 5.13 (Berkeley) 03/01/91"; 1038905Sborman #endif /* not lint */ 1138905Sborman 1238905Sborman #include "telnetd.h" 1338905Sborman #include "pathnames.h" 1438905Sborman 15*46809Sdab #if defined(AUTHENTICATE) 16*46809Sdab #include <libtelnet/auth.h> 17*46809Sdab #endif 18*46809Sdab 1938905Sborman #ifdef NEWINIT 2038905Sborman #include <initreq.h> 2138905Sborman #else /* NEWINIT*/ 2238905Sborman #include <utmp.h> 2338905Sborman struct utmp wtmp; 2438905Sborman 2538905Sborman # ifndef CRAY 2638905Sborman char wtmpf[] = "/usr/adm/wtmp"; 2738905Sborman char utmpf[] = "/etc/utmp"; 2838905Sborman # else /* CRAY */ 2938905Sborman char wtmpf[] = "/etc/wtmp"; 30*46809Sdab #include <tmpdir.h> 31*46809Sdab #include <sys/wait.h> 3238905Sborman # endif /* CRAY */ 3338905Sborman #endif /* NEWINIT */ 3438905Sborman 3538905Sborman #define SCPYN(a, b) (void) strncpy(a, b, sizeof(a)) 3638905Sborman #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 3738905Sborman 3844364Sborman #ifdef STREAMS 3944364Sborman #include <sys/stream.h> 4044364Sborman #endif 4138905Sborman #include <sys/tty.h> 4238905Sborman #ifdef t_erase 4338905Sborman #undef t_erase 4438905Sborman #undef t_kill 4538905Sborman #undef t_intrc 4638905Sborman #undef t_quitc 4738905Sborman #undef t_startc 4838905Sborman #undef t_stopc 4938905Sborman #undef t_eofc 5038905Sborman #undef t_brkc 5138905Sborman #undef t_suspc 5238905Sborman #undef t_dsuspc 5338905Sborman #undef t_rprntc 5438905Sborman #undef t_flushc 5538905Sborman #undef t_werasc 5638905Sborman #undef t_lnextc 5738905Sborman #endif 5838905Sborman 5944364Sborman #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC) 6044364Sborman # define EXTPROC 0400 6144364Sborman #endif 6244364Sborman 6338905Sborman #ifndef USE_TERMIO 6438905Sborman struct termbuf { 6538905Sborman struct sgttyb sg; 6638905Sborman struct tchars tc; 6738905Sborman struct ltchars ltc; 6838905Sborman int state; 6938905Sborman int lflags; 7038905Sborman } termbuf, termbuf2; 7145234Sborman # define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val) 7245234Sborman # define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val) 73*46809Sdab # define cfgetospeed(tp) (tp)->sg.sg_ospeed 74*46809Sdab # define cfgetispeed(tp) (tp)->sg.sg_ispeed 7538905Sborman #else /* USE_TERMIO */ 7638905Sborman # ifdef SYSV_TERMIO 7738905Sborman # define termios termio 7838905Sborman # endif 7945234Sborman # ifndef TCSANOW 8044364Sborman # ifdef TCSETS 8145234Sborman # define TCSANOW TCSETS 8245234Sborman # define TCSADRAIN TCSETSW 83*46809Sdab # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) 8444364Sborman # else 8545234Sborman # ifdef TCSETA 8645234Sborman # define TCSANOW TCSETA 8745234Sborman # define TCSADRAIN TCSETAW 88*46809Sdab # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) 8945234Sborman # else 9045234Sborman # define TCSANOW TIOCSETA 9145234Sborman # define TCSADRAIN TIOCSETAW 92*46809Sdab # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) 9345234Sborman # endif 9444364Sborman # endif 9545234Sborman # define tcsetattr(f, a, t) ioctl(f, a, t) 9645234Sborman # define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 9745234Sborman (tp)->c_cflag |= (val) 98*46809Sdab # define cfgetospeed(tp) ((tp)->c_cflag & CBAUD) 9945234Sborman # ifdef CIBAUD 10045234Sborman # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \ 10145234Sborman (tp)->c_cflag |= ((val)<<IBSHIFT) 102*46809Sdab # define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT) 10345234Sborman # else 10445234Sborman # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 10545234Sborman (tp)->c_cflag |= (val) 106*46809Sdab # define cfgetispeed(tp) ((tp)->c_cflag & CBAUD) 10745234Sborman # endif 10845234Sborman # endif /* TCSANOW */ 10938905Sborman struct termios termbuf, termbuf2; /* pty control structure */ 11038905Sborman #endif /* USE_TERMIO */ 11138905Sborman 11238905Sborman /* 11338905Sborman * init_termbuf() 11438905Sborman * copy_termbuf(cp) 11538905Sborman * set_termbuf() 11638905Sborman * 11738905Sborman * These three routines are used to get and set the "termbuf" structure 11838905Sborman * to and from the kernel. init_termbuf() gets the current settings. 11938905Sborman * copy_termbuf() hands in a new "termbuf" to write to the kernel, and 12038905Sborman * set_termbuf() writes the structure into the kernel. 12138905Sborman */ 12238905Sborman 123*46809Sdab void 12438905Sborman init_termbuf() 12538905Sborman { 12638905Sborman #ifndef USE_TERMIO 12738905Sborman (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg); 12838905Sborman (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc); 12938905Sborman (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc); 13038905Sborman # ifdef TIOCGSTATE 13138905Sborman (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state); 13238905Sborman # endif 13338905Sborman #else 13446685Sbostic (void) tcgetattr(pty, &termbuf); 13538905Sborman #endif 13638905Sborman termbuf2 = termbuf; 13738905Sborman } 13838905Sborman 13938905Sborman #if defined(LINEMODE) && defined(TIOCPKT_IOCTL) 140*46809Sdab void 14138905Sborman copy_termbuf(cp, len) 142*46809Sdab char *cp; 143*46809Sdab int len; 14438905Sborman { 14538905Sborman if (len > sizeof(termbuf)) 14638905Sborman len = sizeof(termbuf); 14738905Sborman bcopy(cp, (char *)&termbuf, len); 14838905Sborman termbuf2 = termbuf; 14938905Sborman } 15038905Sborman #endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ 15138905Sborman 152*46809Sdab void 15338905Sborman set_termbuf() 15438905Sborman { 15538905Sborman /* 15638905Sborman * Only make the necessary changes. 15738905Sborman */ 15838905Sborman #ifndef USE_TERMIO 15938905Sborman if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg))) 16045234Sborman (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg); 16138905Sborman if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc))) 16238905Sborman (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc); 16338905Sborman if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc, 16438905Sborman sizeof(termbuf.ltc))) 16538905Sborman (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc); 16638905Sborman if (termbuf.lflags != termbuf2.lflags) 16738905Sborman (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags); 16838905Sborman #else /* USE_TERMIO */ 16938905Sborman if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) 170*46809Sdab (void) tcsetattr(pty, TCSANOW, &termbuf); 17140242Sborman # if defined(CRAY2) && defined(UNCIOS5) 17238905Sborman needtermstat = 1; 17338905Sborman # endif 17438905Sborman #endif /* USE_TERMIO */ 17538905Sborman } 17638905Sborman 17738905Sborman 17838905Sborman /* 17938905Sborman * spcset(func, valp, valpp) 18038905Sborman * 18138905Sborman * This function takes various special characters (func), and 18238905Sborman * sets *valp to the current value of that character, and 18338905Sborman * *valpp to point to where in the "termbuf" structure that 18438905Sborman * value is kept. 18538905Sborman * 18638905Sborman * It returns the SLC_ level of support for this function. 18738905Sborman */ 18838905Sborman 18938905Sborman #ifndef USE_TERMIO 190*46809Sdab int 19138905Sborman spcset(func, valp, valpp) 192*46809Sdab int func; 193*46809Sdab cc_t *valp; 194*46809Sdab cc_t **valpp; 19538905Sborman { 19638905Sborman switch(func) { 19738905Sborman case SLC_EOF: 19838905Sborman *valp = termbuf.tc.t_eofc; 19940242Sborman *valpp = (cc_t *)&termbuf.tc.t_eofc; 20038905Sborman return(SLC_VARIABLE); 20138905Sborman case SLC_EC: 20238905Sborman *valp = termbuf.sg.sg_erase; 20340242Sborman *valpp = (cc_t *)&termbuf.sg.sg_erase; 20438905Sborman return(SLC_VARIABLE); 20538905Sborman case SLC_EL: 20638905Sborman *valp = termbuf.sg.sg_kill; 20740242Sborman *valpp = (cc_t *)&termbuf.sg.sg_kill; 20838905Sborman return(SLC_VARIABLE); 20938905Sborman case SLC_IP: 21038905Sborman *valp = termbuf.tc.t_intrc; 21140242Sborman *valpp = (cc_t *)&termbuf.tc.t_intrc; 21238905Sborman return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 21338905Sborman case SLC_ABORT: 21438905Sborman *valp = termbuf.tc.t_quitc; 21540242Sborman *valpp = (cc_t *)&termbuf.tc.t_quitc; 21638905Sborman return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 21738905Sborman case SLC_XON: 21838905Sborman *valp = termbuf.tc.t_startc; 21940242Sborman *valpp = (cc_t *)&termbuf.tc.t_startc; 22038905Sborman return(SLC_VARIABLE); 22138905Sborman case SLC_XOFF: 22238905Sborman *valp = termbuf.tc.t_stopc; 22340242Sborman *valpp = (cc_t *)&termbuf.tc.t_stopc; 22438905Sborman return(SLC_VARIABLE); 22538905Sborman case SLC_AO: 22638905Sborman *valp = termbuf.ltc.t_flushc; 22740242Sborman *valpp = (cc_t *)&termbuf.ltc.t_flushc; 22838905Sborman return(SLC_VARIABLE); 22938905Sborman case SLC_SUSP: 23038905Sborman *valp = termbuf.ltc.t_suspc; 23140242Sborman *valpp = (cc_t *)&termbuf.ltc.t_suspc; 23238905Sborman return(SLC_VARIABLE); 23338905Sborman case SLC_EW: 23438905Sborman *valp = termbuf.ltc.t_werasc; 23540242Sborman *valpp = (cc_t *)&termbuf.ltc.t_werasc; 23638905Sborman return(SLC_VARIABLE); 23738905Sborman case SLC_RP: 23838905Sborman *valp = termbuf.ltc.t_rprntc; 23940242Sborman *valpp = (cc_t *)&termbuf.ltc.t_rprntc; 24038905Sborman return(SLC_VARIABLE); 24138905Sborman case SLC_LNEXT: 24238905Sborman *valp = termbuf.ltc.t_lnextc; 24340242Sborman *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 24438905Sborman return(SLC_VARIABLE); 24540242Sborman case SLC_FORW1: 24640242Sborman *valp = termbuf.tc.t_brkc; 24740242Sborman *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 24840242Sborman return(SLC_VARIABLE); 24938905Sborman case SLC_BRK: 25038905Sborman case SLC_SYNCH: 25138905Sborman case SLC_AYT: 25238905Sborman case SLC_EOR: 25340242Sborman *valp = (cc_t)0; 25440242Sborman *valpp = (cc_t *)0; 25538905Sborman return(SLC_DEFAULT); 25638905Sborman default: 25740242Sborman *valp = (cc_t)0; 25840242Sborman *valpp = (cc_t *)0; 25938905Sborman return(SLC_NOSUPPORT); 26038905Sborman } 26138905Sborman } 26238905Sborman 26338905Sborman #else /* USE_TERMIO */ 26438905Sborman 265*46809Sdab int 26638905Sborman spcset(func, valp, valpp) 267*46809Sdab int func; 268*46809Sdab cc_t *valp; 269*46809Sdab cc_t **valpp; 27038905Sborman { 27139503Sborman 27239503Sborman #define setval(a, b) *valp = termbuf.c_cc[a]; \ 27339503Sborman *valpp = &termbuf.c_cc[a]; \ 27439503Sborman return(b); 27540242Sborman #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); 27639503Sborman 27738905Sborman switch(func) { 27838905Sborman case SLC_EOF: 27939503Sborman setval(VEOF, SLC_VARIABLE); 28038905Sborman case SLC_EC: 28139503Sborman setval(VERASE, SLC_VARIABLE); 28238905Sborman case SLC_EL: 28339503Sborman setval(VKILL, SLC_VARIABLE); 28438905Sborman case SLC_IP: 28539503Sborman setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 28638905Sborman case SLC_ABORT: 28739503Sborman setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 28838905Sborman case SLC_XON: 28939503Sborman #ifdef VSTART 29039503Sborman setval(VSTART, SLC_VARIABLE); 29139503Sborman #else 29239503Sborman defval(0x13); 29339503Sborman #endif 29438905Sborman case SLC_XOFF: 29539503Sborman #ifdef VSTOP 29639503Sborman setval(VSTOP, SLC_VARIABLE); 29739503Sborman #else 29839503Sborman defval(0x11); 29939503Sborman #endif 30038905Sborman case SLC_EW: 30139503Sborman #ifdef VWERASE 30239503Sborman setval(VWERASE, SLC_VARIABLE); 30339503Sborman #else 30439503Sborman defval(0); 30539503Sborman #endif 30638905Sborman case SLC_RP: 30739503Sborman #ifdef VREPRINT 30839503Sborman setval(VREPRINT, SLC_VARIABLE); 30939503Sborman #else 31039503Sborman defval(0); 31139503Sborman #endif 31238905Sborman case SLC_LNEXT: 31339503Sborman #ifdef VLNEXT 31439503Sborman setval(VLNEXT, SLC_VARIABLE); 31539503Sborman #else 31639503Sborman defval(0); 31739503Sborman #endif 31839503Sborman case SLC_AO: 31945234Sborman #if !defined(VDISCARD) && defined(VFLUSHO) 32045234Sborman # define VDISCARD VFLUSHO 32145234Sborman #endif 32245234Sborman #ifdef VDISCARD 32345234Sborman setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); 32439503Sborman #else 32539503Sborman defval(0); 32639503Sborman #endif 32739503Sborman case SLC_SUSP: 32839503Sborman #ifdef VSUSP 32939503Sborman setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); 33039503Sborman #else 33139503Sborman defval(0); 33239503Sborman #endif 33340242Sborman #ifdef VEOL 33440242Sborman case SLC_FORW1: 33540242Sborman setval(VEOL, SLC_VARIABLE); 33640242Sborman #endif 33740242Sborman #ifdef VEOL2 33840242Sborman case SLC_FORW2: 33940242Sborman setval(VEOL2, SLC_VARIABLE); 34040242Sborman #endif 34145234Sborman case SLC_AYT: 34245234Sborman #ifdef VSTATUS 34345234Sborman setval(VSTATUS, SLC_VARIABLE); 34445234Sborman #else 34545234Sborman defval(0); 34645234Sborman #endif 34739503Sborman 34838905Sborman case SLC_BRK: 34938905Sborman case SLC_SYNCH: 35038905Sborman case SLC_EOR: 35139503Sborman defval(0); 35239503Sborman 35338905Sborman default: 35438905Sborman *valp = 0; 35538905Sborman *valpp = 0; 35638905Sborman return(SLC_NOSUPPORT); 35738905Sborman } 35838905Sborman } 35938905Sborman #endif /* USE_TERMIO */ 36038905Sborman 36140242Sborman #ifdef CRAY 36238905Sborman /* 36340242Sborman * getnpty() 36440242Sborman * 36540242Sborman * Return the number of pty's configured into the system. 36640242Sborman */ 367*46809Sdab int 36840242Sborman getnpty() 36940242Sborman { 37040242Sborman #ifdef _SC_CRAY_NPTY 371*46809Sdab int numptys; 372*46809Sdab 373*46809Sdab if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) 374*46809Sdab return numptys; 375*46809Sdab else 37640242Sborman #endif /* _SC_CRAY_NPTY */ 377*46809Sdab return 128; 37840242Sborman } 37940242Sborman #endif /* CRAY */ 38040242Sborman 38145234Sborman #ifndef convex 38240242Sborman /* 38338905Sborman * getpty() 38438905Sborman * 38538905Sborman * Allocate a pty. As a side effect, the external character 38638905Sborman * array "line" contains the name of the slave side. 38738905Sborman * 38838905Sborman * Returns the file descriptor of the opened pty. 38938905Sborman */ 39045234Sborman #ifndef __GNUC__ 39138905Sborman char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 39245234Sborman #else 39345234Sborman static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 39445234Sborman char *line = Xline; 39545234Sborman #endif 39645234Sborman #ifdef CRAY 39745234Sborman char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 39845234Sborman #endif /* CRAY */ 39938905Sborman 400*46809Sdab int 40138905Sborman getpty() 40238905Sborman { 40338905Sborman register int p; 40438905Sborman #ifndef CRAY 40538905Sborman register char c, *p1, *p2; 40638905Sborman register int i; 40738905Sborman 40838905Sborman (void) sprintf(line, "/dev/ptyXX"); 40938905Sborman p1 = &line[8]; 41038905Sborman p2 = &line[9]; 41138905Sborman 41238905Sborman for (c = 'p'; c <= 's'; c++) { 41338905Sborman struct stat stb; 41438905Sborman 41538905Sborman *p1 = c; 41638905Sborman *p2 = '0'; 41738905Sborman if (stat(line, &stb) < 0) 41838905Sborman break; 41938905Sborman for (i = 0; i < 16; i++) { 42038905Sborman *p2 = "0123456789abcdef"[i]; 42138905Sborman p = open(line, 2); 42238905Sborman if (p > 0) { 42338905Sborman line[5] = 't'; 42438905Sborman return(p); 42538905Sborman } 42638905Sborman } 42738905Sborman } 42838905Sborman #else /* CRAY */ 42938905Sborman register int npty; 43038905Sborman extern lowpty, highpty; 43145234Sborman struct stat sb; 43238905Sborman 43338905Sborman for (npty = lowpty; npty <= highpty; npty++) { 43445234Sborman (void) sprintf(myline, "/dev/pty/%03d", npty); 43545234Sborman p = open(myline, 2); 43638905Sborman if (p < 0) 43738905Sborman continue; 43838905Sborman (void) sprintf(line, "/dev/ttyp%03d", npty); 43945234Sborman /* 44045234Sborman * Here are some shenanigans to make sure that there 44145234Sborman * are no listeners lurking on the line. 44245234Sborman */ 44345234Sborman if(stat(line, &sb) < 0) { 44445234Sborman (void) close(p); 44545234Sborman continue; 44645234Sborman } 44745234Sborman if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { 44845234Sborman chown(line, 0, 0); 44945234Sborman chmod(line, 0600); 45045234Sborman (void)close(p); 45145234Sborman p = open(myline, 2); 45245234Sborman if (p < 0) 45345234Sborman continue; 45445234Sborman } 45545234Sborman /* 45645234Sborman * Now it should be safe...check for accessability. 45745234Sborman */ 45838905Sborman if (access(line, 6) == 0) 45938905Sborman return(p); 46038905Sborman else { 46138905Sborman /* no tty side to pty so skip it */ 46238905Sborman (void) close(p); 46338905Sborman } 46438905Sborman } 46538905Sborman #endif /* CRAY */ 46638905Sborman return(-1); 46738905Sborman } 46845234Sborman #endif /* convex */ 46938905Sborman 47038905Sborman #ifdef LINEMODE 47138905Sborman /* 47238905Sborman * tty_flowmode() Find out if flow control is enabled or disabled. 47338905Sborman * tty_linemode() Find out if linemode (external processing) is enabled. 47438905Sborman * tty_setlinemod(on) Turn on/off linemode. 47538905Sborman * tty_isecho() Find out if echoing is turned on. 47638905Sborman * tty_setecho(on) Enable/disable character echoing. 47738905Sborman * tty_israw() Find out if terminal is in RAW mode. 47838905Sborman * tty_binaryin(on) Turn on/off BINARY on input. 47938905Sborman * tty_binaryout(on) Turn on/off BINARY on output. 48038905Sborman * tty_isediting() Find out if line editing is enabled. 48138905Sborman * tty_istrapsig() Find out if signal trapping is enabled. 48238905Sborman * tty_setedit(on) Turn on/off line editing. 48338905Sborman * tty_setsig(on) Turn on/off signal trapping. 48444364Sborman * tty_issofttab() Find out if tab expansion is enabled. 48544364Sborman * tty_setsofttab(on) Turn on/off soft tab expansion. 48644364Sborman * tty_islitecho() Find out if typed control chars are echoed literally 48744364Sborman * tty_setlitecho() Turn on/off literal echo of control chars 48838905Sborman * tty_tspeed(val) Set transmit speed to val. 48938905Sborman * tty_rspeed(val) Set receive speed to val. 49038905Sborman */ 49138905Sborman 492*46809Sdab int 49338905Sborman tty_flowmode() 49438905Sborman { 49538905Sborman #ifndef USE_TERMIO 496*46809Sdab return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0); 49738905Sborman #else 49838905Sborman return(termbuf.c_iflag & IXON ? 1 : 0); 49938905Sborman #endif 50038905Sborman } 50138905Sborman 50245234Sborman #ifdef convex 50345234Sborman static int linestate; 50445234Sborman #endif 50545234Sborman 506*46809Sdab int 50738905Sborman tty_linemode() 50838905Sborman { 50945234Sborman #ifndef convex 51038905Sborman #ifndef USE_TERMIO 51138905Sborman return(termbuf.state & TS_EXTPROC); 51238905Sborman #else 51338905Sborman return(termbuf.c_lflag & EXTPROC); 51438905Sborman #endif 51545234Sborman #else 51645234Sborman return(linestate); 51745234Sborman #endif 51838905Sborman } 51938905Sborman 520*46809Sdab void 52138905Sborman tty_setlinemode(on) 522*46809Sdab int on; 52338905Sborman { 52438905Sborman #ifdef TIOCEXT 52545234Sborman # ifndef convex 52645234Sborman set_termbuf(); 52745234Sborman # else 52845234Sborman linestate = on; 52945234Sborman # endif 53038905Sborman (void) ioctl(pty, TIOCEXT, (char *)&on); 53145234Sborman # ifndef convex 53245234Sborman init_termbuf(); 53345234Sborman # endif 53438905Sborman #else /* !TIOCEXT */ 53545234Sborman # ifdef EXTPROC 53638905Sborman if (on) 53738905Sborman termbuf.c_lflag |= EXTPROC; 53838905Sborman else 53938905Sborman termbuf.c_lflag &= ~EXTPROC; 54045234Sborman # endif 54138905Sborman #endif /* TIOCEXT */ 54238905Sborman } 54338905Sborman 544*46809Sdab int 54538905Sborman tty_isecho() 54638905Sborman { 54738905Sborman #ifndef USE_TERMIO 54838905Sborman return (termbuf.sg.sg_flags & ECHO); 54938905Sborman #else 55038905Sborman return (termbuf.c_lflag & ECHO); 55138905Sborman #endif 55238905Sborman } 55338905Sborman #endif /* LINEMODE */ 55438905Sborman 555*46809Sdab void 55638905Sborman tty_setecho(on) 557*46809Sdab int on; 55838905Sborman { 55938905Sborman #ifndef USE_TERMIO 56038905Sborman if (on) 56138905Sborman termbuf.sg.sg_flags |= ECHO|CRMOD; 56238905Sborman else 56338905Sborman termbuf.sg.sg_flags &= ~(ECHO|CRMOD); 56438905Sborman #else 56538905Sborman if (on) 56638905Sborman termbuf.c_lflag |= ECHO; 56738905Sborman else 56838905Sborman termbuf.c_lflag &= ~ECHO; 56938905Sborman #endif 57038905Sborman } 57138905Sborman 57238905Sborman #if defined(LINEMODE) && defined(KLUDGELINEMODE) 573*46809Sdab int 57438905Sborman tty_israw() 57538905Sborman { 57638905Sborman #ifndef USE_TERMIO 57738905Sborman return(termbuf.sg.sg_flags & RAW); 57838905Sborman #else 57938905Sborman return(!(termbuf.c_lflag & ICANON)); 58038905Sborman #endif 58138905Sborman } 58238905Sborman #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 58338905Sborman 584*46809Sdab void 58538905Sborman tty_binaryin(on) 586*46809Sdab int on; 58738905Sborman { 58838905Sborman #ifndef USE_TERMIO 58938905Sborman if (on) 59038905Sborman termbuf.lflags |= LPASS8; 59138905Sborman else 59238905Sborman termbuf.lflags &= ~LPASS8; 59338905Sborman #else 59438905Sborman if (on) { 595*46809Sdab termbuf.c_iflag &= ~ISTRIP; 59638905Sborman } else { 597*46809Sdab termbuf.c_iflag |= ISTRIP; 59838905Sborman } 59938905Sborman #endif 60038905Sborman } 60138905Sborman 602*46809Sdab void 60338905Sborman tty_binaryout(on) 604*46809Sdab int on; 60538905Sborman { 60638905Sborman #ifndef USE_TERMIO 60738905Sborman if (on) 60838905Sborman termbuf.lflags |= LLITOUT; 60938905Sborman else 61038905Sborman termbuf.lflags &= ~LLITOUT; 61138905Sborman #else 61238905Sborman if (on) { 61338905Sborman termbuf.c_cflag &= ~(CSIZE|PARENB); 61438905Sborman termbuf.c_cflag |= CS8; 61538905Sborman termbuf.c_oflag &= ~OPOST; 61638905Sborman } else { 61738905Sborman termbuf.c_cflag &= ~CSIZE; 61838905Sborman termbuf.c_cflag |= CS7|PARENB; 61938905Sborman termbuf.c_oflag |= OPOST; 62038905Sborman } 62138905Sborman #endif 62238905Sborman } 62338905Sborman 624*46809Sdab int 62538905Sborman tty_isbinaryin() 62638905Sborman { 62738905Sborman #ifndef USE_TERMIO 62838905Sborman return(termbuf.lflags & LPASS8); 62938905Sborman #else 63039503Sborman return(!(termbuf.c_iflag & ISTRIP)); 63138905Sborman #endif 63238905Sborman } 63338905Sborman 634*46809Sdab int 63538905Sborman tty_isbinaryout() 63638905Sborman { 63738905Sborman #ifndef USE_TERMIO 63838905Sborman return(termbuf.lflags & LLITOUT); 63938905Sborman #else 64039503Sborman return(!(termbuf.c_oflag&OPOST)); 64138905Sborman #endif 64238905Sborman } 64338905Sborman 64438905Sborman #ifdef LINEMODE 645*46809Sdab int 64638905Sborman tty_isediting() 64738905Sborman { 64838905Sborman #ifndef USE_TERMIO 64938905Sborman return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); 65038905Sborman #else 65138905Sborman return(termbuf.c_lflag & ICANON); 65238905Sborman #endif 65338905Sborman } 65438905Sborman 655*46809Sdab int 65638905Sborman tty_istrapsig() 65738905Sborman { 65838905Sborman #ifndef USE_TERMIO 65938905Sborman return(!(termbuf.sg.sg_flags&RAW)); 66038905Sborman #else 66138905Sborman return(termbuf.c_lflag & ISIG); 66238905Sborman #endif 66338905Sborman } 66438905Sborman 665*46809Sdab void 66638905Sborman tty_setedit(on) 667*46809Sdab int on; 66838905Sborman { 66938905Sborman #ifndef USE_TERMIO 67038905Sborman if (on) 67138905Sborman termbuf.sg.sg_flags &= ~CBREAK; 67238905Sborman else 67338905Sborman termbuf.sg.sg_flags |= CBREAK; 67438905Sborman #else 67538905Sborman if (on) 67638905Sborman termbuf.c_lflag |= ICANON; 67738905Sborman else 67838905Sborman termbuf.c_lflag &= ~ICANON; 67938905Sborman #endif 68038905Sborman } 68138905Sborman 682*46809Sdab void 68338905Sborman tty_setsig(on) 684*46809Sdab int on; 68538905Sborman { 68638905Sborman #ifndef USE_TERMIO 68738905Sborman if (on) 68838905Sborman ; 68938905Sborman #else 69038905Sborman if (on) 69138905Sborman termbuf.c_lflag |= ISIG; 69238905Sborman else 69338905Sborman termbuf.c_lflag &= ~ISIG; 69438905Sborman #endif 69538905Sborman } 69638905Sborman #endif /* LINEMODE */ 69738905Sborman 698*46809Sdab int 69944364Sborman tty_issofttab() 70044364Sborman { 70144364Sborman #ifndef USE_TERMIO 70244364Sborman return (termbuf.sg.sg_flags & XTABS); 70344364Sborman #else 70444364Sborman # ifdef OXTABS 70544364Sborman return (termbuf.c_oflag & OXTABS); 70644364Sborman # endif 70744364Sborman # ifdef TABDLY 70844364Sborman return ((termbuf.c_oflag & TABDLY) == TAB3); 70944364Sborman # endif 71044364Sborman #endif 71144364Sborman } 71244364Sborman 713*46809Sdab void 71444364Sborman tty_setsofttab(on) 715*46809Sdab int on; 71644364Sborman { 71744364Sborman #ifndef USE_TERMIO 71844364Sborman if (on) 71944364Sborman termbuf.sg.sg_flags |= XTABS; 72044364Sborman else 72144364Sborman termbuf.sg.sg_flags &= ~XTABS; 72244364Sborman #else 72344364Sborman if (on) { 72444364Sborman # ifdef OXTABS 72544364Sborman termbuf.c_oflag |= OXTABS; 72644364Sborman # endif 72744364Sborman # ifdef TABDLY 72844364Sborman termbuf.c_oflag &= ~TABDLY; 72944364Sborman termbuf.c_oflag |= TAB3; 73044364Sborman # endif 73144364Sborman } else { 73244364Sborman # ifdef OXTABS 73344364Sborman termbuf.c_oflag &= ~OXTABS; 73444364Sborman # endif 73544364Sborman # ifdef TABDLY 73644364Sborman termbuf.c_oflag &= ~TABDLY; 73744364Sborman termbuf.c_oflag |= TAB0; 73844364Sborman # endif 73944364Sborman } 74044364Sborman #endif 74144364Sborman } 74244364Sborman 743*46809Sdab int 74444364Sborman tty_islitecho() 74544364Sborman { 74644364Sborman #ifndef USE_TERMIO 747*46809Sdab return (!(termbuf.lflags & LCTLECH)); 74844364Sborman #else 74944364Sborman # ifdef ECHOCTL 75044364Sborman return (!(termbuf.c_lflag & ECHOCTL)); 75144364Sborman # endif 75244364Sborman # ifdef TCTLECH 75344364Sborman return (!(termbuf.c_lflag & TCTLECH)); 75444364Sborman # endif 75544364Sborman # if !defined(ECHOCTL) && !defined(TCTLECH) 75644364Sborman return (0); /* assumes ctl chars are echoed '^x' */ 75744364Sborman # endif 75844364Sborman #endif 75944364Sborman } 76044364Sborman 761*46809Sdab void 76244364Sborman tty_setlitecho(on) 763*46809Sdab int on; 76444364Sborman { 76544364Sborman #ifndef USE_TERMIO 76644364Sborman if (on) 767*46809Sdab termbuf.lflags &= ~LCTLECH; 76844364Sborman else 769*46809Sdab termbuf.lflags |= LCTLECH; 77044364Sborman #else 77144364Sborman # ifdef ECHOCTL 77244364Sborman if (on) 77344364Sborman termbuf.c_lflag &= ~ECHOCTL; 77444364Sborman else 77544364Sborman termbuf.c_lflag |= ECHOCTL; 77644364Sborman # endif 77744364Sborman # ifdef TCTLECH 77844364Sborman if (on) 77944364Sborman termbuf.c_lflag &= ~TCTLECH; 78044364Sborman else 78144364Sborman termbuf.c_lflag |= TCTLECH; 78244364Sborman # endif 78344364Sborman #endif 78444364Sborman } 78544364Sborman 786*46809Sdab int 787*46809Sdab tty_iscrnl() 788*46809Sdab { 789*46809Sdab #ifndef USE_TERMIO 790*46809Sdab return (termbuf.sg.sg_flags & CRMOD); 791*46809Sdab #else 792*46809Sdab return (termbuf.c_iflag & ICRNL); 793*46809Sdab #endif 794*46809Sdab } 795*46809Sdab 79638905Sborman /* 79738905Sborman * A table of available terminal speeds 79838905Sborman */ 79938905Sborman struct termspeeds { 80038905Sborman int speed; 80138905Sborman int value; 80238905Sborman } termspeeds[] = { 80338905Sborman { 0, B0 }, { 50, B50 }, { 75, B75 }, 80438905Sborman { 110, B110 }, { 134, B134 }, { 150, B150 }, 80538905Sborman { 200, B200 }, { 300, B300 }, { 600, B600 }, 80638905Sborman { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 80738905Sborman { 4800, B4800 }, { 9600, B9600 }, { 19200, B9600 }, 80838905Sborman { 38400, B9600 }, { -1, B9600 } 80938905Sborman }; 81038905Sborman 811*46809Sdab void 81238905Sborman tty_tspeed(val) 813*46809Sdab int val; 81438905Sborman { 81538905Sborman register struct termspeeds *tp; 81638905Sborman 81738905Sborman for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 81838905Sborman ; 81945234Sborman cfsetospeed(&termbuf, tp->value); 82038905Sborman } 82138905Sborman 822*46809Sdab void 82338905Sborman tty_rspeed(val) 824*46809Sdab int val; 82538905Sborman { 82638905Sborman register struct termspeeds *tp; 82738905Sborman 82838905Sborman for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 82938905Sborman ; 83045234Sborman cfsetispeed(&termbuf, tp->value); 83138905Sborman } 83238905Sborman 83340242Sborman #if defined(CRAY2) && defined(UNICOS5) 834*46809Sdab int 83538905Sborman tty_isnewmap() 83638905Sborman { 83738905Sborman return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) && 83838905Sborman !(termbuf.c_oflag & ONLRET)); 83938905Sborman } 84038905Sborman #endif 84138905Sborman 84238905Sborman #ifdef CRAY 84338905Sborman # ifndef NEWINIT 84438905Sborman extern struct utmp wtmp; 84538905Sborman extern char wtmpf[]; 84638905Sborman # else /* NEWINIT */ 84738905Sborman int gotalarm; 848*46809Sdab 849*46809Sdab /* ARGSUSED */ 850*46809Sdab void 85140242Sborman nologinproc(sig) 852*46809Sdab int sig; 85338905Sborman { 85438905Sborman gotalarm++; 85538905Sborman } 85638905Sborman # endif /* NEWINIT */ 85738905Sborman #endif /* CRAY */ 85838905Sborman 859*46809Sdab #ifndef NEWINIT 860*46809Sdab # ifdef CRAY 861*46809Sdab extern void utmp_sig_init P((void)); 862*46809Sdab extern void utmp_sig_reset P((void)); 863*46809Sdab extern void utmp_sig_wait P((void)); 864*46809Sdab extern void utmp_sig_notify P((int)); 865*46809Sdab # endif 866*46809Sdab #endif 867*46809Sdab 86838905Sborman /* 86938905Sborman * getptyslave() 87038905Sborman * 87138905Sborman * Open the slave side of the pty, and do any initialization 87238905Sborman * that is necessary. The return value is a file descriptor 87338905Sborman * for the slave side. 87438905Sborman */ 875*46809Sdab int 87638905Sborman getptyslave() 87738905Sborman { 87838905Sborman register int t = -1; 87938905Sborman 88045234Sborman #if !defined(CRAY) || !defined(NEWINIT) 88145234Sborman # ifdef LINEMODE 882*46809Sdab int waslm; 883*46809Sdab # endif 884*46809Sdab # ifdef TIOCGWINSZ 885*46809Sdab struct winsize ws; 886*46809Sdab extern int def_row, def_col; 887*46809Sdab # endif 888*46809Sdab extern int def_tspeed, def_rspeed; 88938905Sborman /* 89045234Sborman * Opening the slave side may cause initilization of the 891*46809Sdab * kernel tty structure. We need remember the state of 892*46809Sdab * if linemode was turned on 893*46809Sdab * terminal window size 894*46809Sdab * terminal speed 895*46809Sdab * so that we can re-set them if we need to. 89638905Sborman */ 897*46809Sdab # ifdef LINEMODE 898*46809Sdab waslm = tty_linemode(); 89945234Sborman # endif 90045234Sborman 90145234Sborman 90245234Sborman /* 90345234Sborman * Make sure that we don't have a controlling tty, and 90445234Sborman * that we are the session (process group) leader. 90545234Sborman */ 90645234Sborman # ifdef TIOCNOTTY 90738905Sborman t = open(_PATH_TTY, O_RDWR); 90838905Sborman if (t >= 0) { 90938905Sborman (void) ioctl(t, TIOCNOTTY, (char *)0); 91038905Sborman (void) close(t); 91138905Sborman } 91245234Sborman # endif 91338905Sborman 91445234Sborman 91545234Sborman # ifdef CRAY 91645234Sborman /* 91745234Sborman * Wait for our parent to get the utmp stuff to get done. 91845234Sborman */ 91945234Sborman utmp_sig_wait(); 92045234Sborman # endif 92145234Sborman 92245234Sborman t = cleanopen(line); 92338905Sborman if (t < 0) 92438905Sborman fatalperror(net, line); 92538905Sborman 92645234Sborman /* 92745234Sborman * set up the tty modes as we like them to be. 92845234Sborman */ 92938905Sborman init_termbuf(); 930*46809Sdab # ifdef TIOCGWINSZ 931*46809Sdab if (def_row || def_col) { 932*46809Sdab bzero((char *)&ws, sizeof(ws)); 933*46809Sdab ws.ws_col = def_col; 934*46809Sdab ws.ws_row = def_row; 935*46809Sdab (void)ioctl(t, TIOCSWINSZ, (char *)&ws); 936*46809Sdab } 937*46809Sdab # endif 93845234Sborman 93945234Sborman /* 94045234Sborman * Settings for sgtty based systems 94145234Sborman */ 94245234Sborman # ifndef USE_TERMIO 94340242Sborman termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; 94445234Sborman # endif /* USE_TERMIO */ 94545234Sborman 94645234Sborman /* 94745234Sborman * Settings for UNICOS 94845234Sborman */ 94945234Sborman # ifdef CRAY 95045234Sborman termbuf.c_oflag = OPOST|ONLCR|TAB3; 95145234Sborman termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; 95245234Sborman termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; 95345234Sborman termbuf.c_cflag = EXTB|HUPCL|CS8; 95445234Sborman # endif 95545234Sborman 95645234Sborman /* 95745234Sborman * Settings for all other termios/termio based 95845234Sborman * systems, other than 4.4BSD. In 4.4BSD the 95945234Sborman * kernel does the initial terminal setup. 96045234Sborman */ 96145234Sborman # if defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) 96245234Sborman # ifndef OXTABS 96345234Sborman # define OXTABS 0 96445234Sborman # endif 96538905Sborman termbuf.c_lflag |= ECHO; 96638905Sborman termbuf.c_oflag |= ONLCR|OXTABS; 96738905Sborman termbuf.c_iflag |= ICRNL; 96838905Sborman termbuf.c_iflag &= ~IXOFF; 96945234Sborman # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */ 970*46809Sdab cfsetospeed(&termbuf, (def_tspeed == -1) ? B9600 : def_tspeed); 971*46809Sdab cfsetispeed(&termbuf, (def_rspeed == -1) ? B9600 : def_rspeed); 972*46809Sdab # ifdef LINEMODE 973*46809Sdab if (waslm) 974*46809Sdab tty_setlinemode(1); 975*46809Sdab # endif /* LINEMODE */ 97645234Sborman 97745234Sborman /* 97845234Sborman * Set the tty modes, and make this our controlling tty. 97945234Sborman */ 98045234Sborman set_termbuf(); 98145234Sborman if (login_tty(t) == -1) 98245234Sborman fatalperror(net, "login_tty"); 98345234Sborman #endif /* !defined(CRAY) || !defined(NEWINIT) */ 98445234Sborman if (net > 2) 98545234Sborman (void) close(net); 98645234Sborman if (pty > 2) 98745234Sborman (void) close(pty); 98845234Sborman } 98945234Sborman 99045234Sborman #if !defined(CRAY) || !defined(NEWINIT) 99145234Sborman #ifndef O_NOCTTY 99245234Sborman #define O_NOCTTY 0 99338905Sborman #endif 99445234Sborman /* 99545234Sborman * Open the specified slave side of the pty, 99645234Sborman * making sure that we have a clean tty. 99745234Sborman */ 998*46809Sdab int 99945234Sborman cleanopen(line) 1000*46809Sdab char *line; 100145234Sborman { 100245234Sborman register int t; 100345234Sborman 100445234Sborman /* 100545234Sborman * Make sure that other people can't open the 100645234Sborman * slave side of the connection. 100745234Sborman */ 100838905Sborman (void) chown(line, 0, 0); 100938905Sborman (void) chmod(line, 0600); 101045234Sborman 101145234Sborman # if !defined(CRAY) && (BSD > 43) 101245234Sborman (void) revoke(line); 101345234Sborman # endif 101445234Sborman t = open(line, O_RDWR|O_NOCTTY); 101545234Sborman if (t < 0) 101645234Sborman return(-1); 101745234Sborman 101845234Sborman /* 101945234Sborman * Hangup anybody else using this ttyp, then reopen it for 102045234Sborman * ourselves. 102145234Sborman */ 102245234Sborman # if !defined(CRAY) && (BSD <= 43) 102345234Sborman (void) signal(SIGHUP, SIG_IGN); 102445234Sborman vhangup(); 102545234Sborman (void) signal(SIGHUP, SIG_DFL); 102645234Sborman t = open(line, O_RDWR|O_NOCTTY); 102745234Sborman if (t < 0) 102845234Sborman return(-1); 102945234Sborman # endif 103045234Sborman # if defined(CRAY) && defined(TCVHUP) 103145234Sborman { 103245234Sborman register int i; 103345234Sborman (void) signal(SIGHUP, SIG_IGN); 103445234Sborman (void) ioctl(t, TCVHUP, (char *)0); 103545234Sborman (void) signal(SIGHUP, SIG_DFL); 103645234Sborman setpgrp(); 103745234Sborman i = open(line, O_RDWR); 103845234Sborman if (i < 0) 1039*46809Sdab return(-1); 104045234Sborman (void) close(t); 104145234Sborman t = i; 104245234Sborman } 104345234Sborman # endif /* defined(CRAY) && defined(TCVHUP) */ 104438905Sborman return(t); 104538905Sborman } 104645234Sborman #endif /* !defined(CRAY) || !defined(NEWINIT) */ 104738905Sborman 104845234Sborman #if BSD <= 43 1049*46809Sdab int 105045234Sborman login_tty(t) 1051*46809Sdab int t; 105245234Sborman { 105345234Sborman if (setsid() < 0) 105445234Sborman fatalperror(net, "setsid()"); 105545234Sborman # ifdef TIOCSCTTY 105645234Sborman if (ioctl(t, TIOCSCTTY, (char *)0) < 0) 105745234Sborman fatalperror(net, "ioctl(sctty)"); 105845234Sborman # else 105945234Sborman close(open(line, O_RDWR)); 106045234Sborman # endif 106145234Sborman (void) dup2(t, 0); 106245234Sborman (void) dup2(t, 1); 106345234Sborman (void) dup2(t, 2); 106445234Sborman close(t); 1065*46809Sdab return(0); 106645234Sborman } 106745234Sborman #endif /* BSD <= 43 */ 106845234Sborman 106938905Sborman #ifdef NEWINIT 107038905Sborman char *gen_id = "fe"; 107138905Sborman #endif 107238905Sborman 107338905Sborman /* 107445234Sborman * startslave(host) 107538905Sborman * 107645234Sborman * Given a hostname, do whatever 107738905Sborman * is necessary to startup the login process on the slave side of the pty. 107838905Sborman */ 107938905Sborman 108038905Sborman /* ARGSUSED */ 1081*46809Sdab void 1082*46809Sdab startslave(host, autologin, autoname) 1083*46809Sdab char *host; 1084*46809Sdab int autologin; 1085*46809Sdab char *autoname; 108638905Sborman { 108738905Sborman register int i; 108838905Sborman long time(); 1089*46809Sdab char name[256]; 1090*46809Sdab #ifdef NEWINIT 1091*46809Sdab extern char *ptyip; 1092*46809Sdab struct init_request request; 1093*46809Sdab void nologinproc(); 1094*46809Sdab register int n; 1095*46809Sdab #endif /* NEWINIT */ 109638905Sborman 1097*46809Sdab #if defined(AUTHENTICATE) 1098*46809Sdab if (!autoname || !autoname[0]) 1099*46809Sdab autologin = 0; 1100*46809Sdab 1101*46809Sdab if (autologin < auth_level) { 1102*46809Sdab fatal(net, "Authorization failed"); 1103*46809Sdab exit(1); 1104*46809Sdab } 1105*46809Sdab #endif 1106*46809Sdab 110738905Sborman #ifndef NEWINIT 110838905Sborman # ifdef CRAY 110938905Sborman utmp_sig_init(); 111038905Sborman # endif /* CRAY */ 111138905Sborman 111238905Sborman if ((i = fork()) < 0) 111338905Sborman fatalperror(net, "fork"); 111438905Sborman if (i) { 111538905Sborman # ifdef CRAY 111638905Sborman /* 111738905Sborman * Cray parent will create utmp entry for child and send 111838905Sborman * signal to child to tell when done. Child waits for signal 111938905Sborman * before doing anything important. 112038905Sborman */ 112138905Sborman register int pid = i; 1122*46809Sdab void sigjob P((int)); 112338905Sborman 112438905Sborman setpgrp(); 112544364Sborman utmp_sig_reset(); /* reset handler to default */ 112638905Sborman /* 112738905Sborman * Create utmp entry for child 112838905Sborman */ 112938905Sborman (void) time(&wtmp.ut_time); 113038905Sborman wtmp.ut_type = LOGIN_PROCESS; 113138905Sborman wtmp.ut_pid = pid; 113238905Sborman SCPYN(wtmp.ut_user, "LOGIN"); 113338905Sborman SCPYN(wtmp.ut_host, host); 113438905Sborman SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); 113538905Sborman SCPYN(wtmp.ut_id, wtmp.ut_line+3); 113638905Sborman pututline(&wtmp); 113738905Sborman endutent(); 113838905Sborman if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { 113938905Sborman (void) write(i, (char *)&wtmp, sizeof(struct utmp)); 114038905Sborman (void) close(i); 114138905Sborman } 1142*46809Sdab (void) signal(WJSIGNAL, sigjob); 114338905Sborman utmp_sig_notify(pid); 114438905Sborman # endif /* CRAY */ 114538905Sborman } else { 114645234Sborman getptyslave(); 1147*46809Sdab start_login(host, autologin, autoname); 114838905Sborman /*NOTREACHED*/ 114938905Sborman } 115038905Sborman #else /* NEWINIT */ 115138905Sborman 115238905Sborman /* 115338905Sborman * Init will start up login process if we ask nicely. We only wait 115438905Sborman * for it to start up and begin normal telnet operation. 115538905Sborman */ 115638905Sborman if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { 115738905Sborman char tbuf[128]; 115838905Sborman (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO); 115938905Sborman fatalperror(net, tbuf); 116038905Sborman } 116138905Sborman memset((char *)&request, 0, sizeof(request)); 116238905Sborman request.magic = INIT_MAGIC; 116338905Sborman SCPYN(request.gen_id, gen_id); 116438905Sborman SCPYN(request.tty_id, &line[8]); 116538905Sborman SCPYN(request.host, host); 1166*46809Sdab SCPYN(request.term_type, terminaltype ? terminaltype : "network"); 116744364Sborman #if !defined(UNICOS5) 116840242Sborman request.signal = SIGCLD; 116940242Sborman request.pid = getpid(); 117040242Sborman #endif 117144364Sborman #ifdef BFTPDAEMON 117244364Sborman /* 117344364Sborman * Are we working as the bftp daemon? 117444364Sborman */ 117544364Sborman if (bftpd) { 117644364Sborman SCPYN(request.exec_name, BFTPPATH); 117744364Sborman } 117844364Sborman #endif /* BFTPDAEMON */ 117938905Sborman if (write(i, (char *)&request, sizeof(request)) < 0) { 118038905Sborman char tbuf[128]; 118138905Sborman (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO); 118238905Sborman fatalperror(net, tbuf); 118338905Sborman } 118438905Sborman (void) close(i); 118538905Sborman (void) signal(SIGALRM, nologinproc); 118638905Sborman for (i = 0; ; i++) { 118740242Sborman char tbuf[128]; 118838905Sborman alarm(15); 118938905Sborman n = read(pty, ptyip, BUFSIZ); 119038905Sborman if (i == 3 || n >= 0 || !gotalarm) 119138905Sborman break; 119238905Sborman gotalarm = 0; 119340242Sborman sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line); 119440242Sborman (void) write(net, tbuf, strlen(tbuf)); 119538905Sborman } 119638905Sborman if (n < 0 && gotalarm) 119738905Sborman fatal(net, "/etc/init didn't start login process"); 119838905Sborman pcc += n; 119938905Sborman alarm(0); 120038905Sborman (void) signal(SIGALRM, SIG_DFL); 120138905Sborman 120238905Sborman return; 120338905Sborman #endif /* NEWINIT */ 120438905Sborman } 120538905Sborman 120638905Sborman char *envinit[3]; 120744364Sborman extern char **environ; 120838905Sborman 1209*46809Sdab void 121044364Sborman init_env() 121144364Sborman { 121244364Sborman extern char *getenv(); 121344364Sborman char **envp; 121444364Sborman 121544364Sborman envp = envinit; 121644364Sborman if (*envp = getenv("TZ")) 121744364Sborman *envp++ -= 3; 121844364Sborman #ifdef CRAY 121944364Sborman else 122044364Sborman *envp++ = "TZ=GMT0"; 122144364Sborman #endif 122244364Sborman *envp = 0; 122344364Sborman environ = envinit; 122444364Sborman } 122544364Sborman 122644364Sborman #ifndef NEWINIT 122744364Sborman 122844364Sborman /* 122945234Sborman * start_login(host) 123038905Sborman * 123138905Sborman * Assuming that we are now running as a child processes, this 123238905Sborman * function will turn us into the login process. 123338905Sborman */ 123438905Sborman 1235*46809Sdab void 1236*46809Sdab start_login(host, autologin, name) 1237*46809Sdab char *host; 1238*46809Sdab int autologin; 1239*46809Sdab char *name; 124038905Sborman { 124144364Sborman register char *cp; 124244364Sborman register char **argv; 124344364Sborman char **addarg(); 124438905Sborman 124538905Sborman /* 124638905Sborman * -h : pass on name of host. 124738905Sborman * WARNING: -h is accepted by login if and only if 124838905Sborman * getuid() == 0. 124938905Sborman * -p : don't clobber the environment (so terminal type stays set). 1250*46809Sdab * 1251*46809Sdab * -f : force this login, he has already been authenticated 125238905Sborman */ 125344364Sborman argv = addarg(0, "login"); 125444364Sborman argv = addarg(argv, "-h"); 125544364Sborman argv = addarg(argv, host); 1256*46809Sdab #if !defined(NO_LOGIN_P) 125744364Sborman argv = addarg(argv, "-p"); 125838905Sborman #endif 125944364Sborman #ifdef BFTPDAEMON 126044364Sborman /* 126144364Sborman * Are we working as the bftp daemon? If so, then ask login 126244364Sborman * to start bftp instead of shell. 126344364Sborman */ 126444364Sborman if (bftpd) { 126544364Sborman argv = addarg(argv, "-e"); 126644364Sborman argv = addarg(argv, BFTPPATH); 126744364Sborman } else 126844364Sborman #endif 1269*46809Sdab #if defined (SecurID) 1270*46809Sdab /* 1271*46809Sdab * don't worry about the -f that might get sent. 1272*46809Sdab * A -s is supposed to override it anyhow. 1273*46809Sdab */ 1274*46809Sdab if (require_SecurID) 1275*46809Sdab argv = addarg(argv, "-s"); 1276*46809Sdab #endif 1277*46809Sdab #if defined (AUTHENTICATE) 1278*46809Sdab if (auth_level >= 0 && autologin == AUTH_VALID) { 1279*46809Sdab # if !defined(NO_LOGIN_F) 1280*46809Sdab argv = addarg(argv, "-f"); 1281*46809Sdab # endif 1282*46809Sdab argv = addarg(argv, name); 1283*46809Sdab } else 1284*46809Sdab #endif 128544364Sborman if (getenv("USER")) { 128644364Sborman argv = addarg(argv, getenv("USER")); 1287*46809Sdab #if defined(CRAY) && defined(NO_LOGIN_P) 1288*46809Sdab { 1289*46809Sdab register char **cpp; 1290*46809Sdab for (cpp = environ; *cpp; cpp++) 1291*46809Sdab argv = addarg(argv, *cpp); 1292*46809Sdab } 1293*46809Sdab #endif 129444364Sborman } 1295*46809Sdab closelog(); 129644364Sborman execv(_PATH_LOGIN, argv); 129744364Sborman 129838905Sborman syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN); 129938905Sborman fatalperror(net, _PATH_LOGIN); 130038905Sborman /*NOTREACHED*/ 130138905Sborman } 130244364Sborman 1303*46809Sdab char ** 130444364Sborman addarg(argv, val) 1305*46809Sdab register char **argv; 1306*46809Sdab register char *val; 130744364Sborman { 130844364Sborman register char **cpp; 130944364Sborman 131044364Sborman if (argv == NULL) { 131144364Sborman /* 131244364Sborman * 10 entries, a leading length, and a null 131344364Sborman */ 131444364Sborman argv = (char **)malloc(sizeof(*argv) * 12); 131544364Sborman if (argv == NULL) 131644364Sborman return(NULL); 131744364Sborman *argv++ = (char *)10; 131844364Sborman *argv = (char *)0; 131944364Sborman } 132044364Sborman for (cpp = argv; *cpp; cpp++) 132144364Sborman ; 132244364Sborman if (cpp == &argv[(int)argv[-1]]) { 132344364Sborman --argv; 132444364Sborman *argv = (char *)((int)(*argv) + 10); 132544364Sborman argv = (char **)realloc(argv, (int)(*argv) + 2); 132644364Sborman if (argv == NULL) 132744364Sborman return(NULL); 132844364Sborman argv++; 132944364Sborman cpp = &argv[(int)argv[-1] - 10]; 133044364Sborman } 133144364Sborman *cpp++ = val; 133244364Sborman *cpp = 0; 133344364Sborman return(argv); 133444364Sborman } 1335*46809Sdab #endif /* NEWINIT */ 133638905Sborman 133738905Sborman /* 133838905Sborman * cleanup() 133938905Sborman * 134038905Sborman * This is the routine to call when we are all through, to 134138905Sborman * clean up anything that needs to be cleaned up. 134238905Sborman */ 1343*46809Sdab /* ARGSUSED */ 1344*46809Sdab void 1345*46809Sdab cleanup(sig) 1346*46809Sdab int sig; 134738905Sborman { 134838905Sborman #ifndef CRAY 134945234Sborman # if (BSD > 43) || defined(convex) 135038905Sborman char *p; 135138905Sborman 135238905Sborman p = line + sizeof("/dev/") - 1; 135338905Sborman if (logout(p)) 135438905Sborman logwtmp(p, "", ""); 135538905Sborman (void)chmod(line, 0666); 135638905Sborman (void)chown(line, 0, 0); 135738905Sborman *p = 'p'; 135838905Sborman (void)chmod(line, 0666); 135938905Sborman (void)chown(line, 0, 0); 1360*46809Sdab (void) shutdown(net, 2); 1361*46809Sdab exit(1); 136238905Sborman # else 1363*46809Sdab void rmut(); 1364*46809Sdab 136538905Sborman rmut(); 136638905Sborman vhangup(); /* XXX */ 1367*46809Sdab (void) shutdown(net, 2); 1368*46809Sdab exit(1); 136938905Sborman # endif 137038905Sborman #else /* CRAY */ 1371*46809Sdab # ifdef NEWINIT 137238905Sborman (void) shutdown(net, 2); 1373*46809Sdab exit(1); 137438905Sborman # else /* NEWINIT */ 1375*46809Sdab static int incleanup = 0; 1376*46809Sdab register int t; 1377*46809Sdab 1378*46809Sdab /* 1379*46809Sdab * 1: Pick up the zombie, if we are being called 1380*46809Sdab * as the signal handler. 1381*46809Sdab * 2: If we are a nested cleanup(), return. 1382*46809Sdab * 3: Try to clean up TMPDIR. 1383*46809Sdab * 4: Fill in utmp with shutdown of process. 1384*46809Sdab * 5: Close down the network and pty connections. 1385*46809Sdab * 6: Finish up the TMPDIR cleanup, if needed. 1386*46809Sdab */ 1387*46809Sdab if (sig == SIGCHLD) 1388*46809Sdab while (waitpid(-1, 0, WNOHANG) > 0) 1389*46809Sdab ; /* VOID */ 1390*46809Sdab t = sigblock(sigmask(SIGCHLD)); 1391*46809Sdab if (incleanup) { 1392*46809Sdab sigsetmask(t); 1393*46809Sdab return; 1394*46809Sdab } 1395*46809Sdab incleanup = 1; 1396*46809Sdab sigsetmask(t); 1397*46809Sdab 1398*46809Sdab t = cleantmp(&wtmp); 1399*46809Sdab setutent(); /* just to make sure */ 1400*46809Sdab rmut(line); 1401*46809Sdab close(pty); 140238905Sborman (void) shutdown(net, 2); 1403*46809Sdab if (t == 0) 1404*46809Sdab cleantmp(&wtmp); 1405*46809Sdab exit(1); 140638905Sborman # endif /* NEWINT */ 140738905Sborman #endif /* CRAY */ 140838905Sborman } 140938905Sborman 141038905Sborman #if defined(CRAY) && !defined(NEWINIT) 141138905Sborman /* 141238905Sborman * _utmp_sig_rcv 141338905Sborman * utmp_sig_init 141438905Sborman * utmp_sig_wait 141538905Sborman * These three functions are used to coordinate the handling of 141638905Sborman * the utmp file between the server and the soon-to-be-login shell. 141738905Sborman * The server actually creates the utmp structure, the child calls 141838905Sborman * utmp_sig_wait(), until the server calls utmp_sig_notify() and 141938905Sborman * signals the future-login shell to proceed. 142038905Sborman */ 142138905Sborman static int caught=0; /* NZ when signal intercepted */ 142238905Sborman static void (*func)(); /* address of previous handler */ 142338905Sborman 1424*46809Sdab void 142538905Sborman _utmp_sig_rcv(sig) 1426*46809Sdab int sig; 142738905Sborman { 142838905Sborman caught = 1; 142938905Sborman (void) signal(SIGUSR1, func); 143038905Sborman } 143138905Sborman 1432*46809Sdab void 143338905Sborman utmp_sig_init() 143438905Sborman { 143538905Sborman /* 143638905Sborman * register signal handler for UTMP creation 143738905Sborman */ 143838905Sborman if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) 143938905Sborman fatalperror(net, "telnetd/signal"); 144038905Sborman } 144138905Sborman 1442*46809Sdab void 144344364Sborman utmp_sig_reset() 144444364Sborman { 144544364Sborman (void) signal(SIGUSR1, func); /* reset handler to default */ 144644364Sborman } 144744364Sborman 1448*46809Sdab void 144938905Sborman utmp_sig_wait() 145038905Sborman { 145138905Sborman /* 145238905Sborman * Wait for parent to write our utmp entry. 145338905Sborman */ 145438905Sborman sigoff(); 145538905Sborman while (caught == 0) { 145638905Sborman pause(); /* wait until we get a signal (sigon) */ 145738905Sborman sigoff(); /* turn off signals while we check caught */ 145838905Sborman } 145938905Sborman sigon(); /* turn on signals again */ 146038905Sborman } 146138905Sborman 1462*46809Sdab void 146338905Sborman utmp_sig_notify(pid) 146438905Sborman { 146538905Sborman kill(pid, SIGUSR1); 146638905Sborman } 1467*46809Sdab 1468*46809Sdab static int gotsigjob = 0; 1469*46809Sdab 1470*46809Sdab /*ARGSUSED*/ 1471*46809Sdab void 1472*46809Sdab sigjob(sig) 1473*46809Sdab int sig; 1474*46809Sdab { 1475*46809Sdab register int jid; 1476*46809Sdab register struct jobtemp *jp; 1477*46809Sdab 1478*46809Sdab while ((jid = waitjob(NULL)) != -1) { 1479*46809Sdab if (jid == 0) { 1480*46809Sdab return; 1481*46809Sdab } 1482*46809Sdab gotsigjob++; 1483*46809Sdab jobend(jid, NULL, NULL); 1484*46809Sdab } 1485*46809Sdab } 1486*46809Sdab 1487*46809Sdab /* 1488*46809Sdab * Clean up the TMPDIR that login created. 1489*46809Sdab * The first time this is called we pick up the info 1490*46809Sdab * from the utmp. If the job has already gone away, 1491*46809Sdab * then we'll clean up and be done. If not, then 1492*46809Sdab * when this is called the second time it will wait 1493*46809Sdab * for the signal that the job is done. 1494*46809Sdab */ 1495*46809Sdab int 1496*46809Sdab cleantmp(wtp) 1497*46809Sdab register struct utmp *wtp; 1498*46809Sdab { 1499*46809Sdab struct utmp *utp; 1500*46809Sdab static int first = 1; 1501*46809Sdab register int mask, omask, ret; 1502*46809Sdab extern struct utmp *getutid P((struct utmp *)); 1503*46809Sdab 1504*46809Sdab mask = sigmask(WJSIGNAL); 1505*46809Sdab 1506*46809Sdab if (first == 0) { 1507*46809Sdab omask = sigblock(mask); 1508*46809Sdab while (gotsigjob == 0) 1509*46809Sdab sigpause(omask); 1510*46809Sdab return(1); 1511*46809Sdab } 1512*46809Sdab first = 0; 1513*46809Sdab setutent(); /* just to make sure */ 1514*46809Sdab 1515*46809Sdab utp = getutid(wtp); 1516*46809Sdab if (utp == 0) { 1517*46809Sdab syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); 1518*46809Sdab return(-1); 1519*46809Sdab } 1520*46809Sdab /* 1521*46809Sdab * Nothing to clean up if the user shell was never started. 1522*46809Sdab */ 1523*46809Sdab if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) 1524*46809Sdab return(1); 1525*46809Sdab 1526*46809Sdab /* 1527*46809Sdab * Block the WJSIGNAL while we are in jobend(). 1528*46809Sdab */ 1529*46809Sdab omask = sigblock(mask); 1530*46809Sdab ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); 1531*46809Sdab sigsetmask(omask); 1532*46809Sdab return(ret); 1533*46809Sdab } 1534*46809Sdab 1535*46809Sdab int 1536*46809Sdab jobend(jid, path, user) 1537*46809Sdab register int jid; 1538*46809Sdab register char *path; 1539*46809Sdab register char *user; 1540*46809Sdab { 1541*46809Sdab static int saved_jid = 0; 1542*46809Sdab static char saved_path[sizeof(wtmp.ut_tpath)+1]; 1543*46809Sdab static char saved_user[sizeof(wtmp.ut_user)+1]; 1544*46809Sdab 1545*46809Sdab if (path) { 1546*46809Sdab strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); 1547*46809Sdab strncpy(saved_user, user, sizeof(wtmp.ut_user)); 1548*46809Sdab saved_path[sizeof(saved_path)] = '\0'; 1549*46809Sdab saved_user[sizeof(saved_user)] = '\0'; 1550*46809Sdab } 1551*46809Sdab if (saved_jid == 0) { 1552*46809Sdab saved_jid = jid; 1553*46809Sdab return(0); 1554*46809Sdab } 1555*46809Sdab cleantmpdir(jid, saved_path, saved_user); 1556*46809Sdab return(1); 1557*46809Sdab } 1558*46809Sdab 1559*46809Sdab /* 1560*46809Sdab * Fork a child process to clean up the TMPDIR 1561*46809Sdab */ 1562*46809Sdab cleantmpdir(jid, tpath, user) 1563*46809Sdab register int jid; 1564*46809Sdab register char *tpath; 1565*46809Sdab register char *user; 1566*46809Sdab { 1567*46809Sdab switch(fork()) { 1568*46809Sdab case -1: 1569*46809Sdab syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n", 1570*46809Sdab tpath); 1571*46809Sdab break; 1572*46809Sdab case 0: 1573*46809Sdab execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); 1574*46809Sdab syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", 1575*46809Sdab tpath, CLEANTMPCMD); 1576*46809Sdab exit(1); 1577*46809Sdab default: 1578*46809Sdab /* 1579*46809Sdab * Forget about child. We will exit, and 1580*46809Sdab * /etc/init will pick it up. 1581*46809Sdab */ 1582*46809Sdab break; 1583*46809Sdab } 1584*46809Sdab } 158538905Sborman #endif /* defined(CRAY) && !defined(NEWINIT) */ 158638905Sborman 158738905Sborman /* 158838905Sborman * rmut() 158938905Sborman * 159038905Sborman * This is the function called by cleanup() to 159138905Sborman * remove the utmp entry for this person. 159238905Sborman */ 159338905Sborman 159438905Sborman #if !defined(CRAY) && BSD <= 43 1595*46809Sdab void 159638905Sborman rmut() 159738905Sborman { 159838905Sborman register f; 159938905Sborman int found = 0; 160038905Sborman struct utmp *u, *utmp; 160138905Sborman int nutmp; 160238905Sborman struct stat statbf; 160338905Sborman 160438905Sborman f = open(utmpf, O_RDWR); 160538905Sborman if (f >= 0) { 160638905Sborman (void) fstat(f, &statbf); 160738905Sborman utmp = (struct utmp *)malloc((unsigned)statbf.st_size); 160838905Sborman if (!utmp) 160938905Sborman syslog(LOG_ERR, "utmp malloc failed"); 161038905Sborman if (statbf.st_size && utmp) { 161138905Sborman nutmp = read(f, (char *)utmp, (int)statbf.st_size); 161238905Sborman nutmp /= sizeof(struct utmp); 161338905Sborman 161438905Sborman for (u = utmp ; u < &utmp[nutmp] ; u++) { 161538905Sborman if (SCMPN(u->ut_line, line+5) || 161638905Sborman u->ut_name[0]==0) 161738905Sborman continue; 161838905Sborman (void) lseek(f, ((long)u)-((long)utmp), L_SET); 161938905Sborman SCPYN(u->ut_name, ""); 162038905Sborman SCPYN(u->ut_host, ""); 162138905Sborman (void) time(&u->ut_time); 162238905Sborman (void) write(f, (char *)u, sizeof(wtmp)); 162338905Sborman found++; 162438905Sborman } 162538905Sborman } 162638905Sborman (void) close(f); 162738905Sborman } 162838905Sborman if (found) { 162938905Sborman f = open(wtmpf, O_WRONLY|O_APPEND); 163038905Sborman if (f >= 0) { 163138905Sborman SCPYN(wtmp.ut_line, line+5); 163238905Sborman SCPYN(wtmp.ut_name, ""); 163338905Sborman SCPYN(wtmp.ut_host, ""); 163438905Sborman (void) time(&wtmp.ut_time); 163538905Sborman (void) write(f, (char *)&wtmp, sizeof(wtmp)); 163638905Sborman (void) close(f); 163738905Sborman } 163838905Sborman } 163938905Sborman (void) chmod(line, 0666); 164038905Sborman (void) chown(line, 0, 0); 164138905Sborman line[strlen("/dev/")] = 'p'; 164238905Sborman (void) chmod(line, 0666); 164338905Sborman (void) chown(line, 0, 0); 164438905Sborman } /* end of rmut */ 164538905Sborman #endif /* CRAY */ 1646