diff options
Diffstat (limited to 'libexec/telnetd/sys_term.c')
-rw-r--r-- | libexec/telnetd/sys_term.c | 3080 |
1 files changed, 1323 insertions, 1757 deletions
diff --git a/libexec/telnetd/sys_term.c b/libexec/telnetd/sys_term.c index 5cee73127ac..8ffc44e25a5 100644 --- a/libexec/telnetd/sys_term.c +++ b/libexec/telnetd/sys_term.c @@ -1,6 +1,3 @@ -/* $OpenBSD: sys_term.c,v 1.23 2001/06/11 15:18:52 mickey Exp $ */ -/* $NetBSD: sys_term.c,v 1.9 1996/03/20 04:25:53 tls Exp $ */ - /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. @@ -34,82 +31,89 @@ * SUCH DAMAGE. */ -#ifndef lint -#if 0 -static char sccsid[] = "@(#)sys_term.c 8.4+1 (Berkeley) 5/30/95"; -static char rcsid[] = "$NetBSD: sys_term.c,v 1.8 1996/02/28 20:38:21 thorpej Exp $"; -#else -static char rcsid[] = "$OpenBSD: sys_term.c,v 1.23 2001/06/11 15:18:52 mickey Exp $"; -#endif -#endif /* not lint */ - #include "telnetd.h" -#include "pathnames.h" -#include <util.h> -#include <sys/cdefs.h> -#define P __P +/* RCSID("$KTH: sys_term.c,v 1.100 2001/04/24 23:11:43 assar Exp $"); */ -#if defined(AUTHENTICATION) -#include <libtelnet/auth.h> +#if defined(_CRAY) || (defined(__hpux) && !defined(HAVE_UTMPX_H)) +# define PARENT_DOES_UTMP #endif -#if defined(CRAY) || defined(__hpux) -# define PARENT_DOES_UTMP +#ifdef HAVE_UTMP_H +#include <utmp.h> #endif -#ifdef NEWINIT -#include <initreq.h> -int utmp_len = MAXHOSTNAMELEN; /* sizeof(init_request.host) */ -#else /* NEWINIT*/ -# ifdef UTMPX -# include <utmpx.h> +#ifdef HAVE_UTMPX_H +#include <utmpx.h> +#endif + +#ifdef HAVE_UTMPX_H struct utmpx wtmp; -# else -# include <utmp.h> +#elif defined(HAVE_UTMP_H) struct utmp wtmp; -# endif /* UTMPX */ +#endif /* HAVE_UTMPX_H */ +#ifdef HAVE_STRUCT_UTMP_UT_HOST int utmp_len = sizeof(wtmp.ut_host); -# ifndef PARENT_DOES_UTMP +#else +int utmp_len = MAXHOSTNAMELEN; +#endif + +#ifndef UTMP_FILE +#ifdef _PATH_UTMP +#define UTMP_FILE _PATH_UTMP +#else +#define UTMP_FILE "/etc/utmp" +#endif +#endif + +#if !defined(WTMP_FILE) && defined(_PATH_WTMP) +#define WTMP_FILE _PATH_WTMP +#endif + +#ifndef PARENT_DOES_UTMP +#ifdef WTMP_FILE +char wtmpf[] = WTMP_FILE; +#else char wtmpf[] = "/usr/adm/wtmp"; -char utmpf[] = "/etc/utmp"; -# else /* PARENT_DOES_UTMP */ +#endif +char utmpf[] = UTMP_FILE; +#else /* PARENT_DOES_UTMP */ +#ifdef WTMP_FILE +char wtmpf[] = WTMP_FILE; +#else char wtmpf[] = "/etc/wtmp"; -# endif /* PARENT_DOES_UTMP */ +#endif +#endif /* PARENT_DOES_UTMP */ -# ifdef CRAY +#ifdef HAVE_TMPDIR_H #include <tmpdir.h> -#include <sys/wait.h> -# if (UNICOS_LVL == '7.0') || (UNICOS_LVL == '7.1') -# define UNICOS7x -# endif - -# ifdef UNICOS7x -#include <sys/sysv.h> -#include <sys/secstat.h> -extern int secflag; -extern struct sysv sysv; -# endif /* UNICOS7x */ -# endif /* CRAY */ -#endif /* NEWINIT */ +#endif /* CRAY */ #ifdef STREAMSPTY + +#ifdef HAVE_SAC_H #include <sac.h> +#endif + +#ifdef HAVE_SYS_STROPTS_H #include <sys/stropts.h> #endif -#define SCPYN(a, b) (void) strncpy(a, b, sizeof(a)) -#define SCMPN(a, b) strncmp(a, b, sizeof(a)) +#endif /* STREAMSPTY */ -#ifdef STREAMS -#include <sys/stream.h> +#ifdef HAVE_SYS_STREAM_H +#ifdef HAVE_SYS_UIO_H +#include <sys/uio.h> #endif #ifdef __hpux -#include <sys/resource.h> -#include <sys/proc.h> +#undef SE #endif +#include <sys/stream.h> +#endif +#if !(defined(__sgi) || defined(__linux) || defined(_AIX)) && defined(HAVE_SYS_TTY) #include <sys/tty.h> +#endif #ifdef t_erase #undef t_erase #undef t_kill @@ -127,26 +131,18 @@ extern struct sysv sysv; #undef t_lnextc #endif -#if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC) -# define EXTPROC 0400 -#endif - -#ifndef USE_TERMIO -struct termbuf { - struct sgttyb sg; - struct tchars tc; - struct ltchars ltc; - int state; - int lflags; -} termbuf, termbuf2; -# define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val) -# define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val) -# define cfgetospeed(tp) (tp)->sg.sg_ospeed -# define cfgetispeed(tp) (tp)->sg.sg_ispeed -#else /* USE_TERMIO */ -# ifdef SYSV_TERMIO -# define termios termio -# endif +#ifdef HAVE_TERMIOS_H +#include <termios.h> +#else +#ifdef HAVE_TERMIO_H +#include <termio.h> +#endif +#endif + +#ifdef HAVE_UTIL_H +#include <util.h> +#endif + # ifndef TCSANOW # ifdef TCSETS # define TCSANOW TCSETS @@ -165,26 +161,25 @@ struct termbuf { # endif # define tcsetattr(f, a, t) ioctl(f, a, t) # define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ - (tp)->c_cflag |= (val) +(tp)->c_cflag |= (val) # define cfgetospeed(tp) ((tp)->c_cflag & CBAUD) # ifdef CIBAUD # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \ - (tp)->c_cflag |= ((val)<<IBSHIFT) + (tp)->c_cflag |= ((val)<<IBSHIFT) # define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT) # else # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ - (tp)->c_cflag |= (val) + (tp)->c_cflag |= (val) # define cfgetispeed(tp) ((tp)->c_cflag & CBAUD) # endif # endif /* TCSANOW */ -struct termios termbuf, termbuf2; /* pty control structure */ + struct termios termbuf, termbuf2; /* pty control structure */ # ifdef STREAMSPTY -int ttyfd = -1; + static int ttyfd = -1; + int really_stream = 0; # endif -#endif /* USE_TERMIO */ -int cleanopen P((char *)); -void scrub_env P((void)); + const char *new_login = _PATH_LOGIN; /* * init_termbuf() @@ -197,68 +192,31 @@ void scrub_env P((void)); * set_termbuf() writes the structure into the kernel. */ - void -init_termbuf() + void + init_termbuf(void) { -#ifndef USE_TERMIO - (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg); - (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc); - (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc); -# ifdef TIOCGSTATE - (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state); -# endif -#else # ifdef STREAMSPTY - (void) tcgetattr(ttyfd, &termbuf); -# else - (void) tcgetattr(pty, &termbuf); + if (really_stream) + tcgetattr(ttyfd, &termbuf); + else # endif -#endif - termbuf2 = termbuf; -} - -#if defined(LINEMODE) && defined(TIOCPKT_IOCTL) - void -copy_termbuf(cp, len) - char *cp; - int len; -{ - if (len > sizeof(termbuf)) - len = sizeof(termbuf); - memmove((void *)&termbuf, cp, len); - termbuf2 = termbuf; + tcgetattr(ourpty, &termbuf); + termbuf2 = termbuf; } -#endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ - void -set_termbuf() +void +set_termbuf(void) { - /* - * Only make the necessary changes. + /* + * Only make the necessary changes. */ -#ifndef USE_TERMIO - if (memcmp((void *)&termbuf.sg, (void *)&termbuf2.sg, - sizeof(termbuf.sg))) - (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg); - if (memcmp((void *)&termbuf.tc, (void *)&termbuf2.tc, - sizeof(termbuf.tc))) - (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc); - if (memcmp((void *)&termbuf.ltc, (void *)&termbuf2.ltc, - sizeof(termbuf.ltc))) - (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc); - if (termbuf.lflags != termbuf2.lflags) - (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags); -#else /* USE_TERMIO */ - if (memcmp((void *)&termbuf, (void *)&termbuf2, sizeof(termbuf))) + if (memcmp(&termbuf, &termbuf2, sizeof(termbuf))) # ifdef STREAMSPTY - (void) tcsetattr(ttyfd, TCSANOW, &termbuf); -# else - (void) tcsetattr(pty, TCSANOW, &termbuf); -# endif -# if defined(CRAY2) && defined(UNICOS5) - needtermstat = 1; + if (really_stream) + tcsetattr(ttyfd, TCSANOW, &termbuf); + else # endif -#endif /* USE_TERMIO */ + tcsetattr(ourpty, TCSANOW, &termbuf); } @@ -273,199 +231,119 @@ set_termbuf() * It returns the SLC_ level of support for this function. */ -#ifndef USE_TERMIO - int -spcset(func, valp, valpp) - int func; - cc_t *valp; - cc_t **valpp; -{ - switch(func) { - case SLC_EOF: - *valp = termbuf.tc.t_eofc; - *valpp = (cc_t *)&termbuf.tc.t_eofc; - return(SLC_VARIABLE); - case SLC_EC: - *valp = termbuf.sg.sg_erase; - *valpp = (cc_t *)&termbuf.sg.sg_erase; - return(SLC_VARIABLE); - case SLC_EL: - *valp = termbuf.sg.sg_kill; - *valpp = (cc_t *)&termbuf.sg.sg_kill; - return(SLC_VARIABLE); - case SLC_IP: - *valp = termbuf.tc.t_intrc; - *valpp = (cc_t *)&termbuf.tc.t_intrc; - return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); - case SLC_ABORT: - *valp = termbuf.tc.t_quitc; - *valpp = (cc_t *)&termbuf.tc.t_quitc; - return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); - case SLC_XON: - *valp = termbuf.tc.t_startc; - *valpp = (cc_t *)&termbuf.tc.t_startc; - return(SLC_VARIABLE); - case SLC_XOFF: - *valp = termbuf.tc.t_stopc; - *valpp = (cc_t *)&termbuf.tc.t_stopc; - return(SLC_VARIABLE); - case SLC_AO: - *valp = termbuf.ltc.t_flushc; - *valpp = (cc_t *)&termbuf.ltc.t_flushc; - return(SLC_VARIABLE); - case SLC_SUSP: - *valp = termbuf.ltc.t_suspc; - *valpp = (cc_t *)&termbuf.ltc.t_suspc; - return(SLC_VARIABLE); - case SLC_EW: - *valp = termbuf.ltc.t_werasc; - *valpp = (cc_t *)&termbuf.ltc.t_werasc; - return(SLC_VARIABLE); - case SLC_RP: - *valp = termbuf.ltc.t_rprntc; - *valpp = (cc_t *)&termbuf.ltc.t_rprntc; - return(SLC_VARIABLE); - case SLC_LNEXT: - *valp = termbuf.ltc.t_lnextc; - *valpp = (cc_t *)&termbuf.ltc.t_lnextc; - return(SLC_VARIABLE); - case SLC_FORW1: - *valp = termbuf.tc.t_brkc; - *valpp = (cc_t *)&termbuf.ltc.t_lnextc; - return(SLC_VARIABLE); - case SLC_BRK: - case SLC_SYNCH: - case SLC_AYT: - case SLC_EOR: - *valp = (cc_t)0; - *valpp = (cc_t *)0; - return(SLC_DEFAULT); - default: - *valp = (cc_t)0; - *valpp = (cc_t *)0; - return(SLC_NOSUPPORT); - } -} -#else /* USE_TERMIO */ - - int -spcset(func, valp, valpp) - int func; - cc_t *valp; - cc_t **valpp; +int +spcset(int func, cc_t *valp, cc_t **valpp) { #define setval(a, b) *valp = termbuf.c_cc[a]; \ - *valpp = &termbuf.c_cc[a]; \ - return(b); + *valpp = &termbuf.c_cc[a]; \ + return(b); #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); - switch(func) { - case SLC_EOF: - setval(VEOF, SLC_VARIABLE); - case SLC_EC: - setval(VERASE, SLC_VARIABLE); - case SLC_EL: - setval(VKILL, SLC_VARIABLE); - case SLC_IP: - setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); - case SLC_ABORT: - setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); - case SLC_XON: + switch(func) { + case SLC_EOF: + setval(VEOF, SLC_VARIABLE); + case SLC_EC: + setval(VERASE, SLC_VARIABLE); + case SLC_EL: + setval(VKILL, SLC_VARIABLE); + case SLC_IP: + setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); + case SLC_ABORT: + setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); + case SLC_XON: #ifdef VSTART - setval(VSTART, SLC_VARIABLE); + setval(VSTART, SLC_VARIABLE); #else - defval(0x13); + defval(0x13); #endif - case SLC_XOFF: + case SLC_XOFF: #ifdef VSTOP - setval(VSTOP, SLC_VARIABLE); + setval(VSTOP, SLC_VARIABLE); #else - defval(0x11); + defval(0x11); #endif - case SLC_EW: + case SLC_EW: #ifdef VWERASE - setval(VWERASE, SLC_VARIABLE); + setval(VWERASE, SLC_VARIABLE); #else - defval(0); + defval(0); #endif - case SLC_RP: + case SLC_RP: #ifdef VREPRINT - setval(VREPRINT, SLC_VARIABLE); + setval(VREPRINT, SLC_VARIABLE); #else - defval(0); + defval(0); #endif - case SLC_LNEXT: + case SLC_LNEXT: #ifdef VLNEXT - setval(VLNEXT, SLC_VARIABLE); + setval(VLNEXT, SLC_VARIABLE); #else - defval(0); + defval(0); #endif - case SLC_AO: + case SLC_AO: #if !defined(VDISCARD) && defined(VFLUSHO) # define VDISCARD VFLUSHO #endif #ifdef VDISCARD - setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); + setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); #else - defval(0); + defval(0); #endif - case SLC_SUSP: + case SLC_SUSP: #ifdef VSUSP - setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); + setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); #else - defval(0); + defval(0); #endif #ifdef VEOL - case SLC_FORW1: - setval(VEOL, SLC_VARIABLE); + case SLC_FORW1: + setval(VEOL, SLC_VARIABLE); #endif #ifdef VEOL2 - case SLC_FORW2: - setval(VEOL2, SLC_VARIABLE); + case SLC_FORW2: + setval(VEOL2, SLC_VARIABLE); #endif - case SLC_AYT: + case SLC_AYT: #ifdef VSTATUS - setval(VSTATUS, SLC_VARIABLE); + setval(VSTATUS, SLC_VARIABLE); #else - defval(0); + defval(0); #endif - case SLC_BRK: - case SLC_SYNCH: - case SLC_EOR: - defval(0); + case SLC_BRK: + case SLC_SYNCH: + case SLC_EOR: + defval(0); - default: - *valp = 0; - *valpp = 0; - return(SLC_NOSUPPORT); - } + default: + *valp = 0; + *valpp = 0; + return(SLC_NOSUPPORT); + } } -#endif /* USE_TERMIO */ -#ifdef CRAY +#ifdef _CRAY /* * getnpty() * * Return the number of pty's configured into the system. */ - int +int getnpty() { #ifdef _SC_CRAY_NPTY - int numptys; + int numptys; - if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) - return numptys; - else + if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) + return numptys; + else #endif /* _SC_CRAY_NPTY */ - return 128; + return 128; } #endif /* CRAY */ -#ifndef convex /* * getpty() * @@ -474,480 +352,312 @@ getnpty() * * Returns the file descriptor of the opened pty. */ -#ifdef CRAY -char myline[16]; -#else -char line[16]; -#endif /* CRAY */ - int -getpty(ptynum) -int *ptynum; -{ - register int p; -#ifdef STREAMSPTY - int t; - char *ptsname(); - - p = open("/dev/ptmx", O_RDWR); - if (p > 0) { - grantpt(p); - unlockpt(p); - strcpy(line, ptsname(p)); - return(p); - } +static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; +char *line = Xline; -#else /* ! STREAMSPTY */ -#ifndef CRAY - register char *cp, *p1, *p2; - register int i; -#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207 - int dummy; -#endif - -#ifndef __hpux - (void) sprintf(line, "/dev/ptyXX"); - p1 = &line[8]; - p2 = &line[9]; -#else - (void) sprintf(line, "/dev/ptym/ptyXX"); - p1 = &line[13]; - p2 = &line[14]; -#endif - - for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) { - struct stat stb; - - *p1 = *cp; - *p2 = '0'; - /* - * This stat() check is just to keep us from - * looping through all 256 combinations if there - * aren't that many ptys available. - */ - if (stat(line, &stb) < 0) - break; - for (i = 0; i < 16; i++) { - *p2 = "0123456789abcdef"[i]; - p = open(line, O_RDWR); - if (p > 0) { -#ifndef __hpux - line[5] = 't'; -#else - for (p1 = &line[8]; *p1; p1++) - *p1 = *(p1+1); - line[9] = 't'; -#endif - chown(line, 0, 0); - chmod(line, 0600); -#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207 - if (ioctl(p, TIOCGPGRP, &dummy) == 0 - || errno != EIO) { - chmod(line, 0666); - close(p); - line[5] = 'p'; - } else -#endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */ - return(p); - } - } - } -#else /* CRAY */ - extern lowpty, highpty; - struct stat sb; - - for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) { - (void) sprintf(myline, "/dev/pty/%03d", *ptynum); - p = open(myline, O_RDWR); - if (p < 0) - continue; - (void) sprintf(line, "/dev/ttyp%03d", *ptynum); - /* - * Here are some shenanigans to make sure that there - * are no listeners lurking on the line. - */ - if(stat(line, &sb) < 0) { - (void) close(p); - continue; - } - if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { - chown(line, 0, 0); - chmod(line, 0600); - (void)close(p); - p = open(myline, O_RDWR); - if (p < 0) - continue; - } - /* - * Now it should be safe...check for accessability. - */ - if (access(line, 6) == 0) - return(p); - else { - /* no tty side to pty so skip it */ - (void) close(p); - } - } +#ifdef _CRAY +char myline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; #endif /* CRAY */ -#endif /* STREAMSPTY */ - return(-1); -} -#endif /* convex */ - -#ifdef LINEMODE -/* - * tty_flowmode() Find out if flow control is enabled or disabled. - * tty_linemode() Find out if linemode (external processing) is enabled. - * tty_setlinemod(on) Turn on/off linemode. - * tty_isecho() Find out if echoing is turned on. - * tty_setecho(on) Enable/disable character echoing. - * tty_israw() Find out if terminal is in RAW mode. - * tty_binaryin(on) Turn on/off BINARY on input. - * tty_binaryout(on) Turn on/off BINARY on output. - * tty_isediting() Find out if line editing is enabled. - * tty_istrapsig() Find out if signal trapping is enabled. - * tty_setedit(on) Turn on/off line editing. - * tty_setsig(on) Turn on/off signal trapping. - * tty_issofttab() Find out if tab expansion is enabled. - * tty_setsofttab(on) Turn on/off soft tab expansion. - * tty_islitecho() Find out if typed control chars are echoed literally - * tty_setlitecho() Turn on/off literal echo of control chars - * tty_tspeed(val) Set transmit speed to val. - * tty_rspeed(val) Set receive speed to val. - */ - -#ifdef convex -static int linestate; -#endif - int -tty_linemode() +#if !defined(HAVE_PTSNAME) && defined(STREAMSPTY) +static char *ptsname(int fd) { -#ifndef convex -#ifndef USE_TERMIO - return(termbuf.state & TS_EXTPROC); +#ifdef HAVE_TTYNAME + return ttyname(fd); #else - return(termbuf.c_lflag & EXTPROC); -#endif -#else - return(linestate); + return NULL; #endif } - - void -tty_setlinemode(on) - int on; -{ -#ifdef TIOCEXT -# ifndef convex - set_termbuf(); -# else - linestate = on; -# endif - (void) ioctl(pty, TIOCEXT, (char *)&on); -# ifndef convex - init_termbuf(); -# endif -#else /* !TIOCEXT */ -# ifdef EXTPROC - if (on) - termbuf.c_lflag |= EXTPROC; - else - termbuf.c_lflag &= ~EXTPROC; -# endif -#endif /* TIOCEXT */ -} -#endif /* LINEMODE */ - - int -tty_isecho() -{ -#ifndef USE_TERMIO - return (termbuf.sg.sg_flags & ECHO); -#else - return (termbuf.c_lflag & ECHO); #endif -} - int -tty_flowmode() +int getpty(int *ptynum) { -#ifndef USE_TERMIO - return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0); +#ifdef __osf__ /* XXX */ + int master; + int slave; + if(openpty(&master, &slave, line, 0, 0) == 0){ + close(slave); + return master; + } + return -1; +#else +#ifdef HAVE__GETPTY + int master, slave; + char *p; + p = _getpty(&master, O_RDWR, 0600, 1); + if(p == NULL) + return -1; + strlcpy(line, p, sizeof(Xline)); + return master; #else - return((termbuf.c_iflag & IXON) ? 1 : 0); -#endif -} - int -tty_restartany() -{ -#ifndef USE_TERMIO -# ifdef DECCTQ - return((termbuf.lflags & DECCTQ) ? 0 : 1); -# else - return(-1); -# endif + int p; + char *cp, *p1, *p2; + int i; +#if SunOS == 40 + int dummy; +#endif +#if 0 /* && defined(HAVE_OPENPTY) */ + int master; + int slave; + if(openpty(&master, &slave, line, 0, 0) == 0){ + close(slave); + return master; + } #else - return((termbuf.c_iflag & IXANY) ? 1 : 0); -#endif -} +#ifdef STREAMSPTY + char *clone[] = { "/dev/ptc", "/dev/ptmx", "/dev/ptm", + "/dev/ptym/clone", 0 }; + + char **q; + for(q=clone; *q; q++){ + p=open(*q, O_RDWR); + if(p >= 0){ +#ifdef HAVE_GRANTPT + grantpt(p); +#endif +#ifdef HAVE_UNLOCKPT + unlockpt(p); +#endif + strlcpy(line, ptsname(p), sizeof(Xline)); + really_stream = 1; + return p; + } + } +#endif /* STREAMSPTY */ +#ifndef _CRAY - void -tty_setecho(on) - int on; -{ -#ifndef USE_TERMIO - if (on) - termbuf.sg.sg_flags |= ECHO|CRMOD; - else - termbuf.sg.sg_flags &= ~(ECHO|CRMOD); +#ifndef __hpux + snprintf(line, sizeof(Xline), "/dev/ptyXX"); + p1 = &line[8]; + p2 = &line[9]; #else - if (on) - termbuf.c_lflag |= ECHO; - else - termbuf.c_lflag &= ~ECHO; + snprintf(line, sizeof(Xline), "/dev/ptym/ptyXX"); + p1 = &line[13]; + p2 = &line[14]; #endif -} - int -tty_israw() -{ -#ifndef USE_TERMIO - return(termbuf.sg.sg_flags & RAW); + + for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) { + struct stat stb; + + *p1 = *cp; + *p2 = '0'; + /* + * This stat() check is just to keep us from + * looping through all 256 combinations if there + * aren't that many ptys available. + */ + if (stat(line, &stb) < 0) + break; + for (i = 0; i < 16; i++) { + *p2 = "0123456789abcdef"[i]; + p = open(line, O_RDWR); + if (p > 0) { +#ifndef __hpux + line[5] = 't'; #else - return(!(termbuf.c_lflag & ICANON)); + for (p1 = &line[8]; *p1; p1++) + *p1 = *(p1+1); + line[9] = 't'; +#endif + chown(line, 0, 0); + chmod(line, 0600); +#if SunOS == 40 + if (ioctl(p, TIOCGPGRP, &dummy) == 0 + || errno != EIO) { + chmod(line, 0666); + close(p); + line[5] = 'p'; + } else +#endif /* SunOS == 40 */ + return(p); + } + } + } +#else /* CRAY */ + extern lowpty, highpty; + struct stat sb; + + for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) { + snprintf(myline, sizeof(myline), "/dev/pty/%03d", *ptynum); + p = open(myline, 2); + if (p < 0) + continue; + snprintf(line, sizeof(Xline), "/dev/ttyp%03d", *ptynum); + /* + * Here are some shenanigans to make sure that there + * are no listeners lurking on the line. + */ + if(stat(line, &sb) < 0) { + close(p); + continue; + } + if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { + chown(line, 0, 0); + chmod(line, 0600); + close(p); + p = open(myline, 2); + if (p < 0) + continue; + } + /* + * Now it should be safe...check for accessability. + */ + if (access(line, 6) == 0) + return(p); + else { + /* no tty side to pty so skip it */ + close(p); + } + } +#endif /* CRAY */ +#endif /* STREAMSPTY */ +#endif /* OPENPTY */ + return(-1); #endif } -#if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) - int -tty_setraw(on) + +int +tty_isecho(void) { -# ifndef USE_TERMIO - if (on) - termbuf.sg.sg_flags |= RAW; - else - termbuf.sg.sg_flags &= ~RAW; -# else - if (on) - termbuf.c_lflag &= ~ICANON; - else - termbuf.c_lflag |= ICANON; -# endif + return (termbuf.c_lflag & ECHO); } -#endif - void -tty_binaryin(on) - int on; +int +tty_flowmode(void) { -#ifndef USE_TERMIO - if (on) - termbuf.lflags |= LPASS8; - else - termbuf.lflags &= ~LPASS8; -#else - if (on) { - termbuf.c_iflag &= ~ISTRIP; - } else { - termbuf.c_iflag |= ISTRIP; - } -#endif + return((termbuf.c_iflag & IXON) ? 1 : 0); } - void -tty_binaryout(on) - int on; +int +tty_restartany(void) { -#ifndef USE_TERMIO - if (on) - termbuf.lflags |= LLITOUT; - else - termbuf.lflags &= ~LLITOUT; -#else - if (on) { - termbuf.c_cflag &= ~(CSIZE|PARENB); - termbuf.c_cflag |= CS8; - termbuf.c_oflag &= ~OPOST; - } else { - termbuf.c_cflag &= ~CSIZE; - termbuf.c_cflag |= CS7|PARENB; - termbuf.c_oflag |= OPOST; - } -#endif + return((termbuf.c_iflag & IXANY) ? 1 : 0); } - int -tty_isbinaryin() +void +tty_setecho(int on) { -#ifndef USE_TERMIO - return(termbuf.lflags & LPASS8); -#else - return(!(termbuf.c_iflag & ISTRIP)); -#endif + if (on) + termbuf.c_lflag |= ECHO; + else + termbuf.c_lflag &= ~ECHO; } - int -tty_isbinaryout() +int +tty_israw(void) { -#ifndef USE_TERMIO - return(termbuf.lflags & LLITOUT); -#else - return(!(termbuf.c_oflag&OPOST)); -#endif + return(!(termbuf.c_lflag & ICANON)); } -#ifdef LINEMODE - int -tty_isediting() +void +tty_binaryin(int on) { -#ifndef USE_TERMIO - return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); -#else - return(termbuf.c_lflag & ICANON); -#endif + if (on) { + termbuf.c_iflag &= ~ISTRIP; + } else { + termbuf.c_iflag |= ISTRIP; + } } - int -tty_istrapsig() +void +tty_binaryout(int on) { -#ifndef USE_TERMIO - return(!(termbuf.sg.sg_flags&RAW)); -#else - return(termbuf.c_lflag & ISIG); -#endif + if (on) { + termbuf.c_cflag &= ~(CSIZE|PARENB); + termbuf.c_cflag |= CS8; + termbuf.c_oflag &= ~OPOST; + } else { + termbuf.c_cflag &= ~CSIZE; + termbuf.c_cflag |= CS7|PARENB; + termbuf.c_oflag |= OPOST; + } } - void -tty_setedit(on) - int on; +int +tty_isbinaryin(void) { -#ifndef USE_TERMIO - if (on) - termbuf.sg.sg_flags &= ~CBREAK; - else - termbuf.sg.sg_flags |= CBREAK; -#else - if (on) - termbuf.c_lflag |= ICANON; - else - termbuf.c_lflag &= ~ICANON; -#endif + return(!(termbuf.c_iflag & ISTRIP)); } - void -tty_setsig(on) - int on; +int +tty_isbinaryout(void) { -#ifndef USE_TERMIO - if (on) - ; -#else - if (on) - termbuf.c_lflag |= ISIG; - else - termbuf.c_lflag &= ~ISIG; -#endif + return(!(termbuf.c_oflag&OPOST)); } -#endif /* LINEMODE */ - int -tty_issofttab() + +int +tty_issofttab(void) { -#ifndef USE_TERMIO - return (termbuf.sg.sg_flags & XTABS); -#else # ifdef OXTABS - return (termbuf.c_oflag & OXTABS); + return (termbuf.c_oflag & OXTABS); # endif # ifdef TABDLY - return ((termbuf.c_oflag & TABDLY) == TAB3); + return ((termbuf.c_oflag & TABDLY) == TAB3); # endif -#endif } - void -tty_setsofttab(on) - int on; +void +tty_setsofttab(int on) { -#ifndef USE_TERMIO - if (on) - termbuf.sg.sg_flags |= XTABS; - else - termbuf.sg.sg_flags &= ~XTABS; -#else - if (on) { + if (on) { # ifdef OXTABS - termbuf.c_oflag |= OXTABS; + termbuf.c_oflag |= OXTABS; # endif # ifdef TABDLY - termbuf.c_oflag &= ~TABDLY; - termbuf.c_oflag |= TAB3; + termbuf.c_oflag &= ~TABDLY; + termbuf.c_oflag |= TAB3; # endif - } else { + } else { # ifdef OXTABS - termbuf.c_oflag &= ~OXTABS; + termbuf.c_oflag &= ~OXTABS; # endif # ifdef TABDLY - termbuf.c_oflag &= ~TABDLY; - termbuf.c_oflag |= TAB0; + termbuf.c_oflag &= ~TABDLY; + termbuf.c_oflag |= TAB0; # endif - } -#endif + } } - int -tty_islitecho() +int +tty_islitecho(void) { -#ifndef USE_TERMIO - return (!(termbuf.lflags & LCTLECH)); -#else # ifdef ECHOCTL - return (!(termbuf.c_lflag & ECHOCTL)); + return (!(termbuf.c_lflag & ECHOCTL)); # endif # ifdef TCTLECH - return (!(termbuf.c_lflag & TCTLECH)); + return (!(termbuf.c_lflag & TCTLECH)); # endif # if !defined(ECHOCTL) && !defined(TCTLECH) - return (0); /* assumes ctl chars are echoed '^x' */ + return (0); /* assumes ctl chars are echoed '^x' */ # endif -#endif } - void -tty_setlitecho(on) - int on; +void +tty_setlitecho(int on) { -#ifndef USE_TERMIO - if (on) - termbuf.lflags &= ~LCTLECH; - else - termbuf.lflags |= LCTLECH; -#else # ifdef ECHOCTL - if (on) - termbuf.c_lflag &= ~ECHOCTL; - else - termbuf.c_lflag |= ECHOCTL; + if (on) + termbuf.c_lflag &= ~ECHOCTL; + else + termbuf.c_lflag |= ECHOCTL; # endif # ifdef TCTLECH - if (on) - termbuf.c_lflag &= ~TCTLECH; - else - termbuf.c_lflag |= TCTLECH; + if (on) + termbuf.c_lflag &= ~TCTLECH; + else + termbuf.c_lflag |= TCTLECH; # endif -#endif } - int -tty_iscrnl() +int +tty_iscrnl(void) { -#ifndef USE_TERMIO - return (termbuf.sg.sg_flags & CRMOD); -#else - return (termbuf.c_iflag & ICRNL); -#endif + return (termbuf.c_iflag & ICRNL); } /* @@ -963,257 +673,284 @@ tty_iscrnl() * A table of available terminal speeds */ struct termspeeds { - int speed; - int value; + int speed; + int value; } termspeeds[] = { - { 0, B0 }, { 50, B50 }, { 75, B75 }, - { 110, B110 }, { 134, B134 }, { 150, B150 }, - { 200, B200 }, { 300, B300 }, { 600, B600 }, - { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, - { 4800, B4800 }, + { 0, B0 }, { 50, B50 }, { 75, B75 }, + { 110, B110 }, { 134, B134 }, { 150, B150 }, + { 200, B200 }, { 300, B300 }, { 600, B600 }, + { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, + { 4800, B4800 }, #ifdef B7200 - { 7200, B7200 }, + { 7200, B7200 }, #endif - { 9600, B9600 }, + { 9600, B9600 }, #ifdef B14400 - { 14400, B14400 }, + { 14400, B14400 }, #endif #ifdef B19200 - { 19200, B19200 }, + { 19200, B19200 }, #endif #ifdef B28800 - { 28800, B28800 }, + { 28800, B28800 }, #endif #ifdef B38400 - { 38400, B38400 }, + { 38400, B38400 }, #endif #ifdef B57600 - { 57600, B57600 }, + { 57600, B57600 }, #endif #ifdef B115200 - { 115200, B115200 }, + { 115200, B115200 }, #endif #ifdef B230400 - { 230400, B230400 }, + { 230400, B230400 }, #endif - { -1, 0 } + { -1, 0 } }; #endif /* DECODE_BUAD */ - void -tty_tspeed(val) - int val; +void +tty_tspeed(int val) { #ifdef DECODE_BAUD - register struct termspeeds *tp; + struct termspeeds *tp; - for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) - ; - if (tp->speed == -1) /* back up to last valid value */ - --tp; - cfsetospeed(&termbuf, tp->value); + for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) + ; + if (tp->speed == -1) /* back up to last valid value */ + --tp; + cfsetospeed(&termbuf, tp->value); #else /* DECODE_BUAD */ - cfsetospeed(&termbuf, val); + cfsetospeed(&termbuf, val); #endif /* DECODE_BUAD */ } - void -tty_rspeed(val) - int val; +void +tty_rspeed(int val) { #ifdef DECODE_BAUD - register struct termspeeds *tp; + struct termspeeds *tp; - for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) - ; - if (tp->speed == -1) /* back up to last valid value */ - --tp; - cfsetispeed(&termbuf, tp->value); + for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) + ; + if (tp->speed == -1) /* back up to last valid value */ + --tp; + cfsetispeed(&termbuf, tp->value); #else /* DECODE_BAUD */ - cfsetispeed(&termbuf, val); + cfsetispeed(&termbuf, val); #endif /* DECODE_BAUD */ } -#if defined(CRAY2) && defined(UNICOS5) - int -tty_isnewmap() -{ - return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) && - !(termbuf.c_oflag & ONLRET)); -} -#endif - #ifdef PARENT_DOES_UTMP -# ifndef NEWINIT extern struct utmp wtmp; extern char wtmpf[]; -# else /* NEWINIT */ -int gotalarm; - /* ARGSUSED */ - void -nologinproc(sig) - int sig; +extern void utmp_sig_init (void); +extern void utmp_sig_reset (void); +extern void utmp_sig_wait (void); +extern void utmp_sig_notify (int); +# endif /* PARENT_DOES_UTMP */ + +#ifdef STREAMSPTY + +/* I_FIND seems to live a life of its own */ +static int my_find(int fd, char *module) { - gotalarm++; +#if defined(I_FIND) && defined(I_LIST) + static int flag; + static struct str_list sl; + int n; + int i; + + if(!flag){ + n = ioctl(fd, I_LIST, 0); + if(n < 0){ + perror("ioctl(fd, I_LIST, 0)"); + return -1; + } + sl.sl_modlist=(struct str_mlist*)malloc(n * sizeof(struct str_mlist)); + sl.sl_nmods = n; + n = ioctl(fd, I_LIST, &sl); + if(n < 0){ + perror("ioctl(fd, I_LIST, n)"); + return -1; + } + flag = 1; + } + + for(i=0; i<sl.sl_nmods; i++) + if(!strcmp(sl.sl_modlist[i].l_name, module)) + return 1; +#endif + return 0; } -# endif /* NEWINIT */ -#endif /* PARENT_DOES_UTMP */ -#ifndef NEWINIT -# ifdef PARENT_DOES_UTMP -extern void utmp_sig_init P((void)); -extern void utmp_sig_reset P((void)); -extern void utmp_sig_wait P((void)); -extern void utmp_sig_notify P((int)); -# endif /* PARENT_DOES_UTMP */ +static void maybe_push_modules(int fd, char **modules) +{ + char **p; + int err; + + for(p=modules; *p; p++){ + err = my_find(fd, *p); + if(err == 1) + break; + if(err < 0 && errno != EINVAL) + fatalperror(net, "my_find()"); + /* module not pushed or does not exist */ + } + /* p points to null or to an already pushed module, now push all + modules before this one */ + + for(p--; p >= modules; p--){ + err = ioctl(fd, I_PUSH, *p); + if(err < 0 && errno != EINVAL) + fatalperror(net, "I_PUSH"); + } +} #endif /* * getptyslave() * * Open the slave side of the pty, and do any initialization - * that is necessary. + * that is necessary. The return value is a file descriptor + * for the slave side. */ - void -getptyslave() +void getptyslave(void) { - register int t = -1; - -#if !defined(CRAY) || !defined(NEWINIT) -# ifdef LINEMODE - int waslm; -# endif -# ifdef TIOCGWINSZ - struct winsize ws; - extern int def_row, def_col; -# endif - extern int def_tspeed, def_rspeed; - /* - * Opening the slave side may cause initilization of the - * kernel tty structure. We need remember the state of - * if linemode was turned on - * terminal window size - * terminal speed - * so that we can re-set them if we need to. - */ -# ifdef LINEMODE - waslm = tty_linemode(); -# endif - - - /* - * Make sure that we don't have a controlling tty, and - * that we are the session (process group) leader. - */ + int t = -1; + + struct winsize ws; + extern int def_row, def_col; + extern int def_tspeed, def_rspeed; + /* + * Opening the slave side may cause initilization of the + * kernel tty structure. We need remember the state of + * if linemode was turned on + * terminal window size + * terminal speed + * so that we can re-set them if we need to. + */ + + + /* + * Make sure that we don't have a controlling tty, and + * that we are the session (process group) leader. + */ + +#ifdef HAVE_SETSID + if(setsid()<0) + fatalperror(net, "setsid()"); +#else # ifdef TIOCNOTTY - t = open(_PATH_TTY, O_RDWR); - if (t >= 0) { - (void) ioctl(t, TIOCNOTTY, (char *)0); - (void) close(t); - } + t = open(_PATH_TTY, O_RDWR); + if (t >= 0) { + ioctl(t, TIOCNOTTY, (char *)0); + close(t); + } # endif - +#endif # ifdef PARENT_DOES_UTMP - /* - * Wait for our parent to get the utmp stuff to get done. - */ - utmp_sig_wait(); + /* + * Wait for our parent to get the utmp stuff to get done. + */ + utmp_sig_wait(); # endif - t = cleanopen(line); - if (t < 0) - fatalperror(net, line); + t = cleanopen(line); + if (t < 0) + fatalperror(net, line); #ifdef STREAMSPTY -#ifdef USE_TERMIO - ttyfd = t; -#endif - if (ioctl(t, I_PUSH, "ptem") < 0) - fatal(net, "I_PUSH ptem"); - if (ioctl(t, I_PUSH, "ldterm") < 0) - fatal(net, "I_PUSH ldterm"); - if (ioctl(t, I_PUSH, "ttcompat") < 0) - fatal(net, "I_PUSH ttcompat"); - if (ioctl(pty, I_PUSH, "pckt") < 0) - fatal(net, "I_PUSH pckt"); -#endif + ttyfd = t; + - /* - * set up the tty modes as we like them to be. - */ - init_termbuf(); -# ifdef TIOCGWINSZ - if (def_row || def_col) { - memset((void *)&ws, 0, sizeof(ws)); - ws.ws_col = def_col; - ws.ws_row = def_row; - (void)ioctl(t, TIOCSWINSZ, (char *)&ws); + /* + * Not all systems have (or need) modules ttcompat and pckt so + * don't flag it as a fatal error if they don't exist. + */ + + if (really_stream) + { + /* these are the streams modules that we want pushed. note + that they are in reverse order, ptem will be pushed + first. maybe_push_modules() will try to push all modules + before the first one that isn't already pushed. i.e if + ldterm is pushed, only ttcompat will be attempted. + + all this is because we don't know which modules are + available, and we don't know which modules are already + pushed (via autopush, for instance). + + */ + + char *ttymodules[] = { "ttcompat", "ldterm", "ptem", NULL }; + char *ptymodules[] = { "pckt", NULL }; + + maybe_push_modules(t, ttymodules); + maybe_push_modules(ourpty, ptymodules); } +#endif + /* + * set up the tty modes as we like them to be. + */ + init_termbuf(); +# ifdef TIOCSWINSZ + if (def_row || def_col) { + memset(&ws, 0, sizeof(ws)); + ws.ws_col = def_col; + ws.ws_row = def_row; + ioctl(t, TIOCSWINSZ, (char *)&ws); + } # endif - /* - * Settings for sgtty based systems - */ -# ifndef USE_TERMIO - termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; -# endif /* USE_TERMIO */ - - /* - * Settings for UNICOS (and HPUX) - */ -# if defined(CRAY) || defined(__hpux) - termbuf.c_oflag = OPOST|ONLCR|TAB3; - termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; - termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; - termbuf.c_cflag = EXTB|HUPCL|CS8; + /* + * Settings for sgtty based systems + */ + + /* + * Settings for UNICOS (and HPUX) + */ +# if defined(_CRAY) || defined(__hpux) + termbuf.c_oflag = OPOST|ONLCR|TAB3; + termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; + termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; + termbuf.c_cflag = EXTB|HUPCL|CS8; # endif - /* - * Settings for all other termios/termio based - * systems, other than 4.4BSD. In 4.4BSD the - * kernel does the initial terminal setup. - */ -# if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) + /* + * Settings for all other termios/termio based + * systems, other than 4.4BSD. In 4.4BSD the + * kernel does the initial terminal setup. + */ +# if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43) # ifndef OXTABS # define OXTABS 0 # endif - termbuf.c_lflag |= ECHO; - termbuf.c_oflag |= ONLCR|OXTABS; - termbuf.c_iflag |= ICRNL; - termbuf.c_iflag &= ~IXOFF; -# endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */ - tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); - tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); -# ifdef LINEMODE - if (waslm) - tty_setlinemode(1); -# endif /* LINEMODE */ - - /* - * Set the tty modes, and make this our controlling tty. - */ - set_termbuf(); - if (login_tty(t) == -1) - fatalperror(net, "login_tty"); -#endif /* !defined(CRAY) || !defined(NEWINIT) */ - if (net > 2) - (void) close(net); -#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) - /* - * Leave the pty open so that we can write out the rlogin - * protocol for /bin/login, if the authentication works. - */ -#else - if (pty > 2) { - (void) close(pty); - pty = -1; - } -#endif + termbuf.c_lflag |= ECHO; + termbuf.c_oflag |= ONLCR|OXTABS; + termbuf.c_iflag |= ICRNL; + termbuf.c_iflag &= ~IXOFF; +# endif + tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); + tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); + + /* + * Set the tty modes, and make this our controlling tty. + */ + set_termbuf(); + if (login_tty(t) == -1) + fatalperror(net, "login_tty"); + if (net > 2) + close(net); + if (ourpty > 2) { + close(ourpty); + ourpty = -1; + } } -#if !defined(CRAY) || !defined(NEWINIT) #ifndef O_NOCTTY #define O_NOCTTY 0 #endif @@ -1221,161 +958,147 @@ getptyslave() * Open the specified slave side of the pty, * making sure that we have a clean tty. */ - int -cleanopen(line) - char *line; + +int cleanopen(char *line) { - register int t; -#ifdef UNICOS7x - struct secstat secbuf; -#endif /* UNICOS7x */ + int t; -#ifndef STREAMSPTY - /* - * Make sure that other people can't open the - * slave side of the connection. - */ - (void) chown(line, 0, 0); - (void) chmod(line, 0600); +#ifdef STREAMSPTY + if (!really_stream) #endif - -# if !defined(CRAY) && (BSD > 43) - (void) revoke(line); -# endif -#ifdef UNICOS7x - if (secflag) { - if (secstat(line, &secbuf) < 0) - return(-1); - if (setulvl(secbuf.st_slevel) < 0) - return(-1); - if (setucmp(secbuf.st_compart) < 0) - return(-1); + { + /* + * Make sure that other people can't open the + * slave side of the connection. + */ + chown(line, 0, 0); + chmod(line, 0600); } -#endif /* UNICOS7x */ - t = open(line, O_RDWR|O_NOCTTY); +#ifdef HAVE_REVOKE + revoke(line); +#endif -#ifdef UNICOS7x - if (secflag) { - if (setulvl(sysv.sy_minlvl) < 0) - return(-1); - if (setucmp(0) < 0) - return(-1); - } -#endif /* UNICOS7x */ + t = open(line, O_RDWR|O_NOCTTY); - if (t < 0) - return(-1); + if (t < 0) + return(-1); - /* - * Hangup anybody else using this ttyp, then reopen it for - * ourselves. - */ -# if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY) - (void) signal(SIGHUP, SIG_IGN); - vhangup(); - (void) signal(SIGHUP, SIG_DFL); - t = open(line, O_RDWR|O_NOCTTY); - if (t < 0) - return(-1); + /* + * Hangup anybody else using this ttyp, then reopen it for + * ourselves. + */ +# if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY) + signal(SIGHUP, SIG_IGN); +#ifdef HAVE_VHANGUP + vhangup(); +#else +#endif + signal(SIGHUP, SIG_DFL); + t = open(line, O_RDWR|O_NOCTTY); + if (t < 0) + return(-1); # endif -# if defined(CRAY) && defined(TCVHUP) - { - register int i; - (void) signal(SIGHUP, SIG_IGN); - (void) ioctl(t, TCVHUP, (char *)0); - (void) signal(SIGHUP, SIG_DFL); - -#ifdef UNICOS7x - if (secflag) { - if (secstat(line, &secbuf) < 0) - return(-1); - if (setulvl(secbuf.st_slevel) < 0) - return(-1); - if (setucmp(secbuf.st_compart) < 0) - return(-1); - } -#endif /* UNICOS7x */ - - i = open(line, O_RDWR); - -#ifdef UNICOS7x - if (secflag) { - if (setulvl(sysv.sy_minlvl) < 0) - return(-1); - if (setucmp(0) < 0) - return(-1); - } -#endif /* UNICOS7x */ - - if (i < 0) - return(-1); - (void) close(t); - t = i; - } +# if defined(_CRAY) && defined(TCVHUP) + { + int i; + signal(SIGHUP, SIG_IGN); + ioctl(t, TCVHUP, (char *)0); + signal(SIGHUP, SIG_DFL); + + i = open(line, O_RDWR); + + if (i < 0) + return(-1); + close(t); + t = i; + } # endif /* defined(CRAY) && defined(TCVHUP) */ - return(t); + return(t); } -#endif /* !defined(CRAY) || !defined(NEWINIT) */ -#if BSD <= 43 +#if !defined(BSD4_4) - int -login_tty(t) - int t; +int login_tty(int t) { - if (setsid() < 0) { -#ifdef ultrix - /* - * The setsid() may have failed because we - * already have a pgrp == pid. Zero out - * our pgrp and try again... - */ - if ((setpgrp(0, 0) < 0) || (setsid() < 0)) -#endif - fatalperror(net, "setsid()"); - } -# ifdef TIOCSCTTY - if (ioctl(t, TIOCSCTTY, (char *)0) < 0) - fatalperror(net, "ioctl(sctty)"); -# if defined(CRAY) - /* - * Close the hard fd to /dev/ttypXXX, and re-open through - * the indirect /dev/tty interface. - */ - close(t); - if ((t = open("/dev/tty", O_RDWR)) < 0) - fatalperror(net, "open(/dev/tty)"); +# if defined(TIOCSCTTY) && !defined(__hpux) + if (ioctl(t, TIOCSCTTY, (char *)0) < 0) + fatalperror(net, "ioctl(sctty)"); +# ifdef _CRAY + /* + * Close the hard fd to /dev/ttypXXX, and re-open through + * the indirect /dev/tty interface. + */ + close(t); + if ((t = open("/dev/tty", O_RDWR)) < 0) + fatalperror(net, "open(/dev/tty)"); # endif # else - /* - * We get our controlling tty assigned as a side-effect - * of opening up a tty device. But on BSD based systems, - * this only happens if our process group is zero. The - * setsid() call above may have set our pgrp, so clear - * it out before opening the tty... - */ -# ifndef SOLARIS - (void) setpgrp(0, 0); -# else - (void) setpgrp(); -# endif - close(open(line, O_RDWR)); + /* + * We get our controlling tty assigned as a side-effect + * of opening up a tty device. But on BSD based systems, + * this only happens if our process group is zero. The + * setsid() call above may have set our pgrp, so clear + * it out before opening the tty... + */ +#ifdef HAVE_SETPGID + setpgid(0, 0); +#else + setpgrp(0, 0); /* if setpgid isn't available, setpgrp + probably takes arguments */ +#endif + close(open(line, O_RDWR)); # endif - if (t != 0) - (void) dup2(t, 0); - if (t != 1) - (void) dup2(t, 1); - if (t != 2) - (void) dup2(t, 2); - if (t > 2) - close(t); - return(0); + if (t != 0) + dup2(t, 0); + if (t != 1) + dup2(t, 1); + if (t != 2) + dup2(t, 2); + if (t > 2) + close(t); + return(0); } #endif /* BSD <= 43 */ -#ifdef NEWINIT -char *gen_id = "fe"; +/* + * This comes from ../../bsd/tty.c and should not really be here. + */ + +/* + * Clean the tty name. Return a pointer to the cleaned version. + */ + +static char * +clean_ttyname (char *tty) +{ + char *res = tty; + + if (strncmp (res, _PATH_DEV, strlen(_PATH_DEV)) == 0) + res += strlen(_PATH_DEV); + if (strncmp (res, "pty/", 4) == 0) + res += 4; + if (strncmp (res, "ptym/", 5) == 0) + res += 5; + return res; +} + +/* + * Generate a name usable as an `ut_id', typically without `tty'. + */ + +#ifdef HAVE_STRUCT_UTMP_UT_ID +static char * +make_id (char *tty) +{ + char *res = tty; + + if (strncmp (res, "pts/", 4) == 0) + res += 4; + if (strncmp (res, "tty", 3) == 0) + res += 3; + return res; +} #endif /* @@ -1386,159 +1109,156 @@ char *gen_id = "fe"; */ /* ARGSUSED */ - void -startslave(host, autologin, autoname) - char *host; - int autologin; - char *autoname; +void +startslave(const char *host, const char *utmp_host, + int autologin, char *autoname) { - register int i; -#ifdef NEWINIT - extern char *ptyip; - struct init_request request; - void nologinproc(); - register int n; -#endif /* NEWINIT */ - -#if defined(AUTHENTICATION) - if (!autoname || !autoname[0]) - autologin = 0; - - if (autologin < auth_level) { - fatal(net, "Authorization failed"); - exit(1); - } -#endif + int i; -#ifndef NEWINIT +#ifdef AUTHENTICATION + if (!autoname || !autoname[0]) + autologin = 0; + + if (autologin < auth_level) { + fatal(net, "Authorization failed"); + exit(1); + } +#endif # ifdef PARENT_DOES_UTMP - utmp_sig_init(); + utmp_sig_init(); # endif /* PARENT_DOES_UTMP */ - if ((i = fork()) < 0) - fatalperror(net, "fork"); - if (i) { + if ((i = fork()) < 0) + fatalperror(net, "fork"); + if (i) { # ifdef PARENT_DOES_UTMP - /* - * Cray parent will create utmp entry for child and send - * signal to child to tell when done. Child waits for signal - * before doing anything important. - */ - register int pid = i; - void sigjob P((int)); - - setpgrp(); - utmp_sig_reset(); /* reset handler to default */ - /* - * Create utmp entry for child - */ - (void) time(&wtmp.ut_time); - wtmp.ut_type = LOGIN_PROCESS; - wtmp.ut_pid = pid; - SCPYN(wtmp.ut_user, "LOGIN"); - SCPYN(wtmp.ut_host, host); - SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); -#ifndef __hpux - SCPYN(wtmp.ut_id, wtmp.ut_line+3); -#else - SCPYN(wtmp.ut_id, wtmp.ut_line+7); -#endif - pututline(&wtmp); - endutent(); - if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { - (void) write(i, (char *)&wtmp, sizeof(struct utmp)); - (void) close(i); - } -#ifdef CRAY - (void) signal(WJSIGNAL, sigjob); -#endif - utmp_sig_notify(pid); -# endif /* PARENT_DOES_UTMP */ - } else { - getptyslave(autologin); - start_login(host, autologin, autoname); - /*NOTREACHED*/ - } -#else /* NEWINIT */ - /* - * Init will start up login process if we ask nicely. We only wait - * for it to start up and begin normal telnet operation. + * Cray parent will create utmp entry for child and send + * signal to child to tell when done. Child waits for signal + * before doing anything important. */ - if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { - char tbuf[128]; - (void) snprintf(tbuf, sizeof tbuf, "Can't open %s\n", INIT_FIFO); - fatalperror(net, tbuf); - } - memset((void *)&request, 0, sizeof(request)); - request.magic = INIT_MAGIC; - SCPYN(request.gen_id, gen_id); - SCPYN(request.tty_id, &line[8]); - SCPYN(request.host, host); - SCPYN(request.term_type, terminaltype ? terminaltype : "network"); -#if !defined(UNICOS5) - request.signal = SIGCLD; - request.pid = getpid(); -#endif -#ifdef BFTPDAEMON + int pid = i; + void sigjob (int); + + setpgrp(); + utmp_sig_reset(); /* reset handler to default */ /* - * Are we working as the bftp daemon? + * Create utmp entry for child */ - if (bftpd) { - SCPYN(request.exec_name, BFTPPATH); + wtmp.ut_time = time(NULL); + wtmp.ut_type = LOGIN_PROCESS; + wtmp.ut_pid = pid; + strncpy(wtmp.ut_user, "LOGIN", sizeof(wtmp.ut_user)); + strncpy(wtmp.ut_host, utmp_host, sizeof(wtmp.ut_host)); + strncpy(wtmp.ut_line, clean_ttyname(line), sizeof(wtmp.ut_line)); +#ifdef HAVE_STRUCT_UTMP_UT_ID + strncpy(wtmp.ut_id, wtmp.ut_line + 3, sizeof(wtmp.ut_id)); +#endif + + pututline(&wtmp); + endutent(); + if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { + write(i, &wtmp, sizeof(struct utmp)); + close(i); } -#endif /* BFTPDAEMON */ - if (write(i, (char *)&request, sizeof(request)) < 0) { - char tbuf[128]; - (void) snprintf(tbuf, sizeof tbuf, "Can't write to %s\n", INIT_FIFO); - fatalperror(net, tbuf); - } - (void) close(i); - (void) signal(SIGALRM, nologinproc); - for (i = 0; ; i++) { - char tbuf[128]; - alarm(15); - n = read(pty, ptyip, BUFSIZ); - if (i == 3 || n >= 0 || !gotalarm) - break; - gotalarm = 0; - snprintf(tbuf, sizeof tbuf, - "telnetd: waiting for /etc/init to start login process on %s\r\n", - line); - (void) write(net, tbuf, strlen(tbuf)); - } - if (n < 0 && gotalarm) - fatal(net, "/etc/init didn't start login process"); - pcc += n; - alarm(0); - (void) signal(SIGALRM, SIG_DFL); - - return; -#endif /* NEWINIT */ +#ifdef _CRAY + signal(WJSIGNAL, sigjob); +#endif + utmp_sig_notify(pid); +# endif /* PARENT_DOES_UTMP */ + } else { + getptyslave(); +#if defined(DCE) + /* if we authenticated via K5, try and join the PAG */ + kerberos5_dfspag(); +#endif + start_login(host, autologin, autoname); + /*NOTREACHED*/ + } } char *envinit[3]; extern char **environ; - void -init_env() +void +init_env(void) { - extern char *getenv(); - char **envp; + char **envp; - envp = envinit; - if ((*envp = getenv("TZ"))) - *envp++ -= 3; -#if defined(CRAY) || defined(__hpux) - else - *envp++ = "TZ=GMT0"; + envp = envinit; + if ((*envp = getenv("TZ"))) + *envp++ -= 3; +#if defined(_CRAY) || defined(__hpux) + else + *envp++ = "TZ=GMT0"; #endif - *envp = 0; - environ = envinit; + *envp = 0; + environ = envinit; } -#ifndef NEWINIT +/* We won't agree with the Heimdal people about the right way to check for + * bad environment variables, so we don't use this code. + * See envvarok() in state.c instead. + */ +#if 0 +/* + * scrub_env() + * + * We only accept the environment variables listed below. + */ + +static void +scrub_env(void) +{ + static const char *reject[] = { + "TERMCAP=/", + NULL + }; + + static const char *accept[] = { + "XAUTH=", "XAUTHORITY=", "DISPLAY=", + "TERM=", + "EDITOR=", + "PAGER=", + "PRINTER=", + "LOGNAME=", + "POSIXLY_CORRECT=", + "TERMCAP=", + NULL + }; + + char **cpp, **cpp2; + const char **p; + + for (cpp2 = cpp = environ; *cpp; cpp++) { + int reject_it = 0; + + for(p = reject; *p; p++) + if(strncmp(*cpp, *p, strlen(*p)) == 0) { + reject_it = 1; + break; + } + if (reject_it) + continue; + + for(p = accept; *p; p++) + if(strncmp(*cpp, *p, strlen(*p)) == 0) + break; + if(*p != NULL) + *cpp2++ = *cpp; + } + *cpp2 = NULL; +} +#endif + +struct arg_val { + int size; + int argc; + const char **argv; +}; + +static void addarg(struct arg_val*, const char*); /* * start_login(host) @@ -1547,315 +1267,298 @@ init_env() * function will turn us into the login process. */ - void -start_login(host, autologin, name) - char *host; - int autologin; - char *name; +void +start_login(const char *host, int autologin, char *name) { - register char **argv; - char **addarg(); - extern char *getenv(); - extern char *gettyname; -#define TABBUFSIZ 512 - char defent[TABBUFSIZ]; - char defstrs[TABBUFSIZ]; -#undef TABBUFSIZ - char *loginprog = NULL; -#ifdef UTMPX - register int pid = getpid(); - struct utmpx utmpx; -#endif -#ifdef SOLARIS - char *term; - char termbuf[64]; -#endif - -#ifdef UTMPX - /* - * Create utmp entry for child - */ + struct arg_val argv; + char *user; + int save_errno; - memset((void *)&utmpx, 0, sizeof(utmpx)); - SCPYN(utmpx.ut_user, ".telnet"); - SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); - utmpx.ut_pid = pid; - utmpx.ut_id[0] = 't'; - utmpx.ut_id[1] = 'n'; - utmpx.ut_id[2] = SC_WILDC; - utmpx.ut_id[3] = SC_WILDC; - utmpx.ut_type = LOGIN_PROCESS; - (void) time(&utmpx.ut_tv.tv_sec); - if (makeutx(&utmpx) == NULL) - fatal(net, "makeutx failed"); -#endif - - scrub_env(); - - /* - * -h : pass on name of host. - * WARNING: -h is accepted by login if and only if - * getuid() == 0. - * -p : don't clobber the environment (so terminal type stays set). - * - * -f : force this login, he has already been authenticated - */ - argv = addarg(0, "login"); +#ifdef HAVE_UTMPX_H + int pid = getpid(); + struct utmpx utmpx; + char *clean_tty; -#if !defined(NO_LOGIN_H) + /* + * Create utmp entry for child + */ -# if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) - /* - * Don't add the "-h host" option if we are going - * to be adding the "-r host" option down below... - */ - if ((auth_level < 0) || (autologin != AUTH_VALID)) -# endif - { - argv = addarg(argv, "-h"); - argv = addarg(argv, host); -#ifdef SOLARIS - /* - * SVR4 version of -h takes TERM= as second arg, or - - */ - term = getenv("TERM"); - if (term == NULL || term[0] == 0) { - term = "-"; - } else { - strcpy(termbuf, "TERM="); - strncat(termbuf, term, sizeof(termbuf) - 6); - term = termbuf; - } - argv = addarg(argv, term); -#endif - } + clean_tty = clean_ttyname(line); + memset(&utmpx, 0, sizeof(utmpx)); + strncpy(utmpx.ut_user, ".telnet", sizeof(utmpx.ut_user)); + strncpy(utmpx.ut_line, clean_tty, sizeof(utmpx.ut_line)); +#ifdef HAVE_STRUCT_UTMP_UT_ID + strncpy(utmpx.ut_id, make_id(clean_tty), sizeof(utmpx.ut_id)); #endif -#if !defined(NO_LOGIN_P) - argv = addarg(argv, "-p"); -#endif -#ifdef LINEMODE - /* - * Set the environment variable "LINEMODE" to either - * "real" or "kludge" if we are operating in either - * real or kludge linemode. - */ - if (lmodetype == REAL_LINEMODE) - setenv("LINEMODE", "real", 1); /* XXX mem */ -# ifdef KLUDGELINEMODE - else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK) - setenv("LINEMODE", "kludge", 1); /* XXX mem */ -# endif -#endif -#ifdef BFTPDAEMON - /* - * Are we working as the bftp daemon? If so, then ask login - * to start bftp instead of shell. - */ - if (bftpd) { - argv = addarg(argv, "-e"); - argv = addarg(argv, BFTPPATH); - } else -#endif -#if defined (AUTHENTICATION) - if (auth_level >= 0 && autologin == AUTH_VALID) { -# if !defined(NO_LOGIN_F) - argv = addarg(argv, "-f"); - argv = addarg(argv, "--"); - argv = addarg(argv, name); -# else -# if defined(LOGIN_R) - /* - * We don't have support for "login -f", but we - * can fool /bin/login into thinking that we are - * rlogind, and allow us to log in without a - * password. The rlogin protocol expects - * local-user\0remote-user\0term/speed\0 - */ - - if (pty > 2) { - register char *cp; - char speed[128]; - int isecho, israw, xpty, len; - extern int def_rspeed; -# ifndef LOGIN_HOST - /* - * Tell login that we are coming from "localhost". - * If we passed in the real host name, then the - * user would have to allow .rhost access from - * every machine that they want authenticated - * access to work from, which sort of defeats - * the purpose of an authenticated login... - * So, we tell login that the session is coming - * from "localhost", and the user will only have - * to have "localhost" in their .rhost file. - */ -# define LOGIN_HOST "localhost" -# endif - argv = addarg(argv, "-r"); - argv = addarg(argv, LOGIN_HOST); - - xpty = pty; -# ifndef STREAMSPTY - pty = 0; -# else - ttyfd = 0; -# endif - init_termbuf(); - isecho = tty_isecho(); - israw = tty_israw(); - if (isecho || !israw) { - tty_setecho(0); /* Turn off echo */ - tty_setraw(1); /* Turn on raw */ - set_termbuf(); - } - len = strlen(name)+1; - write(xpty, name, len); - write(xpty, name, len); - snprintf(speed, sizeof speed, - "%s/%d", (cp = getenv("TERM")) ? cp : "", - (def_rspeed > 0) ? def_rspeed : 9600); - len = strlen(speed)+1; - write(xpty, speed, len); - - if (isecho || !israw) { - init_termbuf(); - tty_setecho(isecho); - tty_setraw(israw); - set_termbuf(); - if (!israw) { - /* - * Write a newline to ensure - * that login will be able to - * read the line... - */ - write(xpty, "\n", 1); - } - } - pty = xpty; - } -# else - argv = addarg(argv, "--"); - argv = addarg(argv, name); -# endif -# endif - } else -#endif - if (getenv("USER")) { - argv = addarg(argv, "--"); - argv = addarg(argv, getenv("USER")); -#if defined(LOGIN_ARGS) && defined(NO_LOGIN_P) - { - register char **cpp; - for (cpp = environ; *cpp; cpp++) - argv = addarg(argv, *cpp); - } -#endif - /* - * Assume that login will set the USER variable - * correctly. For SysV systems, this means that - * USER will no longer be set, just LOGNAME by - * login. (The problem is that if the auto-login - * fails, and the user then specifies a different - * account name, he can get logged in with both - * LOGNAME and USER in his environment, but the - * USER value will be wrong. - */ - unsetenv("USER"); - } -#ifdef SOLARIS - else { - char **p; + utmpx.ut_pid = pid; + + utmpx.ut_type = LOGIN_PROCESS; - argv = addarg(argv, ""); /* no login name */ - for (p = environ; *p; p++) { - argv = addarg(argv, *p); - } - } -#endif /* SOLARIS */ -#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) - if (pty > 2) - close(pty); + gettimeofday (&utmpx.ut_tv, NULL); + if (pututxline(&utmpx) == NULL) + fatal(net, "pututxline failed"); #endif - if (gtgetent(defent, gettyname) == 1) { - char *cp = defstrs; - loginprog = gtgetstr("lo", &cp); +#if 0 + scrub_env(); +#endif + /* + * -h : pass on name of host. + * WARNING: -h is accepted by login if and only if + * getuid() == 0. + * -p : don't clobber the environment (so terminal type stays set). + * + * -f : force this login, he has already been authenticated + */ + + /* init argv structure */ + argv.size=0; + argv.argc=0; + argv.argv=malloc(0); /*so we can call realloc later */ + addarg(&argv, "login"); + addarg(&argv, "-h"); + addarg(&argv, host); + addarg(&argv, "-p"); + if(name[0]) + user = name; + else + user = getenv("USER"); +#ifdef AUTHENTICATION + if (auth_level < 0 || autologin != AUTH_VALID) { + if(!no_warn) { + printf("User not authenticated. "); + if (require_otp) + printf("Using one-time password\r\n"); + else + printf("Using plaintext username and password\r\n"); + } + if (require_otp) { + addarg(&argv, "-a"); + addarg(&argv, "otp"); } - if (loginprog == NULL) - loginprog = _PATH_LOGIN; - closelog(); + if(log_unauth) + syslog(LOG_INFO, "unauthenticated access from %s (%s)", + host, user ? user : "unknown user"); + } + if (auth_level >= 0 && autologin == AUTH_VALID) + addarg(&argv, "-f"); +#endif + if(user){ + addarg(&argv, "--"); + addarg(&argv, strdup(user)); + } + if (getenv("USER")) { /* - * This sleep(1) is in here so that telnetd can - * finish up with the tty. There's a race condition - * the login banner message gets lost... + * Assume that login will set the USER variable + * correctly. For SysV systems, this means that + * USER will no longer be set, just LOGNAME by + * login. (The problem is that if the auto-login + * fails, and the user then specifies a different + * account name, he can get logged in with both + * LOGNAME and USER in his environment, but the + * USER value will be wrong. */ - sleep(1); - execv(loginprog, argv); - - syslog(LOG_ERR, "%s: %m", loginprog); - fatalperror(net, loginprog); - /*NOTREACHED*/ + unsetenv("USER"); + } + closelog(); + /* + * This sleep(1) is in here so that telnetd can + * finish up with the tty. There's a race condition + * the login banner message gets lost... + */ + sleep(1); + + execv(new_login, argv.argv); + save_errno = errno; + syslog(LOG_ERR, "%s: %m\n", new_login); + fatalperror_errno(net, new_login, save_errno); + /*NOTREACHED*/ } - char ** -addarg(argv, val) - register char **argv; - register char *val; +static void +addarg(struct arg_val *argv, const char *val) { - register char **cpp; - - if (argv == NULL) { - /* - * 10 entries, a leading length, and a null - */ - argv = (char **)malloc(sizeof(*argv) * 12); - if (argv == NULL) - return(NULL); - *argv++ = (char *)10; - *argv = (char *)0; - } - for (cpp = argv; *cpp; cpp++) - ; - if (cpp == &argv[(long)argv[-1]]) { - --argv; - *argv = (char *)((long)(*argv) + 10); - argv = (char **)realloc(argv, sizeof(*argv)*((long)(*argv) + 2)); - if (argv == NULL) - return(NULL); - argv++; - cpp = &argv[(long)argv[-1] - 10]; - } - *cpp++ = val; - *cpp = 0; - return(argv); + if(argv->size <= argv->argc+1) { + argv->argv = realloc(argv->argv, sizeof(char*) * (argv->size + 10)); + if (argv->argv == NULL) + fatal (net, "realloc: out of memory"); + argv->size+=10; + } + argv->argv[argv->argc++] = val; + argv->argv[argv->argc] = NULL; } -#endif /* NEWINIT */ + /* - * scrub_env() + * rmut() * - * Remove a few things from the environment that - * don't need to be there. + * This is the function called by cleanup() to + * remove the utmp entry for this person. */ - void -scrub_env() + +#ifdef HAVE_UTMPX_H +static void +rmut(void) +{ + struct utmpx utmpx, *non_save_utxp; + char *clean_tty = clean_ttyname(line); + + /* + * This updates the utmpx and utmp entries and make a wtmp/x entry + */ + + setutxent(); + memset(&utmpx, 0, sizeof(utmpx)); + strncpy(utmpx.ut_line, clean_tty, sizeof(utmpx.ut_line)); + utmpx.ut_type = LOGIN_PROCESS; + non_save_utxp = getutxline(&utmpx); + if (non_save_utxp) { + struct utmpx *utxp; + char user0; + + utxp = malloc(sizeof(struct utmpx)); + *utxp = *non_save_utxp; + user0 = utxp->ut_user[0]; + utxp->ut_user[0] = '\0'; + utxp->ut_type = DEAD_PROCESS; +#ifdef HAVE_STRUCT_UTMPX_UT_EXIT +#ifdef _STRUCT___EXIT_STATUS + utxp->ut_exit.__e_termination = 0; + utxp->ut_exit.__e_exit = 0; +#elif defined(__osf__) /* XXX */ + utxp->ut_exit.ut_termination = 0; + utxp->ut_exit.ut_exit = 0; +#else + utxp->ut_exit.e_termination = 0; + utxp->ut_exit.e_exit = 0; +#endif +#endif + gettimeofday(&utxp->ut_tv, NULL); + pututxline(utxp); +#ifdef WTMPX_FILE + utxp->ut_user[0] = user0; + updwtmpx(WTMPX_FILE, utxp); +#elif defined(WTMP_FILE) + /* This is a strange system with a utmpx and a wtmp! */ + { + int f = open(wtmpf, O_WRONLY|O_APPEND); + struct utmp wtmp; + if (f >= 0) { + strncpy(wtmp.ut_line, clean_tty, sizeof(wtmp.ut_line)); + strncpy(wtmp.ut_name, "", sizeof(wtmp.ut_name)); +#ifdef HAVE_STRUCT_UTMP_UT_HOST + strncpy(wtmp.ut_host, "", sizeof(wtmp.ut_host)); +#endif + wtmp.ut_time = time(NULL); + write(f, &wtmp, sizeof(wtmp)); + close(f); + } + } +#endif + free (utxp); + } + endutxent(); +} /* end of rmut */ +#endif + +#if !defined(HAVE_UTMPX_H) && !(defined(_CRAY) || defined(__hpux)) +static void +rmut(void) +{ + int f; + int found = 0; + struct utmp *u, *utmp; + int nutmp; + struct stat statbf; + char *clean_tty = clean_ttyname(line); + + f = open(utmpf, O_RDWR); + if (f >= 0) { + fstat(f, &statbf); + utmp = (struct utmp *)malloc((unsigned)statbf.st_size); + if (!utmp) + syslog(LOG_ERR, "utmp malloc failed"); + if (statbf.st_size && utmp) { + nutmp = read(f, utmp, (int)statbf.st_size); + nutmp /= sizeof(struct utmp); + + for (u = utmp ; u < &utmp[nutmp] ; u++) { + if (strncmp(u->ut_line, + clean_tty, + sizeof(u->ut_line)) || + u->ut_name[0]==0) + continue; + lseek(f, ((long)u)-((long)utmp), L_SET); + strncpy(u->ut_name, "", sizeof(u->ut_name)); +#ifdef HAVE_STRUCT_UTMP_UT_HOST + strncpy(u->ut_host, "", sizeof(u->ut_host)); +#endif + u->ut_time = time(NULL); + write(f, u, sizeof(wtmp)); + found++; + } + } + close(f); + } + if (found) { + f = open(wtmpf, O_WRONLY|O_APPEND); + if (f >= 0) { + strncpy(wtmp.ut_line, clean_tty, sizeof(wtmp.ut_line)); + strncpy(wtmp.ut_name, "", sizeof(wtmp.ut_name)); +#ifdef HAVE_STRUCT_UTMP_UT_HOST + strncpy(wtmp.ut_host, "", sizeof(wtmp.ut_host)); +#endif + wtmp.ut_time = time(NULL); + write(f, &wtmp, sizeof(wtmp)); + close(f); + } + } + chmod(line, 0666); + chown(line, 0, 0); + line[strlen("/dev/")] = 'p'; + chmod(line, 0666); + chown(line, 0, 0); +} /* end of rmut */ +#endif /* CRAY */ + +#if defined(__hpux) && !defined(HAVE_UTMPX_H) +static void +rmut (char *line) { - register char **cpp, **cpp2; - - for (cpp2 = cpp = environ; *cpp; cpp++) { - if (strncmp(*cpp, "LD_", 3) && - strncmp(*cpp, "_RLD_", 5) && - strncmp(*cpp, "LIBPATH=", 8) && - strncmp(*cpp, "TERMINFO=", 9) && - strncmp(*cpp, "TERMINFO_DIRS=", 14) && - strncmp(*cpp, "TERMPATH=", 9) && - strncmp(*cpp, "TERMCAP=/", 9) && - strncmp(*cpp, "ENV=", 4) && - strncmp(*cpp, "IFS=", 4)) - *cpp2++ = *cpp; + struct utmp utmp; + struct utmp *utptr; + int fd; /* for /etc/wtmp */ + + utmp.ut_type = USER_PROCESS; + strncpy(utmp.ut_line, clean_ttyname(line), sizeof(utmp.ut_line)); + setutent(); + utptr = getutline(&utmp); + /* write it out only if it exists */ + if (utptr) { + utptr->ut_type = DEAD_PROCESS; + utptr->ut_time = time(NULL); + pututline(utptr); + /* set wtmp entry if wtmp file exists */ + if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) { + write(fd, utptr, sizeof(utmp)); + close(fd); } - *cpp2 = 0; + } + endutent(); + + chmod(line, 0666); + chown(line, 0, 0); + line[14] = line[13]; + line[13] = line[12]; + line[8] = 'm'; + line[9] = '/'; + line[10] = 'p'; + line[11] = 't'; + line[12] = 'y'; + chmod(line, 0666); + chown(line, 0, 0); } +#endif /* * cleanup() @@ -1863,99 +1566,90 @@ scrub_env() * This is the routine to call when we are all through, to * clean up anything that needs to be cleaned up. */ - /* ARGSUSED */ - void -cleanup(sig) - int sig; -{ -#ifndef PARENT_DOES_UTMP -# if (BSD > 43) || defined(convex) - char *p; - - p = line + sizeof("/dev/") - 1; - if (logout(p)) - logwtmp(p, "", ""); - (void)chmod(line, 0666); - (void)chown(line, 0, 0); - *p = 'p'; - (void)chmod(line, 0666); - (void)chown(line, 0, 0); - (void) shutdown(net, 2); - _exit(1); -# else - void rmut(); - rmut(); - vhangup(); /* XXX */ - (void) shutdown(net, 2); - _exit(1); -# endif -#else /* PARENT_DOES_UTMP */ -# ifdef NEWINIT - (void) shutdown(net, 2); - _exit(1); -# else /* NEWINIT */ -# ifdef CRAY - static int incleanup = 0; - register int t; - int child_status; /* status of child process as returned by waitpid */ - int flags = WNOHANG|WUNTRACED; +#ifdef PARENT_DOES_UTMP - /* - * 1: Pick up the zombie, if we are being called - * as the signal handler. - * 2: If we are a nested cleanup(), return. - * 3: Try to clean up TMPDIR. - * 4: Fill in utmp with shutdown of process. - * 5: Close down the network and pty connections. - * 6: Finish up the TMPDIR cleanup, if needed. +void +cleanup(int sig) +{ +#ifdef _CRAY + static int incleanup = 0; + int t; + int child_status; /* status of child process as returned by waitpid */ + int flags = WNOHANG|WUNTRACED; + + /* + * 1: Pick up the zombie, if we are being called + * as the signal handler. + * 2: If we are a nested cleanup(), return. + * 3: Try to clean up TMPDIR. + * 4: Fill in utmp with shutdown of process. + * 5: Close down the network and pty connections. + * 6: Finish up the TMPDIR cleanup, if needed. + */ + if (sig == SIGCHLD) { + while (waitpid(-1, &child_status, flags) > 0) + ; /* VOID */ + /* Check if the child process was stopped + * rather than exited. We want cleanup only if + * the child has died. */ - if (sig == SIGCHLD) { - while (waitpid(-1, &child_status, flags) > 0) - ; /* VOID */ - /* Check if the child process was stopped - * rather than exited. We want cleanup only if - * the child has died. - */ - if (WIFSTOPPED(child_status)) { - return; - } + if (WIFSTOPPED(child_status)) { + return; } - t = sigblock(sigmask(SIGCHLD)); - if (incleanup) { - sigsetmask(t); - return; - } - incleanup = 1; + } + t = sigblock(sigmask(SIGCHLD)); + if (incleanup) { sigsetmask(t); -#ifdef UNICOS7x - if (secflag) { - /* - * We need to set ourselves back to a null - * label to clean up. - */ - - setulvl(sysv.sy_minlvl); - setucmp((long)0); - } -#endif /* UNICOS7x */ - - t = cleantmp(&wtmp); - setutent(); /* just to make sure */ -# endif /* CRAY */ - rmut(line); - close(pty); - (void) shutdown(net, 2); -# ifdef CRAY - if (t == 0) - cleantmp(&wtmp); -# endif /* CRAY */ - _exit(1); -# endif /* NEWINT */ -#endif /* PARENT_DOES_UTMP */ + return; + } + incleanup = 1; + sigsetmask(t); + + t = cleantmp(&wtmp); + setutent(); /* just to make sure */ +#endif /* CRAY */ + rmut(line); + close(ourpty); + shutdown(net, 2); +#ifdef _CRAY + if (t == 0) + cleantmp(&wtmp); +#endif /* CRAY */ + exit(1); } -#if defined(PARENT_DOES_UTMP) && !defined(NEWINIT) +#else /* PARENT_DOES_UTMP */ + +void +cleanup(int sig) +{ +#if defined(HAVE_UTMPX_H) || !defined(HAVE_LOGWTMP) + rmut(); +#ifdef HAVE_VHANGUP +#ifndef __sgi + vhangup(); /* XXX */ +#endif +#endif +#else + char *p; + + p = line + sizeof("/dev/") - 1; + if (logout(p)) + logwtmp(p, "", ""); + chmod(line, 0666); + chown(line, 0, 0); + *p = 'p'; + chmod(line, 0666); + chown(line, 0, 0); +#endif + shutdown(net, 2); + exit(1); +} + +#endif /* PARENT_DOES_UTMP */ + +#ifdef PARENT_DOES_UTMP /* * _utmp_sig_rcv * utmp_sig_init @@ -1969,28 +1663,28 @@ cleanup(sig) static int caught=0; /* NZ when signal intercepted */ static void (*func)(); /* address of previous handler */ - void +void _utmp_sig_rcv(sig) - int sig; + int sig; { - caught = 1; - (void) signal(SIGUSR1, func); + caught = 1; + signal(SIGUSR1, func); } - void +void utmp_sig_init() { - /* - * register signal handler for UTMP creation - */ - if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) - fatalperror(net, "telnetd/signal"); + /* + * register signal handler for UTMP creation + */ + if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) + fatalperror(net, "telnetd/signal"); } - void +void utmp_sig_reset() { - (void) signal(SIGUSR1, func); /* reset handler to default */ + signal(SIGUSR1, func); /* reset handler to default */ } # ifdef __hpux @@ -1998,44 +1692,44 @@ utmp_sig_reset() # define sigon() /* do nothing */ # endif - void +void utmp_sig_wait() { - /* - * Wait for parent to write our utmp entry. + /* + * Wait for parent to write our utmp entry. */ - sigoff(); - while (caught == 0) { - pause(); /* wait until we get a signal (sigon) */ - sigoff(); /* turn off signals while we check caught */ - } - sigon(); /* turn on signals again */ + sigoff(); + while (caught == 0) { + pause(); /* wait until we get a signal (sigon) */ + sigoff(); /* turn off signals while we check caught */ + } + sigon(); /* turn on signals again */ } - void +void utmp_sig_notify(pid) { - kill(pid, SIGUSR1); + kill(pid, SIGUSR1); } -# ifdef CRAY +#ifdef _CRAY static int gotsigjob = 0; /*ARGSUSED*/ - void +void sigjob(sig) - int sig; + int sig; { - register int jid; - register struct jobtemp *jp; - - while ((jid = waitjob(NULL)) != -1) { - if (jid == 0) { - return; - } - gotsigjob++; - jobend(jid, NULL, NULL); + int jid; + struct jobtemp *jp; + + while ((jid = waitjob(NULL)) != -1) { + if (jid == 0) { + return; } + gotsigjob++; + jobend(jid, NULL, NULL); + } } /* @@ -2044,20 +1738,20 @@ sigjob(sig) * to find the correct $TMPDIR to cleanup. */ - struct utmp * +struct utmp * jid_getutid(jid) - int jid; + int jid; { - struct utmp *cur = NULL; + struct utmp *cur = NULL; - setutent(); /* just to make sure */ - while (cur = getutent()) { - if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) { - return(cur); - } + setutent(); /* just to make sure */ + while (cur = getutent()) { + if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) { + return(cur); } + } - return(0); + return(0); } /* @@ -2068,260 +1762,132 @@ jid_getutid(jid) * when this is called the second time it will wait * for the signal that the job is done. */ - int +int cleantmp(wtp) - register struct utmp *wtp; + struct utmp *wtp; { - struct utmp *utp; - static int first = 1; - register int mask, omask, ret; - extern struct utmp *getutid P((const struct utmp *_Id)); + struct utmp *utp; + static int first = 1; + int mask, omask, ret; + extern struct utmp *getutid (const struct utmp *_Id); - mask = sigmask(WJSIGNAL); + mask = sigmask(WJSIGNAL); - if (first == 0) { - omask = sigblock(mask); - while (gotsigjob == 0) - sigpause(omask); - return(1); - } - first = 0; - setutent(); /* just to make sure */ + if (first == 0) { + omask = sigblock(mask); + while (gotsigjob == 0) + sigpause(omask); + return(1); + } + first = 0; + setutent(); /* just to make sure */ - utp = getutid(wtp); - if (utp == 0) { - syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); - return(-1); - } - /* - * Nothing to clean up if the user shell was never started. - */ - if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) - return(1); + utp = getutid(wtp); + if (utp == 0) { + syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); + return(-1); + } + /* + * Nothing to clean up if the user shell was never started. + */ + if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) + return(1); - /* - * Block the WJSIGNAL while we are in jobend(). - */ - omask = sigblock(mask); - ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); - sigsetmask(omask); - return(ret); + /* + * Block the WJSIGNAL while we are in jobend(). + */ + omask = sigblock(mask); + ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); + sigsetmask(omask); + return(ret); } - int +int jobend(jid, path, user) - register int jid; - register char *path; - register char *user; + int jid; + char *path; + char *user; { - static int saved_jid = 0; - static int pty_saved_jid = 0; - static char saved_path[sizeof(wtmp.ut_tpath)+1]; - static char saved_user[sizeof(wtmp.ut_user)+1]; - - /* - * this little piece of code comes into play - * only when ptyreconnect is used to reconnect - * to an previous session. - * - * this is the only time when the - * "saved_jid != jid" code is executed. - */ - - if ( saved_jid && saved_jid != jid ) { - if (!path) { /* called from signal handler */ - pty_saved_jid = jid; - } else { - pty_saved_jid = saved_jid; - } - } - - if (path) { - strlcpy(saved_path, path, sizeof(saved_path)); - strlcpy(saved_user, user, sizeof(saved_user)); - } - if (saved_jid == 0) { - saved_jid = jid; - return(0); + static int saved_jid = 0; + static int pty_saved_jid = 0; + static char saved_path[sizeof(wtmp.ut_tpath)+1]; + static char saved_user[sizeof(wtmp.ut_user)+1]; + + /* + * this little piece of code comes into play + * only when ptyreconnect is used to reconnect + * to an previous session. + * + * this is the only time when the + * "saved_jid != jid" code is executed. + */ + + if ( saved_jid && saved_jid != jid ) { + if (!path) { /* called from signal handler */ + pty_saved_jid = jid; + } else { + pty_saved_jid = saved_jid; } + } + + if (path) { + strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); + strncpy(saved_user, user, sizeof(wtmp.ut_user)); + saved_path[sizeof(saved_path)] = '\0'; + saved_user[sizeof(saved_user)] = '\0'; + } + if (saved_jid == 0) { + saved_jid = jid; + return(0); + } - /* if the jid has changed, get the correct entry from the utmp file */ - - if ( saved_jid != jid ) { - struct utmp *utp = NULL; - struct utmp *jid_getutid(); + /* if the jid has changed, get the correct entry from the utmp file */ - utp = jid_getutid(pty_saved_jid); + if ( saved_jid != jid ) { + struct utmp *utp = NULL; + struct utmp *jid_getutid(); - if (utp == 0) { - syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); - return(-1); - } + utp = jid_getutid(pty_saved_jid); - cleantmpdir(jid, utp->ut_tpath, utp->ut_user); - return(1); + if (utp == 0) { + syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); + return(-1); } - cleantmpdir(jid, saved_path, saved_user); + cleantmpdir(jid, utp->ut_tpath, utp->ut_user); return(1); + } + + cleantmpdir(jid, saved_path, saved_user); + return(1); } /* * Fork a child process to clean up the TMPDIR */ cleantmpdir(jid, tpath, user) - register int jid; - register char *tpath; - register char *user; + int jid; + char *tpath; + char *user; { - switch(fork()) { - case -1: - syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m", - tpath); - break; - case 0: - execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); - syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m", - tpath, CLEANTMPCMD); - exit(1); - default: - /* - * Forget about child. We will exit, and - * /etc/init will pick it up. - */ - break; - } -} -# endif /* CRAY */ -#endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */ - -/* - * rmut() - * - * This is the function called by cleanup() to - * remove the utmp entry for this person. - */ - -#ifdef UTMPX - void -rmut() -{ - register f; - int found = 0; - struct utmp *u, *utmp; - int nutmp; - struct stat statbf; - - struct utmpx *utxp, utmpx; - + switch(fork()) { + case -1: + syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n", + tpath); + break; + case 0: + execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); + syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", + tpath, CLEANTMPCMD); + exit(1); + default: /* - * This updates the utmpx and utmp entries and make a wtmp/x entry + * Forget about child. We will exit, and + * /etc/init will pick it up. */ - - SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); - utxp = getutxline(&utmpx); - if (utxp) { - utxp->ut_type = DEAD_PROCESS; - utxp->ut_exit.e_termination = 0; - utxp->ut_exit.e_exit = 0; - (void) time(&utmpx.ut_tv.tv_sec); - utmpx.ut_tv.tv_usec = 0; - modutx(utxp); - } - endutxent(); -} /* end of rmut */ -#endif - -#if !defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43 - void -rmut() -{ - register f; - int found = 0; - struct utmp *u, *utmp; - int nutmp; - struct stat statbf; - - f = open(utmpf, O_RDWR); - if (f >= 0) { - (void) fstat(f, &statbf); - utmp = (struct utmp *)malloc((unsigned)statbf.st_size); - if (!utmp) - syslog(LOG_ERR, "utmp malloc failed"); - if (statbf.st_size && utmp) { - nutmp = read(f, (char *)utmp, (int)statbf.st_size); - nutmp /= sizeof(struct utmp); - - for (u = utmp ; u < &utmp[nutmp] ; u++) { - if (SCMPN(u->ut_line, line+5) || - u->ut_name[0]==0) - continue; - (void) lseek(f, ((off_t)u)-((off_t)utmp), - SEEK_SET); - SCPYN(u->ut_name, ""); - SCPYN(u->ut_host, ""); - (void) time(&u->ut_time); - (void) write(f, (char *)u, sizeof(wtmp)); - found++; - } - } - (void) close(f); - } - if (found) { - f = open(wtmpf, O_WRONLY|O_APPEND); - if (f >= 0) { - SCPYN(wtmp.ut_line, line+5); - SCPYN(wtmp.ut_name, ""); - SCPYN(wtmp.ut_host, ""); - (void) time(&wtmp.ut_time); - (void) write(f, (char *)&wtmp, sizeof(wtmp)); - (void) close(f); - } - } - (void) chmod(line, 0666); - (void) chown(line, 0, 0); - line[strlen("/dev/")] = 'p'; - (void) chmod(line, 0666); - (void) chown(line, 0, 0); -} /* end of rmut */ -#endif /* CRAY */ - -#ifdef __hpux -rmut (line) -char *line; -{ - struct utmp utmp; - struct utmp *utptr; - int fd; /* for /etc/wtmp */ - - utmp.ut_type = USER_PROCESS; - (void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id)); - (void) setutent(); - utptr = getutid(&utmp); - /* write it out only if it exists */ - if (utptr) { - utptr->ut_type = DEAD_PROCESS; - utptr->ut_time = time((time_t *) 0); - (void) pututline(utptr); - /* set wtmp entry if wtmp file exists */ - if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) { - (void) write(fd, utptr, sizeof(utmp)); - (void) close(fd); - } - } - (void) endutent(); - - (void) chmod(line, 0666); - (void) chown(line, 0, 0); - line[14] = line[13]; - line[13] = line[12]; - line[8] = 'm'; - line[9] = '/'; - line[10] = 'p'; - line[11] = 't'; - line[12] = 'y'; - (void) chmod(line, 0666); - (void) chown(line, 0, 0); + break; + } } -#endif +#endif /* CRAY */ +#endif /* defined(PARENT_DOES_UTMP) */ |