1251188Smarcel/* 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 34114630Sobrien#if 0 3529088Smarkm#ifndef lint 3629181Smarkmstatic const char sccsid[] = "@(#)sys_term.c 8.4+1 (Berkeley) 5/30/95"; 3731622Scharnier#endif 38114630Sobrien#endif 39114630Sobrien#include <sys/cdefs.h> 40114630Sobrien__FBSDID("$FreeBSD: releng/10.1/contrib/telnet/telnetd/sys_term.c 309636 2016-12-06 18:49:59Z glebius $"); 4129088Smarkm 4287139Smarkm#include <sys/types.h> 4387139Smarkm#include <sys/tty.h> 4487139Smarkm#include <libutil.h> 4587139Smarkm#include <stdlib.h> 4687139Smarkm 4729088Smarkm#include "telnetd.h" 4829088Smarkm#include "pathnames.h" 4929088Smarkm 5087139Smarkm#ifdef AUTHENTICATION 5129088Smarkm#include <libtelnet/auth.h> 5229088Smarkm#endif 5329088Smarkm 5487139Smarkmint cleanopen(char *); 5529181Smarkmvoid scrub_env(void); 5629181Smarkm 5787139Smarkmchar *envinit[3]; 5887139Smarkmextern char **environ; 5929181Smarkm 6029088Smarkm#define SCPYN(a, b) (void) strncpy(a, b, sizeof(a)) 6129088Smarkm#define SCMPN(a, b) strncmp(a, b, sizeof(a)) 6229088Smarkm 6329088Smarkm#ifdef t_erase 6429088Smarkm#undef t_erase 6529088Smarkm#undef t_kill 6629088Smarkm#undef t_intrc 6729088Smarkm#undef t_quitc 6829088Smarkm#undef t_startc 6929088Smarkm#undef t_stopc 7029088Smarkm#undef t_eofc 7129088Smarkm#undef t_brkc 7229088Smarkm#undef t_suspc 7329088Smarkm#undef t_dsuspc 7429088Smarkm#undef t_rprntc 7529088Smarkm#undef t_flushc 7629088Smarkm#undef t_werasc 7729088Smarkm#undef t_lnextc 7829088Smarkm#endif 7929088Smarkm 8029088Smarkm#ifndef USE_TERMIO 8129088Smarkmstruct termbuf { 8229088Smarkm struct sgttyb sg; 8329088Smarkm struct tchars tc; 8429088Smarkm struct ltchars ltc; 8529088Smarkm int state; 8629088Smarkm int lflags; 8729088Smarkm} termbuf, termbuf2; 8829088Smarkm# define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val) 8929088Smarkm# define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val) 9029088Smarkm# define cfgetospeed(tp) (tp)->sg.sg_ospeed 9129088Smarkm# define cfgetispeed(tp) (tp)->sg.sg_ispeed 9229088Smarkm#else /* USE_TERMIO */ 9329088Smarkm# ifndef TCSANOW 9429088Smarkm# ifdef TCSETS 9529088Smarkm# define TCSANOW TCSETS 9629088Smarkm# define TCSADRAIN TCSETSW 9729088Smarkm# define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) 9829088Smarkm# else 9929088Smarkm# ifdef TCSETA 10029088Smarkm# define TCSANOW TCSETA 10129088Smarkm# define TCSADRAIN TCSETAW 10229088Smarkm# define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) 10329088Smarkm# else 10429088Smarkm# define TCSANOW TIOCSETA 10529088Smarkm# define TCSADRAIN TIOCSETAW 10629088Smarkm# define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) 10729088Smarkm# endif 10829088Smarkm# endif 10929088Smarkm# define tcsetattr(f, a, t) ioctl(f, a, t) 11029088Smarkm# define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 11129088Smarkm (tp)->c_cflag |= (val) 11229088Smarkm# define cfgetospeed(tp) ((tp)->c_cflag & CBAUD) 11329088Smarkm# ifdef CIBAUD 11429088Smarkm# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \ 11529088Smarkm (tp)->c_cflag |= ((val)<<IBSHIFT) 11629088Smarkm# define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT) 11729088Smarkm# else 11829088Smarkm# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ 11929088Smarkm (tp)->c_cflag |= (val) 12029088Smarkm# define cfgetispeed(tp) ((tp)->c_cflag & CBAUD) 12129088Smarkm# endif 12229088Smarkm# endif /* TCSANOW */ 12329088Smarkmstruct termios termbuf, termbuf2; /* pty control structure */ 12429088Smarkm#endif /* USE_TERMIO */ 12529088Smarkm 12631622Scharnier#include <sys/types.h> 12731622Scharnier#include <libutil.h> 12831622Scharnier 12987155Smarkmint cleanopen(char *); 13087155Smarkmvoid scrub_env(void); 13187155Smarkmstatic char **addarg(char **, const char *); 13231622Scharnier 13329088Smarkm/* 13429088Smarkm * init_termbuf() 13529088Smarkm * copy_termbuf(cp) 13629088Smarkm * set_termbuf() 13729088Smarkm * 13829088Smarkm * These three routines are used to get and set the "termbuf" structure 13929088Smarkm * to and from the kernel. init_termbuf() gets the current settings. 14029088Smarkm * copy_termbuf() hands in a new "termbuf" to write to the kernel, and 14129088Smarkm * set_termbuf() writes the structure into the kernel. 14229088Smarkm */ 14329088Smarkm 14487139Smarkmvoid 14587139Smarkminit_termbuf(void) 14629088Smarkm{ 14729088Smarkm#ifndef USE_TERMIO 14829088Smarkm (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg); 14929088Smarkm (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc); 15029088Smarkm (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc); 15129088Smarkm# ifdef TIOCGSTATE 15229088Smarkm (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state); 15329088Smarkm# endif 15429088Smarkm#else 15529088Smarkm (void) tcgetattr(pty, &termbuf); 15629088Smarkm#endif 15729088Smarkm termbuf2 = termbuf; 15829088Smarkm} 15929088Smarkm 16029088Smarkm#if defined(LINEMODE) && defined(TIOCPKT_IOCTL) 16187139Smarkmvoid 16287139Smarkmcopy_termbuf(char *cp, size_t len) 16329088Smarkm{ 16429088Smarkm if (len > sizeof(termbuf)) 16529088Smarkm len = sizeof(termbuf); 16629088Smarkm memmove((char *)&termbuf, cp, len); 16729088Smarkm termbuf2 = termbuf; 16829088Smarkm} 16929088Smarkm#endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ 17029088Smarkm 17187139Smarkmvoid 17287139Smarkmset_termbuf(void) 17329088Smarkm{ 17429088Smarkm /* 17529088Smarkm * Only make the necessary changes. 17629088Smarkm */ 17729088Smarkm#ifndef USE_TERMIO 17829088Smarkm if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, 17929088Smarkm sizeof(termbuf.sg))) 18029088Smarkm (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg); 18129088Smarkm if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, 18229088Smarkm sizeof(termbuf.tc))) 18329088Smarkm (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc); 18429088Smarkm if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc, 18529088Smarkm sizeof(termbuf.ltc))) 18629088Smarkm (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc); 18729088Smarkm if (termbuf.lflags != termbuf2.lflags) 18829088Smarkm (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags); 18929088Smarkm#else /* USE_TERMIO */ 19029088Smarkm if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) 19129088Smarkm (void) tcsetattr(pty, TCSANOW, &termbuf); 19229088Smarkm#endif /* USE_TERMIO */ 19329088Smarkm} 19429088Smarkm 19529088Smarkm 19629088Smarkm/* 19729088Smarkm * spcset(func, valp, valpp) 19829088Smarkm * 19929088Smarkm * This function takes various special characters (func), and 20029088Smarkm * sets *valp to the current value of that character, and 20129088Smarkm * *valpp to point to where in the "termbuf" structure that 20229088Smarkm * value is kept. 20329088Smarkm * 20429088Smarkm * It returns the SLC_ level of support for this function. 20529088Smarkm */ 20629088Smarkm 20729088Smarkm#ifndef USE_TERMIO 20887139Smarkmint 20987139Smarkmspcset(int func, cc_t *valp, cc_t **valpp) 21029088Smarkm{ 21129088Smarkm switch(func) { 21229088Smarkm case SLC_EOF: 21329088Smarkm *valp = termbuf.tc.t_eofc; 21429088Smarkm *valpp = (cc_t *)&termbuf.tc.t_eofc; 21529088Smarkm return(SLC_VARIABLE); 21629088Smarkm case SLC_EC: 21729088Smarkm *valp = termbuf.sg.sg_erase; 21829088Smarkm *valpp = (cc_t *)&termbuf.sg.sg_erase; 21929088Smarkm return(SLC_VARIABLE); 22029088Smarkm case SLC_EL: 22129088Smarkm *valp = termbuf.sg.sg_kill; 22229088Smarkm *valpp = (cc_t *)&termbuf.sg.sg_kill; 22329088Smarkm return(SLC_VARIABLE); 22429088Smarkm case SLC_IP: 22529088Smarkm *valp = termbuf.tc.t_intrc; 22629088Smarkm *valpp = (cc_t *)&termbuf.tc.t_intrc; 22729088Smarkm return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 22829088Smarkm case SLC_ABORT: 22929088Smarkm *valp = termbuf.tc.t_quitc; 23029088Smarkm *valpp = (cc_t *)&termbuf.tc.t_quitc; 23129088Smarkm return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 23229088Smarkm case SLC_XON: 23329088Smarkm *valp = termbuf.tc.t_startc; 23429088Smarkm *valpp = (cc_t *)&termbuf.tc.t_startc; 23529088Smarkm return(SLC_VARIABLE); 23629088Smarkm case SLC_XOFF: 23729088Smarkm *valp = termbuf.tc.t_stopc; 23829088Smarkm *valpp = (cc_t *)&termbuf.tc.t_stopc; 23929088Smarkm return(SLC_VARIABLE); 24029088Smarkm case SLC_AO: 24129088Smarkm *valp = termbuf.ltc.t_flushc; 24229088Smarkm *valpp = (cc_t *)&termbuf.ltc.t_flushc; 24329088Smarkm return(SLC_VARIABLE); 24429088Smarkm case SLC_SUSP: 24529088Smarkm *valp = termbuf.ltc.t_suspc; 24629088Smarkm *valpp = (cc_t *)&termbuf.ltc.t_suspc; 24729088Smarkm return(SLC_VARIABLE); 24829088Smarkm case SLC_EW: 24929088Smarkm *valp = termbuf.ltc.t_werasc; 25029088Smarkm *valpp = (cc_t *)&termbuf.ltc.t_werasc; 25129088Smarkm return(SLC_VARIABLE); 25229088Smarkm case SLC_RP: 25329088Smarkm *valp = termbuf.ltc.t_rprntc; 25429088Smarkm *valpp = (cc_t *)&termbuf.ltc.t_rprntc; 25529088Smarkm return(SLC_VARIABLE); 25629088Smarkm case SLC_LNEXT: 25729088Smarkm *valp = termbuf.ltc.t_lnextc; 25829088Smarkm *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 25929088Smarkm return(SLC_VARIABLE); 26029088Smarkm case SLC_FORW1: 26129088Smarkm *valp = termbuf.tc.t_brkc; 26229088Smarkm *valpp = (cc_t *)&termbuf.ltc.t_lnextc; 26329088Smarkm return(SLC_VARIABLE); 26429088Smarkm case SLC_BRK: 26529088Smarkm case SLC_SYNCH: 26629088Smarkm case SLC_AYT: 26729088Smarkm case SLC_EOR: 26829088Smarkm *valp = (cc_t)0; 26929088Smarkm *valpp = (cc_t *)0; 27029088Smarkm return(SLC_DEFAULT); 27129088Smarkm default: 27229088Smarkm *valp = (cc_t)0; 27329088Smarkm *valpp = (cc_t *)0; 27429088Smarkm return(SLC_NOSUPPORT); 27529088Smarkm } 27629088Smarkm} 27729088Smarkm 27829088Smarkm#else /* USE_TERMIO */ 27929088Smarkm 28029088Smarkm 28129088Smarkm#define setval(a, b) *valp = termbuf.c_cc[a]; \ 28229088Smarkm *valpp = &termbuf.c_cc[a]; \ 28329088Smarkm return(b); 28429088Smarkm#define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); 28529088Smarkm 28687139Smarkmint 28787139Smarkmspcset(int func, cc_t *valp, cc_t **valpp) 28887139Smarkm{ 28929088Smarkm switch(func) { 29029088Smarkm case SLC_EOF: 29129088Smarkm setval(VEOF, SLC_VARIABLE); 29229088Smarkm case SLC_EC: 29329088Smarkm setval(VERASE, SLC_VARIABLE); 29429088Smarkm case SLC_EL: 29529088Smarkm setval(VKILL, SLC_VARIABLE); 29629088Smarkm case SLC_IP: 29729088Smarkm setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 29829088Smarkm case SLC_ABORT: 29929088Smarkm setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); 30029088Smarkm case SLC_XON: 30129088Smarkm#ifdef VSTART 30229088Smarkm setval(VSTART, SLC_VARIABLE); 30329088Smarkm#else 30429088Smarkm defval(0x13); 30529088Smarkm#endif 30629088Smarkm case SLC_XOFF: 30729088Smarkm#ifdef VSTOP 30829088Smarkm setval(VSTOP, SLC_VARIABLE); 30929088Smarkm#else 31029088Smarkm defval(0x11); 31129088Smarkm#endif 31229088Smarkm case SLC_EW: 31329088Smarkm#ifdef VWERASE 31429088Smarkm setval(VWERASE, SLC_VARIABLE); 31529088Smarkm#else 31629088Smarkm defval(0); 31729088Smarkm#endif 31829088Smarkm case SLC_RP: 31929088Smarkm#ifdef VREPRINT 32029088Smarkm setval(VREPRINT, SLC_VARIABLE); 32129088Smarkm#else 32229088Smarkm defval(0); 32329088Smarkm#endif 32429088Smarkm case SLC_LNEXT: 32529088Smarkm#ifdef VLNEXT 32629088Smarkm setval(VLNEXT, SLC_VARIABLE); 32729088Smarkm#else 32829088Smarkm defval(0); 32929088Smarkm#endif 33029088Smarkm case SLC_AO: 33129088Smarkm#if !defined(VDISCARD) && defined(VFLUSHO) 33229088Smarkm# define VDISCARD VFLUSHO 33329088Smarkm#endif 33429088Smarkm#ifdef VDISCARD 33529088Smarkm setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); 33629088Smarkm#else 33729088Smarkm defval(0); 33829088Smarkm#endif 33929088Smarkm case SLC_SUSP: 34029088Smarkm#ifdef VSUSP 34129088Smarkm setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); 34229088Smarkm#else 34329088Smarkm defval(0); 34429088Smarkm#endif 34529088Smarkm#ifdef VEOL 34629088Smarkm case SLC_FORW1: 34729088Smarkm setval(VEOL, SLC_VARIABLE); 34829088Smarkm#endif 34929088Smarkm#ifdef VEOL2 35029088Smarkm case SLC_FORW2: 35129088Smarkm setval(VEOL2, SLC_VARIABLE); 35229088Smarkm#endif 35329088Smarkm case SLC_AYT: 35429088Smarkm#ifdef VSTATUS 35529088Smarkm setval(VSTATUS, SLC_VARIABLE); 35629088Smarkm#else 35729088Smarkm defval(0); 35829088Smarkm#endif 35929088Smarkm 36029088Smarkm case SLC_BRK: 36129088Smarkm case SLC_SYNCH: 36229088Smarkm case SLC_EOR: 36329088Smarkm defval(0); 36429088Smarkm 36529088Smarkm default: 36629088Smarkm *valp = 0; 36729088Smarkm *valpp = 0; 36829088Smarkm return(SLC_NOSUPPORT); 36929088Smarkm } 37029088Smarkm} 37129088Smarkm#endif /* USE_TERMIO */ 37229088Smarkm 37329088Smarkm/* 37429088Smarkm * getpty() 37529088Smarkm * 37629088Smarkm * Allocate a pty. As a side effect, the external character 37729088Smarkm * array "line" contains the name of the slave side. 37829088Smarkm * 37929088Smarkm * Returns the file descriptor of the opened pty. 38029088Smarkm */ 381184935Sedchar line[32]; 38229088Smarkm 38387139Smarkmint 38487139Smarkmgetpty(int *ptynum __unused) 38529088Smarkm{ 38687139Smarkm int p; 387184935Sed const char *pn; 38829088Smarkm 389184935Sed p = posix_openpt(O_RDWR|O_NOCTTY); 390184935Sed if (p < 0) 391184935Sed return (-1); 392184935Sed 393184935Sed if (grantpt(p) == -1) 394184935Sed return (-1); 39529088Smarkm 396184935Sed if (unlockpt(p) == -1) 397184935Sed return (-1); 398184935Sed 399184935Sed pn = ptsname(p); 400184935Sed if (pn == NULL) 401184935Sed return (-1); 402184935Sed 403184938Sed if (strlcpy(line, pn, sizeof line) >= sizeof line) 404184938Sed return (-1); 40529088Smarkm 406184935Sed return (p); 40729088Smarkm} 40829088Smarkm 40929088Smarkm#ifdef LINEMODE 41029088Smarkm/* 41129088Smarkm * tty_flowmode() Find out if flow control is enabled or disabled. 41229088Smarkm * tty_linemode() Find out if linemode (external processing) is enabled. 41329088Smarkm * tty_setlinemod(on) Turn on/off linemode. 41429088Smarkm * tty_isecho() Find out if echoing is turned on. 41529088Smarkm * tty_setecho(on) Enable/disable character echoing. 41629088Smarkm * tty_israw() Find out if terminal is in RAW mode. 41729088Smarkm * tty_binaryin(on) Turn on/off BINARY on input. 41829088Smarkm * tty_binaryout(on) Turn on/off BINARY on output. 41929088Smarkm * tty_isediting() Find out if line editing is enabled. 42029088Smarkm * tty_istrapsig() Find out if signal trapping is enabled. 42129088Smarkm * tty_setedit(on) Turn on/off line editing. 42229088Smarkm * tty_setsig(on) Turn on/off signal trapping. 42329088Smarkm * tty_issofttab() Find out if tab expansion is enabled. 42429088Smarkm * tty_setsofttab(on) Turn on/off soft tab expansion. 42529088Smarkm * tty_islitecho() Find out if typed control chars are echoed literally 42629088Smarkm * tty_setlitecho() Turn on/off literal echo of control chars 42729088Smarkm * tty_tspeed(val) Set transmit speed to val. 42829088Smarkm * tty_rspeed(val) Set receive speed to val. 42929088Smarkm */ 43029088Smarkm 43129088Smarkm 43287139Smarkmint 43387139Smarkmtty_linemode(void) 43429088Smarkm{ 43529088Smarkm#ifndef USE_TERMIO 43629088Smarkm return(termbuf.state & TS_EXTPROC); 43729088Smarkm#else 43829088Smarkm return(termbuf.c_lflag & EXTPROC); 43929088Smarkm#endif 44029088Smarkm} 44129088Smarkm 44287139Smarkmvoid 44387139Smarkmtty_setlinemode(int on) 44429088Smarkm{ 44529088Smarkm#ifdef TIOCEXT 44629088Smarkm set_termbuf(); 44729088Smarkm (void) ioctl(pty, TIOCEXT, (char *)&on); 44829088Smarkm init_termbuf(); 44929088Smarkm#else /* !TIOCEXT */ 45029088Smarkm# ifdef EXTPROC 45129088Smarkm if (on) 45229088Smarkm termbuf.c_lflag |= EXTPROC; 45329088Smarkm else 45429088Smarkm termbuf.c_lflag &= ~EXTPROC; 45529088Smarkm# endif 45629088Smarkm#endif /* TIOCEXT */ 45729088Smarkm} 45829088Smarkm#endif /* LINEMODE */ 45929088Smarkm 46087139Smarkmint 46187139Smarkmtty_isecho(void) 46229088Smarkm{ 46329088Smarkm#ifndef USE_TERMIO 46429088Smarkm return (termbuf.sg.sg_flags & ECHO); 46529088Smarkm#else 46629088Smarkm return (termbuf.c_lflag & ECHO); 46729088Smarkm#endif 46829088Smarkm} 46929088Smarkm 47087139Smarkmint 47187139Smarkmtty_flowmode(void) 47229088Smarkm{ 47329088Smarkm#ifndef USE_TERMIO 47429088Smarkm return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0); 47529088Smarkm#else 47629088Smarkm return((termbuf.c_iflag & IXON) ? 1 : 0); 47729088Smarkm#endif 47829088Smarkm} 47929088Smarkm 48087139Smarkmint 48187139Smarkmtty_restartany(void) 48229088Smarkm{ 48329088Smarkm#ifndef USE_TERMIO 48429088Smarkm# ifdef DECCTQ 48529088Smarkm return((termbuf.lflags & DECCTQ) ? 0 : 1); 48629088Smarkm# else 48729088Smarkm return(-1); 48829088Smarkm# endif 48929088Smarkm#else 49029088Smarkm return((termbuf.c_iflag & IXANY) ? 1 : 0); 49129088Smarkm#endif 49229088Smarkm} 49329088Smarkm 49487139Smarkmvoid 49587139Smarkmtty_setecho(int on) 49629088Smarkm{ 49729088Smarkm#ifndef USE_TERMIO 49829088Smarkm if (on) 49929088Smarkm termbuf.sg.sg_flags |= ECHO|CRMOD; 50029088Smarkm else 50129088Smarkm termbuf.sg.sg_flags &= ~(ECHO|CRMOD); 50229088Smarkm#else 50329088Smarkm if (on) 50429088Smarkm termbuf.c_lflag |= ECHO; 50529088Smarkm else 50629088Smarkm termbuf.c_lflag &= ~ECHO; 50729088Smarkm#endif 50829088Smarkm} 50929088Smarkm 51087139Smarkmint 51187139Smarkmtty_israw(void) 51229088Smarkm{ 51329088Smarkm#ifndef USE_TERMIO 51429088Smarkm return(termbuf.sg.sg_flags & RAW); 51529088Smarkm#else 51629088Smarkm return(!(termbuf.c_lflag & ICANON)); 51729088Smarkm#endif 51829088Smarkm} 51929088Smarkm 52087139Smarkm#ifdef AUTHENTICATION 52187139Smarkm#if defined(NO_LOGIN_F) && defined(LOGIN_R) 52287139Smarkmint 52387139Smarkmtty_setraw(int on) 52429088Smarkm{ 52529088Smarkm# ifndef USE_TERMIO 52629088Smarkm if (on) 52729088Smarkm termbuf.sg.sg_flags |= RAW; 52829088Smarkm else 52929088Smarkm termbuf.sg.sg_flags &= ~RAW; 53029088Smarkm# else 53129088Smarkm if (on) 53229088Smarkm termbuf.c_lflag &= ~ICANON; 53329088Smarkm else 53429088Smarkm termbuf.c_lflag |= ICANON; 53529088Smarkm# endif 53629088Smarkm} 53729088Smarkm#endif 53887139Smarkm#endif /* AUTHENTICATION */ 53929088Smarkm 54087139Smarkmvoid 54187139Smarkmtty_binaryin(int on) 54229088Smarkm{ 54329088Smarkm#ifndef USE_TERMIO 54429088Smarkm if (on) 54529088Smarkm termbuf.lflags |= LPASS8; 54629088Smarkm else 54729088Smarkm termbuf.lflags &= ~LPASS8; 54829088Smarkm#else 54929088Smarkm if (on) { 55029088Smarkm termbuf.c_iflag &= ~ISTRIP; 55129088Smarkm } else { 55229088Smarkm termbuf.c_iflag |= ISTRIP; 55329088Smarkm } 55429088Smarkm#endif 55529088Smarkm} 55629088Smarkm 55787139Smarkmvoid 55887139Smarkmtty_binaryout(int on) 55929088Smarkm{ 56029088Smarkm#ifndef USE_TERMIO 56129088Smarkm if (on) 56229088Smarkm termbuf.lflags |= LLITOUT; 56329088Smarkm else 56429088Smarkm termbuf.lflags &= ~LLITOUT; 56529088Smarkm#else 56629088Smarkm if (on) { 56729088Smarkm termbuf.c_cflag &= ~(CSIZE|PARENB); 56829088Smarkm termbuf.c_cflag |= CS8; 56929088Smarkm termbuf.c_oflag &= ~OPOST; 57029088Smarkm } else { 57129088Smarkm termbuf.c_cflag &= ~CSIZE; 57229088Smarkm termbuf.c_cflag |= CS7|PARENB; 57329088Smarkm termbuf.c_oflag |= OPOST; 57429088Smarkm } 57529088Smarkm#endif 57629088Smarkm} 57729088Smarkm 57887139Smarkmint 57987139Smarkmtty_isbinaryin(void) 58029088Smarkm{ 58129088Smarkm#ifndef USE_TERMIO 58229088Smarkm return(termbuf.lflags & LPASS8); 58329088Smarkm#else 58429088Smarkm return(!(termbuf.c_iflag & ISTRIP)); 58529088Smarkm#endif 58629088Smarkm} 58729088Smarkm 58887139Smarkmint 58987139Smarkmtty_isbinaryout(void) 59029088Smarkm{ 59129088Smarkm#ifndef USE_TERMIO 59229088Smarkm return(termbuf.lflags & LLITOUT); 59329088Smarkm#else 59429088Smarkm return(!(termbuf.c_oflag&OPOST)); 59529088Smarkm#endif 59629088Smarkm} 59729088Smarkm 59829088Smarkm#ifdef LINEMODE 59987139Smarkmint 60087139Smarkmtty_isediting(void) 60129088Smarkm{ 60229088Smarkm#ifndef USE_TERMIO 60329088Smarkm return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); 60429088Smarkm#else 60529088Smarkm return(termbuf.c_lflag & ICANON); 60629088Smarkm#endif 60729088Smarkm} 60829088Smarkm 60987139Smarkmint 61087139Smarkmtty_istrapsig(void) 61129088Smarkm{ 61229088Smarkm#ifndef USE_TERMIO 61329088Smarkm return(!(termbuf.sg.sg_flags&RAW)); 61429088Smarkm#else 61529088Smarkm return(termbuf.c_lflag & ISIG); 61629088Smarkm#endif 61729088Smarkm} 61829088Smarkm 61987139Smarkmvoid 62087139Smarkmtty_setedit(int on) 62129088Smarkm{ 62229088Smarkm#ifndef USE_TERMIO 62329088Smarkm if (on) 62429088Smarkm termbuf.sg.sg_flags &= ~CBREAK; 62529088Smarkm else 62629088Smarkm termbuf.sg.sg_flags |= CBREAK; 62729088Smarkm#else 62829088Smarkm if (on) 62929088Smarkm termbuf.c_lflag |= ICANON; 63029088Smarkm else 63129088Smarkm termbuf.c_lflag &= ~ICANON; 63229088Smarkm#endif 63329088Smarkm} 63429088Smarkm 63587139Smarkmvoid 63687139Smarkmtty_setsig(int on) 63729088Smarkm{ 63829088Smarkm#ifndef USE_TERMIO 63929088Smarkm if (on) 64029088Smarkm ; 64129088Smarkm#else 64229088Smarkm if (on) 64329088Smarkm termbuf.c_lflag |= ISIG; 64429088Smarkm else 64529088Smarkm termbuf.c_lflag &= ~ISIG; 64629088Smarkm#endif 64729088Smarkm} 64829088Smarkm#endif /* LINEMODE */ 64929088Smarkm 65087139Smarkmint 65187139Smarkmtty_issofttab(void) 65229088Smarkm{ 65329088Smarkm#ifndef USE_TERMIO 65429088Smarkm return (termbuf.sg.sg_flags & XTABS); 65529088Smarkm#else 65629088Smarkm# ifdef OXTABS 65729088Smarkm return (termbuf.c_oflag & OXTABS); 65829088Smarkm# endif 65929088Smarkm# ifdef TABDLY 66029088Smarkm return ((termbuf.c_oflag & TABDLY) == TAB3); 66129088Smarkm# endif 66229088Smarkm#endif 66329088Smarkm} 66429088Smarkm 66587139Smarkmvoid 66687139Smarkmtty_setsofttab(int on) 66729088Smarkm{ 66829088Smarkm#ifndef USE_TERMIO 66929088Smarkm if (on) 67029088Smarkm termbuf.sg.sg_flags |= XTABS; 67129088Smarkm else 67229088Smarkm termbuf.sg.sg_flags &= ~XTABS; 67329088Smarkm#else 67429088Smarkm if (on) { 67529088Smarkm# ifdef OXTABS 67629088Smarkm termbuf.c_oflag |= OXTABS; 67729088Smarkm# endif 67829088Smarkm# ifdef TABDLY 67929088Smarkm termbuf.c_oflag &= ~TABDLY; 68029088Smarkm termbuf.c_oflag |= TAB3; 68129088Smarkm# endif 68229088Smarkm } else { 68329088Smarkm# ifdef OXTABS 68429088Smarkm termbuf.c_oflag &= ~OXTABS; 68529088Smarkm# endif 68629088Smarkm# ifdef TABDLY 68729088Smarkm termbuf.c_oflag &= ~TABDLY; 68829088Smarkm termbuf.c_oflag |= TAB0; 68929088Smarkm# endif 69029088Smarkm } 69129088Smarkm#endif 69229088Smarkm} 69329088Smarkm 69487139Smarkmint 69587139Smarkmtty_islitecho(void) 69629088Smarkm{ 69729088Smarkm#ifndef USE_TERMIO 69829088Smarkm return (!(termbuf.lflags & LCTLECH)); 69929088Smarkm#else 70029088Smarkm# ifdef ECHOCTL 70129088Smarkm return (!(termbuf.c_lflag & ECHOCTL)); 70229088Smarkm# endif 70329088Smarkm# ifdef TCTLECH 70429088Smarkm return (!(termbuf.c_lflag & TCTLECH)); 70529088Smarkm# endif 70629088Smarkm# if !defined(ECHOCTL) && !defined(TCTLECH) 70729088Smarkm return (0); /* assumes ctl chars are echoed '^x' */ 70829088Smarkm# endif 70929088Smarkm#endif 71029088Smarkm} 71129088Smarkm 71287139Smarkmvoid 71387139Smarkmtty_setlitecho(int on) 71429088Smarkm{ 71529088Smarkm#ifndef USE_TERMIO 71629088Smarkm if (on) 71729088Smarkm termbuf.lflags &= ~LCTLECH; 71829088Smarkm else 71929088Smarkm termbuf.lflags |= LCTLECH; 72029088Smarkm#else 72129088Smarkm# ifdef ECHOCTL 72229088Smarkm if (on) 72329088Smarkm termbuf.c_lflag &= ~ECHOCTL; 72429088Smarkm else 72529088Smarkm termbuf.c_lflag |= ECHOCTL; 72629088Smarkm# endif 72729088Smarkm# ifdef TCTLECH 72829088Smarkm if (on) 72929088Smarkm termbuf.c_lflag &= ~TCTLECH; 73029088Smarkm else 73129088Smarkm termbuf.c_lflag |= TCTLECH; 73229088Smarkm# endif 73329088Smarkm#endif 73429088Smarkm} 73529088Smarkm 73687139Smarkmint 73787139Smarkmtty_iscrnl(void) 73829088Smarkm{ 73929088Smarkm#ifndef USE_TERMIO 74029088Smarkm return (termbuf.sg.sg_flags & CRMOD); 74129088Smarkm#else 74229088Smarkm return (termbuf.c_iflag & ICRNL); 74329088Smarkm#endif 74429088Smarkm} 74529088Smarkm 74629088Smarkm/* 74729088Smarkm * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). 74829088Smarkm */ 74929088Smarkm#if B4800 != 4800 75029088Smarkm#define DECODE_BAUD 75129088Smarkm#endif 75229088Smarkm 75329088Smarkm#ifdef DECODE_BAUD 75429088Smarkm 75529088Smarkm/* 75629088Smarkm * A table of available terminal speeds 75729088Smarkm */ 75829088Smarkmstruct termspeeds { 75929088Smarkm int speed; 76029088Smarkm int value; 76129088Smarkm} termspeeds[] = { 76229088Smarkm { 0, B0 }, { 50, B50 }, { 75, B75 }, 76329088Smarkm { 110, B110 }, { 134, B134 }, { 150, B150 }, 76429088Smarkm { 200, B200 }, { 300, B300 }, { 600, B600 }, 76529088Smarkm { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, 76629088Smarkm { 4800, B4800 }, 76729088Smarkm#ifdef B7200 76829088Smarkm { 7200, B7200 }, 76929088Smarkm#endif 77029088Smarkm { 9600, B9600 }, 77129088Smarkm#ifdef B14400 77229088Smarkm { 14400, B14400 }, 77329088Smarkm#endif 77429088Smarkm#ifdef B19200 77529088Smarkm { 19200, B19200 }, 77629088Smarkm#endif 77729088Smarkm#ifdef B28800 77829088Smarkm { 28800, B28800 }, 77929088Smarkm#endif 78029088Smarkm#ifdef B38400 78129088Smarkm { 38400, B38400 }, 78229088Smarkm#endif 78329088Smarkm#ifdef B57600 78429088Smarkm { 57600, B57600 }, 78529088Smarkm#endif 78629088Smarkm#ifdef B115200 78729088Smarkm { 115200, B115200 }, 78829088Smarkm#endif 78929088Smarkm#ifdef B230400 79029088Smarkm { 230400, B230400 }, 79129088Smarkm#endif 79229088Smarkm { -1, 0 } 79329088Smarkm}; 79431622Scharnier#endif /* DECODE_BAUD */ 79529088Smarkm 79687139Smarkmvoid 79787139Smarkmtty_tspeed(int val) 79829088Smarkm{ 79929088Smarkm#ifdef DECODE_BAUD 80087139Smarkm struct termspeeds *tp; 80129088Smarkm 80229088Smarkm for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 80329088Smarkm ; 80429088Smarkm if (tp->speed == -1) /* back up to last valid value */ 80529088Smarkm --tp; 80629088Smarkm cfsetospeed(&termbuf, tp->value); 80731622Scharnier#else /* DECODE_BAUD */ 80829088Smarkm cfsetospeed(&termbuf, val); 80931622Scharnier#endif /* DECODE_BAUD */ 81029088Smarkm} 81129088Smarkm 81287139Smarkmvoid 81387139Smarkmtty_rspeed(int val) 81429088Smarkm{ 81529088Smarkm#ifdef DECODE_BAUD 81687139Smarkm struct termspeeds *tp; 81729088Smarkm 81829088Smarkm for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) 81929088Smarkm ; 82029088Smarkm if (tp->speed == -1) /* back up to last valid value */ 82129088Smarkm --tp; 82229088Smarkm cfsetispeed(&termbuf, tp->value); 82329088Smarkm#else /* DECODE_BAUD */ 82429088Smarkm cfsetispeed(&termbuf, val); 82529088Smarkm#endif /* DECODE_BAUD */ 82629088Smarkm} 82729088Smarkm 82829088Smarkm/* 82929088Smarkm * getptyslave() 83029088Smarkm * 83129088Smarkm * Open the slave side of the pty, and do any initialization 83231622Scharnier * that is necessary. 83329088Smarkm */ 83487139Smarkmstatic void 83587139Smarkmgetptyslave(void) 83629088Smarkm{ 83787139Smarkm int t = -1; 83829181Smarkm char erase; 83929088Smarkm 84029088Smarkm# ifdef LINEMODE 84129088Smarkm int waslm; 84229088Smarkm# endif 84329088Smarkm# ifdef TIOCGWINSZ 84429088Smarkm struct winsize ws; 84529088Smarkm extern int def_row, def_col; 84629088Smarkm# endif 84729088Smarkm extern int def_tspeed, def_rspeed; 84829088Smarkm /* 84929088Smarkm * Opening the slave side may cause initilization of the 85029088Smarkm * kernel tty structure. We need remember the state of 85129088Smarkm * if linemode was turned on 85229088Smarkm * terminal window size 85329088Smarkm * terminal speed 85429181Smarkm * erase character 85529088Smarkm * so that we can re-set them if we need to. 85629088Smarkm */ 85729088Smarkm# ifdef LINEMODE 85829088Smarkm waslm = tty_linemode(); 85929088Smarkm# endif 86029181Smarkm erase = termbuf.c_cc[VERASE]; 86129088Smarkm 86229088Smarkm /* 86329088Smarkm * Make sure that we don't have a controlling tty, and 86429088Smarkm * that we are the session (process group) leader. 86529088Smarkm */ 86629088Smarkm# ifdef TIOCNOTTY 86729088Smarkm t = open(_PATH_TTY, O_RDWR); 86829088Smarkm if (t >= 0) { 86929088Smarkm (void) ioctl(t, TIOCNOTTY, (char *)0); 87029088Smarkm (void) close(t); 87129088Smarkm } 87229088Smarkm# endif 87329088Smarkm 87429088Smarkm t = cleanopen(line); 87529088Smarkm if (t < 0) 87629088Smarkm fatalperror(net, line); 87729088Smarkm 87829088Smarkm 87929088Smarkm /* 88029088Smarkm * set up the tty modes as we like them to be. 88129088Smarkm */ 88229088Smarkm init_termbuf(); 88329088Smarkm# ifdef TIOCGWINSZ 88429088Smarkm if (def_row || def_col) { 88529088Smarkm memset((char *)&ws, 0, sizeof(ws)); 88629088Smarkm ws.ws_col = def_col; 88729088Smarkm ws.ws_row = def_row; 88829088Smarkm (void)ioctl(t, TIOCSWINSZ, (char *)&ws); 88929088Smarkm } 89029088Smarkm# endif 89129088Smarkm 89229088Smarkm /* 89329088Smarkm * Settings for sgtty based systems 89429088Smarkm */ 89529088Smarkm# ifndef USE_TERMIO 89629088Smarkm termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; 89729088Smarkm# endif /* USE_TERMIO */ 89829088Smarkm 89929088Smarkm /* 90029088Smarkm * Settings for all other termios/termio based 90129088Smarkm * systems, other than 4.4BSD. In 4.4BSD the 90229088Smarkm * kernel does the initial terminal setup. 90329088Smarkm */ 90429088Smarkm tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); 90529088Smarkm tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); 90629181Smarkm if (erase) 90729181Smarkm termbuf.c_cc[VERASE] = erase; 90829088Smarkm# ifdef LINEMODE 90929088Smarkm if (waslm) 91029088Smarkm tty_setlinemode(1); 91129088Smarkm# endif /* LINEMODE */ 91229088Smarkm 91329088Smarkm /* 91429088Smarkm * Set the tty modes, and make this our controlling tty. 91529088Smarkm */ 91629088Smarkm set_termbuf(); 91729088Smarkm if (login_tty(t) == -1) 91829088Smarkm fatalperror(net, "login_tty"); 91929088Smarkm if (net > 2) 92029088Smarkm (void) close(net); 92187139Smarkm#ifdef AUTHENTICATION 92287139Smarkm#if defined(NO_LOGIN_F) && defined(LOGIN_R) 92329088Smarkm /* 92429088Smarkm * Leave the pty open so that we can write out the rlogin 92529088Smarkm * protocol for /bin/login, if the authentication works. 92629088Smarkm */ 92729088Smarkm#else 92829088Smarkm if (pty > 2) { 92929088Smarkm (void) close(pty); 93029088Smarkm pty = -1; 93129088Smarkm } 93229088Smarkm#endif 93387139Smarkm#endif /* AUTHENTICATION */ 93429088Smarkm} 93529088Smarkm 93629088Smarkm#ifndef O_NOCTTY 93729088Smarkm#define O_NOCTTY 0 93829088Smarkm#endif 93929088Smarkm/* 94029088Smarkm * Open the specified slave side of the pty, 94129088Smarkm * making sure that we have a clean tty. 94229088Smarkm */ 94387139Smarkmint 94487139Smarkmcleanopen(char *li) 94529088Smarkm{ 94687139Smarkm int t; 94729088Smarkm 94829088Smarkm /* 94929088Smarkm * Make sure that other people can't open the 95029088Smarkm * slave side of the connection. 95129088Smarkm */ 95287139Smarkm (void) chown(li, 0, 0); 95387139Smarkm (void) chmod(li, 0600); 95429088Smarkm 95587139Smarkm (void) revoke(li); 95629088Smarkm 95729088Smarkm t = open(line, O_RDWR|O_NOCTTY); 95829088Smarkm 95929088Smarkm if (t < 0) 96029088Smarkm return(-1); 96129088Smarkm 96229088Smarkm return(t); 96329088Smarkm} 96429088Smarkm 96529088Smarkm/* 96629088Smarkm * startslave(host) 96729088Smarkm * 96829088Smarkm * Given a hostname, do whatever 96929088Smarkm * is necessary to startup the login process on the slave side of the pty. 97029088Smarkm */ 97129088Smarkm 97229088Smarkm/* ARGSUSED */ 97387139Smarkmvoid 97487139Smarkmstartslave(char *host, int autologin, char *autoname) 97529088Smarkm{ 97687139Smarkm int i; 97729088Smarkm 97887139Smarkm#ifdef AUTHENTICATION 97929088Smarkm if (!autoname || !autoname[0]) 98029088Smarkm autologin = 0; 98129088Smarkm 98229088Smarkm if (autologin < auth_level) { 98329088Smarkm fatal(net, "Authorization failed"); 98429088Smarkm exit(1); 98529088Smarkm } 98629088Smarkm#endif 98729088Smarkm 98829088Smarkm 98929088Smarkm if ((i = fork()) < 0) 99029088Smarkm fatalperror(net, "fork"); 99129088Smarkm if (i) { 99229088Smarkm } else { 99387139Smarkm getptyslave(); 99429088Smarkm start_login(host, autologin, autoname); 99529088Smarkm /*NOTREACHED*/ 99629088Smarkm } 99729088Smarkm} 99829088Smarkm 99987139Smarkmvoid 100087139Smarkminit_env(void) 100129088Smarkm{ 100229088Smarkm char **envp; 100329088Smarkm 100429088Smarkm envp = envinit; 100529181Smarkm if ((*envp = getenv("TZ"))) 100629088Smarkm *envp++ -= 3; 100729088Smarkm *envp = 0; 100829088Smarkm environ = envinit; 100929088Smarkm} 101029088Smarkm 101129088Smarkm 101229088Smarkm/* 101329088Smarkm * start_login(host) 101429088Smarkm * 101529088Smarkm * Assuming that we are now running as a child processes, this 101629088Smarkm * function will turn us into the login process. 101729088Smarkm */ 101829088Smarkm 101987139Smarkm#ifndef AUTHENTICATION 102087139Smarkm#define undef1 __unused 102187139Smarkm#else 102287139Smarkm#define undef1 102329088Smarkm#endif 102429088Smarkm 102587139Smarkmvoid 102687139Smarkmstart_login(char *host undef1, int autologin undef1, char *name undef1) 102787139Smarkm{ 102887139Smarkm char **argv; 1029251188Smarcel char *user; 103029088Smarkm 1031251188Smarcel user = getenv("USER"); 1032251188Smarcel user = (user != NULL) ? strdup(user) : NULL; 1033251188Smarcel 103429088Smarkm scrub_env(); 103529088Smarkm 103629088Smarkm /* 103729088Smarkm * -h : pass on name of host. 103829088Smarkm * WARNING: -h is accepted by login if and only if 103929088Smarkm * getuid() == 0. 104029088Smarkm * -p : don't clobber the environment (so terminal type stays set). 104129088Smarkm * 104229088Smarkm * -f : force this login, he has already been authenticated 104329088Smarkm */ 104429088Smarkm argv = addarg(0, "login"); 104529088Smarkm 104629088Smarkm#if !defined(NO_LOGIN_H) 104787139Smarkm#ifdef AUTHENTICATION 104887139Smarkm# if defined(NO_LOGIN_F) && defined(LOGIN_R) 104929088Smarkm /* 105029088Smarkm * Don't add the "-h host" option if we are going 105129088Smarkm * to be adding the "-r host" option down below... 105229088Smarkm */ 105329088Smarkm if ((auth_level < 0) || (autologin != AUTH_VALID)) 105429088Smarkm# endif 105529088Smarkm { 105629088Smarkm argv = addarg(argv, "-h"); 105729088Smarkm argv = addarg(argv, host); 105829088Smarkm } 105987139Smarkm#endif /* AUTHENTICATION */ 106029088Smarkm#endif 106129088Smarkm#if !defined(NO_LOGIN_P) 106229088Smarkm argv = addarg(argv, "-p"); 106329088Smarkm#endif 106429088Smarkm#ifdef LINEMODE 106529088Smarkm /* 106629088Smarkm * Set the environment variable "LINEMODE" to either 106729088Smarkm * "real" or "kludge" if we are operating in either 106829088Smarkm * real or kludge linemode. 106929088Smarkm */ 107029088Smarkm if (lmodetype == REAL_LINEMODE) 107129088Smarkm setenv("LINEMODE", "real", 1); 107229088Smarkm# ifdef KLUDGELINEMODE 107329088Smarkm else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK) 107429088Smarkm setenv("LINEMODE", "kludge", 1); 107529088Smarkm# endif 107629088Smarkm#endif 107729088Smarkm#ifdef BFTPDAEMON 107829088Smarkm /* 107929088Smarkm * Are we working as the bftp daemon? If so, then ask login 108029088Smarkm * to start bftp instead of shell. 108129088Smarkm */ 108229088Smarkm if (bftpd) { 108329088Smarkm argv = addarg(argv, "-e"); 108429088Smarkm argv = addarg(argv, BFTPPATH); 108529088Smarkm } else 108629088Smarkm#endif 108787139Smarkm#ifdef AUTHENTICATION 108829088Smarkm if (auth_level >= 0 && autologin == AUTH_VALID) { 108929088Smarkm# if !defined(NO_LOGIN_F) 109029088Smarkm argv = addarg(argv, "-f"); 109129181Smarkm argv = addarg(argv, "--"); 109229088Smarkm argv = addarg(argv, name); 109329088Smarkm# else 109429088Smarkm# if defined(LOGIN_R) 109529088Smarkm /* 109629088Smarkm * We don't have support for "login -f", but we 109729088Smarkm * can fool /bin/login into thinking that we are 109829088Smarkm * rlogind, and allow us to log in without a 109929088Smarkm * password. The rlogin protocol expects 110029088Smarkm * local-user\0remote-user\0term/speed\0 110129088Smarkm */ 110229088Smarkm 110329088Smarkm if (pty > 2) { 110487139Smarkm char *cp; 110529088Smarkm char speed[128]; 110629088Smarkm int isecho, israw, xpty, len; 110729088Smarkm extern int def_rspeed; 110829088Smarkm# ifndef LOGIN_HOST 110929088Smarkm /* 111029088Smarkm * Tell login that we are coming from "localhost". 111129088Smarkm * If we passed in the real host name, then the 111229088Smarkm * user would have to allow .rhost access from 111329088Smarkm * every machine that they want authenticated 111429088Smarkm * access to work from, which sort of defeats 111529088Smarkm * the purpose of an authenticated login... 111629088Smarkm * So, we tell login that the session is coming 111729088Smarkm * from "localhost", and the user will only have 111829088Smarkm * to have "localhost" in their .rhost file. 111929088Smarkm */ 112029088Smarkm# define LOGIN_HOST "localhost" 112129088Smarkm# endif 112229088Smarkm argv = addarg(argv, "-r"); 112329088Smarkm argv = addarg(argv, LOGIN_HOST); 112429088Smarkm 112529088Smarkm xpty = pty; 112629088Smarkm pty = 0; 112729088Smarkm init_termbuf(); 112829088Smarkm isecho = tty_isecho(); 112929088Smarkm israw = tty_israw(); 113029088Smarkm if (isecho || !israw) { 113129088Smarkm tty_setecho(0); /* Turn off echo */ 113229088Smarkm tty_setraw(1); /* Turn on raw */ 113329088Smarkm set_termbuf(); 113429088Smarkm } 113529088Smarkm len = strlen(name)+1; 113629088Smarkm write(xpty, name, len); 113729088Smarkm write(xpty, name, len); 113832688Simp snprintf(speed, sizeof(speed), 113932688Simp "%s/%d", (cp = getenv("TERM")) ? cp : "", 114029088Smarkm (def_rspeed > 0) ? def_rspeed : 9600); 114129088Smarkm len = strlen(speed)+1; 114229088Smarkm write(xpty, speed, len); 114329088Smarkm 114429088Smarkm if (isecho || !israw) { 114529088Smarkm init_termbuf(); 114629088Smarkm tty_setecho(isecho); 114729088Smarkm tty_setraw(israw); 114829088Smarkm set_termbuf(); 114929088Smarkm if (!israw) { 115029088Smarkm /* 115129088Smarkm * Write a newline to ensure 115229088Smarkm * that login will be able to 115329088Smarkm * read the line... 115429088Smarkm */ 115529088Smarkm write(xpty, "\n", 1); 115629088Smarkm } 115729088Smarkm } 115829088Smarkm pty = xpty; 115929088Smarkm } 116029088Smarkm# else 116129181Smarkm argv = addarg(argv, "--"); 116229088Smarkm argv = addarg(argv, name); 116329088Smarkm# endif 116429088Smarkm# endif 116529088Smarkm } else 116629088Smarkm#endif 1167251188Smarcel if (user != NULL) { 116829181Smarkm argv = addarg(argv, "--"); 1169251188Smarcel argv = addarg(argv, user); 117029088Smarkm#if defined(LOGIN_ARGS) && defined(NO_LOGIN_P) 117129088Smarkm { 117287139Smarkm char **cpp; 117329088Smarkm for (cpp = environ; *cpp; cpp++) 117429088Smarkm argv = addarg(argv, *cpp); 117529088Smarkm } 117629088Smarkm#endif 117729088Smarkm } 117887139Smarkm#ifdef AUTHENTICATION 117987139Smarkm#if defined(NO_LOGIN_F) && defined(LOGIN_R) 118029088Smarkm if (pty > 2) 118129088Smarkm close(pty); 118229088Smarkm#endif 118387139Smarkm#endif /* AUTHENTICATION */ 118429088Smarkm closelog(); 118529088Smarkm 1186251188Smarcel if (user != NULL) 1187251188Smarcel free(user); 1188251188Smarcel 118929181Smarkm if (altlogin == NULL) { 119029181Smarkm altlogin = _PATH_LOGIN; 119129181Smarkm } 119229181Smarkm execv(altlogin, argv); 119329181Smarkm 119431622Scharnier syslog(LOG_ERR, "%s: %m", altlogin); 119529181Smarkm fatalperror(net, altlogin); 119629088Smarkm /*NOTREACHED*/ 119729088Smarkm} 119829088Smarkm 119987139Smarkmstatic char ** 120087139Smarkmaddarg(char **argv, const char *val) 120129088Smarkm{ 120287139Smarkm char **cpp; 120329088Smarkm 120429088Smarkm if (argv == NULL) { 120529088Smarkm /* 120629088Smarkm * 10 entries, a leading length, and a null 120729088Smarkm */ 120829088Smarkm argv = (char **)malloc(sizeof(*argv) * 12); 120929088Smarkm if (argv == NULL) 1210309636Sglebius fatal(net, "failure allocating argument space"); 121129088Smarkm *argv++ = (char *)10; 121229088Smarkm *argv = (char *)0; 121329088Smarkm } 121429088Smarkm for (cpp = argv; *cpp; cpp++) 121529088Smarkm ; 121687267Smarkm if (cpp == &argv[(long)argv[-1]]) { 121729088Smarkm --argv; 121887267Smarkm *argv = (char *)((long)(*argv) + 10); 121987267Smarkm argv = (char **)realloc(argv, sizeof(*argv)*((long)(*argv) + 2)); 122029088Smarkm if (argv == NULL) 1221309636Sglebius fatal(net, "failure allocating argument space"); 122229088Smarkm argv++; 122387267Smarkm cpp = &argv[(long)argv[-1] - 10]; 122429088Smarkm } 1225309636Sglebius if ((*cpp++ = strdup(val)) == NULL) 1226309636Sglebius fatal(net, "failure allocating argument space"); 122729088Smarkm *cpp = 0; 122829088Smarkm return(argv); 122929088Smarkm} 123029088Smarkm 123129088Smarkm/* 123229088Smarkm * scrub_env() 123329088Smarkm * 123469825Sassar * We only accept the environment variables listed below. 123529088Smarkm */ 123687139Smarkmvoid 123787139Smarkmscrub_env(void) 123829088Smarkm{ 123987139Smarkm static const char *rej[] = { 124069825Sassar "TERMCAP=/", 124169825Sassar NULL 124269825Sassar }; 124329088Smarkm 124487139Smarkm static const char *acc[] = { 124569825Sassar "XAUTH=", "XAUTHORITY=", "DISPLAY=", 124669825Sassar "TERM=", 124769825Sassar "EDITOR=", 124869825Sassar "PAGER=", 124969825Sassar "LOGNAME=", 125069825Sassar "POSIXLY_CORRECT=", 125169825Sassar "PRINTER=", 125269825Sassar NULL 125369825Sassar }; 125469825Sassar 125569825Sassar char **cpp, **cpp2; 125669825Sassar const char **p; 1257188699Scperciva char ** new_environ; 1258188699Scperciva size_t count; 1259188699Scperciva 1260188699Scperciva /* Allocate space for scrubbed environment. */ 1261188699Scperciva for (count = 1, cpp = environ; *cpp; count++, cpp++) 1262188699Scperciva continue; 1263188699Scperciva if ((new_environ = malloc(count * sizeof(char *))) == NULL) { 1264188699Scperciva environ = NULL; 1265188699Scperciva return; 1266188699Scperciva } 1267188699Scperciva 1268188699Scperciva for (cpp2 = new_environ, cpp = environ; *cpp; cpp++) { 126969825Sassar int reject_it = 0; 127069825Sassar 127187139Smarkm for(p = rej; *p; p++) 127269825Sassar if(strncmp(*cpp, *p, strlen(*p)) == 0) { 127369825Sassar reject_it = 1; 127469825Sassar break; 127569825Sassar } 127669825Sassar if (reject_it) 127769825Sassar continue; 127869825Sassar 127987139Smarkm for(p = acc; *p; p++) 128069825Sassar if(strncmp(*cpp, *p, strlen(*p)) == 0) 128169825Sassar break; 1282188699Scperciva if(*p != NULL) { 1283188699Scperciva if ((*cpp2++ = strdup(*cpp)) == NULL) { 1284188699Scperciva environ = new_environ; 1285188699Scperciva return; 1286188699Scperciva } 1287188699Scperciva } 128869825Sassar } 128969825Sassar *cpp2 = NULL; 1290188699Scperciva environ = new_environ; 129129088Smarkm} 129229088Smarkm 129329088Smarkm/* 129429088Smarkm * cleanup() 129529088Smarkm * 129629088Smarkm * This is the routine to call when we are all through, to 129729088Smarkm * clean up anything that needs to be cleaned up. 129829088Smarkm */ 129987139Smarkm/* ARGSUSED */ 130087139Smarkmvoid 130187139Smarkmcleanup(int sig __unused) 130229088Smarkm{ 130329088Smarkm 1304202212Sed (void) shutdown(net, SHUT_RDWR); 130590242Ssheldonh _exit(1); 130629088Smarkm} 1307