138905Sborman /* 261451Sbostic * Copyright (c) 1989, 1993 361451Sbostic * The Regents of the University of California. All rights reserved. 438905Sborman * 542673Sbostic * %sccs.include.redist.c% 638905Sborman */ 738905Sborman 838905Sborman #ifndef lint 9*68348Sdab static char sccsid[] = "@(#)sys_term.c 8.3 (Berkeley) 02/16/95"; 1038905Sborman #endif /* not lint */ 1138905Sborman 1238905Sborman #include "telnetd.h" 1338905Sborman #include "pathnames.h" 1438905Sborman 1557212Sdab #if defined(AUTHENTICATION) 1646809Sdab #include <libtelnet/auth.h> 1746809Sdab #endif 1846809Sdab 1960151Sdab #if defined(CRAY) || defined(__hpux) 2060151Sdab # define PARENT_DOES_UTMP 2160151Sdab #endif 2260151Sdab 2338905Sborman #ifdef NEWINIT 2438905Sborman #include <initreq.h> 2560151Sdab int utmp_len = MAXHOSTNAMELEN; /* sizeof(init_request.host) */ 2638905Sborman #else /* NEWINIT*/ 2757212Sdab # ifdef UTMPX 2857212Sdab # include <utmpx.h> 2965158Sdab struct utmpx wtmp; 3057212Sdab # else 3157212Sdab # include <utmp.h> 3265158Sdab struct utmp wtmp; 3357212Sdab # endif /* UTMPX */ 3438905Sborman 3557212Sdab int utmp_len = sizeof(wtmp.ut_host); 3660151Sdab # ifndef PARENT_DOES_UTMP 3738905Sborman char wtmpf[] = "/usr/adm/wtmp"; 3838905Sborman char utmpf[] = "/etc/utmp"; 3960151Sdab # else /* PARENT_DOES_UTMP */ 4038905Sborman char wtmpf[] = "/etc/wtmp"; 4160151Sdab # endif /* PARENT_DOES_UTMP */ 4260151Sdab 4360151Sdab # ifdef CRAY 4446809Sdab #include <tmpdir.h> 4546809Sdab #include <sys/wait.h> 4660151Sdab # if defined(_SC_CRAY_SECURE_SYS) && !defined(SCM_SECURITY) 4760151Sdab /* 4860151Sdab * UNICOS 6.0/6.1 do not have SCM_SECURITY defined, so we can 4960151Sdab * use it to tell us to turn off all the socket security code, 5060151Sdab * since that is only used in UNICOS 7.0 and later. 5160151Sdab */ 5260151Sdab # undef _SC_CRAY_SECURE_SYS 5360151Sdab # endif 5460151Sdab 5557212Sdab # if defined(_SC_CRAY_SECURE_SYS) 5657212Sdab #include <sys/sysv.h> 5757212Sdab #include <sys/secstat.h> 5857212Sdab extern int secflag; 5957212Sdab extern struct sysv sysv; 6057212Sdab # endif /* _SC_CRAY_SECURE_SYS */ 6138905Sborman # endif /* CRAY */ 6238905Sborman #endif /* NEWINIT */ 6338905Sborman 6457212Sdab #ifdef STREAMSPTY 6557212Sdab #include <sac.h> 6657212Sdab #include <sys/stropts.h> 6757212Sdab #endif 6857212Sdab 6938905Sborman #define SCPYN(a, b) (void) strncpy(a, b, sizeof(a)) 7038905Sborman #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 7138905Sborman 7244364Sborman #ifdef STREAMS 7344364Sborman #include <sys/stream.h> 7444364Sborman #endif 7560151Sdab #ifdef __hpux 7660151Sdab #include <sys/resource.h> 7760151Sdab #include <sys/proc.h> 7860151Sdab #endif 7938905Sborman #include <sys/tty.h> 8038905Sborman #ifdef t_erase 8138905Sborman #undef t_erase 8238905Sborman #undef t_kill 8338905Sborman #undef t_intrc 8438905Sborman #undef t_quitc 8538905Sborman #undef t_startc 8638905Sborman #undef t_stopc 8738905Sborman #undef t_eofc 8838905Sborman #undef t_brkc 8938905Sborman #undef t_suspc 9038905Sborman #undef t_dsuspc 9138905Sborman #undef t_rprntc 9238905Sborman #undef t_flushc 9338905Sborman #undef t_werasc 9438905Sborman #undef t_lnextc 9538905Sborman #endif 9638905Sborman 9744364Sborman #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC) 9844364Sborman # define EXTPROC 0400 9944364Sborman #endif 10044364Sborman 10138905Sborman #ifndef USE_TERMIO 10238905Sborman struct termbuf { 10338905Sborman struct sgttyb sg; 10438905Sborman struct tchars tc; 10538905Sborman struct ltchars ltc; 10638905Sborman int state; 10738905Sborman int lflags; 10838905Sborman } termbuf, termbuf2; 10945234Sborman # define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val) 11045234Sborman # define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val) 11146809Sdab # define cfgetospeed(tp) (tp)->sg.sg_ospeed 11246809Sdab # define cfgetispeed(tp) (tp)->sg.sg_ispeed 11338905Sborman #else /* USE_TERMIO */ 11438905Sborman # ifdef SYSV_TERMIO 11538905Sborman # define termios termio 11638905Sborman # endif 11745234Sborman # ifndef TCSANOW 11844364Sborman # ifdef TCSETS 11945234Sborman # define TCSANOW TCSETS 12045234Sborman # define TCSADRAIN TCSETSW 12146809Sdab # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) 12244364Sborman # else 12345234Sborman # ifdef TCSETA 12445234Sborman # define TCSANOW TCSETA 12545234Sborman # define TCSADRAIN TCSETAW 12646809Sdab # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) 12745234Sborman # else 12845234Sborman # define TCSANOW TIOCSETA 12945234Sborman # define TCSADRAIN TIOCSETAW 13046809Sdab # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) 13145234Sborman # endif 13244364Sborman # endif 13345234Sborman # define tcsetattr(f, a, t) ioctl(f, a, t) 13445234Sborman # define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 13545234Sborman (tp)->c_cflag |= (val) 13646809Sdab # define cfgetospeed(tp) ((tp)->c_cflag & CBAUD) 13745234Sborman # ifdef CIBAUD 13845234Sborman # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \ 13945234Sborman (tp)->c_cflag |= ((val)<<IBSHIFT) 14046809Sdab # define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT) 14145234Sborman # else 14245234Sborman # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 14345234Sborman (tp)->c_cflag |= (val) 14446809Sdab # define cfgetispeed(tp) ((tp)->c_cflag & CBAUD) 14545234Sborman # endif 14645234Sborman # endif /* TCSANOW */ 14738905Sborman struct termios termbuf, termbuf2; /* pty control structure */ 14857592Sdab # ifdef STREAMSPTY 14957212Sdab int ttyfd = -1; 15057592Sdab # endif 15138905Sborman #endif /* USE_TERMIO */ 15238905Sborman 15338905Sborman /* 15438905Sborman * init_termbuf() 15538905Sborman * copy_termbuf(cp) 15638905Sborman * set_termbuf() 15738905Sborman * 15838905Sborman * These three routines are used to get and set the "termbuf" structure 15938905Sborman * to and from the kernel. init_termbuf() gets the current settings. 16038905Sborman * copy_termbuf() hands in a new "termbuf" to write to the kernel, and 16138905Sborman * set_termbuf() writes the structure into the kernel. 16238905Sborman */ 16338905Sborman 16446809Sdab void 16538905Sborman init_termbuf() 16638905Sborman { 16738905Sborman #ifndef USE_TERMIO 16838905Sborman (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg); 16938905Sborman (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc); 17038905Sborman (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc); 17138905Sborman # ifdef TIOCGSTATE 17238905Sborman (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state); 17338905Sborman # endif 17438905Sborman #else 17557592Sdab # ifdef STREAMSPTY 17657212Sdab (void) tcgetattr(ttyfd, &termbuf); 17757592Sdab # else 17857592Sdab (void) tcgetattr(pty, &termbuf); 17957592Sdab # endif 18038905Sborman #endif 18138905Sborman termbuf2 = termbuf; 18238905Sborman } 18338905Sborman 18438905Sborman #if defined(LINEMODE) && defined(TIOCPKT_IOCTL) 18546809Sdab void 18638905Sborman copy_termbuf(cp, len) 18746809Sdab char *cp; 18846809Sdab int len; 18938905Sborman { 19038905Sborman if (len > sizeof(termbuf)) 19138905Sborman len = sizeof(termbuf); 19238905Sborman bcopy(cp, (char *)&termbuf, len); 19338905Sborman termbuf2 = termbuf; 19438905Sborman } 19538905Sborman #endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ 19638905Sborman 19746809Sdab void 19838905Sborman set_termbuf() 19938905Sborman { 20038905Sborman /* 20138905Sborman * Only make the necessary changes. 20238905Sborman */ 20338905Sborman #ifndef USE_TERMIO 20438905Sborman if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg))) 20545234Sborman (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg); 20638905Sborman if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc))) 20738905Sborman (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc); 20838905Sborman if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc, 20938905Sborman sizeof(termbuf.ltc))) 21038905Sborman (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc); 21138905Sborman if (termbuf.lflags != termbuf2.lflags) 21238905Sborman (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags); 21338905Sborman #else /* USE_TERMIO */ 21438905Sborman if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) 21557592Sdab # ifdef STREAMSPTY 21657212Sdab (void) tcsetattr(ttyfd, TCSANOW, &termbuf); 21757592Sdab # else 21857592Sdab (void) tcsetattr(pty, TCSANOW, &termbuf); 21957592Sdab # endif 22057212Sdab # if defined(CRAY2) && defined(UNICOS5) 22138905Sborman needtermstat = 1; 22238905Sborman # endif 22338905Sborman #endif /* USE_TERMIO */ 22438905Sborman } 22538905Sborman 22638905Sborman 22738905Sborman /* 22838905Sborman * spcset(func, valp, valpp) 22938905Sborman * 23038905Sborman * This function takes various special characters (func), and 23138905Sborman * sets *valp to the current value of that character, and 23238905Sborman * *valpp to point to where in the "termbuf" structure that 23338905Sborman * value is kept. 23438905Sborman * 23538905Sborman * It returns the SLC_ level of support for this function. 23638905Sborman */ 23738905Sborman 23838905Sborman #ifndef USE_TERMIO 23946809Sdab int 24038905Sborman spcset(func, valp, valpp) 24146809Sdab int func; 24246809Sdab cc_t *valp; 24346809Sdab cc_t **valpp; 24438905Sborman { 24538905Sborman switch(func) { 24638905Sborman case SLC_EOF: 24738905Sborman *valp = termbuf.tc.t_eofc; 24840242Sborman *valpp = (cc_t *)&termbuf.tc.t_eofc; 24938905Sborman return(SLC_VARIABLE); 25038905Sborman case SLC_EC: 25138905Sborman *valp = termbuf.sg.sg_erase; 25240242Sborman *valpp = (cc_t *)&termbuf.sg.sg_erase; 25338905Sborman return(SLC_VARIABLE); 25438905Sborman case SLC_EL: 25538905Sborman *valp = termbuf.sg.sg_kill; 25640242Sborman *valpp = (cc_t *)&termbuf.sg.sg_kill; 25738905Sborman return(SLC_VARIABLE); 25838905Sborman case SLC_IP: 25938905Sborman *valp = termbuf.tc.t_intrc; 26040242Sborman *valpp = (cc_t *)&termbuf.tc.t_intrc; 26138905Sborman return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 26238905Sborman case SLC_ABORT: 26338905Sborman *valp = termbuf.tc.t_quitc; 26440242Sborman *valpp = (cc_t *)&termbuf.tc.t_quitc; 26538905Sborman return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 26638905Sborman case SLC_XON: 26738905Sborman *valp = termbuf.tc.t_startc; 26840242Sborman *valpp = (cc_t *)&termbuf.tc.t_startc; 26938905Sborman return(SLC_VARIABLE); 27038905Sborman case SLC_XOFF: 27138905Sborman *valp = termbuf.tc.t_stopc; 27240242Sborman *valpp = (cc_t *)&termbuf.tc.t_stopc; 27338905Sborman return(SLC_VARIABLE); 27438905Sborman case SLC_AO: 27538905Sborman *valp = termbuf.ltc.t_flushc; 27640242Sborman *valpp = (cc_t *)&termbuf.ltc.t_flushc; 27738905Sborman return(SLC_VARIABLE); 27838905Sborman case SLC_SUSP: 27938905Sborman *valp = termbuf.ltc.t_suspc; 28040242Sborman *valpp = (cc_t *)&termbuf.ltc.t_suspc; 28138905Sborman return(SLC_VARIABLE); 28238905Sborman case SLC_EW: 28338905Sborman *valp = termbuf.ltc.t_werasc; 28440242Sborman *valpp = (cc_t *)&termbuf.ltc.t_werasc; 28538905Sborman return(SLC_VARIABLE); 28638905Sborman case SLC_RP: 28738905Sborman *valp = termbuf.ltc.t_rprntc; 28840242Sborman *valpp = (cc_t *)&termbuf.ltc.t_rprntc; 28938905Sborman return(SLC_VARIABLE); 29038905Sborman case SLC_LNEXT: 29138905Sborman *valp = termbuf.ltc.t_lnextc; 29240242Sborman *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 29338905Sborman return(SLC_VARIABLE); 29440242Sborman case SLC_FORW1: 29540242Sborman *valp = termbuf.tc.t_brkc; 29640242Sborman *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 29740242Sborman return(SLC_VARIABLE); 29838905Sborman case SLC_BRK: 29938905Sborman case SLC_SYNCH: 30038905Sborman case SLC_AYT: 30138905Sborman case SLC_EOR: 30240242Sborman *valp = (cc_t)0; 30340242Sborman *valpp = (cc_t *)0; 30438905Sborman return(SLC_DEFAULT); 30538905Sborman default: 30640242Sborman *valp = (cc_t)0; 30740242Sborman *valpp = (cc_t *)0; 30838905Sborman return(SLC_NOSUPPORT); 30938905Sborman } 31038905Sborman } 31138905Sborman 31238905Sborman #else /* USE_TERMIO */ 31338905Sborman 31446809Sdab int 31538905Sborman spcset(func, valp, valpp) 31646809Sdab int func; 31746809Sdab cc_t *valp; 31846809Sdab cc_t **valpp; 31938905Sborman { 32039503Sborman 32139503Sborman #define setval(a, b) *valp = termbuf.c_cc[a]; \ 32239503Sborman *valpp = &termbuf.c_cc[a]; \ 32339503Sborman return(b); 32440242Sborman #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); 32539503Sborman 32638905Sborman switch(func) { 32738905Sborman case SLC_EOF: 32839503Sborman setval(VEOF, SLC_VARIABLE); 32938905Sborman case SLC_EC: 33039503Sborman setval(VERASE, SLC_VARIABLE); 33138905Sborman case SLC_EL: 33239503Sborman setval(VKILL, SLC_VARIABLE); 33338905Sborman case SLC_IP: 33439503Sborman setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 33538905Sborman case SLC_ABORT: 33639503Sborman setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 33738905Sborman case SLC_XON: 33839503Sborman #ifdef VSTART 33939503Sborman setval(VSTART, SLC_VARIABLE); 34039503Sborman #else 34139503Sborman defval(0x13); 34239503Sborman #endif 34338905Sborman case SLC_XOFF: 34439503Sborman #ifdef VSTOP 34539503Sborman setval(VSTOP, SLC_VARIABLE); 34639503Sborman #else 34739503Sborman defval(0x11); 34839503Sborman #endif 34938905Sborman case SLC_EW: 35039503Sborman #ifdef VWERASE 35139503Sborman setval(VWERASE, SLC_VARIABLE); 35239503Sborman #else 35339503Sborman defval(0); 35439503Sborman #endif 35538905Sborman case SLC_RP: 35639503Sborman #ifdef VREPRINT 35739503Sborman setval(VREPRINT, SLC_VARIABLE); 35839503Sborman #else 35939503Sborman defval(0); 36039503Sborman #endif 36138905Sborman case SLC_LNEXT: 36239503Sborman #ifdef VLNEXT 36339503Sborman setval(VLNEXT, SLC_VARIABLE); 36439503Sborman #else 36539503Sborman defval(0); 36639503Sborman #endif 36739503Sborman case SLC_AO: 36845234Sborman #if !defined(VDISCARD) && defined(VFLUSHO) 36945234Sborman # define VDISCARD VFLUSHO 37045234Sborman #endif 37145234Sborman #ifdef VDISCARD 37245234Sborman setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); 37339503Sborman #else 37439503Sborman defval(0); 37539503Sborman #endif 37639503Sborman case SLC_SUSP: 37739503Sborman #ifdef VSUSP 37839503Sborman setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); 37939503Sborman #else 38039503Sborman defval(0); 38139503Sborman #endif 38240242Sborman #ifdef VEOL 38340242Sborman case SLC_FORW1: 38440242Sborman setval(VEOL, SLC_VARIABLE); 38540242Sborman #endif 38640242Sborman #ifdef VEOL2 38740242Sborman case SLC_FORW2: 38840242Sborman setval(VEOL2, SLC_VARIABLE); 38940242Sborman #endif 39045234Sborman case SLC_AYT: 39145234Sborman #ifdef VSTATUS 39245234Sborman setval(VSTATUS, SLC_VARIABLE); 39345234Sborman #else 39445234Sborman defval(0); 39545234Sborman #endif 39639503Sborman 39738905Sborman case SLC_BRK: 39838905Sborman case SLC_SYNCH: 39938905Sborman case SLC_EOR: 40039503Sborman defval(0); 40139503Sborman 40238905Sborman default: 40338905Sborman *valp = 0; 40438905Sborman *valpp = 0; 40538905Sborman return(SLC_NOSUPPORT); 40638905Sborman } 40738905Sborman } 40838905Sborman #endif /* USE_TERMIO */ 40938905Sborman 41040242Sborman #ifdef CRAY 41138905Sborman /* 41240242Sborman * getnpty() 41340242Sborman * 41440242Sborman * Return the number of pty's configured into the system. 41540242Sborman */ 41646809Sdab int 41740242Sborman getnpty() 41840242Sborman { 41940242Sborman #ifdef _SC_CRAY_NPTY 42046809Sdab int numptys; 42146809Sdab 42246809Sdab if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) 42346809Sdab return numptys; 42446809Sdab else 42540242Sborman #endif /* _SC_CRAY_NPTY */ 42646809Sdab return 128; 42740242Sborman } 42840242Sborman #endif /* CRAY */ 42940242Sborman 43045234Sborman #ifndef convex 43140242Sborman /* 43238905Sborman * getpty() 43338905Sborman * 43438905Sborman * Allocate a pty. As a side effect, the external character 43538905Sborman * array "line" contains the name of the slave side. 43638905Sborman * 43738905Sborman * Returns the file descriptor of the opened pty. 43838905Sborman */ 43945234Sborman #ifndef __GNUC__ 44038905Sborman char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 44145234Sborman #else 44245234Sborman static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 44345234Sborman char *line = Xline; 44445234Sborman #endif 44545234Sborman #ifdef CRAY 44645234Sborman char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 44745234Sborman #endif /* CRAY */ 44838905Sborman 44946809Sdab int 45060151Sdab getpty(ptynum) 45160151Sdab int *ptynum; 45238905Sborman { 45338905Sborman register int p; 45457212Sdab #ifdef STREAMSPTY 45557212Sdab int t; 45657212Sdab char *ptsname(); 45757212Sdab 45857212Sdab p = open("/dev/ptmx", 2); 45957212Sdab if (p > 0) { 46057212Sdab grantpt(p); 46157212Sdab unlockpt(p); 46257212Sdab strcpy(line, ptsname(p)); 46357212Sdab return(p); 46457212Sdab } 46557212Sdab 46657212Sdab #else /* ! STREAMSPTY */ 46738905Sborman #ifndef CRAY 46857212Sdab register char *cp, *p1, *p2; 46938905Sborman register int i; 47059050Storek #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207 47157212Sdab int dummy; 47257212Sdab #endif 47338905Sborman 47460151Sdab #ifndef __hpux 47538905Sborman (void) sprintf(line, "/dev/ptyXX"); 47638905Sborman p1 = &line[8]; 47738905Sborman p2 = &line[9]; 47860151Sdab #else 47960151Sdab (void) sprintf(line, "/dev/ptym/ptyXX"); 48060151Sdab p1 = &line[13]; 48160151Sdab p2 = &line[14]; 48260151Sdab #endif 48338905Sborman 48457212Sdab for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) { 48538905Sborman struct stat stb; 48638905Sborman 48757212Sdab *p1 = *cp; 48838905Sborman *p2 = '0'; 48957212Sdab /* 49057212Sdab * This stat() check is just to keep us from 49157212Sdab * looping through all 256 combinations if there 49257212Sdab * aren't that many ptys available. 49357212Sdab */ 49438905Sborman if (stat(line, &stb) < 0) 49538905Sborman break; 49638905Sborman for (i = 0; i < 16; i++) { 49738905Sborman *p2 = "0123456789abcdef"[i]; 49838905Sborman p = open(line, 2); 49938905Sborman if (p > 0) { 50060151Sdab #ifndef __hpux 50138905Sborman line[5] = 't'; 50260151Sdab #else 50360151Sdab for (p1 = &line[8]; *p1; p1++) 50460151Sdab *p1 = *(p1+1); 50560151Sdab line[9] = 't'; 50660151Sdab #endif 50757212Sdab chown(line, 0, 0); 50857212Sdab chmod(line, 0600); 50959050Storek #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207 51057212Sdab if (ioctl(p, TIOCGPGRP, &dummy) == 0 51157212Sdab || errno != EIO) { 51257212Sdab chmod(line, 0666); 51357212Sdab close(p); 51457212Sdab line[5] = 'p'; 51557212Sdab } else 51659050Storek #endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */ 51757212Sdab return(p); 51838905Sborman } 51938905Sborman } 52038905Sborman } 52138905Sborman #else /* CRAY */ 52238905Sborman extern lowpty, highpty; 52345234Sborman struct stat sb; 52438905Sborman 52560151Sdab for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) { 52660151Sdab (void) sprintf(myline, "/dev/pty/%03d", *ptynum); 52745234Sborman p = open(myline, 2); 52838905Sborman if (p < 0) 52938905Sborman continue; 53060151Sdab (void) sprintf(line, "/dev/ttyp%03d", *ptynum); 53145234Sborman /* 53245234Sborman * Here are some shenanigans to make sure that there 53345234Sborman * are no listeners lurking on the line. 53445234Sborman */ 53545234Sborman if(stat(line, &sb) < 0) { 53645234Sborman (void) close(p); 53745234Sborman continue; 53845234Sborman } 53945234Sborman if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { 54045234Sborman chown(line, 0, 0); 54145234Sborman chmod(line, 0600); 54245234Sborman (void)close(p); 54345234Sborman p = open(myline, 2); 54445234Sborman if (p < 0) 54545234Sborman continue; 54645234Sborman } 54745234Sborman /* 54845234Sborman * Now it should be safe...check for accessability. 54945234Sborman */ 55038905Sborman if (access(line, 6) == 0) 55138905Sborman return(p); 55238905Sborman else { 55338905Sborman /* no tty side to pty so skip it */ 55438905Sborman (void) close(p); 55538905Sborman } 55638905Sborman } 55738905Sborman #endif /* CRAY */ 55857212Sdab #endif /* STREAMSPTY */ 55938905Sborman return(-1); 56038905Sborman } 56145234Sborman #endif /* convex */ 56238905Sborman 56338905Sborman #ifdef LINEMODE 56438905Sborman /* 56538905Sborman * tty_flowmode() Find out if flow control is enabled or disabled. 56638905Sborman * tty_linemode() Find out if linemode (external processing) is enabled. 56738905Sborman * tty_setlinemod(on) Turn on/off linemode. 56838905Sborman * tty_isecho() Find out if echoing is turned on. 56938905Sborman * tty_setecho(on) Enable/disable character echoing. 57038905Sborman * tty_israw() Find out if terminal is in RAW mode. 57138905Sborman * tty_binaryin(on) Turn on/off BINARY on input. 57238905Sborman * tty_binaryout(on) Turn on/off BINARY on output. 57338905Sborman * tty_isediting() Find out if line editing is enabled. 57438905Sborman * tty_istrapsig() Find out if signal trapping is enabled. 57538905Sborman * tty_setedit(on) Turn on/off line editing. 57638905Sborman * tty_setsig(on) Turn on/off signal trapping. 57744364Sborman * tty_issofttab() Find out if tab expansion is enabled. 57844364Sborman * tty_setsofttab(on) Turn on/off soft tab expansion. 57944364Sborman * tty_islitecho() Find out if typed control chars are echoed literally 58044364Sborman * tty_setlitecho() Turn on/off literal echo of control chars 58138905Sborman * tty_tspeed(val) Set transmit speed to val. 58238905Sborman * tty_rspeed(val) Set receive speed to val. 58338905Sborman */ 58438905Sborman 58545234Sborman #ifdef convex 58645234Sborman static int linestate; 58745234Sborman #endif 58845234Sborman 58946809Sdab int 59038905Sborman tty_linemode() 59138905Sborman { 59245234Sborman #ifndef convex 59338905Sborman #ifndef USE_TERMIO 59438905Sborman return(termbuf.state & TS_EXTPROC); 59538905Sborman #else 59638905Sborman return(termbuf.c_lflag & EXTPROC); 59738905Sborman #endif 59845234Sborman #else 59945234Sborman return(linestate); 60045234Sborman #endif 60138905Sborman } 60238905Sborman 60346809Sdab void 60438905Sborman tty_setlinemode(on) 60546809Sdab int on; 60638905Sborman { 60738905Sborman #ifdef TIOCEXT 60845234Sborman # ifndef convex 60945234Sborman set_termbuf(); 61045234Sborman # else 61145234Sborman linestate = on; 61245234Sborman # endif 61338905Sborman (void) ioctl(pty, TIOCEXT, (char *)&on); 61445234Sborman # ifndef convex 61545234Sborman init_termbuf(); 61645234Sborman # endif 61738905Sborman #else /* !TIOCEXT */ 61845234Sborman # ifdef EXTPROC 61938905Sborman if (on) 62038905Sborman termbuf.c_lflag |= EXTPROC; 62138905Sborman else 62238905Sborman termbuf.c_lflag &= ~EXTPROC; 62345234Sborman # endif 62438905Sborman #endif /* TIOCEXT */ 62538905Sborman } 62665158Sdab #endif /* LINEMODE */ 62738905Sborman 62846809Sdab int 62938905Sborman tty_isecho() 63038905Sborman { 63138905Sborman #ifndef USE_TERMIO 63238905Sborman return (termbuf.sg.sg_flags & ECHO); 63338905Sborman #else 63438905Sborman return (termbuf.c_lflag & ECHO); 63538905Sborman #endif 63638905Sborman } 63738905Sborman 63858971Sdab int 63958971Sdab tty_flowmode() 64058971Sdab { 64158971Sdab #ifndef USE_TERMIO 64258971Sdab return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0); 64358971Sdab #else 64458971Sdab return((termbuf.c_iflag & IXON) ? 1 : 0); 64558971Sdab #endif 64658971Sdab } 64758971Sdab 64858971Sdab int 64958971Sdab tty_restartany() 65058971Sdab { 65158971Sdab #ifndef USE_TERMIO 65258971Sdab # ifdef DECCTQ 65358971Sdab return((termbuf.lflags & DECCTQ) ? 0 : 1); 65458971Sdab # else 65558971Sdab return(-1); 65658971Sdab # endif 65758971Sdab #else 65858971Sdab return((termbuf.c_iflag & IXANY) ? 1 : 0); 65958971Sdab #endif 66058971Sdab } 66158971Sdab 66246809Sdab void 66338905Sborman tty_setecho(on) 66446809Sdab int on; 66538905Sborman { 66638905Sborman #ifndef USE_TERMIO 66738905Sborman if (on) 66838905Sborman termbuf.sg.sg_flags |= ECHO|CRMOD; 66938905Sborman else 67038905Sborman termbuf.sg.sg_flags &= ~(ECHO|CRMOD); 67138905Sborman #else 67238905Sborman if (on) 67338905Sborman termbuf.c_lflag |= ECHO; 67438905Sborman else 67538905Sborman termbuf.c_lflag &= ~ECHO; 67638905Sborman #endif 67738905Sborman } 67838905Sborman 67946809Sdab int 68038905Sborman tty_israw() 68138905Sborman { 68238905Sborman #ifndef USE_TERMIO 68338905Sborman return(termbuf.sg.sg_flags & RAW); 68438905Sborman #else 68538905Sborman return(!(termbuf.c_lflag & ICANON)); 68638905Sborman #endif 68738905Sborman } 68838905Sborman 68965158Sdab #if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 69065158Sdab int 69165158Sdab tty_setraw(on) 69265158Sdab { 69365158Sdab # ifndef USE_TERMIO 69465158Sdab if (on) 69565158Sdab termbuf.sg.sg_flags |= RAW; 69665158Sdab else 69765158Sdab termbuf.sg.sg_flags &= ~RAW; 69865158Sdab # else 69965158Sdab if (on) 70065158Sdab termbuf.c_lflag &= ~ICANON; 70165158Sdab else 70265158Sdab termbuf.c_lflag |= ICANON; 70365158Sdab # endif 70465158Sdab } 70565158Sdab #endif 70665158Sdab 70746809Sdab void 70838905Sborman tty_binaryin(on) 70946809Sdab int on; 71038905Sborman { 71138905Sborman #ifndef USE_TERMIO 71238905Sborman if (on) 71338905Sborman termbuf.lflags |= LPASS8; 71438905Sborman else 71538905Sborman termbuf.lflags &= ~LPASS8; 71638905Sborman #else 71738905Sborman if (on) { 71846809Sdab termbuf.c_iflag &= ~ISTRIP; 71938905Sborman } else { 72046809Sdab termbuf.c_iflag |= ISTRIP; 72138905Sborman } 72238905Sborman #endif 72338905Sborman } 72438905Sborman 72546809Sdab void 72638905Sborman tty_binaryout(on) 72746809Sdab int on; 72838905Sborman { 72938905Sborman #ifndef USE_TERMIO 73038905Sborman if (on) 73138905Sborman termbuf.lflags |= LLITOUT; 73238905Sborman else 73338905Sborman termbuf.lflags &= ~LLITOUT; 73438905Sborman #else 73538905Sborman if (on) { 73638905Sborman termbuf.c_cflag &= ~(CSIZE|PARENB); 73738905Sborman termbuf.c_cflag |= CS8; 73838905Sborman termbuf.c_oflag &= ~OPOST; 73938905Sborman } else { 74038905Sborman termbuf.c_cflag &= ~CSIZE; 74138905Sborman termbuf.c_cflag |= CS7|PARENB; 74238905Sborman termbuf.c_oflag |= OPOST; 74338905Sborman } 74438905Sborman #endif 74538905Sborman } 74638905Sborman 74746809Sdab int 74838905Sborman tty_isbinaryin() 74938905Sborman { 75038905Sborman #ifndef USE_TERMIO 75138905Sborman return(termbuf.lflags & LPASS8); 75238905Sborman #else 75339503Sborman return(!(termbuf.c_iflag & ISTRIP)); 75438905Sborman #endif 75538905Sborman } 75638905Sborman 75746809Sdab int 75838905Sborman tty_isbinaryout() 75938905Sborman { 76038905Sborman #ifndef USE_TERMIO 76138905Sborman return(termbuf.lflags & LLITOUT); 76238905Sborman #else 76339503Sborman return(!(termbuf.c_oflag&OPOST)); 76438905Sborman #endif 76538905Sborman } 76638905Sborman 76738905Sborman #ifdef LINEMODE 76846809Sdab int 76938905Sborman tty_isediting() 77038905Sborman { 77138905Sborman #ifndef USE_TERMIO 77238905Sborman return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); 77338905Sborman #else 77438905Sborman return(termbuf.c_lflag & ICANON); 77538905Sborman #endif 77638905Sborman } 77738905Sborman 77846809Sdab int 77938905Sborman tty_istrapsig() 78038905Sborman { 78138905Sborman #ifndef USE_TERMIO 78238905Sborman return(!(termbuf.sg.sg_flags&RAW)); 78338905Sborman #else 78438905Sborman return(termbuf.c_lflag & ISIG); 78538905Sborman #endif 78638905Sborman } 78738905Sborman 78846809Sdab void 78938905Sborman tty_setedit(on) 79046809Sdab int on; 79138905Sborman { 79238905Sborman #ifndef USE_TERMIO 79338905Sborman if (on) 79438905Sborman termbuf.sg.sg_flags &= ~CBREAK; 79538905Sborman else 79638905Sborman termbuf.sg.sg_flags |= CBREAK; 79738905Sborman #else 79838905Sborman if (on) 79938905Sborman termbuf.c_lflag |= ICANON; 80038905Sborman else 80138905Sborman termbuf.c_lflag &= ~ICANON; 80238905Sborman #endif 80338905Sborman } 80438905Sborman 80546809Sdab void 80638905Sborman tty_setsig(on) 80746809Sdab int on; 80838905Sborman { 80938905Sborman #ifndef USE_TERMIO 81038905Sborman if (on) 81138905Sborman ; 81238905Sborman #else 81338905Sborman if (on) 81438905Sborman termbuf.c_lflag |= ISIG; 81538905Sborman else 81638905Sborman termbuf.c_lflag &= ~ISIG; 81738905Sborman #endif 81838905Sborman } 81938905Sborman #endif /* LINEMODE */ 82038905Sborman 82146809Sdab int 82244364Sborman tty_issofttab() 82344364Sborman { 82444364Sborman #ifndef USE_TERMIO 82544364Sborman return (termbuf.sg.sg_flags & XTABS); 82644364Sborman #else 82744364Sborman # ifdef OXTABS 82844364Sborman return (termbuf.c_oflag & OXTABS); 82944364Sborman # endif 83044364Sborman # ifdef TABDLY 83144364Sborman return ((termbuf.c_oflag & TABDLY) == TAB3); 83244364Sborman # endif 83344364Sborman #endif 83444364Sborman } 83544364Sborman 83646809Sdab void 83744364Sborman tty_setsofttab(on) 83846809Sdab int on; 83944364Sborman { 84044364Sborman #ifndef USE_TERMIO 84144364Sborman if (on) 84244364Sborman termbuf.sg.sg_flags |= XTABS; 84344364Sborman else 84444364Sborman termbuf.sg.sg_flags &= ~XTABS; 84544364Sborman #else 84644364Sborman if (on) { 84744364Sborman # ifdef OXTABS 84844364Sborman termbuf.c_oflag |= OXTABS; 84944364Sborman # endif 85044364Sborman # ifdef TABDLY 85144364Sborman termbuf.c_oflag &= ~TABDLY; 85244364Sborman termbuf.c_oflag |= TAB3; 85344364Sborman # endif 85444364Sborman } else { 85544364Sborman # ifdef OXTABS 85644364Sborman termbuf.c_oflag &= ~OXTABS; 85744364Sborman # endif 85844364Sborman # ifdef TABDLY 85944364Sborman termbuf.c_oflag &= ~TABDLY; 86044364Sborman termbuf.c_oflag |= TAB0; 86144364Sborman # endif 86244364Sborman } 86344364Sborman #endif 86444364Sborman } 86544364Sborman 86646809Sdab int 86744364Sborman tty_islitecho() 86844364Sborman { 86944364Sborman #ifndef USE_TERMIO 87046809Sdab return (!(termbuf.lflags & LCTLECH)); 87144364Sborman #else 87244364Sborman # ifdef ECHOCTL 87344364Sborman return (!(termbuf.c_lflag & ECHOCTL)); 87444364Sborman # endif 87544364Sborman # ifdef TCTLECH 87644364Sborman return (!(termbuf.c_lflag & TCTLECH)); 87744364Sborman # endif 87844364Sborman # if !defined(ECHOCTL) && !defined(TCTLECH) 87944364Sborman return (0); /* assumes ctl chars are echoed '^x' */ 88044364Sborman # endif 88144364Sborman #endif 88244364Sborman } 88344364Sborman 88446809Sdab void 88544364Sborman tty_setlitecho(on) 88646809Sdab int on; 88744364Sborman { 88844364Sborman #ifndef USE_TERMIO 88944364Sborman if (on) 89046809Sdab termbuf.lflags &= ~LCTLECH; 89144364Sborman else 89246809Sdab termbuf.lflags |= LCTLECH; 89344364Sborman #else 89444364Sborman # ifdef ECHOCTL 89544364Sborman if (on) 89644364Sborman termbuf.c_lflag &= ~ECHOCTL; 89744364Sborman else 89844364Sborman termbuf.c_lflag |= ECHOCTL; 89944364Sborman # endif 90044364Sborman # ifdef TCTLECH 90144364Sborman if (on) 90244364Sborman termbuf.c_lflag &= ~TCTLECH; 90344364Sborman else 90444364Sborman termbuf.c_lflag |= TCTLECH; 90544364Sborman # endif 90644364Sborman #endif 90744364Sborman } 90844364Sborman 90946809Sdab int 91046809Sdab tty_iscrnl() 91146809Sdab { 91246809Sdab #ifndef USE_TERMIO 91346809Sdab return (termbuf.sg.sg_flags & CRMOD); 91446809Sdab #else 91546809Sdab return (termbuf.c_iflag & ICRNL); 91646809Sdab #endif 91746809Sdab } 91846809Sdab 91938905Sborman /* 920*68348Sdab * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). 921*68348Sdab */ 922*68348Sdab #if B4800 != 4800 923*68348Sdab #define DECODE_BAUD 924*68348Sdab #endif 925*68348Sdab 926*68348Sdab #ifdef DECODE_BAUD 927*68348Sdab 928*68348Sdab /* 92938905Sborman * A table of available terminal speeds 93038905Sborman */ 93138905Sborman struct termspeeds { 93238905Sborman int speed; 93338905Sborman int value; 93438905Sborman } termspeeds[] = { 935*68348Sdab { 0, B0 }, { 50, B50 }, { 75, B75 }, 936*68348Sdab { 110, B110 }, { 134, B134 }, { 150, B150 }, 937*68348Sdab { 200, B200 }, { 300, B300 }, { 600, B600 }, 938*68348Sdab { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 939*68348Sdab { 4800, B4800 }, 940*68348Sdab #ifdef B7200 941*68348Sdab { 7200, B7200 }, 942*68348Sdab #endif 943*68348Sdab { 9600, B9600 }, 944*68348Sdab #ifdef B14400 945*68348Sdab { 14400, B14400 }, 946*68348Sdab #endif 947*68348Sdab #ifdef B19200 948*68348Sdab { 19200, B19200 }, 949*68348Sdab #endif 950*68348Sdab #ifdef B28800 951*68348Sdab { 28800, B28800 }, 952*68348Sdab #endif 953*68348Sdab #ifdef B38400 954*68348Sdab { 38400, B38400 }, 955*68348Sdab #endif 956*68348Sdab #ifdef B57600 957*68348Sdab { 57600, B57600 }, 958*68348Sdab #endif 959*68348Sdab #ifdef B115200 960*68348Sdab { 115200, B115200 }, 961*68348Sdab #endif 962*68348Sdab #ifdef B230400 963*68348Sdab { 230400, B230400 }, 964*68348Sdab #endif 965*68348Sdab { -1, 0 } 96638905Sborman }; 967*68348Sdab #endif /* DECODE_BUAD */ 96838905Sborman 96946809Sdab void 97038905Sborman tty_tspeed(val) 97146809Sdab int val; 97238905Sborman { 973*68348Sdab #ifdef DECODE_BAUD 97438905Sborman register struct termspeeds *tp; 97538905Sborman 97638905Sborman for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 97738905Sborman ; 978*68348Sdab if (tp->speed == -1) /* back up to last valid value */ 979*68348Sdab --tp; 98045234Sborman cfsetospeed(&termbuf, tp->value); 981*68348Sdab #else /* DECODE_BUAD */ 982*68348Sdab cfsetospeed(&termbuf, val); 983*68348Sdab #endif /* DECODE_BUAD */ 98438905Sborman } 98538905Sborman 98646809Sdab void 98738905Sborman tty_rspeed(val) 98846809Sdab int val; 98938905Sborman { 990*68348Sdab #ifdef DECODE_BAUD 99138905Sborman register struct termspeeds *tp; 99238905Sborman 99338905Sborman for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 99438905Sborman ; 995*68348Sdab if (tp->speed == -1) /* back up to last valid value */ 996*68348Sdab --tp; 99745234Sborman cfsetispeed(&termbuf, tp->value); 998*68348Sdab #else /* DECODE_BAUD */ 999*68348Sdab cfsetispeed(&termbuf, val); 1000*68348Sdab #endif /* DECODE_BAUD */ 100138905Sborman } 100238905Sborman 100340242Sborman #if defined(CRAY2) && defined(UNICOS5) 100446809Sdab int 100538905Sborman tty_isnewmap() 100638905Sborman { 100738905Sborman return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) && 100838905Sborman !(termbuf.c_oflag & ONLRET)); 100938905Sborman } 101038905Sborman #endif 101138905Sborman 101260151Sdab #ifdef PARENT_DOES_UTMP 101338905Sborman # ifndef NEWINIT 101438905Sborman extern struct utmp wtmp; 101538905Sborman extern char wtmpf[]; 101638905Sborman # else /* NEWINIT */ 101738905Sborman int gotalarm; 101846809Sdab 101946809Sdab /* ARGSUSED */ 102046809Sdab void 102140242Sborman nologinproc(sig) 102246809Sdab int sig; 102338905Sborman { 102438905Sborman gotalarm++; 102538905Sborman } 102638905Sborman # endif /* NEWINIT */ 102760151Sdab #endif /* PARENT_DOES_UTMP */ 102838905Sborman 102946809Sdab #ifndef NEWINIT 103060151Sdab # ifdef PARENT_DOES_UTMP 103146809Sdab extern void utmp_sig_init P((void)); 103246809Sdab extern void utmp_sig_reset P((void)); 103346809Sdab extern void utmp_sig_wait P((void)); 103446809Sdab extern void utmp_sig_notify P((int)); 103560151Sdab # endif /* PARENT_DOES_UTMP */ 103646809Sdab #endif 103746809Sdab 103838905Sborman /* 103938905Sborman * getptyslave() 104038905Sborman * 104138905Sborman * Open the slave side of the pty, and do any initialization 104238905Sborman * that is necessary. The return value is a file descriptor 104338905Sborman * for the slave side. 104438905Sborman */ 104546809Sdab int 104638905Sborman getptyslave() 104738905Sborman { 104838905Sborman register int t = -1; 104938905Sborman 105045234Sborman #if !defined(CRAY) || !defined(NEWINIT) 105145234Sborman # ifdef LINEMODE 105246809Sdab int waslm; 105346809Sdab # endif 105446809Sdab # ifdef TIOCGWINSZ 105546809Sdab struct winsize ws; 105646809Sdab extern int def_row, def_col; 105746809Sdab # endif 105846809Sdab extern int def_tspeed, def_rspeed; 105938905Sborman /* 106045234Sborman * Opening the slave side may cause initilization of the 106146809Sdab * kernel tty structure. We need remember the state of 106246809Sdab * if linemode was turned on 106346809Sdab * terminal window size 106446809Sdab * terminal speed 106546809Sdab * so that we can re-set them if we need to. 106638905Sborman */ 106746809Sdab # ifdef LINEMODE 106846809Sdab waslm = tty_linemode(); 106945234Sborman # endif 107045234Sborman 107145234Sborman 107245234Sborman /* 107345234Sborman * Make sure that we don't have a controlling tty, and 107445234Sborman * that we are the session (process group) leader. 107545234Sborman */ 107645234Sborman # ifdef TIOCNOTTY 107738905Sborman t = open(_PATH_TTY, O_RDWR); 107838905Sborman if (t >= 0) { 107938905Sborman (void) ioctl(t, TIOCNOTTY, (char *)0); 108038905Sborman (void) close(t); 108138905Sborman } 108245234Sborman # endif 108338905Sborman 108445234Sborman 108560151Sdab # ifdef PARENT_DOES_UTMP 108645234Sborman /* 108745234Sborman * Wait for our parent to get the utmp stuff to get done. 108845234Sborman */ 108945234Sborman utmp_sig_wait(); 109045234Sborman # endif 109145234Sborman 109245234Sborman t = cleanopen(line); 109338905Sborman if (t < 0) 109438905Sborman fatalperror(net, line); 109538905Sborman 109657592Sdab #ifdef STREAMSPTY 109757212Sdab #ifdef USE_TERMIO 109857212Sdab ttyfd = t; 109957212Sdab #endif 110057212Sdab if (ioctl(t, I_PUSH, "ptem") < 0) 110157212Sdab fatal(net, "I_PUSH ptem"); 110257212Sdab if (ioctl(t, I_PUSH, "ldterm") < 0) 110357212Sdab fatal(net, "I_PUSH ldterm"); 110457212Sdab if (ioctl(t, I_PUSH, "ttcompat") < 0) 110557212Sdab fatal(net, "I_PUSH ttcompat"); 110657212Sdab if (ioctl(pty, I_PUSH, "pckt") < 0) 110757212Sdab fatal(net, "I_PUSH pckt"); 110857212Sdab #endif 110957212Sdab 111045234Sborman /* 111145234Sborman * set up the tty modes as we like them to be. 111245234Sborman */ 111338905Sborman init_termbuf(); 111446809Sdab # ifdef TIOCGWINSZ 111546809Sdab if (def_row || def_col) { 111646809Sdab bzero((char *)&ws, sizeof(ws)); 111746809Sdab ws.ws_col = def_col; 111846809Sdab ws.ws_row = def_row; 111946809Sdab (void)ioctl(t, TIOCSWINSZ, (char *)&ws); 112046809Sdab } 112146809Sdab # endif 112245234Sborman 112345234Sborman /* 112445234Sborman * Settings for sgtty based systems 112545234Sborman */ 112645234Sborman # ifndef USE_TERMIO 112740242Sborman termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; 112845234Sborman # endif /* USE_TERMIO */ 112945234Sborman 113045234Sborman /* 113160151Sdab * Settings for UNICOS (and HPUX) 113245234Sborman */ 113360151Sdab # if defined(CRAY) || defined(__hpux) 113445234Sborman termbuf.c_oflag = OPOST|ONLCR|TAB3; 113545234Sborman termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; 113645234Sborman termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; 113745234Sborman termbuf.c_cflag = EXTB|HUPCL|CS8; 113845234Sborman # endif 113945234Sborman 114045234Sborman /* 114145234Sborman * Settings for all other termios/termio based 114245234Sborman * systems, other than 4.4BSD. In 4.4BSD the 114345234Sborman * kernel does the initial terminal setup. 114445234Sborman */ 114560151Sdab # if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) 114645234Sborman # ifndef OXTABS 114745234Sborman # define OXTABS 0 114845234Sborman # endif 114938905Sborman termbuf.c_lflag |= ECHO; 115038905Sborman termbuf.c_oflag |= ONLCR|OXTABS; 115138905Sborman termbuf.c_iflag |= ICRNL; 115238905Sborman termbuf.c_iflag &= ~IXOFF; 115345234Sborman # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */ 115446996Sdab tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); 115546996Sdab tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); 115646809Sdab # ifdef LINEMODE 115746809Sdab if (waslm) 115846809Sdab tty_setlinemode(1); 115946809Sdab # endif /* LINEMODE */ 116045234Sborman 116145234Sborman /* 116245234Sborman * Set the tty modes, and make this our controlling tty. 116345234Sborman */ 116445234Sborman set_termbuf(); 116545234Sborman if (login_tty(t) == -1) 116645234Sborman fatalperror(net, "login_tty"); 116745234Sborman #endif /* !defined(CRAY) || !defined(NEWINIT) */ 116845234Sborman if (net > 2) 116945234Sborman (void) close(net); 117065158Sdab #if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 117165158Sdab /* 117265158Sdab * Leave the pty open so that we can write out the rlogin 117365158Sdab * protocol for /bin/login, if the authentication works. 117465158Sdab */ 117565158Sdab #else 117665158Sdab if (pty > 2) { 117745234Sborman (void) close(pty); 117865158Sdab pty = -1; 117965158Sdab } 118065158Sdab #endif 118145234Sborman } 118245234Sborman 118345234Sborman #if !defined(CRAY) || !defined(NEWINIT) 118445234Sborman #ifndef O_NOCTTY 118545234Sborman #define O_NOCTTY 0 118638905Sborman #endif 118745234Sborman /* 118845234Sborman * Open the specified slave side of the pty, 118945234Sborman * making sure that we have a clean tty. 119045234Sborman */ 119146809Sdab int 119245234Sborman cleanopen(line) 119346809Sdab char *line; 119445234Sborman { 119545234Sborman register int t; 119657212Sdab #if defined(_SC_CRAY_SECURE_SYS) 119757212Sdab struct secstat secbuf; 119857212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 119945234Sborman 120057212Sdab #ifndef STREAMSPTY 120145234Sborman /* 120245234Sborman * Make sure that other people can't open the 120345234Sborman * slave side of the connection. 120445234Sborman */ 120538905Sborman (void) chown(line, 0, 0); 120638905Sborman (void) chmod(line, 0600); 120757212Sdab #endif 120845234Sborman 120945234Sborman # if !defined(CRAY) && (BSD > 43) 121045234Sborman (void) revoke(line); 121145234Sborman # endif 121257212Sdab #if defined(_SC_CRAY_SECURE_SYS) 121357212Sdab if (secflag) { 121457212Sdab if (secstat(line, &secbuf) < 0) 121557212Sdab return(-1); 121657212Sdab if (setulvl(secbuf.st_slevel) < 0) 121757212Sdab return(-1); 121857212Sdab if (setucmp(secbuf.st_compart) < 0) 121957212Sdab return(-1); 122057212Sdab } 122157212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 122257212Sdab 122345234Sborman t = open(line, O_RDWR|O_NOCTTY); 122457212Sdab 122557212Sdab #if defined(_SC_CRAY_SECURE_SYS) 122657212Sdab if (secflag) { 122757212Sdab if (setulvl(sysv.sy_minlvl) < 0) 122857212Sdab return(-1); 122957212Sdab if (setucmp(0) < 0) 123057212Sdab return(-1); 123157212Sdab } 123257212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 123357212Sdab 123445234Sborman if (t < 0) 123545234Sborman return(-1); 123645234Sborman 123745234Sborman /* 123845234Sborman * Hangup anybody else using this ttyp, then reopen it for 123945234Sborman * ourselves. 124045234Sborman */ 124160151Sdab # if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY) 124245234Sborman (void) signal(SIGHUP, SIG_IGN); 124345234Sborman vhangup(); 124445234Sborman (void) signal(SIGHUP, SIG_DFL); 124545234Sborman t = open(line, O_RDWR|O_NOCTTY); 124645234Sborman if (t < 0) 124745234Sborman return(-1); 124845234Sborman # endif 124945234Sborman # if defined(CRAY) && defined(TCVHUP) 125045234Sborman { 125145234Sborman register int i; 125245234Sborman (void) signal(SIGHUP, SIG_IGN); 125345234Sborman (void) ioctl(t, TCVHUP, (char *)0); 125445234Sborman (void) signal(SIGHUP, SIG_DFL); 125545234Sborman setpgrp(); 125657212Sdab 125757212Sdab #if defined(_SC_CRAY_SECURE_SYS) 125857212Sdab if (secflag) { 125957212Sdab if (secstat(line, &secbuf) < 0) 126057212Sdab return(-1); 126157212Sdab if (setulvl(secbuf.st_slevel) < 0) 126257212Sdab return(-1); 126357212Sdab if (setucmp(secbuf.st_compart) < 0) 126457212Sdab return(-1); 126557212Sdab } 126657212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 126757212Sdab 126845234Sborman i = open(line, O_RDWR); 126957212Sdab 127057212Sdab #if defined(_SC_CRAY_SECURE_SYS) 127157212Sdab if (secflag) { 127257212Sdab if (setulvl(sysv.sy_minlvl) < 0) 127357212Sdab return(-1); 127457212Sdab if (setucmp(0) < 0) 127557212Sdab return(-1); 127657212Sdab } 127757212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 127857212Sdab 127945234Sborman if (i < 0) 128046809Sdab return(-1); 128145234Sborman (void) close(t); 128245234Sborman t = i; 128345234Sborman } 128445234Sborman # endif /* defined(CRAY) && defined(TCVHUP) */ 128538905Sborman return(t); 128638905Sborman } 128745234Sborman #endif /* !defined(CRAY) || !defined(NEWINIT) */ 128838905Sborman 128945234Sborman #if BSD <= 43 129065158Sdab 129146809Sdab int 129245234Sborman login_tty(t) 129346809Sdab int t; 129445234Sborman { 129565158Sdab if (setsid() < 0) { 129665158Sdab #ifdef ultrix 129765158Sdab /* 129865158Sdab * The setsid() may have failed because we 129965158Sdab * already have a pgrp == pid. Zero out 130065158Sdab * our pgrp and try again... 130165158Sdab */ 130265158Sdab if ((setpgrp(0, 0) < 0) || (setsid() < 0)) 130365158Sdab #endif 130465158Sdab fatalperror(net, "setsid()"); 130565158Sdab } 130645234Sborman # ifdef TIOCSCTTY 130745234Sborman if (ioctl(t, TIOCSCTTY, (char *)0) < 0) 130845234Sborman fatalperror(net, "ioctl(sctty)"); 130957212Sdab # if defined(CRAY) 131047613Sdab /* 131147613Sdab * Close the hard fd to /dev/ttypXXX, and re-open through 131247613Sdab * the indirect /dev/tty interface. 131347613Sdab */ 131447613Sdab close(t); 131547613Sdab if ((t = open("/dev/tty", O_RDWR)) < 0) 131647613Sdab fatalperror(net, "open(/dev/tty)"); 131747613Sdab # endif 131845234Sborman # else 131965158Sdab /* 132065158Sdab * We get our controlling tty assigned as a side-effect 132165158Sdab * of opening up a tty device. But on BSD based systems, 132265158Sdab * this only happens if our process group is zero. The 132365158Sdab * setsid() call above may have set our pgrp, so clear 132465158Sdab * it out before opening the tty... 132565158Sdab */ 132665158Sdab (void) setpgrp(0, 0); 132745234Sborman close(open(line, O_RDWR)); 132845234Sborman # endif 132947613Sdab if (t != 0) 133047613Sdab (void) dup2(t, 0); 133147613Sdab if (t != 1) 133247613Sdab (void) dup2(t, 1); 133347613Sdab if (t != 2) 133447613Sdab (void) dup2(t, 2); 133547613Sdab if (t > 2) 133647613Sdab close(t); 133746809Sdab return(0); 133845234Sborman } 133945234Sborman #endif /* BSD <= 43 */ 134045234Sborman 134138905Sborman #ifdef NEWINIT 134238905Sborman char *gen_id = "fe"; 134338905Sborman #endif 134438905Sborman 134538905Sborman /* 134645234Sborman * startslave(host) 134738905Sborman * 134845234Sborman * Given a hostname, do whatever 134938905Sborman * is necessary to startup the login process on the slave side of the pty. 135038905Sborman */ 135138905Sborman 135238905Sborman /* ARGSUSED */ 135346809Sdab void 135446809Sdab startslave(host, autologin, autoname) 135546809Sdab char *host; 135646809Sdab int autologin; 135746809Sdab char *autoname; 135838905Sborman { 135938905Sborman register int i; 136038905Sborman long time(); 136146809Sdab char name[256]; 136246809Sdab #ifdef NEWINIT 136346809Sdab extern char *ptyip; 136446809Sdab struct init_request request; 136546809Sdab void nologinproc(); 136646809Sdab register int n; 136746809Sdab #endif /* NEWINIT */ 136838905Sborman 136957212Sdab #if defined(AUTHENTICATION) 137046809Sdab if (!autoname || !autoname[0]) 137146809Sdab autologin = 0; 137246809Sdab 137346809Sdab if (autologin < auth_level) { 137446809Sdab fatal(net, "Authorization failed"); 137546809Sdab exit(1); 137646809Sdab } 137746809Sdab #endif 137846809Sdab 137938905Sborman #ifndef NEWINIT 138060151Sdab # ifdef PARENT_DOES_UTMP 138138905Sborman utmp_sig_init(); 138260151Sdab # endif /* PARENT_DOES_UTMP */ 138338905Sborman 138438905Sborman if ((i = fork()) < 0) 138538905Sborman fatalperror(net, "fork"); 138638905Sborman if (i) { 138760151Sdab # ifdef PARENT_DOES_UTMP 138838905Sborman /* 138938905Sborman * Cray parent will create utmp entry for child and send 139038905Sborman * signal to child to tell when done. Child waits for signal 139138905Sborman * before doing anything important. 139238905Sborman */ 139338905Sborman register int pid = i; 139446809Sdab void sigjob P((int)); 139538905Sborman 139638905Sborman setpgrp(); 139744364Sborman utmp_sig_reset(); /* reset handler to default */ 139838905Sborman /* 139938905Sborman * Create utmp entry for child 140038905Sborman */ 140138905Sborman (void) time(&wtmp.ut_time); 140238905Sborman wtmp.ut_type = LOGIN_PROCESS; 140338905Sborman wtmp.ut_pid = pid; 140438905Sborman SCPYN(wtmp.ut_user, "LOGIN"); 140538905Sborman SCPYN(wtmp.ut_host, host); 140638905Sborman SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); 140760151Sdab #ifndef __hpux 140838905Sborman SCPYN(wtmp.ut_id, wtmp.ut_line+3); 140960151Sdab #else 141060151Sdab SCPYN(wtmp.ut_id, wtmp.ut_line+7); 141160151Sdab #endif 141238905Sborman pututline(&wtmp); 141338905Sborman endutent(); 141438905Sborman if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { 141538905Sborman (void) write(i, (char *)&wtmp, sizeof(struct utmp)); 141638905Sborman (void) close(i); 141738905Sborman } 141860151Sdab #ifdef CRAY 141946809Sdab (void) signal(WJSIGNAL, sigjob); 142060151Sdab #endif 142138905Sborman utmp_sig_notify(pid); 142260151Sdab # endif /* PARENT_DOES_UTMP */ 142338905Sborman } else { 142465158Sdab getptyslave(autologin); 142546809Sdab start_login(host, autologin, autoname); 142638905Sborman /*NOTREACHED*/ 142738905Sborman } 142838905Sborman #else /* NEWINIT */ 142938905Sborman 143038905Sborman /* 143138905Sborman * Init will start up login process if we ask nicely. We only wait 143238905Sborman * for it to start up and begin normal telnet operation. 143338905Sborman */ 143438905Sborman if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { 143538905Sborman char tbuf[128]; 143638905Sborman (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO); 143738905Sborman fatalperror(net, tbuf); 143838905Sborman } 143938905Sborman memset((char *)&request, 0, sizeof(request)); 144038905Sborman request.magic = INIT_MAGIC; 144138905Sborman SCPYN(request.gen_id, gen_id); 144238905Sborman SCPYN(request.tty_id, &line[8]); 144338905Sborman SCPYN(request.host, host); 144446809Sdab SCPYN(request.term_type, terminaltype ? terminaltype : "network"); 144544364Sborman #if !defined(UNICOS5) 144640242Sborman request.signal = SIGCLD; 144740242Sborman request.pid = getpid(); 144840242Sborman #endif 144944364Sborman #ifdef BFTPDAEMON 145044364Sborman /* 145144364Sborman * Are we working as the bftp daemon? 145244364Sborman */ 145344364Sborman if (bftpd) { 145444364Sborman SCPYN(request.exec_name, BFTPPATH); 145544364Sborman } 145644364Sborman #endif /* BFTPDAEMON */ 145738905Sborman if (write(i, (char *)&request, sizeof(request)) < 0) { 145838905Sborman char tbuf[128]; 145938905Sborman (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO); 146038905Sborman fatalperror(net, tbuf); 146138905Sborman } 146238905Sborman (void) close(i); 146338905Sborman (void) signal(SIGALRM, nologinproc); 146438905Sborman for (i = 0; ; i++) { 146540242Sborman char tbuf[128]; 146638905Sborman alarm(15); 146738905Sborman n = read(pty, ptyip, BUFSIZ); 146838905Sborman if (i == 3 || n >= 0 || !gotalarm) 146938905Sborman break; 147038905Sborman gotalarm = 0; 147140242Sborman sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line); 147240242Sborman (void) write(net, tbuf, strlen(tbuf)); 147338905Sborman } 147438905Sborman if (n < 0 && gotalarm) 147538905Sborman fatal(net, "/etc/init didn't start login process"); 147638905Sborman pcc += n; 147738905Sborman alarm(0); 147838905Sborman (void) signal(SIGALRM, SIG_DFL); 147938905Sborman 148038905Sborman return; 148138905Sborman #endif /* NEWINIT */ 148238905Sborman } 148338905Sborman 148438905Sborman char *envinit[3]; 148544364Sborman extern char **environ; 148638905Sborman 148746809Sdab void 148844364Sborman init_env() 148944364Sborman { 149044364Sborman extern char *getenv(); 149144364Sborman char **envp; 149244364Sborman 149344364Sborman envp = envinit; 149444364Sborman if (*envp = getenv("TZ")) 149544364Sborman *envp++ -= 3; 149660151Sdab #if defined(CRAY) || defined(__hpux) 149744364Sborman else 149844364Sborman *envp++ = "TZ=GMT0"; 149944364Sborman #endif 150044364Sborman *envp = 0; 150144364Sborman environ = envinit; 150244364Sborman } 150344364Sborman 150444364Sborman #ifndef NEWINIT 150544364Sborman 150644364Sborman /* 150745234Sborman * start_login(host) 150838905Sborman * 150938905Sborman * Assuming that we are now running as a child processes, this 151038905Sborman * function will turn us into the login process. 151138905Sborman */ 151238905Sborman 151346809Sdab void 151446809Sdab start_login(host, autologin, name) 151546809Sdab char *host; 151646809Sdab int autologin; 151746809Sdab char *name; 151838905Sborman { 151944364Sborman register char *cp; 152044364Sborman register char **argv; 152144364Sborman char **addarg(); 152265158Sdab extern char *getenv(); 152357212Sdab #ifdef UTMPX 152457212Sdab register int pid = getpid(); 152557212Sdab struct utmpx utmpx; 152657212Sdab #endif 152765158Sdab #ifdef SOLARIS 152857212Sdab char *term; 152957212Sdab char termbuf[64]; 153057212Sdab #endif 153138905Sborman 153257212Sdab #ifdef UTMPX 153338905Sborman /* 153457212Sdab * Create utmp entry for child 153557212Sdab */ 153657212Sdab 153757212Sdab bzero(&utmpx, sizeof(utmpx)); 153857212Sdab SCPYN(utmpx.ut_user, ".telnet"); 153957212Sdab SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); 154057212Sdab utmpx.ut_pid = pid; 154157212Sdab utmpx.ut_id[0] = 't'; 154257212Sdab utmpx.ut_id[1] = 'n'; 154357212Sdab utmpx.ut_id[2] = SC_WILDC; 154457212Sdab utmpx.ut_id[3] = SC_WILDC; 154557212Sdab utmpx.ut_type = LOGIN_PROCESS; 154657212Sdab (void) time(&utmpx.ut_tv.tv_sec); 1547*68348Sdab if (pututxline(&utmpx) == NULL) 1548*68348Sdab fatal(net, "pututxline failed"); 154957212Sdab #endif 155057212Sdab 155157212Sdab /* 155238905Sborman * -h : pass on name of host. 155338905Sborman * WARNING: -h is accepted by login if and only if 155438905Sborman * getuid() == 0. 155538905Sborman * -p : don't clobber the environment (so terminal type stays set). 155646809Sdab * 155746809Sdab * -f : force this login, he has already been authenticated 155838905Sborman */ 155944364Sborman argv = addarg(0, "login"); 156065158Sdab 156160151Sdab #if !defined(NO_LOGIN_H) 156265158Sdab 156365158Sdab # if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 156457212Sdab /* 156565158Sdab * Don't add the "-h host" option if we are going 156665158Sdab * to be adding the "-r host" option down below... 156757212Sdab */ 156865158Sdab if ((auth_level < 0) || (autologin != AUTH_VALID)) 156965158Sdab # endif 157065158Sdab { 157165158Sdab argv = addarg(argv, "-h"); 157265158Sdab argv = addarg(argv, host); 157365158Sdab #ifdef SOLARIS 157465158Sdab /* 157565158Sdab * SVR4 version of -h takes TERM= as second arg, or - 157665158Sdab */ 157765158Sdab term = getenv("TERM"); 157865158Sdab if (term == NULL || term[0] == 0) { 157965158Sdab term = "-"; 158065158Sdab } else { 158165158Sdab strcpy(termbuf, "TERM="); 158265158Sdab strncat(termbuf, term, sizeof(termbuf) - 6); 158365158Sdab term = termbuf; 158465158Sdab } 158565158Sdab argv = addarg(argv, term); 158665158Sdab #endif 158757212Sdab } 158857212Sdab #endif 158946809Sdab #if !defined(NO_LOGIN_P) 159044364Sborman argv = addarg(argv, "-p"); 159138905Sborman #endif 159244364Sborman #ifdef BFTPDAEMON 159344364Sborman /* 159444364Sborman * Are we working as the bftp daemon? If so, then ask login 159544364Sborman * to start bftp instead of shell. 159644364Sborman */ 159744364Sborman if (bftpd) { 159844364Sborman argv = addarg(argv, "-e"); 159944364Sborman argv = addarg(argv, BFTPPATH); 160044364Sborman } else 160144364Sborman #endif 160246809Sdab #if defined (SecurID) 160346809Sdab /* 160446809Sdab * don't worry about the -f that might get sent. 160546809Sdab * A -s is supposed to override it anyhow. 160646809Sdab */ 160746809Sdab if (require_SecurID) 160846809Sdab argv = addarg(argv, "-s"); 160946809Sdab #endif 161057212Sdab #if defined (AUTHENTICATION) 161146809Sdab if (auth_level >= 0 && autologin == AUTH_VALID) { 161246809Sdab # if !defined(NO_LOGIN_F) 161346809Sdab argv = addarg(argv, "-f"); 161465158Sdab argv = addarg(argv, name); 161565158Sdab # else 161665158Sdab # if defined(LOGIN_R) 161765158Sdab /* 161865158Sdab * We don't have support for "login -f", but we 161965158Sdab * can fool /bin/login into thinking that we are 162065158Sdab * rlogind, and allow us to log in without a 162165158Sdab * password. The rlogin protocol expects 162265158Sdab * local-user\0remote-user\0term/speed\0 162365158Sdab */ 162465158Sdab 162565158Sdab if (pty > 2) { 162665158Sdab register char *cp; 162765158Sdab char speed[128]; 162865158Sdab int isecho, israw, xpty, len; 162965158Sdab extern int def_rspeed; 163065158Sdab # ifndef LOGIN_HOST 163165158Sdab /* 163265158Sdab * Tell login that we are coming from "localhost". 163365158Sdab * If we passed in the real host name, then the 163465158Sdab * user would have to allow .rhost access from 163565158Sdab * every machine that they want authenticated 163665158Sdab * access to work from, which sort of defeats 163765158Sdab * the purpose of an authenticated login... 163865158Sdab * So, we tell login that the session is coming 163965158Sdab * from "localhost", and the user will only have 164065158Sdab * to have "localhost" in their .rhost file. 164165158Sdab */ 164265158Sdab # define LOGIN_HOST "localhost" 164365158Sdab # endif 164465158Sdab argv = addarg(argv, "-r"); 164565158Sdab argv = addarg(argv, LOGIN_HOST); 164665158Sdab 164765158Sdab xpty = pty; 164865158Sdab # ifndef STREAMSPTY 164965158Sdab pty = 0; 165065158Sdab # else 165165158Sdab ttyfd = 0; 165246809Sdab # endif 165365158Sdab init_termbuf(); 165465158Sdab isecho = tty_isecho(); 165565158Sdab israw = tty_israw(); 165665158Sdab if (isecho || !israw) { 165765158Sdab tty_setecho(0); /* Turn off echo */ 165865158Sdab tty_setraw(1); /* Turn on raw */ 165965158Sdab set_termbuf(); 166065158Sdab } 166165158Sdab len = strlen(name)+1; 166265158Sdab write(xpty, name, len); 166365158Sdab write(xpty, name, len); 166465158Sdab sprintf(speed, "%s/%d", (cp = getenv("TERM")) ? cp : "", 166565158Sdab (def_rspeed > 0) ? def_rspeed : 9600); 166665158Sdab len = strlen(speed)+1; 166765158Sdab write(xpty, speed, len); 166865158Sdab 166965158Sdab if (isecho || !israw) { 167065158Sdab init_termbuf(); 167165158Sdab tty_setecho(isecho); 167265158Sdab tty_setraw(israw); 167365158Sdab set_termbuf(); 167465158Sdab if (!israw) { 167565158Sdab /* 167665158Sdab * Write a newline to ensure 167765158Sdab * that login will be able to 167865158Sdab * read the line... 167965158Sdab */ 168065158Sdab write(xpty, "\n", 1); 168165158Sdab } 168265158Sdab } 168365158Sdab pty = xpty; 168465158Sdab } 168565158Sdab # else 168646809Sdab argv = addarg(argv, name); 168765158Sdab # endif 168865158Sdab # endif 168946809Sdab } else 169046809Sdab #endif 169144364Sborman if (getenv("USER")) { 169244364Sborman argv = addarg(argv, getenv("USER")); 169365158Sdab #if defined(LOGIN_ARGS) && defined(NO_LOGIN_P) 169446809Sdab { 169546809Sdab register char **cpp; 169646809Sdab for (cpp = environ; *cpp; cpp++) 169746809Sdab argv = addarg(argv, *cpp); 169846809Sdab } 169946809Sdab #endif 170057212Sdab /* 170157212Sdab * Assume that login will set the USER variable 170257212Sdab * correctly. For SysV systems, this means that 170357212Sdab * USER will no longer be set, just LOGNAME by 170457212Sdab * login. (The problem is that if the auto-login 170557212Sdab * fails, and the user then specifies a different 170657212Sdab * account name, he can get logged in with both 170757212Sdab * LOGNAME and USER in his environment, but the 170857212Sdab * USER value will be wrong. 170957212Sdab */ 171057212Sdab unsetenv("USER"); 171144364Sborman } 1712*68348Sdab #ifdef SOLARIS 1713*68348Sdab else { 1714*68348Sdab char **p; 1715*68348Sdab 1716*68348Sdab argv = addarg(argv, ""); /* no login name */ 1717*68348Sdab for (p = environ; *p; p++) { 1718*68348Sdab argv = addarg(argv, *p); 1719*68348Sdab } 1720*68348Sdab } 1721*68348Sdab #endif /* SOLARIS */ 172265158Sdab #if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 172365158Sdab if (pty > 2) 172465158Sdab close(pty); 172565158Sdab #endif 172646809Sdab closelog(); 1727*68348Sdab /* 1728*68348Sdab * This sleep(1) is in here so that telnetd can 1729*68348Sdab * finish up with the tty. There's a race condition 1730*68348Sdab * the login banner message gets lost... 1731*68348Sdab */ 1732*68348Sdab sleep(1); 173344364Sborman execv(_PATH_LOGIN, argv); 173444364Sborman 173538905Sborman syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN); 173638905Sborman fatalperror(net, _PATH_LOGIN); 173738905Sborman /*NOTREACHED*/ 173838905Sborman } 173944364Sborman 174046809Sdab char ** 174144364Sborman addarg(argv, val) 174246809Sdab register char **argv; 174346809Sdab register char *val; 174444364Sborman { 174544364Sborman register char **cpp; 174644364Sborman 174744364Sborman if (argv == NULL) { 174844364Sborman /* 174944364Sborman * 10 entries, a leading length, and a null 175044364Sborman */ 175144364Sborman argv = (char **)malloc(sizeof(*argv) * 12); 175244364Sborman if (argv == NULL) 175344364Sborman return(NULL); 175444364Sborman *argv++ = (char *)10; 175544364Sborman *argv = (char *)0; 175644364Sborman } 175744364Sborman for (cpp = argv; *cpp; cpp++) 175844364Sborman ; 175944364Sborman if (cpp == &argv[(int)argv[-1]]) { 176044364Sborman --argv; 176144364Sborman *argv = (char *)((int)(*argv) + 10); 1762*68348Sdab argv = (char **)realloc(argv, sizeof(*argv)*((int)(*argv) + 2)); 176344364Sborman if (argv == NULL) 176444364Sborman return(NULL); 176544364Sborman argv++; 176644364Sborman cpp = &argv[(int)argv[-1] - 10]; 176744364Sborman } 176844364Sborman *cpp++ = val; 176944364Sborman *cpp = 0; 177044364Sborman return(argv); 177144364Sborman } 177246809Sdab #endif /* NEWINIT */ 177338905Sborman 177438905Sborman /* 177538905Sborman * cleanup() 177638905Sborman * 177738905Sborman * This is the routine to call when we are all through, to 177838905Sborman * clean up anything that needs to be cleaned up. 177938905Sborman */ 178046809Sdab /* ARGSUSED */ 178146809Sdab void 178246809Sdab cleanup(sig) 178346809Sdab int sig; 178438905Sborman { 178560151Sdab #ifndef PARENT_DOES_UTMP 178645234Sborman # if (BSD > 43) || defined(convex) 178738905Sborman char *p; 178838905Sborman 178938905Sborman p = line + sizeof("/dev/") - 1; 179038905Sborman if (logout(p)) 179138905Sborman logwtmp(p, "", ""); 179238905Sborman (void)chmod(line, 0666); 179338905Sborman (void)chown(line, 0, 0); 179438905Sborman *p = 'p'; 179538905Sborman (void)chmod(line, 0666); 179638905Sborman (void)chown(line, 0, 0); 179746809Sdab (void) shutdown(net, 2); 179846809Sdab exit(1); 179938905Sborman # else 180046809Sdab void rmut(); 180146809Sdab 180238905Sborman rmut(); 180338905Sborman vhangup(); /* XXX */ 180446809Sdab (void) shutdown(net, 2); 180546809Sdab exit(1); 180638905Sborman # endif 180760151Sdab #else /* PARENT_DOES_UTMP */ 180846809Sdab # ifdef NEWINIT 180938905Sborman (void) shutdown(net, 2); 181046809Sdab exit(1); 181138905Sborman # else /* NEWINIT */ 181260151Sdab # ifdef CRAY 181346809Sdab static int incleanup = 0; 181446809Sdab register int t; 181546809Sdab 181646809Sdab /* 181746809Sdab * 1: Pick up the zombie, if we are being called 181846809Sdab * as the signal handler. 181946809Sdab * 2: If we are a nested cleanup(), return. 182046809Sdab * 3: Try to clean up TMPDIR. 182146809Sdab * 4: Fill in utmp with shutdown of process. 182246809Sdab * 5: Close down the network and pty connections. 182346809Sdab * 6: Finish up the TMPDIR cleanup, if needed. 182446809Sdab */ 182546809Sdab if (sig == SIGCHLD) 182646809Sdab while (waitpid(-1, 0, WNOHANG) > 0) 182746809Sdab ; /* VOID */ 182846809Sdab t = sigblock(sigmask(SIGCHLD)); 182946809Sdab if (incleanup) { 183046809Sdab sigsetmask(t); 183146809Sdab return; 183246809Sdab } 183346809Sdab incleanup = 1; 183446809Sdab sigsetmask(t); 183560151Sdab if (secflag) { 183660151Sdab /* 183760151Sdab * We need to set ourselves back to a null 183860151Sdab * label to clean up. 183960151Sdab */ 184046809Sdab 184160151Sdab setulvl(sysv.sy_minlvl); 184260151Sdab setucmp((long)0); 184360151Sdab } 184460151Sdab 184546809Sdab t = cleantmp(&wtmp); 184646809Sdab setutent(); /* just to make sure */ 184760151Sdab # endif /* CRAY */ 184846809Sdab rmut(line); 184946809Sdab close(pty); 185038905Sborman (void) shutdown(net, 2); 185160151Sdab # ifdef CRAY 185246809Sdab if (t == 0) 185346809Sdab cleantmp(&wtmp); 185460151Sdab # endif /* CRAY */ 185546809Sdab exit(1); 185638905Sborman # endif /* NEWINT */ 185760151Sdab #endif /* PARENT_DOES_UTMP */ 185838905Sborman } 185938905Sborman 186060151Sdab #if defined(PARENT_DOES_UTMP) && !defined(NEWINIT) 186138905Sborman /* 186238905Sborman * _utmp_sig_rcv 186338905Sborman * utmp_sig_init 186438905Sborman * utmp_sig_wait 186538905Sborman * These three functions are used to coordinate the handling of 186638905Sborman * the utmp file between the server and the soon-to-be-login shell. 186738905Sborman * The server actually creates the utmp structure, the child calls 186838905Sborman * utmp_sig_wait(), until the server calls utmp_sig_notify() and 186938905Sborman * signals the future-login shell to proceed. 187038905Sborman */ 187138905Sborman static int caught=0; /* NZ when signal intercepted */ 187238905Sborman static void (*func)(); /* address of previous handler */ 187338905Sborman 187446809Sdab void 187538905Sborman _utmp_sig_rcv(sig) 187646809Sdab int sig; 187738905Sborman { 187838905Sborman caught = 1; 187938905Sborman (void) signal(SIGUSR1, func); 188038905Sborman } 188138905Sborman 188246809Sdab void 188338905Sborman utmp_sig_init() 188438905Sborman { 188538905Sborman /* 188638905Sborman * register signal handler for UTMP creation 188738905Sborman */ 188838905Sborman if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) 188938905Sborman fatalperror(net, "telnetd/signal"); 189038905Sborman } 189138905Sborman 189246809Sdab void 189344364Sborman utmp_sig_reset() 189444364Sborman { 189544364Sborman (void) signal(SIGUSR1, func); /* reset handler to default */ 189644364Sborman } 189744364Sborman 189860151Sdab # ifdef __hpux 189960151Sdab # define sigoff() /* do nothing */ 190060151Sdab # define sigon() /* do nothing */ 190160151Sdab # endif 190260151Sdab 190346809Sdab void 190438905Sborman utmp_sig_wait() 190538905Sborman { 190638905Sborman /* 190738905Sborman * Wait for parent to write our utmp entry. 190838905Sborman */ 190938905Sborman sigoff(); 191038905Sborman while (caught == 0) { 191138905Sborman pause(); /* wait until we get a signal (sigon) */ 191238905Sborman sigoff(); /* turn off signals while we check caught */ 191338905Sborman } 191438905Sborman sigon(); /* turn on signals again */ 191538905Sborman } 191638905Sborman 191746809Sdab void 191838905Sborman utmp_sig_notify(pid) 191938905Sborman { 192038905Sborman kill(pid, SIGUSR1); 192138905Sborman } 192246809Sdab 192360151Sdab # ifdef CRAY 192446809Sdab static int gotsigjob = 0; 192546809Sdab 192646809Sdab /*ARGSUSED*/ 192746809Sdab void 192846809Sdab sigjob(sig) 192946809Sdab int sig; 193046809Sdab { 193146809Sdab register int jid; 193246809Sdab register struct jobtemp *jp; 193346809Sdab 193446809Sdab while ((jid = waitjob(NULL)) != -1) { 193546809Sdab if (jid == 0) { 193646809Sdab return; 193746809Sdab } 193846809Sdab gotsigjob++; 193946809Sdab jobend(jid, NULL, NULL); 194046809Sdab } 194146809Sdab } 194246809Sdab 194346809Sdab /* 194446809Sdab * Clean up the TMPDIR that login created. 194546809Sdab * The first time this is called we pick up the info 194646809Sdab * from the utmp. If the job has already gone away, 194746809Sdab * then we'll clean up and be done. If not, then 194846809Sdab * when this is called the second time it will wait 194946809Sdab * for the signal that the job is done. 195046809Sdab */ 195146809Sdab int 195246809Sdab cleantmp(wtp) 195346809Sdab register struct utmp *wtp; 195446809Sdab { 195546809Sdab struct utmp *utp; 195646809Sdab static int first = 1; 195746809Sdab register int mask, omask, ret; 195865158Sdab extern struct utmp *getutid P((const struct utmp *_Id)); 195946809Sdab 196065158Sdab 196146809Sdab mask = sigmask(WJSIGNAL); 196246809Sdab 196346809Sdab if (first == 0) { 196446809Sdab omask = sigblock(mask); 196546809Sdab while (gotsigjob == 0) 196646809Sdab sigpause(omask); 196746809Sdab return(1); 196846809Sdab } 196946809Sdab first = 0; 197046809Sdab setutent(); /* just to make sure */ 197146809Sdab 197246809Sdab utp = getutid(wtp); 197346809Sdab if (utp == 0) { 197446809Sdab syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); 197546809Sdab return(-1); 197646809Sdab } 197746809Sdab /* 197846809Sdab * Nothing to clean up if the user shell was never started. 197946809Sdab */ 198046809Sdab if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) 198146809Sdab return(1); 198246809Sdab 198346809Sdab /* 198446809Sdab * Block the WJSIGNAL while we are in jobend(). 198546809Sdab */ 198646809Sdab omask = sigblock(mask); 198746809Sdab ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); 198846809Sdab sigsetmask(omask); 198946809Sdab return(ret); 199046809Sdab } 199146809Sdab 199246809Sdab int 199346809Sdab jobend(jid, path, user) 199446809Sdab register int jid; 199546809Sdab register char *path; 199646809Sdab register char *user; 199746809Sdab { 199846809Sdab static int saved_jid = 0; 199946809Sdab static char saved_path[sizeof(wtmp.ut_tpath)+1]; 200046809Sdab static char saved_user[sizeof(wtmp.ut_user)+1]; 200146809Sdab 200246809Sdab if (path) { 200346809Sdab strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); 200446809Sdab strncpy(saved_user, user, sizeof(wtmp.ut_user)); 200546809Sdab saved_path[sizeof(saved_path)] = '\0'; 200646809Sdab saved_user[sizeof(saved_user)] = '\0'; 200746809Sdab } 200846809Sdab if (saved_jid == 0) { 200946809Sdab saved_jid = jid; 201046809Sdab return(0); 201146809Sdab } 201246809Sdab cleantmpdir(jid, saved_path, saved_user); 201346809Sdab return(1); 201446809Sdab } 201546809Sdab 201646809Sdab /* 201746809Sdab * Fork a child process to clean up the TMPDIR 201846809Sdab */ 201946809Sdab cleantmpdir(jid, tpath, user) 202046809Sdab register int jid; 202146809Sdab register char *tpath; 202246809Sdab register char *user; 202346809Sdab { 202446809Sdab switch(fork()) { 202546809Sdab case -1: 202646809Sdab syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n", 202746809Sdab tpath); 202846809Sdab break; 202946809Sdab case 0: 203046809Sdab execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); 203146809Sdab syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", 203246809Sdab tpath, CLEANTMPCMD); 203346809Sdab exit(1); 203446809Sdab default: 203546809Sdab /* 203646809Sdab * Forget about child. We will exit, and 203746809Sdab * /etc/init will pick it up. 203846809Sdab */ 203946809Sdab break; 204046809Sdab } 204146809Sdab } 204260151Sdab # endif /* CRAY */ 204360151Sdab #endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */ 204438905Sborman 204538905Sborman /* 204638905Sborman * rmut() 204738905Sborman * 204838905Sborman * This is the function called by cleanup() to 204938905Sborman * remove the utmp entry for this person. 205038905Sborman */ 205138905Sborman 205257212Sdab #ifdef UTMPX 205365158Sdab void 205457212Sdab rmut() 205557212Sdab { 205657212Sdab register f; 205757212Sdab int found = 0; 205857212Sdab struct utmp *u, *utmp; 205957212Sdab int nutmp; 206057212Sdab struct stat statbf; 206157212Sdab 206257212Sdab struct utmpx *utxp, utmpx; 206357212Sdab 206457212Sdab /* 206557212Sdab * This updates the utmpx and utmp entries and make a wtmp/x entry 206657212Sdab */ 206757212Sdab 206857212Sdab SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); 206957212Sdab utxp = getutxline(&utmpx); 207057212Sdab if (utxp) { 207157212Sdab utxp->ut_type = DEAD_PROCESS; 207257212Sdab utxp->ut_exit.e_termination = 0; 207357212Sdab utxp->ut_exit.e_exit = 0; 207457212Sdab (void) time(&utmpx.ut_tv.tv_sec); 207557212Sdab utmpx.ut_tv.tv_usec = 0; 207657212Sdab modutx(utxp); 207757212Sdab } 207857212Sdab endutxent(); 207957212Sdab } /* end of rmut */ 208057212Sdab #endif 208157212Sdab 208260151Sdab #if !defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43 208346809Sdab void 208438905Sborman rmut() 208538905Sborman { 208638905Sborman register f; 208738905Sborman int found = 0; 208838905Sborman struct utmp *u, *utmp; 208938905Sborman int nutmp; 209038905Sborman struct stat statbf; 209138905Sborman 209238905Sborman f = open(utmpf, O_RDWR); 209338905Sborman if (f >= 0) { 209438905Sborman (void) fstat(f, &statbf); 209538905Sborman utmp = (struct utmp *)malloc((unsigned)statbf.st_size); 209638905Sborman if (!utmp) 209738905Sborman syslog(LOG_ERR, "utmp malloc failed"); 209838905Sborman if (statbf.st_size && utmp) { 209938905Sborman nutmp = read(f, (char *)utmp, (int)statbf.st_size); 210038905Sborman nutmp /= sizeof(struct utmp); 210138905Sborman 210238905Sborman for (u = utmp ; u < &utmp[nutmp] ; u++) { 210338905Sborman if (SCMPN(u->ut_line, line+5) || 210438905Sborman u->ut_name[0]==0) 210538905Sborman continue; 210638905Sborman (void) lseek(f, ((long)u)-((long)utmp), L_SET); 210738905Sborman SCPYN(u->ut_name, ""); 210838905Sborman SCPYN(u->ut_host, ""); 210938905Sborman (void) time(&u->ut_time); 211038905Sborman (void) write(f, (char *)u, sizeof(wtmp)); 211138905Sborman found++; 211238905Sborman } 211338905Sborman } 211438905Sborman (void) close(f); 211538905Sborman } 211638905Sborman if (found) { 211738905Sborman f = open(wtmpf, O_WRONLY|O_APPEND); 211838905Sborman if (f >= 0) { 211938905Sborman SCPYN(wtmp.ut_line, line+5); 212038905Sborman SCPYN(wtmp.ut_name, ""); 212138905Sborman SCPYN(wtmp.ut_host, ""); 212238905Sborman (void) time(&wtmp.ut_time); 212338905Sborman (void) write(f, (char *)&wtmp, sizeof(wtmp)); 212438905Sborman (void) close(f); 212538905Sborman } 212638905Sborman } 212738905Sborman (void) chmod(line, 0666); 212838905Sborman (void) chown(line, 0, 0); 212938905Sborman line[strlen("/dev/")] = 'p'; 213038905Sborman (void) chmod(line, 0666); 213138905Sborman (void) chown(line, 0, 0); 213238905Sborman } /* end of rmut */ 213338905Sborman #endif /* CRAY */ 213460151Sdab 213560151Sdab #ifdef __hpux 213660151Sdab rmut (line) 213760151Sdab char *line; 213860151Sdab { 213960151Sdab struct utmp utmp; 214060151Sdab struct utmp *utptr; 214160151Sdab int fd; /* for /etc/wtmp */ 214260151Sdab 214360151Sdab utmp.ut_type = USER_PROCESS; 214460151Sdab (void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id)); 214560151Sdab (void) setutent(); 214660151Sdab utptr = getutid(&utmp); 214760151Sdab /* write it out only if it exists */ 214860151Sdab if (utptr) { 214960151Sdab utptr->ut_type = DEAD_PROCESS; 215060151Sdab utptr->ut_time = time((long *) 0); 215160151Sdab (void) pututline(utptr); 215260151Sdab /* set wtmp entry if wtmp file exists */ 215360151Sdab if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) { 215460151Sdab (void) write(fd, utptr, sizeof(utmp)); 215560151Sdab (void) close(fd); 215660151Sdab } 215760151Sdab } 215860151Sdab (void) endutent(); 215960151Sdab 216060151Sdab (void) chmod(line, 0666); 216160151Sdab (void) chown(line, 0, 0); 216260151Sdab line[14] = line[13]; 216360151Sdab line[13] = line[12]; 216460151Sdab line[8] = 'm'; 216560151Sdab line[9] = '/'; 216660151Sdab line[10] = 'p'; 216760151Sdab line[11] = 't'; 216860151Sdab line[12] = 'y'; 216960151Sdab (void) chmod(line, 0666); 217060151Sdab (void) chown(line, 0, 0); 217160151Sdab } 217260151Sdab #endif 2173