113e3f4d6SMark Murray /*
213e3f4d6SMark Murray * Copyright (c) 1989, 1993
313e3f4d6SMark Murray * The Regents of the University of California. All rights reserved.
413e3f4d6SMark Murray *
513e3f4d6SMark Murray * Redistribution and use in source and binary forms, with or without
613e3f4d6SMark Murray * modification, are permitted provided that the following conditions
713e3f4d6SMark Murray * are met:
813e3f4d6SMark Murray * 1. Redistributions of source code must retain the above copyright
913e3f4d6SMark Murray * notice, this list of conditions and the following disclaimer.
1013e3f4d6SMark Murray * 2. Redistributions in binary form must reproduce the above copyright
1113e3f4d6SMark Murray * notice, this list of conditions and the following disclaimer in the
1213e3f4d6SMark Murray * documentation and/or other materials provided with the distribution.
1313e3f4d6SMark Murray * 3. All advertising materials mentioning features or use of this software
1413e3f4d6SMark Murray * must display the following acknowledgement:
1513e3f4d6SMark Murray * This product includes software developed by the University of
1613e3f4d6SMark Murray * California, Berkeley and its contributors.
1713e3f4d6SMark Murray * 4. Neither the name of the University nor the names of its contributors
1813e3f4d6SMark Murray * may be used to endorse or promote products derived from this software
1913e3f4d6SMark Murray * without specific prior written permission.
2013e3f4d6SMark Murray *
2113e3f4d6SMark Murray * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2213e3f4d6SMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2313e3f4d6SMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2413e3f4d6SMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2513e3f4d6SMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2613e3f4d6SMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2713e3f4d6SMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2813e3f4d6SMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2913e3f4d6SMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3013e3f4d6SMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3113e3f4d6SMark Murray * SUCH DAMAGE.
3213e3f4d6SMark Murray */
3313e3f4d6SMark Murray
3413e3f4d6SMark Murray #include "telnetd.h"
3513e3f4d6SMark Murray
36c19800e8SDoug Rabson RCSID("$Id$");
3713e3f4d6SMark Murray
3813e3f4d6SMark Murray #if defined(_CRAY) || (defined(__hpux) && !defined(HAVE_UTMPX_H))
3913e3f4d6SMark Murray # define PARENT_DOES_UTMP
4013e3f4d6SMark Murray #endif
4113e3f4d6SMark Murray
4213e3f4d6SMark Murray #ifdef HAVE_UTMP_H
4313e3f4d6SMark Murray #include <utmp.h>
4413e3f4d6SMark Murray #endif
4513e3f4d6SMark Murray
4613e3f4d6SMark Murray #ifdef HAVE_UTMPX_H
4713e3f4d6SMark Murray #include <utmpx.h>
4813e3f4d6SMark Murray #endif
4913e3f4d6SMark Murray
5013e3f4d6SMark Murray #ifdef HAVE_UTMPX_H
5113e3f4d6SMark Murray struct utmpx wtmp;
5213e3f4d6SMark Murray #elif defined(HAVE_UTMP_H)
5313e3f4d6SMark Murray struct utmp wtmp;
5413e3f4d6SMark Murray #endif /* HAVE_UTMPX_H */
5513e3f4d6SMark Murray
5613e3f4d6SMark Murray #ifdef HAVE_STRUCT_UTMP_UT_HOST
5713e3f4d6SMark Murray int utmp_len = sizeof(wtmp.ut_host);
5813e3f4d6SMark Murray #else
5913e3f4d6SMark Murray int utmp_len = MaxHostNameLen;
6013e3f4d6SMark Murray #endif
6113e3f4d6SMark Murray
6213e3f4d6SMark Murray #ifndef UTMP_FILE
6313e3f4d6SMark Murray #ifdef _PATH_UTMP
6413e3f4d6SMark Murray #define UTMP_FILE _PATH_UTMP
6513e3f4d6SMark Murray #else
6613e3f4d6SMark Murray #define UTMP_FILE "/etc/utmp"
6713e3f4d6SMark Murray #endif
6813e3f4d6SMark Murray #endif
6913e3f4d6SMark Murray
7013e3f4d6SMark Murray /* really, mac os uses wtmpx (or asl) */
7113e3f4d6SMark Murray #ifdef __APPLE__
7213e3f4d6SMark Murray #undef _PATH_WTMP
7313e3f4d6SMark Murray #endif
7413e3f4d6SMark Murray
7513e3f4d6SMark Murray #if !defined(WTMP_FILE) && defined(_PATH_WTMP)
7613e3f4d6SMark Murray #define WTMP_FILE _PATH_WTMP
7713e3f4d6SMark Murray #endif
7813e3f4d6SMark Murray
7913e3f4d6SMark Murray #ifndef PARENT_DOES_UTMP
8013e3f4d6SMark Murray #ifdef WTMP_FILE
8113e3f4d6SMark Murray char wtmpf[] = WTMP_FILE;
8213e3f4d6SMark Murray #else
8313e3f4d6SMark Murray char wtmpf[] = "/usr/adm/wtmp";
8413e3f4d6SMark Murray #endif
8513e3f4d6SMark Murray char utmpf[] = UTMP_FILE;
8613e3f4d6SMark Murray #else /* PARENT_DOES_UTMP */
8713e3f4d6SMark Murray #ifdef WTMP_FILE
8813e3f4d6SMark Murray char wtmpf[] = WTMP_FILE;
8913e3f4d6SMark Murray #else
9013e3f4d6SMark Murray char wtmpf[] = "/etc/wtmp";
9113e3f4d6SMark Murray #endif
9213e3f4d6SMark Murray #endif /* PARENT_DOES_UTMP */
9313e3f4d6SMark Murray
9413e3f4d6SMark Murray #ifdef HAVE_TMPDIR_H
9513e3f4d6SMark Murray #include <tmpdir.h>
9613e3f4d6SMark Murray #endif /* CRAY */
9713e3f4d6SMark Murray
9813e3f4d6SMark Murray #if !(defined(__sgi) || defined(__linux) || defined(_AIX)) && defined(HAVE_SYS_TTY)
9913e3f4d6SMark Murray #include <sys/tty.h>
10013e3f4d6SMark Murray #endif
10113e3f4d6SMark Murray #ifdef t_erase
10213e3f4d6SMark Murray #undef t_erase
10313e3f4d6SMark Murray #undef t_kill
10413e3f4d6SMark Murray #undef t_intrc
10513e3f4d6SMark Murray #undef t_quitc
10613e3f4d6SMark Murray #undef t_startc
10713e3f4d6SMark Murray #undef t_stopc
10813e3f4d6SMark Murray #undef t_eofc
10913e3f4d6SMark Murray #undef t_brkc
11013e3f4d6SMark Murray #undef t_suspc
11113e3f4d6SMark Murray #undef t_dsuspc
11213e3f4d6SMark Murray #undef t_rprntc
11313e3f4d6SMark Murray #undef t_flushc
11413e3f4d6SMark Murray #undef t_werasc
11513e3f4d6SMark Murray #undef t_lnextc
11613e3f4d6SMark Murray #endif
11713e3f4d6SMark Murray
11813e3f4d6SMark Murray #ifdef HAVE_TERMIOS_H
11913e3f4d6SMark Murray #include <termios.h>
12013e3f4d6SMark Murray #else
12113e3f4d6SMark Murray #ifdef HAVE_TERMIO_H
12213e3f4d6SMark Murray #include <termio.h>
12313e3f4d6SMark Murray #endif
1244137ff4cSJacques Vidrine #endif
1254137ff4cSJacques Vidrine
1264137ff4cSJacques Vidrine #ifdef HAVE_UTIL_H
12713e3f4d6SMark Murray #include <util.h>
12813e3f4d6SMark Murray #endif
12913e3f4d6SMark Murray #ifdef HAVE_LIBUTIL_H
13013e3f4d6SMark Murray #include <libutil.h>
13113e3f4d6SMark Murray #endif
13213e3f4d6SMark Murray
13313e3f4d6SMark Murray # ifndef TCSANOW
13413e3f4d6SMark Murray # ifdef TCSETS
13513e3f4d6SMark Murray # define TCSANOW TCSETS
13613e3f4d6SMark Murray # define TCSADRAIN TCSETSW
13713e3f4d6SMark Murray # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
13813e3f4d6SMark Murray # else
13913e3f4d6SMark Murray # ifdef TCSETA
14013e3f4d6SMark Murray # define TCSANOW TCSETA
14113e3f4d6SMark Murray # define TCSADRAIN TCSETAW
14213e3f4d6SMark Murray # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
14313e3f4d6SMark Murray # else
14413e3f4d6SMark Murray # define TCSANOW TIOCSETA
14513e3f4d6SMark Murray # define TCSADRAIN TIOCSETAW
14613e3f4d6SMark Murray # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
14713e3f4d6SMark Murray # endif
14813e3f4d6SMark Murray # endif
14913e3f4d6SMark Murray # define tcsetattr(f, a, t) ioctl(f, a, t)
15013e3f4d6SMark Murray # define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \
15113e3f4d6SMark Murray (tp)->c_cflag |= (val)
15213e3f4d6SMark Murray # define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
15313e3f4d6SMark Murray # ifdef CIBAUD
15413e3f4d6SMark Murray # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \
15513e3f4d6SMark Murray (tp)->c_cflag |= ((val)<<IBSHIFT)
15613e3f4d6SMark Murray # define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT)
15713e3f4d6SMark Murray # else
15813e3f4d6SMark Murray # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \
15913e3f4d6SMark Murray (tp)->c_cflag |= (val)
16013e3f4d6SMark Murray # define cfgetispeed(tp) ((tp)->c_cflag & CBAUD)
16113e3f4d6SMark Murray # endif
16213e3f4d6SMark Murray # endif /* TCSANOW */
16313e3f4d6SMark Murray struct termios termbuf, termbuf2; /* pty control structure */
16413e3f4d6SMark Murray # ifdef STREAMSPTY
16513e3f4d6SMark Murray static int ttyfd = -1;
16613e3f4d6SMark Murray int really_stream = 0;
16713e3f4d6SMark Murray # else
16813e3f4d6SMark Murray #define really_stream 0
16913e3f4d6SMark Murray # endif
17013e3f4d6SMark Murray
17113e3f4d6SMark Murray const char *new_login = _PATH_LOGIN;
17213e3f4d6SMark Murray
17313e3f4d6SMark Murray /*
17413e3f4d6SMark Murray * init_termbuf()
17513e3f4d6SMark Murray * copy_termbuf(cp)
17613e3f4d6SMark Murray * set_termbuf()
17713e3f4d6SMark Murray *
17813e3f4d6SMark Murray * These three routines are used to get and set the "termbuf" structure
17913e3f4d6SMark Murray * to and from the kernel. init_termbuf() gets the current settings.
18013e3f4d6SMark Murray * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
18113e3f4d6SMark Murray * set_termbuf() writes the structure into the kernel.
18213e3f4d6SMark Murray */
18313e3f4d6SMark Murray
18413e3f4d6SMark Murray void
init_termbuf(void)18513e3f4d6SMark Murray init_termbuf(void)
18613e3f4d6SMark Murray {
18713e3f4d6SMark Murray # ifdef STREAMSPTY
18813e3f4d6SMark Murray if (really_stream)
18913e3f4d6SMark Murray tcgetattr(ttyfd, &termbuf);
19013e3f4d6SMark Murray else
19113e3f4d6SMark Murray # endif
19213e3f4d6SMark Murray tcgetattr(ourpty, &termbuf);
19313e3f4d6SMark Murray termbuf2 = termbuf;
19413e3f4d6SMark Murray }
195c19800e8SDoug Rabson
19613e3f4d6SMark Murray void
set_termbuf(void)19713e3f4d6SMark Murray set_termbuf(void)
19813e3f4d6SMark Murray {
19913e3f4d6SMark Murray /*
20013e3f4d6SMark Murray * Only make the necessary changes.
20113e3f4d6SMark Murray */
20213e3f4d6SMark Murray if (memcmp(&termbuf, &termbuf2, sizeof(termbuf))) {
203c19800e8SDoug Rabson # ifdef STREAMSPTY
20413e3f4d6SMark Murray if (really_stream)
20513e3f4d6SMark Murray tcsetattr(ttyfd, TCSANOW, &termbuf);
20613e3f4d6SMark Murray else
20713e3f4d6SMark Murray # endif
20813e3f4d6SMark Murray tcsetattr(ourpty, TCSANOW, &termbuf);
20913e3f4d6SMark Murray }
21013e3f4d6SMark Murray }
21113e3f4d6SMark Murray
21213e3f4d6SMark Murray
21313e3f4d6SMark Murray /*
21413e3f4d6SMark Murray * spcset(func, valp, valpp)
21513e3f4d6SMark Murray *
21613e3f4d6SMark Murray * This function takes various special characters (func), and
21713e3f4d6SMark Murray * sets *valp to the current value of that character, and
21813e3f4d6SMark Murray * *valpp to point to where in the "termbuf" structure that
21913e3f4d6SMark Murray * value is kept.
22013e3f4d6SMark Murray *
22113e3f4d6SMark Murray * It returns the SLC_ level of support for this function.
22213e3f4d6SMark Murray */
22313e3f4d6SMark Murray
22413e3f4d6SMark Murray
22513e3f4d6SMark Murray int
spcset(int func,cc_t * valp,cc_t ** valpp)22613e3f4d6SMark Murray spcset(int func, cc_t *valp, cc_t **valpp)
22713e3f4d6SMark Murray {
22813e3f4d6SMark Murray
22913e3f4d6SMark Murray #define setval(a, b) *valp = termbuf.c_cc[a]; \
23013e3f4d6SMark Murray *valpp = &termbuf.c_cc[a]; \
23113e3f4d6SMark Murray return(b);
23213e3f4d6SMark Murray #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
23313e3f4d6SMark Murray
23413e3f4d6SMark Murray switch(func) {
23513e3f4d6SMark Murray case SLC_EOF:
23613e3f4d6SMark Murray setval(VEOF, SLC_VARIABLE);
23713e3f4d6SMark Murray case SLC_EC:
23813e3f4d6SMark Murray setval(VERASE, SLC_VARIABLE);
23913e3f4d6SMark Murray case SLC_EL:
24013e3f4d6SMark Murray setval(VKILL, SLC_VARIABLE);
24113e3f4d6SMark Murray case SLC_IP:
24213e3f4d6SMark Murray setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
24313e3f4d6SMark Murray case SLC_ABORT:
24413e3f4d6SMark Murray setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
24513e3f4d6SMark Murray case SLC_XON:
24613e3f4d6SMark Murray #ifdef VSTART
24713e3f4d6SMark Murray setval(VSTART, SLC_VARIABLE);
24813e3f4d6SMark Murray #else
24913e3f4d6SMark Murray defval(0x13);
25013e3f4d6SMark Murray #endif
25113e3f4d6SMark Murray case SLC_XOFF:
25213e3f4d6SMark Murray #ifdef VSTOP
25313e3f4d6SMark Murray setval(VSTOP, SLC_VARIABLE);
25413e3f4d6SMark Murray #else
25513e3f4d6SMark Murray defval(0x11);
25613e3f4d6SMark Murray #endif
25713e3f4d6SMark Murray case SLC_EW:
25813e3f4d6SMark Murray #ifdef VWERASE
25913e3f4d6SMark Murray setval(VWERASE, SLC_VARIABLE);
26013e3f4d6SMark Murray #else
26113e3f4d6SMark Murray defval(0);
26213e3f4d6SMark Murray #endif
26313e3f4d6SMark Murray case SLC_RP:
26413e3f4d6SMark Murray #ifdef VREPRINT
26513e3f4d6SMark Murray setval(VREPRINT, SLC_VARIABLE);
26613e3f4d6SMark Murray #else
26713e3f4d6SMark Murray defval(0);
26813e3f4d6SMark Murray #endif
26913e3f4d6SMark Murray case SLC_LNEXT:
27013e3f4d6SMark Murray #ifdef VLNEXT
27113e3f4d6SMark Murray setval(VLNEXT, SLC_VARIABLE);
27213e3f4d6SMark Murray #else
27313e3f4d6SMark Murray defval(0);
27413e3f4d6SMark Murray #endif
27513e3f4d6SMark Murray case SLC_AO:
27613e3f4d6SMark Murray #if !defined(VDISCARD) && defined(VFLUSHO)
27713e3f4d6SMark Murray # define VDISCARD VFLUSHO
27813e3f4d6SMark Murray #endif
27913e3f4d6SMark Murray #ifdef VDISCARD
28013e3f4d6SMark Murray setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
28113e3f4d6SMark Murray #else
28213e3f4d6SMark Murray defval(0);
28313e3f4d6SMark Murray #endif
28413e3f4d6SMark Murray case SLC_SUSP:
28513e3f4d6SMark Murray #ifdef VSUSP
28613e3f4d6SMark Murray setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
28713e3f4d6SMark Murray #else
28813e3f4d6SMark Murray defval(0);
28913e3f4d6SMark Murray #endif
29013e3f4d6SMark Murray #ifdef VEOL
29113e3f4d6SMark Murray case SLC_FORW1:
29213e3f4d6SMark Murray setval(VEOL, SLC_VARIABLE);
29313e3f4d6SMark Murray #endif
29413e3f4d6SMark Murray #ifdef VEOL2
29513e3f4d6SMark Murray case SLC_FORW2:
29613e3f4d6SMark Murray setval(VEOL2, SLC_VARIABLE);
29713e3f4d6SMark Murray #endif
29813e3f4d6SMark Murray case SLC_AYT:
29913e3f4d6SMark Murray #ifdef VSTATUS
30013e3f4d6SMark Murray setval(VSTATUS, SLC_VARIABLE);
30113e3f4d6SMark Murray #else
30213e3f4d6SMark Murray defval(0);
30313e3f4d6SMark Murray #endif
30413e3f4d6SMark Murray
30513e3f4d6SMark Murray case SLC_BRK:
30613e3f4d6SMark Murray case SLC_SYNCH:
30713e3f4d6SMark Murray case SLC_EOR:
30813e3f4d6SMark Murray defval(0);
30913e3f4d6SMark Murray
31013e3f4d6SMark Murray default:
31113e3f4d6SMark Murray *valp = 0;
31213e3f4d6SMark Murray *valpp = 0;
31313e3f4d6SMark Murray return(SLC_NOSUPPORT);
31413e3f4d6SMark Murray }
31513e3f4d6SMark Murray }
31613e3f4d6SMark Murray
31713e3f4d6SMark Murray #ifdef _CRAY
31813e3f4d6SMark Murray /*
31913e3f4d6SMark Murray * getnpty()
32013e3f4d6SMark Murray *
32113e3f4d6SMark Murray * Return the number of pty's configured into the system.
32213e3f4d6SMark Murray */
32313e3f4d6SMark Murray int
getnpty()32413e3f4d6SMark Murray getnpty()
32513e3f4d6SMark Murray {
32613e3f4d6SMark Murray #ifdef _SC_CRAY_NPTY
32713e3f4d6SMark Murray int numptys;
32813e3f4d6SMark Murray
32913e3f4d6SMark Murray if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1)
33013e3f4d6SMark Murray return numptys;
33113e3f4d6SMark Murray else
33213e3f4d6SMark Murray #endif /* _SC_CRAY_NPTY */
33313e3f4d6SMark Murray return 128;
33413e3f4d6SMark Murray }
33513e3f4d6SMark Murray #endif /* CRAY */
33613e3f4d6SMark Murray
33713e3f4d6SMark Murray /*
33813e3f4d6SMark Murray * getpty()
339c19800e8SDoug Rabson *
340c19800e8SDoug Rabson * Allocate a pty. As a side effect, the external character
34113e3f4d6SMark Murray * array "line" contains the name of the slave side.
34213e3f4d6SMark Murray *
34313e3f4d6SMark Murray * Returns the file descriptor of the opened pty.
34413e3f4d6SMark Murray */
34513e3f4d6SMark Murray
34613e3f4d6SMark Murray static int ptyslavefd = -1;
34713e3f4d6SMark Murray
34813e3f4d6SMark Murray static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
34913e3f4d6SMark Murray char *line = Xline;
35013e3f4d6SMark Murray
35113e3f4d6SMark Murray #ifdef _CRAY
35213e3f4d6SMark Murray char myline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
35313e3f4d6SMark Murray #endif /* CRAY */
35413e3f4d6SMark Murray
35513e3f4d6SMark Murray #if !defined(HAVE_PTSNAME) && defined(STREAMSPTY)
ptsname(int fd)35613e3f4d6SMark Murray static char *ptsname(int fd)
35713e3f4d6SMark Murray {
35813e3f4d6SMark Murray #ifdef HAVE_TTYNAME
35913e3f4d6SMark Murray return ttyname(fd);
36013e3f4d6SMark Murray #else
361c19800e8SDoug Rabson return NULL;
362c19800e8SDoug Rabson #endif
36313e3f4d6SMark Murray }
36413e3f4d6SMark Murray #endif
36513e3f4d6SMark Murray
getpty(int * ptynum)366c19800e8SDoug Rabson int getpty(int *ptynum)
36713e3f4d6SMark Murray {
36813e3f4d6SMark Murray #if defined(HAVE_OPENPTY) || defined(__linux) || defined(__osf__) /* XXX */
369c19800e8SDoug Rabson {
370c19800e8SDoug Rabson int master;
37113e3f4d6SMark Murray int slave;
372c19800e8SDoug Rabson if(openpty(&master, &slave, line, 0, 0) == 0){
373c19800e8SDoug Rabson ptyslavefd = slave;
37413e3f4d6SMark Murray return master;
37513e3f4d6SMark Murray }
37613e3f4d6SMark Murray }
37713e3f4d6SMark Murray #endif /* HAVE_OPENPTY .... */
37813e3f4d6SMark Murray #ifdef HAVE__GETPTY
37913e3f4d6SMark Murray {
38013e3f4d6SMark Murray int master;
381c19800e8SDoug Rabson char *p;
382c19800e8SDoug Rabson p = _getpty(&master, O_RDWR, 0600, 1);
38313e3f4d6SMark Murray if(p == NULL)
384c19800e8SDoug Rabson return -1;
38513e3f4d6SMark Murray strlcpy(line, p, sizeof(Xline));
38613e3f4d6SMark Murray return master;
38713e3f4d6SMark Murray }
38813e3f4d6SMark Murray #endif
389c19800e8SDoug Rabson
39013e3f4d6SMark Murray #ifdef STREAMSPTY
39113e3f4d6SMark Murray {
39213e3f4d6SMark Murray char *clone[] = { "/dev/ptc", "/dev/ptmx", "/dev/ptm",
39313e3f4d6SMark Murray "/dev/ptym/clone", 0 };
39413e3f4d6SMark Murray
39513e3f4d6SMark Murray char **q;
39613e3f4d6SMark Murray int p;
39713e3f4d6SMark Murray for(q=clone; *q; q++){
39813e3f4d6SMark Murray p=open(*q, O_RDWR);
39913e3f4d6SMark Murray if(p >= 0){
40013e3f4d6SMark Murray #ifdef HAVE_GRANTPT
40113e3f4d6SMark Murray grantpt(p);
40213e3f4d6SMark Murray #endif
40313e3f4d6SMark Murray #ifdef HAVE_UNLOCKPT
404c19800e8SDoug Rabson unlockpt(p);
40513e3f4d6SMark Murray #endif
40613e3f4d6SMark Murray strlcpy(line, ptsname(p), sizeof(Xline));
407c19800e8SDoug Rabson really_stream = 1;
408c19800e8SDoug Rabson return p;
409c19800e8SDoug Rabson }
410c19800e8SDoug Rabson }
41113e3f4d6SMark Murray }
41213e3f4d6SMark Murray #endif /* STREAMSPTY */
41313e3f4d6SMark Murray #ifndef _CRAY
41413e3f4d6SMark Murray {
41513e3f4d6SMark Murray int p;
41613e3f4d6SMark Murray char *cp, *p1, *p2;
41713e3f4d6SMark Murray int i;
41813e3f4d6SMark Murray
41913e3f4d6SMark Murray #ifndef __hpux
42013e3f4d6SMark Murray snprintf(line, sizeof(Xline), "/dev/ptyXX");
42113e3f4d6SMark Murray p1 = &line[8];
42213e3f4d6SMark Murray p2 = &line[9];
42313e3f4d6SMark Murray #else
42413e3f4d6SMark Murray snprintf(line, sizeof(Xline), "/dev/ptym/ptyXX");
42513e3f4d6SMark Murray p1 = &line[13];
42613e3f4d6SMark Murray p2 = &line[14];
42713e3f4d6SMark Murray #endif
42813e3f4d6SMark Murray
42913e3f4d6SMark Murray
43013e3f4d6SMark Murray for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) {
43113e3f4d6SMark Murray struct stat stb;
43213e3f4d6SMark Murray
43313e3f4d6SMark Murray *p1 = *cp;
43413e3f4d6SMark Murray *p2 = '0';
43513e3f4d6SMark Murray /*
43613e3f4d6SMark Murray * This stat() check is just to keep us from
43713e3f4d6SMark Murray * looping through all 256 combinations if there
43813e3f4d6SMark Murray * aren't that many ptys available.
439c19800e8SDoug Rabson */
440c19800e8SDoug Rabson if (stat(line, &stb) < 0)
441c19800e8SDoug Rabson break;
442c19800e8SDoug Rabson for (i = 0; i < 16; i++) {
44313e3f4d6SMark Murray *p2 = "0123456789abcdef"[i];
44413e3f4d6SMark Murray p = open(line, O_RDWR);
44513e3f4d6SMark Murray if (p > 0) {
44613e3f4d6SMark Murray #if SunOS == 40
44713e3f4d6SMark Murray int dummy;
44813e3f4d6SMark Murray #endif
44913e3f4d6SMark Murray
45013e3f4d6SMark Murray #ifndef __hpux
45113e3f4d6SMark Murray line[5] = 't';
45213e3f4d6SMark Murray #else
45313e3f4d6SMark Murray for (p1 = &line[8]; *p1; p1++)
45413e3f4d6SMark Murray *p1 = *(p1+1);
45513e3f4d6SMark Murray line[9] = 't';
45613e3f4d6SMark Murray #endif
45713e3f4d6SMark Murray chown(line, 0, 0);
45813e3f4d6SMark Murray chmod(line, 0600);
45913e3f4d6SMark Murray #if SunOS == 40
46013e3f4d6SMark Murray if (ioctl(p, TIOCGPGRP, &dummy) == 0
46113e3f4d6SMark Murray || errno != EIO) {
46213e3f4d6SMark Murray chmod(line, 0666);
46313e3f4d6SMark Murray close(p);
464c19800e8SDoug Rabson line[5] = 'p';
46513e3f4d6SMark Murray } else
466c19800e8SDoug Rabson #endif /* SunOS == 40 */
46713e3f4d6SMark Murray return(p);
46813e3f4d6SMark Murray }
469c19800e8SDoug Rabson }
47013e3f4d6SMark Murray }
47113e3f4d6SMark Murray }
47213e3f4d6SMark Murray #else /* CRAY */
47313e3f4d6SMark Murray {
47413e3f4d6SMark Murray extern lowpty, highpty;
47513e3f4d6SMark Murray struct stat sb;
47613e3f4d6SMark Murray int p;
47713e3f4d6SMark Murray
47813e3f4d6SMark Murray for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) {
47913e3f4d6SMark Murray snprintf(myline, sizeof(myline), "/dev/pty/%03d", *ptynum);
48013e3f4d6SMark Murray p = open(myline, 2);
48113e3f4d6SMark Murray if (p < 0)
48213e3f4d6SMark Murray continue;
48313e3f4d6SMark Murray snprintf(line, sizeof(Xline), "/dev/ttyp%03d", *ptynum);
48413e3f4d6SMark Murray /*
48513e3f4d6SMark Murray * Here are some shenanigans to make sure that there
48613e3f4d6SMark Murray * are no listeners lurking on the line.
48713e3f4d6SMark Murray */
48813e3f4d6SMark Murray if(stat(line, &sb) < 0) {
48913e3f4d6SMark Murray close(p);
49013e3f4d6SMark Murray continue;
49113e3f4d6SMark Murray }
49213e3f4d6SMark Murray if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
49313e3f4d6SMark Murray chown(line, 0, 0);
49413e3f4d6SMark Murray chmod(line, 0600);
49513e3f4d6SMark Murray close(p);
49613e3f4d6SMark Murray p = open(myline, 2);
49713e3f4d6SMark Murray if (p < 0)
49813e3f4d6SMark Murray continue;
49913e3f4d6SMark Murray }
50013e3f4d6SMark Murray /*
50113e3f4d6SMark Murray * Now it should be safe...check for accessability.
50213e3f4d6SMark Murray */
503c19800e8SDoug Rabson if (access(line, 6) == 0)
50413e3f4d6SMark Murray return(p);
50513e3f4d6SMark Murray else {
50613e3f4d6SMark Murray /* no tty side to pty so skip it */
50713e3f4d6SMark Murray close(p);
50813e3f4d6SMark Murray }
50913e3f4d6SMark Murray }
51013e3f4d6SMark Murray }
51113e3f4d6SMark Murray #endif /* CRAY */
51213e3f4d6SMark Murray return(-1);
51313e3f4d6SMark Murray }
51413e3f4d6SMark Murray
51513e3f4d6SMark Murray
51613e3f4d6SMark Murray int
tty_isecho(void)51713e3f4d6SMark Murray tty_isecho(void)
51813e3f4d6SMark Murray {
51913e3f4d6SMark Murray return (termbuf.c_lflag & ECHO);
52013e3f4d6SMark Murray }
52113e3f4d6SMark Murray
52213e3f4d6SMark Murray int
tty_flowmode(void)52313e3f4d6SMark Murray tty_flowmode(void)
52413e3f4d6SMark Murray {
52513e3f4d6SMark Murray return((termbuf.c_iflag & IXON) ? 1 : 0);
52613e3f4d6SMark Murray }
52713e3f4d6SMark Murray
52813e3f4d6SMark Murray int
tty_restartany(void)52913e3f4d6SMark Murray tty_restartany(void)
53013e3f4d6SMark Murray {
53113e3f4d6SMark Murray return((termbuf.c_iflag & IXANY) ? 1 : 0);
53213e3f4d6SMark Murray }
53313e3f4d6SMark Murray
53413e3f4d6SMark Murray void
tty_setecho(int on)53513e3f4d6SMark Murray tty_setecho(int on)
53613e3f4d6SMark Murray {
53713e3f4d6SMark Murray if (on)
53813e3f4d6SMark Murray termbuf.c_lflag |= ECHO;
53913e3f4d6SMark Murray else
54013e3f4d6SMark Murray termbuf.c_lflag &= ~ECHO;
54113e3f4d6SMark Murray }
54213e3f4d6SMark Murray
54313e3f4d6SMark Murray int
tty_israw(void)54413e3f4d6SMark Murray tty_israw(void)
54513e3f4d6SMark Murray {
54613e3f4d6SMark Murray return(!(termbuf.c_lflag & ICANON));
54713e3f4d6SMark Murray }
54813e3f4d6SMark Murray
54913e3f4d6SMark Murray void
tty_binaryin(int on)55013e3f4d6SMark Murray tty_binaryin(int on)
55113e3f4d6SMark Murray {
55213e3f4d6SMark Murray if (on) {
55313e3f4d6SMark Murray termbuf.c_iflag &= ~ISTRIP;
55413e3f4d6SMark Murray } else {
55513e3f4d6SMark Murray termbuf.c_iflag |= ISTRIP;
55613e3f4d6SMark Murray }
55713e3f4d6SMark Murray }
55813e3f4d6SMark Murray
55913e3f4d6SMark Murray void
tty_binaryout(int on)56013e3f4d6SMark Murray tty_binaryout(int on)
56113e3f4d6SMark Murray {
56213e3f4d6SMark Murray if (on) {
56313e3f4d6SMark Murray termbuf.c_cflag &= ~(CSIZE|PARENB);
56413e3f4d6SMark Murray termbuf.c_cflag |= CS8;
56513e3f4d6SMark Murray termbuf.c_oflag &= ~OPOST;
56613e3f4d6SMark Murray } else {
56713e3f4d6SMark Murray termbuf.c_cflag &= ~CSIZE;
56813e3f4d6SMark Murray termbuf.c_cflag |= CS7|PARENB;
56913e3f4d6SMark Murray termbuf.c_oflag |= OPOST;
57013e3f4d6SMark Murray }
57113e3f4d6SMark Murray }
57213e3f4d6SMark Murray
57313e3f4d6SMark Murray int
tty_isbinaryin(void)57413e3f4d6SMark Murray tty_isbinaryin(void)
57513e3f4d6SMark Murray {
57613e3f4d6SMark Murray return(!(termbuf.c_iflag & ISTRIP));
57713e3f4d6SMark Murray }
57813e3f4d6SMark Murray
57913e3f4d6SMark Murray int
tty_isbinaryout(void)58013e3f4d6SMark Murray tty_isbinaryout(void)
58113e3f4d6SMark Murray {
58213e3f4d6SMark Murray return(!(termbuf.c_oflag&OPOST));
58313e3f4d6SMark Murray }
58413e3f4d6SMark Murray
58513e3f4d6SMark Murray
58613e3f4d6SMark Murray int
tty_issofttab(void)58713e3f4d6SMark Murray tty_issofttab(void)
58813e3f4d6SMark Murray {
58913e3f4d6SMark Murray # ifdef OXTABS
59013e3f4d6SMark Murray return (termbuf.c_oflag & OXTABS);
59113e3f4d6SMark Murray # endif
59213e3f4d6SMark Murray # ifdef TABDLY
59313e3f4d6SMark Murray return ((termbuf.c_oflag & TABDLY) == TAB3);
59413e3f4d6SMark Murray # endif
59513e3f4d6SMark Murray }
59613e3f4d6SMark Murray
59713e3f4d6SMark Murray void
tty_setsofttab(int on)59813e3f4d6SMark Murray tty_setsofttab(int on)
59913e3f4d6SMark Murray {
60013e3f4d6SMark Murray if (on) {
60113e3f4d6SMark Murray # ifdef OXTABS
60213e3f4d6SMark Murray termbuf.c_oflag |= OXTABS;
60313e3f4d6SMark Murray # endif
60413e3f4d6SMark Murray # ifdef TABDLY
60513e3f4d6SMark Murray termbuf.c_oflag &= ~TABDLY;
60613e3f4d6SMark Murray termbuf.c_oflag |= TAB3;
60713e3f4d6SMark Murray # endif
60813e3f4d6SMark Murray } else {
60913e3f4d6SMark Murray # ifdef OXTABS
61013e3f4d6SMark Murray termbuf.c_oflag &= ~OXTABS;
61113e3f4d6SMark Murray # endif
61213e3f4d6SMark Murray # ifdef TABDLY
61313e3f4d6SMark Murray termbuf.c_oflag &= ~TABDLY;
61413e3f4d6SMark Murray termbuf.c_oflag |= TAB0;
61513e3f4d6SMark Murray # endif
61613e3f4d6SMark Murray }
61713e3f4d6SMark Murray }
61813e3f4d6SMark Murray
61913e3f4d6SMark Murray int
tty_islitecho(void)62013e3f4d6SMark Murray tty_islitecho(void)
62113e3f4d6SMark Murray {
62213e3f4d6SMark Murray # ifdef ECHOCTL
62313e3f4d6SMark Murray return (!(termbuf.c_lflag & ECHOCTL));
62413e3f4d6SMark Murray # endif
62513e3f4d6SMark Murray # ifdef TCTLECH
62613e3f4d6SMark Murray return (!(termbuf.c_lflag & TCTLECH));
62713e3f4d6SMark Murray # endif
62813e3f4d6SMark Murray # if !defined(ECHOCTL) && !defined(TCTLECH)
62913e3f4d6SMark Murray return (0); /* assumes ctl chars are echoed '^x' */
63013e3f4d6SMark Murray # endif
63113e3f4d6SMark Murray }
63213e3f4d6SMark Murray
63313e3f4d6SMark Murray void
tty_setlitecho(int on)63413e3f4d6SMark Murray tty_setlitecho(int on)
63513e3f4d6SMark Murray {
63613e3f4d6SMark Murray # ifdef ECHOCTL
63713e3f4d6SMark Murray if (on)
63813e3f4d6SMark Murray termbuf.c_lflag &= ~ECHOCTL;
63913e3f4d6SMark Murray else
64013e3f4d6SMark Murray termbuf.c_lflag |= ECHOCTL;
64113e3f4d6SMark Murray # endif
64213e3f4d6SMark Murray # ifdef TCTLECH
64313e3f4d6SMark Murray if (on)
64413e3f4d6SMark Murray termbuf.c_lflag &= ~TCTLECH;
64513e3f4d6SMark Murray else
64613e3f4d6SMark Murray termbuf.c_lflag |= TCTLECH;
64713e3f4d6SMark Murray # endif
64813e3f4d6SMark Murray }
64913e3f4d6SMark Murray
65013e3f4d6SMark Murray int
tty_iscrnl(void)65113e3f4d6SMark Murray tty_iscrnl(void)
65213e3f4d6SMark Murray {
65313e3f4d6SMark Murray return (termbuf.c_iflag & ICRNL);
65413e3f4d6SMark Murray }
65513e3f4d6SMark Murray
65613e3f4d6SMark Murray /*
65713e3f4d6SMark Murray * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
65813e3f4d6SMark Murray */
65913e3f4d6SMark Murray #if B4800 != 4800
66013e3f4d6SMark Murray #define DECODE_BAUD
66113e3f4d6SMark Murray #endif
66213e3f4d6SMark Murray
66313e3f4d6SMark Murray #ifdef DECODE_BAUD
66413e3f4d6SMark Murray
66513e3f4d6SMark Murray /*
66613e3f4d6SMark Murray * A table of available terminal speeds
66713e3f4d6SMark Murray */
66813e3f4d6SMark Murray struct termspeeds {
66913e3f4d6SMark Murray int speed;
67013e3f4d6SMark Murray int value;
67113e3f4d6SMark Murray } termspeeds[] = {
67213e3f4d6SMark Murray { 0, B0 }, { 50, B50 }, { 75, B75 },
67313e3f4d6SMark Murray { 110, B110 }, { 134, B134 }, { 150, B150 },
67413e3f4d6SMark Murray { 200, B200 }, { 300, B300 }, { 600, B600 },
67513e3f4d6SMark Murray { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 },
67613e3f4d6SMark Murray { 4800, B4800 },
67713e3f4d6SMark Murray #ifdef B7200
67813e3f4d6SMark Murray { 7200, B7200 },
67913e3f4d6SMark Murray #endif
68013e3f4d6SMark Murray { 9600, B9600 },
68113e3f4d6SMark Murray #ifdef B14400
68213e3f4d6SMark Murray { 14400, B14400 },
68313e3f4d6SMark Murray #endif
68413e3f4d6SMark Murray #ifdef B19200
68513e3f4d6SMark Murray { 19200, B19200 },
68613e3f4d6SMark Murray #endif
68713e3f4d6SMark Murray #ifdef B28800
68813e3f4d6SMark Murray { 28800, B28800 },
68913e3f4d6SMark Murray #endif
69013e3f4d6SMark Murray #ifdef B38400
69113e3f4d6SMark Murray { 38400, B38400 },
69213e3f4d6SMark Murray #endif
69313e3f4d6SMark Murray #ifdef B57600
69413e3f4d6SMark Murray { 57600, B57600 },
69513e3f4d6SMark Murray #endif
69613e3f4d6SMark Murray #ifdef B115200
69713e3f4d6SMark Murray { 115200, B115200 },
69813e3f4d6SMark Murray #endif
69913e3f4d6SMark Murray #ifdef B230400
70013e3f4d6SMark Murray { 230400, B230400 },
70113e3f4d6SMark Murray #endif
70213e3f4d6SMark Murray { -1, 0 }
70313e3f4d6SMark Murray };
70413e3f4d6SMark Murray #endif /* DECODE_BUAD */
70513e3f4d6SMark Murray
70613e3f4d6SMark Murray void
tty_tspeed(int val)70713e3f4d6SMark Murray tty_tspeed(int val)
70813e3f4d6SMark Murray {
70913e3f4d6SMark Murray #ifdef DECODE_BAUD
71013e3f4d6SMark Murray struct termspeeds *tp;
71113e3f4d6SMark Murray
71213e3f4d6SMark Murray for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
71313e3f4d6SMark Murray ;
71413e3f4d6SMark Murray if (tp->speed == -1) /* back up to last valid value */
71513e3f4d6SMark Murray --tp;
71613e3f4d6SMark Murray cfsetospeed(&termbuf, tp->value);
71713e3f4d6SMark Murray #else /* DECODE_BUAD */
71813e3f4d6SMark Murray cfsetospeed(&termbuf, val);
71913e3f4d6SMark Murray #endif /* DECODE_BUAD */
72013e3f4d6SMark Murray }
72113e3f4d6SMark Murray
72213e3f4d6SMark Murray void
tty_rspeed(int val)72313e3f4d6SMark Murray tty_rspeed(int val)
72413e3f4d6SMark Murray {
72513e3f4d6SMark Murray #ifdef DECODE_BAUD
72613e3f4d6SMark Murray struct termspeeds *tp;
72713e3f4d6SMark Murray
72813e3f4d6SMark Murray for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
72913e3f4d6SMark Murray ;
73013e3f4d6SMark Murray if (tp->speed == -1) /* back up to last valid value */
73113e3f4d6SMark Murray --tp;
73213e3f4d6SMark Murray cfsetispeed(&termbuf, tp->value);
73313e3f4d6SMark Murray #else /* DECODE_BAUD */
73413e3f4d6SMark Murray cfsetispeed(&termbuf, val);
73513e3f4d6SMark Murray #endif /* DECODE_BAUD */
73613e3f4d6SMark Murray }
73713e3f4d6SMark Murray
73813e3f4d6SMark Murray #ifdef PARENT_DOES_UTMP
73913e3f4d6SMark Murray extern struct utmp wtmp;
74013e3f4d6SMark Murray extern char wtmpf[];
74113e3f4d6SMark Murray
74213e3f4d6SMark Murray extern void utmp_sig_init (void);
74313e3f4d6SMark Murray extern void utmp_sig_reset (void);
74413e3f4d6SMark Murray extern void utmp_sig_wait (void);
74513e3f4d6SMark Murray extern void utmp_sig_notify (int);
74613e3f4d6SMark Murray # endif /* PARENT_DOES_UTMP */
74713e3f4d6SMark Murray
74813e3f4d6SMark Murray #ifdef STREAMSPTY
74913e3f4d6SMark Murray
75013e3f4d6SMark Murray /* I_FIND seems to live a life of its own */
my_find(int fd,char * module)75113e3f4d6SMark Murray static int my_find(int fd, char *module)
75213e3f4d6SMark Murray {
75313e3f4d6SMark Murray #if defined(I_FIND) && defined(I_LIST)
75413e3f4d6SMark Murray static int flag;
75513e3f4d6SMark Murray static struct str_list sl;
75613e3f4d6SMark Murray int n;
75713e3f4d6SMark Murray int i;
75813e3f4d6SMark Murray
75913e3f4d6SMark Murray if(!flag){
76013e3f4d6SMark Murray n = ioctl(fd, I_LIST, 0);
76113e3f4d6SMark Murray if(n < 0){
76213e3f4d6SMark Murray perror("ioctl(fd, I_LIST, 0)");
76313e3f4d6SMark Murray return -1;
76413e3f4d6SMark Murray }
76513e3f4d6SMark Murray sl.sl_modlist=(struct str_mlist*)malloc(n * sizeof(struct str_mlist));
76613e3f4d6SMark Murray sl.sl_nmods = n;
76713e3f4d6SMark Murray n = ioctl(fd, I_LIST, &sl);
76813e3f4d6SMark Murray if(n < 0){
76913e3f4d6SMark Murray perror("ioctl(fd, I_LIST, n)");
77013e3f4d6SMark Murray return -1;
77113e3f4d6SMark Murray }
77213e3f4d6SMark Murray flag = 1;
77313e3f4d6SMark Murray }
77413e3f4d6SMark Murray
77513e3f4d6SMark Murray for(i=0; i<sl.sl_nmods; i++)
77613e3f4d6SMark Murray if(!strcmp(sl.sl_modlist[i].l_name, module))
77713e3f4d6SMark Murray return 1;
77813e3f4d6SMark Murray #endif
77913e3f4d6SMark Murray return 0;
78013e3f4d6SMark Murray }
78113e3f4d6SMark Murray
maybe_push_modules(int fd,char ** modules)78213e3f4d6SMark Murray static void maybe_push_modules(int fd, char **modules)
78313e3f4d6SMark Murray {
78413e3f4d6SMark Murray char **p;
78513e3f4d6SMark Murray int err;
78613e3f4d6SMark Murray
78713e3f4d6SMark Murray for(p=modules; *p; p++){
78813e3f4d6SMark Murray err = my_find(fd, *p);
78913e3f4d6SMark Murray if(err == 1)
79013e3f4d6SMark Murray break;
79113e3f4d6SMark Murray if(err < 0 && errno != EINVAL)
79213e3f4d6SMark Murray fatalperror(net, "my_find()");
79313e3f4d6SMark Murray /* module not pushed or does not exist */
79413e3f4d6SMark Murray }
79513e3f4d6SMark Murray /* p points to null or to an already pushed module, now push all
79613e3f4d6SMark Murray modules before this one */
79713e3f4d6SMark Murray
79813e3f4d6SMark Murray for(p--; p >= modules; p--){
79913e3f4d6SMark Murray err = ioctl(fd, I_PUSH, *p);
80013e3f4d6SMark Murray if(err < 0 && errno != EINVAL)
80113e3f4d6SMark Murray fatalperror(net, "I_PUSH");
80213e3f4d6SMark Murray }
80313e3f4d6SMark Murray }
80413e3f4d6SMark Murray #endif
80513e3f4d6SMark Murray
80613e3f4d6SMark Murray /*
80713e3f4d6SMark Murray * getptyslave()
80813e3f4d6SMark Murray *
80913e3f4d6SMark Murray * Open the slave side of the pty, and do any initialization
81013e3f4d6SMark Murray * that is necessary. The return value is a file descriptor
81113e3f4d6SMark Murray * for the slave side.
81213e3f4d6SMark Murray */
getptyslave(void)81313e3f4d6SMark Murray void getptyslave(void)
81413e3f4d6SMark Murray {
81513e3f4d6SMark Murray int t = -1;
81613e3f4d6SMark Murray
81713e3f4d6SMark Murray struct winsize ws;
81813e3f4d6SMark Murray /*
81913e3f4d6SMark Murray * Opening the slave side may cause initilization of the
82013e3f4d6SMark Murray * kernel tty structure. We need remember the state of
82113e3f4d6SMark Murray * if linemode was turned on
82213e3f4d6SMark Murray * terminal window size
82313e3f4d6SMark Murray * terminal speed
82413e3f4d6SMark Murray * so that we can re-set them if we need to.
82513e3f4d6SMark Murray */
82613e3f4d6SMark Murray
82713e3f4d6SMark Murray
82813e3f4d6SMark Murray /*
82913e3f4d6SMark Murray * Make sure that we don't have a controlling tty, and
83013e3f4d6SMark Murray * that we are the session (process group) leader.
83113e3f4d6SMark Murray */
83213e3f4d6SMark Murray
83313e3f4d6SMark Murray #ifdef HAVE_SETSID
83413e3f4d6SMark Murray if(setsid()<0)
83513e3f4d6SMark Murray fatalperror(net, "setsid()");
83613e3f4d6SMark Murray #else
83713e3f4d6SMark Murray # ifdef TIOCNOTTY
83813e3f4d6SMark Murray t = open(_PATH_TTY, O_RDWR);
83913e3f4d6SMark Murray if (t >= 0) {
84013e3f4d6SMark Murray ioctl(t, TIOCNOTTY, (char *)0);
84113e3f4d6SMark Murray close(t);
84213e3f4d6SMark Murray }
84313e3f4d6SMark Murray # endif
84413e3f4d6SMark Murray #endif
84513e3f4d6SMark Murray
84613e3f4d6SMark Murray # ifdef PARENT_DOES_UTMP
84713e3f4d6SMark Murray /*
84813e3f4d6SMark Murray * Wait for our parent to get the utmp stuff to get done.
84913e3f4d6SMark Murray */
85013e3f4d6SMark Murray utmp_sig_wait();
85113e3f4d6SMark Murray # endif
85213e3f4d6SMark Murray
85313e3f4d6SMark Murray t = cleanopen(line);
85413e3f4d6SMark Murray if (t < 0)
85513e3f4d6SMark Murray fatalperror(net, line);
85613e3f4d6SMark Murray
85713e3f4d6SMark Murray #ifdef STREAMSPTY
85813e3f4d6SMark Murray ttyfd = t;
85913e3f4d6SMark Murray
86013e3f4d6SMark Murray
86113e3f4d6SMark Murray /*
86213e3f4d6SMark Murray * Not all systems have (or need) modules ttcompat and pckt so
86313e3f4d6SMark Murray * don't flag it as a fatal error if they don't exist.
86413e3f4d6SMark Murray */
86513e3f4d6SMark Murray
86613e3f4d6SMark Murray if (really_stream)
86713e3f4d6SMark Murray {
86813e3f4d6SMark Murray /* these are the streams modules that we want pushed. note
86913e3f4d6SMark Murray that they are in reverse order, ptem will be pushed
87013e3f4d6SMark Murray first. maybe_push_modules() will try to push all modules
87113e3f4d6SMark Murray before the first one that isn't already pushed. i.e if
87213e3f4d6SMark Murray ldterm is pushed, only ttcompat will be attempted.
87313e3f4d6SMark Murray
87413e3f4d6SMark Murray all this is because we don't know which modules are
87513e3f4d6SMark Murray available, and we don't know which modules are already
87613e3f4d6SMark Murray pushed (via autopush, for instance).
87713e3f4d6SMark Murray
87813e3f4d6SMark Murray */
87913e3f4d6SMark Murray
88013e3f4d6SMark Murray char *ttymodules[] = { "ttcompat", "ldterm", "ptem", NULL };
88113e3f4d6SMark Murray char *ptymodules[] = { "pckt", NULL };
88213e3f4d6SMark Murray
88313e3f4d6SMark Murray maybe_push_modules(t, ttymodules);
88413e3f4d6SMark Murray maybe_push_modules(ourpty, ptymodules);
88513e3f4d6SMark Murray }
88613e3f4d6SMark Murray #endif
88713e3f4d6SMark Murray /*
88813e3f4d6SMark Murray * set up the tty modes as we like them to be.
88913e3f4d6SMark Murray */
89013e3f4d6SMark Murray init_termbuf();
89113e3f4d6SMark Murray # ifdef TIOCSWINSZ
89213e3f4d6SMark Murray if (def_row || def_col) {
89313e3f4d6SMark Murray memset(&ws, 0, sizeof(ws));
89413e3f4d6SMark Murray ws.ws_col = def_col;
89513e3f4d6SMark Murray ws.ws_row = def_row;
89613e3f4d6SMark Murray ioctl(t, TIOCSWINSZ, (char *)&ws);
89713e3f4d6SMark Murray }
89813e3f4d6SMark Murray # endif
89913e3f4d6SMark Murray
90013e3f4d6SMark Murray /*
90113e3f4d6SMark Murray * Settings for sgtty based systems
90213e3f4d6SMark Murray */
90313e3f4d6SMark Murray
90413e3f4d6SMark Murray /*
90513e3f4d6SMark Murray * Settings for UNICOS (and HPUX)
90613e3f4d6SMark Murray */
90713e3f4d6SMark Murray # if defined(_CRAY) || defined(__hpux)
90813e3f4d6SMark Murray termbuf.c_oflag = OPOST|ONLCR|TAB3;
90913e3f4d6SMark Murray termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
91013e3f4d6SMark Murray termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
91113e3f4d6SMark Murray termbuf.c_cflag = EXTB|HUPCL|CS8;
91213e3f4d6SMark Murray # endif
91313e3f4d6SMark Murray
91413e3f4d6SMark Murray /*
91513e3f4d6SMark Murray * Settings for all other termios/termio based
91613e3f4d6SMark Murray * systems, other than 4.4BSD. In 4.4BSD the
91713e3f4d6SMark Murray * kernel does the initial terminal setup.
91813e3f4d6SMark Murray */
91913e3f4d6SMark Murray # if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43)
92013e3f4d6SMark Murray # ifndef OXTABS
92113e3f4d6SMark Murray # define OXTABS 0
92213e3f4d6SMark Murray # endif
92313e3f4d6SMark Murray termbuf.c_lflag |= ECHO;
92413e3f4d6SMark Murray termbuf.c_oflag |= ONLCR|OXTABS;
92513e3f4d6SMark Murray termbuf.c_iflag |= ICRNL;
92613e3f4d6SMark Murray termbuf.c_iflag &= ~IXOFF;
92713e3f4d6SMark Murray # endif
92813e3f4d6SMark Murray tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
92913e3f4d6SMark Murray tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
93013e3f4d6SMark Murray
93113e3f4d6SMark Murray /*
93213e3f4d6SMark Murray * Set the tty modes, and make this our controlling tty.
93313e3f4d6SMark Murray */
93413e3f4d6SMark Murray set_termbuf();
93513e3f4d6SMark Murray if (login_tty(t) == -1)
93613e3f4d6SMark Murray fatalperror(net, "login_tty");
93713e3f4d6SMark Murray if (net > 2)
93813e3f4d6SMark Murray close(net);
93913e3f4d6SMark Murray if (ourpty > 2) {
94013e3f4d6SMark Murray close(ourpty);
94113e3f4d6SMark Murray ourpty = -1;
94213e3f4d6SMark Murray }
94313e3f4d6SMark Murray }
94413e3f4d6SMark Murray
94513e3f4d6SMark Murray #ifndef O_NOCTTY
94613e3f4d6SMark Murray #define O_NOCTTY 0
94713e3f4d6SMark Murray #endif
94813e3f4d6SMark Murray /*
94913e3f4d6SMark Murray * Open the specified slave side of the pty,
950c19800e8SDoug Rabson * making sure that we have a clean tty.
951c19800e8SDoug Rabson */
952c19800e8SDoug Rabson
cleanopen(char * line)95313e3f4d6SMark Murray int cleanopen(char *line)
95413e3f4d6SMark Murray {
95513e3f4d6SMark Murray int t;
95613e3f4d6SMark Murray
95713e3f4d6SMark Murray if (ptyslavefd != -1)
95813e3f4d6SMark Murray return ptyslavefd;
95913e3f4d6SMark Murray
96013e3f4d6SMark Murray #ifdef STREAMSPTY
96113e3f4d6SMark Murray if (!really_stream)
96213e3f4d6SMark Murray #endif
96313e3f4d6SMark Murray {
96413e3f4d6SMark Murray /*
96513e3f4d6SMark Murray * Make sure that other people can't open the
96613e3f4d6SMark Murray * slave side of the connection.
96713e3f4d6SMark Murray */
96813e3f4d6SMark Murray chown(line, 0, 0);
96913e3f4d6SMark Murray chmod(line, 0600);
97013e3f4d6SMark Murray }
97113e3f4d6SMark Murray
97213e3f4d6SMark Murray #ifdef HAVE_REVOKE
97313e3f4d6SMark Murray revoke(line);
97413e3f4d6SMark Murray #endif
97513e3f4d6SMark Murray
97613e3f4d6SMark Murray t = open(line, O_RDWR|O_NOCTTY);
97713e3f4d6SMark Murray
97813e3f4d6SMark Murray if (t < 0)
97913e3f4d6SMark Murray return(-1);
98013e3f4d6SMark Murray
98113e3f4d6SMark Murray /*
98213e3f4d6SMark Murray * Hangup anybody else using this ttyp, then reopen it for
98313e3f4d6SMark Murray * ourselves.
98413e3f4d6SMark Murray */
98513e3f4d6SMark Murray # if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY)
98613e3f4d6SMark Murray signal(SIGHUP, SIG_IGN);
98713e3f4d6SMark Murray #ifdef HAVE_VHANGUP
98813e3f4d6SMark Murray vhangup();
98913e3f4d6SMark Murray #else
99013e3f4d6SMark Murray #endif
99113e3f4d6SMark Murray signal(SIGHUP, SIG_DFL);
99213e3f4d6SMark Murray t = open(line, O_RDWR|O_NOCTTY);
99313e3f4d6SMark Murray if (t < 0)
99413e3f4d6SMark Murray return(-1);
99513e3f4d6SMark Murray # endif
99613e3f4d6SMark Murray # if defined(_CRAY) && defined(TCVHUP)
99713e3f4d6SMark Murray {
99813e3f4d6SMark Murray int i;
99913e3f4d6SMark Murray signal(SIGHUP, SIG_IGN);
100013e3f4d6SMark Murray ioctl(t, TCVHUP, (char *)0);
100113e3f4d6SMark Murray signal(SIGHUP, SIG_DFL);
100213e3f4d6SMark Murray
100313e3f4d6SMark Murray i = open(line, O_RDWR);
100413e3f4d6SMark Murray
100513e3f4d6SMark Murray if (i < 0)
100613e3f4d6SMark Murray return(-1);
100713e3f4d6SMark Murray close(t);
100813e3f4d6SMark Murray t = i;
100913e3f4d6SMark Murray }
101013e3f4d6SMark Murray # endif /* defined(CRAY) && defined(TCVHUP) */
101113e3f4d6SMark Murray return(t);
101213e3f4d6SMark Murray }
101313e3f4d6SMark Murray
101413e3f4d6SMark Murray #if !defined(BSD4_4)
101513e3f4d6SMark Murray
login_tty(int t)101613e3f4d6SMark Murray int login_tty(int t)
101713e3f4d6SMark Murray {
101813e3f4d6SMark Murray /* Dont need to set this as the controlling PTY on steams sockets,
101913e3f4d6SMark Murray * don't abort on failure. */
102013e3f4d6SMark Murray # if defined(TIOCSCTTY) && !defined(__hpux)
102113e3f4d6SMark Murray if (ioctl(t, TIOCSCTTY, (char *)0) < 0 && !really_stream)
102213e3f4d6SMark Murray fatalperror(net, "ioctl(sctty)");
102313e3f4d6SMark Murray # ifdef _CRAY
102413e3f4d6SMark Murray /*
102513e3f4d6SMark Murray * Close the hard fd to /dev/ttypXXX, and re-open through
102613e3f4d6SMark Murray * the indirect /dev/tty interface.
102713e3f4d6SMark Murray */
102813e3f4d6SMark Murray close(t);
102913e3f4d6SMark Murray if ((t = open("/dev/tty", O_RDWR)) < 0)
103013e3f4d6SMark Murray fatalperror(net, "open(/dev/tty)");
103113e3f4d6SMark Murray # endif
103213e3f4d6SMark Murray # else
103313e3f4d6SMark Murray /*
103413e3f4d6SMark Murray * We get our controlling tty assigned as a side-effect
103513e3f4d6SMark Murray * of opening up a tty device. But on BSD based systems,
103613e3f4d6SMark Murray * this only happens if our process group is zero. The
103713e3f4d6SMark Murray * setsid() call above may have set our pgrp, so clear
103813e3f4d6SMark Murray * it out before opening the tty...
103913e3f4d6SMark Murray */
104013e3f4d6SMark Murray #ifdef HAVE_SETPGID
104113e3f4d6SMark Murray setpgid(0, 0);
104213e3f4d6SMark Murray #else
104313e3f4d6SMark Murray setpgrp(0, 0); /* if setpgid isn't available, setpgrp
104413e3f4d6SMark Murray probably takes arguments */
104513e3f4d6SMark Murray #endif
104613e3f4d6SMark Murray close(open(line, O_RDWR));
104713e3f4d6SMark Murray # endif
104813e3f4d6SMark Murray if (t != 0)
104913e3f4d6SMark Murray dup2(t, 0);
105013e3f4d6SMark Murray if (t != 1)
105113e3f4d6SMark Murray dup2(t, 1);
105213e3f4d6SMark Murray if (t != 2)
105313e3f4d6SMark Murray dup2(t, 2);
105413e3f4d6SMark Murray if (t > 2)
105513e3f4d6SMark Murray close(t);
105613e3f4d6SMark Murray return(0);
105713e3f4d6SMark Murray }
105813e3f4d6SMark Murray #endif /* BSD <= 43 */
1059c19800e8SDoug Rabson
1060c19800e8SDoug Rabson /*
106113e3f4d6SMark Murray * This comes from ../../bsd/tty.c and should not really be here.
106213e3f4d6SMark Murray */
106313e3f4d6SMark Murray
106413e3f4d6SMark Murray /*
106513e3f4d6SMark Murray * Clean the tty name. Return a pointer to the cleaned version.
106613e3f4d6SMark Murray */
106713e3f4d6SMark Murray
106813e3f4d6SMark Murray static char * clean_ttyname (char *) __attribute__((unused));
106913e3f4d6SMark Murray
107013e3f4d6SMark Murray static char *
clean_ttyname(char * tty)107113e3f4d6SMark Murray clean_ttyname (char *tty)
107213e3f4d6SMark Murray {
107313e3f4d6SMark Murray char *res = tty;
107413e3f4d6SMark Murray
107513e3f4d6SMark Murray if (strncmp (res, _PATH_DEV, strlen(_PATH_DEV)) == 0)
107613e3f4d6SMark Murray res += strlen(_PATH_DEV);
107713e3f4d6SMark Murray if (strncmp (res, "pty/", 4) == 0)
107813e3f4d6SMark Murray res += 4;
107913e3f4d6SMark Murray if (strncmp (res, "ptym/", 5) == 0)
108013e3f4d6SMark Murray res += 5;
108113e3f4d6SMark Murray return res;
108213e3f4d6SMark Murray }
108313e3f4d6SMark Murray
108413e3f4d6SMark Murray /*
108513e3f4d6SMark Murray * Generate a name usable as an `ut_id', typically without `tty'.
108613e3f4d6SMark Murray */
108713e3f4d6SMark Murray
108813e3f4d6SMark Murray #ifdef HAVE_STRUCT_UTMP_UT_ID
108913e3f4d6SMark Murray static char *
make_id(char * tty)109013e3f4d6SMark Murray make_id (char *tty)
109113e3f4d6SMark Murray {
109213e3f4d6SMark Murray char *res = tty;
109313e3f4d6SMark Murray
109413e3f4d6SMark Murray if (strncmp (res, "pts/", 4) == 0)
109513e3f4d6SMark Murray res += 4;
109613e3f4d6SMark Murray if (strncmp (res, "tty", 3) == 0)
109713e3f4d6SMark Murray res += 3;
109813e3f4d6SMark Murray return res;
109913e3f4d6SMark Murray }
110013e3f4d6SMark Murray #endif
110113e3f4d6SMark Murray
1102adb0ddaeSAssar Westerlund /*
1103adb0ddaeSAssar Westerlund * startslave(host)
110413e3f4d6SMark Murray *
110513e3f4d6SMark Murray * Given a hostname, do whatever
110613e3f4d6SMark Murray * is necessary to startup the login process on the slave side of the pty.
110713e3f4d6SMark Murray */
110813e3f4d6SMark Murray
110913e3f4d6SMark Murray /* ARGSUSED */
111013e3f4d6SMark Murray void
startslave(const char * host,const char * utmp_host,int autologin,char * autoname)111113e3f4d6SMark Murray startslave(const char *host, const char *utmp_host,
111213e3f4d6SMark Murray int autologin, char *autoname)
111313e3f4d6SMark Murray {
111413e3f4d6SMark Murray int i;
111513e3f4d6SMark Murray
111613e3f4d6SMark Murray #ifdef AUTHENTICATION
111713e3f4d6SMark Murray if (!autoname || !autoname[0])
111813e3f4d6SMark Murray autologin = 0;
111913e3f4d6SMark Murray
112013e3f4d6SMark Murray if (autologin < auth_level) {
112113e3f4d6SMark Murray fatal(net, "Authorization failed");
112213e3f4d6SMark Murray exit(1);
112313e3f4d6SMark Murray }
1124c19800e8SDoug Rabson #endif
112513e3f4d6SMark Murray
112613e3f4d6SMark Murray {
112713e3f4d6SMark Murray char *tbuf =
112813e3f4d6SMark Murray "\r\n*** Connection not encrypted! "
112913e3f4d6SMark Murray "Communication may be eavesdropped. ***\r\n";
113013e3f4d6SMark Murray #ifdef ENCRYPTION
113113e3f4d6SMark Murray if (!no_warn && (encrypt_output == 0 || decrypt_input == 0))
113213e3f4d6SMark Murray #endif
113313e3f4d6SMark Murray writenet(tbuf, strlen(tbuf));
113413e3f4d6SMark Murray }
113513e3f4d6SMark Murray # ifdef PARENT_DOES_UTMP
113613e3f4d6SMark Murray utmp_sig_init();
113713e3f4d6SMark Murray # endif /* PARENT_DOES_UTMP */
113813e3f4d6SMark Murray
113913e3f4d6SMark Murray if ((i = fork()) < 0)
114013e3f4d6SMark Murray fatalperror(net, "fork");
114113e3f4d6SMark Murray if (i) {
114213e3f4d6SMark Murray # ifdef PARENT_DOES_UTMP
114313e3f4d6SMark Murray /*
114413e3f4d6SMark Murray * Cray parent will create utmp entry for child and send
114513e3f4d6SMark Murray * signal to child to tell when done. Child waits for signal
114613e3f4d6SMark Murray * before doing anything important.
11475e9cd1aeSAssar Westerlund */
114813e3f4d6SMark Murray int pid = i;
114913e3f4d6SMark Murray void sigjob (int);
115013e3f4d6SMark Murray
1151adb0ddaeSAssar Westerlund setpgrp();
115213e3f4d6SMark Murray utmp_sig_reset(); /* reset handler to default */
115313e3f4d6SMark Murray /*
115413e3f4d6SMark Murray * Create utmp entry for child
115513e3f4d6SMark Murray */
115613e3f4d6SMark Murray wtmp.ut_time = time(NULL);
115713e3f4d6SMark Murray wtmp.ut_type = LOGIN_PROCESS;
115813e3f4d6SMark Murray wtmp.ut_pid = pid;
115913e3f4d6SMark Murray strncpy(wtmp.ut_user, "LOGIN", sizeof(wtmp.ut_user));
116013e3f4d6SMark Murray strncpy(wtmp.ut_host, utmp_host, sizeof(wtmp.ut_host));
116113e3f4d6SMark Murray strncpy(wtmp.ut_line, clean_ttyname(line), sizeof(wtmp.ut_line));
116213e3f4d6SMark Murray #ifdef HAVE_STRUCT_UTMP_UT_ID
116313e3f4d6SMark Murray strncpy(wtmp.ut_id, wtmp.ut_line + 3, sizeof(wtmp.ut_id));
116413e3f4d6SMark Murray #endif
116513e3f4d6SMark Murray
116613e3f4d6SMark Murray pututline(&wtmp);
116713e3f4d6SMark Murray endutent();
116813e3f4d6SMark Murray if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
116913e3f4d6SMark Murray write(i, &wtmp, sizeof(struct utmp));
11705e9cd1aeSAssar Westerlund close(i);
11715e9cd1aeSAssar Westerlund }
11725e9cd1aeSAssar Westerlund #ifdef _CRAY
11735e9cd1aeSAssar Westerlund signal(WJSIGNAL, sigjob);
117413e3f4d6SMark Murray #endif
117513e3f4d6SMark Murray utmp_sig_notify(pid);
117613e3f4d6SMark Murray # endif /* PARENT_DOES_UTMP */
117713e3f4d6SMark Murray } else {
117813e3f4d6SMark Murray getptyslave();
117913e3f4d6SMark Murray #if defined(DCE)
118013e3f4d6SMark Murray /* if we authenticated via K5, try and join the PAG */
118113e3f4d6SMark Murray kerberos5_dfspag();
118213e3f4d6SMark Murray #endif
118313e3f4d6SMark Murray start_login(host, autologin, autoname);
118413e3f4d6SMark Murray /*NOTREACHED*/
118513e3f4d6SMark Murray }
118613e3f4d6SMark Murray }
118713e3f4d6SMark Murray
118813e3f4d6SMark Murray char *envinit[3];
118913e3f4d6SMark Murray #if !HAVE_DECL_ENVIRON
119013e3f4d6SMark Murray extern char **environ;
119113e3f4d6SMark Murray #endif
119213e3f4d6SMark Murray
119313e3f4d6SMark Murray void
init_env(void)119413e3f4d6SMark Murray init_env(void)
119513e3f4d6SMark Murray {
119613e3f4d6SMark Murray char **envp;
119713e3f4d6SMark Murray
119813e3f4d6SMark Murray envp = envinit;
119913e3f4d6SMark Murray if ((*envp = getenv("TZ")))
120013e3f4d6SMark Murray *envp++ -= 3;
12015e9cd1aeSAssar Westerlund #if defined(_CRAY) || defined(__hpux)
120213e3f4d6SMark Murray else
120313e3f4d6SMark Murray *envp++ = "TZ=GMT0";
12045e9cd1aeSAssar Westerlund #endif
12055e9cd1aeSAssar Westerlund *envp = 0;
120613e3f4d6SMark Murray environ = envinit;
12075e9cd1aeSAssar Westerlund }
12085e9cd1aeSAssar Westerlund
12095e9cd1aeSAssar Westerlund /*
12105e9cd1aeSAssar Westerlund * scrub_env()
12115e9cd1aeSAssar Westerlund *
12125e9cd1aeSAssar Westerlund * We only accept the environment variables listed below.
12135e9cd1aeSAssar Westerlund */
12145e9cd1aeSAssar Westerlund
12155e9cd1aeSAssar Westerlund static void
scrub_env(void)12165e9cd1aeSAssar Westerlund scrub_env(void)
12175e9cd1aeSAssar Westerlund {
12185e9cd1aeSAssar Westerlund static const char *reject[] = {
12195e9cd1aeSAssar Westerlund "TERMCAP=/",
12205e9cd1aeSAssar Westerlund NULL
12215e9cd1aeSAssar Westerlund };
12225e9cd1aeSAssar Westerlund
122313e3f4d6SMark Murray static const char *accept[] = {
122413e3f4d6SMark Murray "XAUTH=", "XAUTHORITY=", "DISPLAY=",
12255e9cd1aeSAssar Westerlund "TERM=",
122613e3f4d6SMark Murray "EDITOR=",
122713e3f4d6SMark Murray "PAGER=",
12285e9cd1aeSAssar Westerlund "PRINTER=",
12295e9cd1aeSAssar Westerlund "LOGNAME=",
12305e9cd1aeSAssar Westerlund "POSIXLY_CORRECT=",
12315e9cd1aeSAssar Westerlund "TERMCAP=",
12325e9cd1aeSAssar Westerlund NULL
12335e9cd1aeSAssar Westerlund };
12345e9cd1aeSAssar Westerlund
12355e9cd1aeSAssar Westerlund char **cpp, **cpp2;
12365e9cd1aeSAssar Westerlund const char **p;
12375e9cd1aeSAssar Westerlund
12385e9cd1aeSAssar Westerlund for (cpp2 = cpp = environ; *cpp; cpp++) {
123913e3f4d6SMark Murray int reject_it = 0;
124013e3f4d6SMark Murray
12415e9cd1aeSAssar Westerlund for(p = reject; *p; p++)
124213e3f4d6SMark Murray if(strncmp(*cpp, *p, strlen(*p)) == 0) {
124313e3f4d6SMark Murray reject_it = 1;
12445e9cd1aeSAssar Westerlund break;
124513e3f4d6SMark Murray }
124613e3f4d6SMark Murray if (reject_it)
124713e3f4d6SMark Murray continue;
124813e3f4d6SMark Murray
124913e3f4d6SMark Murray for(p = accept; *p; p++)
125013e3f4d6SMark Murray if(strncmp(*cpp, *p, strlen(*p)) == 0)
1251c19800e8SDoug Rabson break;
125213e3f4d6SMark Murray if(*p != NULL)
125313e3f4d6SMark Murray *cpp2++ = *cpp;
1254adb0ddaeSAssar Westerlund }
125513e3f4d6SMark Murray *cpp2 = NULL;
125613e3f4d6SMark Murray }
125713e3f4d6SMark Murray
125813e3f4d6SMark Murray
125913e3f4d6SMark Murray struct arg_val {
126013e3f4d6SMark Murray int size;
126113e3f4d6SMark Murray int argc;
126213e3f4d6SMark Murray char **argv;
126313e3f4d6SMark Murray };
1264adb0ddaeSAssar Westerlund
126513e3f4d6SMark Murray static void addarg(struct arg_val*, const char*);
126613e3f4d6SMark Murray
126713e3f4d6SMark Murray /*
1268adb0ddaeSAssar Westerlund * start_login(host)
126913e3f4d6SMark Murray *
1270c19800e8SDoug Rabson * Assuming that we are now running as a child processes, this
1271c19800e8SDoug Rabson * function will turn us into the login process.
1272c19800e8SDoug Rabson */
1273c19800e8SDoug Rabson
1274c19800e8SDoug Rabson void
start_login(const char * host,int autologin,char * name)127513e3f4d6SMark Murray start_login(const char *host, int autologin, char *name)
1276c19800e8SDoug Rabson {
127713e3f4d6SMark Murray struct arg_val argv;
127813e3f4d6SMark Murray char *user;
1279c19800e8SDoug Rabson int save_errno;
128013e3f4d6SMark Murray
128113e3f4d6SMark Murray #ifdef ENCRYPTION
128213e3f4d6SMark Murray encrypt_output = NULL;
128313e3f4d6SMark Murray decrypt_input = NULL;
128413e3f4d6SMark Murray #endif
128513e3f4d6SMark Murray
128613e3f4d6SMark Murray #ifdef HAVE_UTMPX_H
128713e3f4d6SMark Murray {
128813e3f4d6SMark Murray int pid = getpid();
128913e3f4d6SMark Murray struct utmpx utmpx;
129013e3f4d6SMark Murray struct timeval tv;
129113e3f4d6SMark Murray char *clean_tty;
129213e3f4d6SMark Murray
129313e3f4d6SMark Murray /*
129413e3f4d6SMark Murray * Create utmp entry for child
129513e3f4d6SMark Murray */
129613e3f4d6SMark Murray
1297c19800e8SDoug Rabson clean_tty = clean_ttyname(line);
1298c19800e8SDoug Rabson memset(&utmpx, 0, sizeof(utmpx));
1299c19800e8SDoug Rabson strncpy(utmpx.ut_user, ".telnet", sizeof(utmpx.ut_user));
1300c19800e8SDoug Rabson strncpy(utmpx.ut_line, clean_tty, sizeof(utmpx.ut_line));
130113e3f4d6SMark Murray #ifdef HAVE_STRUCT_UTMP_UT_ID
130213e3f4d6SMark Murray strncpy(utmpx.ut_id, make_id(clean_tty), sizeof(utmpx.ut_id));
1303c19800e8SDoug Rabson #endif
130413e3f4d6SMark Murray utmpx.ut_pid = pid;
130513e3f4d6SMark Murray
130613e3f4d6SMark Murray utmpx.ut_type = LOGIN_PROCESS;
130713e3f4d6SMark Murray
130813e3f4d6SMark Murray gettimeofday (&tv, NULL);
130913e3f4d6SMark Murray utmpx.ut_tv.tv_sec = tv.tv_sec;
131013e3f4d6SMark Murray utmpx.ut_tv.tv_usec = tv.tv_usec;
131113e3f4d6SMark Murray
131213e3f4d6SMark Murray if (pututxline(&utmpx) == NULL)
131313e3f4d6SMark Murray fatal(net, "pututxline failed");
131413e3f4d6SMark Murray }
131513e3f4d6SMark Murray #endif
131613e3f4d6SMark Murray
131713e3f4d6SMark Murray scrub_env();
131813e3f4d6SMark Murray
131913e3f4d6SMark Murray /*
1320adb0ddaeSAssar Westerlund * -h : pass on name of host.
132113e3f4d6SMark Murray * WARNING: -h is accepted by login if and only if
132213e3f4d6SMark Murray * getuid() == 0.
132313e3f4d6SMark Murray * -p : don't clobber the environment (so terminal type stays set).
132413e3f4d6SMark Murray *
132513e3f4d6SMark Murray * -f : force this login, he has already been authenticated
132613e3f4d6SMark Murray */
132713e3f4d6SMark Murray
132813e3f4d6SMark Murray /* init argv structure */
132913e3f4d6SMark Murray argv.size=0;
133013e3f4d6SMark Murray argv.argc=0;
133113e3f4d6SMark Murray argv.argv=malloc(0); /*so we can call realloc later */
133213e3f4d6SMark Murray addarg(&argv, "login");
133313e3f4d6SMark Murray addarg(&argv, "-h");
133413e3f4d6SMark Murray addarg(&argv, host);
133513e3f4d6SMark Murray addarg(&argv, "-p");
133613e3f4d6SMark Murray if(name && name[0])
133713e3f4d6SMark Murray user = name;
133813e3f4d6SMark Murray else
133913e3f4d6SMark Murray user = getenv("USER");
134013e3f4d6SMark Murray #ifdef AUTHENTICATION
134113e3f4d6SMark Murray if (auth_level < 0 || autologin != AUTH_VALID) {
134213e3f4d6SMark Murray if(!no_warn) {
134313e3f4d6SMark Murray printf("User not authenticated. ");
134413e3f4d6SMark Murray if (require_otp)
134513e3f4d6SMark Murray printf("Using one-time password\r\n");
134613e3f4d6SMark Murray else
134713e3f4d6SMark Murray printf("Using plaintext username and password\r\n");
134813e3f4d6SMark Murray }
134913e3f4d6SMark Murray if (require_otp) {
135013e3f4d6SMark Murray addarg(&argv, "-a");
135113e3f4d6SMark Murray addarg(&argv, "otp");
135213e3f4d6SMark Murray }
135313e3f4d6SMark Murray if(log_unauth)
135413e3f4d6SMark Murray syslog(LOG_INFO, "unauthenticated access from %s (%s)",
135513e3f4d6SMark Murray host, user ? user : "unknown user");
135613e3f4d6SMark Murray }
135713e3f4d6SMark Murray if (auth_level >= 0 && autologin == AUTH_VALID)
135813e3f4d6SMark Murray addarg(&argv, "-f");
135913e3f4d6SMark Murray #endif
136013e3f4d6SMark Murray if(user){
136113e3f4d6SMark Murray addarg(&argv, "--");
136213e3f4d6SMark Murray addarg(&argv, strdup(user));
136313e3f4d6SMark Murray }
136413e3f4d6SMark Murray if (getenv("USER")) {
136513e3f4d6SMark Murray /*
136613e3f4d6SMark Murray * Assume that login will set the USER variable
136713e3f4d6SMark Murray * correctly. For SysV systems, this means that
136813e3f4d6SMark Murray * USER will no longer be set, just LOGNAME by
136913e3f4d6SMark Murray * login. (The problem is that if the auto-login
137013e3f4d6SMark Murray * fails, and the user then specifies a different
137113e3f4d6SMark Murray * account name, he can get logged in with both
137213e3f4d6SMark Murray * LOGNAME and USER in his environment, but the
137313e3f4d6SMark Murray * USER value will be wrong.
137413e3f4d6SMark Murray */
1375adb0ddaeSAssar Westerlund unsetenv("USER");
1376c19800e8SDoug Rabson }
1377adb0ddaeSAssar Westerlund closelog();
137813e3f4d6SMark Murray /*
137913e3f4d6SMark Murray * This sleep(1) is in here so that telnetd can
138013e3f4d6SMark Murray * finish up with the tty. There's a race condition
138113e3f4d6SMark Murray * the login banner message gets lost...
1382adb0ddaeSAssar Westerlund */
138313e3f4d6SMark Murray sleep(1);
138413e3f4d6SMark Murray
138513e3f4d6SMark Murray execv(new_login, argv.argv);
138613e3f4d6SMark Murray save_errno = errno;
138713e3f4d6SMark Murray syslog(LOG_ERR, "%s: %m", new_login);
138813e3f4d6SMark Murray fatalperror_errno(net, new_login, save_errno);
138913e3f4d6SMark Murray /*NOTREACHED*/
1390c19800e8SDoug Rabson }
1391c19800e8SDoug Rabson
139213e3f4d6SMark Murray static void
addarg(struct arg_val * argv,const char * val)139313e3f4d6SMark Murray addarg(struct arg_val *argv, const char *val)
139413e3f4d6SMark Murray {
139513e3f4d6SMark Murray if(argv->size <= argv->argc+1) {
139613e3f4d6SMark Murray argv->argv = realloc(argv->argv, sizeof(char*) * (argv->size + 10));
139713e3f4d6SMark Murray if (argv->argv == NULL)
139813e3f4d6SMark Murray fatal (net, "realloc: out of memory");
139913e3f4d6SMark Murray argv->size+=10;
140013e3f4d6SMark Murray }
140113e3f4d6SMark Murray if((argv->argv[argv->argc++] = strdup(val)) == NULL)
140213e3f4d6SMark Murray fatal (net, "strdup: out of memory");
140313e3f4d6SMark Murray argv->argv[argv->argc] = NULL;
140413e3f4d6SMark Murray }
140513e3f4d6SMark Murray
140613e3f4d6SMark Murray
140713e3f4d6SMark Murray /*
140813e3f4d6SMark Murray * rmut()
140913e3f4d6SMark Murray *
141013e3f4d6SMark Murray * This is the function called by cleanup() to
141113e3f4d6SMark Murray * remove the utmp entry for this person.
141213e3f4d6SMark Murray */
141313e3f4d6SMark Murray
141413e3f4d6SMark Murray #ifdef HAVE_UTMPX_H
141513e3f4d6SMark Murray static void
rmut(void)141613e3f4d6SMark Murray rmut(void)
141713e3f4d6SMark Murray {
141813e3f4d6SMark Murray struct utmpx utmpx, *non_save_utxp;
141913e3f4d6SMark Murray char *clean_tty = clean_ttyname(line);
142013e3f4d6SMark Murray
1421c19800e8SDoug Rabson /*
142213e3f4d6SMark Murray * This updates the utmpx and utmp entries and make a wtmp/x entry
142313e3f4d6SMark Murray */
142413e3f4d6SMark Murray
142513e3f4d6SMark Murray setutxent();
142613e3f4d6SMark Murray memset(&utmpx, 0, sizeof(utmpx));
142713e3f4d6SMark Murray strncpy(utmpx.ut_line, clean_tty, sizeof(utmpx.ut_line));
142813e3f4d6SMark Murray utmpx.ut_type = LOGIN_PROCESS;
142913e3f4d6SMark Murray non_save_utxp = getutxline(&utmpx);
143013e3f4d6SMark Murray if (non_save_utxp) {
143113e3f4d6SMark Murray struct utmpx *utxp;
143213e3f4d6SMark Murray struct timeval tv;
143313e3f4d6SMark Murray char user0;
143413e3f4d6SMark Murray
143513e3f4d6SMark Murray utxp = malloc(sizeof(struct utmpx));
143613e3f4d6SMark Murray *utxp = *non_save_utxp;
143713e3f4d6SMark Murray user0 = utxp->ut_user[0];
143813e3f4d6SMark Murray utxp->ut_user[0] = '\0';
143913e3f4d6SMark Murray utxp->ut_type = DEAD_PROCESS;
144013e3f4d6SMark Murray #ifdef HAVE_STRUCT_UTMPX_UT_EXIT
1441c19800e8SDoug Rabson #ifdef _STRUCT___EXIT_STATUS
1442c19800e8SDoug Rabson utxp->ut_exit.__e_termination = 0;
1443c19800e8SDoug Rabson utxp->ut_exit.__e_exit = 0;
1444c19800e8SDoug Rabson #elif defined(__osf__) /* XXX */
144513e3f4d6SMark Murray utxp->ut_exit.ut_termination = 0;
144613e3f4d6SMark Murray utxp->ut_exit.ut_exit = 0;
144713e3f4d6SMark Murray #else
144813e3f4d6SMark Murray utxp->ut_exit.e_termination = 0;
144913e3f4d6SMark Murray utxp->ut_exit.e_exit = 0;
145013e3f4d6SMark Murray #endif
145113e3f4d6SMark Murray #endif
145213e3f4d6SMark Murray gettimeofday (&tv, NULL);
145313e3f4d6SMark Murray utxp->ut_tv.tv_sec = tv.tv_sec;
145413e3f4d6SMark Murray utxp->ut_tv.tv_usec = tv.tv_usec;
145513e3f4d6SMark Murray
145613e3f4d6SMark Murray pututxline(utxp);
145713e3f4d6SMark Murray #ifdef WTMPX_FILE
145813e3f4d6SMark Murray utxp->ut_user[0] = user0;
145913e3f4d6SMark Murray updwtmpx(WTMPX_FILE, utxp);
14605e9cd1aeSAssar Westerlund #elif defined(WTMP_FILE)
146113e3f4d6SMark Murray /* This is a strange system with a utmpx and a wtmp! */
146213e3f4d6SMark Murray {
146313e3f4d6SMark Murray int f = open(wtmpf, O_WRONLY|O_APPEND);
146413e3f4d6SMark Murray struct utmp wtmp;
146513e3f4d6SMark Murray if (f >= 0) {
146613e3f4d6SMark Murray strncpy(wtmp.ut_line, clean_tty, sizeof(wtmp.ut_line));
146713e3f4d6SMark Murray strncpy(wtmp.ut_name, "", sizeof(wtmp.ut_name));
146813e3f4d6SMark Murray #ifdef HAVE_STRUCT_UTMP_UT_HOST
146913e3f4d6SMark Murray strncpy(wtmp.ut_host, "", sizeof(wtmp.ut_host));
147013e3f4d6SMark Murray #endif
147113e3f4d6SMark Murray wtmp.ut_time = time(NULL);
147213e3f4d6SMark Murray write(f, &wtmp, sizeof(wtmp));
147313e3f4d6SMark Murray close(f);
147413e3f4d6SMark Murray }
147513e3f4d6SMark Murray }
147613e3f4d6SMark Murray #endif
147713e3f4d6SMark Murray free (utxp);
147813e3f4d6SMark Murray }
147913e3f4d6SMark Murray endutxent();
148013e3f4d6SMark Murray } /* end of rmut */
148113e3f4d6SMark Murray #endif
148213e3f4d6SMark Murray
148313e3f4d6SMark Murray #if !defined(HAVE_UTMPX_H) && !(defined(_CRAY) || defined(__hpux)) && BSD <= 43
148413e3f4d6SMark Murray static void
rmut(void)148513e3f4d6SMark Murray rmut(void)
148613e3f4d6SMark Murray {
148713e3f4d6SMark Murray int f;
148813e3f4d6SMark Murray int found = 0;
148913e3f4d6SMark Murray struct utmp *u, *utmp;
149013e3f4d6SMark Murray int nutmp;
149113e3f4d6SMark Murray struct stat statbf;
149213e3f4d6SMark Murray char *clean_tty = clean_ttyname(line);
149313e3f4d6SMark Murray
149413e3f4d6SMark Murray f = open(utmpf, O_RDWR);
149513e3f4d6SMark Murray if (f >= 0) {
149613e3f4d6SMark Murray fstat(f, &statbf);
149713e3f4d6SMark Murray utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
149813e3f4d6SMark Murray if (!utmp)
149913e3f4d6SMark Murray syslog(LOG_ERR, "utmp malloc failed");
150013e3f4d6SMark Murray if (statbf.st_size && utmp) {
150113e3f4d6SMark Murray nutmp = read(f, utmp, (int)statbf.st_size);
150213e3f4d6SMark Murray nutmp /= sizeof(struct utmp);
150313e3f4d6SMark Murray
15045e9cd1aeSAssar Westerlund for (u = utmp ; u < &utmp[nutmp] ; u++) {
150513e3f4d6SMark Murray if (strncmp(u->ut_line,
150613e3f4d6SMark Murray clean_tty,
150713e3f4d6SMark Murray sizeof(u->ut_line)) ||
150813e3f4d6SMark Murray u->ut_name[0]==0)
150913e3f4d6SMark Murray continue;
151013e3f4d6SMark Murray lseek(f, ((long)u)-((long)utmp), L_SET);
151113e3f4d6SMark Murray strncpy(u->ut_name, "", sizeof(u->ut_name));
151213e3f4d6SMark Murray #ifdef HAVE_STRUCT_UTMP_UT_HOST
151313e3f4d6SMark Murray strncpy(u->ut_host, "", sizeof(u->ut_host));
151413e3f4d6SMark Murray #endif
151513e3f4d6SMark Murray u->ut_time = time(NULL);
151613e3f4d6SMark Murray write(f, u, sizeof(wtmp));
151713e3f4d6SMark Murray found++;
151813e3f4d6SMark Murray }
15195e9cd1aeSAssar Westerlund }
152013e3f4d6SMark Murray close(f);
152113e3f4d6SMark Murray }
152213e3f4d6SMark Murray if (found) {
152313e3f4d6SMark Murray f = open(wtmpf, O_WRONLY|O_APPEND);
152413e3f4d6SMark Murray if (f >= 0) {
152513e3f4d6SMark Murray strncpy(wtmp.ut_line, clean_tty, sizeof(wtmp.ut_line));
152613e3f4d6SMark Murray strncpy(wtmp.ut_name, "", sizeof(wtmp.ut_name));
152713e3f4d6SMark Murray #ifdef HAVE_STRUCT_UTMP_UT_HOST
152813e3f4d6SMark Murray strncpy(wtmp.ut_host, "", sizeof(wtmp.ut_host));
152913e3f4d6SMark Murray #endif
153013e3f4d6SMark Murray wtmp.ut_time = time(NULL);
153113e3f4d6SMark Murray write(f, &wtmp, sizeof(wtmp));
153213e3f4d6SMark Murray close(f);
153313e3f4d6SMark Murray }
153413e3f4d6SMark Murray }
153513e3f4d6SMark Murray chmod(line, 0666);
153613e3f4d6SMark Murray chown(line, 0, 0);
153713e3f4d6SMark Murray line[strlen("/dev/")] = 'p';
153813e3f4d6SMark Murray chmod(line, 0666);
153913e3f4d6SMark Murray chown(line, 0, 0);
154013e3f4d6SMark Murray } /* end of rmut */
154113e3f4d6SMark Murray #endif /* CRAY */
154213e3f4d6SMark Murray
154313e3f4d6SMark Murray #if defined(__hpux) && !defined(HAVE_UTMPX_H)
154413e3f4d6SMark Murray static void
rmut(char * line)154513e3f4d6SMark Murray rmut (char *line)
154613e3f4d6SMark Murray {
154713e3f4d6SMark Murray struct utmp utmp;
154813e3f4d6SMark Murray struct utmp *utptr;
154913e3f4d6SMark Murray int fd; /* for /etc/wtmp */
155013e3f4d6SMark Murray
155113e3f4d6SMark Murray utmp.ut_type = USER_PROCESS;
155213e3f4d6SMark Murray strncpy(utmp.ut_line, clean_ttyname(line), sizeof(utmp.ut_line));
155313e3f4d6SMark Murray setutent();
155413e3f4d6SMark Murray utptr = getutline(&utmp);
155513e3f4d6SMark Murray /* write it out only if it exists */
155613e3f4d6SMark Murray if (utptr) {
155713e3f4d6SMark Murray utptr->ut_type = DEAD_PROCESS;
155813e3f4d6SMark Murray utptr->ut_time = time(NULL);
155913e3f4d6SMark Murray pututline(utptr);
156013e3f4d6SMark Murray /* set wtmp entry if wtmp file exists */
156113e3f4d6SMark Murray if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) {
156213e3f4d6SMark Murray write(fd, utptr, sizeof(utmp));
156313e3f4d6SMark Murray close(fd);
156413e3f4d6SMark Murray }
156513e3f4d6SMark Murray }
156613e3f4d6SMark Murray endutent();
156713e3f4d6SMark Murray
156813e3f4d6SMark Murray chmod(line, 0666);
156913e3f4d6SMark Murray chown(line, 0, 0);
157013e3f4d6SMark Murray line[14] = line[13];
157113e3f4d6SMark Murray line[13] = line[12];
157213e3f4d6SMark Murray line[8] = 'm';
157313e3f4d6SMark Murray line[9] = '/';
157413e3f4d6SMark Murray line[10] = 'p';
157513e3f4d6SMark Murray line[11] = 't';
157613e3f4d6SMark Murray line[12] = 'y';
157713e3f4d6SMark Murray chmod(line, 0666);
157813e3f4d6SMark Murray chown(line, 0, 0);
157913e3f4d6SMark Murray }
158013e3f4d6SMark Murray #endif
158113e3f4d6SMark Murray
158213e3f4d6SMark Murray /*
158313e3f4d6SMark Murray * cleanup()
158413e3f4d6SMark Murray *
158513e3f4d6SMark Murray * This is the routine to call when we are all through, to
158613e3f4d6SMark Murray * clean up anything that needs to be cleaned up.
158713e3f4d6SMark Murray */
158813e3f4d6SMark Murray
158913e3f4d6SMark Murray #ifdef PARENT_DOES_UTMP
159013e3f4d6SMark Murray
159113e3f4d6SMark Murray void
cleanup(int sig)159213e3f4d6SMark Murray cleanup(int sig)
159313e3f4d6SMark Murray {
159413e3f4d6SMark Murray #ifdef _CRAY
159513e3f4d6SMark Murray static int incleanup = 0;
159613e3f4d6SMark Murray int t;
159713e3f4d6SMark Murray int child_status; /* status of child process as returned by waitpid */
159813e3f4d6SMark Murray int flags = WNOHANG|WUNTRACED;
159913e3f4d6SMark Murray
160013e3f4d6SMark Murray /*
160113e3f4d6SMark Murray * 1: Pick up the zombie, if we are being called
160213e3f4d6SMark Murray * as the signal handler.
160313e3f4d6SMark Murray * 2: If we are a nested cleanup(), return.
160413e3f4d6SMark Murray * 3: Try to clean up TMPDIR.
160513e3f4d6SMark Murray * 4: Fill in utmp with shutdown of process.
160613e3f4d6SMark Murray * 5: Close down the network and pty connections.
160713e3f4d6SMark Murray * 6: Finish up the TMPDIR cleanup, if needed.
160813e3f4d6SMark Murray */
160913e3f4d6SMark Murray if (sig == SIGCHLD) {
161013e3f4d6SMark Murray while (waitpid(-1, &child_status, flags) > 0)
161113e3f4d6SMark Murray ; /* VOID */
161213e3f4d6SMark Murray /* Check if the child process was stopped
161313e3f4d6SMark Murray * rather than exited. We want cleanup only if
161413e3f4d6SMark Murray * the child has died.
161513e3f4d6SMark Murray */
161613e3f4d6SMark Murray if (WIFSTOPPED(child_status)) {
161713e3f4d6SMark Murray return;
161813e3f4d6SMark Murray }
161913e3f4d6SMark Murray }
162013e3f4d6SMark Murray t = sigblock(sigmask(SIGCHLD));
162113e3f4d6SMark Murray if (incleanup) {
162213e3f4d6SMark Murray sigsetmask(t);
162313e3f4d6SMark Murray return;
162413e3f4d6SMark Murray }
162513e3f4d6SMark Murray incleanup = 1;
162613e3f4d6SMark Murray sigsetmask(t);
162713e3f4d6SMark Murray
162813e3f4d6SMark Murray t = cleantmp(&wtmp);
162913e3f4d6SMark Murray setutent(); /* just to make sure */
163013e3f4d6SMark Murray #endif /* CRAY */
163113e3f4d6SMark Murray rmut(line);
163213e3f4d6SMark Murray close(ourpty);
163313e3f4d6SMark Murray shutdown(net, 2);
163413e3f4d6SMark Murray #ifdef _CRAY
163513e3f4d6SMark Murray if (t == 0)
163613e3f4d6SMark Murray cleantmp(&wtmp);
163713e3f4d6SMark Murray #endif /* CRAY */
163813e3f4d6SMark Murray exit(1);
163913e3f4d6SMark Murray }
164013e3f4d6SMark Murray
164113e3f4d6SMark Murray #else /* PARENT_DOES_UTMP */
164213e3f4d6SMark Murray
164313e3f4d6SMark Murray void
cleanup(int sig)164413e3f4d6SMark Murray cleanup(int sig)
164513e3f4d6SMark Murray {
164613e3f4d6SMark Murray #if defined(HAVE_UTMPX_H) || !defined(HAVE_LOGWTMP)
164713e3f4d6SMark Murray rmut();
164813e3f4d6SMark Murray #ifdef HAVE_VHANGUP
164913e3f4d6SMark Murray #ifndef __sgi
165013e3f4d6SMark Murray vhangup(); /* XXX */
165113e3f4d6SMark Murray #endif
165213e3f4d6SMark Murray #endif
165313e3f4d6SMark Murray #else
165413e3f4d6SMark Murray char *p;
165513e3f4d6SMark Murray
165613e3f4d6SMark Murray p = line + sizeof("/dev/") - 1;
165713e3f4d6SMark Murray if (logout(p))
165813e3f4d6SMark Murray logwtmp(p, "", "");
165913e3f4d6SMark Murray chmod(line, 0666);
166013e3f4d6SMark Murray chown(line, 0, 0);
166113e3f4d6SMark Murray *p = 'p';
166213e3f4d6SMark Murray chmod(line, 0666);
166313e3f4d6SMark Murray chown(line, 0, 0);
166413e3f4d6SMark Murray #endif
166513e3f4d6SMark Murray shutdown(net, 2);
166613e3f4d6SMark Murray exit(1);
166713e3f4d6SMark Murray }
166813e3f4d6SMark Murray
166913e3f4d6SMark Murray #endif /* PARENT_DOES_UTMP */
167013e3f4d6SMark Murray
167113e3f4d6SMark Murray #ifdef PARENT_DOES_UTMP
167213e3f4d6SMark Murray /*
167313e3f4d6SMark Murray * _utmp_sig_rcv
167413e3f4d6SMark Murray * utmp_sig_init
167513e3f4d6SMark Murray * utmp_sig_wait
167613e3f4d6SMark Murray * These three functions are used to coordinate the handling of
167713e3f4d6SMark Murray * the utmp file between the server and the soon-to-be-login shell.
167813e3f4d6SMark Murray * The server actually creates the utmp structure, the child calls
167913e3f4d6SMark Murray * utmp_sig_wait(), until the server calls utmp_sig_notify() and
168013e3f4d6SMark Murray * signals the future-login shell to proceed.
168113e3f4d6SMark Murray */
168213e3f4d6SMark Murray static int caught=0; /* NZ when signal intercepted */
168313e3f4d6SMark Murray static void (*func)(); /* address of previous handler */
168413e3f4d6SMark Murray
168513e3f4d6SMark Murray void
_utmp_sig_rcv(sig)168613e3f4d6SMark Murray _utmp_sig_rcv(sig)
168713e3f4d6SMark Murray int sig;
168813e3f4d6SMark Murray {
168913e3f4d6SMark Murray caught = 1;
169013e3f4d6SMark Murray signal(SIGUSR1, func);
169113e3f4d6SMark Murray }
169213e3f4d6SMark Murray
169313e3f4d6SMark Murray void
utmp_sig_init()169413e3f4d6SMark Murray utmp_sig_init()
169513e3f4d6SMark Murray {
169613e3f4d6SMark Murray /*
169713e3f4d6SMark Murray * register signal handler for UTMP creation
169813e3f4d6SMark Murray */
169913e3f4d6SMark Murray if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
170013e3f4d6SMark Murray fatalperror(net, "telnetd/signal");
170113e3f4d6SMark Murray }
170213e3f4d6SMark Murray
170313e3f4d6SMark Murray void
utmp_sig_reset()170413e3f4d6SMark Murray utmp_sig_reset()
170513e3f4d6SMark Murray {
170613e3f4d6SMark Murray signal(SIGUSR1, func); /* reset handler to default */
170713e3f4d6SMark Murray }
170813e3f4d6SMark Murray
170913e3f4d6SMark Murray # ifdef __hpux
171013e3f4d6SMark Murray # define sigoff() /* do nothing */
171113e3f4d6SMark Murray # define sigon() /* do nothing */
171213e3f4d6SMark Murray # endif
171313e3f4d6SMark Murray
171413e3f4d6SMark Murray void
utmp_sig_wait()171513e3f4d6SMark Murray utmp_sig_wait()
171613e3f4d6SMark Murray {
171713e3f4d6SMark Murray /*
171813e3f4d6SMark Murray * Wait for parent to write our utmp entry.
171913e3f4d6SMark Murray */
172013e3f4d6SMark Murray sigoff();
172113e3f4d6SMark Murray while (caught == 0) {
172213e3f4d6SMark Murray pause(); /* wait until we get a signal (sigon) */
172313e3f4d6SMark Murray sigoff(); /* turn off signals while we check caught */
172413e3f4d6SMark Murray }
172513e3f4d6SMark Murray sigon(); /* turn on signals again */
172613e3f4d6SMark Murray }
172713e3f4d6SMark Murray
172813e3f4d6SMark Murray void
utmp_sig_notify(pid)172913e3f4d6SMark Murray utmp_sig_notify(pid)
173013e3f4d6SMark Murray {
173113e3f4d6SMark Murray kill(pid, SIGUSR1);
173213e3f4d6SMark Murray }
173313e3f4d6SMark Murray
173413e3f4d6SMark Murray #ifdef _CRAY
173513e3f4d6SMark Murray static int gotsigjob = 0;
173613e3f4d6SMark Murray
173713e3f4d6SMark Murray /*ARGSUSED*/
173813e3f4d6SMark Murray void
sigjob(sig)173913e3f4d6SMark Murray sigjob(sig)
174013e3f4d6SMark Murray int sig;
174113e3f4d6SMark Murray {
174213e3f4d6SMark Murray int jid;
174313e3f4d6SMark Murray struct jobtemp *jp;
174413e3f4d6SMark Murray
174513e3f4d6SMark Murray while ((jid = waitjob(NULL)) != -1) {
174613e3f4d6SMark Murray if (jid == 0) {
174713e3f4d6SMark Murray return;
174813e3f4d6SMark Murray }
174913e3f4d6SMark Murray gotsigjob++;
175013e3f4d6SMark Murray jobend(jid, NULL, NULL);
175113e3f4d6SMark Murray }
175213e3f4d6SMark Murray }
175313e3f4d6SMark Murray
175413e3f4d6SMark Murray /*
175513e3f4d6SMark Murray * jid_getutid:
175613e3f4d6SMark Murray * called by jobend() before calling cleantmp()
175713e3f4d6SMark Murray * to find the correct $TMPDIR to cleanup.
175813e3f4d6SMark Murray */
175913e3f4d6SMark Murray
176013e3f4d6SMark Murray struct utmp *
jid_getutid(jid)176113e3f4d6SMark Murray jid_getutid(jid)
176213e3f4d6SMark Murray int jid;
176313e3f4d6SMark Murray {
176413e3f4d6SMark Murray struct utmp *cur = NULL;
176513e3f4d6SMark Murray
176613e3f4d6SMark Murray setutent(); /* just to make sure */
176713e3f4d6SMark Murray while (cur = getutent()) {
176813e3f4d6SMark Murray if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) {
176913e3f4d6SMark Murray return(cur);
177013e3f4d6SMark Murray }
177113e3f4d6SMark Murray }
177213e3f4d6SMark Murray
177313e3f4d6SMark Murray return(0);
177413e3f4d6SMark Murray }
177513e3f4d6SMark Murray
177613e3f4d6SMark Murray /*
177713e3f4d6SMark Murray * Clean up the TMPDIR that login created.
177813e3f4d6SMark Murray * The first time this is called we pick up the info
177913e3f4d6SMark Murray * from the utmp. If the job has already gone away,
178013e3f4d6SMark Murray * then we'll clean up and be done. If not, then
178113e3f4d6SMark Murray * when this is called the second time it will wait
178213e3f4d6SMark Murray * for the signal that the job is done.
178313e3f4d6SMark Murray */
178413e3f4d6SMark Murray int
cleantmp(wtp)178513e3f4d6SMark Murray cleantmp(wtp)
178613e3f4d6SMark Murray struct utmp *wtp;
178713e3f4d6SMark Murray {
178813e3f4d6SMark Murray struct utmp *utp;
178913e3f4d6SMark Murray static int first = 1;
179013e3f4d6SMark Murray int mask, omask, ret;
179113e3f4d6SMark Murray extern struct utmp *getutid (const struct utmp *_Id);
179213e3f4d6SMark Murray
179313e3f4d6SMark Murray
179413e3f4d6SMark Murray mask = sigmask(WJSIGNAL);
179513e3f4d6SMark Murray
179613e3f4d6SMark Murray if (first == 0) {
179713e3f4d6SMark Murray omask = sigblock(mask);
179813e3f4d6SMark Murray while (gotsigjob == 0)
179913e3f4d6SMark Murray sigpause(omask);
180013e3f4d6SMark Murray return(1);
180113e3f4d6SMark Murray }
180213e3f4d6SMark Murray first = 0;
180313e3f4d6SMark Murray setutent(); /* just to make sure */
180413e3f4d6SMark Murray
180513e3f4d6SMark Murray utp = getutid(wtp);
180613e3f4d6SMark Murray if (utp == 0) {
180713e3f4d6SMark Murray syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
180813e3f4d6SMark Murray return(-1);
180913e3f4d6SMark Murray }
181013e3f4d6SMark Murray /*
181113e3f4d6SMark Murray * Nothing to clean up if the user shell was never started.
181213e3f4d6SMark Murray */
181313e3f4d6SMark Murray if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0)
181413e3f4d6SMark Murray return(1);
181513e3f4d6SMark Murray
181613e3f4d6SMark Murray /*
181713e3f4d6SMark Murray * Block the WJSIGNAL while we are in jobend().
181813e3f4d6SMark Murray */
181913e3f4d6SMark Murray omask = sigblock(mask);
182013e3f4d6SMark Murray ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user);
182113e3f4d6SMark Murray sigsetmask(omask);
182213e3f4d6SMark Murray return(ret);
182313e3f4d6SMark Murray }
182413e3f4d6SMark Murray
182513e3f4d6SMark Murray int
jobend(jid,path,user)182613e3f4d6SMark Murray jobend(jid, path, user)
182713e3f4d6SMark Murray int jid;
182813e3f4d6SMark Murray char *path;
182913e3f4d6SMark Murray char *user;
183013e3f4d6SMark Murray {
183113e3f4d6SMark Murray static int saved_jid = 0;
183213e3f4d6SMark Murray static int pty_saved_jid = 0;
183313e3f4d6SMark Murray static char saved_path[sizeof(wtmp.ut_tpath)+1];
183413e3f4d6SMark Murray static char saved_user[sizeof(wtmp.ut_user)+1];
183513e3f4d6SMark Murray
183613e3f4d6SMark Murray /*
183713e3f4d6SMark Murray * this little piece of code comes into play
183813e3f4d6SMark Murray * only when ptyreconnect is used to reconnect
183913e3f4d6SMark Murray * to an previous session.
184013e3f4d6SMark Murray *
184113e3f4d6SMark Murray * this is the only time when the
184213e3f4d6SMark Murray * "saved_jid != jid" code is executed.
1843c19800e8SDoug Rabson */
1844c19800e8SDoug Rabson
184513e3f4d6SMark Murray if ( saved_jid && saved_jid != jid ) {
184613e3f4d6SMark Murray if (!path) { /* called from signal handler */
184713e3f4d6SMark Murray pty_saved_jid = jid;
184813e3f4d6SMark Murray } else {
184913e3f4d6SMark Murray pty_saved_jid = saved_jid;
185013e3f4d6SMark Murray }
185113e3f4d6SMark Murray }
185213e3f4d6SMark Murray
185313e3f4d6SMark Murray if (path) {
185413e3f4d6SMark Murray strlcpy(saved_path, path, sizeof(saved_path));
185513e3f4d6SMark Murray strlcpy(saved_user, user, sizeof(saved_user));
185613e3f4d6SMark Murray }
185713e3f4d6SMark Murray if (saved_jid == 0) {
185813e3f4d6SMark Murray saved_jid = jid;
185913e3f4d6SMark Murray return(0);
186013e3f4d6SMark Murray }
186113e3f4d6SMark Murray
186213e3f4d6SMark Murray /* if the jid has changed, get the correct entry from the utmp file */
186313e3f4d6SMark Murray
186413e3f4d6SMark Murray if ( saved_jid != jid ) {
186513e3f4d6SMark Murray struct utmp *utp = NULL;
186613e3f4d6SMark Murray struct utmp *jid_getutid();
186713e3f4d6SMark Murray
186813e3f4d6SMark Murray utp = jid_getutid(pty_saved_jid);
186913e3f4d6SMark Murray
187013e3f4d6SMark Murray if (utp == 0) {
187113e3f4d6SMark Murray syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
187213e3f4d6SMark Murray return(-1);
187313e3f4d6SMark Murray }
187413e3f4d6SMark Murray
187513e3f4d6SMark Murray cleantmpdir(jid, utp->ut_tpath, utp->ut_user);
187613e3f4d6SMark Murray return(1);
187713e3f4d6SMark Murray }
187813e3f4d6SMark Murray
187913e3f4d6SMark Murray cleantmpdir(jid, saved_path, saved_user);
188013e3f4d6SMark Murray return(1);
188113e3f4d6SMark Murray }
188213e3f4d6SMark Murray
188313e3f4d6SMark Murray /*
188413e3f4d6SMark Murray * Fork a child process to clean up the TMPDIR
188513e3f4d6SMark Murray */
cleantmpdir(jid,tpath,user)1886c19800e8SDoug Rabson cleantmpdir(jid, tpath, user)
188713e3f4d6SMark Murray int jid;
188813e3f4d6SMark Murray char *tpath;
188913e3f4d6SMark Murray char *user;
189013e3f4d6SMark Murray {
189113e3f4d6SMark Murray switch(fork()) {
189213e3f4d6SMark Murray case -1:
189313e3f4d6SMark Murray syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n",
189413e3f4d6SMark Murray tpath);
189513e3f4d6SMark Murray break;
189613e3f4d6SMark Murray case 0:
189713e3f4d6SMark Murray execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, NULL);
189813e3f4d6SMark Murray syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n",
189913e3f4d6SMark Murray tpath, CLEANTMPCMD);
1900 exit(1);
1901 default:
1902 /*
1903 * Forget about child. We will exit, and
1904 * /etc/init will pick it up.
1905 */
1906 break;
1907 }
1908 }
1909 #endif /* CRAY */
1910 #endif /* defined(PARENT_DOES_UTMP) */
1911