sys_term.c revision 69825
129088Smarkm/* 229088Smarkm * Copyright (c) 1989, 1993 329088Smarkm * The Regents of the University of California. All rights reserved. 429088Smarkm * 529088Smarkm * Redistribution and use in source and binary forms, with or without 629088Smarkm * modification, are permitted provided that the following conditions 729088Smarkm * are met: 829088Smarkm * 1. Redistributions of source code must retain the above copyright 929088Smarkm * notice, this list of conditions and the following disclaimer. 1029088Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1129088Smarkm * notice, this list of conditions and the following disclaimer in the 1229088Smarkm * documentation and/or other materials provided with the distribution. 1329088Smarkm * 3. All advertising materials mentioning features or use of this software 1429088Smarkm * must display the following acknowledgement: 1529088Smarkm * This product includes software developed by the University of 1629088Smarkm * California, Berkeley and its contributors. 1729088Smarkm * 4. Neither the name of the University nor the names of its contributors 1829088Smarkm * may be used to endorse or promote products derived from this software 1929088Smarkm * without specific prior written permission. 2029088Smarkm * 2129088Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2229088Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2329088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2429088Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2529088Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2629088Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2729088Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2829088Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2929088Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3029088Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3129088Smarkm * SUCH DAMAGE. 3229088Smarkm */ 3329088Smarkm 3429088Smarkm#ifndef lint 3531622Scharnier#if 0 3629181Smarkmstatic const char sccsid[] = "@(#)sys_term.c 8.4+1 (Berkeley) 5/30/95"; 3731622Scharnier#endif 3831622Scharnierstatic const char rcsid[] = 3950479Speter "$FreeBSD: head/contrib/telnet/telnetd/sys_term.c 69825 2000-12-10 20:50:20Z assar $"; 4029088Smarkm#endif /* not lint */ 4129088Smarkm 4229088Smarkm#include "telnetd.h" 4329088Smarkm#include "pathnames.h" 4429088Smarkm 4529088Smarkm#if defined(AUTHENTICATION) 4629088Smarkm#include <libtelnet/auth.h> 4729088Smarkm#endif 4829088Smarkm 4929181Smarkmextern char *altlogin; 5029181Smarkmint cleanopen(char *line); 5129181Smarkmvoid scrub_env(void); 5229181Smarkm 5329088Smarkm#if defined(CRAY) || defined(__hpux) 5429088Smarkm# define PARENT_DOES_UTMP 5529088Smarkm#endif 5629088Smarkm 5729088Smarkm#ifdef NEWINIT 5829088Smarkm#include <initreq.h> 5929088Smarkm#else /* NEWINIT*/ 6029088Smarkm# ifdef UTMPX 6129088Smarkm# include <utmpx.h> 6229088Smarkmstruct utmpx wtmp; 6329088Smarkm# else 6429088Smarkm# include <utmp.h> 6529088Smarkmstruct utmp wtmp; 6629088Smarkm# endif /* UTMPX */ 6729088Smarkm 6829088Smarkm# ifndef PARENT_DOES_UTMP 6929181Smarkm#ifdef _PATH_WTMP 7029181Smarkmchar wtmpf[] = _PATH_WTMP; 7129181Smarkm#else 7229088Smarkmchar wtmpf[] = "/usr/adm/wtmp"; 7329181Smarkm#endif 7429181Smarkm#ifdef _PATH_UTMP 7529181Smarkmchar utmpf[] = _PATH_UTMP; 7629181Smarkm#else 7729088Smarkmchar utmpf[] = "/etc/utmp"; 7829181Smarkm#endif 7929088Smarkm# else /* PARENT_DOES_UTMP */ 8029088Smarkmchar wtmpf[] = "/etc/wtmp"; 8129088Smarkm# endif /* PARENT_DOES_UTMP */ 8229088Smarkm 8329181Smarkm#include <libutil.h> 8429181Smarkm 8529088Smarkm# ifdef CRAY 8629088Smarkm#include <tmpdir.h> 8729088Smarkm#include <sys/wait.h> 8829088Smarkm# if (UNICOS_LVL == '7.0') || (UNICOS_LVL == '7.1') 8929088Smarkm# define UNICOS7x 9029088Smarkm# endif 9129088Smarkm 9229088Smarkm# ifdef UNICOS7x 9329088Smarkm#include <sys/sysv.h> 9429088Smarkm#include <sys/secstat.h> 9529088Smarkmextern int secflag; 9629088Smarkmextern struct sysv sysv; 9729088Smarkm# endif /* UNICOS7x */ 9829088Smarkm# endif /* CRAY */ 9929088Smarkm#endif /* NEWINIT */ 10029088Smarkm 10129088Smarkm#ifdef STREAMSPTY 10229088Smarkm#include <sac.h> 10329088Smarkm#include <sys/stropts.h> 10429088Smarkm#endif 10529088Smarkm 10629088Smarkm#define SCPYN(a, b) (void) strncpy(a, b, sizeof(a)) 10729088Smarkm#define SCMPN(a, b) strncmp(a, b, sizeof(a)) 10829088Smarkm 10929088Smarkm#ifdef STREAMS 11029088Smarkm#include <sys/stream.h> 11129088Smarkm#endif 11229088Smarkm#ifdef __hpux 11329088Smarkm#include <sys/resource.h> 11429088Smarkm#include <sys/proc.h> 11529088Smarkm#endif 11629088Smarkm#include <sys/tty.h> 11729088Smarkm#ifdef t_erase 11829088Smarkm#undef t_erase 11929088Smarkm#undef t_kill 12029088Smarkm#undef t_intrc 12129088Smarkm#undef t_quitc 12229088Smarkm#undef t_startc 12329088Smarkm#undef t_stopc 12429088Smarkm#undef t_eofc 12529088Smarkm#undef t_brkc 12629088Smarkm#undef t_suspc 12729088Smarkm#undef t_dsuspc 12829088Smarkm#undef t_rprntc 12929088Smarkm#undef t_flushc 13029088Smarkm#undef t_werasc 13129088Smarkm#undef t_lnextc 13229088Smarkm#endif 13329088Smarkm 13429088Smarkm#if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC) 13529088Smarkm# define EXTPROC 0400 13629088Smarkm#endif 13729088Smarkm 13829088Smarkm#ifndef USE_TERMIO 13929088Smarkmstruct termbuf { 14029088Smarkm struct sgttyb sg; 14129088Smarkm struct tchars tc; 14229088Smarkm struct ltchars ltc; 14329088Smarkm int state; 14429088Smarkm int lflags; 14529088Smarkm} termbuf, termbuf2; 14629088Smarkm# define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val) 14729088Smarkm# define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val) 14829088Smarkm# define cfgetospeed(tp) (tp)->sg.sg_ospeed 14929088Smarkm# define cfgetispeed(tp) (tp)->sg.sg_ispeed 15029088Smarkm#else /* USE_TERMIO */ 15129088Smarkm# ifdef SYSV_TERMIO 15229088Smarkm# define termios termio 15329088Smarkm# endif 15429088Smarkm# ifndef TCSANOW 15529088Smarkm# ifdef TCSETS 15629088Smarkm# define TCSANOW TCSETS 15729088Smarkm# define TCSADRAIN TCSETSW 15829088Smarkm# define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) 15929088Smarkm# else 16029088Smarkm# ifdef TCSETA 16129088Smarkm# define TCSANOW TCSETA 16229088Smarkm# define TCSADRAIN TCSETAW 16329088Smarkm# define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) 16429088Smarkm# else 16529088Smarkm# define TCSANOW TIOCSETA 16629088Smarkm# define TCSADRAIN TIOCSETAW 16729088Smarkm# define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) 16829088Smarkm# endif 16929088Smarkm# endif 17029088Smarkm# define tcsetattr(f, a, t) ioctl(f, a, t) 17129088Smarkm# define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 17229088Smarkm (tp)->c_cflag |= (val) 17329088Smarkm# define cfgetospeed(tp) ((tp)->c_cflag & CBAUD) 17429088Smarkm# ifdef CIBAUD 17529088Smarkm# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \ 17629088Smarkm (tp)->c_cflag |= ((val)<<IBSHIFT) 17729088Smarkm# define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT) 17829088Smarkm# else 17929088Smarkm# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 18029088Smarkm (tp)->c_cflag |= (val) 18129088Smarkm# define cfgetispeed(tp) ((tp)->c_cflag & CBAUD) 18229088Smarkm# endif 18329088Smarkm# endif /* TCSANOW */ 18429088Smarkmstruct termios termbuf, termbuf2; /* pty control structure */ 18529088Smarkm# ifdef STREAMSPTY 18629088Smarkmint ttyfd = -1; 18729088Smarkm# endif 18829088Smarkm#endif /* USE_TERMIO */ 18929088Smarkm 19031622Scharnier#include <sys/types.h> 19131622Scharnier#include <libutil.h> 19231622Scharnier 19331622Scharnierint cleanopen __P((char *)); 19431622Scharniervoid scrub_env __P((void)); 19531622Scharnier 19629088Smarkm/* 19729088Smarkm * init_termbuf() 19829088Smarkm * copy_termbuf(cp) 19929088Smarkm * set_termbuf() 20029088Smarkm * 20129088Smarkm * These three routines are used to get and set the "termbuf" structure 20229088Smarkm * to and from the kernel. init_termbuf() gets the current settings. 20329088Smarkm * copy_termbuf() hands in a new "termbuf" to write to the kernel, and 20429088Smarkm * set_termbuf() writes the structure into the kernel. 20529088Smarkm */ 20629088Smarkm 20729088Smarkm void 20829088Smarkminit_termbuf() 20929088Smarkm{ 21029088Smarkm#ifndef USE_TERMIO 21129088Smarkm (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg); 21229088Smarkm (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc); 21329088Smarkm (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc); 21429088Smarkm# ifdef TIOCGSTATE 21529088Smarkm (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state); 21629088Smarkm# endif 21729088Smarkm#else 21829088Smarkm# ifdef STREAMSPTY 21929088Smarkm (void) tcgetattr(ttyfd, &termbuf); 22029088Smarkm# else 22129088Smarkm (void) tcgetattr(pty, &termbuf); 22229088Smarkm# endif 22329088Smarkm#endif 22429088Smarkm termbuf2 = termbuf; 22529088Smarkm} 22629088Smarkm 22729088Smarkm#if defined(LINEMODE) && defined(TIOCPKT_IOCTL) 22829088Smarkm void 22929088Smarkmcopy_termbuf(cp, len) 23029088Smarkm char *cp; 23129088Smarkm int len; 23229088Smarkm{ 23329088Smarkm if (len > sizeof(termbuf)) 23429088Smarkm len = sizeof(termbuf); 23529088Smarkm memmove((char *)&termbuf, cp, len); 23629088Smarkm termbuf2 = termbuf; 23729088Smarkm} 23829088Smarkm#endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ 23929088Smarkm 24029088Smarkm void 24129088Smarkmset_termbuf() 24229088Smarkm{ 24329088Smarkm /* 24429088Smarkm * Only make the necessary changes. 24529088Smarkm */ 24629088Smarkm#ifndef USE_TERMIO 24729088Smarkm if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, 24829088Smarkm sizeof(termbuf.sg))) 24929088Smarkm (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg); 25029088Smarkm if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, 25129088Smarkm sizeof(termbuf.tc))) 25229088Smarkm (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc); 25329088Smarkm if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc, 25429088Smarkm sizeof(termbuf.ltc))) 25529088Smarkm (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc); 25629088Smarkm if (termbuf.lflags != termbuf2.lflags) 25729088Smarkm (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags); 25829088Smarkm#else /* USE_TERMIO */ 25929088Smarkm if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) 26029088Smarkm# ifdef STREAMSPTY 26129088Smarkm (void) tcsetattr(ttyfd, TCSANOW, &termbuf); 26229088Smarkm# else 26329088Smarkm (void) tcsetattr(pty, TCSANOW, &termbuf); 26429088Smarkm# endif 26529088Smarkm# if defined(CRAY2) && defined(UNICOS5) 26629088Smarkm needtermstat = 1; 26729088Smarkm# endif 26829088Smarkm#endif /* USE_TERMIO */ 26929088Smarkm} 27029088Smarkm 27129088Smarkm 27229088Smarkm/* 27329088Smarkm * spcset(func, valp, valpp) 27429088Smarkm * 27529088Smarkm * This function takes various special characters (func), and 27629088Smarkm * sets *valp to the current value of that character, and 27729088Smarkm * *valpp to point to where in the "termbuf" structure that 27829088Smarkm * value is kept. 27929088Smarkm * 28029088Smarkm * It returns the SLC_ level of support for this function. 28129088Smarkm */ 28229088Smarkm 28329088Smarkm#ifndef USE_TERMIO 28429088Smarkm int 28529088Smarkmspcset(func, valp, valpp) 28629088Smarkm int func; 28729088Smarkm cc_t *valp; 28829088Smarkm cc_t **valpp; 28929088Smarkm{ 29029088Smarkm switch(func) { 29129088Smarkm case SLC_EOF: 29229088Smarkm *valp = termbuf.tc.t_eofc; 29329088Smarkm *valpp = (cc_t *)&termbuf.tc.t_eofc; 29429088Smarkm return(SLC_VARIABLE); 29529088Smarkm case SLC_EC: 29629088Smarkm *valp = termbuf.sg.sg_erase; 29729088Smarkm *valpp = (cc_t *)&termbuf.sg.sg_erase; 29829088Smarkm return(SLC_VARIABLE); 29929088Smarkm case SLC_EL: 30029088Smarkm *valp = termbuf.sg.sg_kill; 30129088Smarkm *valpp = (cc_t *)&termbuf.sg.sg_kill; 30229088Smarkm return(SLC_VARIABLE); 30329088Smarkm case SLC_IP: 30429088Smarkm *valp = termbuf.tc.t_intrc; 30529088Smarkm *valpp = (cc_t *)&termbuf.tc.t_intrc; 30629088Smarkm return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 30729088Smarkm case SLC_ABORT: 30829088Smarkm *valp = termbuf.tc.t_quitc; 30929088Smarkm *valpp = (cc_t *)&termbuf.tc.t_quitc; 31029088Smarkm return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 31129088Smarkm case SLC_XON: 31229088Smarkm *valp = termbuf.tc.t_startc; 31329088Smarkm *valpp = (cc_t *)&termbuf.tc.t_startc; 31429088Smarkm return(SLC_VARIABLE); 31529088Smarkm case SLC_XOFF: 31629088Smarkm *valp = termbuf.tc.t_stopc; 31729088Smarkm *valpp = (cc_t *)&termbuf.tc.t_stopc; 31829088Smarkm return(SLC_VARIABLE); 31929088Smarkm case SLC_AO: 32029088Smarkm *valp = termbuf.ltc.t_flushc; 32129088Smarkm *valpp = (cc_t *)&termbuf.ltc.t_flushc; 32229088Smarkm return(SLC_VARIABLE); 32329088Smarkm case SLC_SUSP: 32429088Smarkm *valp = termbuf.ltc.t_suspc; 32529088Smarkm *valpp = (cc_t *)&termbuf.ltc.t_suspc; 32629088Smarkm return(SLC_VARIABLE); 32729088Smarkm case SLC_EW: 32829088Smarkm *valp = termbuf.ltc.t_werasc; 32929088Smarkm *valpp = (cc_t *)&termbuf.ltc.t_werasc; 33029088Smarkm return(SLC_VARIABLE); 33129088Smarkm case SLC_RP: 33229088Smarkm *valp = termbuf.ltc.t_rprntc; 33329088Smarkm *valpp = (cc_t *)&termbuf.ltc.t_rprntc; 33429088Smarkm return(SLC_VARIABLE); 33529088Smarkm case SLC_LNEXT: 33629088Smarkm *valp = termbuf.ltc.t_lnextc; 33729088Smarkm *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 33829088Smarkm return(SLC_VARIABLE); 33929088Smarkm case SLC_FORW1: 34029088Smarkm *valp = termbuf.tc.t_brkc; 34129088Smarkm *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 34229088Smarkm return(SLC_VARIABLE); 34329088Smarkm case SLC_BRK: 34429088Smarkm case SLC_SYNCH: 34529088Smarkm case SLC_AYT: 34629088Smarkm case SLC_EOR: 34729088Smarkm *valp = (cc_t)0; 34829088Smarkm *valpp = (cc_t *)0; 34929088Smarkm return(SLC_DEFAULT); 35029088Smarkm default: 35129088Smarkm *valp = (cc_t)0; 35229088Smarkm *valpp = (cc_t *)0; 35329088Smarkm return(SLC_NOSUPPORT); 35429088Smarkm } 35529088Smarkm} 35629088Smarkm 35729088Smarkm#else /* USE_TERMIO */ 35829088Smarkm 35929088Smarkm int 36029088Smarkmspcset(func, valp, valpp) 36129088Smarkm int func; 36229088Smarkm cc_t *valp; 36329088Smarkm cc_t **valpp; 36429088Smarkm{ 36529088Smarkm 36629088Smarkm#define setval(a, b) *valp = termbuf.c_cc[a]; \ 36729088Smarkm *valpp = &termbuf.c_cc[a]; \ 36829088Smarkm return(b); 36929088Smarkm#define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); 37029088Smarkm 37129088Smarkm switch(func) { 37229088Smarkm case SLC_EOF: 37329088Smarkm setval(VEOF, SLC_VARIABLE); 37429088Smarkm case SLC_EC: 37529088Smarkm setval(VERASE, SLC_VARIABLE); 37629088Smarkm case SLC_EL: 37729088Smarkm setval(VKILL, SLC_VARIABLE); 37829088Smarkm case SLC_IP: 37929088Smarkm setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 38029088Smarkm case SLC_ABORT: 38129088Smarkm setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 38229088Smarkm case SLC_XON: 38329088Smarkm#ifdef VSTART 38429088Smarkm setval(VSTART, SLC_VARIABLE); 38529088Smarkm#else 38629088Smarkm defval(0x13); 38729088Smarkm#endif 38829088Smarkm case SLC_XOFF: 38929088Smarkm#ifdef VSTOP 39029088Smarkm setval(VSTOP, SLC_VARIABLE); 39129088Smarkm#else 39229088Smarkm defval(0x11); 39329088Smarkm#endif 39429088Smarkm case SLC_EW: 39529088Smarkm#ifdef VWERASE 39629088Smarkm setval(VWERASE, SLC_VARIABLE); 39729088Smarkm#else 39829088Smarkm defval(0); 39929088Smarkm#endif 40029088Smarkm case SLC_RP: 40129088Smarkm#ifdef VREPRINT 40229088Smarkm setval(VREPRINT, SLC_VARIABLE); 40329088Smarkm#else 40429088Smarkm defval(0); 40529088Smarkm#endif 40629088Smarkm case SLC_LNEXT: 40729088Smarkm#ifdef VLNEXT 40829088Smarkm setval(VLNEXT, SLC_VARIABLE); 40929088Smarkm#else 41029088Smarkm defval(0); 41129088Smarkm#endif 41229088Smarkm case SLC_AO: 41329088Smarkm#if !defined(VDISCARD) && defined(VFLUSHO) 41429088Smarkm# define VDISCARD VFLUSHO 41529088Smarkm#endif 41629088Smarkm#ifdef VDISCARD 41729088Smarkm setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); 41829088Smarkm#else 41929088Smarkm defval(0); 42029088Smarkm#endif 42129088Smarkm case SLC_SUSP: 42229088Smarkm#ifdef VSUSP 42329088Smarkm setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); 42429088Smarkm#else 42529088Smarkm defval(0); 42629088Smarkm#endif 42729088Smarkm#ifdef VEOL 42829088Smarkm case SLC_FORW1: 42929088Smarkm setval(VEOL, SLC_VARIABLE); 43029088Smarkm#endif 43129088Smarkm#ifdef VEOL2 43229088Smarkm case SLC_FORW2: 43329088Smarkm setval(VEOL2, SLC_VARIABLE); 43429088Smarkm#endif 43529088Smarkm case SLC_AYT: 43629088Smarkm#ifdef VSTATUS 43729088Smarkm setval(VSTATUS, SLC_VARIABLE); 43829088Smarkm#else 43929088Smarkm defval(0); 44029088Smarkm#endif 44129088Smarkm 44229088Smarkm case SLC_BRK: 44329088Smarkm case SLC_SYNCH: 44429088Smarkm case SLC_EOR: 44529088Smarkm defval(0); 44629088Smarkm 44729088Smarkm default: 44829088Smarkm *valp = 0; 44929088Smarkm *valpp = 0; 45029088Smarkm return(SLC_NOSUPPORT); 45129088Smarkm } 45229088Smarkm} 45329088Smarkm#endif /* USE_TERMIO */ 45429088Smarkm 45529088Smarkm#ifdef CRAY 45629088Smarkm/* 45729088Smarkm * getnpty() 45829088Smarkm * 45929088Smarkm * Return the number of pty's configured into the system. 46029088Smarkm */ 46129088Smarkm int 46229088Smarkmgetnpty() 46329088Smarkm{ 46429088Smarkm#ifdef _SC_CRAY_NPTY 46529088Smarkm int numptys; 46629088Smarkm 46729088Smarkm if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) 46829088Smarkm return numptys; 46929088Smarkm else 47029088Smarkm#endif /* _SC_CRAY_NPTY */ 47129088Smarkm return 128; 47229088Smarkm} 47329088Smarkm#endif /* CRAY */ 47429088Smarkm 47529088Smarkm#ifndef convex 47629088Smarkm/* 47729088Smarkm * getpty() 47829088Smarkm * 47929088Smarkm * Allocate a pty. As a side effect, the external character 48029088Smarkm * array "line" contains the name of the slave side. 48129088Smarkm * 48229088Smarkm * Returns the file descriptor of the opened pty. 48329088Smarkm */ 48429088Smarkm#ifndef __GNUC__ 48529088Smarkmchar *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 48629088Smarkm#else 48729088Smarkmstatic char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 48829088Smarkmchar *line = Xline; 48929088Smarkm#endif 49029088Smarkm#ifdef CRAY 49129088Smarkmchar *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 49229088Smarkm#endif /* CRAY */ 49329088Smarkm 49429088Smarkm int 49529088Smarkmgetpty(ptynum) 49629088Smarkmint *ptynum; 49729088Smarkm{ 49829088Smarkm register int p; 49929088Smarkm#ifdef STREAMSPTY 50029088Smarkm int t; 50129088Smarkm char *ptsname(); 50229088Smarkm 50329088Smarkm p = open("/dev/ptmx", 2); 50429088Smarkm if (p > 0) { 50529088Smarkm grantpt(p); 50629088Smarkm unlockpt(p); 50729088Smarkm strcpy(line, ptsname(p)); 50829088Smarkm return(p); 50929088Smarkm } 51029088Smarkm 51129088Smarkm#else /* ! STREAMSPTY */ 51229088Smarkm#ifndef CRAY 51329088Smarkm register char *cp, *p1, *p2; 51429088Smarkm register int i; 51529088Smarkm#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207 51629088Smarkm int dummy; 51729088Smarkm#endif 51829088Smarkm 51929088Smarkm#ifndef __hpux 52032688Simp (void) strcpy(line, "/dev/ptyXX"); 52129088Smarkm p1 = &line[8]; 52229088Smarkm p2 = &line[9]; 52329088Smarkm#else 52432688Simp (void) strcpy(line, "/dev/ptym/ptyXX"); 52529088Smarkm p1 = &line[13]; 52629088Smarkm p2 = &line[14]; 52729088Smarkm#endif 52829088Smarkm 52929181Smarkm for (cp = "pqrsPQRS"; *cp; cp++) { 53029088Smarkm struct stat stb; 53129088Smarkm 53229088Smarkm *p1 = *cp; 53329088Smarkm *p2 = '0'; 53429088Smarkm /* 53529088Smarkm * This stat() check is just to keep us from 53629088Smarkm * looping through all 256 combinations if there 53729088Smarkm * aren't that many ptys available. 53829088Smarkm */ 53929088Smarkm if (stat(line, &stb) < 0) 54029088Smarkm break; 54129181Smarkm for (i = 0; i < 32; i++) { 54229181Smarkm *p2 = "0123456789abcdefghijklmnopqrstuv"[i]; 54329088Smarkm p = open(line, 2); 54429088Smarkm if (p > 0) { 54529088Smarkm#ifndef __hpux 54629088Smarkm line[5] = 't'; 54729088Smarkm#else 54829088Smarkm for (p1 = &line[8]; *p1; p1++) 54929088Smarkm *p1 = *(p1+1); 55029088Smarkm line[9] = 't'; 55129088Smarkm#endif 55229088Smarkm chown(line, 0, 0); 55329088Smarkm chmod(line, 0600); 55429088Smarkm#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207 55529088Smarkm if (ioctl(p, TIOCGPGRP, &dummy) == 0 55629088Smarkm || errno != EIO) { 55729088Smarkm chmod(line, 0666); 55829088Smarkm close(p); 55929088Smarkm line[5] = 'p'; 56029088Smarkm } else 56129088Smarkm#endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */ 56229088Smarkm return(p); 56329088Smarkm } 56429088Smarkm } 56529088Smarkm } 56629088Smarkm#else /* CRAY */ 56729088Smarkm extern lowpty, highpty; 56829088Smarkm struct stat sb; 56929088Smarkm 57029088Smarkm for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) { 57129088Smarkm (void) sprintf(myline, "/dev/pty/%03d", *ptynum); 57229088Smarkm p = open(myline, 2); 57329088Smarkm if (p < 0) 57429088Smarkm continue; 57529088Smarkm (void) sprintf(line, "/dev/ttyp%03d", *ptynum); 57629088Smarkm /* 57729088Smarkm * Here are some shenanigans to make sure that there 57829088Smarkm * are no listeners lurking on the line. 57929088Smarkm */ 58029088Smarkm if(stat(line, &sb) < 0) { 58129088Smarkm (void) close(p); 58229088Smarkm continue; 58329088Smarkm } 58429088Smarkm if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { 58529088Smarkm chown(line, 0, 0); 58629088Smarkm chmod(line, 0600); 58729088Smarkm (void)close(p); 58829088Smarkm p = open(myline, 2); 58929088Smarkm if (p < 0) 59029088Smarkm continue; 59129088Smarkm } 59229088Smarkm /* 59329088Smarkm * Now it should be safe...check for accessability. 59429088Smarkm */ 59529088Smarkm if (access(line, 6) == 0) 59629088Smarkm return(p); 59729088Smarkm else { 59829088Smarkm /* no tty side to pty so skip it */ 59929088Smarkm (void) close(p); 60029088Smarkm } 60129088Smarkm } 60229088Smarkm#endif /* CRAY */ 60329088Smarkm#endif /* STREAMSPTY */ 60429088Smarkm return(-1); 60529088Smarkm} 60629088Smarkm#endif /* convex */ 60729088Smarkm 60829088Smarkm#ifdef LINEMODE 60929088Smarkm/* 61029088Smarkm * tty_flowmode() Find out if flow control is enabled or disabled. 61129088Smarkm * tty_linemode() Find out if linemode (external processing) is enabled. 61229088Smarkm * tty_setlinemod(on) Turn on/off linemode. 61329088Smarkm * tty_isecho() Find out if echoing is turned on. 61429088Smarkm * tty_setecho(on) Enable/disable character echoing. 61529088Smarkm * tty_israw() Find out if terminal is in RAW mode. 61629088Smarkm * tty_binaryin(on) Turn on/off BINARY on input. 61729088Smarkm * tty_binaryout(on) Turn on/off BINARY on output. 61829088Smarkm * tty_isediting() Find out if line editing is enabled. 61929088Smarkm * tty_istrapsig() Find out if signal trapping is enabled. 62029088Smarkm * tty_setedit(on) Turn on/off line editing. 62129088Smarkm * tty_setsig(on) Turn on/off signal trapping. 62229088Smarkm * tty_issofttab() Find out if tab expansion is enabled. 62329088Smarkm * tty_setsofttab(on) Turn on/off soft tab expansion. 62429088Smarkm * tty_islitecho() Find out if typed control chars are echoed literally 62529088Smarkm * tty_setlitecho() Turn on/off literal echo of control chars 62629088Smarkm * tty_tspeed(val) Set transmit speed to val. 62729088Smarkm * tty_rspeed(val) Set receive speed to val. 62829088Smarkm */ 62929088Smarkm 63029088Smarkm#ifdef convex 63129088Smarkmstatic int linestate; 63229088Smarkm#endif 63329088Smarkm 63429088Smarkm int 63529088Smarkmtty_linemode() 63629088Smarkm{ 63729088Smarkm#ifndef convex 63829088Smarkm#ifndef USE_TERMIO 63929088Smarkm return(termbuf.state & TS_EXTPROC); 64029088Smarkm#else 64129088Smarkm return(termbuf.c_lflag & EXTPROC); 64229088Smarkm#endif 64329088Smarkm#else 64429088Smarkm return(linestate); 64529088Smarkm#endif 64629088Smarkm} 64729088Smarkm 64829088Smarkm void 64929088Smarkmtty_setlinemode(on) 65029088Smarkm int on; 65129088Smarkm{ 65229088Smarkm#ifdef TIOCEXT 65329088Smarkm# ifndef convex 65429088Smarkm set_termbuf(); 65529088Smarkm# else 65629088Smarkm linestate = on; 65729088Smarkm# endif 65829088Smarkm (void) ioctl(pty, TIOCEXT, (char *)&on); 65929088Smarkm# ifndef convex 66029088Smarkm init_termbuf(); 66129088Smarkm# endif 66229088Smarkm#else /* !TIOCEXT */ 66329088Smarkm# ifdef EXTPROC 66429088Smarkm if (on) 66529088Smarkm termbuf.c_lflag |= EXTPROC; 66629088Smarkm else 66729088Smarkm termbuf.c_lflag &= ~EXTPROC; 66829088Smarkm# endif 66929088Smarkm#endif /* TIOCEXT */ 67029088Smarkm} 67129088Smarkm#endif /* LINEMODE */ 67229088Smarkm 67329088Smarkm int 67429088Smarkmtty_isecho() 67529088Smarkm{ 67629088Smarkm#ifndef USE_TERMIO 67729088Smarkm return (termbuf.sg.sg_flags & ECHO); 67829088Smarkm#else 67929088Smarkm return (termbuf.c_lflag & ECHO); 68029088Smarkm#endif 68129088Smarkm} 68229088Smarkm 68329088Smarkm int 68429088Smarkmtty_flowmode() 68529088Smarkm{ 68629088Smarkm#ifndef USE_TERMIO 68729088Smarkm return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0); 68829088Smarkm#else 68929088Smarkm return((termbuf.c_iflag & IXON) ? 1 : 0); 69029088Smarkm#endif 69129088Smarkm} 69229088Smarkm 69329088Smarkm int 69429088Smarkmtty_restartany() 69529088Smarkm{ 69629088Smarkm#ifndef USE_TERMIO 69729088Smarkm# ifdef DECCTQ 69829088Smarkm return((termbuf.lflags & DECCTQ) ? 0 : 1); 69929088Smarkm# else 70029088Smarkm return(-1); 70129088Smarkm# endif 70229088Smarkm#else 70329088Smarkm return((termbuf.c_iflag & IXANY) ? 1 : 0); 70429088Smarkm#endif 70529088Smarkm} 70629088Smarkm 70729088Smarkm void 70829088Smarkmtty_setecho(on) 70929088Smarkm int on; 71029088Smarkm{ 71129088Smarkm#ifndef USE_TERMIO 71229088Smarkm if (on) 71329088Smarkm termbuf.sg.sg_flags |= ECHO|CRMOD; 71429088Smarkm else 71529088Smarkm termbuf.sg.sg_flags &= ~(ECHO|CRMOD); 71629088Smarkm#else 71729088Smarkm if (on) 71829088Smarkm termbuf.c_lflag |= ECHO; 71929088Smarkm else 72029088Smarkm termbuf.c_lflag &= ~ECHO; 72129088Smarkm#endif 72229088Smarkm} 72329088Smarkm 72429088Smarkm int 72529088Smarkmtty_israw() 72629088Smarkm{ 72729088Smarkm#ifndef USE_TERMIO 72829088Smarkm return(termbuf.sg.sg_flags & RAW); 72929088Smarkm#else 73029088Smarkm return(!(termbuf.c_lflag & ICANON)); 73129088Smarkm#endif 73229088Smarkm} 73329088Smarkm 73429088Smarkm#if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 73529088Smarkm int 73629088Smarkmtty_setraw(on) 73729088Smarkm{ 73829088Smarkm# ifndef USE_TERMIO 73929088Smarkm if (on) 74029088Smarkm termbuf.sg.sg_flags |= RAW; 74129088Smarkm else 74229088Smarkm termbuf.sg.sg_flags &= ~RAW; 74329088Smarkm# else 74429088Smarkm if (on) 74529088Smarkm termbuf.c_lflag &= ~ICANON; 74629088Smarkm else 74729088Smarkm termbuf.c_lflag |= ICANON; 74829088Smarkm# endif 74929088Smarkm} 75029088Smarkm#endif 75129088Smarkm 75229088Smarkm void 75329088Smarkmtty_binaryin(on) 75429088Smarkm int on; 75529088Smarkm{ 75629088Smarkm#ifndef USE_TERMIO 75729088Smarkm if (on) 75829088Smarkm termbuf.lflags |= LPASS8; 75929088Smarkm else 76029088Smarkm termbuf.lflags &= ~LPASS8; 76129088Smarkm#else 76229088Smarkm if (on) { 76329088Smarkm termbuf.c_iflag &= ~ISTRIP; 76429088Smarkm } else { 76529088Smarkm termbuf.c_iflag |= ISTRIP; 76629088Smarkm } 76729088Smarkm#endif 76829088Smarkm} 76929088Smarkm 77029088Smarkm void 77129088Smarkmtty_binaryout(on) 77229088Smarkm int on; 77329088Smarkm{ 77429088Smarkm#ifndef USE_TERMIO 77529088Smarkm if (on) 77629088Smarkm termbuf.lflags |= LLITOUT; 77729088Smarkm else 77829088Smarkm termbuf.lflags &= ~LLITOUT; 77929088Smarkm#else 78029088Smarkm if (on) { 78129088Smarkm termbuf.c_cflag &= ~(CSIZE|PARENB); 78229088Smarkm termbuf.c_cflag |= CS8; 78329088Smarkm termbuf.c_oflag &= ~OPOST; 78429088Smarkm } else { 78529088Smarkm termbuf.c_cflag &= ~CSIZE; 78629088Smarkm termbuf.c_cflag |= CS7|PARENB; 78729088Smarkm termbuf.c_oflag |= OPOST; 78829088Smarkm } 78929088Smarkm#endif 79029088Smarkm} 79129088Smarkm 79229088Smarkm int 79329088Smarkmtty_isbinaryin() 79429088Smarkm{ 79529088Smarkm#ifndef USE_TERMIO 79629088Smarkm return(termbuf.lflags & LPASS8); 79729088Smarkm#else 79829088Smarkm return(!(termbuf.c_iflag & ISTRIP)); 79929088Smarkm#endif 80029088Smarkm} 80129088Smarkm 80229088Smarkm int 80329088Smarkmtty_isbinaryout() 80429088Smarkm{ 80529088Smarkm#ifndef USE_TERMIO 80629088Smarkm return(termbuf.lflags & LLITOUT); 80729088Smarkm#else 80829088Smarkm return(!(termbuf.c_oflag&OPOST)); 80929088Smarkm#endif 81029088Smarkm} 81129088Smarkm 81229088Smarkm#ifdef LINEMODE 81329088Smarkm int 81429088Smarkmtty_isediting() 81529088Smarkm{ 81629088Smarkm#ifndef USE_TERMIO 81729088Smarkm return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); 81829088Smarkm#else 81929088Smarkm return(termbuf.c_lflag & ICANON); 82029088Smarkm#endif 82129088Smarkm} 82229088Smarkm 82329088Smarkm int 82429088Smarkmtty_istrapsig() 82529088Smarkm{ 82629088Smarkm#ifndef USE_TERMIO 82729088Smarkm return(!(termbuf.sg.sg_flags&RAW)); 82829088Smarkm#else 82929088Smarkm return(termbuf.c_lflag & ISIG); 83029088Smarkm#endif 83129088Smarkm} 83229088Smarkm 83329088Smarkm void 83429088Smarkmtty_setedit(on) 83529088Smarkm int on; 83629088Smarkm{ 83729088Smarkm#ifndef USE_TERMIO 83829088Smarkm if (on) 83929088Smarkm termbuf.sg.sg_flags &= ~CBREAK; 84029088Smarkm else 84129088Smarkm termbuf.sg.sg_flags |= CBREAK; 84229088Smarkm#else 84329088Smarkm if (on) 84429088Smarkm termbuf.c_lflag |= ICANON; 84529088Smarkm else 84629088Smarkm termbuf.c_lflag &= ~ICANON; 84729088Smarkm#endif 84829088Smarkm} 84929088Smarkm 85029088Smarkm void 85129088Smarkmtty_setsig(on) 85229088Smarkm int on; 85329088Smarkm{ 85429088Smarkm#ifndef USE_TERMIO 85529088Smarkm if (on) 85629088Smarkm ; 85729088Smarkm#else 85829088Smarkm if (on) 85929088Smarkm termbuf.c_lflag |= ISIG; 86029088Smarkm else 86129088Smarkm termbuf.c_lflag &= ~ISIG; 86229088Smarkm#endif 86329088Smarkm} 86429088Smarkm#endif /* LINEMODE */ 86529088Smarkm 86629088Smarkm int 86729088Smarkmtty_issofttab() 86829088Smarkm{ 86929088Smarkm#ifndef USE_TERMIO 87029088Smarkm return (termbuf.sg.sg_flags & XTABS); 87129088Smarkm#else 87229088Smarkm# ifdef OXTABS 87329088Smarkm return (termbuf.c_oflag & OXTABS); 87429088Smarkm# endif 87529088Smarkm# ifdef TABDLY 87629088Smarkm return ((termbuf.c_oflag & TABDLY) == TAB3); 87729088Smarkm# endif 87829088Smarkm#endif 87929088Smarkm} 88029088Smarkm 88129088Smarkm void 88229088Smarkmtty_setsofttab(on) 88329088Smarkm int on; 88429088Smarkm{ 88529088Smarkm#ifndef USE_TERMIO 88629088Smarkm if (on) 88729088Smarkm termbuf.sg.sg_flags |= XTABS; 88829088Smarkm else 88929088Smarkm termbuf.sg.sg_flags &= ~XTABS; 89029088Smarkm#else 89129088Smarkm if (on) { 89229088Smarkm# ifdef OXTABS 89329088Smarkm termbuf.c_oflag |= OXTABS; 89429088Smarkm# endif 89529088Smarkm# ifdef TABDLY 89629088Smarkm termbuf.c_oflag &= ~TABDLY; 89729088Smarkm termbuf.c_oflag |= TAB3; 89829088Smarkm# endif 89929088Smarkm } else { 90029088Smarkm# ifdef OXTABS 90129088Smarkm termbuf.c_oflag &= ~OXTABS; 90229088Smarkm# endif 90329088Smarkm# ifdef TABDLY 90429088Smarkm termbuf.c_oflag &= ~TABDLY; 90529088Smarkm termbuf.c_oflag |= TAB0; 90629088Smarkm# endif 90729088Smarkm } 90829088Smarkm#endif 90929088Smarkm} 91029088Smarkm 91129088Smarkm int 91229088Smarkmtty_islitecho() 91329088Smarkm{ 91429088Smarkm#ifndef USE_TERMIO 91529088Smarkm return (!(termbuf.lflags & LCTLECH)); 91629088Smarkm#else 91729088Smarkm# ifdef ECHOCTL 91829088Smarkm return (!(termbuf.c_lflag & ECHOCTL)); 91929088Smarkm# endif 92029088Smarkm# ifdef TCTLECH 92129088Smarkm return (!(termbuf.c_lflag & TCTLECH)); 92229088Smarkm# endif 92329088Smarkm# if !defined(ECHOCTL) && !defined(TCTLECH) 92429088Smarkm return (0); /* assumes ctl chars are echoed '^x' */ 92529088Smarkm# endif 92629088Smarkm#endif 92729088Smarkm} 92829088Smarkm 92929088Smarkm void 93029088Smarkmtty_setlitecho(on) 93129088Smarkm int on; 93229088Smarkm{ 93329088Smarkm#ifndef USE_TERMIO 93429088Smarkm if (on) 93529088Smarkm termbuf.lflags &= ~LCTLECH; 93629088Smarkm else 93729088Smarkm termbuf.lflags |= LCTLECH; 93829088Smarkm#else 93929088Smarkm# ifdef ECHOCTL 94029088Smarkm if (on) 94129088Smarkm termbuf.c_lflag &= ~ECHOCTL; 94229088Smarkm else 94329088Smarkm termbuf.c_lflag |= ECHOCTL; 94429088Smarkm# endif 94529088Smarkm# ifdef TCTLECH 94629088Smarkm if (on) 94729088Smarkm termbuf.c_lflag &= ~TCTLECH; 94829088Smarkm else 94929088Smarkm termbuf.c_lflag |= TCTLECH; 95029088Smarkm# endif 95129088Smarkm#endif 95229088Smarkm} 95329088Smarkm 95429088Smarkm int 95529088Smarkmtty_iscrnl() 95629088Smarkm{ 95729088Smarkm#ifndef USE_TERMIO 95829088Smarkm return (termbuf.sg.sg_flags & CRMOD); 95929088Smarkm#else 96029088Smarkm return (termbuf.c_iflag & ICRNL); 96129088Smarkm#endif 96229088Smarkm} 96329088Smarkm 96429088Smarkm/* 96529088Smarkm * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). 96629088Smarkm */ 96729088Smarkm#if B4800 != 4800 96829088Smarkm#define DECODE_BAUD 96929088Smarkm#endif 97029088Smarkm 97129088Smarkm#ifdef DECODE_BAUD 97229088Smarkm 97329088Smarkm/* 97429088Smarkm * A table of available terminal speeds 97529088Smarkm */ 97629088Smarkmstruct termspeeds { 97729088Smarkm int speed; 97829088Smarkm int value; 97929088Smarkm} termspeeds[] = { 98029088Smarkm { 0, B0 }, { 50, B50 }, { 75, B75 }, 98129088Smarkm { 110, B110 }, { 134, B134 }, { 150, B150 }, 98229088Smarkm { 200, B200 }, { 300, B300 }, { 600, B600 }, 98329088Smarkm { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 98429088Smarkm { 4800, B4800 }, 98529088Smarkm#ifdef B7200 98629088Smarkm { 7200, B7200 }, 98729088Smarkm#endif 98829088Smarkm { 9600, B9600 }, 98929088Smarkm#ifdef B14400 99029088Smarkm { 14400, B14400 }, 99129088Smarkm#endif 99229088Smarkm#ifdef B19200 99329088Smarkm { 19200, B19200 }, 99429088Smarkm#endif 99529088Smarkm#ifdef B28800 99629088Smarkm { 28800, B28800 }, 99729088Smarkm#endif 99829088Smarkm#ifdef B38400 99929088Smarkm { 38400, B38400 }, 100029088Smarkm#endif 100129088Smarkm#ifdef B57600 100229088Smarkm { 57600, B57600 }, 100329088Smarkm#endif 100429088Smarkm#ifdef B115200 100529088Smarkm { 115200, B115200 }, 100629088Smarkm#endif 100729088Smarkm#ifdef B230400 100829088Smarkm { 230400, B230400 }, 100929088Smarkm#endif 101029088Smarkm { -1, 0 } 101129088Smarkm}; 101231622Scharnier#endif /* DECODE_BAUD */ 101329088Smarkm 101429088Smarkm void 101529088Smarkmtty_tspeed(val) 101629088Smarkm int val; 101729088Smarkm{ 101829088Smarkm#ifdef DECODE_BAUD 101929088Smarkm register struct termspeeds *tp; 102029088Smarkm 102129088Smarkm for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 102229088Smarkm ; 102329088Smarkm if (tp->speed == -1) /* back up to last valid value */ 102429088Smarkm --tp; 102529088Smarkm cfsetospeed(&termbuf, tp->value); 102631622Scharnier#else /* DECODE_BAUD */ 102729088Smarkm cfsetospeed(&termbuf, val); 102831622Scharnier#endif /* DECODE_BAUD */ 102929088Smarkm} 103029088Smarkm 103129088Smarkm void 103229088Smarkmtty_rspeed(val) 103329088Smarkm int val; 103429088Smarkm{ 103529088Smarkm#ifdef DECODE_BAUD 103629088Smarkm register struct termspeeds *tp; 103729088Smarkm 103829088Smarkm for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 103929088Smarkm ; 104029088Smarkm if (tp->speed == -1) /* back up to last valid value */ 104129088Smarkm --tp; 104229088Smarkm cfsetispeed(&termbuf, tp->value); 104329088Smarkm#else /* DECODE_BAUD */ 104429088Smarkm cfsetispeed(&termbuf, val); 104529088Smarkm#endif /* DECODE_BAUD */ 104629088Smarkm} 104729088Smarkm 104829088Smarkm#if defined(CRAY2) && defined(UNICOS5) 104929088Smarkm int 105029088Smarkmtty_isnewmap() 105129088Smarkm{ 105229088Smarkm return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) && 105329088Smarkm !(termbuf.c_oflag & ONLRET)); 105429088Smarkm} 105529088Smarkm#endif 105629088Smarkm 105729088Smarkm#ifdef PARENT_DOES_UTMP 105829088Smarkm# ifndef NEWINIT 105929088Smarkmextern struct utmp wtmp; 106029088Smarkmextern char wtmpf[]; 106129088Smarkm# else /* NEWINIT */ 106229088Smarkmint gotalarm; 106329088Smarkm 106429088Smarkm /* ARGSUSED */ 106529088Smarkm void 106629088Smarkmnologinproc(sig) 106729088Smarkm int sig; 106829088Smarkm{ 106929088Smarkm gotalarm++; 107029088Smarkm} 107129088Smarkm# endif /* NEWINIT */ 107229088Smarkm#endif /* PARENT_DOES_UTMP */ 107329088Smarkm 107429088Smarkm#ifndef NEWINIT 107529088Smarkm# ifdef PARENT_DOES_UTMP 107629088Smarkmextern void utmp_sig_init P((void)); 107729088Smarkmextern void utmp_sig_reset P((void)); 107829088Smarkmextern void utmp_sig_wait P((void)); 107929088Smarkmextern void utmp_sig_notify P((int)); 108029088Smarkm# endif /* PARENT_DOES_UTMP */ 108129088Smarkm#endif 108229088Smarkm 108329088Smarkm/* 108429088Smarkm * getptyslave() 108529088Smarkm * 108629088Smarkm * Open the slave side of the pty, and do any initialization 108731622Scharnier * that is necessary. 108829088Smarkm */ 108929181Smarkm void 109029088Smarkmgetptyslave() 109129088Smarkm{ 109229088Smarkm register int t = -1; 109329181Smarkm char erase; 109429088Smarkm 109529088Smarkm#if !defined(CRAY) || !defined(NEWINIT) 109629088Smarkm# ifdef LINEMODE 109729088Smarkm int waslm; 109829088Smarkm# endif 109929088Smarkm# ifdef TIOCGWINSZ 110029088Smarkm struct winsize ws; 110129088Smarkm extern int def_row, def_col; 110229088Smarkm# endif 110329088Smarkm extern int def_tspeed, def_rspeed; 110429088Smarkm /* 110529088Smarkm * Opening the slave side may cause initilization of the 110629088Smarkm * kernel tty structure. We need remember the state of 110729088Smarkm * if linemode was turned on 110829088Smarkm * terminal window size 110929088Smarkm * terminal speed 111029181Smarkm * erase character 111129088Smarkm * so that we can re-set them if we need to. 111229088Smarkm */ 111329088Smarkm# ifdef LINEMODE 111429088Smarkm waslm = tty_linemode(); 111529088Smarkm# endif 111629181Smarkm erase = termbuf.c_cc[VERASE]; 111729088Smarkm 111829088Smarkm /* 111929088Smarkm * Make sure that we don't have a controlling tty, and 112029088Smarkm * that we are the session (process group) leader. 112129088Smarkm */ 112229088Smarkm# ifdef TIOCNOTTY 112329088Smarkm t = open(_PATH_TTY, O_RDWR); 112429088Smarkm if (t >= 0) { 112529088Smarkm (void) ioctl(t, TIOCNOTTY, (char *)0); 112629088Smarkm (void) close(t); 112729088Smarkm } 112829088Smarkm# endif 112929088Smarkm 113029088Smarkm 113129088Smarkm# ifdef PARENT_DOES_UTMP 113229088Smarkm /* 113329088Smarkm * Wait for our parent to get the utmp stuff to get done. 113429088Smarkm */ 113529088Smarkm utmp_sig_wait(); 113629088Smarkm# endif 113729088Smarkm 113829088Smarkm t = cleanopen(line); 113929088Smarkm if (t < 0) 114029088Smarkm fatalperror(net, line); 114129088Smarkm 114229088Smarkm#ifdef STREAMSPTY 114329088Smarkm#ifdef USE_TERMIO 114429088Smarkm ttyfd = t; 114529088Smarkm#endif 114629088Smarkm if (ioctl(t, I_PUSH, "ptem") < 0) 114729088Smarkm fatal(net, "I_PUSH ptem"); 114829088Smarkm if (ioctl(t, I_PUSH, "ldterm") < 0) 114929088Smarkm fatal(net, "I_PUSH ldterm"); 115029088Smarkm if (ioctl(t, I_PUSH, "ttcompat") < 0) 115129088Smarkm fatal(net, "I_PUSH ttcompat"); 115229088Smarkm if (ioctl(pty, I_PUSH, "pckt") < 0) 115329088Smarkm fatal(net, "I_PUSH pckt"); 115429088Smarkm#endif 115529088Smarkm 115629088Smarkm /* 115729088Smarkm * set up the tty modes as we like them to be. 115829088Smarkm */ 115929088Smarkm init_termbuf(); 116029088Smarkm# ifdef TIOCGWINSZ 116129088Smarkm if (def_row || def_col) { 116229088Smarkm memset((char *)&ws, 0, sizeof(ws)); 116329088Smarkm ws.ws_col = def_col; 116429088Smarkm ws.ws_row = def_row; 116529088Smarkm (void)ioctl(t, TIOCSWINSZ, (char *)&ws); 116629088Smarkm } 116729088Smarkm# endif 116829088Smarkm 116929088Smarkm /* 117029088Smarkm * Settings for sgtty based systems 117129088Smarkm */ 117229088Smarkm# ifndef USE_TERMIO 117329088Smarkm termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; 117429088Smarkm# endif /* USE_TERMIO */ 117529088Smarkm 117629088Smarkm /* 117729088Smarkm * Settings for UNICOS (and HPUX) 117829088Smarkm */ 117929088Smarkm# if defined(CRAY) || defined(__hpux) 118029088Smarkm termbuf.c_oflag = OPOST|ONLCR|TAB3; 118129088Smarkm termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; 118229088Smarkm termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; 118329088Smarkm termbuf.c_cflag = EXTB|HUPCL|CS8; 118429088Smarkm# endif 118529088Smarkm 118629088Smarkm /* 118729088Smarkm * Settings for all other termios/termio based 118829088Smarkm * systems, other than 4.4BSD. In 4.4BSD the 118929088Smarkm * kernel does the initial terminal setup. 119029088Smarkm */ 119129088Smarkm# if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) 119229088Smarkm# ifndef OXTABS 119329088Smarkm# define OXTABS 0 119429088Smarkm# endif 119529088Smarkm termbuf.c_lflag |= ECHO; 119629088Smarkm termbuf.c_oflag |= ONLCR|OXTABS; 119729088Smarkm termbuf.c_iflag |= ICRNL; 119829088Smarkm termbuf.c_iflag &= ~IXOFF; 119929088Smarkm# endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */ 120029088Smarkm tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); 120129088Smarkm tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); 120229181Smarkm if (erase) 120329181Smarkm termbuf.c_cc[VERASE] = erase; 120429088Smarkm# ifdef LINEMODE 120529088Smarkm if (waslm) 120629088Smarkm tty_setlinemode(1); 120729088Smarkm# endif /* LINEMODE */ 120829088Smarkm 120929088Smarkm /* 121029088Smarkm * Set the tty modes, and make this our controlling tty. 121129088Smarkm */ 121229088Smarkm set_termbuf(); 121329088Smarkm if (login_tty(t) == -1) 121429088Smarkm fatalperror(net, "login_tty"); 121529088Smarkm#endif /* !defined(CRAY) || !defined(NEWINIT) */ 121629088Smarkm if (net > 2) 121729088Smarkm (void) close(net); 121829088Smarkm#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 121929088Smarkm /* 122029088Smarkm * Leave the pty open so that we can write out the rlogin 122129088Smarkm * protocol for /bin/login, if the authentication works. 122229088Smarkm */ 122329088Smarkm#else 122429088Smarkm if (pty > 2) { 122529088Smarkm (void) close(pty); 122629088Smarkm pty = -1; 122729088Smarkm } 122829088Smarkm#endif 122929088Smarkm} 123029088Smarkm 123129088Smarkm#if !defined(CRAY) || !defined(NEWINIT) 123229088Smarkm#ifndef O_NOCTTY 123329088Smarkm#define O_NOCTTY 0 123429088Smarkm#endif 123529088Smarkm/* 123629088Smarkm * Open the specified slave side of the pty, 123729088Smarkm * making sure that we have a clean tty. 123829088Smarkm */ 123929088Smarkm int 124029088Smarkmcleanopen(line) 124129088Smarkm char *line; 124229088Smarkm{ 124329088Smarkm register int t; 124429088Smarkm#ifdef UNICOS7x 124529088Smarkm struct secstat secbuf; 124629088Smarkm#endif /* UNICOS7x */ 124729088Smarkm 124829088Smarkm#ifndef STREAMSPTY 124929088Smarkm /* 125029088Smarkm * Make sure that other people can't open the 125129088Smarkm * slave side of the connection. 125229088Smarkm */ 125329088Smarkm (void) chown(line, 0, 0); 125429088Smarkm (void) chmod(line, 0600); 125529088Smarkm#endif 125629088Smarkm 125729088Smarkm# if !defined(CRAY) && (BSD > 43) 125829088Smarkm (void) revoke(line); 125929088Smarkm# endif 126029088Smarkm#ifdef UNICOS7x 126129088Smarkm if (secflag) { 126229088Smarkm if (secstat(line, &secbuf) < 0) 126329088Smarkm return(-1); 126429088Smarkm if (setulvl(secbuf.st_slevel) < 0) 126529088Smarkm return(-1); 126629088Smarkm if (setucmp(secbuf.st_compart) < 0) 126729088Smarkm return(-1); 126829088Smarkm } 126929088Smarkm#endif /* UNICOS7x */ 127029088Smarkm 127129088Smarkm t = open(line, O_RDWR|O_NOCTTY); 127229088Smarkm 127329088Smarkm#ifdef UNICOS7x 127429088Smarkm if (secflag) { 127529088Smarkm if (setulvl(sysv.sy_minlvl) < 0) 127629088Smarkm return(-1); 127729088Smarkm if (setucmp(0) < 0) 127829088Smarkm return(-1); 127929088Smarkm } 128029088Smarkm#endif /* UNICOS7x */ 128129088Smarkm 128229088Smarkm if (t < 0) 128329088Smarkm return(-1); 128429088Smarkm 128529088Smarkm /* 128629088Smarkm * Hangup anybody else using this ttyp, then reopen it for 128729088Smarkm * ourselves. 128829088Smarkm */ 128929088Smarkm# if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY) 129029088Smarkm (void) signal(SIGHUP, SIG_IGN); 129129088Smarkm vhangup(); 129229088Smarkm (void) signal(SIGHUP, SIG_DFL); 129329088Smarkm t = open(line, O_RDWR|O_NOCTTY); 129429088Smarkm if (t < 0) 129529088Smarkm return(-1); 129629088Smarkm# endif 129729088Smarkm# if defined(CRAY) && defined(TCVHUP) 129829088Smarkm { 129929088Smarkm register int i; 130029088Smarkm (void) signal(SIGHUP, SIG_IGN); 130129088Smarkm (void) ioctl(t, TCVHUP, (char *)0); 130229088Smarkm (void) signal(SIGHUP, SIG_DFL); 130329088Smarkm 130429088Smarkm#ifdef UNICOS7x 130529088Smarkm if (secflag) { 130629088Smarkm if (secstat(line, &secbuf) < 0) 130729088Smarkm return(-1); 130829088Smarkm if (setulvl(secbuf.st_slevel) < 0) 130929088Smarkm return(-1); 131029088Smarkm if (setucmp(secbuf.st_compart) < 0) 131129088Smarkm return(-1); 131229088Smarkm } 131329088Smarkm#endif /* UNICOS7x */ 131429088Smarkm 131529088Smarkm i = open(line, O_RDWR); 131629088Smarkm 131729088Smarkm#ifdef UNICOS7x 131829088Smarkm if (secflag) { 131929088Smarkm if (setulvl(sysv.sy_minlvl) < 0) 132029088Smarkm return(-1); 132129088Smarkm if (setucmp(0) < 0) 132229088Smarkm return(-1); 132329088Smarkm } 132429088Smarkm#endif /* UNICOS7x */ 132529088Smarkm 132629088Smarkm if (i < 0) 132729088Smarkm return(-1); 132829088Smarkm (void) close(t); 132929088Smarkm t = i; 133029088Smarkm } 133129088Smarkm# endif /* defined(CRAY) && defined(TCVHUP) */ 133229088Smarkm return(t); 133329088Smarkm} 133429088Smarkm#endif /* !defined(CRAY) || !defined(NEWINIT) */ 133529088Smarkm 133629088Smarkm#if BSD <= 43 133729088Smarkm 133829088Smarkm int 133929088Smarkmlogin_tty(t) 134029088Smarkm int t; 134129088Smarkm{ 134229088Smarkm if (setsid() < 0) { 134329088Smarkm#ifdef ultrix 134429088Smarkm /* 134529088Smarkm * The setsid() may have failed because we 134629088Smarkm * already have a pgrp == pid. Zero out 134729088Smarkm * our pgrp and try again... 134829088Smarkm */ 134929088Smarkm if ((setpgrp(0, 0) < 0) || (setsid() < 0)) 135029088Smarkm#endif 135129088Smarkm fatalperror(net, "setsid()"); 135229088Smarkm } 135329088Smarkm# ifdef TIOCSCTTY 135429088Smarkm if (ioctl(t, TIOCSCTTY, (char *)0) < 0) 135529088Smarkm fatalperror(net, "ioctl(sctty)"); 135629088Smarkm# if defined(CRAY) 135729088Smarkm /* 135829088Smarkm * Close the hard fd to /dev/ttypXXX, and re-open through 135929088Smarkm * the indirect /dev/tty interface. 136029088Smarkm */ 136129088Smarkm close(t); 136229088Smarkm if ((t = open("/dev/tty", O_RDWR)) < 0) 136329088Smarkm fatalperror(net, "open(/dev/tty)"); 136429088Smarkm# endif 136529088Smarkm# else 136629088Smarkm /* 136729088Smarkm * We get our controlling tty assigned as a side-effect 136829088Smarkm * of opening up a tty device. But on BSD based systems, 136929088Smarkm * this only happens if our process group is zero. The 137029088Smarkm * setsid() call above may have set our pgrp, so clear 137129088Smarkm * it out before opening the tty... 137229088Smarkm */ 137329088Smarkm# ifndef SOLARIS 137429088Smarkm (void) setpgrp(0, 0); 137529088Smarkm# else 137629088Smarkm (void) setpgrp(); 137729088Smarkm# endif 137829088Smarkm close(open(line, O_RDWR)); 137929088Smarkm# endif 138029088Smarkm if (t != 0) 138129088Smarkm (void) dup2(t, 0); 138229088Smarkm if (t != 1) 138329088Smarkm (void) dup2(t, 1); 138429088Smarkm if (t != 2) 138529088Smarkm (void) dup2(t, 2); 138629088Smarkm if (t > 2) 138729088Smarkm close(t); 138829088Smarkm return(0); 138929088Smarkm} 139029088Smarkm#endif /* BSD <= 43 */ 139129088Smarkm 139229088Smarkm#ifdef NEWINIT 139329088Smarkmchar *gen_id = "fe"; 139429088Smarkm#endif 139529088Smarkm 139629088Smarkm/* 139729088Smarkm * startslave(host) 139829088Smarkm * 139929088Smarkm * Given a hostname, do whatever 140029088Smarkm * is necessary to startup the login process on the slave side of the pty. 140129088Smarkm */ 140229088Smarkm 140329088Smarkm/* ARGSUSED */ 140429088Smarkm void 140529088Smarkmstartslave(host, autologin, autoname) 140629088Smarkm char *host; 140729088Smarkm int autologin; 140829088Smarkm char *autoname; 140929088Smarkm{ 141029088Smarkm register int i; 141129088Smarkm#ifdef NEWINIT 141229088Smarkm extern char *ptyip; 141329088Smarkm struct init_request request; 141429088Smarkm void nologinproc(); 141529088Smarkm register int n; 141629088Smarkm#endif /* NEWINIT */ 141729088Smarkm 141829088Smarkm#if defined(AUTHENTICATION) 141929088Smarkm if (!autoname || !autoname[0]) 142029088Smarkm autologin = 0; 142129088Smarkm 142229088Smarkm if (autologin < auth_level) { 142329088Smarkm fatal(net, "Authorization failed"); 142429088Smarkm exit(1); 142529088Smarkm } 142629088Smarkm#endif 142729088Smarkm 142829088Smarkm#ifndef NEWINIT 142929088Smarkm# ifdef PARENT_DOES_UTMP 143029088Smarkm utmp_sig_init(); 143129088Smarkm# endif /* PARENT_DOES_UTMP */ 143229088Smarkm 143329088Smarkm if ((i = fork()) < 0) 143429088Smarkm fatalperror(net, "fork"); 143529088Smarkm if (i) { 143629088Smarkm# ifdef PARENT_DOES_UTMP 143729088Smarkm /* 143829088Smarkm * Cray parent will create utmp entry for child and send 143929088Smarkm * signal to child to tell when done. Child waits for signal 144029088Smarkm * before doing anything important. 144129088Smarkm */ 144229088Smarkm register int pid = i; 144329088Smarkm void sigjob P((int)); 144429088Smarkm 144529088Smarkm setpgrp(); 144629088Smarkm utmp_sig_reset(); /* reset handler to default */ 144729088Smarkm /* 144829088Smarkm * Create utmp entry for child 144929088Smarkm */ 145029088Smarkm (void) time(&wtmp.ut_time); 145129088Smarkm wtmp.ut_type = LOGIN_PROCESS; 145229088Smarkm wtmp.ut_pid = pid; 145329088Smarkm SCPYN(wtmp.ut_user, "LOGIN"); 145429088Smarkm SCPYN(wtmp.ut_host, host); 145529088Smarkm SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); 145629088Smarkm#ifndef __hpux 145729088Smarkm SCPYN(wtmp.ut_id, wtmp.ut_line+3); 145829088Smarkm#else 145929088Smarkm SCPYN(wtmp.ut_id, wtmp.ut_line+7); 146029088Smarkm#endif 146129088Smarkm pututline(&wtmp); 146229088Smarkm endutent(); 146329088Smarkm if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { 146429088Smarkm (void) write(i, (char *)&wtmp, sizeof(struct utmp)); 146529088Smarkm (void) close(i); 146629088Smarkm } 146729088Smarkm#ifdef CRAY 146829088Smarkm (void) signal(WJSIGNAL, sigjob); 146929088Smarkm#endif 147029088Smarkm utmp_sig_notify(pid); 147129088Smarkm# endif /* PARENT_DOES_UTMP */ 147229088Smarkm } else { 147329088Smarkm getptyslave(autologin); 147429088Smarkm start_login(host, autologin, autoname); 147529088Smarkm /*NOTREACHED*/ 147629088Smarkm } 147729088Smarkm#else /* NEWINIT */ 147829088Smarkm 147929088Smarkm /* 148029088Smarkm * Init will start up login process if we ask nicely. We only wait 148129088Smarkm * for it to start up and begin normal telnet operation. 148229088Smarkm */ 148329088Smarkm if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { 148429088Smarkm char tbuf[128]; 148532688Simp (void) snprintf(tbuf, sizeof(tbuf), "Can't open %s\n", INIT_FIFO); 148629088Smarkm fatalperror(net, tbuf); 148729088Smarkm } 148829088Smarkm memset((char *)&request, 0, sizeof(request)); 148929088Smarkm request.magic = INIT_MAGIC; 149029088Smarkm SCPYN(request.gen_id, gen_id); 149129088Smarkm SCPYN(request.tty_id, &line[8]); 149229088Smarkm SCPYN(request.host, host); 149329088Smarkm SCPYN(request.term_type, terminaltype ? terminaltype : "network"); 149429088Smarkm#if !defined(UNICOS5) 149529088Smarkm request.signal = SIGCLD; 149629088Smarkm request.pid = getpid(); 149729088Smarkm#endif 149829088Smarkm#ifdef BFTPDAEMON 149929088Smarkm /* 150029088Smarkm * Are we working as the bftp daemon? 150129088Smarkm */ 150229088Smarkm if (bftpd) { 150329088Smarkm SCPYN(request.exec_name, BFTPPATH); 150429088Smarkm } 150529088Smarkm#endif /* BFTPDAEMON */ 150629088Smarkm if (write(i, (char *)&request, sizeof(request)) < 0) { 150729088Smarkm char tbuf[128]; 150832688Simp (void) snprintf(tbuf, sizeof(tbuf), "Can't write to %s\n", INIT_FIFO); 150929088Smarkm fatalperror(net, tbuf); 151029088Smarkm } 151129088Smarkm (void) close(i); 151229088Smarkm (void) signal(SIGALRM, nologinproc); 151329088Smarkm for (i = 0; ; i++) { 151429088Smarkm char tbuf[128]; 151529088Smarkm alarm(15); 151629088Smarkm n = read(pty, ptyip, BUFSIZ); 151729088Smarkm if (i == 3 || n >= 0 || !gotalarm) 151829088Smarkm break; 151929088Smarkm gotalarm = 0; 152032688Simp snprintf(tbuf, sizeof(tbuf), "telnetd: waiting for /etc/init to start login process on %s\r\n", line); 152129088Smarkm (void) write(net, tbuf, strlen(tbuf)); 152229088Smarkm } 152329088Smarkm if (n < 0 && gotalarm) 152429088Smarkm fatal(net, "/etc/init didn't start login process"); 152529088Smarkm pcc += n; 152629088Smarkm alarm(0); 152729088Smarkm (void) signal(SIGALRM, SIG_DFL); 152829088Smarkm 152929088Smarkm return; 153029088Smarkm#endif /* NEWINIT */ 153129088Smarkm} 153229088Smarkm 153329088Smarkmchar *envinit[3]; 153429088Smarkmextern char **environ; 153529088Smarkm 153629088Smarkm void 153729088Smarkminit_env() 153829088Smarkm{ 153929088Smarkm extern char *getenv(); 154029088Smarkm char **envp; 154129088Smarkm 154229088Smarkm envp = envinit; 154329181Smarkm if ((*envp = getenv("TZ"))) 154429088Smarkm *envp++ -= 3; 154529088Smarkm#if defined(CRAY) || defined(__hpux) 154629088Smarkm else 154729088Smarkm *envp++ = "TZ=GMT0"; 154829088Smarkm#endif 154929088Smarkm *envp = 0; 155029088Smarkm environ = envinit; 155129088Smarkm} 155229088Smarkm 155329088Smarkm#ifndef NEWINIT 155429088Smarkm 155529088Smarkm/* 155629088Smarkm * start_login(host) 155729088Smarkm * 155829088Smarkm * Assuming that we are now running as a child processes, this 155929088Smarkm * function will turn us into the login process. 156029088Smarkm */ 156129088Smarkm 156229088Smarkm void 156329088Smarkmstart_login(host, autologin, name) 156429088Smarkm char *host; 156529088Smarkm int autologin; 156629088Smarkm char *name; 156729088Smarkm{ 156829088Smarkm register char **argv; 156929181Smarkm char **addarg(), *user; 157029088Smarkm extern char *getenv(); 157129088Smarkm#ifdef UTMPX 157229088Smarkm register int pid = getpid(); 157329088Smarkm struct utmpx utmpx; 157429088Smarkm#endif 157529088Smarkm#ifdef SOLARIS 157629088Smarkm char *term; 157729088Smarkm char termbuf[64]; 157829088Smarkm#endif 157929088Smarkm 158029088Smarkm#ifdef UTMPX 158129088Smarkm /* 158229088Smarkm * Create utmp entry for child 158329088Smarkm */ 158429088Smarkm 158529088Smarkm memset(&utmpx, 0, sizeof(utmpx)); 158629088Smarkm SCPYN(utmpx.ut_user, ".telnet"); 158729088Smarkm SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); 158829088Smarkm utmpx.ut_pid = pid; 158929088Smarkm utmpx.ut_id[0] = 't'; 159029088Smarkm utmpx.ut_id[1] = 'n'; 159129088Smarkm utmpx.ut_id[2] = SC_WILDC; 159229088Smarkm utmpx.ut_id[3] = SC_WILDC; 159329088Smarkm utmpx.ut_type = LOGIN_PROCESS; 159429088Smarkm (void) time(&utmpx.ut_tv.tv_sec); 159529088Smarkm if (makeutx(&utmpx) == NULL) 159629088Smarkm fatal(net, "makeutx failed"); 159729088Smarkm#endif 159829088Smarkm 159929088Smarkm scrub_env(); 160029088Smarkm 160129088Smarkm /* 160229088Smarkm * -h : pass on name of host. 160329088Smarkm * WARNING: -h is accepted by login if and only if 160429088Smarkm * getuid() == 0. 160529088Smarkm * -p : don't clobber the environment (so terminal type stays set). 160629088Smarkm * 160729088Smarkm * -f : force this login, he has already been authenticated 160829088Smarkm */ 160929088Smarkm argv = addarg(0, "login"); 161029088Smarkm 161129088Smarkm#if !defined(NO_LOGIN_H) 161229088Smarkm 161329088Smarkm# if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 161429088Smarkm /* 161529088Smarkm * Don't add the "-h host" option if we are going 161629088Smarkm * to be adding the "-r host" option down below... 161729088Smarkm */ 161829088Smarkm if ((auth_level < 0) || (autologin != AUTH_VALID)) 161929088Smarkm# endif 162029088Smarkm { 162129088Smarkm argv = addarg(argv, "-h"); 162229088Smarkm argv = addarg(argv, host); 162329088Smarkm#ifdef SOLARIS 162429088Smarkm /* 162529088Smarkm * SVR4 version of -h takes TERM= as second arg, or - 162629088Smarkm */ 162729088Smarkm term = getenv("TERM"); 162829088Smarkm if (term == NULL || term[0] == 0) { 162929088Smarkm term = "-"; 163029088Smarkm } else { 163129088Smarkm strcpy(termbuf, "TERM="); 163229088Smarkm strncat(termbuf, term, sizeof(termbuf) - 6); 163329088Smarkm term = termbuf; 163429088Smarkm } 163529088Smarkm argv = addarg(argv, term); 163629088Smarkm#endif 163729088Smarkm } 163829088Smarkm#endif 163929088Smarkm#if !defined(NO_LOGIN_P) 164029088Smarkm argv = addarg(argv, "-p"); 164129088Smarkm#endif 164229088Smarkm#ifdef LINEMODE 164329088Smarkm /* 164429088Smarkm * Set the environment variable "LINEMODE" to either 164529088Smarkm * "real" or "kludge" if we are operating in either 164629088Smarkm * real or kludge linemode. 164729088Smarkm */ 164829088Smarkm if (lmodetype == REAL_LINEMODE) 164929088Smarkm setenv("LINEMODE", "real", 1); 165029088Smarkm# ifdef KLUDGELINEMODE 165129088Smarkm else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK) 165229088Smarkm setenv("LINEMODE", "kludge", 1); 165329088Smarkm# endif 165429088Smarkm#endif 165529088Smarkm#ifdef BFTPDAEMON 165629088Smarkm /* 165729088Smarkm * Are we working as the bftp daemon? If so, then ask login 165829088Smarkm * to start bftp instead of shell. 165929088Smarkm */ 166029088Smarkm if (bftpd) { 166129088Smarkm argv = addarg(argv, "-e"); 166229088Smarkm argv = addarg(argv, BFTPPATH); 166329088Smarkm } else 166429088Smarkm#endif 166529088Smarkm#if defined (SecurID) 166629088Smarkm /* 166729088Smarkm * don't worry about the -f that might get sent. 166829088Smarkm * A -s is supposed to override it anyhow. 166929088Smarkm */ 167029088Smarkm if (require_SecurID) 167129088Smarkm argv = addarg(argv, "-s"); 167229088Smarkm#endif 167329088Smarkm#if defined (AUTHENTICATION) 167429088Smarkm if (auth_level >= 0 && autologin == AUTH_VALID) { 167529088Smarkm# if !defined(NO_LOGIN_F) 167629088Smarkm argv = addarg(argv, "-f"); 167729181Smarkm argv = addarg(argv, "--"); 167829088Smarkm argv = addarg(argv, name); 167929088Smarkm# else 168029088Smarkm# if defined(LOGIN_R) 168129088Smarkm /* 168229088Smarkm * We don't have support for "login -f", but we 168329088Smarkm * can fool /bin/login into thinking that we are 168429088Smarkm * rlogind, and allow us to log in without a 168529088Smarkm * password. The rlogin protocol expects 168629088Smarkm * local-user\0remote-user\0term/speed\0 168729088Smarkm */ 168829088Smarkm 168929088Smarkm if (pty > 2) { 169029088Smarkm register char *cp; 169129088Smarkm char speed[128]; 169229088Smarkm int isecho, israw, xpty, len; 169329088Smarkm extern int def_rspeed; 169429088Smarkm# ifndef LOGIN_HOST 169529088Smarkm /* 169629088Smarkm * Tell login that we are coming from "localhost". 169729088Smarkm * If we passed in the real host name, then the 169829088Smarkm * user would have to allow .rhost access from 169929088Smarkm * every machine that they want authenticated 170029088Smarkm * access to work from, which sort of defeats 170129088Smarkm * the purpose of an authenticated login... 170229088Smarkm * So, we tell login that the session is coming 170329088Smarkm * from "localhost", and the user will only have 170429088Smarkm * to have "localhost" in their .rhost file. 170529088Smarkm */ 170629088Smarkm# define LOGIN_HOST "localhost" 170729088Smarkm# endif 170829088Smarkm argv = addarg(argv, "-r"); 170929088Smarkm argv = addarg(argv, LOGIN_HOST); 171029088Smarkm 171129088Smarkm xpty = pty; 171229088Smarkm# ifndef STREAMSPTY 171329088Smarkm pty = 0; 171429088Smarkm# else 171529088Smarkm ttyfd = 0; 171629088Smarkm# endif 171729088Smarkm init_termbuf(); 171829088Smarkm isecho = tty_isecho(); 171929088Smarkm israw = tty_israw(); 172029088Smarkm if (isecho || !israw) { 172129088Smarkm tty_setecho(0); /* Turn off echo */ 172229088Smarkm tty_setraw(1); /* Turn on raw */ 172329088Smarkm set_termbuf(); 172429088Smarkm } 172529088Smarkm len = strlen(name)+1; 172629088Smarkm write(xpty, name, len); 172729088Smarkm write(xpty, name, len); 172832688Simp snprintf(speed, sizeof(speed), 172932688Simp "%s/%d", (cp = getenv("TERM")) ? cp : "", 173029088Smarkm (def_rspeed > 0) ? def_rspeed : 9600); 173129088Smarkm len = strlen(speed)+1; 173229088Smarkm write(xpty, speed, len); 173329088Smarkm 173429088Smarkm if (isecho || !israw) { 173529088Smarkm init_termbuf(); 173629088Smarkm tty_setecho(isecho); 173729088Smarkm tty_setraw(israw); 173829088Smarkm set_termbuf(); 173929088Smarkm if (!israw) { 174029088Smarkm /* 174129088Smarkm * Write a newline to ensure 174229088Smarkm * that login will be able to 174329088Smarkm * read the line... 174429088Smarkm */ 174529088Smarkm write(xpty, "\n", 1); 174629088Smarkm } 174729088Smarkm } 174829088Smarkm pty = xpty; 174929088Smarkm } 175029088Smarkm# else 175129181Smarkm argv = addarg(argv, "--"); 175229088Smarkm argv = addarg(argv, name); 175329088Smarkm# endif 175429088Smarkm# endif 175529088Smarkm } else 175629088Smarkm#endif 175729088Smarkm if (getenv("USER")) { 175829181Smarkm argv = addarg(argv, "--"); 175929088Smarkm argv = addarg(argv, getenv("USER")); 176029088Smarkm#if defined(LOGIN_ARGS) && defined(NO_LOGIN_P) 176129088Smarkm { 176229088Smarkm register char **cpp; 176329088Smarkm for (cpp = environ; *cpp; cpp++) 176429088Smarkm argv = addarg(argv, *cpp); 176529088Smarkm } 176629088Smarkm#endif 176729088Smarkm /* 176829088Smarkm * Assume that login will set the USER variable 176929088Smarkm * correctly. For SysV systems, this means that 177029088Smarkm * USER will no longer be set, just LOGNAME by 177129088Smarkm * login. (The problem is that if the auto-login 177229088Smarkm * fails, and the user then specifies a different 177329088Smarkm * account name, he can get logged in with both 177429088Smarkm * LOGNAME and USER in his environment, but the 177529088Smarkm * USER value will be wrong. 177629088Smarkm */ 177729088Smarkm unsetenv("USER"); 177829088Smarkm } 177929088Smarkm#ifdef SOLARIS 178029088Smarkm else { 178129088Smarkm char **p; 178229088Smarkm 178329088Smarkm argv = addarg(argv, ""); /* no login name */ 178429088Smarkm for (p = environ; *p; p++) { 178529088Smarkm argv = addarg(argv, *p); 178629088Smarkm } 178729088Smarkm } 178829088Smarkm#endif /* SOLARIS */ 178929088Smarkm#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) 179029088Smarkm if (pty > 2) 179129088Smarkm close(pty); 179229088Smarkm#endif 179329088Smarkm closelog(); 179429088Smarkm 179529181Smarkm if (altlogin == NULL) { 179629181Smarkm altlogin = _PATH_LOGIN; 179729181Smarkm } 179829181Smarkm execv(altlogin, argv); 179929181Smarkm 180031622Scharnier syslog(LOG_ERR, "%s: %m", altlogin); 180129181Smarkm fatalperror(net, altlogin); 180229088Smarkm /*NOTREACHED*/ 180329088Smarkm} 180429088Smarkm 180529088Smarkm char ** 180629088Smarkmaddarg(argv, val) 180729088Smarkm register char **argv; 180829088Smarkm register char *val; 180929088Smarkm{ 181029088Smarkm register char **cpp; 181129088Smarkm 181229088Smarkm if (argv == NULL) { 181329088Smarkm /* 181429088Smarkm * 10 entries, a leading length, and a null 181529088Smarkm */ 181629088Smarkm argv = (char **)malloc(sizeof(*argv) * 12); 181729088Smarkm if (argv == NULL) 181829088Smarkm return(NULL); 181929088Smarkm *argv++ = (char *)10; 182029088Smarkm *argv = (char *)0; 182129088Smarkm } 182229088Smarkm for (cpp = argv; *cpp; cpp++) 182329088Smarkm ; 182429088Smarkm if (cpp == &argv[(int)argv[-1]]) { 182529088Smarkm --argv; 182629088Smarkm *argv = (char *)((int)(*argv) + 10); 182729088Smarkm argv = (char **)realloc(argv, sizeof(*argv)*((int)(*argv) + 2)); 182829088Smarkm if (argv == NULL) 182929088Smarkm return(NULL); 183029088Smarkm argv++; 183129088Smarkm cpp = &argv[(int)argv[-1] - 10]; 183229088Smarkm } 183329088Smarkm *cpp++ = val; 183429088Smarkm *cpp = 0; 183529088Smarkm return(argv); 183629088Smarkm} 183729088Smarkm#endif /* NEWINIT */ 183829088Smarkm 183929088Smarkm/* 184029088Smarkm * scrub_env() 184129088Smarkm * 184269825Sassar * We only accept the environment variables listed below. 184329088Smarkm */ 184429181Smarkm void 184529088Smarkmscrub_env() 184629088Smarkm{ 184769825Sassar static const char *reject[] = { 184869825Sassar "TERMCAP=/", 184969825Sassar NULL 185069825Sassar }; 185129088Smarkm 185269825Sassar static const char *accept[] = { 185369825Sassar "XAUTH=", "XAUTHORITY=", "DISPLAY=", 185469825Sassar "TERM=", 185569825Sassar "EDITOR=", 185669825Sassar "PAGER=", 185769825Sassar "LOGNAME=", 185869825Sassar "POSIXLY_CORRECT=", 185969825Sassar "PRINTER=", 186069825Sassar NULL 186169825Sassar }; 186269825Sassar 186369825Sassar char **cpp, **cpp2; 186469825Sassar const char **p; 186569825Sassar 186669825Sassar for (cpp2 = cpp = environ; *cpp; cpp++) { 186769825Sassar int reject_it = 0; 186869825Sassar 186969825Sassar for(p = reject; *p; p++) 187069825Sassar if(strncmp(*cpp, *p, strlen(*p)) == 0) { 187169825Sassar reject_it = 1; 187269825Sassar break; 187369825Sassar } 187469825Sassar if (reject_it) 187569825Sassar continue; 187669825Sassar 187769825Sassar for(p = accept; *p; p++) 187869825Sassar if(strncmp(*cpp, *p, strlen(*p)) == 0) 187969825Sassar break; 188069825Sassar if(*p != NULL) 188169825Sassar *cpp2++ = *cpp; 188269825Sassar } 188369825Sassar *cpp2 = NULL; 188429088Smarkm} 188529088Smarkm 188629088Smarkm/* 188729088Smarkm * cleanup() 188829088Smarkm * 188929088Smarkm * This is the routine to call when we are all through, to 189029088Smarkm * clean up anything that needs to be cleaned up. 189129088Smarkm */ 189229088Smarkm /* ARGSUSED */ 189329088Smarkm void 189429088Smarkmcleanup(sig) 189529088Smarkm int sig; 189629088Smarkm{ 189729088Smarkm#ifndef PARENT_DOES_UTMP 189829088Smarkm# if (BSD > 43) || defined(convex) 189929088Smarkm char *p; 190029088Smarkm 190129088Smarkm p = line + sizeof("/dev/") - 1; 190229088Smarkm if (logout(p)) 190329088Smarkm logwtmp(p, "", ""); 190429088Smarkm (void)chmod(line, 0666); 190529088Smarkm (void)chown(line, 0, 0); 190629088Smarkm *p = 'p'; 190729088Smarkm (void)chmod(line, 0666); 190829088Smarkm (void)chown(line, 0, 0); 190929088Smarkm (void) shutdown(net, 2); 191029088Smarkm exit(1); 191129088Smarkm# else 191229088Smarkm void rmut(); 191329088Smarkm 191429088Smarkm rmut(); 191529088Smarkm vhangup(); /* XXX */ 191629088Smarkm (void) shutdown(net, 2); 191729088Smarkm exit(1); 191829088Smarkm# endif 191929088Smarkm#else /* PARENT_DOES_UTMP */ 192029088Smarkm# ifdef NEWINIT 192129088Smarkm (void) shutdown(net, 2); 192229088Smarkm exit(1); 192329088Smarkm# else /* NEWINIT */ 192429088Smarkm# ifdef CRAY 192529088Smarkm static int incleanup = 0; 192629088Smarkm register int t; 192729088Smarkm int child_status; /* status of child process as returned by waitpid */ 192829088Smarkm int flags = WNOHANG|WUNTRACED; 192929088Smarkm 193029088Smarkm /* 193129088Smarkm * 1: Pick up the zombie, if we are being called 193229088Smarkm * as the signal handler. 193329088Smarkm * 2: If we are a nested cleanup(), return. 193429088Smarkm * 3: Try to clean up TMPDIR. 193529088Smarkm * 4: Fill in utmp with shutdown of process. 193629088Smarkm * 5: Close down the network and pty connections. 193729088Smarkm * 6: Finish up the TMPDIR cleanup, if needed. 193829088Smarkm */ 193929088Smarkm if (sig == SIGCHLD) { 194029088Smarkm while (waitpid(-1, &child_status, flags) > 0) 194129088Smarkm ; /* VOID */ 194229088Smarkm /* Check if the child process was stopped 194329088Smarkm * rather than exited. We want cleanup only if 194429088Smarkm * the child has died. 194529088Smarkm */ 194629088Smarkm if (WIFSTOPPED(child_status)) { 194729088Smarkm return; 194829088Smarkm } 194929088Smarkm } 195029088Smarkm t = sigblock(sigmask(SIGCHLD)); 195129088Smarkm if (incleanup) { 195229088Smarkm sigsetmask(t); 195329088Smarkm return; 195429088Smarkm } 195529088Smarkm incleanup = 1; 195629088Smarkm sigsetmask(t); 195729088Smarkm#ifdef UNICOS7x 195829088Smarkm if (secflag) { 195929088Smarkm /* 196029088Smarkm * We need to set ourselves back to a null 196129088Smarkm * label to clean up. 196229088Smarkm */ 196329088Smarkm 196429088Smarkm setulvl(sysv.sy_minlvl); 196529088Smarkm setucmp((long)0); 196629088Smarkm } 196729088Smarkm#endif /* UNICOS7x */ 196829088Smarkm 196929088Smarkm t = cleantmp(&wtmp); 197029088Smarkm setutent(); /* just to make sure */ 197129088Smarkm# endif /* CRAY */ 197229088Smarkm rmut(line); 197329088Smarkm close(pty); 197429088Smarkm (void) shutdown(net, 2); 197529088Smarkm# ifdef CRAY 197629088Smarkm if (t == 0) 197729088Smarkm cleantmp(&wtmp); 197829088Smarkm# endif /* CRAY */ 197929088Smarkm exit(1); 198029088Smarkm# endif /* NEWINT */ 198129088Smarkm#endif /* PARENT_DOES_UTMP */ 198229088Smarkm} 198329088Smarkm 198429088Smarkm#if defined(PARENT_DOES_UTMP) && !defined(NEWINIT) 198529088Smarkm/* 198629088Smarkm * _utmp_sig_rcv 198729088Smarkm * utmp_sig_init 198829088Smarkm * utmp_sig_wait 198929088Smarkm * These three functions are used to coordinate the handling of 199029088Smarkm * the utmp file between the server and the soon-to-be-login shell. 199129088Smarkm * The server actually creates the utmp structure, the child calls 199229088Smarkm * utmp_sig_wait(), until the server calls utmp_sig_notify() and 199329088Smarkm * signals the future-login shell to proceed. 199429088Smarkm */ 199529088Smarkmstatic int caught=0; /* NZ when signal intercepted */ 199629088Smarkmstatic void (*func)(); /* address of previous handler */ 199729088Smarkm 199829088Smarkm void 199929088Smarkm_utmp_sig_rcv(sig) 200029088Smarkm int sig; 200129088Smarkm{ 200229088Smarkm caught = 1; 200329088Smarkm (void) signal(SIGUSR1, func); 200429088Smarkm} 200529088Smarkm 200629088Smarkm void 200729088Smarkmutmp_sig_init() 200829088Smarkm{ 200929088Smarkm /* 201029088Smarkm * register signal handler for UTMP creation 201129088Smarkm */ 201229088Smarkm if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) 201329088Smarkm fatalperror(net, "telnetd/signal"); 201429088Smarkm} 201529088Smarkm 201629088Smarkm void 201729088Smarkmutmp_sig_reset() 201829088Smarkm{ 201929088Smarkm (void) signal(SIGUSR1, func); /* reset handler to default */ 202029088Smarkm} 202129088Smarkm 202229088Smarkm# ifdef __hpux 202329088Smarkm# define sigoff() /* do nothing */ 202429088Smarkm# define sigon() /* do nothing */ 202529088Smarkm# endif 202629088Smarkm 202729088Smarkm void 202829088Smarkmutmp_sig_wait() 202929088Smarkm{ 203029088Smarkm /* 203129088Smarkm * Wait for parent to write our utmp entry. 203229088Smarkm */ 203329088Smarkm sigoff(); 203429088Smarkm while (caught == 0) { 203529088Smarkm pause(); /* wait until we get a signal (sigon) */ 203629088Smarkm sigoff(); /* turn off signals while we check caught */ 203729088Smarkm } 203829088Smarkm sigon(); /* turn on signals again */ 203929088Smarkm} 204029088Smarkm 204129088Smarkm void 204229088Smarkmutmp_sig_notify(pid) 204329088Smarkm{ 204429088Smarkm kill(pid, SIGUSR1); 204529088Smarkm} 204629088Smarkm 204729088Smarkm# ifdef CRAY 204829088Smarkmstatic int gotsigjob = 0; 204929088Smarkm 205029088Smarkm /*ARGSUSED*/ 205129088Smarkm void 205229088Smarkmsigjob(sig) 205329088Smarkm int sig; 205429088Smarkm{ 205529088Smarkm register int jid; 205629088Smarkm register struct jobtemp *jp; 205729088Smarkm 205829088Smarkm while ((jid = waitjob(NULL)) != -1) { 205929088Smarkm if (jid == 0) { 206029088Smarkm return; 206129088Smarkm } 206229088Smarkm gotsigjob++; 206329088Smarkm jobend(jid, NULL, NULL); 206429088Smarkm } 206529088Smarkm} 206629088Smarkm 206729088Smarkm/* 206829088Smarkm * jid_getutid: 206929088Smarkm * called by jobend() before calling cleantmp() 207029088Smarkm * to find the correct $TMPDIR to cleanup. 207129088Smarkm */ 207229088Smarkm 207329088Smarkm struct utmp * 207429088Smarkmjid_getutid(jid) 207529088Smarkm int jid; 207629088Smarkm{ 207729088Smarkm struct utmp *cur = NULL; 207829088Smarkm 207929088Smarkm setutent(); /* just to make sure */ 208029088Smarkm while (cur = getutent()) { 208129088Smarkm if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) { 208229088Smarkm return(cur); 208329088Smarkm } 208429088Smarkm } 208529088Smarkm 208629088Smarkm return(0); 208729088Smarkm} 208829088Smarkm 208929088Smarkm/* 209029088Smarkm * Clean up the TMPDIR that login created. 209129088Smarkm * The first time this is called we pick up the info 209229088Smarkm * from the utmp. If the job has already gone away, 209329088Smarkm * then we'll clean up and be done. If not, then 209429088Smarkm * when this is called the second time it will wait 209529088Smarkm * for the signal that the job is done. 209629088Smarkm */ 209729088Smarkm int 209829088Smarkmcleantmp(wtp) 209929088Smarkm register struct utmp *wtp; 210029088Smarkm{ 210129088Smarkm struct utmp *utp; 210229088Smarkm static int first = 1; 210329088Smarkm register int mask, omask, ret; 210429088Smarkm extern struct utmp *getutid P((const struct utmp *_Id)); 210529088Smarkm 210629088Smarkm 210729088Smarkm mask = sigmask(WJSIGNAL); 210829088Smarkm 210929088Smarkm if (first == 0) { 211029088Smarkm omask = sigblock(mask); 211129088Smarkm while (gotsigjob == 0) 211229088Smarkm sigpause(omask); 211329088Smarkm return(1); 211429088Smarkm } 211529088Smarkm first = 0; 211629088Smarkm setutent(); /* just to make sure */ 211729088Smarkm 211829088Smarkm utp = getutid(wtp); 211929088Smarkm if (utp == 0) { 212031622Scharnier syslog(LOG_ERR, "can't get /etc/utmp entry to clean TMPDIR"); 212129088Smarkm return(-1); 212229088Smarkm } 212329088Smarkm /* 212429088Smarkm * Nothing to clean up if the user shell was never started. 212529088Smarkm */ 212629088Smarkm if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) 212729088Smarkm return(1); 212829088Smarkm 212929088Smarkm /* 213029088Smarkm * Block the WJSIGNAL while we are in jobend(). 213129088Smarkm */ 213229088Smarkm omask = sigblock(mask); 213329088Smarkm ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); 213429088Smarkm sigsetmask(omask); 213529088Smarkm return(ret); 213629088Smarkm} 213729088Smarkm 213829088Smarkm int 213929088Smarkmjobend(jid, path, user) 214029088Smarkm register int jid; 214129088Smarkm register char *path; 214229088Smarkm register char *user; 214329088Smarkm{ 214429088Smarkm static int saved_jid = 0; 214529088Smarkm static int pty_saved_jid = 0; 214629088Smarkm static char saved_path[sizeof(wtmp.ut_tpath)+1]; 214729088Smarkm static char saved_user[sizeof(wtmp.ut_user)+1]; 214829088Smarkm 214929088Smarkm /* 215029088Smarkm * this little piece of code comes into play 215129088Smarkm * only when ptyreconnect is used to reconnect 215229088Smarkm * to an previous session. 215329088Smarkm * 215429088Smarkm * this is the only time when the 215529088Smarkm * "saved_jid != jid" code is executed. 215629088Smarkm */ 215729088Smarkm 215829088Smarkm if ( saved_jid && saved_jid != jid ) { 215929088Smarkm if (!path) { /* called from signal handler */ 216029088Smarkm pty_saved_jid = jid; 216129088Smarkm } else { 216229088Smarkm pty_saved_jid = saved_jid; 216329088Smarkm } 216429088Smarkm } 216529088Smarkm 216629088Smarkm if (path) { 216729088Smarkm strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); 216829088Smarkm strncpy(saved_user, user, sizeof(wtmp.ut_user)); 216929088Smarkm saved_path[sizeof(saved_path)] = '\0'; 217029088Smarkm saved_user[sizeof(saved_user)] = '\0'; 217129088Smarkm } 217229088Smarkm if (saved_jid == 0) { 217329088Smarkm saved_jid = jid; 217429088Smarkm return(0); 217529088Smarkm } 217629088Smarkm 217729088Smarkm /* if the jid has changed, get the correct entry from the utmp file */ 217829088Smarkm 217929088Smarkm if ( saved_jid != jid ) { 218029088Smarkm struct utmp *utp = NULL; 218129088Smarkm struct utmp *jid_getutid(); 218229088Smarkm 218329088Smarkm utp = jid_getutid(pty_saved_jid); 218429088Smarkm 218529088Smarkm if (utp == 0) { 218629088Smarkm syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); 218729088Smarkm return(-1); 218829088Smarkm } 218929088Smarkm 219029088Smarkm cleantmpdir(jid, utp->ut_tpath, utp->ut_user); 219129088Smarkm return(1); 219229088Smarkm } 219329088Smarkm 219429088Smarkm cleantmpdir(jid, saved_path, saved_user); 219529088Smarkm return(1); 219629088Smarkm} 219729088Smarkm 219829088Smarkm/* 219929088Smarkm * Fork a child process to clean up the TMPDIR 220029088Smarkm */ 220129088Smarkmcleantmpdir(jid, tpath, user) 220229088Smarkm register int jid; 220329088Smarkm register char *tpath; 220429088Smarkm register char *user; 220529088Smarkm{ 220629088Smarkm switch(fork()) { 220729088Smarkm case -1: 220831622Scharnier syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m", 220929088Smarkm tpath); 221029088Smarkm break; 221129088Smarkm case 0: 221229088Smarkm execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); 221331622Scharnier syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m", 221429088Smarkm tpath, CLEANTMPCMD); 221529088Smarkm exit(1); 221629088Smarkm default: 221729088Smarkm /* 221829088Smarkm * Forget about child. We will exit, and 221929088Smarkm * /etc/init will pick it up. 222029088Smarkm */ 222129088Smarkm break; 222229088Smarkm } 222329088Smarkm} 222429088Smarkm# endif /* CRAY */ 222529088Smarkm#endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */ 222629088Smarkm 222729088Smarkm/* 222829088Smarkm * rmut() 222929088Smarkm * 223029088Smarkm * This is the function called by cleanup() to 223129088Smarkm * remove the utmp entry for this person. 223229088Smarkm */ 223329088Smarkm 223429088Smarkm#ifdef UTMPX 223529088Smarkm void 223629088Smarkmrmut() 223729088Smarkm{ 223829088Smarkm register f; 223929088Smarkm int found = 0; 224029088Smarkm struct utmp *u, *utmp; 224129088Smarkm int nutmp; 224229088Smarkm struct stat statbf; 224329088Smarkm 224429088Smarkm struct utmpx *utxp, utmpx; 224529088Smarkm 224629088Smarkm /* 224729088Smarkm * This updates the utmpx and utmp entries and make a wtmp/x entry 224829088Smarkm */ 224929088Smarkm 225029088Smarkm SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); 225129088Smarkm utxp = getutxline(&utmpx); 225229088Smarkm if (utxp) { 225329088Smarkm utxp->ut_type = DEAD_PROCESS; 225429088Smarkm utxp->ut_exit.e_termination = 0; 225529088Smarkm utxp->ut_exit.e_exit = 0; 225629088Smarkm (void) time(&utmpx.ut_tv.tv_sec); 225729088Smarkm utmpx.ut_tv.tv_usec = 0; 225829088Smarkm modutx(utxp); 225929088Smarkm } 226029088Smarkm endutxent(); 226129088Smarkm} /* end of rmut */ 226229088Smarkm#endif 226329088Smarkm 226429088Smarkm#if !defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43 226529088Smarkm void 226629088Smarkmrmut() 226729088Smarkm{ 226829088Smarkm register f; 226929088Smarkm int found = 0; 227029088Smarkm struct utmp *u, *utmp; 227129088Smarkm int nutmp; 227229088Smarkm struct stat statbf; 227329088Smarkm 227429088Smarkm f = open(utmpf, O_RDWR); 227529088Smarkm if (f >= 0) { 227629088Smarkm (void) fstat(f, &statbf); 227729088Smarkm utmp = (struct utmp *)malloc((unsigned)statbf.st_size); 227829088Smarkm if (!utmp) 227929088Smarkm syslog(LOG_ERR, "utmp malloc failed"); 228029088Smarkm if (statbf.st_size && utmp) { 228129088Smarkm nutmp = read(f, (char *)utmp, (int)statbf.st_size); 228229088Smarkm nutmp /= sizeof(struct utmp); 228329088Smarkm 228429088Smarkm for (u = utmp ; u < &utmp[nutmp] ; u++) { 228529088Smarkm if (SCMPN(u->ut_line, line+5) || 228629088Smarkm u->ut_name[0]==0) 228729088Smarkm continue; 228829088Smarkm (void) lseek(f, ((long)u)-((long)utmp), L_SET); 228929088Smarkm SCPYN(u->ut_name, ""); 229029088Smarkm SCPYN(u->ut_host, ""); 229129088Smarkm (void) time(&u->ut_time); 229229088Smarkm (void) write(f, (char *)u, sizeof(wtmp)); 229329088Smarkm found++; 229429088Smarkm } 229529088Smarkm } 229629088Smarkm (void) close(f); 229729088Smarkm } 229829088Smarkm if (found) { 229929088Smarkm f = open(wtmpf, O_WRONLY|O_APPEND); 230029088Smarkm if (f >= 0) { 230129088Smarkm SCPYN(wtmp.ut_line, line+5); 230229088Smarkm SCPYN(wtmp.ut_name, ""); 230329088Smarkm SCPYN(wtmp.ut_host, ""); 230429088Smarkm (void) time(&wtmp.ut_time); 230529088Smarkm (void) write(f, (char *)&wtmp, sizeof(wtmp)); 230629088Smarkm (void) close(f); 230729088Smarkm } 230829088Smarkm } 230929088Smarkm (void) chmod(line, 0666); 231029088Smarkm (void) chown(line, 0, 0); 231129088Smarkm line[strlen("/dev/")] = 'p'; 231229088Smarkm (void) chmod(line, 0666); 231329088Smarkm (void) chown(line, 0, 0); 231429088Smarkm} /* end of rmut */ 231529088Smarkm#endif /* CRAY */ 231629088Smarkm 231729088Smarkm#ifdef __hpux 231829088Smarkmrmut (line) 231929088Smarkmchar *line; 232029088Smarkm{ 232129088Smarkm struct utmp utmp; 232229088Smarkm struct utmp *utptr; 232329088Smarkm int fd; /* for /etc/wtmp */ 232429088Smarkm 232529088Smarkm utmp.ut_type = USER_PROCESS; 232629088Smarkm (void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id)); 232729088Smarkm (void) setutent(); 232829088Smarkm utptr = getutid(&utmp); 232929088Smarkm /* write it out only if it exists */ 233029088Smarkm if (utptr) { 233129088Smarkm utptr->ut_type = DEAD_PROCESS; 233229088Smarkm utptr->ut_time = time((long *) 0); 233329088Smarkm (void) pututline(utptr); 233429088Smarkm /* set wtmp entry if wtmp file exists */ 233529088Smarkm if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) { 233629088Smarkm (void) write(fd, utptr, sizeof(utmp)); 233729088Smarkm (void) close(fd); 233829088Smarkm } 233929088Smarkm } 234029088Smarkm (void) endutent(); 234129088Smarkm 234229088Smarkm (void) chmod(line, 0666); 234329088Smarkm (void) chown(line, 0, 0); 234429088Smarkm line[14] = line[13]; 234529088Smarkm line[13] = line[12]; 234629088Smarkm line[8] = 'm'; 234729088Smarkm line[9] = '/'; 234829088Smarkm line[10] = 'p'; 234929088Smarkm line[11] = 't'; 235029088Smarkm line[12] = 'y'; 235129088Smarkm (void) chmod(line, 0666); 235229088Smarkm (void) chown(line, 0, 0); 235329088Smarkm} 235429088Smarkm#endif 2355