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*46685Sbostic static char sccsid[] = "@(#)sys_term.c 5.12 (Berkeley) 02/26/91"; 1038905Sborman #endif /* not lint */ 1138905Sborman 1238905Sborman #include "telnetd.h" 1338905Sborman #include "pathnames.h" 1438905Sborman 1538905Sborman #ifdef NEWINIT 1638905Sborman #include <initreq.h> 1738905Sborman #else /* NEWINIT*/ 1838905Sborman #include <utmp.h> 1938905Sborman struct utmp wtmp; 2038905Sborman 2138905Sborman # ifndef CRAY 2238905Sborman char wtmpf[] = "/usr/adm/wtmp"; 2338905Sborman char utmpf[] = "/etc/utmp"; 2438905Sborman # else /* CRAY */ 2538905Sborman char wtmpf[] = "/etc/wtmp"; 2638905Sborman # endif /* CRAY */ 2738905Sborman #endif /* NEWINIT */ 2838905Sborman 2938905Sborman #define SCPYN(a, b) (void) strncpy(a, b, sizeof(a)) 3038905Sborman #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 3138905Sborman 3244364Sborman #ifdef STREAMS 3344364Sborman #include <sys/stream.h> 3444364Sborman #endif 3538905Sborman #include <sys/tty.h> 3638905Sborman #ifdef t_erase 3738905Sborman #undef t_erase 3838905Sborman #undef t_kill 3938905Sborman #undef t_intrc 4038905Sborman #undef t_quitc 4138905Sborman #undef t_startc 4238905Sborman #undef t_stopc 4338905Sborman #undef t_eofc 4438905Sborman #undef t_brkc 4538905Sborman #undef t_suspc 4638905Sborman #undef t_dsuspc 4738905Sborman #undef t_rprntc 4838905Sborman #undef t_flushc 4938905Sborman #undef t_werasc 5038905Sborman #undef t_lnextc 5138905Sborman #endif 5238905Sborman 5344364Sborman #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC) 5444364Sborman # define EXTPROC 0400 5544364Sborman #endif 5644364Sborman 5738905Sborman #ifndef USE_TERMIO 5838905Sborman struct termbuf { 5938905Sborman struct sgttyb sg; 6038905Sborman struct tchars tc; 6138905Sborman struct ltchars ltc; 6238905Sborman int state; 6338905Sborman int lflags; 6438905Sborman } termbuf, termbuf2; 6545234Sborman # define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val) 6645234Sborman # define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val) 6738905Sborman #else /* USE_TERMIO */ 6838905Sborman # ifdef SYSV_TERMIO 6938905Sborman # define termios termio 7038905Sborman # endif 7145234Sborman # ifndef TCSANOW 7244364Sborman # ifdef TCSETS 7345234Sborman # define TCSANOW TCSETS 7445234Sborman # define TCSADRAIN TCSETSW 7545234Sborman # define tcgetattr(f, t) iotcl(f, TCGETS, t) 7644364Sborman # else 7745234Sborman # ifdef TCSETA 7845234Sborman # define TCSANOW TCSETA 7945234Sborman # define TCSADRAIN TCSETAW 8045234Sborman # define tcgetattr(f, t) ioctl(f, TCGETA, t) 8145234Sborman # else 8245234Sborman # define TCSANOW TIOCSETA 8345234Sborman # define TCSADRAIN TIOCSETAW 8445234Sborman # define tcgetattr(f, t) iotcl(f, TIOCGETA, t) 8545234Sborman # endif 8644364Sborman # endif 8745234Sborman # define tcsetattr(f, a, t) ioctl(f, a, t) 8845234Sborman # define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 8945234Sborman (tp)->c_cflag |= (val) 9045234Sborman # ifdef CIBAUD 9145234Sborman # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \ 9245234Sborman (tp)->c_cflag |= ((val)<<IBSHIFT) 9345234Sborman # else 9445234Sborman # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 9545234Sborman (tp)->c_cflag |= (val) 9645234Sborman # endif 9745234Sborman # endif /* TCSANOW */ 9838905Sborman struct termios termbuf, termbuf2; /* pty control structure */ 9938905Sborman #endif /* USE_TERMIO */ 10038905Sborman 10138905Sborman /* 10238905Sborman * init_termbuf() 10338905Sborman * copy_termbuf(cp) 10438905Sborman * set_termbuf() 10538905Sborman * 10638905Sborman * These three routines are used to get and set the "termbuf" structure 10738905Sborman * to and from the kernel. init_termbuf() gets the current settings. 10838905Sborman * copy_termbuf() hands in a new "termbuf" to write to the kernel, and 10938905Sborman * set_termbuf() writes the structure into the kernel. 11038905Sborman */ 11138905Sborman 11238905Sborman init_termbuf() 11338905Sborman { 11438905Sborman #ifndef USE_TERMIO 11538905Sborman (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg); 11638905Sborman (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc); 11738905Sborman (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc); 11838905Sborman # ifdef TIOCGSTATE 11938905Sborman (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state); 12038905Sborman # endif 12138905Sborman #else 122*46685Sbostic (void) tcgetattr(pty, &termbuf); 12338905Sborman #endif 12438905Sborman termbuf2 = termbuf; 12538905Sborman } 12638905Sborman 12738905Sborman #if defined(LINEMODE) && defined(TIOCPKT_IOCTL) 12838905Sborman copy_termbuf(cp, len) 12938905Sborman char *cp; 13038905Sborman int len; 13138905Sborman { 13238905Sborman if (len > sizeof(termbuf)) 13338905Sborman len = sizeof(termbuf); 13438905Sborman bcopy(cp, (char *)&termbuf, len); 13538905Sborman termbuf2 = termbuf; 13638905Sborman } 13738905Sborman #endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ 13838905Sborman 13938905Sborman set_termbuf() 14038905Sborman { 14138905Sborman /* 14238905Sborman * Only make the necessary changes. 14338905Sborman */ 14438905Sborman #ifndef USE_TERMIO 14538905Sborman if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg))) 14645234Sborman (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg); 14738905Sborman if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc))) 14838905Sborman (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc); 14938905Sborman if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc, 15038905Sborman sizeof(termbuf.ltc))) 15138905Sborman (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc); 15238905Sborman if (termbuf.lflags != termbuf2.lflags) 15338905Sborman (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags); 15438905Sborman #else /* USE_TERMIO */ 15538905Sborman if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) 156*46685Sbostic (void) tcsetattr(pty, TCSADRAIN, &termbuf); 15740242Sborman # if defined(CRAY2) && defined(UNCIOS5) 15838905Sborman needtermstat = 1; 15938905Sborman # endif 16038905Sborman #endif /* USE_TERMIO */ 16138905Sborman } 16238905Sborman 16338905Sborman 16438905Sborman /* 16538905Sborman * spcset(func, valp, valpp) 16638905Sborman * 16738905Sborman * This function takes various special characters (func), and 16838905Sborman * sets *valp to the current value of that character, and 16938905Sborman * *valpp to point to where in the "termbuf" structure that 17038905Sborman * value is kept. 17138905Sborman * 17238905Sborman * It returns the SLC_ level of support for this function. 17338905Sborman */ 17438905Sborman 17538905Sborman #ifndef USE_TERMIO 17638905Sborman spcset(func, valp, valpp) 17738905Sborman int func; 17840242Sborman cc_t *valp; 17940242Sborman cc_t **valpp; 18038905Sborman { 18138905Sborman switch(func) { 18238905Sborman case SLC_EOF: 18338905Sborman *valp = termbuf.tc.t_eofc; 18440242Sborman *valpp = (cc_t *)&termbuf.tc.t_eofc; 18538905Sborman return(SLC_VARIABLE); 18638905Sborman case SLC_EC: 18738905Sborman *valp = termbuf.sg.sg_erase; 18840242Sborman *valpp = (cc_t *)&termbuf.sg.sg_erase; 18938905Sborman return(SLC_VARIABLE); 19038905Sborman case SLC_EL: 19138905Sborman *valp = termbuf.sg.sg_kill; 19240242Sborman *valpp = (cc_t *)&termbuf.sg.sg_kill; 19338905Sborman return(SLC_VARIABLE); 19438905Sborman case SLC_IP: 19538905Sborman *valp = termbuf.tc.t_intrc; 19640242Sborman *valpp = (cc_t *)&termbuf.tc.t_intrc; 19738905Sborman return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 19838905Sborman case SLC_ABORT: 19938905Sborman *valp = termbuf.tc.t_quitc; 20040242Sborman *valpp = (cc_t *)&termbuf.tc.t_quitc; 20138905Sborman return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 20238905Sborman case SLC_XON: 20338905Sborman *valp = termbuf.tc.t_startc; 20440242Sborman *valpp = (cc_t *)&termbuf.tc.t_startc; 20538905Sborman return(SLC_VARIABLE); 20638905Sborman case SLC_XOFF: 20738905Sborman *valp = termbuf.tc.t_stopc; 20840242Sborman *valpp = (cc_t *)&termbuf.tc.t_stopc; 20938905Sborman return(SLC_VARIABLE); 21038905Sborman case SLC_AO: 21138905Sborman *valp = termbuf.ltc.t_flushc; 21240242Sborman *valpp = (cc_t *)&termbuf.ltc.t_flushc; 21338905Sborman return(SLC_VARIABLE); 21438905Sborman case SLC_SUSP: 21538905Sborman *valp = termbuf.ltc.t_suspc; 21640242Sborman *valpp = (cc_t *)&termbuf.ltc.t_suspc; 21738905Sborman return(SLC_VARIABLE); 21838905Sborman case SLC_EW: 21938905Sborman *valp = termbuf.ltc.t_werasc; 22040242Sborman *valpp = (cc_t *)&termbuf.ltc.t_werasc; 22138905Sborman return(SLC_VARIABLE); 22238905Sborman case SLC_RP: 22338905Sborman *valp = termbuf.ltc.t_rprntc; 22440242Sborman *valpp = (cc_t *)&termbuf.ltc.t_rprntc; 22538905Sborman return(SLC_VARIABLE); 22638905Sborman case SLC_LNEXT: 22738905Sborman *valp = termbuf.ltc.t_lnextc; 22840242Sborman *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 22938905Sborman return(SLC_VARIABLE); 23040242Sborman case SLC_FORW1: 23140242Sborman *valp = termbuf.tc.t_brkc; 23240242Sborman *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 23340242Sborman return(SLC_VARIABLE); 23438905Sborman case SLC_BRK: 23538905Sborman case SLC_SYNCH: 23638905Sborman case SLC_AYT: 23738905Sborman case SLC_EOR: 23840242Sborman *valp = (cc_t)0; 23940242Sborman *valpp = (cc_t *)0; 24038905Sborman return(SLC_DEFAULT); 24138905Sborman default: 24240242Sborman *valp = (cc_t)0; 24340242Sborman *valpp = (cc_t *)0; 24438905Sborman return(SLC_NOSUPPORT); 24538905Sborman } 24638905Sborman } 24738905Sborman 24838905Sborman #else /* USE_TERMIO */ 24938905Sborman 25038905Sborman spcset(func, valp, valpp) 25138905Sborman int func; 25240242Sborman cc_t *valp; 25340242Sborman cc_t **valpp; 25438905Sborman { 25539503Sborman 25639503Sborman #define setval(a, b) *valp = termbuf.c_cc[a]; \ 25739503Sborman *valpp = &termbuf.c_cc[a]; \ 25839503Sborman return(b); 25940242Sborman #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); 26039503Sborman 26138905Sborman switch(func) { 26238905Sborman case SLC_EOF: 26339503Sborman setval(VEOF, SLC_VARIABLE); 26438905Sborman case SLC_EC: 26539503Sborman setval(VERASE, SLC_VARIABLE); 26638905Sborman case SLC_EL: 26739503Sborman setval(VKILL, SLC_VARIABLE); 26838905Sborman case SLC_IP: 26939503Sborman setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 27038905Sborman case SLC_ABORT: 27139503Sborman setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 27238905Sborman case SLC_XON: 27339503Sborman #ifdef VSTART 27439503Sborman setval(VSTART, SLC_VARIABLE); 27539503Sborman #else 27639503Sborman defval(0x13); 27739503Sborman #endif 27838905Sborman case SLC_XOFF: 27939503Sborman #ifdef VSTOP 28039503Sborman setval(VSTOP, SLC_VARIABLE); 28139503Sborman #else 28239503Sborman defval(0x11); 28339503Sborman #endif 28438905Sborman case SLC_EW: 28539503Sborman #ifdef VWERASE 28639503Sborman setval(VWERASE, SLC_VARIABLE); 28739503Sborman #else 28839503Sborman defval(0); 28939503Sborman #endif 29038905Sborman case SLC_RP: 29139503Sborman #ifdef VREPRINT 29239503Sborman setval(VREPRINT, SLC_VARIABLE); 29339503Sborman #else 29439503Sborman defval(0); 29539503Sborman #endif 29638905Sborman case SLC_LNEXT: 29739503Sborman #ifdef VLNEXT 29839503Sborman setval(VLNEXT, SLC_VARIABLE); 29939503Sborman #else 30039503Sborman defval(0); 30139503Sborman #endif 30239503Sborman case SLC_AO: 30345234Sborman #if !defined(VDISCARD) && defined(VFLUSHO) 30445234Sborman # define VDISCARD VFLUSHO 30545234Sborman #endif 30645234Sborman #ifdef VDISCARD 30745234Sborman setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); 30839503Sborman #else 30939503Sborman defval(0); 31039503Sborman #endif 31139503Sborman case SLC_SUSP: 31239503Sborman #ifdef VSUSP 31339503Sborman setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); 31439503Sborman #else 31539503Sborman defval(0); 31639503Sborman #endif 31740242Sborman #ifdef VEOL 31840242Sborman case SLC_FORW1: 31940242Sborman setval(VEOL, SLC_VARIABLE); 32040242Sborman #endif 32140242Sborman #ifdef VEOL2 32240242Sborman case SLC_FORW2: 32340242Sborman setval(VEOL2, SLC_VARIABLE); 32440242Sborman #endif 32545234Sborman case SLC_AYT: 32645234Sborman #ifdef VSTATUS 32745234Sborman setval(VSTATUS, SLC_VARIABLE); 32845234Sborman #else 32945234Sborman defval(0); 33045234Sborman #endif 33139503Sborman 33238905Sborman case SLC_BRK: 33338905Sborman case SLC_SYNCH: 33438905Sborman case SLC_EOR: 33539503Sborman defval(0); 33639503Sborman 33738905Sborman default: 33838905Sborman *valp = 0; 33938905Sborman *valpp = 0; 34038905Sborman return(SLC_NOSUPPORT); 34138905Sborman } 34238905Sborman } 34338905Sborman #endif /* USE_TERMIO */ 34438905Sborman 34540242Sborman #ifdef CRAY 34638905Sborman /* 34740242Sborman * getnpty() 34840242Sborman * 34940242Sborman * Return the number of pty's configured into the system. 35040242Sborman */ 35140242Sborman getnpty() 35240242Sborman { 35340242Sborman #ifdef _SC_CRAY_NPTY 35440242Sborman return sysconf(_SC_CRAY_NPTY); 35540242Sborman #else 35640242Sborman return 128; 35740242Sborman #endif /* _SC_CRAY_NPTY */ 35840242Sborman } 35940242Sborman #endif /* CRAY */ 36040242Sborman 36145234Sborman #ifndef convex 36240242Sborman /* 36338905Sborman * getpty() 36438905Sborman * 36538905Sborman * Allocate a pty. As a side effect, the external character 36638905Sborman * array "line" contains the name of the slave side. 36738905Sborman * 36838905Sborman * Returns the file descriptor of the opened pty. 36938905Sborman */ 37045234Sborman #ifndef __GNUC__ 37138905Sborman char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 37245234Sborman #else 37345234Sborman static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 37445234Sborman char *line = Xline; 37545234Sborman #endif 37645234Sborman #ifdef CRAY 37745234Sborman char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 37845234Sborman #endif /* CRAY */ 37938905Sborman 38038905Sborman getpty() 38138905Sborman { 38238905Sborman register int p; 38338905Sborman #ifndef CRAY 38438905Sborman register char c, *p1, *p2; 38538905Sborman register int i; 38638905Sborman 38738905Sborman (void) sprintf(line, "/dev/ptyXX"); 38838905Sborman p1 = &line[8]; 38938905Sborman p2 = &line[9]; 39038905Sborman 39138905Sborman for (c = 'p'; c <= 's'; c++) { 39238905Sborman struct stat stb; 39338905Sborman 39438905Sborman *p1 = c; 39538905Sborman *p2 = '0'; 39638905Sborman if (stat(line, &stb) < 0) 39738905Sborman break; 39838905Sborman for (i = 0; i < 16; i++) { 39938905Sborman *p2 = "0123456789abcdef"[i]; 40038905Sborman p = open(line, 2); 40138905Sborman if (p > 0) { 40238905Sborman line[5] = 't'; 40338905Sborman return(p); 40438905Sborman } 40538905Sborman } 40638905Sborman } 40738905Sborman #else /* CRAY */ 40838905Sborman register int npty; 40938905Sborman extern lowpty, highpty; 41045234Sborman struct stat sb; 41138905Sborman 41238905Sborman for (npty = lowpty; npty <= highpty; npty++) { 41345234Sborman (void) sprintf(myline, "/dev/pty/%03d", npty); 41445234Sborman p = open(myline, 2); 41538905Sborman if (p < 0) 41638905Sborman continue; 41738905Sborman (void) sprintf(line, "/dev/ttyp%03d", npty); 41845234Sborman /* 41945234Sborman * Here are some shenanigans to make sure that there 42045234Sborman * are no listeners lurking on the line. 42145234Sborman */ 42245234Sborman if(stat(line, &sb) < 0) { 42345234Sborman (void) close(p); 42445234Sborman continue; 42545234Sborman } 42645234Sborman if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { 42745234Sborman chown(line, 0, 0); 42845234Sborman chmod(line, 0600); 42945234Sborman (void)close(p); 43045234Sborman p = open(myline, 2); 43145234Sborman if (p < 0) 43245234Sborman continue; 43345234Sborman } 43445234Sborman /* 43545234Sborman * Now it should be safe...check for accessability. 43645234Sborman */ 43738905Sborman if (access(line, 6) == 0) 43838905Sborman return(p); 43938905Sborman else { 44038905Sborman /* no tty side to pty so skip it */ 44138905Sborman (void) close(p); 44238905Sborman } 44338905Sborman } 44438905Sborman #endif /* CRAY */ 44538905Sborman return(-1); 44638905Sborman } 44745234Sborman #endif /* convex */ 44838905Sborman 44938905Sborman #ifdef LINEMODE 45038905Sborman /* 45138905Sborman * tty_flowmode() Find out if flow control is enabled or disabled. 45238905Sborman * tty_linemode() Find out if linemode (external processing) is enabled. 45338905Sborman * tty_setlinemod(on) Turn on/off linemode. 45438905Sborman * tty_isecho() Find out if echoing is turned on. 45538905Sborman * tty_setecho(on) Enable/disable character echoing. 45638905Sborman * tty_israw() Find out if terminal is in RAW mode. 45738905Sborman * tty_binaryin(on) Turn on/off BINARY on input. 45838905Sborman * tty_binaryout(on) Turn on/off BINARY on output. 45938905Sborman * tty_isediting() Find out if line editing is enabled. 46038905Sborman * tty_istrapsig() Find out if signal trapping is enabled. 46138905Sborman * tty_setedit(on) Turn on/off line editing. 46238905Sborman * tty_setsig(on) Turn on/off signal trapping. 46344364Sborman * tty_issofttab() Find out if tab expansion is enabled. 46444364Sborman * tty_setsofttab(on) Turn on/off soft tab expansion. 46544364Sborman * tty_islitecho() Find out if typed control chars are echoed literally 46644364Sborman * tty_setlitecho() Turn on/off literal echo of control chars 46738905Sborman * tty_tspeed(val) Set transmit speed to val. 46838905Sborman * tty_rspeed(val) Set receive speed to val. 46938905Sborman */ 47038905Sborman 47138905Sborman tty_flowmode() 47238905Sborman { 47338905Sborman #ifndef USE_TERMIO 47438905Sborman return((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0); 47538905Sborman #else 47638905Sborman return(termbuf.c_iflag & IXON ? 1 : 0); 47738905Sborman #endif 47838905Sborman } 47938905Sborman 48045234Sborman #ifdef convex 48145234Sborman static int linestate; 48245234Sborman #endif 48345234Sborman 48438905Sborman tty_linemode() 48538905Sborman { 48645234Sborman #ifndef convex 48738905Sborman #ifndef USE_TERMIO 48838905Sborman return(termbuf.state & TS_EXTPROC); 48938905Sborman #else 49038905Sborman return(termbuf.c_lflag & EXTPROC); 49138905Sborman #endif 49245234Sborman #else 49345234Sborman return(linestate); 49445234Sborman #endif 49538905Sborman } 49638905Sborman 49738905Sborman tty_setlinemode(on) 49838905Sborman int on; 49938905Sborman { 50038905Sborman #ifdef TIOCEXT 50145234Sborman # ifndef convex 50245234Sborman set_termbuf(); 50345234Sborman # else 50445234Sborman linestate = on; 50545234Sborman # endif 50638905Sborman (void) ioctl(pty, TIOCEXT, (char *)&on); 50745234Sborman # ifndef convex 50845234Sborman init_termbuf(); 50945234Sborman # endif 51038905Sborman #else /* !TIOCEXT */ 51145234Sborman # ifdef EXTPROC 51238905Sborman if (on) 51338905Sborman termbuf.c_lflag |= EXTPROC; 51438905Sborman else 51538905Sborman termbuf.c_lflag &= ~EXTPROC; 51645234Sborman # endif 51738905Sborman #endif /* TIOCEXT */ 51838905Sborman } 51938905Sborman 52038905Sborman tty_isecho() 52138905Sborman { 52238905Sborman #ifndef USE_TERMIO 52338905Sborman return (termbuf.sg.sg_flags & ECHO); 52438905Sborman #else 52538905Sborman return (termbuf.c_lflag & ECHO); 52638905Sborman #endif 52738905Sborman } 52838905Sborman #endif /* LINEMODE */ 52938905Sborman 53038905Sborman tty_setecho(on) 53138905Sborman { 53238905Sborman #ifndef USE_TERMIO 53338905Sborman if (on) 53438905Sborman termbuf.sg.sg_flags |= ECHO|CRMOD; 53538905Sborman else 53638905Sborman termbuf.sg.sg_flags &= ~(ECHO|CRMOD); 53738905Sborman #else 53838905Sborman if (on) 53938905Sborman termbuf.c_lflag |= ECHO; 54038905Sborman else 54138905Sborman termbuf.c_lflag &= ~ECHO; 54238905Sborman #endif 54338905Sborman } 54438905Sborman 54538905Sborman #if defined(LINEMODE) && defined(KLUDGELINEMODE) 54638905Sborman tty_israw() 54738905Sborman { 54838905Sborman #ifndef USE_TERMIO 54938905Sborman return(termbuf.sg.sg_flags & RAW); 55038905Sborman #else 55138905Sborman return(!(termbuf.c_lflag & ICANON)); 55238905Sborman #endif 55338905Sborman } 55438905Sborman #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 55538905Sborman 55638905Sborman tty_binaryin(on) 55738905Sborman { 55838905Sborman #ifndef USE_TERMIO 55938905Sborman if (on) 56038905Sborman termbuf.lflags |= LPASS8; 56138905Sborman else 56238905Sborman termbuf.lflags &= ~LPASS8; 56338905Sborman #else 56438905Sborman if (on) { 56538905Sborman termbuf.c_lflag &= ~ISTRIP; 56638905Sborman } else { 56738905Sborman termbuf.c_lflag |= ISTRIP; 56838905Sborman } 56938905Sborman #endif 57038905Sborman } 57138905Sborman 57238905Sborman tty_binaryout(on) 57338905Sborman { 57438905Sborman #ifndef USE_TERMIO 57538905Sborman if (on) 57638905Sborman termbuf.lflags |= LLITOUT; 57738905Sborman else 57838905Sborman termbuf.lflags &= ~LLITOUT; 57938905Sborman #else 58038905Sborman if (on) { 58138905Sborman termbuf.c_cflag &= ~(CSIZE|PARENB); 58238905Sborman termbuf.c_cflag |= CS8; 58338905Sborman termbuf.c_oflag &= ~OPOST; 58438905Sborman } else { 58538905Sborman termbuf.c_cflag &= ~CSIZE; 58638905Sborman termbuf.c_cflag |= CS7|PARENB; 58738905Sborman termbuf.c_oflag |= OPOST; 58838905Sborman } 58938905Sborman #endif 59038905Sborman } 59138905Sborman 59238905Sborman tty_isbinaryin() 59338905Sborman { 59438905Sborman #ifndef USE_TERMIO 59538905Sborman return(termbuf.lflags & LPASS8); 59638905Sborman #else 59739503Sborman return(!(termbuf.c_iflag & ISTRIP)); 59838905Sborman #endif 59938905Sborman } 60038905Sborman 60138905Sborman tty_isbinaryout() 60238905Sborman { 60338905Sborman #ifndef USE_TERMIO 60438905Sborman return(termbuf.lflags & LLITOUT); 60538905Sborman #else 60639503Sborman return(!(termbuf.c_oflag&OPOST)); 60738905Sborman #endif 60838905Sborman } 60938905Sborman 61038905Sborman #ifdef LINEMODE 61138905Sborman tty_isediting() 61238905Sborman { 61338905Sborman #ifndef USE_TERMIO 61438905Sborman return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); 61538905Sborman #else 61638905Sborman return(termbuf.c_lflag & ICANON); 61738905Sborman #endif 61838905Sborman } 61938905Sborman 62038905Sborman tty_istrapsig() 62138905Sborman { 62238905Sborman #ifndef USE_TERMIO 62338905Sborman return(!(termbuf.sg.sg_flags&RAW)); 62438905Sborman #else 62538905Sborman return(termbuf.c_lflag & ISIG); 62638905Sborman #endif 62738905Sborman } 62838905Sborman 62938905Sborman tty_setedit(on) 63038905Sborman int on; 63138905Sborman { 63238905Sborman #ifndef USE_TERMIO 63338905Sborman if (on) 63438905Sborman termbuf.sg.sg_flags &= ~CBREAK; 63538905Sborman else 63638905Sborman termbuf.sg.sg_flags |= CBREAK; 63738905Sborman #else 63838905Sborman if (on) 63938905Sborman termbuf.c_lflag |= ICANON; 64038905Sborman else 64138905Sborman termbuf.c_lflag &= ~ICANON; 64238905Sborman #endif 64338905Sborman } 64438905Sborman 64538905Sborman tty_setsig(on) 64638905Sborman int on; 64738905Sborman { 64838905Sborman #ifndef USE_TERMIO 64938905Sborman if (on) 65038905Sborman ; 65138905Sborman #else 65238905Sborman if (on) 65338905Sborman termbuf.c_lflag |= ISIG; 65438905Sborman else 65538905Sborman termbuf.c_lflag &= ~ISIG; 65638905Sborman #endif 65738905Sborman } 65838905Sborman #endif /* LINEMODE */ 65938905Sborman 66044364Sborman tty_issofttab() 66144364Sborman { 66244364Sborman #ifndef USE_TERMIO 66344364Sborman return (termbuf.sg.sg_flags & XTABS); 66444364Sborman #else 66544364Sborman # ifdef OXTABS 66644364Sborman return (termbuf.c_oflag & OXTABS); 66744364Sborman # endif 66844364Sborman # ifdef TABDLY 66944364Sborman return ((termbuf.c_oflag & TABDLY) == TAB3); 67044364Sborman # endif 67144364Sborman #endif 67244364Sborman } 67344364Sborman 67444364Sborman tty_setsofttab(on) 67544364Sborman int on; 67644364Sborman { 67744364Sborman #ifndef USE_TERMIO 67844364Sborman if (on) 67944364Sborman termbuf.sg.sg_flags |= XTABS; 68044364Sborman else 68144364Sborman termbuf.sg.sg_flags &= ~XTABS; 68244364Sborman #else 68344364Sborman if (on) { 68444364Sborman # ifdef OXTABS 68544364Sborman termbuf.c_oflag |= OXTABS; 68644364Sborman # endif 68744364Sborman # ifdef TABDLY 68844364Sborman termbuf.c_oflag &= ~TABDLY; 68944364Sborman termbuf.c_oflag |= TAB3; 69044364Sborman # endif 69144364Sborman } else { 69244364Sborman # ifdef OXTABS 69344364Sborman termbuf.c_oflag &= ~OXTABS; 69444364Sborman # endif 69544364Sborman # ifdef TABDLY 69644364Sborman termbuf.c_oflag &= ~TABDLY; 69744364Sborman termbuf.c_oflag |= TAB0; 69844364Sborman # endif 69944364Sborman } 70044364Sborman #endif 70144364Sborman } 70244364Sborman 70344364Sborman tty_islitecho() 70444364Sborman { 70544364Sborman #ifndef USE_TERMIO 70644364Sborman return (!(termbuf.sg.sg_flags & CTLECH)); 70744364Sborman #else 70844364Sborman # ifdef ECHOCTL 70944364Sborman return (!(termbuf.c_lflag & ECHOCTL)); 71044364Sborman # endif 71144364Sborman # ifdef TCTLECH 71244364Sborman return (!(termbuf.c_lflag & TCTLECH)); 71344364Sborman # endif 71444364Sborman # if !defined(ECHOCTL) && !defined(TCTLECH) 71544364Sborman return (0); /* assumes ctl chars are echoed '^x' */ 71644364Sborman # endif 71744364Sborman #endif 71844364Sborman } 71944364Sborman 72044364Sborman tty_setlitecho(on) 72144364Sborman int on; 72244364Sborman { 72344364Sborman #ifndef USE_TERMIO 72444364Sborman if (on) 72544364Sborman termbuf.sg.sg_flags &= ~CTLECH; 72644364Sborman else 72744364Sborman termbuf.sg.sg_flags |= CTLECH; 72844364Sborman #else 72944364Sborman # ifdef ECHOCTL 73044364Sborman if (on) 73144364Sborman termbuf.c_lflag &= ~ECHOCTL; 73244364Sborman else 73344364Sborman termbuf.c_lflag |= ECHOCTL; 73444364Sborman # endif 73544364Sborman # ifdef TCTLECH 73644364Sborman if (on) 73744364Sborman termbuf.c_lflag &= ~TCTLECH; 73844364Sborman else 73944364Sborman termbuf.c_lflag |= TCTLECH; 74044364Sborman # endif 74144364Sborman #endif 74244364Sborman } 74344364Sborman 74438905Sborman /* 74538905Sborman * A table of available terminal speeds 74638905Sborman */ 74738905Sborman struct termspeeds { 74838905Sborman int speed; 74938905Sborman int value; 75038905Sborman } termspeeds[] = { 75138905Sborman { 0, B0 }, { 50, B50 }, { 75, B75 }, 75238905Sborman { 110, B110 }, { 134, B134 }, { 150, B150 }, 75338905Sborman { 200, B200 }, { 300, B300 }, { 600, B600 }, 75438905Sborman { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 75538905Sborman { 4800, B4800 }, { 9600, B9600 }, { 19200, B9600 }, 75638905Sborman { 38400, B9600 }, { -1, B9600 } 75738905Sborman }; 75838905Sborman 75938905Sborman tty_tspeed(val) 76038905Sborman { 76138905Sborman register struct termspeeds *tp; 76238905Sborman 76338905Sborman for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 76438905Sborman ; 76545234Sborman cfsetospeed(&termbuf, tp->value); 76638905Sborman } 76738905Sborman 76838905Sborman tty_rspeed(val) 76938905Sborman { 77038905Sborman register struct termspeeds *tp; 77138905Sborman 77238905Sborman for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 77338905Sborman ; 77445234Sborman cfsetispeed(&termbuf, tp->value); 77538905Sborman } 77638905Sborman 77740242Sborman #if defined(CRAY2) && defined(UNICOS5) 77838905Sborman tty_isnewmap() 77938905Sborman { 78038905Sborman return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) && 78138905Sborman !(termbuf.c_oflag & ONLRET)); 78238905Sborman } 78338905Sborman #endif 78438905Sborman 78538905Sborman #ifdef CRAY 78638905Sborman # ifndef NEWINIT 78738905Sborman extern struct utmp wtmp; 78838905Sborman extern char wtmpf[]; 78938905Sborman # else /* NEWINIT */ 79038905Sborman int gotalarm; 79140242Sborman /* ARGSUSED */ 79240242Sborman void 79340242Sborman nologinproc(sig) 79440242Sborman int sig; 79538905Sborman { 79638905Sborman gotalarm++; 79738905Sborman } 79838905Sborman # endif /* NEWINIT */ 79938905Sborman #endif /* CRAY */ 80038905Sborman 80138905Sborman /* 80238905Sborman * getptyslave() 80338905Sborman * 80438905Sborman * Open the slave side of the pty, and do any initialization 80538905Sborman * that is necessary. The return value is a file descriptor 80638905Sborman * for the slave side. 80738905Sborman */ 80838905Sborman getptyslave() 80938905Sborman { 81038905Sborman register int t = -1; 81138905Sborman 81245234Sborman #if !defined(CRAY) || !defined(NEWINIT) 81345234Sborman # ifdef LINEMODE 81438905Sborman /* 81545234Sborman * Opening the slave side may cause initilization of the 81645234Sborman * kernel tty structure. We need remember whether or not 81745234Sborman * linemode was turned on, so that we can re-set it if we 81845234Sborman * need to. 81938905Sborman */ 82045234Sborman int waslm = tty_linemode(); 82145234Sborman # endif 82245234Sborman 82345234Sborman 82445234Sborman /* 82545234Sborman * Make sure that we don't have a controlling tty, and 82645234Sborman * that we are the session (process group) leader. 82745234Sborman */ 82845234Sborman # ifdef TIOCNOTTY 82938905Sborman t = open(_PATH_TTY, O_RDWR); 83038905Sborman if (t >= 0) { 83138905Sborman (void) ioctl(t, TIOCNOTTY, (char *)0); 83238905Sborman (void) close(t); 83338905Sborman } 83445234Sborman # endif 83538905Sborman 83645234Sborman 83745234Sborman # ifdef CRAY 83845234Sborman /* 83945234Sborman * Wait for our parent to get the utmp stuff to get done. 84045234Sborman */ 84145234Sborman utmp_sig_wait(); 84245234Sborman # endif 84345234Sborman 84445234Sborman t = cleanopen(line); 84538905Sborman if (t < 0) 84638905Sborman fatalperror(net, line); 84738905Sborman 84845234Sborman /* 84945234Sborman * set up the tty modes as we like them to be. 85045234Sborman */ 85138905Sborman init_termbuf(); 85245234Sborman # ifdef LINEMODE 85345234Sborman if (waslm) 85445234Sborman tty_setlinemode(); 85545234Sborman # endif LINEMODE 85645234Sborman 85745234Sborman /* 85845234Sborman * Settings for sgtty based systems 85945234Sborman */ 86045234Sborman # ifndef USE_TERMIO 86140242Sborman termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; 86238905Sborman termbuf.sg.sg_ospeed = termbuf.sg.sg_ispeed = B9600; 86345234Sborman # endif /* USE_TERMIO */ 86445234Sborman 86545234Sborman /* 86645234Sborman * Settings for UNICOS 86745234Sborman */ 86845234Sborman # ifdef CRAY 86945234Sborman termbuf.c_oflag = OPOST|ONLCR|TAB3; 87045234Sborman termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; 87145234Sborman termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; 87245234Sborman termbuf.c_cflag = EXTB|HUPCL|CS8; 87345234Sborman # endif 87445234Sborman 87545234Sborman /* 87645234Sborman * Settings for all other termios/termio based 87745234Sborman * systems, other than 4.4BSD. In 4.4BSD the 87845234Sborman * kernel does the initial terminal setup. 87945234Sborman */ 88045234Sborman # if defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) 88145234Sborman # ifndef OXTABS 88245234Sborman # define OXTABS 0 88345234Sborman # endif 88438905Sborman termbuf.c_lflag |= ECHO; 88538905Sborman termbuf.c_oflag |= ONLCR|OXTABS; 88638905Sborman termbuf.c_iflag |= ICRNL; 88738905Sborman termbuf.c_iflag &= ~IXOFF; 88845234Sborman cfsetospeed(&termbuf, B9600); 88945234Sborman cfsetispeed(&termbuf, B9600); 89045234Sborman # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */ 89145234Sborman 89245234Sborman /* 89345234Sborman * Set the tty modes, and make this our controlling tty. 89445234Sborman */ 89545234Sborman set_termbuf(); 89645234Sborman if (login_tty(t) == -1) 89745234Sborman fatalperror(net, "login_tty"); 89845234Sborman #endif /* !defined(CRAY) || !defined(NEWINIT) */ 89945234Sborman if (net > 2) 90045234Sborman (void) close(net); 90145234Sborman if (pty > 2) 90245234Sborman (void) close(pty); 90345234Sborman } 90445234Sborman 90545234Sborman #if !defined(CRAY) || !defined(NEWINIT) 90645234Sborman #ifndef O_NOCTTY 90745234Sborman #define O_NOCTTY 0 90838905Sborman #endif 90945234Sborman /* 91045234Sborman * Open the specified slave side of the pty, 91145234Sborman * making sure that we have a clean tty. 91245234Sborman */ 91345234Sborman cleanopen(line) 91445234Sborman char *line; 91545234Sborman { 91645234Sborman register int t; 91745234Sborman 91845234Sborman /* 91945234Sborman * Make sure that other people can't open the 92045234Sborman * slave side of the connection. 92145234Sborman */ 92238905Sborman (void) chown(line, 0, 0); 92338905Sborman (void) chmod(line, 0600); 92445234Sborman 92545234Sborman # if !defined(CRAY) && (BSD > 43) 92645234Sborman (void) revoke(line); 92745234Sborman # endif 92845234Sborman t = open(line, O_RDWR|O_NOCTTY); 92945234Sborman if (t < 0) 93045234Sborman return(-1); 93145234Sborman 93245234Sborman /* 93345234Sborman * Hangup anybody else using this ttyp, then reopen it for 93445234Sborman * ourselves. 93545234Sborman */ 93645234Sborman # if !defined(CRAY) && (BSD <= 43) 93745234Sborman (void) signal(SIGHUP, SIG_IGN); 93845234Sborman vhangup(); 93945234Sborman (void) signal(SIGHUP, SIG_DFL); 94045234Sborman t = open(line, O_RDWR|O_NOCTTY); 94145234Sborman if (t < 0) 94245234Sborman return(-1); 94345234Sborman # endif 94445234Sborman # if defined(CRAY) && defined(TCVHUP) 94545234Sborman { 94645234Sborman register int i; 94745234Sborman (void) signal(SIGHUP, SIG_IGN); 94845234Sborman (void) ioctl(t, TCVHUP, (char *)0); 94945234Sborman (void) signal(SIGHUP, SIG_DFL); 95045234Sborman setpgrp(); 95145234Sborman i = open(line, O_RDWR); 95245234Sborman if (i < 0) 95345234Sborman return(-1) 95445234Sborman (void) close(t); 95545234Sborman t = i; 95645234Sborman } 95745234Sborman # endif /* defined(CRAY) && defined(TCVHUP) */ 95838905Sborman return(t); 95938905Sborman } 96045234Sborman #endif /* !defined(CRAY) || !defined(NEWINIT) */ 96138905Sborman 96245234Sborman #if BSD <= 43 96345234Sborman login_tty(t) 96445234Sborman int t; 96545234Sborman { 96645234Sborman # ifndef NO_SETSID 96745234Sborman if (setsid() < 0) 96845234Sborman fatalperror(net, "setsid()"); 96945234Sborman # else 97045234Sborman # ifndef convex 97145234Sborman if (setpgrp(0,0) < 0) 97245234Sborman fatalperror(net, "setpgrp()"); 97345234Sborman # endif 97445234Sborman # endif 97545234Sborman # ifdef TIOCSCTTY 97645234Sborman if (ioctl(t, TIOCSCTTY, (char *)0) < 0) 97745234Sborman fatalperror(net, "ioctl(sctty)"); 97845234Sborman # else 97945234Sborman close(open(line, O_RDWR)); 98045234Sborman # endif 98145234Sborman (void) dup2(t, 0); 98245234Sborman (void) dup2(t, 1); 98345234Sborman (void) dup2(t, 2); 98445234Sborman close(t); 98545234Sborman } 98645234Sborman #endif /* BSD <= 43 */ 98745234Sborman 98838905Sborman #ifdef NEWINIT 98938905Sborman char *gen_id = "fe"; 99038905Sborman #endif 99138905Sborman 99238905Sborman /* 99345234Sborman * startslave(host) 99438905Sborman * 99545234Sborman * Given a hostname, do whatever 99638905Sborman * is necessary to startup the login process on the slave side of the pty. 99738905Sborman */ 99838905Sborman 99938905Sborman /* ARGSUSED */ 100045234Sborman startslave(host) 100138905Sborman char *host; 100238905Sborman { 100338905Sborman register int i; 100438905Sborman long time(); 100538905Sborman 100638905Sborman #ifndef NEWINIT 100738905Sborman # ifdef CRAY 100838905Sborman utmp_sig_init(); 100938905Sborman # endif /* CRAY */ 101038905Sborman 101138905Sborman if ((i = fork()) < 0) 101238905Sborman fatalperror(net, "fork"); 101338905Sborman if (i) { 101438905Sborman # ifdef CRAY 101538905Sborman /* 101638905Sborman * Cray parent will create utmp entry for child and send 101738905Sborman * signal to child to tell when done. Child waits for signal 101838905Sborman * before doing anything important. 101938905Sborman */ 102038905Sborman register int pid = i; 102138905Sborman 102238905Sborman setpgrp(); 102344364Sborman utmp_sig_reset(); /* reset handler to default */ 102438905Sborman /* 102538905Sborman * Create utmp entry for child 102638905Sborman */ 102738905Sborman (void) time(&wtmp.ut_time); 102838905Sborman wtmp.ut_type = LOGIN_PROCESS; 102938905Sborman wtmp.ut_pid = pid; 103038905Sborman SCPYN(wtmp.ut_user, "LOGIN"); 103138905Sborman SCPYN(wtmp.ut_host, host); 103238905Sborman SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); 103338905Sborman SCPYN(wtmp.ut_id, wtmp.ut_line+3); 103438905Sborman pututline(&wtmp); 103538905Sborman endutent(); 103638905Sborman if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { 103738905Sborman (void) write(i, (char *)&wtmp, sizeof(struct utmp)); 103838905Sborman (void) close(i); 103938905Sborman } 104038905Sborman utmp_sig_notify(pid); 104138905Sborman # endif /* CRAY */ 104238905Sborman } else { 104345234Sborman getptyslave(); 104445234Sborman start_login(host); 104538905Sborman /*NOTREACHED*/ 104638905Sborman } 104738905Sborman #else /* NEWINIT */ 104838905Sborman 104938905Sborman extern char *ptyip; 105038905Sborman struct init_request request; 105140242Sborman void nologinproc(); 105238905Sborman register int n; 105338905Sborman 105438905Sborman /* 105538905Sborman * Init will start up login process if we ask nicely. We only wait 105638905Sborman * for it to start up and begin normal telnet operation. 105738905Sborman */ 105838905Sborman if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { 105938905Sborman char tbuf[128]; 106038905Sborman (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO); 106138905Sborman fatalperror(net, tbuf); 106238905Sborman } 106338905Sborman memset((char *)&request, 0, sizeof(request)); 106438905Sborman request.magic = INIT_MAGIC; 106538905Sborman SCPYN(request.gen_id, gen_id); 106638905Sborman SCPYN(request.tty_id, &line[8]); 106738905Sborman SCPYN(request.host, host); 106844364Sborman SCPYN(request.term_type, terminaltype); 106944364Sborman #if !defined(UNICOS5) 107040242Sborman request.signal = SIGCLD; 107140242Sborman request.pid = getpid(); 107240242Sborman #endif 107344364Sborman #ifdef BFTPDAEMON 107444364Sborman /* 107544364Sborman * Are we working as the bftp daemon? 107644364Sborman */ 107744364Sborman if (bftpd) { 107844364Sborman SCPYN(request.exec_name, BFTPPATH); 107944364Sborman } 108044364Sborman #endif /* BFTPDAEMON */ 108138905Sborman if (write(i, (char *)&request, sizeof(request)) < 0) { 108238905Sborman char tbuf[128]; 108338905Sborman (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO); 108438905Sborman fatalperror(net, tbuf); 108538905Sborman } 108638905Sborman (void) close(i); 108738905Sborman (void) signal(SIGALRM, nologinproc); 108838905Sborman for (i = 0; ; i++) { 108940242Sborman char tbuf[128]; 109038905Sborman alarm(15); 109138905Sborman n = read(pty, ptyip, BUFSIZ); 109238905Sborman if (i == 3 || n >= 0 || !gotalarm) 109338905Sborman break; 109438905Sborman gotalarm = 0; 109540242Sborman sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line); 109640242Sborman (void) write(net, tbuf, strlen(tbuf)); 109738905Sborman } 109838905Sborman if (n < 0 && gotalarm) 109938905Sborman fatal(net, "/etc/init didn't start login process"); 110038905Sborman pcc += n; 110138905Sborman alarm(0); 110238905Sborman (void) signal(SIGALRM, SIG_DFL); 110338905Sborman 110438905Sborman return; 110538905Sborman #endif /* NEWINIT */ 110638905Sborman } 110738905Sborman 110838905Sborman char *envinit[3]; 110944364Sborman extern char **environ; 111038905Sborman 111144364Sborman init_env() 111244364Sborman { 111344364Sborman extern char *getenv(); 111444364Sborman char **envp; 111544364Sborman 111644364Sborman envp = envinit; 111744364Sborman if (*envp = getenv("TZ")) 111844364Sborman *envp++ -= 3; 111944364Sborman #ifdef CRAY 112044364Sborman else 112144364Sborman *envp++ = "TZ=GMT0"; 112244364Sborman #endif 112344364Sborman *envp = 0; 112444364Sborman environ = envinit; 112544364Sborman } 112644364Sborman 112744364Sborman #ifdef CRAY 112838905Sborman /* 112944364Sborman * These are environment variable that we 113044364Sborman * don't put on the argument line. 113144364Sborman */ 113244364Sborman char *invalid[] = { 113344364Sborman "USER=", /* Set up by login */ 113444364Sborman "HOME=", /* Set up by login */ 113544364Sborman "LOGNAME=", /* Set up by login */ 113644364Sborman "TMPDIR=", /* Set up by login */ 113744364Sborman "SHELL=", /* Set up by login */ 113844364Sborman "PATH=", /* Set up by login */ 113944364Sborman "MAIL=", /* Set up by login */ 114044364Sborman "TZ=", /* Login gets it from the environment */ 114144364Sborman "TERM=", /* Login gets it from the environment */ 114244364Sborman 0 114344364Sborman }; 114444364Sborman #endif 114544364Sborman 114644364Sborman #ifndef NEWINIT 114744364Sborman 114844364Sborman /* 114945234Sborman * start_login(host) 115038905Sborman * 115138905Sborman * Assuming that we are now running as a child processes, this 115238905Sborman * function will turn us into the login process. 115338905Sborman */ 115438905Sborman 115545234Sborman start_login(host) 115638905Sborman char *host; 115738905Sborman { 115844364Sborman register char *cp; 115944364Sborman register char **argv; 116044364Sborman char **addarg(); 116138905Sborman #ifdef CRAY 116244364Sborman register char **cpp, **cpp2; 116338905Sborman #endif /* CRAY */ 116438905Sborman 116538905Sborman /* 116638905Sborman * -h : pass on name of host. 116738905Sborman * WARNING: -h is accepted by login if and only if 116838905Sborman * getuid() == 0. 116938905Sborman * -p : don't clobber the environment (so terminal type stays set). 117038905Sborman */ 117144364Sborman argv = addarg(0, "login"); 117244364Sborman argv = addarg(argv, "-h"); 117344364Sborman argv = addarg(argv, host); 117444364Sborman #if !defined(CRAY) && !defined(NO_LOGIN_P) 117544364Sborman argv = addarg(argv, "-p"); 117638905Sborman #endif 117744364Sborman #ifdef BFTPDAEMON 117844364Sborman /* 117944364Sborman * Are we working as the bftp daemon? If so, then ask login 118044364Sborman * to start bftp instead of shell. 118144364Sborman */ 118244364Sborman if (bftpd) { 118344364Sborman argv = addarg(argv, "-e"); 118444364Sborman argv = addarg(argv, BFTPPATH); 118544364Sborman } else 118644364Sborman #endif 118744364Sborman if (getenv("USER")) { 118844364Sborman argv = addarg(argv, getenv("USER")); 118944364Sborman } 119044364Sborman #ifdef CRAY 119144364Sborman for (cpp = environ; *cpp; cpp++) { 119244364Sborman for (cpp2 = invalid; *cpp2; cpp2++) 119344364Sborman if (strncmp(*cpp2, *cpp, strlen(*cpp2)) == 0) 119444364Sborman break; 119544364Sborman if (*cpp2) 119644364Sborman continue; 119744364Sborman argv = addarg(argv, *cpp); 119844364Sborman } 119944364Sborman #endif 120044364Sborman 120144364Sborman execv(_PATH_LOGIN, argv); 120244364Sborman 120338905Sborman syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN); 120438905Sborman fatalperror(net, _PATH_LOGIN); 120538905Sborman /*NOTREACHED*/ 120638905Sborman } 120744364Sborman 120844364Sborman char ** 120944364Sborman addarg(argv, val) 121044364Sborman register char **argv; 121144364Sborman register char *val; 121244364Sborman { 121344364Sborman register char **cpp; 121444364Sborman char *malloc(); 121544364Sborman 121644364Sborman if (argv == NULL) { 121744364Sborman /* 121844364Sborman * 10 entries, a leading length, and a null 121944364Sborman */ 122044364Sborman argv = (char **)malloc(sizeof(*argv) * 12); 122144364Sborman if (argv == NULL) 122244364Sborman return(NULL); 122344364Sborman *argv++ = (char *)10; 122444364Sborman *argv = (char *)0; 122544364Sborman } 122644364Sborman for (cpp = argv; *cpp; cpp++) 122744364Sborman ; 122844364Sborman if (cpp == &argv[(int)argv[-1]]) { 122944364Sborman --argv; 123044364Sborman *argv = (char *)((int)(*argv) + 10); 123144364Sborman argv = (char **)realloc(argv, (int)(*argv) + 2); 123244364Sborman if (argv == NULL) 123344364Sborman return(NULL); 123444364Sborman argv++; 123544364Sborman cpp = &argv[(int)argv[-1] - 10]; 123644364Sborman } 123744364Sborman *cpp++ = val; 123844364Sborman *cpp = 0; 123944364Sborman return(argv); 124044364Sborman } 124138905Sborman #endif NEWINIT 124238905Sborman 124338905Sborman /* 124438905Sborman * cleanup() 124538905Sborman * 124638905Sborman * This is the routine to call when we are all through, to 124738905Sborman * clean up anything that needs to be cleaned up. 124838905Sborman */ 124945234Sborman void 125038905Sborman cleanup() 125138905Sborman { 125238905Sborman 125338905Sborman #ifndef CRAY 125445234Sborman # if (BSD > 43) || defined(convex) 125538905Sborman char *p; 125638905Sborman 125738905Sborman p = line + sizeof("/dev/") - 1; 125838905Sborman if (logout(p)) 125938905Sborman logwtmp(p, "", ""); 126038905Sborman (void)chmod(line, 0666); 126138905Sborman (void)chown(line, 0, 0); 126238905Sborman *p = 'p'; 126338905Sborman (void)chmod(line, 0666); 126438905Sborman (void)chown(line, 0, 0); 126538905Sborman # else 126638905Sborman rmut(); 126738905Sborman vhangup(); /* XXX */ 126838905Sborman # endif 126938905Sborman (void) shutdown(net, 2); 127038905Sborman #else /* CRAY */ 127138905Sborman # ifndef NEWINIT 127238905Sborman rmut(line); 127338905Sborman (void) shutdown(net, 2); 127438905Sborman kill(0, SIGHUP); 127538905Sborman # else /* NEWINIT */ 127638905Sborman (void) shutdown(net, 2); 127738905Sborman # endif /* NEWINT */ 127838905Sborman #endif /* CRAY */ 127938905Sborman exit(1); 128038905Sborman } 128138905Sborman 128238905Sborman #if defined(CRAY) && !defined(NEWINIT) 128338905Sborman /* 128438905Sborman * _utmp_sig_rcv 128538905Sborman * utmp_sig_init 128638905Sborman * utmp_sig_wait 128738905Sborman * These three functions are used to coordinate the handling of 128838905Sborman * the utmp file between the server and the soon-to-be-login shell. 128938905Sborman * The server actually creates the utmp structure, the child calls 129038905Sborman * utmp_sig_wait(), until the server calls utmp_sig_notify() and 129138905Sborman * signals the future-login shell to proceed. 129238905Sborman */ 129338905Sborman static int caught=0; /* NZ when signal intercepted */ 129438905Sborman static void (*func)(); /* address of previous handler */ 129538905Sborman 129638905Sborman void 129738905Sborman _utmp_sig_rcv(sig) 129838905Sborman int sig; 129938905Sborman { 130038905Sborman caught = 1; 130138905Sborman (void) signal(SIGUSR1, func); 130238905Sborman } 130338905Sborman 130438905Sborman utmp_sig_init() 130538905Sborman { 130638905Sborman /* 130738905Sborman * register signal handler for UTMP creation 130838905Sborman */ 130938905Sborman if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) 131038905Sborman fatalperror(net, "telnetd/signal"); 131138905Sborman } 131238905Sborman 131344364Sborman utmp_sig_reset() 131444364Sborman { 131544364Sborman (void) signal(SIGUSR1, func); /* reset handler to default */ 131644364Sborman } 131744364Sborman 131838905Sborman utmp_sig_wait() 131938905Sborman { 132038905Sborman /* 132138905Sborman * Wait for parent to write our utmp entry. 132238905Sborman */ 132338905Sborman sigoff(); 132438905Sborman while (caught == 0) { 132538905Sborman pause(); /* wait until we get a signal (sigon) */ 132638905Sborman sigoff(); /* turn off signals while we check caught */ 132738905Sborman } 132838905Sborman sigon(); /* turn on signals again */ 132938905Sborman } 133038905Sborman 133138905Sborman utmp_sig_notify(pid) 133238905Sborman { 133338905Sborman kill(pid, SIGUSR1); 133438905Sborman } 133538905Sborman #endif /* defined(CRAY) && !defined(NEWINIT) */ 133638905Sborman 133738905Sborman /* 133838905Sborman * rmut() 133938905Sborman * 134038905Sborman * This is the function called by cleanup() to 134138905Sborman * remove the utmp entry for this person. 134238905Sborman */ 134338905Sborman 134438905Sborman #if !defined(CRAY) && BSD <= 43 134538905Sborman rmut() 134638905Sborman { 134738905Sborman register f; 134838905Sborman int found = 0; 134938905Sborman struct utmp *u, *utmp; 135038905Sborman int nutmp; 135138905Sborman struct stat statbf; 135238905Sborman char *malloc(); 135338905Sborman long time(); 135438905Sborman off_t lseek(); 135538905Sborman 135638905Sborman f = open(utmpf, O_RDWR); 135738905Sborman if (f >= 0) { 135838905Sborman (void) fstat(f, &statbf); 135938905Sborman utmp = (struct utmp *)malloc((unsigned)statbf.st_size); 136038905Sborman if (!utmp) 136138905Sborman syslog(LOG_ERR, "utmp malloc failed"); 136238905Sborman if (statbf.st_size && utmp) { 136338905Sborman nutmp = read(f, (char *)utmp, (int)statbf.st_size); 136438905Sborman nutmp /= sizeof(struct utmp); 136538905Sborman 136638905Sborman for (u = utmp ; u < &utmp[nutmp] ; u++) { 136738905Sborman if (SCMPN(u->ut_line, line+5) || 136838905Sborman u->ut_name[0]==0) 136938905Sborman continue; 137038905Sborman (void) lseek(f, ((long)u)-((long)utmp), L_SET); 137138905Sborman SCPYN(u->ut_name, ""); 137238905Sborman SCPYN(u->ut_host, ""); 137338905Sborman (void) time(&u->ut_time); 137438905Sborman (void) write(f, (char *)u, sizeof(wtmp)); 137538905Sborman found++; 137638905Sborman } 137738905Sborman } 137838905Sborman (void) close(f); 137938905Sborman } 138038905Sborman if (found) { 138138905Sborman f = open(wtmpf, O_WRONLY|O_APPEND); 138238905Sborman if (f >= 0) { 138338905Sborman SCPYN(wtmp.ut_line, line+5); 138438905Sborman SCPYN(wtmp.ut_name, ""); 138538905Sborman SCPYN(wtmp.ut_host, ""); 138638905Sborman (void) time(&wtmp.ut_time); 138738905Sborman (void) write(f, (char *)&wtmp, sizeof(wtmp)); 138838905Sborman (void) close(f); 138938905Sborman } 139038905Sborman } 139138905Sborman (void) chmod(line, 0666); 139238905Sborman (void) chown(line, 0, 0); 139338905Sborman line[strlen("/dev/")] = 'p'; 139438905Sborman (void) chmod(line, 0666); 139538905Sborman (void) chown(line, 0, 0); 139638905Sborman } /* end of rmut */ 139738905Sborman #endif /* CRAY */ 1398