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*65158Sdab static char sccsid[] = "@(#)sys_term.c 8.2 (Berkeley) 12/15/93"; 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> 29*65158Sdab struct utmpx wtmp; 3057212Sdab # else 3157212Sdab # include <utmp.h> 32*65158Sdab 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 } 626*65158Sdab #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 689*65158Sdab #if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 690*65158Sdab int 691*65158Sdab tty_setraw(on) 692*65158Sdab { 693*65158Sdab # ifndef USE_TERMIO 694*65158Sdab if (on) 695*65158Sdab termbuf.sg.sg_flags |= RAW; 696*65158Sdab else 697*65158Sdab termbuf.sg.sg_flags &= ~RAW; 698*65158Sdab # else 699*65158Sdab if (on) 700*65158Sdab termbuf.c_lflag &= ~ICANON; 701*65158Sdab else 702*65158Sdab termbuf.c_lflag |= ICANON; 703*65158Sdab # endif 704*65158Sdab } 705*65158Sdab #endif 706*65158Sdab 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 /* 92038905Sborman * A table of available terminal speeds 92138905Sborman */ 92238905Sborman struct termspeeds { 92338905Sborman int speed; 92438905Sborman int value; 92538905Sborman } termspeeds[] = { 92638905Sborman { 0, B0 }, { 50, B50 }, { 75, B75 }, 92738905Sborman { 110, B110 }, { 134, B134 }, { 150, B150 }, 92838905Sborman { 200, B200 }, { 300, B300 }, { 600, B600 }, 92938905Sborman { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 93038905Sborman { 4800, B4800 }, { 9600, B9600 }, { 19200, B9600 }, 93138905Sborman { 38400, B9600 }, { -1, B9600 } 93238905Sborman }; 93338905Sborman 93446809Sdab void 93538905Sborman tty_tspeed(val) 93646809Sdab int val; 93738905Sborman { 93838905Sborman register struct termspeeds *tp; 93938905Sborman 94038905Sborman for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 94138905Sborman ; 94245234Sborman cfsetospeed(&termbuf, tp->value); 94338905Sborman } 94438905Sborman 94546809Sdab void 94638905Sborman tty_rspeed(val) 94746809Sdab int val; 94838905Sborman { 94938905Sborman register struct termspeeds *tp; 95038905Sborman 95138905Sborman for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 95238905Sborman ; 95345234Sborman cfsetispeed(&termbuf, tp->value); 95438905Sborman } 95538905Sborman 95640242Sborman #if defined(CRAY2) && defined(UNICOS5) 95746809Sdab int 95838905Sborman tty_isnewmap() 95938905Sborman { 96038905Sborman return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) && 96138905Sborman !(termbuf.c_oflag & ONLRET)); 96238905Sborman } 96338905Sborman #endif 96438905Sborman 96560151Sdab #ifdef PARENT_DOES_UTMP 96638905Sborman # ifndef NEWINIT 96738905Sborman extern struct utmp wtmp; 96838905Sborman extern char wtmpf[]; 96938905Sborman # else /* NEWINIT */ 97038905Sborman int gotalarm; 97146809Sdab 97246809Sdab /* ARGSUSED */ 97346809Sdab void 97440242Sborman nologinproc(sig) 97546809Sdab int sig; 97638905Sborman { 97738905Sborman gotalarm++; 97838905Sborman } 97938905Sborman # endif /* NEWINIT */ 98060151Sdab #endif /* PARENT_DOES_UTMP */ 98138905Sborman 98246809Sdab #ifndef NEWINIT 98360151Sdab # ifdef PARENT_DOES_UTMP 98446809Sdab extern void utmp_sig_init P((void)); 98546809Sdab extern void utmp_sig_reset P((void)); 98646809Sdab extern void utmp_sig_wait P((void)); 98746809Sdab extern void utmp_sig_notify P((int)); 98860151Sdab # endif /* PARENT_DOES_UTMP */ 98946809Sdab #endif 99046809Sdab 99138905Sborman /* 99238905Sborman * getptyslave() 99338905Sborman * 99438905Sborman * Open the slave side of the pty, and do any initialization 99538905Sborman * that is necessary. The return value is a file descriptor 99638905Sborman * for the slave side. 99738905Sborman */ 99846809Sdab int 99938905Sborman getptyslave() 100038905Sborman { 100138905Sborman register int t = -1; 100238905Sborman 100345234Sborman #if !defined(CRAY) || !defined(NEWINIT) 100445234Sborman # ifdef LINEMODE 100546809Sdab int waslm; 100646809Sdab # endif 100746809Sdab # ifdef TIOCGWINSZ 100846809Sdab struct winsize ws; 100946809Sdab extern int def_row, def_col; 101046809Sdab # endif 101146809Sdab extern int def_tspeed, def_rspeed; 101238905Sborman /* 101345234Sborman * Opening the slave side may cause initilization of the 101446809Sdab * kernel tty structure. We need remember the state of 101546809Sdab * if linemode was turned on 101646809Sdab * terminal window size 101746809Sdab * terminal speed 101846809Sdab * so that we can re-set them if we need to. 101938905Sborman */ 102046809Sdab # ifdef LINEMODE 102146809Sdab waslm = tty_linemode(); 102245234Sborman # endif 102345234Sborman 102445234Sborman 102545234Sborman /* 102645234Sborman * Make sure that we don't have a controlling tty, and 102745234Sborman * that we are the session (process group) leader. 102845234Sborman */ 102945234Sborman # ifdef TIOCNOTTY 103038905Sborman t = open(_PATH_TTY, O_RDWR); 103138905Sborman if (t >= 0) { 103238905Sborman (void) ioctl(t, TIOCNOTTY, (char *)0); 103338905Sborman (void) close(t); 103438905Sborman } 103545234Sborman # endif 103638905Sborman 103745234Sborman 103860151Sdab # ifdef PARENT_DOES_UTMP 103945234Sborman /* 104045234Sborman * Wait for our parent to get the utmp stuff to get done. 104145234Sborman */ 104245234Sborman utmp_sig_wait(); 104345234Sborman # endif 104445234Sborman 104545234Sborman t = cleanopen(line); 104638905Sborman if (t < 0) 104738905Sborman fatalperror(net, line); 104838905Sborman 104957592Sdab #ifdef STREAMSPTY 105057212Sdab #ifdef USE_TERMIO 105157212Sdab ttyfd = t; 105257212Sdab #endif 105357212Sdab if (ioctl(t, I_PUSH, "ptem") < 0) 105457212Sdab fatal(net, "I_PUSH ptem"); 105557212Sdab if (ioctl(t, I_PUSH, "ldterm") < 0) 105657212Sdab fatal(net, "I_PUSH ldterm"); 105757212Sdab if (ioctl(t, I_PUSH, "ttcompat") < 0) 105857212Sdab fatal(net, "I_PUSH ttcompat"); 105957212Sdab if (ioctl(pty, I_PUSH, "pckt") < 0) 106057212Sdab fatal(net, "I_PUSH pckt"); 106157212Sdab #endif 106257212Sdab 106345234Sborman /* 106445234Sborman * set up the tty modes as we like them to be. 106545234Sborman */ 106638905Sborman init_termbuf(); 106746809Sdab # ifdef TIOCGWINSZ 106846809Sdab if (def_row || def_col) { 106946809Sdab bzero((char *)&ws, sizeof(ws)); 107046809Sdab ws.ws_col = def_col; 107146809Sdab ws.ws_row = def_row; 107246809Sdab (void)ioctl(t, TIOCSWINSZ, (char *)&ws); 107346809Sdab } 107446809Sdab # endif 107545234Sborman 107645234Sborman /* 107745234Sborman * Settings for sgtty based systems 107845234Sborman */ 107945234Sborman # ifndef USE_TERMIO 108040242Sborman termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; 108145234Sborman # endif /* USE_TERMIO */ 108245234Sborman 108345234Sborman /* 108460151Sdab * Settings for UNICOS (and HPUX) 108545234Sborman */ 108660151Sdab # if defined(CRAY) || defined(__hpux) 108745234Sborman termbuf.c_oflag = OPOST|ONLCR|TAB3; 108845234Sborman termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; 108945234Sborman termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; 109045234Sborman termbuf.c_cflag = EXTB|HUPCL|CS8; 109145234Sborman # endif 109245234Sborman 109345234Sborman /* 109445234Sborman * Settings for all other termios/termio based 109545234Sborman * systems, other than 4.4BSD. In 4.4BSD the 109645234Sborman * kernel does the initial terminal setup. 109745234Sborman */ 109860151Sdab # if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) 109945234Sborman # ifndef OXTABS 110045234Sborman # define OXTABS 0 110145234Sborman # endif 110238905Sborman termbuf.c_lflag |= ECHO; 110338905Sborman termbuf.c_oflag |= ONLCR|OXTABS; 110438905Sborman termbuf.c_iflag |= ICRNL; 110538905Sborman termbuf.c_iflag &= ~IXOFF; 110645234Sborman # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */ 110746996Sdab tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); 110846996Sdab tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); 110946809Sdab # ifdef LINEMODE 111046809Sdab if (waslm) 111146809Sdab tty_setlinemode(1); 111246809Sdab # endif /* LINEMODE */ 111345234Sborman 111445234Sborman /* 111545234Sborman * Set the tty modes, and make this our controlling tty. 111645234Sborman */ 111745234Sborman set_termbuf(); 111845234Sborman if (login_tty(t) == -1) 111945234Sborman fatalperror(net, "login_tty"); 112045234Sborman #endif /* !defined(CRAY) || !defined(NEWINIT) */ 112145234Sborman if (net > 2) 112245234Sborman (void) close(net); 1123*65158Sdab #if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 1124*65158Sdab /* 1125*65158Sdab * Leave the pty open so that we can write out the rlogin 1126*65158Sdab * protocol for /bin/login, if the authentication works. 1127*65158Sdab */ 1128*65158Sdab #else 1129*65158Sdab if (pty > 2) { 113045234Sborman (void) close(pty); 1131*65158Sdab pty = -1; 1132*65158Sdab } 1133*65158Sdab #endif 113445234Sborman } 113545234Sborman 113645234Sborman #if !defined(CRAY) || !defined(NEWINIT) 113745234Sborman #ifndef O_NOCTTY 113845234Sborman #define O_NOCTTY 0 113938905Sborman #endif 114045234Sborman /* 114145234Sborman * Open the specified slave side of the pty, 114245234Sborman * making sure that we have a clean tty. 114345234Sborman */ 114446809Sdab int 114545234Sborman cleanopen(line) 114646809Sdab char *line; 114745234Sborman { 114845234Sborman register int t; 114957212Sdab #if defined(_SC_CRAY_SECURE_SYS) 115057212Sdab struct secstat secbuf; 115157212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 115245234Sborman 115357212Sdab #ifndef STREAMSPTY 115445234Sborman /* 115545234Sborman * Make sure that other people can't open the 115645234Sborman * slave side of the connection. 115745234Sborman */ 115838905Sborman (void) chown(line, 0, 0); 115938905Sborman (void) chmod(line, 0600); 116057212Sdab #endif 116145234Sborman 116245234Sborman # if !defined(CRAY) && (BSD > 43) 116345234Sborman (void) revoke(line); 116445234Sborman # endif 116557212Sdab #if defined(_SC_CRAY_SECURE_SYS) 116657212Sdab if (secflag) { 116757212Sdab if (secstat(line, &secbuf) < 0) 116857212Sdab return(-1); 116957212Sdab if (setulvl(secbuf.st_slevel) < 0) 117057212Sdab return(-1); 117157212Sdab if (setucmp(secbuf.st_compart) < 0) 117257212Sdab return(-1); 117357212Sdab } 117457212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 117557212Sdab 117645234Sborman t = open(line, O_RDWR|O_NOCTTY); 117757212Sdab 117857212Sdab #if defined(_SC_CRAY_SECURE_SYS) 117957212Sdab if (secflag) { 118057212Sdab if (setulvl(sysv.sy_minlvl) < 0) 118157212Sdab return(-1); 118257212Sdab if (setucmp(0) < 0) 118357212Sdab return(-1); 118457212Sdab } 118557212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 118657212Sdab 118745234Sborman if (t < 0) 118845234Sborman return(-1); 118945234Sborman 119045234Sborman /* 119145234Sborman * Hangup anybody else using this ttyp, then reopen it for 119245234Sborman * ourselves. 119345234Sborman */ 119460151Sdab # if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY) 119545234Sborman (void) signal(SIGHUP, SIG_IGN); 119645234Sborman vhangup(); 119745234Sborman (void) signal(SIGHUP, SIG_DFL); 119845234Sborman t = open(line, O_RDWR|O_NOCTTY); 119945234Sborman if (t < 0) 120045234Sborman return(-1); 120145234Sborman # endif 120245234Sborman # if defined(CRAY) && defined(TCVHUP) 120345234Sborman { 120445234Sborman register int i; 120545234Sborman (void) signal(SIGHUP, SIG_IGN); 120645234Sborman (void) ioctl(t, TCVHUP, (char *)0); 120745234Sborman (void) signal(SIGHUP, SIG_DFL); 120845234Sborman setpgrp(); 120957212Sdab 121057212Sdab #if defined(_SC_CRAY_SECURE_SYS) 121157212Sdab if (secflag) { 121257212Sdab if (secstat(line, &secbuf) < 0) 121357212Sdab return(-1); 121457212Sdab if (setulvl(secbuf.st_slevel) < 0) 121557212Sdab return(-1); 121657212Sdab if (setucmp(secbuf.st_compart) < 0) 121757212Sdab return(-1); 121857212Sdab } 121957212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 122057212Sdab 122145234Sborman i = open(line, O_RDWR); 122257212Sdab 122357212Sdab #if defined(_SC_CRAY_SECURE_SYS) 122457212Sdab if (secflag) { 122557212Sdab if (setulvl(sysv.sy_minlvl) < 0) 122657212Sdab return(-1); 122757212Sdab if (setucmp(0) < 0) 122857212Sdab return(-1); 122957212Sdab } 123057212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 123157212Sdab 123245234Sborman if (i < 0) 123346809Sdab return(-1); 123445234Sborman (void) close(t); 123545234Sborman t = i; 123645234Sborman } 123745234Sborman # endif /* defined(CRAY) && defined(TCVHUP) */ 123838905Sborman return(t); 123938905Sborman } 124045234Sborman #endif /* !defined(CRAY) || !defined(NEWINIT) */ 124138905Sborman 124245234Sborman #if BSD <= 43 1243*65158Sdab 124446809Sdab int 124545234Sborman login_tty(t) 124646809Sdab int t; 124745234Sborman { 1248*65158Sdab if (setsid() < 0) { 1249*65158Sdab #ifdef ultrix 1250*65158Sdab /* 1251*65158Sdab * The setsid() may have failed because we 1252*65158Sdab * already have a pgrp == pid. Zero out 1253*65158Sdab * our pgrp and try again... 1254*65158Sdab */ 1255*65158Sdab if ((setpgrp(0, 0) < 0) || (setsid() < 0)) 1256*65158Sdab #endif 1257*65158Sdab fatalperror(net, "setsid()"); 1258*65158Sdab } 125945234Sborman # ifdef TIOCSCTTY 126045234Sborman if (ioctl(t, TIOCSCTTY, (char *)0) < 0) 126145234Sborman fatalperror(net, "ioctl(sctty)"); 126257212Sdab # if defined(CRAY) 126347613Sdab /* 126447613Sdab * Close the hard fd to /dev/ttypXXX, and re-open through 126547613Sdab * the indirect /dev/tty interface. 126647613Sdab */ 126747613Sdab close(t); 126847613Sdab if ((t = open("/dev/tty", O_RDWR)) < 0) 126947613Sdab fatalperror(net, "open(/dev/tty)"); 127047613Sdab # endif 127145234Sborman # else 1272*65158Sdab /* 1273*65158Sdab * We get our controlling tty assigned as a side-effect 1274*65158Sdab * of opening up a tty device. But on BSD based systems, 1275*65158Sdab * this only happens if our process group is zero. The 1276*65158Sdab * setsid() call above may have set our pgrp, so clear 1277*65158Sdab * it out before opening the tty... 1278*65158Sdab */ 1279*65158Sdab (void) setpgrp(0, 0); 128045234Sborman close(open(line, O_RDWR)); 128145234Sborman # endif 128247613Sdab if (t != 0) 128347613Sdab (void) dup2(t, 0); 128447613Sdab if (t != 1) 128547613Sdab (void) dup2(t, 1); 128647613Sdab if (t != 2) 128747613Sdab (void) dup2(t, 2); 128847613Sdab if (t > 2) 128947613Sdab close(t); 129046809Sdab return(0); 129145234Sborman } 129245234Sborman #endif /* BSD <= 43 */ 129345234Sborman 129438905Sborman #ifdef NEWINIT 129538905Sborman char *gen_id = "fe"; 129638905Sborman #endif 129738905Sborman 129838905Sborman /* 129945234Sborman * startslave(host) 130038905Sborman * 130145234Sborman * Given a hostname, do whatever 130238905Sborman * is necessary to startup the login process on the slave side of the pty. 130338905Sborman */ 130438905Sborman 130538905Sborman /* ARGSUSED */ 130646809Sdab void 130746809Sdab startslave(host, autologin, autoname) 130846809Sdab char *host; 130946809Sdab int autologin; 131046809Sdab char *autoname; 131138905Sborman { 131238905Sborman register int i; 131338905Sborman long time(); 131446809Sdab char name[256]; 131546809Sdab #ifdef NEWINIT 131646809Sdab extern char *ptyip; 131746809Sdab struct init_request request; 131846809Sdab void nologinproc(); 131946809Sdab register int n; 132046809Sdab #endif /* NEWINIT */ 132138905Sborman 132257212Sdab #if defined(AUTHENTICATION) 132346809Sdab if (!autoname || !autoname[0]) 132446809Sdab autologin = 0; 132546809Sdab 132646809Sdab if (autologin < auth_level) { 132746809Sdab fatal(net, "Authorization failed"); 132846809Sdab exit(1); 132946809Sdab } 133046809Sdab #endif 133146809Sdab 133238905Sborman #ifndef NEWINIT 133360151Sdab # ifdef PARENT_DOES_UTMP 133438905Sborman utmp_sig_init(); 133560151Sdab # endif /* PARENT_DOES_UTMP */ 133638905Sborman 133738905Sborman if ((i = fork()) < 0) 133838905Sborman fatalperror(net, "fork"); 133938905Sborman if (i) { 134060151Sdab # ifdef PARENT_DOES_UTMP 134138905Sborman /* 134238905Sborman * Cray parent will create utmp entry for child and send 134338905Sborman * signal to child to tell when done. Child waits for signal 134438905Sborman * before doing anything important. 134538905Sborman */ 134638905Sborman register int pid = i; 134746809Sdab void sigjob P((int)); 134838905Sborman 134938905Sborman setpgrp(); 135044364Sborman utmp_sig_reset(); /* reset handler to default */ 135138905Sborman /* 135238905Sborman * Create utmp entry for child 135338905Sborman */ 135438905Sborman (void) time(&wtmp.ut_time); 135538905Sborman wtmp.ut_type = LOGIN_PROCESS; 135638905Sborman wtmp.ut_pid = pid; 135738905Sborman SCPYN(wtmp.ut_user, "LOGIN"); 135838905Sborman SCPYN(wtmp.ut_host, host); 135938905Sborman SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); 136060151Sdab #ifndef __hpux 136138905Sborman SCPYN(wtmp.ut_id, wtmp.ut_line+3); 136260151Sdab #else 136360151Sdab SCPYN(wtmp.ut_id, wtmp.ut_line+7); 136460151Sdab #endif 136538905Sborman pututline(&wtmp); 136638905Sborman endutent(); 136738905Sborman if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { 136838905Sborman (void) write(i, (char *)&wtmp, sizeof(struct utmp)); 136938905Sborman (void) close(i); 137038905Sborman } 137160151Sdab #ifdef CRAY 137246809Sdab (void) signal(WJSIGNAL, sigjob); 137360151Sdab #endif 137438905Sborman utmp_sig_notify(pid); 137560151Sdab # endif /* PARENT_DOES_UTMP */ 137638905Sborman } else { 1377*65158Sdab getptyslave(autologin); 137846809Sdab start_login(host, autologin, autoname); 137938905Sborman /*NOTREACHED*/ 138038905Sborman } 138138905Sborman #else /* NEWINIT */ 138238905Sborman 138338905Sborman /* 138438905Sborman * Init will start up login process if we ask nicely. We only wait 138538905Sborman * for it to start up and begin normal telnet operation. 138638905Sborman */ 138738905Sborman if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { 138838905Sborman char tbuf[128]; 138938905Sborman (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO); 139038905Sborman fatalperror(net, tbuf); 139138905Sborman } 139238905Sborman memset((char *)&request, 0, sizeof(request)); 139338905Sborman request.magic = INIT_MAGIC; 139438905Sborman SCPYN(request.gen_id, gen_id); 139538905Sborman SCPYN(request.tty_id, &line[8]); 139638905Sborman SCPYN(request.host, host); 139746809Sdab SCPYN(request.term_type, terminaltype ? terminaltype : "network"); 139844364Sborman #if !defined(UNICOS5) 139940242Sborman request.signal = SIGCLD; 140040242Sborman request.pid = getpid(); 140140242Sborman #endif 140244364Sborman #ifdef BFTPDAEMON 140344364Sborman /* 140444364Sborman * Are we working as the bftp daemon? 140544364Sborman */ 140644364Sborman if (bftpd) { 140744364Sborman SCPYN(request.exec_name, BFTPPATH); 140844364Sborman } 140944364Sborman #endif /* BFTPDAEMON */ 141038905Sborman if (write(i, (char *)&request, sizeof(request)) < 0) { 141138905Sborman char tbuf[128]; 141238905Sborman (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO); 141338905Sborman fatalperror(net, tbuf); 141438905Sborman } 141538905Sborman (void) close(i); 141638905Sborman (void) signal(SIGALRM, nologinproc); 141738905Sborman for (i = 0; ; i++) { 141840242Sborman char tbuf[128]; 141938905Sborman alarm(15); 142038905Sborman n = read(pty, ptyip, BUFSIZ); 142138905Sborman if (i == 3 || n >= 0 || !gotalarm) 142238905Sborman break; 142338905Sborman gotalarm = 0; 142440242Sborman sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line); 142540242Sborman (void) write(net, tbuf, strlen(tbuf)); 142638905Sborman } 142738905Sborman if (n < 0 && gotalarm) 142838905Sborman fatal(net, "/etc/init didn't start login process"); 142938905Sborman pcc += n; 143038905Sborman alarm(0); 143138905Sborman (void) signal(SIGALRM, SIG_DFL); 143238905Sborman 143338905Sborman return; 143438905Sborman #endif /* NEWINIT */ 143538905Sborman } 143638905Sborman 143738905Sborman char *envinit[3]; 143844364Sborman extern char **environ; 143938905Sborman 144046809Sdab void 144144364Sborman init_env() 144244364Sborman { 144344364Sborman extern char *getenv(); 144444364Sborman char **envp; 144544364Sborman 144644364Sborman envp = envinit; 144744364Sborman if (*envp = getenv("TZ")) 144844364Sborman *envp++ -= 3; 144960151Sdab #if defined(CRAY) || defined(__hpux) 145044364Sborman else 145144364Sborman *envp++ = "TZ=GMT0"; 145244364Sborman #endif 145344364Sborman *envp = 0; 145444364Sborman environ = envinit; 145544364Sborman } 145644364Sborman 145744364Sborman #ifndef NEWINIT 145844364Sborman 145944364Sborman /* 146045234Sborman * start_login(host) 146138905Sborman * 146238905Sborman * Assuming that we are now running as a child processes, this 146338905Sborman * function will turn us into the login process. 146438905Sborman */ 146538905Sborman 146646809Sdab void 146746809Sdab start_login(host, autologin, name) 146846809Sdab char *host; 146946809Sdab int autologin; 147046809Sdab char *name; 147138905Sborman { 147244364Sborman register char *cp; 147344364Sborman register char **argv; 147444364Sborman char **addarg(); 1475*65158Sdab extern char *getenv(); 147657212Sdab #ifdef UTMPX 147757212Sdab register int pid = getpid(); 147857212Sdab struct utmpx utmpx; 147957212Sdab #endif 1480*65158Sdab #ifdef SOLARIS 148157212Sdab char *term; 148257212Sdab char termbuf[64]; 148357212Sdab #endif 148438905Sborman 148557212Sdab #ifdef UTMPX 148638905Sborman /* 148757212Sdab * Create utmp entry for child 148857212Sdab */ 148957212Sdab 149057212Sdab bzero(&utmpx, sizeof(utmpx)); 149157212Sdab SCPYN(utmpx.ut_user, ".telnet"); 149257212Sdab SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); 149357212Sdab utmpx.ut_pid = pid; 149457212Sdab utmpx.ut_id[0] = 't'; 149557212Sdab utmpx.ut_id[1] = 'n'; 149657212Sdab utmpx.ut_id[2] = SC_WILDC; 149757212Sdab utmpx.ut_id[3] = SC_WILDC; 149857212Sdab utmpx.ut_type = LOGIN_PROCESS; 149957212Sdab (void) time(&utmpx.ut_tv.tv_sec); 150057212Sdab if (makeutx(&utmpx) == NULL) 150157212Sdab fatal(net, "makeutx failed"); 150257212Sdab #endif 150357212Sdab 150457212Sdab /* 150538905Sborman * -h : pass on name of host. 150638905Sborman * WARNING: -h is accepted by login if and only if 150738905Sborman * getuid() == 0. 150838905Sborman * -p : don't clobber the environment (so terminal type stays set). 150946809Sdab * 151046809Sdab * -f : force this login, he has already been authenticated 151138905Sborman */ 151244364Sborman argv = addarg(0, "login"); 1513*65158Sdab 151460151Sdab #if !defined(NO_LOGIN_H) 1515*65158Sdab 1516*65158Sdab # if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 151757212Sdab /* 1518*65158Sdab * Don't add the "-h host" option if we are going 1519*65158Sdab * to be adding the "-r host" option down below... 152057212Sdab */ 1521*65158Sdab if ((auth_level < 0) || (autologin != AUTH_VALID)) 1522*65158Sdab # endif 1523*65158Sdab { 1524*65158Sdab argv = addarg(argv, "-h"); 1525*65158Sdab argv = addarg(argv, host); 1526*65158Sdab #ifdef SOLARIS 1527*65158Sdab /* 1528*65158Sdab * SVR4 version of -h takes TERM= as second arg, or - 1529*65158Sdab */ 1530*65158Sdab term = getenv("TERM"); 1531*65158Sdab if (term == NULL || term[0] == 0) { 1532*65158Sdab term = "-"; 1533*65158Sdab } else { 1534*65158Sdab strcpy(termbuf, "TERM="); 1535*65158Sdab strncat(termbuf, term, sizeof(termbuf) - 6); 1536*65158Sdab term = termbuf; 1537*65158Sdab } 1538*65158Sdab argv = addarg(argv, term); 1539*65158Sdab #endif 154057212Sdab } 154157212Sdab #endif 154246809Sdab #if !defined(NO_LOGIN_P) 154344364Sborman argv = addarg(argv, "-p"); 154438905Sborman #endif 154544364Sborman #ifdef BFTPDAEMON 154644364Sborman /* 154744364Sborman * Are we working as the bftp daemon? If so, then ask login 154844364Sborman * to start bftp instead of shell. 154944364Sborman */ 155044364Sborman if (bftpd) { 155144364Sborman argv = addarg(argv, "-e"); 155244364Sborman argv = addarg(argv, BFTPPATH); 155344364Sborman } else 155444364Sborman #endif 155546809Sdab #if defined (SecurID) 155646809Sdab /* 155746809Sdab * don't worry about the -f that might get sent. 155846809Sdab * A -s is supposed to override it anyhow. 155946809Sdab */ 156046809Sdab if (require_SecurID) 156146809Sdab argv = addarg(argv, "-s"); 156246809Sdab #endif 156357212Sdab #if defined (AUTHENTICATION) 156446809Sdab if (auth_level >= 0 && autologin == AUTH_VALID) { 156546809Sdab # if !defined(NO_LOGIN_F) 156646809Sdab argv = addarg(argv, "-f"); 1567*65158Sdab argv = addarg(argv, name); 1568*65158Sdab # else 1569*65158Sdab # if defined(LOGIN_R) 1570*65158Sdab /* 1571*65158Sdab * We don't have support for "login -f", but we 1572*65158Sdab * can fool /bin/login into thinking that we are 1573*65158Sdab * rlogind, and allow us to log in without a 1574*65158Sdab * password. The rlogin protocol expects 1575*65158Sdab * local-user\0remote-user\0term/speed\0 1576*65158Sdab */ 1577*65158Sdab 1578*65158Sdab if (pty > 2) { 1579*65158Sdab register char *cp; 1580*65158Sdab char speed[128]; 1581*65158Sdab int isecho, israw, xpty, len; 1582*65158Sdab extern int def_rspeed; 1583*65158Sdab # ifndef LOGIN_HOST 1584*65158Sdab /* 1585*65158Sdab * Tell login that we are coming from "localhost". 1586*65158Sdab * If we passed in the real host name, then the 1587*65158Sdab * user would have to allow .rhost access from 1588*65158Sdab * every machine that they want authenticated 1589*65158Sdab * access to work from, which sort of defeats 1590*65158Sdab * the purpose of an authenticated login... 1591*65158Sdab * So, we tell login that the session is coming 1592*65158Sdab * from "localhost", and the user will only have 1593*65158Sdab * to have "localhost" in their .rhost file. 1594*65158Sdab */ 1595*65158Sdab # define LOGIN_HOST "localhost" 1596*65158Sdab # endif 1597*65158Sdab argv = addarg(argv, "-r"); 1598*65158Sdab argv = addarg(argv, LOGIN_HOST); 1599*65158Sdab 1600*65158Sdab xpty = pty; 1601*65158Sdab # ifndef STREAMSPTY 1602*65158Sdab pty = 0; 1603*65158Sdab # else 1604*65158Sdab ttyfd = 0; 160546809Sdab # endif 1606*65158Sdab init_termbuf(); 1607*65158Sdab isecho = tty_isecho(); 1608*65158Sdab israw = tty_israw(); 1609*65158Sdab if (isecho || !israw) { 1610*65158Sdab tty_setecho(0); /* Turn off echo */ 1611*65158Sdab tty_setraw(1); /* Turn on raw */ 1612*65158Sdab set_termbuf(); 1613*65158Sdab } 1614*65158Sdab len = strlen(name)+1; 1615*65158Sdab write(xpty, name, len); 1616*65158Sdab write(xpty, name, len); 1617*65158Sdab sprintf(speed, "%s/%d", (cp = getenv("TERM")) ? cp : "", 1618*65158Sdab (def_rspeed > 0) ? def_rspeed : 9600); 1619*65158Sdab len = strlen(speed)+1; 1620*65158Sdab write(xpty, speed, len); 1621*65158Sdab 1622*65158Sdab if (isecho || !israw) { 1623*65158Sdab init_termbuf(); 1624*65158Sdab tty_setecho(isecho); 1625*65158Sdab tty_setraw(israw); 1626*65158Sdab set_termbuf(); 1627*65158Sdab if (!israw) { 1628*65158Sdab /* 1629*65158Sdab * Write a newline to ensure 1630*65158Sdab * that login will be able to 1631*65158Sdab * read the line... 1632*65158Sdab */ 1633*65158Sdab write(xpty, "\n", 1); 1634*65158Sdab } 1635*65158Sdab } 1636*65158Sdab pty = xpty; 1637*65158Sdab } 1638*65158Sdab # else 163946809Sdab argv = addarg(argv, name); 1640*65158Sdab # endif 1641*65158Sdab # endif 164246809Sdab } else 164346809Sdab #endif 164444364Sborman if (getenv("USER")) { 164544364Sborman argv = addarg(argv, getenv("USER")); 1646*65158Sdab #if defined(LOGIN_ARGS) && defined(NO_LOGIN_P) 164746809Sdab { 164846809Sdab register char **cpp; 164946809Sdab for (cpp = environ; *cpp; cpp++) 165046809Sdab argv = addarg(argv, *cpp); 165146809Sdab } 165246809Sdab #endif 165357212Sdab /* 165457212Sdab * Assume that login will set the USER variable 165557212Sdab * correctly. For SysV systems, this means that 165657212Sdab * USER will no longer be set, just LOGNAME by 165757212Sdab * login. (The problem is that if the auto-login 165857212Sdab * fails, and the user then specifies a different 165957212Sdab * account name, he can get logged in with both 166057212Sdab * LOGNAME and USER in his environment, but the 166157212Sdab * USER value will be wrong. 166257212Sdab */ 166357212Sdab unsetenv("USER"); 166444364Sborman } 1665*65158Sdab #if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 1666*65158Sdab if (pty > 2) 1667*65158Sdab close(pty); 1668*65158Sdab #endif 166946809Sdab closelog(); 167044364Sborman execv(_PATH_LOGIN, argv); 167144364Sborman 167238905Sborman syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN); 167338905Sborman fatalperror(net, _PATH_LOGIN); 167438905Sborman /*NOTREACHED*/ 167538905Sborman } 167644364Sborman 167746809Sdab char ** 167844364Sborman addarg(argv, val) 167946809Sdab register char **argv; 168046809Sdab register char *val; 168144364Sborman { 168244364Sborman register char **cpp; 168344364Sborman 168444364Sborman if (argv == NULL) { 168544364Sborman /* 168644364Sborman * 10 entries, a leading length, and a null 168744364Sborman */ 168844364Sborman argv = (char **)malloc(sizeof(*argv) * 12); 168944364Sborman if (argv == NULL) 169044364Sborman return(NULL); 169144364Sborman *argv++ = (char *)10; 169244364Sborman *argv = (char *)0; 169344364Sborman } 169444364Sborman for (cpp = argv; *cpp; cpp++) 169544364Sborman ; 169644364Sborman if (cpp == &argv[(int)argv[-1]]) { 169744364Sborman --argv; 169844364Sborman *argv = (char *)((int)(*argv) + 10); 169944364Sborman argv = (char **)realloc(argv, (int)(*argv) + 2); 170044364Sborman if (argv == NULL) 170144364Sborman return(NULL); 170244364Sborman argv++; 170344364Sborman cpp = &argv[(int)argv[-1] - 10]; 170444364Sborman } 170544364Sborman *cpp++ = val; 170644364Sborman *cpp = 0; 170744364Sborman return(argv); 170844364Sborman } 170946809Sdab #endif /* NEWINIT */ 171038905Sborman 171138905Sborman /* 171238905Sborman * cleanup() 171338905Sborman * 171438905Sborman * This is the routine to call when we are all through, to 171538905Sborman * clean up anything that needs to be cleaned up. 171638905Sborman */ 171746809Sdab /* ARGSUSED */ 171846809Sdab void 171946809Sdab cleanup(sig) 172046809Sdab int sig; 172138905Sborman { 172260151Sdab #ifndef PARENT_DOES_UTMP 172345234Sborman # if (BSD > 43) || defined(convex) 172438905Sborman char *p; 172538905Sborman 172638905Sborman p = line + sizeof("/dev/") - 1; 172738905Sborman if (logout(p)) 172838905Sborman logwtmp(p, "", ""); 172938905Sborman (void)chmod(line, 0666); 173038905Sborman (void)chown(line, 0, 0); 173138905Sborman *p = 'p'; 173238905Sborman (void)chmod(line, 0666); 173338905Sborman (void)chown(line, 0, 0); 173446809Sdab (void) shutdown(net, 2); 173546809Sdab exit(1); 173638905Sborman # else 173746809Sdab void rmut(); 173846809Sdab 173938905Sborman rmut(); 174038905Sborman vhangup(); /* XXX */ 174146809Sdab (void) shutdown(net, 2); 174246809Sdab exit(1); 174338905Sborman # endif 174460151Sdab #else /* PARENT_DOES_UTMP */ 174546809Sdab # ifdef NEWINIT 174638905Sborman (void) shutdown(net, 2); 174746809Sdab exit(1); 174838905Sborman # else /* NEWINIT */ 174960151Sdab # ifdef CRAY 175046809Sdab static int incleanup = 0; 175146809Sdab register int t; 175246809Sdab 175346809Sdab /* 175446809Sdab * 1: Pick up the zombie, if we are being called 175546809Sdab * as the signal handler. 175646809Sdab * 2: If we are a nested cleanup(), return. 175746809Sdab * 3: Try to clean up TMPDIR. 175846809Sdab * 4: Fill in utmp with shutdown of process. 175946809Sdab * 5: Close down the network and pty connections. 176046809Sdab * 6: Finish up the TMPDIR cleanup, if needed. 176146809Sdab */ 176246809Sdab if (sig == SIGCHLD) 176346809Sdab while (waitpid(-1, 0, WNOHANG) > 0) 176446809Sdab ; /* VOID */ 176546809Sdab t = sigblock(sigmask(SIGCHLD)); 176646809Sdab if (incleanup) { 176746809Sdab sigsetmask(t); 176846809Sdab return; 176946809Sdab } 177046809Sdab incleanup = 1; 177146809Sdab sigsetmask(t); 177260151Sdab if (secflag) { 177360151Sdab /* 177460151Sdab * We need to set ourselves back to a null 177560151Sdab * label to clean up. 177660151Sdab */ 177746809Sdab 177860151Sdab setulvl(sysv.sy_minlvl); 177960151Sdab setucmp((long)0); 178060151Sdab } 178160151Sdab 178246809Sdab t = cleantmp(&wtmp); 178346809Sdab setutent(); /* just to make sure */ 178460151Sdab # endif /* CRAY */ 178546809Sdab rmut(line); 178646809Sdab close(pty); 178738905Sborman (void) shutdown(net, 2); 178860151Sdab # ifdef CRAY 178946809Sdab if (t == 0) 179046809Sdab cleantmp(&wtmp); 179160151Sdab # endif /* CRAY */ 179246809Sdab exit(1); 179338905Sborman # endif /* NEWINT */ 179460151Sdab #endif /* PARENT_DOES_UTMP */ 179538905Sborman } 179638905Sborman 179760151Sdab #if defined(PARENT_DOES_UTMP) && !defined(NEWINIT) 179838905Sborman /* 179938905Sborman * _utmp_sig_rcv 180038905Sborman * utmp_sig_init 180138905Sborman * utmp_sig_wait 180238905Sborman * These three functions are used to coordinate the handling of 180338905Sborman * the utmp file between the server and the soon-to-be-login shell. 180438905Sborman * The server actually creates the utmp structure, the child calls 180538905Sborman * utmp_sig_wait(), until the server calls utmp_sig_notify() and 180638905Sborman * signals the future-login shell to proceed. 180738905Sborman */ 180838905Sborman static int caught=0; /* NZ when signal intercepted */ 180938905Sborman static void (*func)(); /* address of previous handler */ 181038905Sborman 181146809Sdab void 181238905Sborman _utmp_sig_rcv(sig) 181346809Sdab int sig; 181438905Sborman { 181538905Sborman caught = 1; 181638905Sborman (void) signal(SIGUSR1, func); 181738905Sborman } 181838905Sborman 181946809Sdab void 182038905Sborman utmp_sig_init() 182138905Sborman { 182238905Sborman /* 182338905Sborman * register signal handler for UTMP creation 182438905Sborman */ 182538905Sborman if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) 182638905Sborman fatalperror(net, "telnetd/signal"); 182738905Sborman } 182838905Sborman 182946809Sdab void 183044364Sborman utmp_sig_reset() 183144364Sborman { 183244364Sborman (void) signal(SIGUSR1, func); /* reset handler to default */ 183344364Sborman } 183444364Sborman 183560151Sdab # ifdef __hpux 183660151Sdab # define sigoff() /* do nothing */ 183760151Sdab # define sigon() /* do nothing */ 183860151Sdab # endif 183960151Sdab 184046809Sdab void 184138905Sborman utmp_sig_wait() 184238905Sborman { 184338905Sborman /* 184438905Sborman * Wait for parent to write our utmp entry. 184538905Sborman */ 184638905Sborman sigoff(); 184738905Sborman while (caught == 0) { 184838905Sborman pause(); /* wait until we get a signal (sigon) */ 184938905Sborman sigoff(); /* turn off signals while we check caught */ 185038905Sborman } 185138905Sborman sigon(); /* turn on signals again */ 185238905Sborman } 185338905Sborman 185446809Sdab void 185538905Sborman utmp_sig_notify(pid) 185638905Sborman { 185738905Sborman kill(pid, SIGUSR1); 185838905Sborman } 185946809Sdab 186060151Sdab # ifdef CRAY 186146809Sdab static int gotsigjob = 0; 186246809Sdab 186346809Sdab /*ARGSUSED*/ 186446809Sdab void 186546809Sdab sigjob(sig) 186646809Sdab int sig; 186746809Sdab { 186846809Sdab register int jid; 186946809Sdab register struct jobtemp *jp; 187046809Sdab 187146809Sdab while ((jid = waitjob(NULL)) != -1) { 187246809Sdab if (jid == 0) { 187346809Sdab return; 187446809Sdab } 187546809Sdab gotsigjob++; 187646809Sdab jobend(jid, NULL, NULL); 187746809Sdab } 187846809Sdab } 187946809Sdab 188046809Sdab /* 188146809Sdab * Clean up the TMPDIR that login created. 188246809Sdab * The first time this is called we pick up the info 188346809Sdab * from the utmp. If the job has already gone away, 188446809Sdab * then we'll clean up and be done. If not, then 188546809Sdab * when this is called the second time it will wait 188646809Sdab * for the signal that the job is done. 188746809Sdab */ 188846809Sdab int 188946809Sdab cleantmp(wtp) 189046809Sdab register struct utmp *wtp; 189146809Sdab { 189246809Sdab struct utmp *utp; 189346809Sdab static int first = 1; 189446809Sdab register int mask, omask, ret; 1895*65158Sdab extern struct utmp *getutid P((const struct utmp *_Id)); 189646809Sdab 1897*65158Sdab 189846809Sdab mask = sigmask(WJSIGNAL); 189946809Sdab 190046809Sdab if (first == 0) { 190146809Sdab omask = sigblock(mask); 190246809Sdab while (gotsigjob == 0) 190346809Sdab sigpause(omask); 190446809Sdab return(1); 190546809Sdab } 190646809Sdab first = 0; 190746809Sdab setutent(); /* just to make sure */ 190846809Sdab 190946809Sdab utp = getutid(wtp); 191046809Sdab if (utp == 0) { 191146809Sdab syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); 191246809Sdab return(-1); 191346809Sdab } 191446809Sdab /* 191546809Sdab * Nothing to clean up if the user shell was never started. 191646809Sdab */ 191746809Sdab if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) 191846809Sdab return(1); 191946809Sdab 192046809Sdab /* 192146809Sdab * Block the WJSIGNAL while we are in jobend(). 192246809Sdab */ 192346809Sdab omask = sigblock(mask); 192446809Sdab ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); 192546809Sdab sigsetmask(omask); 192646809Sdab return(ret); 192746809Sdab } 192846809Sdab 192946809Sdab int 193046809Sdab jobend(jid, path, user) 193146809Sdab register int jid; 193246809Sdab register char *path; 193346809Sdab register char *user; 193446809Sdab { 193546809Sdab static int saved_jid = 0; 193646809Sdab static char saved_path[sizeof(wtmp.ut_tpath)+1]; 193746809Sdab static char saved_user[sizeof(wtmp.ut_user)+1]; 193846809Sdab 193946809Sdab if (path) { 194046809Sdab strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); 194146809Sdab strncpy(saved_user, user, sizeof(wtmp.ut_user)); 194246809Sdab saved_path[sizeof(saved_path)] = '\0'; 194346809Sdab saved_user[sizeof(saved_user)] = '\0'; 194446809Sdab } 194546809Sdab if (saved_jid == 0) { 194646809Sdab saved_jid = jid; 194746809Sdab return(0); 194846809Sdab } 194946809Sdab cleantmpdir(jid, saved_path, saved_user); 195046809Sdab return(1); 195146809Sdab } 195246809Sdab 195346809Sdab /* 195446809Sdab * Fork a child process to clean up the TMPDIR 195546809Sdab */ 195646809Sdab cleantmpdir(jid, tpath, user) 195746809Sdab register int jid; 195846809Sdab register char *tpath; 195946809Sdab register char *user; 196046809Sdab { 196146809Sdab switch(fork()) { 196246809Sdab case -1: 196346809Sdab syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n", 196446809Sdab tpath); 196546809Sdab break; 196646809Sdab case 0: 196746809Sdab execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); 196846809Sdab syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", 196946809Sdab tpath, CLEANTMPCMD); 197046809Sdab exit(1); 197146809Sdab default: 197246809Sdab /* 197346809Sdab * Forget about child. We will exit, and 197446809Sdab * /etc/init will pick it up. 197546809Sdab */ 197646809Sdab break; 197746809Sdab } 197846809Sdab } 197960151Sdab # endif /* CRAY */ 198060151Sdab #endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */ 198138905Sborman 198238905Sborman /* 198338905Sborman * rmut() 198438905Sborman * 198538905Sborman * This is the function called by cleanup() to 198638905Sborman * remove the utmp entry for this person. 198738905Sborman */ 198838905Sborman 198957212Sdab #ifdef UTMPX 1990*65158Sdab void 199157212Sdab rmut() 199257212Sdab { 199357212Sdab register f; 199457212Sdab int found = 0; 199557212Sdab struct utmp *u, *utmp; 199657212Sdab int nutmp; 199757212Sdab struct stat statbf; 199857212Sdab 199957212Sdab struct utmpx *utxp, utmpx; 200057212Sdab 200157212Sdab /* 200257212Sdab * This updates the utmpx and utmp entries and make a wtmp/x entry 200357212Sdab */ 200457212Sdab 200557212Sdab SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); 200657212Sdab utxp = getutxline(&utmpx); 200757212Sdab if (utxp) { 200857212Sdab utxp->ut_type = DEAD_PROCESS; 200957212Sdab utxp->ut_exit.e_termination = 0; 201057212Sdab utxp->ut_exit.e_exit = 0; 201157212Sdab (void) time(&utmpx.ut_tv.tv_sec); 201257212Sdab utmpx.ut_tv.tv_usec = 0; 201357212Sdab modutx(utxp); 201457212Sdab } 201557212Sdab endutxent(); 201657212Sdab } /* end of rmut */ 201757212Sdab #endif 201857212Sdab 201960151Sdab #if !defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43 202046809Sdab void 202138905Sborman rmut() 202238905Sborman { 202338905Sborman register f; 202438905Sborman int found = 0; 202538905Sborman struct utmp *u, *utmp; 202638905Sborman int nutmp; 202738905Sborman struct stat statbf; 202838905Sborman 202938905Sborman f = open(utmpf, O_RDWR); 203038905Sborman if (f >= 0) { 203138905Sborman (void) fstat(f, &statbf); 203238905Sborman utmp = (struct utmp *)malloc((unsigned)statbf.st_size); 203338905Sborman if (!utmp) 203438905Sborman syslog(LOG_ERR, "utmp malloc failed"); 203538905Sborman if (statbf.st_size && utmp) { 203638905Sborman nutmp = read(f, (char *)utmp, (int)statbf.st_size); 203738905Sborman nutmp /= sizeof(struct utmp); 203838905Sborman 203938905Sborman for (u = utmp ; u < &utmp[nutmp] ; u++) { 204038905Sborman if (SCMPN(u->ut_line, line+5) || 204138905Sborman u->ut_name[0]==0) 204238905Sborman continue; 204338905Sborman (void) lseek(f, ((long)u)-((long)utmp), L_SET); 204438905Sborman SCPYN(u->ut_name, ""); 204538905Sborman SCPYN(u->ut_host, ""); 204638905Sborman (void) time(&u->ut_time); 204738905Sborman (void) write(f, (char *)u, sizeof(wtmp)); 204838905Sborman found++; 204938905Sborman } 205038905Sborman } 205138905Sborman (void) close(f); 205238905Sborman } 205338905Sborman if (found) { 205438905Sborman f = open(wtmpf, O_WRONLY|O_APPEND); 205538905Sborman if (f >= 0) { 205638905Sborman SCPYN(wtmp.ut_line, line+5); 205738905Sborman SCPYN(wtmp.ut_name, ""); 205838905Sborman SCPYN(wtmp.ut_host, ""); 205938905Sborman (void) time(&wtmp.ut_time); 206038905Sborman (void) write(f, (char *)&wtmp, sizeof(wtmp)); 206138905Sborman (void) close(f); 206238905Sborman } 206338905Sborman } 206438905Sborman (void) chmod(line, 0666); 206538905Sborman (void) chown(line, 0, 0); 206638905Sborman line[strlen("/dev/")] = 'p'; 206738905Sborman (void) chmod(line, 0666); 206838905Sborman (void) chown(line, 0, 0); 206938905Sborman } /* end of rmut */ 207038905Sborman #endif /* CRAY */ 207160151Sdab 207260151Sdab #ifdef __hpux 207360151Sdab rmut (line) 207460151Sdab char *line; 207560151Sdab { 207660151Sdab struct utmp utmp; 207760151Sdab struct utmp *utptr; 207860151Sdab int fd; /* for /etc/wtmp */ 207960151Sdab 208060151Sdab utmp.ut_type = USER_PROCESS; 208160151Sdab (void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id)); 208260151Sdab (void) setutent(); 208360151Sdab utptr = getutid(&utmp); 208460151Sdab /* write it out only if it exists */ 208560151Sdab if (utptr) { 208660151Sdab utptr->ut_type = DEAD_PROCESS; 208760151Sdab utptr->ut_time = time((long *) 0); 208860151Sdab (void) pututline(utptr); 208960151Sdab /* set wtmp entry if wtmp file exists */ 209060151Sdab if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) { 209160151Sdab (void) write(fd, utptr, sizeof(utmp)); 209260151Sdab (void) close(fd); 209360151Sdab } 209460151Sdab } 209560151Sdab (void) endutent(); 209660151Sdab 209760151Sdab (void) chmod(line, 0666); 209860151Sdab (void) chown(line, 0, 0); 209960151Sdab line[14] = line[13]; 210060151Sdab line[13] = line[12]; 210160151Sdab line[8] = 'm'; 210260151Sdab line[9] = '/'; 210360151Sdab line[10] = 'p'; 210460151Sdab line[11] = 't'; 210560151Sdab line[12] = 'y'; 210660151Sdab (void) chmod(line, 0666); 210760151Sdab (void) chown(line, 0, 0); 210860151Sdab } 210960151Sdab #endif 2110