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*47613Sdab static char sccsid[] = "@(#)sys_term.c 5.16 (Berkeley) 03/22/91"; 1038905Sborman #endif /* not lint */ 1138905Sborman 1238905Sborman #include "telnetd.h" 1338905Sborman #include "pathnames.h" 1438905Sborman 1546809Sdab #if defined(AUTHENTICATE) 1646809Sdab #include <libtelnet/auth.h> 1746809Sdab #endif 1846809Sdab 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"; 3046809Sdab #include <tmpdir.h> 3146809Sdab #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) 7346809Sdab # define cfgetospeed(tp) (tp)->sg.sg_ospeed 7446809Sdab # 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 8346809Sdab # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) 8444364Sborman # else 8545234Sborman # ifdef TCSETA 8645234Sborman # define TCSANOW TCSETA 8745234Sborman # define TCSADRAIN TCSETAW 8846809Sdab # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) 8945234Sborman # else 9045234Sborman # define TCSANOW TIOCSETA 9145234Sborman # define TCSADRAIN TIOCSETAW 9246809Sdab # 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) 9846809Sdab # 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) 10246809Sdab # define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT) 10345234Sborman # else 10445234Sborman # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 10545234Sborman (tp)->c_cflag |= (val) 10646809Sdab # 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 12346809Sdab 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) 14046809Sdab void 14138905Sborman copy_termbuf(cp, len) 14246809Sdab char *cp; 14346809Sdab 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 15246809Sdab 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))) 17046809Sdab (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 19046809Sdab int 19138905Sborman spcset(func, valp, valpp) 19246809Sdab int func; 19346809Sdab cc_t *valp; 19446809Sdab 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 26546809Sdab int 26638905Sborman spcset(func, valp, valpp) 26746809Sdab int func; 26846809Sdab cc_t *valp; 26946809Sdab 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 */ 36746809Sdab int 36840242Sborman getnpty() 36940242Sborman { 37040242Sborman #ifdef _SC_CRAY_NPTY 37146809Sdab int numptys; 37246809Sdab 37346809Sdab if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) 37446809Sdab return numptys; 37546809Sdab else 37640242Sborman #endif /* _SC_CRAY_NPTY */ 37746809Sdab 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 40046809Sdab 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 49246809Sdab int 49338905Sborman tty_flowmode() 49438905Sborman { 49538905Sborman #ifndef USE_TERMIO 49646809Sdab 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 50646809Sdab 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 52046809Sdab void 52138905Sborman tty_setlinemode(on) 52246809Sdab 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 54446809Sdab 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 55546809Sdab void 55638905Sborman tty_setecho(on) 55746809Sdab 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) 57346809Sdab 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 58446809Sdab void 58538905Sborman tty_binaryin(on) 58646809Sdab 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) { 59546809Sdab termbuf.c_iflag &= ~ISTRIP; 59638905Sborman } else { 59746809Sdab termbuf.c_iflag |= ISTRIP; 59838905Sborman } 59938905Sborman #endif 60038905Sborman } 60138905Sborman 60246809Sdab void 60338905Sborman tty_binaryout(on) 60446809Sdab 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 62446809Sdab 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 63446809Sdab 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 64546809Sdab 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 65546809Sdab 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 66546809Sdab void 66638905Sborman tty_setedit(on) 66746809Sdab 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 68246809Sdab void 68338905Sborman tty_setsig(on) 68446809Sdab 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 69846809Sdab 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 71346809Sdab void 71444364Sborman tty_setsofttab(on) 71546809Sdab 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 74346809Sdab int 74444364Sborman tty_islitecho() 74544364Sborman { 74644364Sborman #ifndef USE_TERMIO 74746809Sdab 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 76146809Sdab void 76244364Sborman tty_setlitecho(on) 76346809Sdab int on; 76444364Sborman { 76544364Sborman #ifndef USE_TERMIO 76644364Sborman if (on) 76746809Sdab termbuf.lflags &= ~LCTLECH; 76844364Sborman else 76946809Sdab 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 78646809Sdab int 78746809Sdab tty_iscrnl() 78846809Sdab { 78946809Sdab #ifndef USE_TERMIO 79046809Sdab return (termbuf.sg.sg_flags & CRMOD); 79146809Sdab #else 79246809Sdab return (termbuf.c_iflag & ICRNL); 79346809Sdab #endif 79446809Sdab } 79546809Sdab 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 81146809Sdab void 81238905Sborman tty_tspeed(val) 81346809Sdab 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 82246809Sdab void 82338905Sborman tty_rspeed(val) 82446809Sdab 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) 83446809Sdab 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; 84846809Sdab 84946809Sdab /* ARGSUSED */ 85046809Sdab void 85140242Sborman nologinproc(sig) 85246809Sdab int sig; 85338905Sborman { 85438905Sborman gotalarm++; 85538905Sborman } 85638905Sborman # endif /* NEWINIT */ 85738905Sborman #endif /* CRAY */ 85838905Sborman 85946809Sdab #ifndef NEWINIT 86046809Sdab # ifdef CRAY 86146809Sdab extern void utmp_sig_init P((void)); 86246809Sdab extern void utmp_sig_reset P((void)); 86346809Sdab extern void utmp_sig_wait P((void)); 86446809Sdab extern void utmp_sig_notify P((int)); 86546809Sdab # endif 86646809Sdab #endif 86746809Sdab 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 */ 87546809Sdab int 87638905Sborman getptyslave() 87738905Sborman { 87838905Sborman register int t = -1; 87938905Sborman 88045234Sborman #if !defined(CRAY) || !defined(NEWINIT) 88145234Sborman # ifdef LINEMODE 88246809Sdab int waslm; 88346809Sdab # endif 88446809Sdab # ifdef TIOCGWINSZ 88546809Sdab struct winsize ws; 88646809Sdab extern int def_row, def_col; 88746809Sdab # endif 88846809Sdab extern int def_tspeed, def_rspeed; 88938905Sborman /* 89045234Sborman * Opening the slave side may cause initilization of the 89146809Sdab * kernel tty structure. We need remember the state of 89246809Sdab * if linemode was turned on 89346809Sdab * terminal window size 89446809Sdab * terminal speed 89546809Sdab * so that we can re-set them if we need to. 89638905Sborman */ 89746809Sdab # ifdef LINEMODE 89846809Sdab 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(); 93046809Sdab # ifdef TIOCGWINSZ 93146809Sdab if (def_row || def_col) { 93246809Sdab bzero((char *)&ws, sizeof(ws)); 93346809Sdab ws.ws_col = def_col; 93446809Sdab ws.ws_row = def_row; 93546809Sdab (void)ioctl(t, TIOCSWINSZ, (char *)&ws); 93646809Sdab } 93746809Sdab # 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) */ 97046996Sdab tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); 97146996Sdab tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); 97246809Sdab # ifdef LINEMODE 97346809Sdab if (waslm) 97446809Sdab tty_setlinemode(1); 97546809Sdab # 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 */ 99846809Sdab int 99945234Sborman cleanopen(line) 100046809Sdab 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) 103946809Sdab 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 104946809Sdab int 105045234Sborman login_tty(t) 105146809Sdab 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)"); 1058*47613Sdab # if defined(CRAY) && defined(SESS_CTTY) /* SESS_CTTY is in param.h */ 1059*47613Sdab /* 1060*47613Sdab * Close the hard fd to /dev/ttypXXX, and re-open through 1061*47613Sdab * the indirect /dev/tty interface. 1062*47613Sdab */ 1063*47613Sdab close(t); 1064*47613Sdab if ((t = open("/dev/tty", O_RDWR)) < 0) 1065*47613Sdab fatalperror(net, "open(/dev/tty)"); 1066*47613Sdab # endif 106745234Sborman # else 106845234Sborman close(open(line, O_RDWR)); 106945234Sborman # endif 1070*47613Sdab if (t != 0) 1071*47613Sdab (void) dup2(t, 0); 1072*47613Sdab if (t != 1) 1073*47613Sdab (void) dup2(t, 1); 1074*47613Sdab if (t != 2) 1075*47613Sdab (void) dup2(t, 2); 1076*47613Sdab if (t > 2) 1077*47613Sdab close(t); 107846809Sdab return(0); 107945234Sborman } 108045234Sborman #endif /* BSD <= 43 */ 108145234Sborman 108238905Sborman #ifdef NEWINIT 108338905Sborman char *gen_id = "fe"; 108438905Sborman #endif 108538905Sborman 108638905Sborman /* 108745234Sborman * startslave(host) 108838905Sborman * 108945234Sborman * Given a hostname, do whatever 109038905Sborman * is necessary to startup the login process on the slave side of the pty. 109138905Sborman */ 109238905Sborman 109338905Sborman /* ARGSUSED */ 109446809Sdab void 109546809Sdab startslave(host, autologin, autoname) 109646809Sdab char *host; 109746809Sdab int autologin; 109846809Sdab char *autoname; 109938905Sborman { 110038905Sborman register int i; 110138905Sborman long time(); 110246809Sdab char name[256]; 110346809Sdab #ifdef NEWINIT 110446809Sdab extern char *ptyip; 110546809Sdab struct init_request request; 110646809Sdab void nologinproc(); 110746809Sdab register int n; 110846809Sdab #endif /* NEWINIT */ 110938905Sborman 111046809Sdab #if defined(AUTHENTICATE) 111146809Sdab if (!autoname || !autoname[0]) 111246809Sdab autologin = 0; 111346809Sdab 111446809Sdab if (autologin < auth_level) { 111546809Sdab fatal(net, "Authorization failed"); 111646809Sdab exit(1); 111746809Sdab } 111846809Sdab #endif 111946809Sdab 112038905Sborman #ifndef NEWINIT 112138905Sborman # ifdef CRAY 112238905Sborman utmp_sig_init(); 112338905Sborman # endif /* CRAY */ 112438905Sborman 112538905Sborman if ((i = fork()) < 0) 112638905Sborman fatalperror(net, "fork"); 112738905Sborman if (i) { 112838905Sborman # ifdef CRAY 112938905Sborman /* 113038905Sborman * Cray parent will create utmp entry for child and send 113138905Sborman * signal to child to tell when done. Child waits for signal 113238905Sborman * before doing anything important. 113338905Sborman */ 113438905Sborman register int pid = i; 113546809Sdab void sigjob P((int)); 113638905Sborman 113738905Sborman setpgrp(); 113844364Sborman utmp_sig_reset(); /* reset handler to default */ 113938905Sborman /* 114038905Sborman * Create utmp entry for child 114138905Sborman */ 114238905Sborman (void) time(&wtmp.ut_time); 114338905Sborman wtmp.ut_type = LOGIN_PROCESS; 114438905Sborman wtmp.ut_pid = pid; 114538905Sborman SCPYN(wtmp.ut_user, "LOGIN"); 114638905Sborman SCPYN(wtmp.ut_host, host); 114738905Sborman SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); 114838905Sborman SCPYN(wtmp.ut_id, wtmp.ut_line+3); 114938905Sborman pututline(&wtmp); 115038905Sborman endutent(); 115138905Sborman if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { 115238905Sborman (void) write(i, (char *)&wtmp, sizeof(struct utmp)); 115338905Sborman (void) close(i); 115438905Sborman } 115546809Sdab (void) signal(WJSIGNAL, sigjob); 115638905Sborman utmp_sig_notify(pid); 115738905Sborman # endif /* CRAY */ 115838905Sborman } else { 115945234Sborman getptyslave(); 116046809Sdab start_login(host, autologin, autoname); 116138905Sborman /*NOTREACHED*/ 116238905Sborman } 116338905Sborman #else /* NEWINIT */ 116438905Sborman 116538905Sborman /* 116638905Sborman * Init will start up login process if we ask nicely. We only wait 116738905Sborman * for it to start up and begin normal telnet operation. 116838905Sborman */ 116938905Sborman if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { 117038905Sborman char tbuf[128]; 117138905Sborman (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO); 117238905Sborman fatalperror(net, tbuf); 117338905Sborman } 117438905Sborman memset((char *)&request, 0, sizeof(request)); 117538905Sborman request.magic = INIT_MAGIC; 117638905Sborman SCPYN(request.gen_id, gen_id); 117738905Sborman SCPYN(request.tty_id, &line[8]); 117838905Sborman SCPYN(request.host, host); 117946809Sdab SCPYN(request.term_type, terminaltype ? terminaltype : "network"); 118044364Sborman #if !defined(UNICOS5) 118140242Sborman request.signal = SIGCLD; 118240242Sborman request.pid = getpid(); 118340242Sborman #endif 118444364Sborman #ifdef BFTPDAEMON 118544364Sborman /* 118644364Sborman * Are we working as the bftp daemon? 118744364Sborman */ 118844364Sborman if (bftpd) { 118944364Sborman SCPYN(request.exec_name, BFTPPATH); 119044364Sborman } 119144364Sborman #endif /* BFTPDAEMON */ 119238905Sborman if (write(i, (char *)&request, sizeof(request)) < 0) { 119338905Sborman char tbuf[128]; 119438905Sborman (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO); 119538905Sborman fatalperror(net, tbuf); 119638905Sborman } 119738905Sborman (void) close(i); 119838905Sborman (void) signal(SIGALRM, nologinproc); 119938905Sborman for (i = 0; ; i++) { 120040242Sborman char tbuf[128]; 120138905Sborman alarm(15); 120238905Sborman n = read(pty, ptyip, BUFSIZ); 120338905Sborman if (i == 3 || n >= 0 || !gotalarm) 120438905Sborman break; 120538905Sborman gotalarm = 0; 120640242Sborman sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line); 120740242Sborman (void) write(net, tbuf, strlen(tbuf)); 120838905Sborman } 120938905Sborman if (n < 0 && gotalarm) 121038905Sborman fatal(net, "/etc/init didn't start login process"); 121138905Sborman pcc += n; 121238905Sborman alarm(0); 121338905Sborman (void) signal(SIGALRM, SIG_DFL); 121438905Sborman 121538905Sborman return; 121638905Sborman #endif /* NEWINIT */ 121738905Sborman } 121838905Sborman 121938905Sborman char *envinit[3]; 122044364Sborman extern char **environ; 122138905Sborman 122246809Sdab void 122344364Sborman init_env() 122444364Sborman { 122544364Sborman extern char *getenv(); 122644364Sborman char **envp; 122744364Sborman 122844364Sborman envp = envinit; 122944364Sborman if (*envp = getenv("TZ")) 123044364Sborman *envp++ -= 3; 123144364Sborman #ifdef CRAY 123244364Sborman else 123344364Sborman *envp++ = "TZ=GMT0"; 123444364Sborman #endif 123544364Sborman *envp = 0; 123644364Sborman environ = envinit; 123744364Sborman } 123844364Sborman 123944364Sborman #ifndef NEWINIT 124044364Sborman 124144364Sborman /* 124245234Sborman * start_login(host) 124338905Sborman * 124438905Sborman * Assuming that we are now running as a child processes, this 124538905Sborman * function will turn us into the login process. 124638905Sborman */ 124738905Sborman 124846809Sdab void 124946809Sdab start_login(host, autologin, name) 125046809Sdab char *host; 125146809Sdab int autologin; 125246809Sdab char *name; 125338905Sborman { 125444364Sborman register char *cp; 125544364Sborman register char **argv; 125644364Sborman char **addarg(); 125738905Sborman 125838905Sborman /* 125938905Sborman * -h : pass on name of host. 126038905Sborman * WARNING: -h is accepted by login if and only if 126138905Sborman * getuid() == 0. 126238905Sborman * -p : don't clobber the environment (so terminal type stays set). 126346809Sdab * 126446809Sdab * -f : force this login, he has already been authenticated 126538905Sborman */ 126644364Sborman argv = addarg(0, "login"); 126744364Sborman argv = addarg(argv, "-h"); 126844364Sborman argv = addarg(argv, host); 126946809Sdab #if !defined(NO_LOGIN_P) 127044364Sborman argv = addarg(argv, "-p"); 127138905Sborman #endif 127244364Sborman #ifdef BFTPDAEMON 127344364Sborman /* 127444364Sborman * Are we working as the bftp daemon? If so, then ask login 127544364Sborman * to start bftp instead of shell. 127644364Sborman */ 127744364Sborman if (bftpd) { 127844364Sborman argv = addarg(argv, "-e"); 127944364Sborman argv = addarg(argv, BFTPPATH); 128044364Sborman } else 128144364Sborman #endif 128246809Sdab #if defined (SecurID) 128346809Sdab /* 128446809Sdab * don't worry about the -f that might get sent. 128546809Sdab * A -s is supposed to override it anyhow. 128646809Sdab */ 128746809Sdab if (require_SecurID) 128846809Sdab argv = addarg(argv, "-s"); 128946809Sdab #endif 129046809Sdab #if defined (AUTHENTICATE) 129146809Sdab if (auth_level >= 0 && autologin == AUTH_VALID) { 129246809Sdab # if !defined(NO_LOGIN_F) 129346809Sdab argv = addarg(argv, "-f"); 129446809Sdab # endif 129546809Sdab argv = addarg(argv, name); 129646809Sdab } else 129746809Sdab #endif 129844364Sborman if (getenv("USER")) { 129944364Sborman argv = addarg(argv, getenv("USER")); 130046809Sdab #if defined(CRAY) && defined(NO_LOGIN_P) 130146809Sdab { 130246809Sdab register char **cpp; 130346809Sdab for (cpp = environ; *cpp; cpp++) 130446809Sdab argv = addarg(argv, *cpp); 130546809Sdab } 130646809Sdab #endif 130744364Sborman } 130846809Sdab closelog(); 130944364Sborman execv(_PATH_LOGIN, argv); 131044364Sborman 131138905Sborman syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN); 131238905Sborman fatalperror(net, _PATH_LOGIN); 131338905Sborman /*NOTREACHED*/ 131438905Sborman } 131544364Sborman 131646809Sdab char ** 131744364Sborman addarg(argv, val) 131846809Sdab register char **argv; 131946809Sdab register char *val; 132044364Sborman { 132144364Sborman register char **cpp; 132244364Sborman 132344364Sborman if (argv == NULL) { 132444364Sborman /* 132544364Sborman * 10 entries, a leading length, and a null 132644364Sborman */ 132744364Sborman argv = (char **)malloc(sizeof(*argv) * 12); 132844364Sborman if (argv == NULL) 132944364Sborman return(NULL); 133044364Sborman *argv++ = (char *)10; 133144364Sborman *argv = (char *)0; 133244364Sborman } 133344364Sborman for (cpp = argv; *cpp; cpp++) 133444364Sborman ; 133544364Sborman if (cpp == &argv[(int)argv[-1]]) { 133644364Sborman --argv; 133744364Sborman *argv = (char *)((int)(*argv) + 10); 133844364Sborman argv = (char **)realloc(argv, (int)(*argv) + 2); 133944364Sborman if (argv == NULL) 134044364Sborman return(NULL); 134144364Sborman argv++; 134244364Sborman cpp = &argv[(int)argv[-1] - 10]; 134344364Sborman } 134444364Sborman *cpp++ = val; 134544364Sborman *cpp = 0; 134644364Sborman return(argv); 134744364Sborman } 134846809Sdab #endif /* NEWINIT */ 134938905Sborman 135038905Sborman /* 135138905Sborman * cleanup() 135238905Sborman * 135338905Sborman * This is the routine to call when we are all through, to 135438905Sborman * clean up anything that needs to be cleaned up. 135538905Sborman */ 135646809Sdab /* ARGSUSED */ 135746809Sdab void 135846809Sdab cleanup(sig) 135946809Sdab int sig; 136038905Sborman { 136138905Sborman #ifndef CRAY 136245234Sborman # if (BSD > 43) || defined(convex) 136338905Sborman char *p; 136438905Sborman 136538905Sborman p = line + sizeof("/dev/") - 1; 136638905Sborman if (logout(p)) 136738905Sborman logwtmp(p, "", ""); 136838905Sborman (void)chmod(line, 0666); 136938905Sborman (void)chown(line, 0, 0); 137038905Sborman *p = 'p'; 137138905Sborman (void)chmod(line, 0666); 137238905Sborman (void)chown(line, 0, 0); 137346809Sdab (void) shutdown(net, 2); 137446809Sdab exit(1); 137538905Sborman # else 137646809Sdab void rmut(); 137746809Sdab 137838905Sborman rmut(); 137938905Sborman vhangup(); /* XXX */ 138046809Sdab (void) shutdown(net, 2); 138146809Sdab exit(1); 138238905Sborman # endif 138338905Sborman #else /* CRAY */ 138446809Sdab # ifdef NEWINIT 138538905Sborman (void) shutdown(net, 2); 138646809Sdab exit(1); 138738905Sborman # else /* NEWINIT */ 138846809Sdab static int incleanup = 0; 138946809Sdab register int t; 139046809Sdab 139146809Sdab /* 139246809Sdab * 1: Pick up the zombie, if we are being called 139346809Sdab * as the signal handler. 139446809Sdab * 2: If we are a nested cleanup(), return. 139546809Sdab * 3: Try to clean up TMPDIR. 139646809Sdab * 4: Fill in utmp with shutdown of process. 139746809Sdab * 5: Close down the network and pty connections. 139846809Sdab * 6: Finish up the TMPDIR cleanup, if needed. 139946809Sdab */ 140046809Sdab if (sig == SIGCHLD) 140146809Sdab while (waitpid(-1, 0, WNOHANG) > 0) 140246809Sdab ; /* VOID */ 140346809Sdab t = sigblock(sigmask(SIGCHLD)); 140446809Sdab if (incleanup) { 140546809Sdab sigsetmask(t); 140646809Sdab return; 140746809Sdab } 140846809Sdab incleanup = 1; 140946809Sdab sigsetmask(t); 141046809Sdab 141146809Sdab t = cleantmp(&wtmp); 141246809Sdab setutent(); /* just to make sure */ 141346809Sdab rmut(line); 141446809Sdab close(pty); 141538905Sborman (void) shutdown(net, 2); 141646809Sdab if (t == 0) 141746809Sdab cleantmp(&wtmp); 141846809Sdab exit(1); 141938905Sborman # endif /* NEWINT */ 142038905Sborman #endif /* CRAY */ 142138905Sborman } 142238905Sborman 142338905Sborman #if defined(CRAY) && !defined(NEWINIT) 142438905Sborman /* 142538905Sborman * _utmp_sig_rcv 142638905Sborman * utmp_sig_init 142738905Sborman * utmp_sig_wait 142838905Sborman * These three functions are used to coordinate the handling of 142938905Sborman * the utmp file between the server and the soon-to-be-login shell. 143038905Sborman * The server actually creates the utmp structure, the child calls 143138905Sborman * utmp_sig_wait(), until the server calls utmp_sig_notify() and 143238905Sborman * signals the future-login shell to proceed. 143338905Sborman */ 143438905Sborman static int caught=0; /* NZ when signal intercepted */ 143538905Sborman static void (*func)(); /* address of previous handler */ 143638905Sborman 143746809Sdab void 143838905Sborman _utmp_sig_rcv(sig) 143946809Sdab int sig; 144038905Sborman { 144138905Sborman caught = 1; 144238905Sborman (void) signal(SIGUSR1, func); 144338905Sborman } 144438905Sborman 144546809Sdab void 144638905Sborman utmp_sig_init() 144738905Sborman { 144838905Sborman /* 144938905Sborman * register signal handler for UTMP creation 145038905Sborman */ 145138905Sborman if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) 145238905Sborman fatalperror(net, "telnetd/signal"); 145338905Sborman } 145438905Sborman 145546809Sdab void 145644364Sborman utmp_sig_reset() 145744364Sborman { 145844364Sborman (void) signal(SIGUSR1, func); /* reset handler to default */ 145944364Sborman } 146044364Sborman 146146809Sdab void 146238905Sborman utmp_sig_wait() 146338905Sborman { 146438905Sborman /* 146538905Sborman * Wait for parent to write our utmp entry. 146638905Sborman */ 146738905Sborman sigoff(); 146838905Sborman while (caught == 0) { 146938905Sborman pause(); /* wait until we get a signal (sigon) */ 147038905Sborman sigoff(); /* turn off signals while we check caught */ 147138905Sborman } 147238905Sborman sigon(); /* turn on signals again */ 147338905Sborman } 147438905Sborman 147546809Sdab void 147638905Sborman utmp_sig_notify(pid) 147738905Sborman { 147838905Sborman kill(pid, SIGUSR1); 147938905Sborman } 148046809Sdab 148146809Sdab static int gotsigjob = 0; 148246809Sdab 148346809Sdab /*ARGSUSED*/ 148446809Sdab void 148546809Sdab sigjob(sig) 148646809Sdab int sig; 148746809Sdab { 148846809Sdab register int jid; 148946809Sdab register struct jobtemp *jp; 149046809Sdab 149146809Sdab while ((jid = waitjob(NULL)) != -1) { 149246809Sdab if (jid == 0) { 149346809Sdab return; 149446809Sdab } 149546809Sdab gotsigjob++; 149646809Sdab jobend(jid, NULL, NULL); 149746809Sdab } 149846809Sdab } 149946809Sdab 150046809Sdab /* 150146809Sdab * Clean up the TMPDIR that login created. 150246809Sdab * The first time this is called we pick up the info 150346809Sdab * from the utmp. If the job has already gone away, 150446809Sdab * then we'll clean up and be done. If not, then 150546809Sdab * when this is called the second time it will wait 150646809Sdab * for the signal that the job is done. 150746809Sdab */ 150846809Sdab int 150946809Sdab cleantmp(wtp) 151046809Sdab register struct utmp *wtp; 151146809Sdab { 151246809Sdab struct utmp *utp; 151346809Sdab static int first = 1; 151446809Sdab register int mask, omask, ret; 151546809Sdab extern struct utmp *getutid P((struct utmp *)); 151646809Sdab 151746809Sdab mask = sigmask(WJSIGNAL); 151846809Sdab 151946809Sdab if (first == 0) { 152046809Sdab omask = sigblock(mask); 152146809Sdab while (gotsigjob == 0) 152246809Sdab sigpause(omask); 152346809Sdab return(1); 152446809Sdab } 152546809Sdab first = 0; 152646809Sdab setutent(); /* just to make sure */ 152746809Sdab 152846809Sdab utp = getutid(wtp); 152946809Sdab if (utp == 0) { 153046809Sdab syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); 153146809Sdab return(-1); 153246809Sdab } 153346809Sdab /* 153446809Sdab * Nothing to clean up if the user shell was never started. 153546809Sdab */ 153646809Sdab if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) 153746809Sdab return(1); 153846809Sdab 153946809Sdab /* 154046809Sdab * Block the WJSIGNAL while we are in jobend(). 154146809Sdab */ 154246809Sdab omask = sigblock(mask); 154346809Sdab ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); 154446809Sdab sigsetmask(omask); 154546809Sdab return(ret); 154646809Sdab } 154746809Sdab 154846809Sdab int 154946809Sdab jobend(jid, path, user) 155046809Sdab register int jid; 155146809Sdab register char *path; 155246809Sdab register char *user; 155346809Sdab { 155446809Sdab static int saved_jid = 0; 155546809Sdab static char saved_path[sizeof(wtmp.ut_tpath)+1]; 155646809Sdab static char saved_user[sizeof(wtmp.ut_user)+1]; 155746809Sdab 155846809Sdab if (path) { 155946809Sdab strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); 156046809Sdab strncpy(saved_user, user, sizeof(wtmp.ut_user)); 156146809Sdab saved_path[sizeof(saved_path)] = '\0'; 156246809Sdab saved_user[sizeof(saved_user)] = '\0'; 156346809Sdab } 156446809Sdab if (saved_jid == 0) { 156546809Sdab saved_jid = jid; 156646809Sdab return(0); 156746809Sdab } 156846809Sdab cleantmpdir(jid, saved_path, saved_user); 156946809Sdab return(1); 157046809Sdab } 157146809Sdab 157246809Sdab /* 157346809Sdab * Fork a child process to clean up the TMPDIR 157446809Sdab */ 157546809Sdab cleantmpdir(jid, tpath, user) 157646809Sdab register int jid; 157746809Sdab register char *tpath; 157846809Sdab register char *user; 157946809Sdab { 158046809Sdab switch(fork()) { 158146809Sdab case -1: 158246809Sdab syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n", 158346809Sdab tpath); 158446809Sdab break; 158546809Sdab case 0: 158646809Sdab execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); 158746809Sdab syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", 158846809Sdab tpath, CLEANTMPCMD); 158946809Sdab exit(1); 159046809Sdab default: 159146809Sdab /* 159246809Sdab * Forget about child. We will exit, and 159346809Sdab * /etc/init will pick it up. 159446809Sdab */ 159546809Sdab break; 159646809Sdab } 159746809Sdab } 159838905Sborman #endif /* defined(CRAY) && !defined(NEWINIT) */ 159938905Sborman 160038905Sborman /* 160138905Sborman * rmut() 160238905Sborman * 160338905Sborman * This is the function called by cleanup() to 160438905Sborman * remove the utmp entry for this person. 160538905Sborman */ 160638905Sborman 160738905Sborman #if !defined(CRAY) && BSD <= 43 160846809Sdab void 160938905Sborman rmut() 161038905Sborman { 161138905Sborman register f; 161238905Sborman int found = 0; 161338905Sborman struct utmp *u, *utmp; 161438905Sborman int nutmp; 161538905Sborman struct stat statbf; 161638905Sborman 161738905Sborman f = open(utmpf, O_RDWR); 161838905Sborman if (f >= 0) { 161938905Sborman (void) fstat(f, &statbf); 162038905Sborman utmp = (struct utmp *)malloc((unsigned)statbf.st_size); 162138905Sborman if (!utmp) 162238905Sborman syslog(LOG_ERR, "utmp malloc failed"); 162338905Sborman if (statbf.st_size && utmp) { 162438905Sborman nutmp = read(f, (char *)utmp, (int)statbf.st_size); 162538905Sborman nutmp /= sizeof(struct utmp); 162638905Sborman 162738905Sborman for (u = utmp ; u < &utmp[nutmp] ; u++) { 162838905Sborman if (SCMPN(u->ut_line, line+5) || 162938905Sborman u->ut_name[0]==0) 163038905Sborman continue; 163138905Sborman (void) lseek(f, ((long)u)-((long)utmp), L_SET); 163238905Sborman SCPYN(u->ut_name, ""); 163338905Sborman SCPYN(u->ut_host, ""); 163438905Sborman (void) time(&u->ut_time); 163538905Sborman (void) write(f, (char *)u, sizeof(wtmp)); 163638905Sborman found++; 163738905Sborman } 163838905Sborman } 163938905Sborman (void) close(f); 164038905Sborman } 164138905Sborman if (found) { 164238905Sborman f = open(wtmpf, O_WRONLY|O_APPEND); 164338905Sborman if (f >= 0) { 164438905Sborman SCPYN(wtmp.ut_line, line+5); 164538905Sborman SCPYN(wtmp.ut_name, ""); 164638905Sborman SCPYN(wtmp.ut_host, ""); 164738905Sborman (void) time(&wtmp.ut_time); 164838905Sborman (void) write(f, (char *)&wtmp, sizeof(wtmp)); 164938905Sborman (void) close(f); 165038905Sborman } 165138905Sborman } 165238905Sborman (void) chmod(line, 0666); 165338905Sborman (void) chown(line, 0, 0); 165438905Sborman line[strlen("/dev/")] = 'p'; 165538905Sborman (void) chmod(line, 0666); 165638905Sborman (void) chown(line, 0, 0); 165738905Sborman } /* end of rmut */ 165838905Sborman #endif /* CRAY */ 1659