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*44364Sborman static char sccsid[] = "@(#)sys_term.c 5.8 (Berkeley) 06/28/90"; 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 32*44364Sborman #ifdef STREAMS 33*44364Sborman #include <sys/stream.h> 34*44364Sborman #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 53*44364Sborman #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC) 54*44364Sborman # define EXTPROC 0400 55*44364Sborman #endif 56*44364Sborman 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; 6538905Sborman #else /* USE_TERMIO */ 6638905Sborman # ifdef SYSV_TERMIO 6738905Sborman # define termios termio 6838905Sborman # endif 6939974Ssklower # ifndef TCSETA 70*44364Sborman # ifdef TCSETS 71*44364Sborman # define TCSETA TCSETS 72*44364Sborman # define TCGETA TCGETS 73*44364Sborman # else 74*44364Sborman # define TCSETA TIOCSETA 75*44364Sborman # define TCGETA TIOCGETA 76*44364Sborman # endif 7739974Ssklower # endif /* 4.4BSD */ 7838905Sborman struct termios termbuf, termbuf2; /* pty control structure */ 7938905Sborman #endif /* USE_TERMIO */ 8038905Sborman 8138905Sborman /* 8238905Sborman * init_termbuf() 8338905Sborman * copy_termbuf(cp) 8438905Sborman * set_termbuf() 8538905Sborman * 8638905Sborman * These three routines are used to get and set the "termbuf" structure 8738905Sborman * to and from the kernel. init_termbuf() gets the current settings. 8838905Sborman * copy_termbuf() hands in a new "termbuf" to write to the kernel, and 8938905Sborman * set_termbuf() writes the structure into the kernel. 9038905Sborman */ 9138905Sborman 9238905Sborman init_termbuf() 9338905Sborman { 9438905Sborman #ifndef USE_TERMIO 9538905Sborman (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg); 9638905Sborman (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc); 9738905Sborman (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc); 9838905Sborman # ifdef TIOCGSTATE 9938905Sborman (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state); 10038905Sborman # endif 10138905Sborman #else 10238905Sborman (void) ioctl(pty, TCGETA, (char *)&termbuf); 10338905Sborman #endif 10438905Sborman termbuf2 = termbuf; 10538905Sborman } 10638905Sborman 10738905Sborman #if defined(LINEMODE) && defined(TIOCPKT_IOCTL) 10838905Sborman copy_termbuf(cp, len) 10938905Sborman char *cp; 11038905Sborman int len; 11138905Sborman { 11238905Sborman if (len > sizeof(termbuf)) 11338905Sborman len = sizeof(termbuf); 11438905Sborman bcopy(cp, (char *)&termbuf, len); 11538905Sborman termbuf2 = termbuf; 11638905Sborman } 11738905Sborman #endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ 11838905Sborman 11938905Sborman set_termbuf() 12038905Sborman { 12138905Sborman /* 12238905Sborman * Only make the necessary changes. 12338905Sborman */ 12438905Sborman #ifndef USE_TERMIO 12538905Sborman if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg))) 12638905Sborman (void) ioctl(pty, TIOCSETP, (char *)&termbuf.sg); 12738905Sborman if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc))) 12838905Sborman (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc); 12938905Sborman if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc, 13038905Sborman sizeof(termbuf.ltc))) 13138905Sborman (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc); 13238905Sborman if (termbuf.lflags != termbuf2.lflags) 13338905Sborman (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags); 13438905Sborman #else /* USE_TERMIO */ 13538905Sborman if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) 13638905Sborman (void) ioctl(pty, TCSETA, (char *)&termbuf); 13740242Sborman # if defined(CRAY2) && defined(UNCIOS5) 13838905Sborman needtermstat = 1; 13938905Sborman # endif 14038905Sborman #endif /* USE_TERMIO */ 14138905Sborman } 14238905Sborman 14338905Sborman 14438905Sborman /* 14538905Sborman * spcset(func, valp, valpp) 14638905Sborman * 14738905Sborman * This function takes various special characters (func), and 14838905Sborman * sets *valp to the current value of that character, and 14938905Sborman * *valpp to point to where in the "termbuf" structure that 15038905Sborman * value is kept. 15138905Sborman * 15238905Sborman * It returns the SLC_ level of support for this function. 15338905Sborman */ 15438905Sborman 15538905Sborman #ifndef USE_TERMIO 15638905Sborman spcset(func, valp, valpp) 15738905Sborman int func; 15840242Sborman cc_t *valp; 15940242Sborman cc_t **valpp; 16038905Sborman { 16138905Sborman switch(func) { 16238905Sborman case SLC_EOF: 16338905Sborman *valp = termbuf.tc.t_eofc; 16440242Sborman *valpp = (cc_t *)&termbuf.tc.t_eofc; 16538905Sborman return(SLC_VARIABLE); 16638905Sborman case SLC_EC: 16738905Sborman *valp = termbuf.sg.sg_erase; 16840242Sborman *valpp = (cc_t *)&termbuf.sg.sg_erase; 16938905Sborman return(SLC_VARIABLE); 17038905Sborman case SLC_EL: 17138905Sborman *valp = termbuf.sg.sg_kill; 17240242Sborman *valpp = (cc_t *)&termbuf.sg.sg_kill; 17338905Sborman return(SLC_VARIABLE); 17438905Sborman case SLC_IP: 17538905Sborman *valp = termbuf.tc.t_intrc; 17640242Sborman *valpp = (cc_t *)&termbuf.tc.t_intrc; 17738905Sborman return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 17838905Sborman case SLC_ABORT: 17938905Sborman *valp = termbuf.tc.t_quitc; 18040242Sborman *valpp = (cc_t *)&termbuf.tc.t_quitc; 18138905Sborman return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 18238905Sborman case SLC_XON: 18338905Sborman *valp = termbuf.tc.t_startc; 18440242Sborman *valpp = (cc_t *)&termbuf.tc.t_startc; 18538905Sborman return(SLC_VARIABLE); 18638905Sborman case SLC_XOFF: 18738905Sborman *valp = termbuf.tc.t_stopc; 18840242Sborman *valpp = (cc_t *)&termbuf.tc.t_stopc; 18938905Sborman return(SLC_VARIABLE); 19038905Sborman case SLC_AO: 19138905Sborman *valp = termbuf.ltc.t_flushc; 19240242Sborman *valpp = (cc_t *)&termbuf.ltc.t_flushc; 19338905Sborman return(SLC_VARIABLE); 19438905Sborman case SLC_SUSP: 19538905Sborman *valp = termbuf.ltc.t_suspc; 19640242Sborman *valpp = (cc_t *)&termbuf.ltc.t_suspc; 19738905Sborman return(SLC_VARIABLE); 19838905Sborman case SLC_EW: 19938905Sborman *valp = termbuf.ltc.t_werasc; 20040242Sborman *valpp = (cc_t *)&termbuf.ltc.t_werasc; 20138905Sborman return(SLC_VARIABLE); 20238905Sborman case SLC_RP: 20338905Sborman *valp = termbuf.ltc.t_rprntc; 20440242Sborman *valpp = (cc_t *)&termbuf.ltc.t_rprntc; 20538905Sborman return(SLC_VARIABLE); 20638905Sborman case SLC_LNEXT: 20738905Sborman *valp = termbuf.ltc.t_lnextc; 20840242Sborman *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 20938905Sborman return(SLC_VARIABLE); 21040242Sborman case SLC_FORW1: 21140242Sborman *valp = termbuf.tc.t_brkc; 21240242Sborman *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 21340242Sborman return(SLC_VARIABLE); 21438905Sborman case SLC_BRK: 21538905Sborman case SLC_SYNCH: 21638905Sborman case SLC_AYT: 21738905Sborman case SLC_EOR: 21840242Sborman *valp = (cc_t)0; 21940242Sborman *valpp = (cc_t *)0; 22038905Sborman return(SLC_DEFAULT); 22138905Sborman default: 22240242Sborman *valp = (cc_t)0; 22340242Sborman *valpp = (cc_t *)0; 22438905Sborman return(SLC_NOSUPPORT); 22538905Sborman } 22638905Sborman } 22738905Sborman 22838905Sborman #else /* USE_TERMIO */ 22938905Sborman 23038905Sborman spcset(func, valp, valpp) 23138905Sborman int func; 23240242Sborman cc_t *valp; 23340242Sborman cc_t **valpp; 23438905Sborman { 23539503Sborman 23639503Sborman #define setval(a, b) *valp = termbuf.c_cc[a]; \ 23739503Sborman *valpp = &termbuf.c_cc[a]; \ 23839503Sborman return(b); 23940242Sborman #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); 24039503Sborman 24138905Sborman switch(func) { 24238905Sborman case SLC_EOF: 24339503Sborman setval(VEOF, SLC_VARIABLE); 24438905Sborman case SLC_EC: 24539503Sborman setval(VERASE, SLC_VARIABLE); 24638905Sborman case SLC_EL: 24739503Sborman setval(VKILL, SLC_VARIABLE); 24838905Sborman case SLC_IP: 24939503Sborman setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 25038905Sborman case SLC_ABORT: 25139503Sborman setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 25238905Sborman case SLC_XON: 25339503Sborman #ifdef VSTART 25439503Sborman setval(VSTART, SLC_VARIABLE); 25539503Sborman #else 25639503Sborman defval(0x13); 25739503Sborman #endif 25838905Sborman case SLC_XOFF: 25939503Sborman #ifdef VSTOP 26039503Sborman setval(VSTOP, SLC_VARIABLE); 26139503Sborman #else 26239503Sborman defval(0x11); 26339503Sborman #endif 26438905Sborman case SLC_EW: 26539503Sborman #ifdef VWERASE 26639503Sborman setval(VWERASE, SLC_VARIABLE); 26739503Sborman #else 26839503Sborman defval(0); 26939503Sborman #endif 27038905Sborman case SLC_RP: 27139503Sborman #ifdef VREPRINT 27239503Sborman setval(VREPRINT, SLC_VARIABLE); 27339503Sborman #else 27439503Sborman defval(0); 27539503Sborman #endif 27638905Sborman case SLC_LNEXT: 27739503Sborman #ifdef VLNEXT 27839503Sborman setval(VLNEXT, SLC_VARIABLE); 27939503Sborman #else 28039503Sborman defval(0); 28139503Sborman #endif 28239503Sborman case SLC_AO: 283*44364Sborman #ifdef VFLUSHO 284*44364Sborman setval(VFLUSHO, SLC_VARIABLE|SLC_FLUSHOUT); 28539503Sborman #else 28639503Sborman defval(0); 28739503Sborman #endif 28839503Sborman case SLC_SUSP: 28939503Sborman #ifdef VSUSP 29039503Sborman setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); 29139503Sborman #else 29239503Sborman defval(0); 29339503Sborman #endif 29440242Sborman #ifdef VEOL 29540242Sborman case SLC_FORW1: 29640242Sborman setval(VEOL, SLC_VARIABLE); 29740242Sborman #endif 29840242Sborman #ifdef VEOL2 29940242Sborman case SLC_FORW2: 30040242Sborman setval(VEOL2, SLC_VARIABLE); 30140242Sborman #endif 30239503Sborman 30338905Sborman case SLC_BRK: 30438905Sborman case SLC_SYNCH: 30538905Sborman case SLC_AYT: 30638905Sborman case SLC_EOR: 30739503Sborman defval(0); 30839503Sborman 30938905Sborman default: 31038905Sborman *valp = 0; 31138905Sborman *valpp = 0; 31238905Sborman return(SLC_NOSUPPORT); 31338905Sborman } 31438905Sborman } 31538905Sborman #endif /* USE_TERMIO */ 31638905Sborman 31740242Sborman #ifdef CRAY 31838905Sborman /* 31940242Sborman * getnpty() 32040242Sborman * 32140242Sborman * Return the number of pty's configured into the system. 32240242Sborman */ 32340242Sborman getnpty() 32440242Sborman { 32540242Sborman #ifdef _SC_CRAY_NPTY 32640242Sborman return sysconf(_SC_CRAY_NPTY); 32740242Sborman #else 32840242Sborman return 128; 32940242Sborman #endif /* _SC_CRAY_NPTY */ 33040242Sborman } 33140242Sborman #endif /* CRAY */ 33240242Sborman 33340242Sborman /* 33438905Sborman * getpty() 33538905Sborman * 33638905Sborman * Allocate a pty. As a side effect, the external character 33738905Sborman * array "line" contains the name of the slave side. 33838905Sborman * 33938905Sborman * Returns the file descriptor of the opened pty. 34038905Sborman */ 34138905Sborman char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 34238905Sborman 34338905Sborman getpty() 34438905Sborman { 34538905Sborman register int p; 34638905Sborman #ifndef CRAY 34738905Sborman register char c, *p1, *p2; 34838905Sborman register int i; 34938905Sborman 35038905Sborman (void) sprintf(line, "/dev/ptyXX"); 35138905Sborman p1 = &line[8]; 35238905Sborman p2 = &line[9]; 35338905Sborman 35438905Sborman for (c = 'p'; c <= 's'; c++) { 35538905Sborman struct stat stb; 35638905Sborman 35738905Sborman *p1 = c; 35838905Sborman *p2 = '0'; 35938905Sborman if (stat(line, &stb) < 0) 36038905Sborman break; 36138905Sborman for (i = 0; i < 16; i++) { 36238905Sborman *p2 = "0123456789abcdef"[i]; 36338905Sborman p = open(line, 2); 36438905Sborman if (p > 0) { 36538905Sborman line[5] = 't'; 36638905Sborman return(p); 36738905Sborman } 36838905Sborman } 36938905Sborman } 37038905Sborman #else /* CRAY */ 37138905Sborman register int npty; 37238905Sborman extern lowpty, highpty; 37338905Sborman 37438905Sborman for (npty = lowpty; npty <= highpty; npty++) { 37538905Sborman (void) sprintf(line, "/dev/pty/%03d", npty); 37638905Sborman p = open(line, 2); 37738905Sborman if (p < 0) 37838905Sborman continue; 37938905Sborman (void) sprintf(line, "/dev/ttyp%03d", npty); 38038905Sborman if (access(line, 6) == 0) 38138905Sborman return(p); 38238905Sborman else { 38338905Sborman /* no tty side to pty so skip it */ 38438905Sborman (void) close(p); 38538905Sborman } 38638905Sborman } 38738905Sborman #endif /* CRAY */ 38838905Sborman return(-1); 38938905Sborman } 39038905Sborman 39138905Sborman #ifdef LINEMODE 39238905Sborman /* 39338905Sborman * tty_flowmode() Find out if flow control is enabled or disabled. 39438905Sborman * tty_linemode() Find out if linemode (external processing) is enabled. 39538905Sborman * tty_setlinemod(on) Turn on/off linemode. 39638905Sborman * tty_isecho() Find out if echoing is turned on. 39738905Sborman * tty_setecho(on) Enable/disable character echoing. 39838905Sborman * tty_israw() Find out if terminal is in RAW mode. 39938905Sborman * tty_binaryin(on) Turn on/off BINARY on input. 40038905Sborman * tty_binaryout(on) Turn on/off BINARY on output. 40138905Sborman * tty_isediting() Find out if line editing is enabled. 40238905Sborman * tty_istrapsig() Find out if signal trapping is enabled. 40338905Sborman * tty_setedit(on) Turn on/off line editing. 40438905Sborman * tty_setsig(on) Turn on/off signal trapping. 405*44364Sborman * tty_issofttab() Find out if tab expansion is enabled. 406*44364Sborman * tty_setsofttab(on) Turn on/off soft tab expansion. 407*44364Sborman * tty_islitecho() Find out if typed control chars are echoed literally 408*44364Sborman * tty_setlitecho() Turn on/off literal echo of control chars 40938905Sborman * tty_tspeed(val) Set transmit speed to val. 41038905Sborman * tty_rspeed(val) Set receive speed to val. 41138905Sborman */ 41238905Sborman 41338905Sborman tty_flowmode() 41438905Sborman { 41538905Sborman #ifndef USE_TERMIO 41638905Sborman return((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0); 41738905Sborman #else 41838905Sborman return(termbuf.c_iflag & IXON ? 1 : 0); 41938905Sborman #endif 42038905Sborman } 42138905Sborman 42238905Sborman tty_linemode() 42338905Sborman { 42438905Sborman #ifndef USE_TERMIO 42538905Sborman return(termbuf.state & TS_EXTPROC); 42638905Sborman #else 42738905Sborman return(termbuf.c_lflag & EXTPROC); 42838905Sborman #endif 42938905Sborman } 43038905Sborman 43138905Sborman tty_setlinemode(on) 43238905Sborman int on; 43338905Sborman { 43438905Sborman #ifdef TIOCEXT 43538905Sborman (void) ioctl(pty, TIOCEXT, (char *)&on); 43638905Sborman #else /* !TIOCEXT */ 43738905Sborman #ifdef EXTPROC 43838905Sborman if (on) 43938905Sborman termbuf.c_lflag |= EXTPROC; 44038905Sborman else 44138905Sborman termbuf.c_lflag &= ~EXTPROC; 44238905Sborman #endif 44338905Sborman set_termbuf(); 44438905Sborman #endif /* TIOCEXT */ 44538905Sborman } 44638905Sborman 44738905Sborman tty_isecho() 44838905Sborman { 44938905Sborman #ifndef USE_TERMIO 45038905Sborman return (termbuf.sg.sg_flags & ECHO); 45138905Sborman #else 45238905Sborman return (termbuf.c_lflag & ECHO); 45338905Sborman #endif 45438905Sborman } 45538905Sborman #endif /* LINEMODE */ 45638905Sborman 45738905Sborman tty_setecho(on) 45838905Sborman { 45938905Sborman #ifndef USE_TERMIO 46038905Sborman if (on) 46138905Sborman termbuf.sg.sg_flags |= ECHO|CRMOD; 46238905Sborman else 46338905Sborman termbuf.sg.sg_flags &= ~(ECHO|CRMOD); 46438905Sborman #else 46538905Sborman if (on) 46638905Sborman termbuf.c_lflag |= ECHO; 46738905Sborman else 46838905Sborman termbuf.c_lflag &= ~ECHO; 46938905Sborman #endif 47038905Sborman } 47138905Sborman 47238905Sborman #if defined(LINEMODE) && defined(KLUDGELINEMODE) 47338905Sborman tty_israw() 47438905Sborman { 47538905Sborman #ifndef USE_TERMIO 47638905Sborman return(termbuf.sg.sg_flags & RAW); 47738905Sborman #else 47838905Sborman return(!(termbuf.c_lflag & ICANON)); 47938905Sborman #endif 48038905Sborman } 48138905Sborman #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 48238905Sborman 48338905Sborman tty_binaryin(on) 48438905Sborman { 48538905Sborman #ifndef USE_TERMIO 48638905Sborman if (on) 48738905Sborman termbuf.lflags |= LPASS8; 48838905Sborman else 48938905Sborman termbuf.lflags &= ~LPASS8; 49038905Sborman #else 49138905Sborman if (on) { 49238905Sborman termbuf.c_lflag &= ~ISTRIP; 49338905Sborman } else { 49438905Sborman termbuf.c_lflag |= ISTRIP; 49538905Sborman } 49638905Sborman #endif 49738905Sborman } 49838905Sborman 49938905Sborman tty_binaryout(on) 50038905Sborman { 50138905Sborman #ifndef USE_TERMIO 50238905Sborman if (on) 50338905Sborman termbuf.lflags |= LLITOUT; 50438905Sborman else 50538905Sborman termbuf.lflags &= ~LLITOUT; 50638905Sborman #else 50738905Sborman if (on) { 50838905Sborman termbuf.c_cflag &= ~(CSIZE|PARENB); 50938905Sborman termbuf.c_cflag |= CS8; 51038905Sborman termbuf.c_oflag &= ~OPOST; 51138905Sborman } else { 51238905Sborman termbuf.c_cflag &= ~CSIZE; 51338905Sborman termbuf.c_cflag |= CS7|PARENB; 51438905Sborman termbuf.c_oflag |= OPOST; 51538905Sborman } 51638905Sborman #endif 51738905Sborman } 51838905Sborman 51938905Sborman tty_isbinaryin() 52038905Sborman { 52138905Sborman #ifndef USE_TERMIO 52238905Sborman return(termbuf.lflags & LPASS8); 52338905Sborman #else 52439503Sborman return(!(termbuf.c_iflag & ISTRIP)); 52538905Sborman #endif 52638905Sborman } 52738905Sborman 52838905Sborman tty_isbinaryout() 52938905Sborman { 53038905Sborman #ifndef USE_TERMIO 53138905Sborman return(termbuf.lflags & LLITOUT); 53238905Sborman #else 53339503Sborman return(!(termbuf.c_oflag&OPOST)); 53438905Sborman #endif 53538905Sborman } 53638905Sborman 53738905Sborman #ifdef LINEMODE 53838905Sborman tty_isediting() 53938905Sborman { 54038905Sborman #ifndef USE_TERMIO 54138905Sborman return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); 54238905Sborman #else 54338905Sborman return(termbuf.c_lflag & ICANON); 54438905Sborman #endif 54538905Sborman } 54638905Sborman 54738905Sborman tty_istrapsig() 54838905Sborman { 54938905Sborman #ifndef USE_TERMIO 55038905Sborman return(!(termbuf.sg.sg_flags&RAW)); 55138905Sborman #else 55238905Sborman return(termbuf.c_lflag & ISIG); 55338905Sborman #endif 55438905Sborman } 55538905Sborman 55638905Sborman tty_setedit(on) 55738905Sborman int on; 55838905Sborman { 55938905Sborman #ifndef USE_TERMIO 56038905Sborman if (on) 56138905Sborman termbuf.sg.sg_flags &= ~CBREAK; 56238905Sborman else 56338905Sborman termbuf.sg.sg_flags |= CBREAK; 56438905Sborman #else 56538905Sborman if (on) 56638905Sborman termbuf.c_lflag |= ICANON; 56738905Sborman else 56838905Sborman termbuf.c_lflag &= ~ICANON; 56938905Sborman #endif 57038905Sborman } 57138905Sborman 57238905Sborman tty_setsig(on) 57338905Sborman int on; 57438905Sborman { 57538905Sborman #ifndef USE_TERMIO 57638905Sborman if (on) 57738905Sborman ; 57838905Sborman #else 57938905Sborman if (on) 58038905Sborman termbuf.c_lflag |= ISIG; 58138905Sborman else 58238905Sborman termbuf.c_lflag &= ~ISIG; 58338905Sborman #endif 58438905Sborman } 58538905Sborman #endif /* LINEMODE */ 58638905Sborman 587*44364Sborman tty_issofttab() 588*44364Sborman { 589*44364Sborman #ifndef USE_TERMIO 590*44364Sborman return (termbuf.sg.sg_flags & XTABS); 591*44364Sborman #else 592*44364Sborman # ifdef OXTABS 593*44364Sborman return (termbuf.c_oflag & OXTABS); 594*44364Sborman # endif 595*44364Sborman # ifdef TABDLY 596*44364Sborman return ((termbuf.c_oflag & TABDLY) == TAB3); 597*44364Sborman # endif 598*44364Sborman #endif 599*44364Sborman } 600*44364Sborman 601*44364Sborman tty_setsofttab(on) 602*44364Sborman int on; 603*44364Sborman { 604*44364Sborman #ifndef USE_TERMIO 605*44364Sborman if (on) 606*44364Sborman termbuf.sg.sg_flags |= XTABS; 607*44364Sborman else 608*44364Sborman termbuf.sg.sg_flags &= ~XTABS; 609*44364Sborman #else 610*44364Sborman if (on) { 611*44364Sborman # ifdef OXTABS 612*44364Sborman termbuf.c_oflag |= OXTABS; 613*44364Sborman # endif 614*44364Sborman # ifdef TABDLY 615*44364Sborman termbuf.c_oflag &= ~TABDLY; 616*44364Sborman termbuf.c_oflag |= TAB3; 617*44364Sborman # endif 618*44364Sborman } else { 619*44364Sborman # ifdef OXTABS 620*44364Sborman termbuf.c_oflag &= ~OXTABS; 621*44364Sborman # endif 622*44364Sborman # ifdef TABDLY 623*44364Sborman termbuf.c_oflag &= ~TABDLY; 624*44364Sborman termbuf.c_oflag |= TAB0; 625*44364Sborman # endif 626*44364Sborman } 627*44364Sborman #endif 628*44364Sborman } 629*44364Sborman 630*44364Sborman tty_islitecho() 631*44364Sborman { 632*44364Sborman #ifndef USE_TERMIO 633*44364Sborman return (!(termbuf.sg.sg_flags & CTLECH)); 634*44364Sborman #else 635*44364Sborman # ifdef ECHOCTL 636*44364Sborman return (!(termbuf.c_lflag & ECHOCTL)); 637*44364Sborman # endif 638*44364Sborman # ifdef TCTLECH 639*44364Sborman return (!(termbuf.c_lflag & TCTLECH)); 640*44364Sborman # endif 641*44364Sborman # if !defined(ECHOCTL) && !defined(TCTLECH) 642*44364Sborman return (0); /* assumes ctl chars are echoed '^x' */ 643*44364Sborman # endif 644*44364Sborman #endif 645*44364Sborman } 646*44364Sborman 647*44364Sborman tty_setlitecho(on) 648*44364Sborman int on; 649*44364Sborman { 650*44364Sborman #ifndef USE_TERMIO 651*44364Sborman if (on) 652*44364Sborman termbuf.sg.sg_flags &= ~CTLECH; 653*44364Sborman else 654*44364Sborman termbuf.sg.sg_flags |= CTLECH; 655*44364Sborman #else 656*44364Sborman # ifdef ECHOCTL 657*44364Sborman if (on) 658*44364Sborman termbuf.c_lflag &= ~ECHOCTL; 659*44364Sborman else 660*44364Sborman termbuf.c_lflag |= ECHOCTL; 661*44364Sborman # endif 662*44364Sborman # ifdef TCTLECH 663*44364Sborman if (on) 664*44364Sborman termbuf.c_lflag &= ~TCTLECH; 665*44364Sborman else 666*44364Sborman termbuf.c_lflag |= TCTLECH; 667*44364Sborman # endif 668*44364Sborman #endif 669*44364Sborman } 670*44364Sborman 67138905Sborman /* 67238905Sborman * A table of available terminal speeds 67338905Sborman */ 67438905Sborman struct termspeeds { 67538905Sborman int speed; 67638905Sborman int value; 67738905Sborman } termspeeds[] = { 67838905Sborman { 0, B0 }, { 50, B50 }, { 75, B75 }, 67938905Sborman { 110, B110 }, { 134, B134 }, { 150, B150 }, 68038905Sborman { 200, B200 }, { 300, B300 }, { 600, B600 }, 68138905Sborman { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 68238905Sborman { 4800, B4800 }, { 9600, B9600 }, { 19200, B9600 }, 68338905Sborman { 38400, B9600 }, { -1, B9600 } 68438905Sborman }; 68538905Sborman 68638905Sborman tty_tspeed(val) 68738905Sborman { 68838905Sborman register struct termspeeds *tp; 68938905Sborman 69038905Sborman for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 69138905Sborman ; 69238905Sborman #ifndef USE_TERMIO 69338905Sborman termbuf.sg.sg_ospeed = tp->value; 69438905Sborman #else 695*44364Sborman # ifdef CBAUD 69638905Sborman termbuf.c_cflag &= ~CBAUD; 69738905Sborman termbuf.c_cflag |= tp->value; 69838905Sborman # else 69938905Sborman termbuf.c_ospeed = tp->value; 70038905Sborman # endif 70138905Sborman #endif 70238905Sborman } 70338905Sborman 70438905Sborman tty_rspeed(val) 70538905Sborman { 70638905Sborman register struct termspeeds *tp; 70738905Sborman 70838905Sborman for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 70938905Sborman ; 71038905Sborman #ifndef USE_TERMIO 71138905Sborman termbuf.sg.sg_ispeed = tp->value; 71238905Sborman #else 713*44364Sborman # ifdef CBAUD 71438905Sborman termbuf.c_cflag &= ~CBAUD; 71538905Sborman termbuf.c_cflag |= tp->value; 71638905Sborman # else 71738905Sborman termbuf.c_ispeed = tp->value; 71838905Sborman # endif 71938905Sborman #endif 72038905Sborman } 72138905Sborman 72240242Sborman #if defined(CRAY2) && defined(UNICOS5) 72338905Sborman tty_isnewmap() 72438905Sborman { 72538905Sborman return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) && 72638905Sborman !(termbuf.c_oflag & ONLRET)); 72738905Sborman } 72838905Sborman #endif 72938905Sborman 73038905Sborman #ifdef CRAY 73138905Sborman # ifndef NEWINIT 73238905Sborman extern struct utmp wtmp; 73338905Sborman extern char wtmpf[]; 73438905Sborman # else /* NEWINIT */ 73538905Sborman int gotalarm; 73640242Sborman /* ARGSUSED */ 73740242Sborman void 73840242Sborman nologinproc(sig) 73940242Sborman int sig; 74038905Sborman { 74138905Sborman gotalarm++; 74238905Sborman } 74338905Sborman # endif /* NEWINIT */ 74438905Sborman #endif /* CRAY */ 74538905Sborman 74638905Sborman /* 74738905Sborman * getptyslave() 74838905Sborman * 74938905Sborman * Open the slave side of the pty, and do any initialization 75038905Sborman * that is necessary. The return value is a file descriptor 75138905Sborman * for the slave side. 75238905Sborman */ 75338905Sborman getptyslave() 75438905Sborman { 75538905Sborman register int t = -1; 75638905Sborman 75738905Sborman #ifndef CRAY 75838905Sborman /* 75938905Sborman * Disassociate self from control terminal and open ttyp side. 76038905Sborman * Set important flags on ttyp and ptyp. 76138905Sborman */ 76238905Sborman t = open(_PATH_TTY, O_RDWR); 76338905Sborman if (t >= 0) { 76438905Sborman (void) ioctl(t, TIOCNOTTY, (char *)0); 76538905Sborman (void) close(t); 76638905Sborman } 76738905Sborman 76838905Sborman t = open(line, O_RDWR); 76938905Sborman if (t < 0) 77038905Sborman fatalperror(net, line); 77138905Sborman if (fchmod(t, 0)) 77238905Sborman fatalperror(net, line); 773*44364Sborman #if BSD <= 43 77438905Sborman (void) signal(SIGHUP, SIG_IGN); 77538905Sborman vhangup(); 77638905Sborman (void) signal(SIGHUP, SIG_DFL); 77738905Sborman t = open(line, O_RDWR); 77838905Sborman if (t < 0) 77938905Sborman fatalperror(net, line); 780*44364Sborman #endif 78138905Sborman 78238905Sborman init_termbuf(); 78338905Sborman #ifndef USE_TERMIO 78440242Sborman termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; 78538905Sborman termbuf.sg.sg_ospeed = termbuf.sg.sg_ispeed = B9600; 78638905Sborman #else 78738905Sborman termbuf.c_lflag |= ECHO; 788*44364Sborman #ifndef OXTABS 789*44364Sborman #define OXTABS 0 790*44364Sborman #endif 79138905Sborman termbuf.c_oflag |= ONLCR|OXTABS; 79238905Sborman termbuf.c_iflag |= ICRNL; 79338905Sborman termbuf.c_iflag &= ~IXOFF; 794*44364Sborman # ifdef CBAUD 795*44364Sborman termbuf.c_cflag &= ~CBAUD; 796*44364Sborman termbuf.c_cflag |= B9600; 797*44364Sborman # else /* CBAUD */ 79838905Sborman termbuf.c_ospeed = termbuf.c_ispeed = B9600; 799*44364Sborman # endif /* CBAUD */ 80038905Sborman #endif 80138905Sborman set_termbuf(); 80238905Sborman #else /* CRAY */ 80338905Sborman (void) chown(line, 0, 0); 80438905Sborman (void) chmod(line, 0600); 80538905Sborman #endif /* CRAY */ 80638905Sborman return(t); 80738905Sborman } 80838905Sborman 80938905Sborman #ifdef NEWINIT 81038905Sborman char *gen_id = "fe"; 81138905Sborman #endif 81238905Sborman 81338905Sborman /* 81438905Sborman * startslave(t, host) 81538905Sborman * 81638905Sborman * Given a file descriptor (t) for a tty, and a hostname, do whatever 81738905Sborman * is necessary to startup the login process on the slave side of the pty. 81838905Sborman */ 81938905Sborman 82038905Sborman /* ARGSUSED */ 82138905Sborman startslave(t, host) 82238905Sborman int t; 82338905Sborman char *host; 82438905Sborman { 82538905Sborman register int i; 82638905Sborman long time(); 82738905Sborman 82838905Sborman #ifndef NEWINIT 82938905Sborman # ifdef CRAY 83038905Sborman utmp_sig_init(); 83138905Sborman # endif /* CRAY */ 83238905Sborman 83338905Sborman if ((i = fork()) < 0) 83438905Sborman fatalperror(net, "fork"); 83538905Sborman if (i) { 83638905Sborman # ifdef CRAY 83738905Sborman /* 83838905Sborman * Cray parent will create utmp entry for child and send 83938905Sborman * signal to child to tell when done. Child waits for signal 84038905Sborman * before doing anything important. 84138905Sborman */ 84238905Sborman register int pid = i; 84338905Sborman 84438905Sborman setpgrp(); 845*44364Sborman utmp_sig_reset(); /* reset handler to default */ 84638905Sborman /* 84738905Sborman * Create utmp entry for child 84838905Sborman */ 84938905Sborman (void) time(&wtmp.ut_time); 85038905Sborman wtmp.ut_type = LOGIN_PROCESS; 85138905Sborman wtmp.ut_pid = pid; 85238905Sborman SCPYN(wtmp.ut_user, "LOGIN"); 85338905Sborman SCPYN(wtmp.ut_host, host); 85438905Sborman SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); 85538905Sborman SCPYN(wtmp.ut_id, wtmp.ut_line+3); 85638905Sborman pututline(&wtmp); 85738905Sborman endutent(); 85838905Sborman if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { 85938905Sborman (void) write(i, (char *)&wtmp, sizeof(struct utmp)); 86038905Sborman (void) close(i); 86138905Sborman } 86238905Sborman utmp_sig_notify(pid); 86338905Sborman # endif /* CRAY */ 86438905Sborman (void) close(t); 86538905Sborman } else { 86638905Sborman start_login(t, host); 86738905Sborman /*NOTREACHED*/ 86838905Sborman } 86938905Sborman #else /* NEWINIT */ 87038905Sborman 87138905Sborman extern char *ptyip; 87238905Sborman struct init_request request; 87340242Sborman void nologinproc(); 87438905Sborman register int n; 87538905Sborman 87638905Sborman /* 87738905Sborman * Init will start up login process if we ask nicely. We only wait 87838905Sborman * for it to start up and begin normal telnet operation. 87938905Sborman */ 88038905Sborman if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { 88138905Sborman char tbuf[128]; 88238905Sborman (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO); 88338905Sborman fatalperror(net, tbuf); 88438905Sborman } 88538905Sborman memset((char *)&request, 0, sizeof(request)); 88638905Sborman request.magic = INIT_MAGIC; 88738905Sborman SCPYN(request.gen_id, gen_id); 88838905Sborman SCPYN(request.tty_id, &line[8]); 88938905Sborman SCPYN(request.host, host); 890*44364Sborman SCPYN(request.term_type, terminaltype); 891*44364Sborman #if !defined(UNICOS5) 89240242Sborman request.signal = SIGCLD; 89340242Sborman request.pid = getpid(); 89440242Sborman #endif 895*44364Sborman #ifdef BFTPDAEMON 896*44364Sborman /* 897*44364Sborman * Are we working as the bftp daemon? 898*44364Sborman */ 899*44364Sborman if (bftpd) { 900*44364Sborman SCPYN(request.exec_name, BFTPPATH); 901*44364Sborman } 902*44364Sborman #endif /* BFTPDAEMON */ 90338905Sborman if (write(i, (char *)&request, sizeof(request)) < 0) { 90438905Sborman char tbuf[128]; 90538905Sborman (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO); 90638905Sborman fatalperror(net, tbuf); 90738905Sborman } 90838905Sborman (void) close(i); 90938905Sborman (void) signal(SIGALRM, nologinproc); 91038905Sborman for (i = 0; ; i++) { 91140242Sborman char tbuf[128]; 91238905Sborman alarm(15); 91338905Sborman n = read(pty, ptyip, BUFSIZ); 91438905Sborman if (i == 3 || n >= 0 || !gotalarm) 91538905Sborman break; 91638905Sborman gotalarm = 0; 91740242Sborman sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line); 91840242Sborman (void) write(net, tbuf, strlen(tbuf)); 91938905Sborman } 92038905Sborman if (n < 0 && gotalarm) 92138905Sborman fatal(net, "/etc/init didn't start login process"); 92238905Sborman pcc += n; 92338905Sborman alarm(0); 92438905Sborman (void) signal(SIGALRM, SIG_DFL); 92538905Sborman 92638905Sborman return; 92738905Sborman #endif /* NEWINIT */ 92838905Sborman } 92938905Sborman 93038905Sborman char *envinit[3]; 931*44364Sborman extern char **environ; 93238905Sborman 933*44364Sborman init_env() 934*44364Sborman { 935*44364Sborman extern char *getenv(); 936*44364Sborman char **envp; 937*44364Sborman 938*44364Sborman envp = envinit; 939*44364Sborman if (*envp = getenv("TZ")) 940*44364Sborman *envp++ -= 3; 941*44364Sborman #ifdef CRAY 942*44364Sborman else 943*44364Sborman *envp++ = "TZ=GMT0"; 944*44364Sborman #endif 945*44364Sborman *envp = 0; 946*44364Sborman environ = envinit; 947*44364Sborman } 948*44364Sborman 949*44364Sborman #ifdef CRAY 95038905Sborman /* 951*44364Sborman * These are environment variable that we 952*44364Sborman * don't put on the argument line. 953*44364Sborman */ 954*44364Sborman char *invalid[] = { 955*44364Sborman "USER=", /* Set up by login */ 956*44364Sborman "HOME=", /* Set up by login */ 957*44364Sborman "LOGNAME=", /* Set up by login */ 958*44364Sborman "TMPDIR=", /* Set up by login */ 959*44364Sborman "SHELL=", /* Set up by login */ 960*44364Sborman "PATH=", /* Set up by login */ 961*44364Sborman "MAIL=", /* Set up by login */ 962*44364Sborman "TZ=", /* Login gets it from the environment */ 963*44364Sborman "TERM=", /* Login gets it from the environment */ 964*44364Sborman 0 965*44364Sborman }; 966*44364Sborman #endif 967*44364Sborman 968*44364Sborman #ifndef NEWINIT 969*44364Sborman 970*44364Sborman /* 97138905Sborman * start_login(t, host) 97238905Sborman * 97338905Sborman * Assuming that we are now running as a child processes, this 97438905Sborman * function will turn us into the login process. 97538905Sborman */ 97638905Sborman 97738905Sborman start_login(t, host) 97838905Sborman int t; 97938905Sborman char *host; 98038905Sborman { 981*44364Sborman register char *cp; 982*44364Sborman register char **argv; 983*44364Sborman char **addarg(); 98438905Sborman #ifdef CRAY 985*44364Sborman register char **cpp, **cpp2; 98638905Sborman utmp_sig_wait(); 98738905Sborman # ifndef TCVHUP 98838905Sborman setpgrp(); 98938905Sborman # endif 99038905Sborman t = open(line, 2); /* open ttyp */ 99138905Sborman if (t < 0) 99238905Sborman fatalperror(net, line); 99338905Sborman # ifdef TCVHUP 99438905Sborman /* 99538905Sborman * Hangup anybody else using this ttyp, then reopen it for 99638905Sborman * ourselves. 99738905Sborman */ 99838905Sborman (void) chown(line, 0, 0); 99938905Sborman (void) chmod(line, 0600); 100038905Sborman (void) signal(SIGHUP, SIG_IGN); 100138905Sborman (void) ioctl(t, TCVHUP, (char *)0); 100238905Sborman (void) signal(SIGHUP, SIG_DFL); 100338905Sborman setpgrp(); 100438905Sborman i = open(line, 2); 100538905Sborman if (i < 0) 100638905Sborman fatalperror(net, line); 100738905Sborman (void) close(t); 100838905Sborman t = i; 100938905Sborman # endif /* TCVHUP */ 101038905Sborman /* 101138905Sborman * set ttyp modes as we like them to be 101238905Sborman */ 101338905Sborman init_termbuf(); 101440242Sborman termbuf.c_oflag = OPOST|ONLCR|TAB3; 101538905Sborman termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; 101638905Sborman termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; 101738905Sborman termbuf.c_cflag = EXTB|HUPCL|CS8; 101838905Sborman set_termbuf(); 101938905Sborman #endif /* CRAY */ 102038905Sborman 102138905Sborman /* 102238905Sborman * set up standard paths before forking to login 102338905Sborman */ 1024*44364Sborman #ifndef NO_SETSID 102538905Sborman if (setsid() < 0) 102638905Sborman fatalperror(net, "setsid"); 1027*44364Sborman #endif 1028*44364Sborman 1029*44364Sborman #ifdef TIOCSCTTY 103038905Sborman if (ioctl(t, TIOCSCTTY, (char *)0) < 0) 103138905Sborman fatalperror(net, "ioctl(sctty)"); 103238905Sborman #endif 103338905Sborman (void) close(net); 103438905Sborman (void) close(pty); 103538905Sborman (void) dup2(t, 0); 103638905Sborman (void) dup2(t, 1); 103738905Sborman (void) dup2(t, 2); 103838905Sborman (void) close(t); 103938905Sborman /* 104038905Sborman * -h : pass on name of host. 104138905Sborman * WARNING: -h is accepted by login if and only if 104238905Sborman * getuid() == 0. 104338905Sborman * -p : don't clobber the environment (so terminal type stays set). 104438905Sborman */ 1045*44364Sborman argv = addarg(0, "login"); 1046*44364Sborman argv = addarg(argv, "-h"); 1047*44364Sborman argv = addarg(argv, host); 1048*44364Sborman #if !defined(CRAY) && !defined(NO_LOGIN_P) 1049*44364Sborman argv = addarg(argv, "-p"); 105038905Sborman #endif 1051*44364Sborman #ifdef BFTPDAEMON 1052*44364Sborman /* 1053*44364Sborman * Are we working as the bftp daemon? If so, then ask login 1054*44364Sborman * to start bftp instead of shell. 1055*44364Sborman */ 1056*44364Sborman if (bftpd) { 1057*44364Sborman argv = addarg(argv, "-e"); 1058*44364Sborman argv = addarg(argv, BFTPPATH); 1059*44364Sborman } else 1060*44364Sborman #endif 1061*44364Sborman if (getenv("USER")) { 1062*44364Sborman argv = addarg(argv, getenv("USER")); 1063*44364Sborman } 1064*44364Sborman #ifdef CRAY 1065*44364Sborman for (cpp = environ; *cpp; cpp++) { 1066*44364Sborman for (cpp2 = invalid; *cpp2; cpp2++) 1067*44364Sborman if (strncmp(*cpp2, *cpp, strlen(*cpp2)) == 0) 1068*44364Sborman break; 1069*44364Sborman if (*cpp2) 1070*44364Sborman continue; 1071*44364Sborman argv = addarg(argv, *cpp); 1072*44364Sborman } 1073*44364Sborman #endif 1074*44364Sborman 1075*44364Sborman execv(_PATH_LOGIN, argv); 1076*44364Sborman 107738905Sborman syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN); 107838905Sborman fatalperror(net, _PATH_LOGIN); 107938905Sborman /*NOTREACHED*/ 108038905Sborman } 1081*44364Sborman 1082*44364Sborman char ** 1083*44364Sborman addarg(argv, val) 1084*44364Sborman register char **argv; 1085*44364Sborman register char *val; 1086*44364Sborman { 1087*44364Sborman register char **cpp; 1088*44364Sborman char *malloc(); 1089*44364Sborman 1090*44364Sborman if (argv == NULL) { 1091*44364Sborman /* 1092*44364Sborman * 10 entries, a leading length, and a null 1093*44364Sborman */ 1094*44364Sborman argv = (char **)malloc(sizeof(*argv) * 12); 1095*44364Sborman if (argv == NULL) 1096*44364Sborman return(NULL); 1097*44364Sborman *argv++ = (char *)10; 1098*44364Sborman *argv = (char *)0; 1099*44364Sborman } 1100*44364Sborman for (cpp = argv; *cpp; cpp++) 1101*44364Sborman ; 1102*44364Sborman if (cpp == &argv[(int)argv[-1]]) { 1103*44364Sborman --argv; 1104*44364Sborman *argv = (char *)((int)(*argv) + 10); 1105*44364Sborman argv = (char **)realloc(argv, (int)(*argv) + 2); 1106*44364Sborman if (argv == NULL) 1107*44364Sborman return(NULL); 1108*44364Sborman argv++; 1109*44364Sborman cpp = &argv[(int)argv[-1] - 10]; 1110*44364Sborman } 1111*44364Sborman *cpp++ = val; 1112*44364Sborman *cpp = 0; 1113*44364Sborman return(argv); 1114*44364Sborman } 111538905Sborman #endif NEWINIT 111638905Sborman 111738905Sborman /* 111838905Sborman * cleanup() 111938905Sborman * 112038905Sborman * This is the routine to call when we are all through, to 112138905Sborman * clean up anything that needs to be cleaned up. 112238905Sborman */ 112338905Sborman cleanup() 112438905Sborman { 112538905Sborman 112638905Sborman #ifndef CRAY 112738905Sborman # if BSD > 43 112838905Sborman char *p; 112938905Sborman 113038905Sborman p = line + sizeof("/dev/") - 1; 113138905Sborman if (logout(p)) 113238905Sborman logwtmp(p, "", ""); 113338905Sborman (void)chmod(line, 0666); 113438905Sborman (void)chown(line, 0, 0); 113538905Sborman *p = 'p'; 113638905Sborman (void)chmod(line, 0666); 113738905Sborman (void)chown(line, 0, 0); 113838905Sborman # else 113938905Sborman rmut(); 114038905Sborman vhangup(); /* XXX */ 114138905Sborman # endif 114238905Sborman (void) shutdown(net, 2); 114338905Sborman #else /* CRAY */ 114438905Sborman # ifndef NEWINIT 114538905Sborman rmut(line); 114638905Sborman (void) shutdown(net, 2); 114738905Sborman kill(0, SIGHUP); 114838905Sborman # else /* NEWINIT */ 114938905Sborman (void) shutdown(net, 2); 115038905Sborman # endif /* NEWINT */ 115138905Sborman #endif /* CRAY */ 115238905Sborman exit(1); 115338905Sborman } 115438905Sborman 115538905Sborman #if defined(CRAY) && !defined(NEWINIT) 115638905Sborman /* 115738905Sborman * _utmp_sig_rcv 115838905Sborman * utmp_sig_init 115938905Sborman * utmp_sig_wait 116038905Sborman * These three functions are used to coordinate the handling of 116138905Sborman * the utmp file between the server and the soon-to-be-login shell. 116238905Sborman * The server actually creates the utmp structure, the child calls 116338905Sborman * utmp_sig_wait(), until the server calls utmp_sig_notify() and 116438905Sborman * signals the future-login shell to proceed. 116538905Sborman */ 116638905Sborman static int caught=0; /* NZ when signal intercepted */ 116738905Sborman static void (*func)(); /* address of previous handler */ 116838905Sborman 116938905Sborman void 117038905Sborman _utmp_sig_rcv(sig) 117138905Sborman int sig; 117238905Sborman { 117338905Sborman caught = 1; 117438905Sborman (void) signal(SIGUSR1, func); 117538905Sborman } 117638905Sborman 117738905Sborman utmp_sig_init() 117838905Sborman { 117938905Sborman /* 118038905Sborman * register signal handler for UTMP creation 118138905Sborman */ 118238905Sborman if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) 118338905Sborman fatalperror(net, "telnetd/signal"); 118438905Sborman } 118538905Sborman 1186*44364Sborman utmp_sig_reset() 1187*44364Sborman { 1188*44364Sborman (void) signal(SIGUSR1, func); /* reset handler to default */ 1189*44364Sborman } 1190*44364Sborman 119138905Sborman utmp_sig_wait() 119238905Sborman { 119338905Sborman /* 119438905Sborman * Wait for parent to write our utmp entry. 119538905Sborman */ 119638905Sborman sigoff(); 119738905Sborman while (caught == 0) { 119838905Sborman pause(); /* wait until we get a signal (sigon) */ 119938905Sborman sigoff(); /* turn off signals while we check caught */ 120038905Sborman } 120138905Sborman sigon(); /* turn on signals again */ 120238905Sborman } 120338905Sborman 120438905Sborman utmp_sig_notify(pid) 120538905Sborman { 120638905Sborman kill(pid, SIGUSR1); 120738905Sborman } 120838905Sborman #endif /* defined(CRAY) && !defined(NEWINIT) */ 120938905Sborman 121038905Sborman /* 121138905Sborman * rmut() 121238905Sborman * 121338905Sborman * This is the function called by cleanup() to 121438905Sborman * remove the utmp entry for this person. 121538905Sborman */ 121638905Sborman 121738905Sborman #if !defined(CRAY) && BSD <= 43 121838905Sborman rmut() 121938905Sborman { 122038905Sborman register f; 122138905Sborman int found = 0; 122238905Sborman struct utmp *u, *utmp; 122338905Sborman int nutmp; 122438905Sborman struct stat statbf; 122538905Sborman char *malloc(); 122638905Sborman long time(); 122738905Sborman off_t lseek(); 122838905Sborman 122938905Sborman f = open(utmpf, O_RDWR); 123038905Sborman if (f >= 0) { 123138905Sborman (void) fstat(f, &statbf); 123238905Sborman utmp = (struct utmp *)malloc((unsigned)statbf.st_size); 123338905Sborman if (!utmp) 123438905Sborman syslog(LOG_ERR, "utmp malloc failed"); 123538905Sborman if (statbf.st_size && utmp) { 123638905Sborman nutmp = read(f, (char *)utmp, (int)statbf.st_size); 123738905Sborman nutmp /= sizeof(struct utmp); 123838905Sborman 123938905Sborman for (u = utmp ; u < &utmp[nutmp] ; u++) { 124038905Sborman if (SCMPN(u->ut_line, line+5) || 124138905Sborman u->ut_name[0]==0) 124238905Sborman continue; 124338905Sborman (void) lseek(f, ((long)u)-((long)utmp), L_SET); 124438905Sborman SCPYN(u->ut_name, ""); 124538905Sborman SCPYN(u->ut_host, ""); 124638905Sborman (void) time(&u->ut_time); 124738905Sborman (void) write(f, (char *)u, sizeof(wtmp)); 124838905Sborman found++; 124938905Sborman } 125038905Sborman } 125138905Sborman (void) close(f); 125238905Sborman } 125338905Sborman if (found) { 125438905Sborman f = open(wtmpf, O_WRONLY|O_APPEND); 125538905Sborman if (f >= 0) { 125638905Sborman SCPYN(wtmp.ut_line, line+5); 125738905Sborman SCPYN(wtmp.ut_name, ""); 125838905Sborman SCPYN(wtmp.ut_host, ""); 125938905Sborman (void) time(&wtmp.ut_time); 126038905Sborman (void) write(f, (char *)&wtmp, sizeof(wtmp)); 126138905Sborman (void) close(f); 126238905Sborman } 126338905Sborman } 126438905Sborman (void) chmod(line, 0666); 126538905Sborman (void) chown(line, 0, 0); 126638905Sborman line[strlen("/dev/")] = 'p'; 126738905Sborman (void) chmod(line, 0666); 126838905Sborman (void) chown(line, 0, 0); 126938905Sborman } /* end of rmut */ 127038905Sborman #endif /* CRAY */ 1271