138905Sborman /* 2*61451Sbostic * Copyright (c) 1989, 1993 3*61451Sbostic * The Regents of the University of California. All rights reserved. 438905Sborman * 542673Sbostic * %sccs.include.redist.c% 638905Sborman */ 738905Sborman 838905Sborman #ifndef lint 9*61451Sbostic static char sccsid[] = "@(#)sys_term.c 8.1 (Berkeley) 06/04/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> 2957212Sdab # else 3057212Sdab # include <utmp.h> 3157212Sdab # endif /* UTMPX */ 3238905Sborman struct utmp wtmp; 3338905Sborman 3457212Sdab int utmp_len = sizeof(wtmp.ut_host); 3560151Sdab # ifndef PARENT_DOES_UTMP 3638905Sborman char wtmpf[] = "/usr/adm/wtmp"; 3738905Sborman char utmpf[] = "/etc/utmp"; 3860151Sdab # else /* PARENT_DOES_UTMP */ 3938905Sborman char wtmpf[] = "/etc/wtmp"; 4060151Sdab # endif /* PARENT_DOES_UTMP */ 4160151Sdab 4260151Sdab # ifdef CRAY 4346809Sdab #include <tmpdir.h> 4446809Sdab #include <sys/wait.h> 4560151Sdab # if defined(_SC_CRAY_SECURE_SYS) && !defined(SCM_SECURITY) 4660151Sdab /* 4760151Sdab * UNICOS 6.0/6.1 do not have SCM_SECURITY defined, so we can 4860151Sdab * use it to tell us to turn off all the socket security code, 4960151Sdab * since that is only used in UNICOS 7.0 and later. 5060151Sdab */ 5160151Sdab # undef _SC_CRAY_SECURE_SYS 5260151Sdab # endif 5360151Sdab 5457212Sdab # if defined(_SC_CRAY_SECURE_SYS) 5557212Sdab #include <sys/sysv.h> 5657212Sdab #include <sys/secstat.h> 5757212Sdab extern int secflag; 5857212Sdab extern struct sysv sysv; 5957212Sdab # endif /* _SC_CRAY_SECURE_SYS */ 6038905Sborman # endif /* CRAY */ 6138905Sborman #endif /* NEWINIT */ 6238905Sborman 6357212Sdab #ifdef STREAMSPTY 6457212Sdab #include <sac.h> 6557212Sdab #include <sys/stropts.h> 6657212Sdab #endif 6757212Sdab 6838905Sborman #define SCPYN(a, b) (void) strncpy(a, b, sizeof(a)) 6938905Sborman #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 7038905Sborman 7144364Sborman #ifdef STREAMS 7244364Sborman #include <sys/stream.h> 7344364Sborman #endif 7460151Sdab #ifdef __hpux 7560151Sdab #include <sys/resource.h> 7660151Sdab #include <sys/proc.h> 7760151Sdab #endif 7838905Sborman #include <sys/tty.h> 7938905Sborman #ifdef t_erase 8038905Sborman #undef t_erase 8138905Sborman #undef t_kill 8238905Sborman #undef t_intrc 8338905Sborman #undef t_quitc 8438905Sborman #undef t_startc 8538905Sborman #undef t_stopc 8638905Sborman #undef t_eofc 8738905Sborman #undef t_brkc 8838905Sborman #undef t_suspc 8938905Sborman #undef t_dsuspc 9038905Sborman #undef t_rprntc 9138905Sborman #undef t_flushc 9238905Sborman #undef t_werasc 9338905Sborman #undef t_lnextc 9438905Sborman #endif 9538905Sborman 9644364Sborman #if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC) 9744364Sborman # define EXTPROC 0400 9844364Sborman #endif 9944364Sborman 10038905Sborman #ifndef USE_TERMIO 10138905Sborman struct termbuf { 10238905Sborman struct sgttyb sg; 10338905Sborman struct tchars tc; 10438905Sborman struct ltchars ltc; 10538905Sborman int state; 10638905Sborman int lflags; 10738905Sborman } termbuf, termbuf2; 10845234Sborman # define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val) 10945234Sborman # define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val) 11046809Sdab # define cfgetospeed(tp) (tp)->sg.sg_ospeed 11146809Sdab # define cfgetispeed(tp) (tp)->sg.sg_ispeed 11238905Sborman #else /* USE_TERMIO */ 11338905Sborman # ifdef SYSV_TERMIO 11438905Sborman # define termios termio 11538905Sborman # endif 11645234Sborman # ifndef TCSANOW 11744364Sborman # ifdef TCSETS 11845234Sborman # define TCSANOW TCSETS 11945234Sborman # define TCSADRAIN TCSETSW 12046809Sdab # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) 12144364Sborman # else 12245234Sborman # ifdef TCSETA 12345234Sborman # define TCSANOW TCSETA 12445234Sborman # define TCSADRAIN TCSETAW 12546809Sdab # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) 12645234Sborman # else 12745234Sborman # define TCSANOW TIOCSETA 12845234Sborman # define TCSADRAIN TIOCSETAW 12946809Sdab # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) 13045234Sborman # endif 13144364Sborman # endif 13245234Sborman # define tcsetattr(f, a, t) ioctl(f, a, t) 13345234Sborman # define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 13445234Sborman (tp)->c_cflag |= (val) 13546809Sdab # define cfgetospeed(tp) ((tp)->c_cflag & CBAUD) 13645234Sborman # ifdef CIBAUD 13745234Sborman # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \ 13845234Sborman (tp)->c_cflag |= ((val)<<IBSHIFT) 13946809Sdab # define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT) 14045234Sborman # else 14145234Sborman # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 14245234Sborman (tp)->c_cflag |= (val) 14346809Sdab # define cfgetispeed(tp) ((tp)->c_cflag & CBAUD) 14445234Sborman # endif 14545234Sborman # endif /* TCSANOW */ 14638905Sborman struct termios termbuf, termbuf2; /* pty control structure */ 14757592Sdab # ifdef STREAMSPTY 14857212Sdab int ttyfd = -1; 14957592Sdab # endif 15038905Sborman #endif /* USE_TERMIO */ 15138905Sborman 15238905Sborman /* 15338905Sborman * init_termbuf() 15438905Sborman * copy_termbuf(cp) 15538905Sborman * set_termbuf() 15638905Sborman * 15738905Sborman * These three routines are used to get and set the "termbuf" structure 15838905Sborman * to and from the kernel. init_termbuf() gets the current settings. 15938905Sborman * copy_termbuf() hands in a new "termbuf" to write to the kernel, and 16038905Sborman * set_termbuf() writes the structure into the kernel. 16138905Sborman */ 16238905Sborman 16346809Sdab void 16438905Sborman init_termbuf() 16538905Sborman { 16638905Sborman #ifndef USE_TERMIO 16738905Sborman (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg); 16838905Sborman (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc); 16938905Sborman (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc); 17038905Sborman # ifdef TIOCGSTATE 17138905Sborman (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state); 17238905Sborman # endif 17338905Sborman #else 17457592Sdab # ifdef STREAMSPTY 17557212Sdab (void) tcgetattr(ttyfd, &termbuf); 17657592Sdab # else 17757592Sdab (void) tcgetattr(pty, &termbuf); 17857592Sdab # endif 17938905Sborman #endif 18038905Sborman termbuf2 = termbuf; 18138905Sborman } 18238905Sborman 18338905Sborman #if defined(LINEMODE) && defined(TIOCPKT_IOCTL) 18446809Sdab void 18538905Sborman copy_termbuf(cp, len) 18646809Sdab char *cp; 18746809Sdab int len; 18838905Sborman { 18938905Sborman if (len > sizeof(termbuf)) 19038905Sborman len = sizeof(termbuf); 19138905Sborman bcopy(cp, (char *)&termbuf, len); 19238905Sborman termbuf2 = termbuf; 19338905Sborman } 19438905Sborman #endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ 19538905Sborman 19646809Sdab void 19738905Sborman set_termbuf() 19838905Sborman { 19938905Sborman /* 20038905Sborman * Only make the necessary changes. 20138905Sborman */ 20238905Sborman #ifndef USE_TERMIO 20338905Sborman if (bcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg))) 20445234Sborman (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg); 20538905Sborman if (bcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc))) 20638905Sborman (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc); 20738905Sborman if (bcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc, 20838905Sborman sizeof(termbuf.ltc))) 20938905Sborman (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc); 21038905Sborman if (termbuf.lflags != termbuf2.lflags) 21138905Sborman (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags); 21238905Sborman #else /* USE_TERMIO */ 21338905Sborman if (bcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) 21457592Sdab # ifdef STREAMSPTY 21557212Sdab (void) tcsetattr(ttyfd, TCSANOW, &termbuf); 21657592Sdab # else 21757592Sdab (void) tcsetattr(pty, TCSANOW, &termbuf); 21857592Sdab # endif 21957212Sdab # if defined(CRAY2) && defined(UNICOS5) 22038905Sborman needtermstat = 1; 22138905Sborman # endif 22238905Sborman #endif /* USE_TERMIO */ 22338905Sborman } 22438905Sborman 22538905Sborman 22638905Sborman /* 22738905Sborman * spcset(func, valp, valpp) 22838905Sborman * 22938905Sborman * This function takes various special characters (func), and 23038905Sborman * sets *valp to the current value of that character, and 23138905Sborman * *valpp to point to where in the "termbuf" structure that 23238905Sborman * value is kept. 23338905Sborman * 23438905Sborman * It returns the SLC_ level of support for this function. 23538905Sborman */ 23638905Sborman 23738905Sborman #ifndef USE_TERMIO 23846809Sdab int 23938905Sborman spcset(func, valp, valpp) 24046809Sdab int func; 24146809Sdab cc_t *valp; 24246809Sdab cc_t **valpp; 24338905Sborman { 24438905Sborman switch(func) { 24538905Sborman case SLC_EOF: 24638905Sborman *valp = termbuf.tc.t_eofc; 24740242Sborman *valpp = (cc_t *)&termbuf.tc.t_eofc; 24838905Sborman return(SLC_VARIABLE); 24938905Sborman case SLC_EC: 25038905Sborman *valp = termbuf.sg.sg_erase; 25140242Sborman *valpp = (cc_t *)&termbuf.sg.sg_erase; 25238905Sborman return(SLC_VARIABLE); 25338905Sborman case SLC_EL: 25438905Sborman *valp = termbuf.sg.sg_kill; 25540242Sborman *valpp = (cc_t *)&termbuf.sg.sg_kill; 25638905Sborman return(SLC_VARIABLE); 25738905Sborman case SLC_IP: 25838905Sborman *valp = termbuf.tc.t_intrc; 25940242Sborman *valpp = (cc_t *)&termbuf.tc.t_intrc; 26038905Sborman return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 26138905Sborman case SLC_ABORT: 26238905Sborman *valp = termbuf.tc.t_quitc; 26340242Sborman *valpp = (cc_t *)&termbuf.tc.t_quitc; 26438905Sborman return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 26538905Sborman case SLC_XON: 26638905Sborman *valp = termbuf.tc.t_startc; 26740242Sborman *valpp = (cc_t *)&termbuf.tc.t_startc; 26838905Sborman return(SLC_VARIABLE); 26938905Sborman case SLC_XOFF: 27038905Sborman *valp = termbuf.tc.t_stopc; 27140242Sborman *valpp = (cc_t *)&termbuf.tc.t_stopc; 27238905Sborman return(SLC_VARIABLE); 27338905Sborman case SLC_AO: 27438905Sborman *valp = termbuf.ltc.t_flushc; 27540242Sborman *valpp = (cc_t *)&termbuf.ltc.t_flushc; 27638905Sborman return(SLC_VARIABLE); 27738905Sborman case SLC_SUSP: 27838905Sborman *valp = termbuf.ltc.t_suspc; 27940242Sborman *valpp = (cc_t *)&termbuf.ltc.t_suspc; 28038905Sborman return(SLC_VARIABLE); 28138905Sborman case SLC_EW: 28238905Sborman *valp = termbuf.ltc.t_werasc; 28340242Sborman *valpp = (cc_t *)&termbuf.ltc.t_werasc; 28438905Sborman return(SLC_VARIABLE); 28538905Sborman case SLC_RP: 28638905Sborman *valp = termbuf.ltc.t_rprntc; 28740242Sborman *valpp = (cc_t *)&termbuf.ltc.t_rprntc; 28838905Sborman return(SLC_VARIABLE); 28938905Sborman case SLC_LNEXT: 29038905Sborman *valp = termbuf.ltc.t_lnextc; 29140242Sborman *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 29238905Sborman return(SLC_VARIABLE); 29340242Sborman case SLC_FORW1: 29440242Sborman *valp = termbuf.tc.t_brkc; 29540242Sborman *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 29640242Sborman return(SLC_VARIABLE); 29738905Sborman case SLC_BRK: 29838905Sborman case SLC_SYNCH: 29938905Sborman case SLC_AYT: 30038905Sborman case SLC_EOR: 30140242Sborman *valp = (cc_t)0; 30240242Sborman *valpp = (cc_t *)0; 30338905Sborman return(SLC_DEFAULT); 30438905Sborman default: 30540242Sborman *valp = (cc_t)0; 30640242Sborman *valpp = (cc_t *)0; 30738905Sborman return(SLC_NOSUPPORT); 30838905Sborman } 30938905Sborman } 31038905Sborman 31138905Sborman #else /* USE_TERMIO */ 31238905Sborman 31346809Sdab int 31438905Sborman spcset(func, valp, valpp) 31546809Sdab int func; 31646809Sdab cc_t *valp; 31746809Sdab cc_t **valpp; 31838905Sborman { 31939503Sborman 32039503Sborman #define setval(a, b) *valp = termbuf.c_cc[a]; \ 32139503Sborman *valpp = &termbuf.c_cc[a]; \ 32239503Sborman return(b); 32340242Sborman #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); 32439503Sborman 32538905Sborman switch(func) { 32638905Sborman case SLC_EOF: 32739503Sborman setval(VEOF, SLC_VARIABLE); 32838905Sborman case SLC_EC: 32939503Sborman setval(VERASE, SLC_VARIABLE); 33038905Sborman case SLC_EL: 33139503Sborman setval(VKILL, SLC_VARIABLE); 33238905Sborman case SLC_IP: 33339503Sborman setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 33438905Sborman case SLC_ABORT: 33539503Sborman setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 33638905Sborman case SLC_XON: 33739503Sborman #ifdef VSTART 33839503Sborman setval(VSTART, SLC_VARIABLE); 33939503Sborman #else 34039503Sborman defval(0x13); 34139503Sborman #endif 34238905Sborman case SLC_XOFF: 34339503Sborman #ifdef VSTOP 34439503Sborman setval(VSTOP, SLC_VARIABLE); 34539503Sborman #else 34639503Sborman defval(0x11); 34739503Sborman #endif 34838905Sborman case SLC_EW: 34939503Sborman #ifdef VWERASE 35039503Sborman setval(VWERASE, SLC_VARIABLE); 35139503Sborman #else 35239503Sborman defval(0); 35339503Sborman #endif 35438905Sborman case SLC_RP: 35539503Sborman #ifdef VREPRINT 35639503Sborman setval(VREPRINT, SLC_VARIABLE); 35739503Sborman #else 35839503Sborman defval(0); 35939503Sborman #endif 36038905Sborman case SLC_LNEXT: 36139503Sborman #ifdef VLNEXT 36239503Sborman setval(VLNEXT, SLC_VARIABLE); 36339503Sborman #else 36439503Sborman defval(0); 36539503Sborman #endif 36639503Sborman case SLC_AO: 36745234Sborman #if !defined(VDISCARD) && defined(VFLUSHO) 36845234Sborman # define VDISCARD VFLUSHO 36945234Sborman #endif 37045234Sborman #ifdef VDISCARD 37145234Sborman setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); 37239503Sborman #else 37339503Sborman defval(0); 37439503Sborman #endif 37539503Sborman case SLC_SUSP: 37639503Sborman #ifdef VSUSP 37739503Sborman setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); 37839503Sborman #else 37939503Sborman defval(0); 38039503Sborman #endif 38140242Sborman #ifdef VEOL 38240242Sborman case SLC_FORW1: 38340242Sborman setval(VEOL, SLC_VARIABLE); 38440242Sborman #endif 38540242Sborman #ifdef VEOL2 38640242Sborman case SLC_FORW2: 38740242Sborman setval(VEOL2, SLC_VARIABLE); 38840242Sborman #endif 38945234Sborman case SLC_AYT: 39045234Sborman #ifdef VSTATUS 39145234Sborman setval(VSTATUS, SLC_VARIABLE); 39245234Sborman #else 39345234Sborman defval(0); 39445234Sborman #endif 39539503Sborman 39638905Sborman case SLC_BRK: 39738905Sborman case SLC_SYNCH: 39838905Sborman case SLC_EOR: 39939503Sborman defval(0); 40039503Sborman 40138905Sborman default: 40238905Sborman *valp = 0; 40338905Sborman *valpp = 0; 40438905Sborman return(SLC_NOSUPPORT); 40538905Sborman } 40638905Sborman } 40738905Sborman #endif /* USE_TERMIO */ 40838905Sborman 40940242Sborman #ifdef CRAY 41038905Sborman /* 41140242Sborman * getnpty() 41240242Sborman * 41340242Sborman * Return the number of pty's configured into the system. 41440242Sborman */ 41546809Sdab int 41640242Sborman getnpty() 41740242Sborman { 41840242Sborman #ifdef _SC_CRAY_NPTY 41946809Sdab int numptys; 42046809Sdab 42146809Sdab if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) 42246809Sdab return numptys; 42346809Sdab else 42440242Sborman #endif /* _SC_CRAY_NPTY */ 42546809Sdab return 128; 42640242Sborman } 42740242Sborman #endif /* CRAY */ 42840242Sborman 42945234Sborman #ifndef convex 43040242Sborman /* 43138905Sborman * getpty() 43238905Sborman * 43338905Sborman * Allocate a pty. As a side effect, the external character 43438905Sborman * array "line" contains the name of the slave side. 43538905Sborman * 43638905Sborman * Returns the file descriptor of the opened pty. 43738905Sborman */ 43845234Sborman #ifndef __GNUC__ 43938905Sborman char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 44045234Sborman #else 44145234Sborman static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 44245234Sborman char *line = Xline; 44345234Sborman #endif 44445234Sborman #ifdef CRAY 44545234Sborman char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 44645234Sborman #endif /* CRAY */ 44738905Sborman 44846809Sdab int 44960151Sdab getpty(ptynum) 45060151Sdab int *ptynum; 45138905Sborman { 45238905Sborman register int p; 45357212Sdab #ifdef STREAMSPTY 45457212Sdab int t; 45557212Sdab char *ptsname(); 45657212Sdab 45757212Sdab p = open("/dev/ptmx", 2); 45857212Sdab if (p > 0) { 45957212Sdab grantpt(p); 46057212Sdab unlockpt(p); 46157212Sdab strcpy(line, ptsname(p)); 46257212Sdab return(p); 46357212Sdab } 46457212Sdab 46557212Sdab #else /* ! STREAMSPTY */ 46638905Sborman #ifndef CRAY 46757212Sdab register char *cp, *p1, *p2; 46838905Sborman register int i; 46959050Storek #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207 47057212Sdab int dummy; 47157212Sdab #endif 47238905Sborman 47360151Sdab #ifndef __hpux 47438905Sborman (void) sprintf(line, "/dev/ptyXX"); 47538905Sborman p1 = &line[8]; 47638905Sborman p2 = &line[9]; 47760151Sdab #else 47860151Sdab (void) sprintf(line, "/dev/ptym/ptyXX"); 47960151Sdab p1 = &line[13]; 48060151Sdab p2 = &line[14]; 48160151Sdab #endif 48238905Sborman 48357212Sdab for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) { 48438905Sborman struct stat stb; 48538905Sborman 48657212Sdab *p1 = *cp; 48738905Sborman *p2 = '0'; 48857212Sdab /* 48957212Sdab * This stat() check is just to keep us from 49057212Sdab * looping through all 256 combinations if there 49157212Sdab * aren't that many ptys available. 49257212Sdab */ 49338905Sborman if (stat(line, &stb) < 0) 49438905Sborman break; 49538905Sborman for (i = 0; i < 16; i++) { 49638905Sborman *p2 = "0123456789abcdef"[i]; 49738905Sborman p = open(line, 2); 49838905Sborman if (p > 0) { 49960151Sdab #ifndef __hpux 50038905Sborman line[5] = 't'; 50160151Sdab #else 50260151Sdab for (p1 = &line[8]; *p1; p1++) 50360151Sdab *p1 = *(p1+1); 50460151Sdab line[9] = 't'; 50560151Sdab #endif 50657212Sdab chown(line, 0, 0); 50757212Sdab chmod(line, 0600); 50859050Storek #if defined(sun) && defined(TIOCGPGRP) && BSD < 199207 50957212Sdab if (ioctl(p, TIOCGPGRP, &dummy) == 0 51057212Sdab || errno != EIO) { 51157212Sdab chmod(line, 0666); 51257212Sdab close(p); 51357212Sdab line[5] = 'p'; 51457212Sdab } else 51559050Storek #endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */ 51657212Sdab return(p); 51738905Sborman } 51838905Sborman } 51938905Sborman } 52038905Sborman #else /* CRAY */ 52138905Sborman extern lowpty, highpty; 52245234Sborman struct stat sb; 52338905Sborman 52460151Sdab for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) { 52560151Sdab (void) sprintf(myline, "/dev/pty/%03d", *ptynum); 52645234Sborman p = open(myline, 2); 52738905Sborman if (p < 0) 52838905Sborman continue; 52960151Sdab (void) sprintf(line, "/dev/ttyp%03d", *ptynum); 53045234Sborman /* 53145234Sborman * Here are some shenanigans to make sure that there 53245234Sborman * are no listeners lurking on the line. 53345234Sborman */ 53445234Sborman if(stat(line, &sb) < 0) { 53545234Sborman (void) close(p); 53645234Sborman continue; 53745234Sborman } 53845234Sborman if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { 53945234Sborman chown(line, 0, 0); 54045234Sborman chmod(line, 0600); 54145234Sborman (void)close(p); 54245234Sborman p = open(myline, 2); 54345234Sborman if (p < 0) 54445234Sborman continue; 54545234Sborman } 54645234Sborman /* 54745234Sborman * Now it should be safe...check for accessability. 54845234Sborman */ 54938905Sborman if (access(line, 6) == 0) 55038905Sborman return(p); 55138905Sborman else { 55238905Sborman /* no tty side to pty so skip it */ 55338905Sborman (void) close(p); 55438905Sborman } 55538905Sborman } 55638905Sborman #endif /* CRAY */ 55757212Sdab #endif /* STREAMSPTY */ 55838905Sborman return(-1); 55938905Sborman } 56045234Sborman #endif /* convex */ 56138905Sborman 56238905Sborman #ifdef LINEMODE 56338905Sborman /* 56438905Sborman * tty_flowmode() Find out if flow control is enabled or disabled. 56538905Sborman * tty_linemode() Find out if linemode (external processing) is enabled. 56638905Sborman * tty_setlinemod(on) Turn on/off linemode. 56738905Sborman * tty_isecho() Find out if echoing is turned on. 56838905Sborman * tty_setecho(on) Enable/disable character echoing. 56938905Sborman * tty_israw() Find out if terminal is in RAW mode. 57038905Sborman * tty_binaryin(on) Turn on/off BINARY on input. 57138905Sborman * tty_binaryout(on) Turn on/off BINARY on output. 57238905Sborman * tty_isediting() Find out if line editing is enabled. 57338905Sborman * tty_istrapsig() Find out if signal trapping is enabled. 57438905Sborman * tty_setedit(on) Turn on/off line editing. 57538905Sborman * tty_setsig(on) Turn on/off signal trapping. 57644364Sborman * tty_issofttab() Find out if tab expansion is enabled. 57744364Sborman * tty_setsofttab(on) Turn on/off soft tab expansion. 57844364Sborman * tty_islitecho() Find out if typed control chars are echoed literally 57944364Sborman * tty_setlitecho() Turn on/off literal echo of control chars 58038905Sborman * tty_tspeed(val) Set transmit speed to val. 58138905Sborman * tty_rspeed(val) Set receive speed to val. 58238905Sborman */ 58338905Sborman 58445234Sborman #ifdef convex 58545234Sborman static int linestate; 58645234Sborman #endif 58745234Sborman 58846809Sdab int 58938905Sborman tty_linemode() 59038905Sborman { 59145234Sborman #ifndef convex 59238905Sborman #ifndef USE_TERMIO 59338905Sborman return(termbuf.state & TS_EXTPROC); 59438905Sborman #else 59538905Sborman return(termbuf.c_lflag & EXTPROC); 59638905Sborman #endif 59745234Sborman #else 59845234Sborman return(linestate); 59945234Sborman #endif 60038905Sborman } 60138905Sborman 60246809Sdab void 60338905Sborman tty_setlinemode(on) 60446809Sdab int on; 60538905Sborman { 60638905Sborman #ifdef TIOCEXT 60745234Sborman # ifndef convex 60845234Sborman set_termbuf(); 60945234Sborman # else 61045234Sborman linestate = on; 61145234Sborman # endif 61238905Sborman (void) ioctl(pty, TIOCEXT, (char *)&on); 61345234Sborman # ifndef convex 61445234Sborman init_termbuf(); 61545234Sborman # endif 61638905Sborman #else /* !TIOCEXT */ 61745234Sborman # ifdef EXTPROC 61838905Sborman if (on) 61938905Sborman termbuf.c_lflag |= EXTPROC; 62038905Sborman else 62138905Sborman termbuf.c_lflag &= ~EXTPROC; 62245234Sborman # endif 62338905Sborman #endif /* TIOCEXT */ 62438905Sborman } 62538905Sborman 62646809Sdab int 62738905Sborman tty_isecho() 62838905Sborman { 62938905Sborman #ifndef USE_TERMIO 63038905Sborman return (termbuf.sg.sg_flags & ECHO); 63138905Sborman #else 63238905Sborman return (termbuf.c_lflag & ECHO); 63338905Sborman #endif 63438905Sborman } 63538905Sborman #endif /* LINEMODE */ 63638905Sborman 63758971Sdab int 63858971Sdab tty_flowmode() 63958971Sdab { 64058971Sdab #ifndef USE_TERMIO 64158971Sdab return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0); 64258971Sdab #else 64358971Sdab return((termbuf.c_iflag & IXON) ? 1 : 0); 64458971Sdab #endif 64558971Sdab } 64658971Sdab 64758971Sdab int 64858971Sdab tty_restartany() 64958971Sdab { 65058971Sdab #ifndef USE_TERMIO 65158971Sdab # ifdef DECCTQ 65258971Sdab return((termbuf.lflags & DECCTQ) ? 0 : 1); 65358971Sdab # else 65458971Sdab return(-1); 65558971Sdab # endif 65658971Sdab #else 65758971Sdab return((termbuf.c_iflag & IXANY) ? 1 : 0); 65858971Sdab #endif 65958971Sdab } 66058971Sdab 66146809Sdab void 66238905Sborman tty_setecho(on) 66346809Sdab int on; 66438905Sborman { 66538905Sborman #ifndef USE_TERMIO 66638905Sborman if (on) 66738905Sborman termbuf.sg.sg_flags |= ECHO|CRMOD; 66838905Sborman else 66938905Sborman termbuf.sg.sg_flags &= ~(ECHO|CRMOD); 67038905Sborman #else 67138905Sborman if (on) 67238905Sborman termbuf.c_lflag |= ECHO; 67338905Sborman else 67438905Sborman termbuf.c_lflag &= ~ECHO; 67538905Sborman #endif 67638905Sborman } 67738905Sborman 67838905Sborman #if defined(LINEMODE) && defined(KLUDGELINEMODE) 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 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 68938905Sborman 69046809Sdab void 69138905Sborman tty_binaryin(on) 69246809Sdab int on; 69338905Sborman { 69438905Sborman #ifndef USE_TERMIO 69538905Sborman if (on) 69638905Sborman termbuf.lflags |= LPASS8; 69738905Sborman else 69838905Sborman termbuf.lflags &= ~LPASS8; 69938905Sborman #else 70038905Sborman if (on) { 70146809Sdab termbuf.c_iflag &= ~ISTRIP; 70238905Sborman } else { 70346809Sdab termbuf.c_iflag |= ISTRIP; 70438905Sborman } 70538905Sborman #endif 70638905Sborman } 70738905Sborman 70846809Sdab void 70938905Sborman tty_binaryout(on) 71046809Sdab int on; 71138905Sborman { 71238905Sborman #ifndef USE_TERMIO 71338905Sborman if (on) 71438905Sborman termbuf.lflags |= LLITOUT; 71538905Sborman else 71638905Sborman termbuf.lflags &= ~LLITOUT; 71738905Sborman #else 71838905Sborman if (on) { 71938905Sborman termbuf.c_cflag &= ~(CSIZE|PARENB); 72038905Sborman termbuf.c_cflag |= CS8; 72138905Sborman termbuf.c_oflag &= ~OPOST; 72238905Sborman } else { 72338905Sborman termbuf.c_cflag &= ~CSIZE; 72438905Sborman termbuf.c_cflag |= CS7|PARENB; 72538905Sborman termbuf.c_oflag |= OPOST; 72638905Sborman } 72738905Sborman #endif 72838905Sborman } 72938905Sborman 73046809Sdab int 73138905Sborman tty_isbinaryin() 73238905Sborman { 73338905Sborman #ifndef USE_TERMIO 73438905Sborman return(termbuf.lflags & LPASS8); 73538905Sborman #else 73639503Sborman return(!(termbuf.c_iflag & ISTRIP)); 73738905Sborman #endif 73838905Sborman } 73938905Sborman 74046809Sdab int 74138905Sborman tty_isbinaryout() 74238905Sborman { 74338905Sborman #ifndef USE_TERMIO 74438905Sborman return(termbuf.lflags & LLITOUT); 74538905Sborman #else 74639503Sborman return(!(termbuf.c_oflag&OPOST)); 74738905Sborman #endif 74838905Sborman } 74938905Sborman 75038905Sborman #ifdef LINEMODE 75146809Sdab int 75238905Sborman tty_isediting() 75338905Sborman { 75438905Sborman #ifndef USE_TERMIO 75538905Sborman return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); 75638905Sborman #else 75738905Sborman return(termbuf.c_lflag & ICANON); 75838905Sborman #endif 75938905Sborman } 76038905Sborman 76146809Sdab int 76238905Sborman tty_istrapsig() 76338905Sborman { 76438905Sborman #ifndef USE_TERMIO 76538905Sborman return(!(termbuf.sg.sg_flags&RAW)); 76638905Sborman #else 76738905Sborman return(termbuf.c_lflag & ISIG); 76838905Sborman #endif 76938905Sborman } 77038905Sborman 77146809Sdab void 77238905Sborman tty_setedit(on) 77346809Sdab int on; 77438905Sborman { 77538905Sborman #ifndef USE_TERMIO 77638905Sborman if (on) 77738905Sborman termbuf.sg.sg_flags &= ~CBREAK; 77838905Sborman else 77938905Sborman termbuf.sg.sg_flags |= CBREAK; 78038905Sborman #else 78138905Sborman if (on) 78238905Sborman termbuf.c_lflag |= ICANON; 78338905Sborman else 78438905Sborman termbuf.c_lflag &= ~ICANON; 78538905Sborman #endif 78638905Sborman } 78738905Sborman 78846809Sdab void 78938905Sborman tty_setsig(on) 79046809Sdab int on; 79138905Sborman { 79238905Sborman #ifndef USE_TERMIO 79338905Sborman if (on) 79438905Sborman ; 79538905Sborman #else 79638905Sborman if (on) 79738905Sborman termbuf.c_lflag |= ISIG; 79838905Sborman else 79938905Sborman termbuf.c_lflag &= ~ISIG; 80038905Sborman #endif 80138905Sborman } 80238905Sborman #endif /* LINEMODE */ 80338905Sborman 80446809Sdab int 80544364Sborman tty_issofttab() 80644364Sborman { 80744364Sborman #ifndef USE_TERMIO 80844364Sborman return (termbuf.sg.sg_flags & XTABS); 80944364Sborman #else 81044364Sborman # ifdef OXTABS 81144364Sborman return (termbuf.c_oflag & OXTABS); 81244364Sborman # endif 81344364Sborman # ifdef TABDLY 81444364Sborman return ((termbuf.c_oflag & TABDLY) == TAB3); 81544364Sborman # endif 81644364Sborman #endif 81744364Sborman } 81844364Sborman 81946809Sdab void 82044364Sborman tty_setsofttab(on) 82146809Sdab int on; 82244364Sborman { 82344364Sborman #ifndef USE_TERMIO 82444364Sborman if (on) 82544364Sborman termbuf.sg.sg_flags |= XTABS; 82644364Sborman else 82744364Sborman termbuf.sg.sg_flags &= ~XTABS; 82844364Sborman #else 82944364Sborman if (on) { 83044364Sborman # ifdef OXTABS 83144364Sborman termbuf.c_oflag |= OXTABS; 83244364Sborman # endif 83344364Sborman # ifdef TABDLY 83444364Sborman termbuf.c_oflag &= ~TABDLY; 83544364Sborman termbuf.c_oflag |= TAB3; 83644364Sborman # endif 83744364Sborman } else { 83844364Sborman # ifdef OXTABS 83944364Sborman termbuf.c_oflag &= ~OXTABS; 84044364Sborman # endif 84144364Sborman # ifdef TABDLY 84244364Sborman termbuf.c_oflag &= ~TABDLY; 84344364Sborman termbuf.c_oflag |= TAB0; 84444364Sborman # endif 84544364Sborman } 84644364Sborman #endif 84744364Sborman } 84844364Sborman 84946809Sdab int 85044364Sborman tty_islitecho() 85144364Sborman { 85244364Sborman #ifndef USE_TERMIO 85346809Sdab return (!(termbuf.lflags & LCTLECH)); 85444364Sborman #else 85544364Sborman # ifdef ECHOCTL 85644364Sborman return (!(termbuf.c_lflag & ECHOCTL)); 85744364Sborman # endif 85844364Sborman # ifdef TCTLECH 85944364Sborman return (!(termbuf.c_lflag & TCTLECH)); 86044364Sborman # endif 86144364Sborman # if !defined(ECHOCTL) && !defined(TCTLECH) 86244364Sborman return (0); /* assumes ctl chars are echoed '^x' */ 86344364Sborman # endif 86444364Sborman #endif 86544364Sborman } 86644364Sborman 86746809Sdab void 86844364Sborman tty_setlitecho(on) 86946809Sdab int on; 87044364Sborman { 87144364Sborman #ifndef USE_TERMIO 87244364Sborman if (on) 87346809Sdab termbuf.lflags &= ~LCTLECH; 87444364Sborman else 87546809Sdab termbuf.lflags |= LCTLECH; 87644364Sborman #else 87744364Sborman # ifdef ECHOCTL 87844364Sborman if (on) 87944364Sborman termbuf.c_lflag &= ~ECHOCTL; 88044364Sborman else 88144364Sborman termbuf.c_lflag |= ECHOCTL; 88244364Sborman # endif 88344364Sborman # ifdef TCTLECH 88444364Sborman if (on) 88544364Sborman termbuf.c_lflag &= ~TCTLECH; 88644364Sborman else 88744364Sborman termbuf.c_lflag |= TCTLECH; 88844364Sborman # endif 88944364Sborman #endif 89044364Sborman } 89144364Sborman 89246809Sdab int 89346809Sdab tty_iscrnl() 89446809Sdab { 89546809Sdab #ifndef USE_TERMIO 89646809Sdab return (termbuf.sg.sg_flags & CRMOD); 89746809Sdab #else 89846809Sdab return (termbuf.c_iflag & ICRNL); 89946809Sdab #endif 90046809Sdab } 90146809Sdab 90238905Sborman /* 90338905Sborman * A table of available terminal speeds 90438905Sborman */ 90538905Sborman struct termspeeds { 90638905Sborman int speed; 90738905Sborman int value; 90838905Sborman } termspeeds[] = { 90938905Sborman { 0, B0 }, { 50, B50 }, { 75, B75 }, 91038905Sborman { 110, B110 }, { 134, B134 }, { 150, B150 }, 91138905Sborman { 200, B200 }, { 300, B300 }, { 600, B600 }, 91238905Sborman { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 91338905Sborman { 4800, B4800 }, { 9600, B9600 }, { 19200, B9600 }, 91438905Sborman { 38400, B9600 }, { -1, B9600 } 91538905Sborman }; 91638905Sborman 91746809Sdab void 91838905Sborman tty_tspeed(val) 91946809Sdab int val; 92038905Sborman { 92138905Sborman register struct termspeeds *tp; 92238905Sborman 92338905Sborman for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 92438905Sborman ; 92545234Sborman cfsetospeed(&termbuf, tp->value); 92638905Sborman } 92738905Sborman 92846809Sdab void 92938905Sborman tty_rspeed(val) 93046809Sdab int val; 93138905Sborman { 93238905Sborman register struct termspeeds *tp; 93338905Sborman 93438905Sborman for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 93538905Sborman ; 93645234Sborman cfsetispeed(&termbuf, tp->value); 93738905Sborman } 93838905Sborman 93940242Sborman #if defined(CRAY2) && defined(UNICOS5) 94046809Sdab int 94138905Sborman tty_isnewmap() 94238905Sborman { 94338905Sborman return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) && 94438905Sborman !(termbuf.c_oflag & ONLRET)); 94538905Sborman } 94638905Sborman #endif 94738905Sborman 94860151Sdab #ifdef PARENT_DOES_UTMP 94938905Sborman # ifndef NEWINIT 95038905Sborman extern struct utmp wtmp; 95138905Sborman extern char wtmpf[]; 95238905Sborman # else /* NEWINIT */ 95338905Sborman int gotalarm; 95446809Sdab 95546809Sdab /* ARGSUSED */ 95646809Sdab void 95740242Sborman nologinproc(sig) 95846809Sdab int sig; 95938905Sborman { 96038905Sborman gotalarm++; 96138905Sborman } 96238905Sborman # endif /* NEWINIT */ 96360151Sdab #endif /* PARENT_DOES_UTMP */ 96438905Sborman 96546809Sdab #ifndef NEWINIT 96660151Sdab # ifdef PARENT_DOES_UTMP 96746809Sdab extern void utmp_sig_init P((void)); 96846809Sdab extern void utmp_sig_reset P((void)); 96946809Sdab extern void utmp_sig_wait P((void)); 97046809Sdab extern void utmp_sig_notify P((int)); 97160151Sdab # endif /* PARENT_DOES_UTMP */ 97246809Sdab #endif 97346809Sdab 97438905Sborman /* 97538905Sborman * getptyslave() 97638905Sborman * 97738905Sborman * Open the slave side of the pty, and do any initialization 97838905Sborman * that is necessary. The return value is a file descriptor 97938905Sborman * for the slave side. 98038905Sborman */ 98146809Sdab int 98238905Sborman getptyslave() 98338905Sborman { 98438905Sborman register int t = -1; 98538905Sborman 98645234Sborman #if !defined(CRAY) || !defined(NEWINIT) 98745234Sborman # ifdef LINEMODE 98846809Sdab int waslm; 98946809Sdab # endif 99046809Sdab # ifdef TIOCGWINSZ 99146809Sdab struct winsize ws; 99246809Sdab extern int def_row, def_col; 99346809Sdab # endif 99446809Sdab extern int def_tspeed, def_rspeed; 99538905Sborman /* 99645234Sborman * Opening the slave side may cause initilization of the 99746809Sdab * kernel tty structure. We need remember the state of 99846809Sdab * if linemode was turned on 99946809Sdab * terminal window size 100046809Sdab * terminal speed 100146809Sdab * so that we can re-set them if we need to. 100238905Sborman */ 100346809Sdab # ifdef LINEMODE 100446809Sdab waslm = tty_linemode(); 100545234Sborman # endif 100645234Sborman 100745234Sborman 100845234Sborman /* 100945234Sborman * Make sure that we don't have a controlling tty, and 101045234Sborman * that we are the session (process group) leader. 101145234Sborman */ 101245234Sborman # ifdef TIOCNOTTY 101338905Sborman t = open(_PATH_TTY, O_RDWR); 101438905Sborman if (t >= 0) { 101538905Sborman (void) ioctl(t, TIOCNOTTY, (char *)0); 101638905Sborman (void) close(t); 101738905Sborman } 101845234Sborman # endif 101938905Sborman 102045234Sborman 102160151Sdab # ifdef PARENT_DOES_UTMP 102245234Sborman /* 102345234Sborman * Wait for our parent to get the utmp stuff to get done. 102445234Sborman */ 102545234Sborman utmp_sig_wait(); 102645234Sborman # endif 102745234Sborman 102845234Sborman t = cleanopen(line); 102938905Sborman if (t < 0) 103038905Sborman fatalperror(net, line); 103138905Sborman 103257592Sdab #ifdef STREAMSPTY 103357212Sdab #ifdef USE_TERMIO 103457212Sdab ttyfd = t; 103557212Sdab #endif 103657212Sdab if (ioctl(t, I_PUSH, "ptem") < 0) 103757212Sdab fatal(net, "I_PUSH ptem"); 103857212Sdab if (ioctl(t, I_PUSH, "ldterm") < 0) 103957212Sdab fatal(net, "I_PUSH ldterm"); 104057212Sdab if (ioctl(t, I_PUSH, "ttcompat") < 0) 104157212Sdab fatal(net, "I_PUSH ttcompat"); 104257212Sdab if (ioctl(pty, I_PUSH, "pckt") < 0) 104357212Sdab fatal(net, "I_PUSH pckt"); 104457212Sdab #endif 104557212Sdab 104645234Sborman /* 104745234Sborman * set up the tty modes as we like them to be. 104845234Sborman */ 104938905Sborman init_termbuf(); 105046809Sdab # ifdef TIOCGWINSZ 105146809Sdab if (def_row || def_col) { 105246809Sdab bzero((char *)&ws, sizeof(ws)); 105346809Sdab ws.ws_col = def_col; 105446809Sdab ws.ws_row = def_row; 105546809Sdab (void)ioctl(t, TIOCSWINSZ, (char *)&ws); 105646809Sdab } 105746809Sdab # endif 105845234Sborman 105945234Sborman /* 106045234Sborman * Settings for sgtty based systems 106145234Sborman */ 106245234Sborman # ifndef USE_TERMIO 106340242Sborman termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; 106445234Sborman # endif /* USE_TERMIO */ 106545234Sborman 106645234Sborman /* 106760151Sdab * Settings for UNICOS (and HPUX) 106845234Sborman */ 106960151Sdab # if defined(CRAY) || defined(__hpux) 107045234Sborman termbuf.c_oflag = OPOST|ONLCR|TAB3; 107145234Sborman termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; 107245234Sborman termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; 107345234Sborman termbuf.c_cflag = EXTB|HUPCL|CS8; 107445234Sborman # endif 107545234Sborman 107645234Sborman /* 107745234Sborman * Settings for all other termios/termio based 107845234Sborman * systems, other than 4.4BSD. In 4.4BSD the 107945234Sborman * kernel does the initial terminal setup. 108045234Sborman */ 108160151Sdab # if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) 108245234Sborman # ifndef OXTABS 108345234Sborman # define OXTABS 0 108445234Sborman # endif 108538905Sborman termbuf.c_lflag |= ECHO; 108638905Sborman termbuf.c_oflag |= ONLCR|OXTABS; 108738905Sborman termbuf.c_iflag |= ICRNL; 108838905Sborman termbuf.c_iflag &= ~IXOFF; 108945234Sborman # endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */ 109046996Sdab tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); 109146996Sdab tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); 109246809Sdab # ifdef LINEMODE 109346809Sdab if (waslm) 109446809Sdab tty_setlinemode(1); 109546809Sdab # endif /* LINEMODE */ 109645234Sborman 109745234Sborman /* 109845234Sborman * Set the tty modes, and make this our controlling tty. 109945234Sborman */ 110045234Sborman set_termbuf(); 110145234Sborman if (login_tty(t) == -1) 110245234Sborman fatalperror(net, "login_tty"); 110345234Sborman #endif /* !defined(CRAY) || !defined(NEWINIT) */ 110445234Sborman if (net > 2) 110545234Sborman (void) close(net); 110645234Sborman if (pty > 2) 110745234Sborman (void) close(pty); 110845234Sborman } 110945234Sborman 111045234Sborman #if !defined(CRAY) || !defined(NEWINIT) 111145234Sborman #ifndef O_NOCTTY 111245234Sborman #define O_NOCTTY 0 111338905Sborman #endif 111445234Sborman /* 111545234Sborman * Open the specified slave side of the pty, 111645234Sborman * making sure that we have a clean tty. 111745234Sborman */ 111846809Sdab int 111945234Sborman cleanopen(line) 112046809Sdab char *line; 112145234Sborman { 112245234Sborman register int t; 112357212Sdab #if defined(_SC_CRAY_SECURE_SYS) 112457212Sdab struct secstat secbuf; 112557212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 112645234Sborman 112757212Sdab #ifndef STREAMSPTY 112845234Sborman /* 112945234Sborman * Make sure that other people can't open the 113045234Sborman * slave side of the connection. 113145234Sborman */ 113238905Sborman (void) chown(line, 0, 0); 113338905Sborman (void) chmod(line, 0600); 113457212Sdab #endif 113545234Sborman 113645234Sborman # if !defined(CRAY) && (BSD > 43) 113745234Sborman (void) revoke(line); 113845234Sborman # endif 113957212Sdab #if defined(_SC_CRAY_SECURE_SYS) 114057212Sdab if (secflag) { 114157212Sdab if (secstat(line, &secbuf) < 0) 114257212Sdab return(-1); 114357212Sdab if (setulvl(secbuf.st_slevel) < 0) 114457212Sdab return(-1); 114557212Sdab if (setucmp(secbuf.st_compart) < 0) 114657212Sdab return(-1); 114757212Sdab } 114857212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 114957212Sdab 115045234Sborman t = open(line, O_RDWR|O_NOCTTY); 115157212Sdab 115257212Sdab #if defined(_SC_CRAY_SECURE_SYS) 115357212Sdab if (secflag) { 115457212Sdab if (setulvl(sysv.sy_minlvl) < 0) 115557212Sdab return(-1); 115657212Sdab if (setucmp(0) < 0) 115757212Sdab return(-1); 115857212Sdab } 115957212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 116057212Sdab 116145234Sborman if (t < 0) 116245234Sborman return(-1); 116345234Sborman 116445234Sborman /* 116545234Sborman * Hangup anybody else using this ttyp, then reopen it for 116645234Sborman * ourselves. 116745234Sborman */ 116860151Sdab # if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY) 116945234Sborman (void) signal(SIGHUP, SIG_IGN); 117045234Sborman vhangup(); 117145234Sborman (void) signal(SIGHUP, SIG_DFL); 117245234Sborman t = open(line, O_RDWR|O_NOCTTY); 117345234Sborman if (t < 0) 117445234Sborman return(-1); 117545234Sborman # endif 117645234Sborman # if defined(CRAY) && defined(TCVHUP) 117745234Sborman { 117845234Sborman register int i; 117945234Sborman (void) signal(SIGHUP, SIG_IGN); 118045234Sborman (void) ioctl(t, TCVHUP, (char *)0); 118145234Sborman (void) signal(SIGHUP, SIG_DFL); 118245234Sborman setpgrp(); 118357212Sdab 118457212Sdab #if defined(_SC_CRAY_SECURE_SYS) 118557212Sdab if (secflag) { 118657212Sdab if (secstat(line, &secbuf) < 0) 118757212Sdab return(-1); 118857212Sdab if (setulvl(secbuf.st_slevel) < 0) 118957212Sdab return(-1); 119057212Sdab if (setucmp(secbuf.st_compart) < 0) 119157212Sdab return(-1); 119257212Sdab } 119357212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 119457212Sdab 119545234Sborman i = open(line, O_RDWR); 119657212Sdab 119757212Sdab #if defined(_SC_CRAY_SECURE_SYS) 119857212Sdab if (secflag) { 119957212Sdab if (setulvl(sysv.sy_minlvl) < 0) 120057212Sdab return(-1); 120157212Sdab if (setucmp(0) < 0) 120257212Sdab return(-1); 120357212Sdab } 120457212Sdab #endif /* _SC_CRAY_SECURE_SYS */ 120557212Sdab 120645234Sborman if (i < 0) 120746809Sdab return(-1); 120845234Sborman (void) close(t); 120945234Sborman t = i; 121045234Sborman } 121145234Sborman # endif /* defined(CRAY) && defined(TCVHUP) */ 121238905Sborman return(t); 121338905Sborman } 121445234Sborman #endif /* !defined(CRAY) || !defined(NEWINIT) */ 121538905Sborman 121645234Sborman #if BSD <= 43 121746809Sdab int 121845234Sborman login_tty(t) 121946809Sdab int t; 122045234Sborman { 122145234Sborman if (setsid() < 0) 122245234Sborman fatalperror(net, "setsid()"); 122345234Sborman # ifdef TIOCSCTTY 122445234Sborman if (ioctl(t, TIOCSCTTY, (char *)0) < 0) 122545234Sborman fatalperror(net, "ioctl(sctty)"); 122657212Sdab # if defined(CRAY) 122747613Sdab /* 122847613Sdab * Close the hard fd to /dev/ttypXXX, and re-open through 122947613Sdab * the indirect /dev/tty interface. 123047613Sdab */ 123147613Sdab close(t); 123247613Sdab if ((t = open("/dev/tty", O_RDWR)) < 0) 123347613Sdab fatalperror(net, "open(/dev/tty)"); 123447613Sdab # endif 123545234Sborman # else 123645234Sborman close(open(line, O_RDWR)); 123745234Sborman # endif 123847613Sdab if (t != 0) 123947613Sdab (void) dup2(t, 0); 124047613Sdab if (t != 1) 124147613Sdab (void) dup2(t, 1); 124247613Sdab if (t != 2) 124347613Sdab (void) dup2(t, 2); 124447613Sdab if (t > 2) 124547613Sdab close(t); 124646809Sdab return(0); 124745234Sborman } 124845234Sborman #endif /* BSD <= 43 */ 124945234Sborman 125038905Sborman #ifdef NEWINIT 125138905Sborman char *gen_id = "fe"; 125238905Sborman #endif 125338905Sborman 125438905Sborman /* 125545234Sborman * startslave(host) 125638905Sborman * 125745234Sborman * Given a hostname, do whatever 125838905Sborman * is necessary to startup the login process on the slave side of the pty. 125938905Sborman */ 126038905Sborman 126138905Sborman /* ARGSUSED */ 126246809Sdab void 126346809Sdab startslave(host, autologin, autoname) 126446809Sdab char *host; 126546809Sdab int autologin; 126646809Sdab char *autoname; 126738905Sborman { 126838905Sborman register int i; 126938905Sborman long time(); 127046809Sdab char name[256]; 127146809Sdab #ifdef NEWINIT 127246809Sdab extern char *ptyip; 127346809Sdab struct init_request request; 127446809Sdab void nologinproc(); 127546809Sdab register int n; 127646809Sdab #endif /* NEWINIT */ 127738905Sborman 127857212Sdab #if defined(AUTHENTICATION) 127946809Sdab if (!autoname || !autoname[0]) 128046809Sdab autologin = 0; 128146809Sdab 128246809Sdab if (autologin < auth_level) { 128346809Sdab fatal(net, "Authorization failed"); 128446809Sdab exit(1); 128546809Sdab } 128646809Sdab #endif 128746809Sdab 128838905Sborman #ifndef NEWINIT 128960151Sdab # ifdef PARENT_DOES_UTMP 129038905Sborman utmp_sig_init(); 129160151Sdab # endif /* PARENT_DOES_UTMP */ 129238905Sborman 129338905Sborman if ((i = fork()) < 0) 129438905Sborman fatalperror(net, "fork"); 129538905Sborman if (i) { 129660151Sdab # ifdef PARENT_DOES_UTMP 129738905Sborman /* 129838905Sborman * Cray parent will create utmp entry for child and send 129938905Sborman * signal to child to tell when done. Child waits for signal 130038905Sborman * before doing anything important. 130138905Sborman */ 130238905Sborman register int pid = i; 130346809Sdab void sigjob P((int)); 130438905Sborman 130538905Sborman setpgrp(); 130644364Sborman utmp_sig_reset(); /* reset handler to default */ 130738905Sborman /* 130838905Sborman * Create utmp entry for child 130938905Sborman */ 131038905Sborman (void) time(&wtmp.ut_time); 131138905Sborman wtmp.ut_type = LOGIN_PROCESS; 131238905Sborman wtmp.ut_pid = pid; 131338905Sborman SCPYN(wtmp.ut_user, "LOGIN"); 131438905Sborman SCPYN(wtmp.ut_host, host); 131538905Sborman SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); 131660151Sdab #ifndef __hpux 131738905Sborman SCPYN(wtmp.ut_id, wtmp.ut_line+3); 131860151Sdab #else 131960151Sdab SCPYN(wtmp.ut_id, wtmp.ut_line+7); 132060151Sdab #endif 132138905Sborman pututline(&wtmp); 132238905Sborman endutent(); 132338905Sborman if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { 132438905Sborman (void) write(i, (char *)&wtmp, sizeof(struct utmp)); 132538905Sborman (void) close(i); 132638905Sborman } 132760151Sdab #ifdef CRAY 132846809Sdab (void) signal(WJSIGNAL, sigjob); 132960151Sdab #endif 133038905Sborman utmp_sig_notify(pid); 133160151Sdab # endif /* PARENT_DOES_UTMP */ 133238905Sborman } else { 133345234Sborman getptyslave(); 133446809Sdab start_login(host, autologin, autoname); 133538905Sborman /*NOTREACHED*/ 133638905Sborman } 133738905Sborman #else /* NEWINIT */ 133838905Sborman 133938905Sborman /* 134038905Sborman * Init will start up login process if we ask nicely. We only wait 134138905Sborman * for it to start up and begin normal telnet operation. 134238905Sborman */ 134338905Sborman if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { 134438905Sborman char tbuf[128]; 134538905Sborman (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO); 134638905Sborman fatalperror(net, tbuf); 134738905Sborman } 134838905Sborman memset((char *)&request, 0, sizeof(request)); 134938905Sborman request.magic = INIT_MAGIC; 135038905Sborman SCPYN(request.gen_id, gen_id); 135138905Sborman SCPYN(request.tty_id, &line[8]); 135238905Sborman SCPYN(request.host, host); 135346809Sdab SCPYN(request.term_type, terminaltype ? terminaltype : "network"); 135444364Sborman #if !defined(UNICOS5) 135540242Sborman request.signal = SIGCLD; 135640242Sborman request.pid = getpid(); 135740242Sborman #endif 135844364Sborman #ifdef BFTPDAEMON 135944364Sborman /* 136044364Sborman * Are we working as the bftp daemon? 136144364Sborman */ 136244364Sborman if (bftpd) { 136344364Sborman SCPYN(request.exec_name, BFTPPATH); 136444364Sborman } 136544364Sborman #endif /* BFTPDAEMON */ 136638905Sborman if (write(i, (char *)&request, sizeof(request)) < 0) { 136738905Sborman char tbuf[128]; 136838905Sborman (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO); 136938905Sborman fatalperror(net, tbuf); 137038905Sborman } 137138905Sborman (void) close(i); 137238905Sborman (void) signal(SIGALRM, nologinproc); 137338905Sborman for (i = 0; ; i++) { 137440242Sborman char tbuf[128]; 137538905Sborman alarm(15); 137638905Sborman n = read(pty, ptyip, BUFSIZ); 137738905Sborman if (i == 3 || n >= 0 || !gotalarm) 137838905Sborman break; 137938905Sborman gotalarm = 0; 138040242Sborman sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line); 138140242Sborman (void) write(net, tbuf, strlen(tbuf)); 138238905Sborman } 138338905Sborman if (n < 0 && gotalarm) 138438905Sborman fatal(net, "/etc/init didn't start login process"); 138538905Sborman pcc += n; 138638905Sborman alarm(0); 138738905Sborman (void) signal(SIGALRM, SIG_DFL); 138838905Sborman 138938905Sborman return; 139038905Sborman #endif /* NEWINIT */ 139138905Sborman } 139238905Sborman 139338905Sborman char *envinit[3]; 139444364Sborman extern char **environ; 139538905Sborman 139646809Sdab void 139744364Sborman init_env() 139844364Sborman { 139944364Sborman extern char *getenv(); 140044364Sborman char **envp; 140144364Sborman 140244364Sborman envp = envinit; 140344364Sborman if (*envp = getenv("TZ")) 140444364Sborman *envp++ -= 3; 140560151Sdab #if defined(CRAY) || defined(__hpux) 140644364Sborman else 140744364Sborman *envp++ = "TZ=GMT0"; 140844364Sborman #endif 140944364Sborman *envp = 0; 141044364Sborman environ = envinit; 141144364Sborman } 141244364Sborman 141344364Sborman #ifndef NEWINIT 141444364Sborman 141544364Sborman /* 141645234Sborman * start_login(host) 141738905Sborman * 141838905Sborman * Assuming that we are now running as a child processes, this 141938905Sborman * function will turn us into the login process. 142038905Sborman */ 142138905Sborman 142246809Sdab void 142346809Sdab start_login(host, autologin, name) 142446809Sdab char *host; 142546809Sdab int autologin; 142646809Sdab char *name; 142738905Sborman { 142844364Sborman register char *cp; 142944364Sborman register char **argv; 143044364Sborman char **addarg(); 143157212Sdab #ifdef UTMPX 143257212Sdab register int pid = getpid(); 143357212Sdab struct utmpx utmpx; 143457212Sdab #endif 143557212Sdab #ifdef __svr4__ 143657212Sdab char *term; 143757212Sdab char termbuf[64]; 143857212Sdab #endif 143938905Sborman 144057212Sdab #ifdef UTMPX 144138905Sborman /* 144257212Sdab * Create utmp entry for child 144357212Sdab */ 144457212Sdab 144557212Sdab bzero(&utmpx, sizeof(utmpx)); 144657212Sdab SCPYN(utmpx.ut_user, ".telnet"); 144757212Sdab SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); 144857212Sdab utmpx.ut_pid = pid; 144957212Sdab utmpx.ut_id[0] = 't'; 145057212Sdab utmpx.ut_id[1] = 'n'; 145157212Sdab utmpx.ut_id[2] = SC_WILDC; 145257212Sdab utmpx.ut_id[3] = SC_WILDC; 145357212Sdab utmpx.ut_type = LOGIN_PROCESS; 145457212Sdab (void) time(&utmpx.ut_tv.tv_sec); 145557212Sdab if (makeutx(&utmpx) == NULL) 145657212Sdab fatal(net, "makeutx failed"); 145757212Sdab #endif 145857212Sdab 145957212Sdab /* 146038905Sborman * -h : pass on name of host. 146138905Sborman * WARNING: -h is accepted by login if and only if 146238905Sborman * getuid() == 0. 146338905Sborman * -p : don't clobber the environment (so terminal type stays set). 146446809Sdab * 146546809Sdab * -f : force this login, he has already been authenticated 146638905Sborman */ 146744364Sborman argv = addarg(0, "login"); 146860151Sdab #if !defined(NO_LOGIN_H) 146944364Sborman argv = addarg(argv, "-h"); 147044364Sborman argv = addarg(argv, host); 147160151Sdab #endif 147257212Sdab #ifdef __svr4__ 147357212Sdab /* 147457212Sdab * SVR4 version of -h takes TERM= as second arg, or - 147557212Sdab */ 147657212Sdab term = getenv("TERM"); 147757212Sdab if (term == NULL || term[0] == 0) { 147857212Sdab term = "-"; 147957212Sdab } else { 148057212Sdab strcpy(termbuf, "TERM="); 148157212Sdab strncat(termbuf, term, sizeof(termbuf) - 6); 148257212Sdab term = termbuf; 148357212Sdab } 148457212Sdab argv = addarg(argv, term); 148557212Sdab #endif 148646809Sdab #if !defined(NO_LOGIN_P) 148744364Sborman argv = addarg(argv, "-p"); 148838905Sborman #endif 148944364Sborman #ifdef BFTPDAEMON 149044364Sborman /* 149144364Sborman * Are we working as the bftp daemon? If so, then ask login 149244364Sborman * to start bftp instead of shell. 149344364Sborman */ 149444364Sborman if (bftpd) { 149544364Sborman argv = addarg(argv, "-e"); 149644364Sborman argv = addarg(argv, BFTPPATH); 149744364Sborman } else 149844364Sborman #endif 149946809Sdab #if defined (SecurID) 150046809Sdab /* 150146809Sdab * don't worry about the -f that might get sent. 150246809Sdab * A -s is supposed to override it anyhow. 150346809Sdab */ 150446809Sdab if (require_SecurID) 150546809Sdab argv = addarg(argv, "-s"); 150646809Sdab #endif 150757212Sdab #if defined (AUTHENTICATION) 150846809Sdab if (auth_level >= 0 && autologin == AUTH_VALID) { 150946809Sdab # if !defined(NO_LOGIN_F) 151046809Sdab argv = addarg(argv, "-f"); 151146809Sdab # endif 151246809Sdab argv = addarg(argv, name); 151346809Sdab } else 151446809Sdab #endif 151544364Sborman if (getenv("USER")) { 151644364Sborman argv = addarg(argv, getenv("USER")); 151760151Sdab #if (defined(CRAY) || defined(__hpux)) && defined(NO_LOGIN_P) 151846809Sdab { 151946809Sdab register char **cpp; 152046809Sdab for (cpp = environ; *cpp; cpp++) 152146809Sdab argv = addarg(argv, *cpp); 152246809Sdab } 152346809Sdab #endif 152457212Sdab /* 152557212Sdab * Assume that login will set the USER variable 152657212Sdab * correctly. For SysV systems, this means that 152757212Sdab * USER will no longer be set, just LOGNAME by 152857212Sdab * login. (The problem is that if the auto-login 152957212Sdab * fails, and the user then specifies a different 153057212Sdab * account name, he can get logged in with both 153157212Sdab * LOGNAME and USER in his environment, but the 153257212Sdab * USER value will be wrong. 153357212Sdab */ 153457212Sdab unsetenv("USER"); 153544364Sborman } 153646809Sdab closelog(); 153744364Sborman execv(_PATH_LOGIN, argv); 153844364Sborman 153938905Sborman syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN); 154038905Sborman fatalperror(net, _PATH_LOGIN); 154138905Sborman /*NOTREACHED*/ 154238905Sborman } 154344364Sborman 154446809Sdab char ** 154544364Sborman addarg(argv, val) 154646809Sdab register char **argv; 154746809Sdab register char *val; 154844364Sborman { 154944364Sborman register char **cpp; 155044364Sborman 155144364Sborman if (argv == NULL) { 155244364Sborman /* 155344364Sborman * 10 entries, a leading length, and a null 155444364Sborman */ 155544364Sborman argv = (char **)malloc(sizeof(*argv) * 12); 155644364Sborman if (argv == NULL) 155744364Sborman return(NULL); 155844364Sborman *argv++ = (char *)10; 155944364Sborman *argv = (char *)0; 156044364Sborman } 156144364Sborman for (cpp = argv; *cpp; cpp++) 156244364Sborman ; 156344364Sborman if (cpp == &argv[(int)argv[-1]]) { 156444364Sborman --argv; 156544364Sborman *argv = (char *)((int)(*argv) + 10); 156644364Sborman argv = (char **)realloc(argv, (int)(*argv) + 2); 156744364Sborman if (argv == NULL) 156844364Sborman return(NULL); 156944364Sborman argv++; 157044364Sborman cpp = &argv[(int)argv[-1] - 10]; 157144364Sborman } 157244364Sborman *cpp++ = val; 157344364Sborman *cpp = 0; 157444364Sborman return(argv); 157544364Sborman } 157646809Sdab #endif /* NEWINIT */ 157738905Sborman 157838905Sborman /* 157938905Sborman * cleanup() 158038905Sborman * 158138905Sborman * This is the routine to call when we are all through, to 158238905Sborman * clean up anything that needs to be cleaned up. 158338905Sborman */ 158446809Sdab /* ARGSUSED */ 158546809Sdab void 158646809Sdab cleanup(sig) 158746809Sdab int sig; 158838905Sborman { 158960151Sdab #ifndef PARENT_DOES_UTMP 159045234Sborman # if (BSD > 43) || defined(convex) 159138905Sborman char *p; 159238905Sborman 159338905Sborman p = line + sizeof("/dev/") - 1; 159438905Sborman if (logout(p)) 159538905Sborman logwtmp(p, "", ""); 159638905Sborman (void)chmod(line, 0666); 159738905Sborman (void)chown(line, 0, 0); 159838905Sborman *p = 'p'; 159938905Sborman (void)chmod(line, 0666); 160038905Sborman (void)chown(line, 0, 0); 160146809Sdab (void) shutdown(net, 2); 160246809Sdab exit(1); 160338905Sborman # else 160446809Sdab void rmut(); 160546809Sdab 160638905Sborman rmut(); 160738905Sborman vhangup(); /* XXX */ 160846809Sdab (void) shutdown(net, 2); 160946809Sdab exit(1); 161038905Sborman # endif 161160151Sdab #else /* PARENT_DOES_UTMP */ 161246809Sdab # ifdef NEWINIT 161338905Sborman (void) shutdown(net, 2); 161446809Sdab exit(1); 161538905Sborman # else /* NEWINIT */ 161660151Sdab # ifdef CRAY 161746809Sdab static int incleanup = 0; 161846809Sdab register int t; 161946809Sdab 162046809Sdab /* 162146809Sdab * 1: Pick up the zombie, if we are being called 162246809Sdab * as the signal handler. 162346809Sdab * 2: If we are a nested cleanup(), return. 162446809Sdab * 3: Try to clean up TMPDIR. 162546809Sdab * 4: Fill in utmp with shutdown of process. 162646809Sdab * 5: Close down the network and pty connections. 162746809Sdab * 6: Finish up the TMPDIR cleanup, if needed. 162846809Sdab */ 162946809Sdab if (sig == SIGCHLD) 163046809Sdab while (waitpid(-1, 0, WNOHANG) > 0) 163146809Sdab ; /* VOID */ 163246809Sdab t = sigblock(sigmask(SIGCHLD)); 163346809Sdab if (incleanup) { 163446809Sdab sigsetmask(t); 163546809Sdab return; 163646809Sdab } 163746809Sdab incleanup = 1; 163846809Sdab sigsetmask(t); 163960151Sdab if (secflag) { 164060151Sdab /* 164160151Sdab * We need to set ourselves back to a null 164260151Sdab * label to clean up. 164360151Sdab */ 164446809Sdab 164560151Sdab setulvl(sysv.sy_minlvl); 164660151Sdab setucmp((long)0); 164760151Sdab } 164860151Sdab 164946809Sdab t = cleantmp(&wtmp); 165046809Sdab setutent(); /* just to make sure */ 165160151Sdab # endif /* CRAY */ 165246809Sdab rmut(line); 165346809Sdab close(pty); 165438905Sborman (void) shutdown(net, 2); 165560151Sdab # ifdef CRAY 165646809Sdab if (t == 0) 165746809Sdab cleantmp(&wtmp); 165860151Sdab # endif /* CRAY */ 165946809Sdab exit(1); 166038905Sborman # endif /* NEWINT */ 166160151Sdab #endif /* PARENT_DOES_UTMP */ 166238905Sborman } 166338905Sborman 166460151Sdab #if defined(PARENT_DOES_UTMP) && !defined(NEWINIT) 166538905Sborman /* 166638905Sborman * _utmp_sig_rcv 166738905Sborman * utmp_sig_init 166838905Sborman * utmp_sig_wait 166938905Sborman * These three functions are used to coordinate the handling of 167038905Sborman * the utmp file between the server and the soon-to-be-login shell. 167138905Sborman * The server actually creates the utmp structure, the child calls 167238905Sborman * utmp_sig_wait(), until the server calls utmp_sig_notify() and 167338905Sborman * signals the future-login shell to proceed. 167438905Sborman */ 167538905Sborman static int caught=0; /* NZ when signal intercepted */ 167638905Sborman static void (*func)(); /* address of previous handler */ 167738905Sborman 167846809Sdab void 167938905Sborman _utmp_sig_rcv(sig) 168046809Sdab int sig; 168138905Sborman { 168238905Sborman caught = 1; 168338905Sborman (void) signal(SIGUSR1, func); 168438905Sborman } 168538905Sborman 168646809Sdab void 168738905Sborman utmp_sig_init() 168838905Sborman { 168938905Sborman /* 169038905Sborman * register signal handler for UTMP creation 169138905Sborman */ 169238905Sborman if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) 169338905Sborman fatalperror(net, "telnetd/signal"); 169438905Sborman } 169538905Sborman 169646809Sdab void 169744364Sborman utmp_sig_reset() 169844364Sborman { 169944364Sborman (void) signal(SIGUSR1, func); /* reset handler to default */ 170044364Sborman } 170144364Sborman 170260151Sdab # ifdef __hpux 170360151Sdab # define sigoff() /* do nothing */ 170460151Sdab # define sigon() /* do nothing */ 170560151Sdab # endif 170660151Sdab 170746809Sdab void 170838905Sborman utmp_sig_wait() 170938905Sborman { 171038905Sborman /* 171138905Sborman * Wait for parent to write our utmp entry. 171238905Sborman */ 171338905Sborman sigoff(); 171438905Sborman while (caught == 0) { 171538905Sborman pause(); /* wait until we get a signal (sigon) */ 171638905Sborman sigoff(); /* turn off signals while we check caught */ 171738905Sborman } 171838905Sborman sigon(); /* turn on signals again */ 171938905Sborman } 172038905Sborman 172146809Sdab void 172238905Sborman utmp_sig_notify(pid) 172338905Sborman { 172438905Sborman kill(pid, SIGUSR1); 172538905Sborman } 172646809Sdab 172760151Sdab # ifdef CRAY 172846809Sdab static int gotsigjob = 0; 172946809Sdab 173046809Sdab /*ARGSUSED*/ 173146809Sdab void 173246809Sdab sigjob(sig) 173346809Sdab int sig; 173446809Sdab { 173546809Sdab register int jid; 173646809Sdab register struct jobtemp *jp; 173746809Sdab 173846809Sdab while ((jid = waitjob(NULL)) != -1) { 173946809Sdab if (jid == 0) { 174046809Sdab return; 174146809Sdab } 174246809Sdab gotsigjob++; 174346809Sdab jobend(jid, NULL, NULL); 174446809Sdab } 174546809Sdab } 174646809Sdab 174746809Sdab /* 174846809Sdab * Clean up the TMPDIR that login created. 174946809Sdab * The first time this is called we pick up the info 175046809Sdab * from the utmp. If the job has already gone away, 175146809Sdab * then we'll clean up and be done. If not, then 175246809Sdab * when this is called the second time it will wait 175346809Sdab * for the signal that the job is done. 175446809Sdab */ 175546809Sdab int 175646809Sdab cleantmp(wtp) 175746809Sdab register struct utmp *wtp; 175846809Sdab { 175946809Sdab struct utmp *utp; 176046809Sdab static int first = 1; 176146809Sdab register int mask, omask, ret; 176246809Sdab extern struct utmp *getutid P((struct utmp *)); 176346809Sdab 176446809Sdab mask = sigmask(WJSIGNAL); 176546809Sdab 176646809Sdab if (first == 0) { 176746809Sdab omask = sigblock(mask); 176846809Sdab while (gotsigjob == 0) 176946809Sdab sigpause(omask); 177046809Sdab return(1); 177146809Sdab } 177246809Sdab first = 0; 177346809Sdab setutent(); /* just to make sure */ 177446809Sdab 177546809Sdab utp = getutid(wtp); 177646809Sdab if (utp == 0) { 177746809Sdab syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); 177846809Sdab return(-1); 177946809Sdab } 178046809Sdab /* 178146809Sdab * Nothing to clean up if the user shell was never started. 178246809Sdab */ 178346809Sdab if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) 178446809Sdab return(1); 178546809Sdab 178646809Sdab /* 178746809Sdab * Block the WJSIGNAL while we are in jobend(). 178846809Sdab */ 178946809Sdab omask = sigblock(mask); 179046809Sdab ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); 179146809Sdab sigsetmask(omask); 179246809Sdab return(ret); 179346809Sdab } 179446809Sdab 179546809Sdab int 179646809Sdab jobend(jid, path, user) 179746809Sdab register int jid; 179846809Sdab register char *path; 179946809Sdab register char *user; 180046809Sdab { 180146809Sdab static int saved_jid = 0; 180246809Sdab static char saved_path[sizeof(wtmp.ut_tpath)+1]; 180346809Sdab static char saved_user[sizeof(wtmp.ut_user)+1]; 180446809Sdab 180546809Sdab if (path) { 180646809Sdab strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); 180746809Sdab strncpy(saved_user, user, sizeof(wtmp.ut_user)); 180846809Sdab saved_path[sizeof(saved_path)] = '\0'; 180946809Sdab saved_user[sizeof(saved_user)] = '\0'; 181046809Sdab } 181146809Sdab if (saved_jid == 0) { 181246809Sdab saved_jid = jid; 181346809Sdab return(0); 181446809Sdab } 181546809Sdab cleantmpdir(jid, saved_path, saved_user); 181646809Sdab return(1); 181746809Sdab } 181846809Sdab 181946809Sdab /* 182046809Sdab * Fork a child process to clean up the TMPDIR 182146809Sdab */ 182246809Sdab cleantmpdir(jid, tpath, user) 182346809Sdab register int jid; 182446809Sdab register char *tpath; 182546809Sdab register char *user; 182646809Sdab { 182746809Sdab switch(fork()) { 182846809Sdab case -1: 182946809Sdab syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n", 183046809Sdab tpath); 183146809Sdab break; 183246809Sdab case 0: 183346809Sdab execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); 183446809Sdab syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", 183546809Sdab tpath, CLEANTMPCMD); 183646809Sdab exit(1); 183746809Sdab default: 183846809Sdab /* 183946809Sdab * Forget about child. We will exit, and 184046809Sdab * /etc/init will pick it up. 184146809Sdab */ 184246809Sdab break; 184346809Sdab } 184446809Sdab } 184560151Sdab # endif /* CRAY */ 184660151Sdab #endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */ 184738905Sborman 184838905Sborman /* 184938905Sborman * rmut() 185038905Sborman * 185138905Sborman * This is the function called by cleanup() to 185238905Sborman * remove the utmp entry for this person. 185338905Sborman */ 185438905Sborman 185557212Sdab #ifdef UTMPX 185657212Sdab rmut() 185757212Sdab { 185857212Sdab register f; 185957212Sdab int found = 0; 186057212Sdab struct utmp *u, *utmp; 186157212Sdab int nutmp; 186257212Sdab struct stat statbf; 186357212Sdab 186457212Sdab struct utmpx *utxp, utmpx; 186557212Sdab 186657212Sdab /* 186757212Sdab * This updates the utmpx and utmp entries and make a wtmp/x entry 186857212Sdab */ 186957212Sdab 187057212Sdab SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); 187157212Sdab utxp = getutxline(&utmpx); 187257212Sdab if (utxp) { 187357212Sdab utxp->ut_type = DEAD_PROCESS; 187457212Sdab utxp->ut_exit.e_termination = 0; 187557212Sdab utxp->ut_exit.e_exit = 0; 187657212Sdab (void) time(&utmpx.ut_tv.tv_sec); 187757212Sdab utmpx.ut_tv.tv_usec = 0; 187857212Sdab modutx(utxp); 187957212Sdab } 188057212Sdab endutxent(); 188157212Sdab } /* end of rmut */ 188257212Sdab #endif 188357212Sdab 188460151Sdab #if !defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43 188546809Sdab void 188638905Sborman rmut() 188738905Sborman { 188838905Sborman register f; 188938905Sborman int found = 0; 189038905Sborman struct utmp *u, *utmp; 189138905Sborman int nutmp; 189238905Sborman struct stat statbf; 189338905Sborman 189438905Sborman f = open(utmpf, O_RDWR); 189538905Sborman if (f >= 0) { 189638905Sborman (void) fstat(f, &statbf); 189738905Sborman utmp = (struct utmp *)malloc((unsigned)statbf.st_size); 189838905Sborman if (!utmp) 189938905Sborman syslog(LOG_ERR, "utmp malloc failed"); 190038905Sborman if (statbf.st_size && utmp) { 190138905Sborman nutmp = read(f, (char *)utmp, (int)statbf.st_size); 190238905Sborman nutmp /= sizeof(struct utmp); 190338905Sborman 190438905Sborman for (u = utmp ; u < &utmp[nutmp] ; u++) { 190538905Sborman if (SCMPN(u->ut_line, line+5) || 190638905Sborman u->ut_name[0]==0) 190738905Sborman continue; 190838905Sborman (void) lseek(f, ((long)u)-((long)utmp), L_SET); 190938905Sborman SCPYN(u->ut_name, ""); 191038905Sborman SCPYN(u->ut_host, ""); 191138905Sborman (void) time(&u->ut_time); 191238905Sborman (void) write(f, (char *)u, sizeof(wtmp)); 191338905Sborman found++; 191438905Sborman } 191538905Sborman } 191638905Sborman (void) close(f); 191738905Sborman } 191838905Sborman if (found) { 191938905Sborman f = open(wtmpf, O_WRONLY|O_APPEND); 192038905Sborman if (f >= 0) { 192138905Sborman SCPYN(wtmp.ut_line, line+5); 192238905Sborman SCPYN(wtmp.ut_name, ""); 192338905Sborman SCPYN(wtmp.ut_host, ""); 192438905Sborman (void) time(&wtmp.ut_time); 192538905Sborman (void) write(f, (char *)&wtmp, sizeof(wtmp)); 192638905Sborman (void) close(f); 192738905Sborman } 192838905Sborman } 192938905Sborman (void) chmod(line, 0666); 193038905Sborman (void) chown(line, 0, 0); 193138905Sborman line[strlen("/dev/")] = 'p'; 193238905Sborman (void) chmod(line, 0666); 193338905Sborman (void) chown(line, 0, 0); 193438905Sborman } /* end of rmut */ 193538905Sborman #endif /* CRAY */ 193660151Sdab 193760151Sdab #ifdef __hpux 193860151Sdab rmut (line) 193960151Sdab char *line; 194060151Sdab { 194160151Sdab struct utmp utmp; 194260151Sdab struct utmp *utptr; 194360151Sdab int fd; /* for /etc/wtmp */ 194460151Sdab 194560151Sdab utmp.ut_type = USER_PROCESS; 194660151Sdab (void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id)); 194760151Sdab (void) setutent(); 194860151Sdab utptr = getutid(&utmp); 194960151Sdab /* write it out only if it exists */ 195060151Sdab if (utptr) { 195160151Sdab utptr->ut_type = DEAD_PROCESS; 195260151Sdab utptr->ut_time = time((long *) 0); 195360151Sdab (void) pututline(utptr); 195460151Sdab /* set wtmp entry if wtmp file exists */ 195560151Sdab if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) { 195660151Sdab (void) write(fd, utptr, sizeof(utmp)); 195760151Sdab (void) close(fd); 195860151Sdab } 195960151Sdab } 196060151Sdab (void) endutent(); 196160151Sdab 196260151Sdab (void) chmod(line, 0666); 196360151Sdab (void) chown(line, 0, 0); 196460151Sdab line[14] = line[13]; 196560151Sdab line[13] = line[12]; 196660151Sdab line[8] = 'm'; 196760151Sdab line[9] = '/'; 196860151Sdab line[10] = 'p'; 196960151Sdab line[11] = 't'; 197060151Sdab line[12] = 'y'; 197160151Sdab (void) chmod(line, 0666); 197260151Sdab (void) chown(line, 0, 0); 197360151Sdab } 197460151Sdab #endif 1975