openenvutils/telnetserver/src/sys_term.c
changeset 0 2e3d3ce01487
child 4 0fdb7f6b0309
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 // sys_term.c
       
     2 //
       
     3 // © Portions Copyright (c) Symbian Software Ltd 2007. All rights reserved.
       
     4 //
       
     5 /*
       
     6  * Copyright (c) 1989, 1993
       
     7  *	The Regents of the University of California.  All rights reserved.
       
     8  *
       
     9  * Redistribution and use in source and binary forms, with or without
       
    10  * modification, are permitted provided that the following conditions
       
    11  * are met:
       
    12  * 1. Redistributions of source code must retain the above copyright
       
    13  *    notice, this list of conditions and the following disclaimer.
       
    14  * 2. Redistributions in binary form must reproduce the above copyright
       
    15  *    notice, this list of conditions and the following disclaimer in the
       
    16  *    documentation and/or other materials provided with the distribution.
       
    17  * 3. Neither the name of the University nor the names of its contributors
       
    18  *    may be used to endorse or promote products derived from this software
       
    19  *    without specific prior written permission.
       
    20  *
       
    21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
       
    22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
       
    24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
       
    25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
       
    26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
       
    27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
       
    28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
       
    29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
       
    30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
       
    31  * SUCH DAMAGE.
       
    32  */
       
    33 #include "telnetd.h"
       
    34 
       
    35 #ifdef __SYMBIAN32__
       
    36 #include "dummy.h"
       
    37 #endif
       
    38 
       
    39 #ifndef __SYMBIAN32__
       
    40 __RCSID("$Heimdal: sys_term.c,v 1.104 2001/09/17 02:09:04 assar Exp $"
       
    41         "$NetBSD: sys_term.c,v 1.2 2003/08/07 09:15:30 agc Exp $");
       
    42 #endif
       
    43 
       
    44 #if defined(_CRAY) || (defined(__hpux) && !defined(HAVE_UTMPX_H))
       
    45 # define PARENT_DOES_UTMP
       
    46 #endif
       
    47 
       
    48 #include <utmp.h>
       
    49 
       
    50 #ifdef HAVE_UTMPX_H
       
    51 #include <utmpx.h>
       
    52 #endif
       
    53 
       
    54 #ifdef __SYMBIAN32__
       
    55 #ifdef __WINSCW__
       
    56 #pragma warn_unusedarg off
       
    57 #endif//__WINSCW__
       
    58 #endif//__SYMBIAN32__
       
    59 
       
    60 #ifdef HAVE_UTMPX_H
       
    61 struct	utmpx wtmp;
       
    62 #elif defined(HAVE_UTMP_H)
       
    63 struct	utmp wtmp;
       
    64 #endif /* HAVE_UTMPX_H */
       
    65 
       
    66 #ifdef HAVE_STRUCT_UTMP_UT_HOST
       
    67 int	utmp_len = sizeof(wtmp.ut_host);
       
    68 #else
       
    69 int	utmp_len = MAXHOSTNAMELEN;
       
    70 #endif
       
    71 
       
    72 #ifndef UTMP_FILE
       
    73 #ifdef _PATH_UTMP
       
    74 #define UTMP_FILE _PATH_UTMP
       
    75 #else
       
    76 #define UTMP_FILE "/etc/utmp"
       
    77 #endif
       
    78 #endif
       
    79 
       
    80 #if !defined(WTMP_FILE) && defined(_PATH_WTMP)
       
    81 #define WTMP_FILE _PATH_WTMP
       
    82 #endif
       
    83 
       
    84 #ifndef PARENT_DOES_UTMP
       
    85 #ifdef WTMP_FILE
       
    86 char	wtmpf[] = WTMP_FILE;
       
    87 #else
       
    88 char	wtmpf[]	= "/usr/adm/wtmp";
       
    89 #endif
       
    90 char	utmpf[] = UTMP_FILE;
       
    91 #else /* PARENT_DOES_UTMP */
       
    92 #ifdef WTMP_FILE
       
    93 char	wtmpf[] = WTMP_FILE;
       
    94 #else
       
    95 char	wtmpf[]	= "/etc/wtmp";
       
    96 #endif
       
    97 #endif /* PARENT_DOES_UTMP */
       
    98 
       
    99 #ifdef HAVE_TMPDIR_H
       
   100 #include <tmpdir.h>
       
   101 #endif	/* CRAY */
       
   102 
       
   103 #ifdef	STREAMSPTY
       
   104 
       
   105 #ifdef HAVE_SAC_H
       
   106 #include <sac.h>
       
   107 #endif
       
   108 
       
   109 #ifdef HAVE_SYS_STROPTS_H
       
   110 #include <sys/stropts.h>
       
   111 #endif
       
   112 
       
   113 #endif /* STREAMSPTY */
       
   114 
       
   115 #undef NOERROR
       
   116 
       
   117 #ifdef	HAVE_SYS_STREAM_H
       
   118 #ifdef  HAVE_SYS_UIO_H
       
   119 #include <sys/uio.h>
       
   120 #endif
       
   121 #ifdef __hpux
       
   122 #undef SE
       
   123 #endif
       
   124 #include <sys/stream.h>
       
   125 #endif
       
   126 #if !(defined(__sgi) || defined(__linux) || defined(_AIX)) && defined(HAVE_SYS_TTY)
       
   127 #include <sys/tty.h>
       
   128 #endif
       
   129 #ifdef	t_erase
       
   130 #undef	t_erase
       
   131 #undef	t_kill
       
   132 #undef	t_intrc
       
   133 #undef	t_quitc
       
   134 #undef	t_startc
       
   135 #undef	t_stopc
       
   136 #undef	t_eofc
       
   137 #undef	t_brkc
       
   138 #undef	t_suspc
       
   139 #undef	t_dsuspc
       
   140 #undef	t_rprntc
       
   141 #undef	t_flushc
       
   142 #undef	t_werasc
       
   143 #undef	t_lnextc
       
   144 #endif
       
   145 
       
   146 #ifdef HAVE_TERMIOS_H
       
   147 #include <termios.h>
       
   148 #else
       
   149 #ifdef HAVE_TERMIO_H
       
   150 #include <termio.h>
       
   151 #endif
       
   152 #endif
       
   153 
       
   154 #ifdef HAVE_UTIL_H
       
   155 #include <util.h>
       
   156 #endif
       
   157 #ifdef HAVE_LIBUTIL_H
       
   158 #include <libutil.h>
       
   159 #endif
       
   160 
       
   161 # ifndef	TCSANOW
       
   162 #  ifdef TCSETS
       
   163 #   define	TCSANOW		TCSETS
       
   164 #   define	TCSADRAIN	TCSETSW
       
   165 #   define	tcgetattr(f, t)	ioctl(f, TCGETS, (char *)t)
       
   166 #  else
       
   167 #   ifdef TCSETA
       
   168 #    define	TCSANOW		TCSETA
       
   169 #    define	TCSADRAIN	TCSETAW
       
   170 #    define	tcgetattr(f, t)	ioctl(f, TCGETA, (char *)t)
       
   171 #   else
       
   172 #    define	TCSANOW		TIOCSETA
       
   173 #    define	TCSADRAIN	TIOCSETAW
       
   174 #    define	tcgetattr(f, t)	ioctl(f, TIOCGETA, (char *)t)
       
   175 #   endif
       
   176 #  endif
       
   177 #  define	tcsetattr(f, a, t)	ioctl(f, a, t)
       
   178 #  define	cfsetospeed(tp, val)	(tp)->c_cflag &= ~CBAUD; \
       
   179 (tp)->c_cflag |= (val)
       
   180 #  define	cfgetospeed(tp)		((tp)->c_cflag & CBAUD)
       
   181 #  ifdef CIBAUD
       
   182 #   define	cfsetispeed(tp, val)	(tp)->c_cflag &= ~CIBAUD; \
       
   183      (tp)->c_cflag |= ((val)<<IBSHIFT)
       
   184 #   define	cfgetispeed(tp)		(((tp)->c_cflag & CIBAUD)>>IBSHIFT)
       
   185 #  else
       
   186 #   define	cfsetispeed(tp, val)	(tp)->c_cflag &= ~CBAUD; \
       
   187      (tp)->c_cflag |= (val)
       
   188 #   define	cfgetispeed(tp)		((tp)->c_cflag & CBAUD)
       
   189 #  endif
       
   190 # endif /* TCSANOW */
       
   191      struct termios termbuf, termbuf2;	/* pty control structure */
       
   192 # ifdef  STREAMSPTY
       
   193      static int ttyfd = -1;
       
   194      int really_stream = 0;
       
   195 # endif
       
   196 
       
   197      const char *new_login = _PATH_LOGIN;
       
   198 
       
   199 /*
       
   200  * init_termbuf()
       
   201  * copy_termbuf(cp)
       
   202  * set_termbuf()
       
   203  *
       
   204  * These three routines are used to get and set the "termbuf" structure
       
   205  * to and from the kernel.  init_termbuf() gets the current settings.
       
   206  * copy_termbuf() hands in a new "termbuf" to write to the kernel, and
       
   207  * set_termbuf() writes the structure into the kernel.
       
   208  */
       
   209 
       
   210      void
       
   211      init_termbuf(void)
       
   212 {
       
   213 # ifdef  STREAMSPTY
       
   214     if (really_stream)
       
   215 	tcgetattr(ttyfd, &termbuf);
       
   216     else
       
   217 # endif
       
   218 	tcgetattr(ourpty, &termbuf);
       
   219     termbuf2 = termbuf;
       
   220 }
       
   221 
       
   222 void
       
   223 set_termbuf(void)
       
   224 {
       
   225     /*
       
   226      * Only make the necessary changes.
       
   227 	 */
       
   228     if (memcmp(&termbuf, &termbuf2, sizeof(termbuf)))
       
   229 # ifdef  STREAMSPTY
       
   230 	if (really_stream)
       
   231 	    tcsetattr(ttyfd, TCSANOW, &termbuf);
       
   232 	else
       
   233 # endif
       
   234 	    tcsetattr(ourpty, TCSANOW, &termbuf);
       
   235 }
       
   236 
       
   237 
       
   238 /*
       
   239  * spcset(func, valp, valpp)
       
   240  *
       
   241  * This function takes various special characters (func), and
       
   242  * sets *valp to the current value of that character, and
       
   243  * *valpp to point to where in the "termbuf" structure that
       
   244  * value is kept.
       
   245  *
       
   246  * It returns the SLC_ level of support for this function.
       
   247  */
       
   248 
       
   249 
       
   250 int
       
   251 spcset(int func, cc_t *valp, cc_t **valpp)
       
   252 {
       
   253 
       
   254 #define	setval(a, b)	*valp = termbuf.c_cc[a]; \
       
   255     *valpp = &termbuf.c_cc[a]; \
       
   256 				   return(b);
       
   257 #define	defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT);
       
   258 
       
   259     switch(func) {
       
   260     case SLC_EOF:
       
   261 	setval(VEOF, SLC_VARIABLE);
       
   262     case SLC_EC:
       
   263 	setval(VERASE, SLC_VARIABLE);
       
   264     case SLC_EL:
       
   265 	setval(VKILL, SLC_VARIABLE);
       
   266     case SLC_IP:
       
   267 	setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
       
   268     case SLC_ABORT:
       
   269 	setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT);
       
   270     case SLC_XON:
       
   271 #ifdef	VSTART
       
   272 	setval(VSTART, SLC_VARIABLE);
       
   273 #else
       
   274 	defval(0x13);
       
   275 #endif
       
   276     case SLC_XOFF:
       
   277 #ifdef	VSTOP
       
   278 	setval(VSTOP, SLC_VARIABLE);
       
   279 #else
       
   280 	defval(0x11);
       
   281 #endif
       
   282     case SLC_EW:
       
   283 #ifdef	VWERASE
       
   284 	setval(VWERASE, SLC_VARIABLE);
       
   285 #else
       
   286 	defval(0);
       
   287 #endif
       
   288     case SLC_RP:
       
   289 #ifdef	VREPRINT
       
   290 	setval(VREPRINT, SLC_VARIABLE);
       
   291 #else
       
   292 	defval(0);
       
   293 #endif
       
   294     case SLC_LNEXT:
       
   295 #ifdef	VLNEXT
       
   296 	setval(VLNEXT, SLC_VARIABLE);
       
   297 #else
       
   298 	defval(0);
       
   299 #endif
       
   300     case SLC_AO:
       
   301 #if	!defined(VDISCARD) && defined(VFLUSHO)
       
   302 # define VDISCARD VFLUSHO
       
   303 #endif
       
   304 #ifdef	VDISCARD
       
   305 	setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT);
       
   306 #else
       
   307 	defval(0);
       
   308 #endif
       
   309     case SLC_SUSP:
       
   310 #ifdef	VSUSP
       
   311 	setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN);
       
   312 #else
       
   313 	defval(0);
       
   314 #endif
       
   315 #ifdef	VEOL
       
   316     case SLC_FORW1:
       
   317 	setval(VEOL, SLC_VARIABLE);
       
   318 #endif
       
   319 #ifdef	VEOL2
       
   320     case SLC_FORW2:
       
   321 	setval(VEOL2, SLC_VARIABLE);
       
   322 #endif
       
   323     case SLC_AYT:
       
   324 #ifdef	VSTATUS
       
   325 	setval(VSTATUS, SLC_VARIABLE);
       
   326 #else
       
   327 	defval(0);
       
   328 #endif
       
   329 
       
   330     case SLC_BRK:
       
   331     case SLC_SYNCH:
       
   332     case SLC_EOR:
       
   333 	defval(0);
       
   334 
       
   335     default:
       
   336 	*valp = 0;
       
   337 	*valpp = 0;
       
   338 	return(SLC_NOSUPPORT);
       
   339     }
       
   340 }
       
   341 
       
   342 #ifdef _CRAY
       
   343 /*
       
   344  * getnpty()
       
   345  *
       
   346  * Return the number of pty's configured into the system.
       
   347  */
       
   348 int
       
   349 getnpty()
       
   350 {
       
   351 #ifdef _SC_CRAY_NPTY
       
   352     int numptys;
       
   353 
       
   354     if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1)
       
   355 	return numptys;
       
   356     else
       
   357 #endif /* _SC_CRAY_NPTY */
       
   358 	return 128;
       
   359 }
       
   360 #endif /* CRAY */
       
   361 
       
   362 /*
       
   363  * getpty()
       
   364  *
       
   365  * Allocate a pty.  As a side effect, the external character
       
   366  * array "line" contains the name of the slave side.
       
   367  *
       
   368  * Returns the file descriptor of the opened pty.
       
   369  */
       
   370 
       
   371 static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
       
   372 char *line = Xline;
       
   373 
       
   374 #ifdef	_CRAY
       
   375 char myline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
       
   376 #endif	/* CRAY */
       
   377 
       
   378 #if !defined(HAVE_PTSNAME) && defined(STREAMSPTY)
       
   379 static char *ptsname(int fd)
       
   380 {
       
   381 #ifdef HAVE_TTYNAME
       
   382     return ttyname(fd);
       
   383 #else
       
   384     return NULL;
       
   385 #endif
       
   386 }
       
   387 #endif
       
   388 
       
   389 int getpty(int *ptynum)
       
   390 {
       
   391 #ifdef __osf__ /* XXX */
       
   392     int master;
       
   393     int slave;
       
   394     if(openpty(&master, &slave, line, 0, 0) == 0){
       
   395 	close(slave);
       
   396 	return master;
       
   397     }
       
   398     return -1;
       
   399 #else
       
   400 #ifdef HAVE__GETPTY
       
   401     int master, slave;
       
   402     char *p;
       
   403     p = _getpty(&master, O_RDWR, 0600, 1);
       
   404     if(p == NULL)
       
   405 	return -1;
       
   406     strlcpy(line, p, sizeof(Xline));
       
   407     return master;
       
   408 #else
       
   409 
       
   410     int p;
       
   411     char *cp, *p1, *p2;
       
   412     int i;
       
   413 #if SunOS == 40
       
   414     int dummy;
       
   415 #endif
       
   416 #if __linux
       
   417     int master;
       
   418     int slave;
       
   419     if(openpty(&master, &slave, line, 0, 0) == 0){
       
   420 	close(slave);
       
   421 	return master;
       
   422     }
       
   423 #else
       
   424 #ifdef	STREAMSPTY
       
   425     char *clone[] = { "/dev/ptc", "/dev/ptmx", "/dev/ptm", 
       
   426 		      "/dev/ptym/clone", 0 };
       
   427 
       
   428     char **q;
       
   429     for(q=clone; *q; q++){
       
   430 	p=open(*q, O_RDWR);
       
   431 	if(p >= 0){
       
   432 #ifdef HAVE_GRANTPT
       
   433 	    grantpt(p);
       
   434 #endif
       
   435 #ifdef HAVE_UNLOCKPT
       
   436 	    unlockpt(p);
       
   437 #endif
       
   438 	    strlcpy(line, ptsname(p), sizeof(Xline));
       
   439 	    really_stream = 1;
       
   440 	    return p;
       
   441 	}
       
   442     }
       
   443 #endif /* STREAMSPTY */
       
   444 #ifndef _CRAY
       
   445 
       
   446 #ifndef	__hpux
       
   447     snprintf(line, sizeof(Xline), "/dev/ptyXX");
       
   448     p1 = &line[8];
       
   449     p2 = &line[9];
       
   450 #else
       
   451     snprintf(line, sizeof(Xline), "/dev/ptym/ptyXX");
       
   452     p1 = &line[13];
       
   453     p2 = &line[14];
       
   454 #endif
       
   455 
       
   456 	
       
   457     for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) {
       
   458 	struct stat stb;
       
   459 
       
   460 	*p1 = *cp;
       
   461 	*p2 = '0';
       
   462 	/*
       
   463 	 * This stat() check is just to keep us from
       
   464 	 * looping through all 256 combinations if there
       
   465 	 * aren't that many ptys available.
       
   466 	 */
       
   467 	if (stat(line, &stb) < 0)
       
   468 	    break;
       
   469 	for (i = 0; i < 16; i++) {
       
   470 	    *p2 = "0123456789abcdef"[i];
       
   471 	    p = open(line, O_RDWR);
       
   472 	    if (p > 0) {
       
   473 #ifndef	__hpux
       
   474 		line[5] = 't';
       
   475 #else
       
   476 		for (p1 = &line[8]; *p1; p1++)
       
   477 		    *p1 = *(p1+1);
       
   478 		line[9] = 't';
       
   479 #endif
       
   480 		chown(line, 0, 0);
       
   481 		chmod(line, 0600);
       
   482 #if SunOS == 40
       
   483 		if (ioctl(p, TIOCGPGRP, &dummy) == 0
       
   484 		    || errno != EIO) {
       
   485 		    chmod(line, 0666);
       
   486 		    close(p);
       
   487 		    line[5] = 'p';
       
   488 		} else
       
   489 #endif /* SunOS == 40 */
       
   490 		    return(p);
       
   491 	    }
       
   492 	}
       
   493     }
       
   494 #else	/* CRAY */
       
   495     extern lowpty, highpty;
       
   496     struct stat sb;
       
   497 
       
   498     for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) {
       
   499 	snprintf(myline, sizeof(myline), "/dev/pty/%03d", *ptynum);
       
   500 	p = open(myline, 2);
       
   501 	if (p < 0)
       
   502 	    continue;
       
   503 	snprintf(line, sizeof(Xline), "/dev/ttyp%03d", *ptynum);
       
   504 	/*
       
   505 	 * Here are some shenanigans to make sure that there
       
   506 	 * are no listeners lurking on the line.
       
   507 	 */
       
   508 	if(stat(line, &sb) < 0) {
       
   509 	    close(p);
       
   510 	    continue;
       
   511 	}
       
   512 	if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) {
       
   513 	    chown(line, 0, 0);
       
   514 	    chmod(line, 0600);
       
   515 	    close(p);
       
   516 	    p = open(myline, 2);
       
   517 	    if (p < 0)
       
   518 		continue;
       
   519 	}
       
   520 	/*
       
   521 	 * Now it should be safe...check for accessability.
       
   522 	 */
       
   523 	if (access(line, 6) == 0)
       
   524 	    return(p);
       
   525 	else {
       
   526 	    /* no tty side to pty so skip it */
       
   527 	    close(p);
       
   528 	}
       
   529     }
       
   530 #endif	/* CRAY */
       
   531 #endif	/* STREAMSPTY */
       
   532 #endif /* OPENPTY */
       
   533     return(-1);
       
   534 #endif
       
   535 }
       
   536 
       
   537 
       
   538 int
       
   539 tty_isecho(void)
       
   540 {
       
   541     return (termbuf.c_lflag & ECHO);
       
   542 }
       
   543 
       
   544 int
       
   545 tty_flowmode(void)
       
   546 {
       
   547     return((termbuf.c_iflag & IXON) ? 1 : 0);
       
   548 }
       
   549 
       
   550 int
       
   551 tty_restartany(void)
       
   552 {
       
   553     return((termbuf.c_iflag & IXANY) ? 1 : 0);
       
   554 }
       
   555 
       
   556 void
       
   557 tty_setecho(int on)
       
   558 {
       
   559     if (on)
       
   560 	termbuf.c_lflag |= ECHO;
       
   561     else
       
   562 	termbuf.c_lflag &= ~ECHO;
       
   563 }
       
   564 
       
   565 int
       
   566 tty_israw(void)
       
   567 {
       
   568     return(!(termbuf.c_lflag & ICANON));
       
   569 }
       
   570 
       
   571 void
       
   572 tty_binaryin(int on)
       
   573 {
       
   574     if (on) {
       
   575 	termbuf.c_iflag &= ~ISTRIP;
       
   576     } else {
       
   577 	termbuf.c_iflag |= ISTRIP;
       
   578     }
       
   579 }
       
   580 
       
   581 void
       
   582 tty_binaryout(int on)
       
   583 {
       
   584     if (on) {
       
   585 	termbuf.c_cflag &= ~(CSIZE|PARENB);
       
   586 	termbuf.c_cflag |= CS8;
       
   587 	termbuf.c_oflag &= ~OPOST;
       
   588     } else {
       
   589 	termbuf.c_cflag &= ~CSIZE;
       
   590 	termbuf.c_cflag |= CS7|PARENB;
       
   591 	termbuf.c_oflag |= OPOST;
       
   592     }
       
   593 }
       
   594 
       
   595 int
       
   596 tty_isbinaryin(void)
       
   597 {
       
   598     return(!(termbuf.c_iflag & ISTRIP));
       
   599 }
       
   600 
       
   601 int
       
   602 tty_isbinaryout(void)
       
   603 {
       
   604     return(!(termbuf.c_oflag&OPOST));
       
   605 }
       
   606 
       
   607 
       
   608 int
       
   609 tty_issofttab(void)
       
   610 {
       
   611 # ifdef	OXTABS
       
   612     return (termbuf.c_oflag & OXTABS);
       
   613 # endif
       
   614 # ifdef	TABDLY
       
   615     return ((termbuf.c_oflag & TABDLY) == TAB3);
       
   616 # endif
       
   617 }
       
   618 
       
   619 void
       
   620 tty_setsofttab(int on)
       
   621 {
       
   622     if (on) {
       
   623 # ifdef	OXTABS
       
   624 	termbuf.c_oflag |= OXTABS;
       
   625 # endif
       
   626 # ifdef	TABDLY
       
   627 	termbuf.c_oflag &= ~TABDLY;
       
   628 	termbuf.c_oflag |= TAB3;
       
   629 # endif
       
   630     } else {
       
   631 # ifdef	OXTABS
       
   632 	termbuf.c_oflag &= ~OXTABS;
       
   633 # endif
       
   634 # ifdef	TABDLY
       
   635 	termbuf.c_oflag &= ~TABDLY;
       
   636 	termbuf.c_oflag |= TAB0;
       
   637 # endif
       
   638     }
       
   639 }
       
   640 
       
   641 int
       
   642 tty_islitecho(void)
       
   643 {
       
   644 # ifdef	ECHOCTL
       
   645     return (!(termbuf.c_lflag & ECHOCTL));
       
   646 # endif
       
   647 # ifdef	TCTLECH
       
   648     return (!(termbuf.c_lflag & TCTLECH));
       
   649 # endif
       
   650 # if	!defined(ECHOCTL) && !defined(TCTLECH)
       
   651     return (0);	/* assumes ctl chars are echoed '^x' */
       
   652 # endif
       
   653 }
       
   654 
       
   655 void
       
   656 tty_setlitecho(int on)
       
   657 {
       
   658 # ifdef	ECHOCTL
       
   659     if (on)
       
   660 	termbuf.c_lflag &= ~ECHOCTL;
       
   661     else
       
   662 	termbuf.c_lflag |= ECHOCTL;
       
   663 # endif
       
   664 # ifdef	TCTLECH
       
   665     if (on)
       
   666 	termbuf.c_lflag &= ~TCTLECH;
       
   667     else
       
   668 	termbuf.c_lflag |= TCTLECH;
       
   669 # endif
       
   670 }
       
   671 
       
   672 int
       
   673 tty_iscrnl(void)
       
   674 {
       
   675     return (termbuf.c_iflag & ICRNL);
       
   676 }
       
   677 
       
   678 /*
       
   679  * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
       
   680  */
       
   681 #if B4800 != 4800
       
   682 #define	DECODE_BAUD
       
   683 #endif
       
   684 
       
   685 #ifdef	DECODE_BAUD
       
   686 
       
   687 /*
       
   688  * A table of available terminal speeds
       
   689  */
       
   690 struct termspeeds {
       
   691     int	speed;
       
   692     int	value;
       
   693 } termspeeds[] = {
       
   694     { 0,      B0 },      { 50,    B50 },    { 75,     B75 },
       
   695     { 110,    B110 },    { 134,   B134 },   { 150,    B150 },
       
   696     { 200,    B200 },    { 300,   B300 },   { 600,    B600 },
       
   697     { 1200,   B1200 },   { 1800,  B1800 },  { 2400,   B2400 },
       
   698     { 4800,   B4800 },
       
   699 #ifdef	B7200
       
   700     { 7200,  B7200 },
       
   701 #endif
       
   702     { 9600,   B9600 },
       
   703 #ifdef	B14400
       
   704     { 14400,  B14400 },
       
   705 #endif
       
   706 #ifdef	B19200
       
   707     { 19200,  B19200 },
       
   708 #endif
       
   709 #ifdef	B28800
       
   710     { 28800,  B28800 },
       
   711 #endif
       
   712 #ifdef	B38400
       
   713     { 38400,  B38400 },
       
   714 #endif
       
   715 #ifdef	B57600
       
   716     { 57600,  B57600 },
       
   717 #endif
       
   718 #ifdef	B115200
       
   719     { 115200, B115200 },
       
   720 #endif
       
   721 #ifdef	B230400
       
   722     { 230400, B230400 },
       
   723 #endif
       
   724     { -1,     0 }
       
   725 };
       
   726 #endif	/* DECODE_BUAD */
       
   727 
       
   728 void
       
   729 tty_tspeed(int val)
       
   730 {
       
   731 #ifdef	DECODE_BAUD
       
   732     struct termspeeds *tp;
       
   733 
       
   734     for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
       
   735 	;
       
   736     if (tp->speed == -1)	/* back up to last valid value */
       
   737 	--tp;
       
   738     cfsetospeed(&termbuf, tp->value);
       
   739 #else	/* DECODE_BUAD */
       
   740     cfsetospeed(&termbuf, val);
       
   741 #endif	/* DECODE_BUAD */
       
   742 }
       
   743 
       
   744 void
       
   745 tty_rspeed(int val)
       
   746 {
       
   747 #ifdef	DECODE_BAUD
       
   748     struct termspeeds *tp;
       
   749 
       
   750     for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++)
       
   751 	;
       
   752     if (tp->speed == -1)	/* back up to last valid value */
       
   753 	--tp;
       
   754     cfsetispeed(&termbuf, tp->value);
       
   755 #else	/* DECODE_BAUD */
       
   756     cfsetispeed(&termbuf, val);
       
   757 #endif	/* DECODE_BAUD */
       
   758 }
       
   759 
       
   760 #ifdef PARENT_DOES_UTMP
       
   761 extern	struct utmp wtmp;
       
   762 extern char wtmpf[];
       
   763 
       
   764 extern void utmp_sig_init (void);
       
   765 extern void utmp_sig_reset (void);
       
   766 extern void utmp_sig_wait (void);
       
   767 extern void utmp_sig_notify (int);
       
   768 # endif /* PARENT_DOES_UTMP */
       
   769 
       
   770 #ifdef STREAMSPTY
       
   771 
       
   772 /* I_FIND seems to live a life of its own */
       
   773 static int my_find(int fd, char *module)
       
   774 {
       
   775 #if defined(I_FIND) && defined(I_LIST)
       
   776     static int flag;
       
   777     static struct str_list sl;
       
   778     int n;
       
   779     int i;
       
   780   
       
   781     if(!flag){
       
   782 	n = ioctl(fd, I_LIST, 0);
       
   783 	if(n < 0){
       
   784 	    perror("ioctl(fd, I_LIST, 0)");
       
   785 	    return -1;
       
   786 	}
       
   787 	sl.sl_modlist=(struct str_mlist*)malloc(n * sizeof(struct str_mlist));
       
   788 	sl.sl_nmods = n;
       
   789 	n = ioctl(fd, I_LIST, &sl);
       
   790 	if(n < 0){
       
   791 	    perror("ioctl(fd, I_LIST, n)");
       
   792 	    return -1;
       
   793 	}
       
   794 	flag = 1;
       
   795     }
       
   796   
       
   797     for(i=0; i<sl.sl_nmods; i++)
       
   798 	if(!strcmp(sl.sl_modlist[i].l_name, module))
       
   799 	    return 1;
       
   800 #endif
       
   801     return 0;
       
   802 }
       
   803 
       
   804 static void maybe_push_modules(int fd, char **modules)
       
   805 {
       
   806     char **p;
       
   807     int err;
       
   808 
       
   809     for(p=modules; *p; p++){
       
   810 	err = my_find(fd, *p);
       
   811 	if(err == 1)
       
   812 	    break;
       
   813 	if(err < 0 && errno != EINVAL)
       
   814 	    fatalperror(net, "my_find()");
       
   815 	/* module not pushed or does not exist */
       
   816     }
       
   817     /* p points to null or to an already pushed module, now push all
       
   818        modules before this one */
       
   819   
       
   820     for(p--; p >= modules; p--){
       
   821 	err = ioctl(fd, I_PUSH, *p);
       
   822 	if(err < 0 && errno != EINVAL)
       
   823 	    fatalperror(net, "I_PUSH");
       
   824     }
       
   825 }
       
   826 #endif
       
   827 
       
   828 /*
       
   829  * getptyslave()
       
   830  *
       
   831  * Open the slave side of the pty, and do any initialization
       
   832  * that is necessary.  The return value is a file descriptor
       
   833  * for the slave side.
       
   834  */
       
   835 void getptyslave(void)
       
   836 {
       
   837     int t = -1;
       
   838 
       
   839     struct winsize ws;
       
   840     /*
       
   841      * Opening the slave side may cause initilization of the
       
   842      * kernel tty structure.  We need remember the state of
       
   843      * 	if linemode was turned on
       
   844      *	terminal window size
       
   845      *	terminal speed
       
   846      * so that we can re-set them if we need to.
       
   847      */
       
   848 
       
   849 
       
   850     /*
       
   851      * Make sure that we don't have a controlling tty, and
       
   852      * that we are the session (process group) leader.
       
   853      */
       
   854 
       
   855 #ifdef HAVE_SETSID
       
   856     if(setsid()<0)
       
   857 	fatalperror(net, "setsid()");
       
   858 #else
       
   859 # ifdef	TIOCNOTTY
       
   860     t = open(_PATH_TTY, O_RDWR);
       
   861     if (t >= 0) {
       
   862 	ioctl(t, TIOCNOTTY, (char *)0);
       
   863 	close(t);
       
   864     }
       
   865 # endif
       
   866 #endif
       
   867 
       
   868 # ifdef PARENT_DOES_UTMP
       
   869     /*
       
   870      * Wait for our parent to get the utmp stuff to get done.
       
   871      */
       
   872     utmp_sig_wait();
       
   873 # endif
       
   874 
       
   875     t = cleanopen(line);
       
   876     if (t < 0)
       
   877 	fatalperror(net, line);
       
   878 
       
   879 #ifdef  STREAMSPTY
       
   880     ttyfd = t;
       
   881 	  
       
   882 
       
   883     /*
       
   884      * Not all systems have (or need) modules ttcompat and pckt so
       
   885      * don't flag it as a fatal error if they don't exist.
       
   886      */
       
   887 
       
   888     if (really_stream)
       
   889 	{
       
   890 	    /* these are the streams modules that we want pushed. note
       
   891 	       that they are in reverse order, ptem will be pushed
       
   892 	       first. maybe_push_modules() will try to push all modules
       
   893 	       before the first one that isn't already pushed. i.e if
       
   894 	       ldterm is pushed, only ttcompat will be attempted.
       
   895 
       
   896 	       all this is because we don't know which modules are
       
   897 	       available, and we don't know which modules are already
       
   898 	       pushed (via autopush, for instance).
       
   899 
       
   900 	       */
       
   901 	     
       
   902 	    char *ttymodules[] = { "ttcompat", "ldterm", "ptem", NULL };
       
   903 	    char *ptymodules[] = { "pckt", NULL };
       
   904 
       
   905 	    maybe_push_modules(t, ttymodules);
       
   906 	    maybe_push_modules(ourpty, ptymodules);
       
   907 	}
       
   908 #endif
       
   909     /*
       
   910      * set up the tty modes as we like them to be.
       
   911      */
       
   912     init_termbuf();
       
   913 # ifdef	TIOCSWINSZ
       
   914     if (def_row || def_col) {
       
   915 	memset(&ws, 0, sizeof(ws));
       
   916 	ws.ws_col = def_col;
       
   917 	ws.ws_row = def_row;
       
   918 	ioctl(t, TIOCSWINSZ, (char *)&ws);
       
   919     }
       
   920 # endif
       
   921 
       
   922     /*
       
   923      * Settings for sgtty based systems
       
   924      */
       
   925 
       
   926     /*
       
   927      * Settings for UNICOS (and HPUX)
       
   928      */
       
   929 # if defined(_CRAY) || defined(__hpux)
       
   930     termbuf.c_oflag = OPOST|ONLCR|TAB3;
       
   931     termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
       
   932     termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
       
   933     termbuf.c_cflag = EXTB|HUPCL|CS8;
       
   934 # endif
       
   935 
       
   936     /*
       
   937      * Settings for all other termios/termio based
       
   938      * systems, other than 4.4BSD.  In 4.4BSD the
       
   939      * kernel does the initial terminal setup.
       
   940      */
       
   941 # if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43)
       
   942 #  ifndef	OXTABS
       
   943 #   define OXTABS	0
       
   944 #  endif
       
   945     termbuf.c_lflag |= ECHO;
       
   946     termbuf.c_oflag |= ONLCR|OXTABS;
       
   947     termbuf.c_iflag |= ICRNL;
       
   948     termbuf.c_iflag &= ~IXOFF;
       
   949 # endif
       
   950     tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600);
       
   951     tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600);
       
   952 
       
   953     /*
       
   954      * Set the tty modes, and make this our controlling tty.
       
   955      */
       
   956     set_termbuf();
       
   957     if (login_tty(t) == -1)
       
   958 	fatalperror(net, "login_tty");
       
   959     if (net > 2)
       
   960 	close(net);
       
   961     if (ourpty > 2) {
       
   962 	close(ourpty);
       
   963 	ourpty = -1;
       
   964     }
       
   965 }
       
   966 
       
   967 #ifndef	O_NOCTTY
       
   968 #define	O_NOCTTY	0
       
   969 #endif
       
   970 /*
       
   971  * Open the specified slave side of the pty,
       
   972  * making sure that we have a clean tty.
       
   973  */
       
   974 
       
   975 int cleanopen(char *line)
       
   976 {
       
   977     int t;
       
   978 
       
   979 #ifdef STREAMSPTY
       
   980     if (!really_stream)
       
   981 #endif
       
   982 	{
       
   983 	    /*
       
   984 	     * Make sure that other people can't open the
       
   985 	     * slave side of the connection.
       
   986 	     */
       
   987 	    chown(line, 0, 0);
       
   988 	    chmod(line, 0600);
       
   989 	}
       
   990 
       
   991 #ifdef HAVE_REVOKE
       
   992     revoke(line);
       
   993 #endif
       
   994 
       
   995     t = open(line, O_RDWR|O_NOCTTY);
       
   996 
       
   997     if (t < 0)
       
   998 	return(-1);
       
   999 
       
  1000     /*
       
  1001      * Hangup anybody else using this ttyp, then reopen it for
       
  1002      * ourselves.
       
  1003      */
       
  1004 # if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY)
       
  1005     signal(SIGHUP, SIG_IGN);
       
  1006 #ifdef HAVE_VHANGUP
       
  1007     vhangup();
       
  1008 #else
       
  1009 #endif
       
  1010     signal(SIGHUP, SIG_DFL);
       
  1011     t = open(line, O_RDWR|O_NOCTTY);
       
  1012     if (t < 0)
       
  1013 	return(-1);
       
  1014 # endif
       
  1015 # if	defined(_CRAY) && defined(TCVHUP)
       
  1016     {
       
  1017 	int i;
       
  1018 	signal(SIGHUP, SIG_IGN);
       
  1019 	ioctl(t, TCVHUP, (char *)0);
       
  1020 	signal(SIGHUP, SIG_DFL);
       
  1021 
       
  1022 	i = open(line, O_RDWR);
       
  1023 
       
  1024 	if (i < 0)
       
  1025 	    return(-1);
       
  1026 	close(t);
       
  1027 	t = i;
       
  1028     }
       
  1029 # endif	/* defined(CRAY) && defined(TCVHUP) */
       
  1030     return(t);
       
  1031 }
       
  1032 
       
  1033 //#if !defined(BSD4_4)
       
  1034 
       
  1035 int login_tty(int t)
       
  1036 {
       
  1037 # if defined(TIOCSCTTY) && !defined(__hpux)
       
  1038     if (ioctl(t, TIOCSCTTY, (char *)0) < 0)
       
  1039 	fatalperror(net, "ioctl(sctty)");
       
  1040 #  ifdef _CRAY
       
  1041     /*
       
  1042      * Close the hard fd to /dev/ttypXXX, and re-open through
       
  1043      * the indirect /dev/tty interface.
       
  1044      */
       
  1045     close(t);
       
  1046     if ((t = open("/dev/tty", O_RDWR)) < 0)
       
  1047 	fatalperror(net, "open(/dev/tty)");
       
  1048 #  endif
       
  1049 # else
       
  1050     /*
       
  1051      * We get our controlling tty assigned as a side-effect
       
  1052      * of opening up a tty device.  But on BSD based systems,
       
  1053      * this only happens if our process group is zero.  The
       
  1054      * setsid() call above may have set our pgrp, so clear
       
  1055      * it out before opening the tty...
       
  1056      */
       
  1057 #ifdef HAVE_SETPGID
       
  1058     setpgid(0, 0);
       
  1059 #else
       
  1060     setpgrp(0, 0); /* if setpgid isn't available, setpgrp
       
  1061 		      probably takes arguments */
       
  1062 #endif
       
  1063     close(open(line, O_RDWR));
       
  1064 # endif
       
  1065     if (t != 0)
       
  1066 	dup2(t, 0);
       
  1067     if (t != 1)
       
  1068 	dup2(t, 1);
       
  1069     if (t != 2)
       
  1070 	dup2(t, 2);
       
  1071     if (t > 2)
       
  1072 	close(t);
       
  1073     return(0);
       
  1074 }
       
  1075 //#endif	/* BSD <= 43 */
       
  1076 
       
  1077 /*
       
  1078  * This comes from ../../bsd/tty.c and should not really be here.
       
  1079  */
       
  1080 
       
  1081 /*
       
  1082  * Clean the tty name.  Return a pointer to the cleaned version.
       
  1083  */
       
  1084 #ifndef __SYMBIAN32__
       
  1085 static char *
       
  1086 clean_ttyname (char *tty)
       
  1087 {
       
  1088   char *res = tty;
       
  1089 
       
  1090   if (strncmp (res, _PATH_DEV, strlen(_PATH_DEV)) == 0)
       
  1091     res += strlen(_PATH_DEV);
       
  1092   if (strncmp (res, "pty/", 4) == 0)
       
  1093     res += 4;
       
  1094   if (strncmp (res, "ptym/", 5) == 0)
       
  1095     res += 5;
       
  1096   return res;
       
  1097 }
       
  1098 #endif
       
  1099 /*
       
  1100  * Generate a name usable as an `ut_id', typically without `tty'.
       
  1101  */
       
  1102 
       
  1103 #ifdef HAVE_STRUCT_UTMP_UT_ID
       
  1104 static char *
       
  1105 make_id (char *tty)
       
  1106 {
       
  1107   char *res = tty;
       
  1108   
       
  1109   if (strncmp (res, "pts/", 4) == 0)
       
  1110     res += 4;
       
  1111   if (strncmp (res, "tty", 3) == 0)
       
  1112     res += 3;
       
  1113   return res;
       
  1114 }
       
  1115 #endif
       
  1116 
       
  1117 
       
  1118 /*
       
  1119  * startslave(host)
       
  1120  *
       
  1121  * Given a hostname, do whatever
       
  1122  * is necessary to startup the login process on the slave side of the pty.
       
  1123  */
       
  1124 
       
  1125 /* ARGSUSED */
       
  1126 void
       
  1127 startslave(const char *host, const char *utmp_host,
       
  1128 	   int autologin, char *autoname)
       
  1129 {
       
  1130 #ifndef __SYMBIAN32__
       
  1131 	int i;
       
  1132 #else	
       
  1133     int fds[3];
       
  1134     int pid;
       
  1135 #endif	
       
  1136 
       
  1137 #ifdef AUTHENTICATION
       
  1138     if (!autoname || !autoname[0])
       
  1139 	autologin = 0;
       
  1140 
       
  1141     if (autologin < auth_level) {
       
  1142 	fatal(net, "Authorization failed");
       
  1143 	exit(1);
       
  1144     }
       
  1145 #endif
       
  1146 
       
  1147     {
       
  1148 	char *tbuf =
       
  1149 	    "\r\n*** Connection not encrypted! "
       
  1150 	    "Communication may be eavesdropped. ***\r\n";
       
  1151 #ifdef ENCRYPTION
       
  1152 	if (!no_warn && (encrypt_output == 0 || decrypt_input == 0))
       
  1153 #endif
       
  1154 	    writenet((unsigned char*)tbuf, strlen(tbuf));
       
  1155     }
       
  1156 # ifdef	PARENT_DOES_UTMP
       
  1157     utmp_sig_init();
       
  1158 # endif	/* PARENT_DOES_UTMP */
       
  1159 
       
  1160 #ifdef __SYMBIAN32__
       
  1161 	pid=popen3("Z:\\sys\\bin\\zsh.exe", NULL, NULL, fds);
       
  1162 		
       
  1163 	if (pid==-1) 
       
  1164 		{
       
  1165 		fatalperror(net, "popen3");			
       
  1166 		}
       
  1167 #endif //__SYMBIAN32__
       
  1168 
       
  1169 #ifndef __SYMBIAN32__		
       
  1170     if ((i = fork()) < 0)
       
  1171 	fatalperror(net, "fork");
       
  1172     if (i) {
       
  1173 # ifdef PARENT_DOES_UTMP
       
  1174 	/*
       
  1175 	 * Cray parent will create utmp entry for child and send
       
  1176 	 * signal to child to tell when done.  Child waits for signal
       
  1177 	 * before doing anything important.
       
  1178 	 */
       
  1179 	int pid = i;
       
  1180 	void sigjob (int);
       
  1181 
       
  1182 	setpgrp();
       
  1183 	utmp_sig_reset();		/* reset handler to default */
       
  1184 	/*
       
  1185 	 * Create utmp entry for child
       
  1186 	 */
       
  1187 	wtmp.ut_time = time(NULL);
       
  1188 	wtmp.ut_type = LOGIN_PROCESS;
       
  1189 	wtmp.ut_pid = pid;
       
  1190 	strncpy(wtmp.ut_user,  "LOGIN", sizeof(wtmp.ut_user));
       
  1191 	strncpy(wtmp.ut_host,  utmp_host, sizeof(wtmp.ut_host));
       
  1192 	strncpy(wtmp.ut_line,  clean_ttyname(line), sizeof(wtmp.ut_line));
       
  1193 #ifdef HAVE_STRUCT_UTMP_UT_ID
       
  1194 	strncpy(wtmp.ut_id, wtmp.ut_line + 3, sizeof(wtmp.ut_id));
       
  1195 #endif
       
  1196 
       
  1197 	pututline(&wtmp);
       
  1198 	endutent();
       
  1199 	if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) {
       
  1200 	    write(i, &wtmp, sizeof(struct utmp));
       
  1201 	    close(i);
       
  1202 	}
       
  1203 #ifdef	_CRAY
       
  1204 	signal(WJSIGNAL, sigjob);
       
  1205 #endif
       
  1206 	utmp_sig_notify(pid);
       
  1207 # endif	/* PARENT_DOES_UTMP */
       
  1208     } else {
       
  1209 	getptyslave();
       
  1210 #if defined(DCE)
       
  1211 	/* if we authenticated via K5, try and join the PAG */
       
  1212 	kerberos5_dfspag();
       
  1213 #endif
       
  1214 	start_login(host, autologin, autoname);
       
  1215 	/*NOTREACHED*/
       
  1216     } 
       
  1217 #endif//__SYMBIAN32__     
       
  1218 }
       
  1219 
       
  1220 
       
  1221 char	*envinit[3];
       
  1222 #ifndef __SYMBIAN32__
       
  1223 extern char **environ;
       
  1224 #endif
       
  1225 
       
  1226 void
       
  1227 init_env(void)
       
  1228 {
       
  1229     char **envp;
       
  1230 
       
  1231     envp = envinit;
       
  1232     *envp = getenv("TZ");
       
  1233     if (*envp)
       
  1234 	*envp++ -= 3;
       
  1235 #if defined(_CRAY) || defined(__hpux)
       
  1236     else
       
  1237 	*envp++ = "TZ=GMT0";
       
  1238 #endif
       
  1239     *envp = 0;
       
  1240     environ = envinit;
       
  1241 }
       
  1242 
       
  1243 /*
       
  1244  * scrub_env()
       
  1245  *
       
  1246  * We only accept the environment variables listed below.
       
  1247  */
       
  1248 #ifndef __SYMBIAN32__
       
  1249 static void
       
  1250 scrub_env(void)
       
  1251 {
       
  1252     static const char *reject[] = {
       
  1253 	"TERMCAP=/",
       
  1254 	NULL
       
  1255     };
       
  1256 
       
  1257     static const char *accept[] = {
       
  1258 	"XAUTH=", "XAUTHORITY=", "DISPLAY=",
       
  1259 	"TERM=",
       
  1260 	"EDITOR=",
       
  1261 	"PAGER=",
       
  1262 	"PRINTER=",
       
  1263 	"LOGNAME=",
       
  1264 	"POSIXLY_CORRECT=",
       
  1265 	"TERMCAP=",
       
  1266 	NULL
       
  1267     };
       
  1268 
       
  1269     char **cpp, **cpp2;
       
  1270     const char **p;
       
  1271   
       
  1272     for (cpp2 = cpp = environ; *cpp; cpp++) {
       
  1273 	int reject_it = 0;
       
  1274 
       
  1275 	for(p = reject; *p; p++)
       
  1276 	    if(strncmp(*cpp, *p, strlen(*p)) == 0) {
       
  1277 		reject_it = 1;
       
  1278 		break;
       
  1279 	    }
       
  1280 	if (reject_it)
       
  1281 	    continue;
       
  1282 
       
  1283 	for(p = accept; *p; p++)
       
  1284 	    if(strncmp(*cpp, *p, strlen(*p)) == 0)
       
  1285 		break;
       
  1286 	if(*p != NULL)
       
  1287 	    *cpp2++ = *cpp;
       
  1288     }
       
  1289     *cpp2 = NULL;
       
  1290 }
       
  1291 #endif
       
  1292 
       
  1293 struct arg_val {
       
  1294     int size;
       
  1295     int argc;
       
  1296     const char **argv;
       
  1297 };
       
  1298 
       
  1299 #ifndef __SYMBIAN32__
       
  1300 static void addarg(struct arg_val*, const char*);
       
  1301 /*
       
  1302  * start_login(host)
       
  1303  *
       
  1304  * Assuming that we are now running as a child processes, this
       
  1305  * function will turn us into the login process.
       
  1306  */
       
  1307 
       
  1308 void
       
  1309 start_login(const char *host, int autologin, char *name)
       
  1310 {
       
  1311     struct arg_val argv;
       
  1312     char *user;
       
  1313     int save_errno;
       
  1314 
       
  1315 #ifdef HAVE_UTMPX_H
       
  1316     int pid = getpid();
       
  1317     struct utmpx utmpx;
       
  1318     char *clean_tty;
       
  1319 
       
  1320     /*
       
  1321      * Create utmp entry for child
       
  1322      */
       
  1323 
       
  1324     clean_tty = clean_ttyname(line);
       
  1325     memset(&utmpx, 0, sizeof(utmpx));
       
  1326     strncpy(utmpx.ut_user,  ".telnet", sizeof(utmpx.ut_user));
       
  1327     strncpy(utmpx.ut_line,  clean_tty, sizeof(utmpx.ut_line));
       
  1328 #ifdef HAVE_STRUCT_UTMP_UT_ID
       
  1329     strncpy(utmpx.ut_id, make_id(clean_tty), sizeof(utmpx.ut_id));
       
  1330 #endif
       
  1331     utmpx.ut_pid = pid;
       
  1332 	
       
  1333     utmpx.ut_type = LOGIN_PROCESS;
       
  1334 
       
  1335     gettimeofday (&utmpx.ut_tv, NULL);
       
  1336     if (pututxline(&utmpx) == NULL)
       
  1337 	fatal(net, "pututxline failed");
       
  1338 #endif
       
  1339 
       
  1340     scrub_env();
       
  1341 	
       
  1342     /*
       
  1343      * -h : pass on name of host.
       
  1344      *		WARNING:  -h is accepted by login if and only if
       
  1345      *			getuid() == 0.
       
  1346      * -p : don't clobber the environment (so terminal type stays set).
       
  1347      *
       
  1348      * -f : force this login, he has already been authenticated
       
  1349      */
       
  1350 
       
  1351     /* init argv structure */ 
       
  1352     argv.size=0;
       
  1353     argv.argc=0;
       
  1354     argv.argv=malloc(0); /*so we can call realloc later */
       
  1355     addarg(&argv, "login");
       
  1356     addarg(&argv, "-h");
       
  1357     addarg(&argv, host);
       
  1358     addarg(&argv, "-p");
       
  1359     if(name[0])
       
  1360 	user = name;
       
  1361     else
       
  1362 	user = getenv("USER");
       
  1363 #ifdef AUTHENTICATION
       
  1364     if (auth_level < 0 || autologin != AUTH_VALID) {
       
  1365 	if(!no_warn) {
       
  1366 	    printf("User not authenticated. ");
       
  1367 	    if (require_otp)
       
  1368 		printf("Using one-time password\r\n");
       
  1369 	    else
       
  1370 		printf("Using plaintext username and password\r\n");
       
  1371 	}
       
  1372 	if (require_otp) {
       
  1373 	    addarg(&argv, "-a");
       
  1374 	    addarg(&argv, "otp");
       
  1375 	}
       
  1376 	if(log_unauth) 
       
  1377 	    syslog(LOG_INFO, "unauthenticated access from %s (%s)", 
       
  1378 		   host, user ? user : "unknown user");
       
  1379     }
       
  1380     if (auth_level >= 0 && autologin == AUTH_VALID)
       
  1381 	addarg(&argv, "-f");
       
  1382 #endif
       
  1383     if(user){
       
  1384 	addarg(&argv, "--");
       
  1385 	addarg(&argv, strdup(user));
       
  1386     }
       
  1387     if (getenv("USER")) {
       
  1388 	/*
       
  1389 	 * Assume that login will set the USER variable
       
  1390 	 * correctly.  For SysV systems, this means that
       
  1391 	 * USER will no longer be set, just LOGNAME by
       
  1392 	 * login.  (The problem is that if the auto-login
       
  1393 	 * fails, and the user then specifies a different
       
  1394 	 * account name, he can get logged in with both
       
  1395 	 * LOGNAME and USER in his environment, but the
       
  1396 	 * USER value will be wrong.
       
  1397 	 */
       
  1398 	unsetenv("USER");
       
  1399     }
       
  1400     closelog();
       
  1401     /*
       
  1402      * This sleep(1) is in here so that telnetd can
       
  1403      * finish up with the tty.  There's a race condition
       
  1404      * the login banner message gets lost...
       
  1405      */
       
  1406     sleep(1);
       
  1407 
       
  1408     execv(new_login, argv.argv);
       
  1409     save_errno = errno;
       
  1410 #ifndef __SYMBIAN32__    
       
  1411     syslog(LOG_ERR, "%s: %m\n", new_login);
       
  1412 #endif    
       
  1413     fatalperror_errno(net, new_login, save_errno);
       
  1414     /*NOTREACHED*/
       
  1415 }
       
  1416 
       
  1417 static void
       
  1418 addarg(struct arg_val *argv, const char *val)
       
  1419 {
       
  1420     if(argv->size <= argv->argc+1) {
       
  1421 	argv->argv = realloc(argv->argv, sizeof(char*) * (argv->size + 10));
       
  1422 	if (argv->argv == NULL)
       
  1423 	    fatal (net, "realloc: out of memory");
       
  1424 	argv->size+=10;
       
  1425     }
       
  1426     argv->argv[argv->argc++] = val;
       
  1427     argv->argv[argv->argc]   = NULL;
       
  1428 }
       
  1429 #endif //__SYMBIAN32__
       
  1430 
       
  1431 /*
       
  1432  * rmut()
       
  1433  *
       
  1434  * This is the function called by cleanup() to
       
  1435  * remove the utmp entry for this person.
       
  1436  */
       
  1437 
       
  1438 #ifdef HAVE_UTMPX_H
       
  1439 static void
       
  1440 rmut(void)
       
  1441 {
       
  1442     struct utmpx utmpx, *non_save_utxp;
       
  1443     char *clean_tty = clean_ttyname(line);
       
  1444 
       
  1445     /*
       
  1446      * This updates the utmpx and utmp entries and make a wtmp/x entry
       
  1447      */
       
  1448 
       
  1449     setutxent();
       
  1450     memset(&utmpx, 0, sizeof(utmpx));
       
  1451     strncpy(utmpx.ut_line, clean_tty, sizeof(utmpx.ut_line));
       
  1452     utmpx.ut_type = LOGIN_PROCESS;
       
  1453     non_save_utxp = getutxline(&utmpx);
       
  1454     if (non_save_utxp) {
       
  1455 	struct utmpx *utxp;
       
  1456 	char user0;
       
  1457 
       
  1458 	utxp = malloc(sizeof(struct utmpx));
       
  1459 	*utxp = *non_save_utxp;
       
  1460 	user0 = utxp->ut_user[0];
       
  1461 	utxp->ut_user[0] = '\0';
       
  1462 	utxp->ut_type = DEAD_PROCESS;
       
  1463 #ifdef HAVE_STRUCT_UTMPX_UT_EXIT
       
  1464 #ifdef _STRUCT___EXIT_STATUS
       
  1465 	utxp->ut_exit.__e_termination = 0;
       
  1466 	utxp->ut_exit.__e_exit = 0;
       
  1467 #elif defined(__osf__) /* XXX */
       
  1468 	utxp->ut_exit.ut_termination = 0;
       
  1469 	utxp->ut_exit.ut_exit = 0;
       
  1470 #else	
       
  1471 	utxp->ut_exit.e_termination = 0;
       
  1472 	utxp->ut_exit.e_exit = 0;
       
  1473 #endif
       
  1474 #endif
       
  1475 	gettimeofday(&utxp->ut_tv, NULL);
       
  1476 	pututxline(utxp);
       
  1477 #ifdef WTMPX_FILE
       
  1478 	utxp->ut_user[0] = user0;
       
  1479 	updwtmpx(WTMPX_FILE, utxp);
       
  1480 #elif defined(WTMP_FILE)
       
  1481 	/* This is a strange system with a utmpx and a wtmp! */
       
  1482 	{
       
  1483 	  int f = open(wtmpf, O_WRONLY|O_APPEND);
       
  1484 	  struct utmp wtmp;
       
  1485 	  if (f >= 0) {
       
  1486 	    strncpy(wtmp.ut_line,  clean_tty, sizeof(wtmp.ut_line));
       
  1487 	    strncpy(wtmp.ut_name,  "", sizeof(wtmp.ut_name));
       
  1488 #ifdef HAVE_STRUCT_UTMP_UT_HOST
       
  1489 	    strncpy(wtmp.ut_host,  "", sizeof(wtmp.ut_host));
       
  1490 #endif
       
  1491 	    wtmp.ut_time = time(NULL);
       
  1492 	    write(f, &wtmp, sizeof(wtmp));
       
  1493 	    close(f);
       
  1494 	  }
       
  1495 	}
       
  1496 #endif
       
  1497 	free (utxp);
       
  1498     }
       
  1499     endutxent();
       
  1500 }  /* end of rmut */
       
  1501 #endif
       
  1502 
       
  1503 #if !defined(HAVE_UTMPX_H) && !(defined(_CRAY) || defined(__hpux)) && BSD <= 43
       
  1504 static void
       
  1505 rmut(void)
       
  1506 {
       
  1507     int f;
       
  1508     int found = 0;
       
  1509     struct utmp *u, *utmp;
       
  1510     int nutmp;
       
  1511     struct stat statbf;
       
  1512     char *clean_tty = clean_ttyname(line);
       
  1513 
       
  1514     f = open(utmpf, O_RDWR);
       
  1515     if (f >= 0) {
       
  1516 	fstat(f, &statbf);
       
  1517 	utmp = (struct utmp *)malloc((unsigned)statbf.st_size);
       
  1518 	if (!utmp)
       
  1519 	    syslog(LOG_ERR, "utmp malloc failed");
       
  1520 	if (statbf.st_size && utmp) {
       
  1521 	    nutmp = read(f, utmp, (int)statbf.st_size);
       
  1522 	    nutmp /= sizeof(struct utmp);
       
  1523 
       
  1524 	    for (u = utmp ; u < &utmp[nutmp] ; u++) {
       
  1525 		if (strncmp(u->ut_line,
       
  1526 			    clean_tty,
       
  1527 			    sizeof(u->ut_line)) ||
       
  1528 		    u->ut_name[0]==0)
       
  1529 		    continue;
       
  1530 		lseek(f, ((long)u)-((long)utmp), L_SET);
       
  1531 		strncpy(u->ut_name,  "", sizeof(u->ut_name));
       
  1532 #ifdef HAVE_STRUCT_UTMP_UT_HOST
       
  1533 		strncpy(u->ut_host,  "", sizeof(u->ut_host));
       
  1534 #endif
       
  1535 		u->ut_time = time(NULL);
       
  1536 		write(f, u, sizeof(wtmp));
       
  1537 		found++;
       
  1538 	    }
       
  1539 	}
       
  1540 	close(f);
       
  1541     }
       
  1542     if (found) {
       
  1543 	f = open(wtmpf, O_WRONLY|O_APPEND);
       
  1544 	if (f >= 0) {
       
  1545 	    strncpy(wtmp.ut_line,  clean_tty, sizeof(wtmp.ut_line));
       
  1546 	    strncpy(wtmp.ut_name,  "", sizeof(wtmp.ut_name));
       
  1547 #ifdef HAVE_STRUCT_UTMP_UT_HOST
       
  1548 	    strncpy(wtmp.ut_host,  "", sizeof(wtmp.ut_host));
       
  1549 #endif
       
  1550 	    wtmp.ut_time = time(NULL);
       
  1551 	    write(f, &wtmp, sizeof(wtmp));
       
  1552 	    close(f);
       
  1553 	}
       
  1554     }
       
  1555     chmod(line, 0666);
       
  1556     chown(line, 0, 0);
       
  1557     line[strlen("/dev/")] = 'p';
       
  1558     chmod(line, 0666);
       
  1559     chown(line, 0, 0);
       
  1560 }  /* end of rmut */
       
  1561 #endif	/* CRAY */
       
  1562 
       
  1563 #if defined(__hpux) && !defined(HAVE_UTMPX_H)
       
  1564 static void
       
  1565 rmut (char *line)
       
  1566 {
       
  1567     struct utmp utmp;
       
  1568     struct utmp *utptr;
       
  1569     int fd;			/* for /etc/wtmp */
       
  1570 
       
  1571     utmp.ut_type = USER_PROCESS;
       
  1572     strncpy(utmp.ut_line, clean_ttyname(line), sizeof(utmp.ut_line));
       
  1573     setutent();
       
  1574     utptr = getutline(&utmp);
       
  1575     /* write it out only if it exists */
       
  1576     if (utptr) {
       
  1577 	utptr->ut_type = DEAD_PROCESS;
       
  1578 	utptr->ut_time = time(NULL);
       
  1579 	pututline(utptr);
       
  1580 	/* set wtmp entry if wtmp file exists */
       
  1581 	if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) {
       
  1582 	    write(fd, utptr, sizeof(utmp));
       
  1583 	    close(fd);
       
  1584 	}
       
  1585     }
       
  1586     endutent();
       
  1587 
       
  1588     chmod(line, 0666);
       
  1589     chown(line, 0, 0);
       
  1590     line[14] = line[13];
       
  1591     line[13] = line[12];
       
  1592     line[8] = 'm';
       
  1593     line[9] = '/';
       
  1594     line[10] = 'p';
       
  1595     line[11] = 't';
       
  1596     line[12] = 'y';
       
  1597     chmod(line, 0666);
       
  1598     chown(line, 0, 0);
       
  1599 }
       
  1600 #endif
       
  1601 
       
  1602 /*
       
  1603  * cleanup()
       
  1604  *
       
  1605  * This is the routine to call when we are all through, to
       
  1606  * clean up anything that needs to be cleaned up.
       
  1607  */
       
  1608 
       
  1609 #ifdef PARENT_DOES_UTMP
       
  1610 
       
  1611 void
       
  1612 cleanup(int sig)
       
  1613 {
       
  1614 #ifdef _CRAY
       
  1615     static int incleanup = 0;
       
  1616     int t;
       
  1617     int child_status; /* status of child process as returned by waitpid */
       
  1618     int flags = WNOHANG|WUNTRACED;
       
  1619     
       
  1620     /*
       
  1621      * 1: Pick up the zombie, if we are being called
       
  1622      *    as the signal handler.
       
  1623      * 2: If we are a nested cleanup(), return.
       
  1624      * 3: Try to clean up TMPDIR.
       
  1625      * 4: Fill in utmp with shutdown of process.
       
  1626      * 5: Close down the network and pty connections.
       
  1627      * 6: Finish up the TMPDIR cleanup, if needed.
       
  1628      */
       
  1629     if (sig == SIGCHLD) {
       
  1630 	while (waitpid(-1, &child_status, flags) > 0)
       
  1631 	    ;	/* VOID */
       
  1632 	/* Check if the child process was stopped
       
  1633 	 * rather than exited.  We want cleanup only if
       
  1634 	 * the child has died.
       
  1635 	 */
       
  1636 	if (WIFSTOPPED(child_status)) {
       
  1637 	    return;
       
  1638 	}
       
  1639     }
       
  1640     t = sigblock(sigmask(SIGCHLD));
       
  1641     if (incleanup) {
       
  1642 	sigsetmask(t);
       
  1643 	return;
       
  1644     }
       
  1645     incleanup = 1;
       
  1646     sigsetmask(t);
       
  1647     
       
  1648     t = cleantmp(&wtmp);
       
  1649     setutent();	/* just to make sure */
       
  1650 #endif /* CRAY */
       
  1651     rmut(line);
       
  1652     close(ourpty);
       
  1653     shutdown(net, 2);
       
  1654 #ifdef _CRAY
       
  1655     if (t == 0)
       
  1656 	cleantmp(&wtmp);
       
  1657 #endif /* CRAY */
       
  1658     exit(1);
       
  1659 }
       
  1660 
       
  1661 #else /* PARENT_DOES_UTMP */
       
  1662 
       
  1663 void
       
  1664 cleanup(int sig)
       
  1665 {
       
  1666 #if defined(HAVE_UTMPX_H) || !defined(HAVE_LOGWTMP)
       
  1667 #ifndef __SYMBIAN32__
       
  1668    rmut(); 
       
  1669 #endif   
       
  1670 #ifdef HAVE_VHANGUP
       
  1671 #ifndef __sgi
       
  1672     vhangup(); /* XXX */
       
  1673 #endif
       
  1674 #endif
       
  1675 #else
       
  1676     char *p;
       
  1677     
       
  1678     p = line + sizeof("/dev/") - 1;
       
  1679     if (logout(p))
       
  1680 	logwtmp(p, "", "");
       
  1681     chmod(line, 0666);
       
  1682     chown(line, 0, 0);
       
  1683     *p = 'p';
       
  1684     chmod(line, 0666);
       
  1685     chown(line, 0, 0);
       
  1686 #endif
       
  1687     shutdown(net, 2);
       
  1688     exit(1);
       
  1689 }
       
  1690 
       
  1691 #endif /* PARENT_DOES_UTMP */
       
  1692 
       
  1693 #ifdef PARENT_DOES_UTMP
       
  1694 /*
       
  1695  * _utmp_sig_rcv
       
  1696  * utmp_sig_init
       
  1697  * utmp_sig_wait
       
  1698  *	These three functions are used to coordinate the handling of
       
  1699  *	the utmp file between the server and the soon-to-be-login shell.
       
  1700  *	The server actually creates the utmp structure, the child calls
       
  1701  *	utmp_sig_wait(), until the server calls utmp_sig_notify() and
       
  1702  *	signals the future-login shell to proceed.
       
  1703  */
       
  1704 static int caught=0;		/* NZ when signal intercepted */
       
  1705 static void (*func)();		/* address of previous handler */
       
  1706 
       
  1707 void
       
  1708 _utmp_sig_rcv(sig)
       
  1709      int sig;
       
  1710 {
       
  1711     caught = 1;
       
  1712     signal(SIGUSR1, func);
       
  1713 }
       
  1714 
       
  1715 void
       
  1716 utmp_sig_init()
       
  1717 {
       
  1718     /*
       
  1719      * register signal handler for UTMP creation
       
  1720      */
       
  1721     if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)
       
  1722 	fatalperror(net, "telnetd/signal");
       
  1723 }
       
  1724 
       
  1725 void
       
  1726 utmp_sig_reset()
       
  1727 {
       
  1728     signal(SIGUSR1, func);	/* reset handler to default */
       
  1729 }
       
  1730 
       
  1731 # ifdef __hpux
       
  1732 # define sigoff() /* do nothing */
       
  1733 # define sigon() /* do nothing */
       
  1734 # endif
       
  1735 
       
  1736 void
       
  1737 utmp_sig_wait()
       
  1738 {
       
  1739     /*
       
  1740      * Wait for parent to write our utmp entry.
       
  1741 	 */
       
  1742     sigoff();
       
  1743     while (caught == 0) {
       
  1744 	pause();	/* wait until we get a signal (sigon) */
       
  1745 	sigoff();	/* turn off signals while we check caught */
       
  1746     }
       
  1747     sigon();		/* turn on signals again */
       
  1748 }
       
  1749 
       
  1750 void
       
  1751 utmp_sig_notify(pid)
       
  1752 {
       
  1753     kill(pid, SIGUSR1);
       
  1754 }
       
  1755 
       
  1756 #ifdef _CRAY
       
  1757 static int gotsigjob = 0;
       
  1758 
       
  1759 	/*ARGSUSED*/
       
  1760 void
       
  1761 sigjob(sig)
       
  1762      int sig;
       
  1763 {
       
  1764     int jid;
       
  1765     struct jobtemp *jp;
       
  1766 
       
  1767     while ((jid = waitjob(NULL)) != -1) {
       
  1768 	if (jid == 0) {
       
  1769 	    return;
       
  1770 	}
       
  1771 	gotsigjob++;
       
  1772 	jobend(jid, NULL, NULL);
       
  1773     }
       
  1774 }
       
  1775 
       
  1776 /*
       
  1777  *	jid_getutid:
       
  1778  *		called by jobend() before calling cleantmp()
       
  1779  *		to find the correct $TMPDIR to cleanup.
       
  1780  */
       
  1781 
       
  1782 struct utmp *
       
  1783 jid_getutid(jid)
       
  1784      int jid;
       
  1785 {
       
  1786     struct utmp *cur = NULL;
       
  1787 
       
  1788     setutent();	/* just to make sure */
       
  1789     while (cur = getutent()) {
       
  1790 	if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) {
       
  1791 	    return(cur);
       
  1792 	}
       
  1793     }
       
  1794 
       
  1795     return(0);
       
  1796 }
       
  1797 
       
  1798 /*
       
  1799  * Clean up the TMPDIR that login created.
       
  1800  * The first time this is called we pick up the info
       
  1801  * from the utmp.  If the job has already gone away,
       
  1802  * then we'll clean up and be done.  If not, then
       
  1803  * when this is called the second time it will wait
       
  1804  * for the signal that the job is done.
       
  1805  */
       
  1806 int
       
  1807 cleantmp(wtp)
       
  1808      struct utmp *wtp;
       
  1809 {
       
  1810     struct utmp *utp;
       
  1811     static int first = 1;
       
  1812     int mask, omask, ret;
       
  1813     extern struct utmp *getutid (const struct utmp *_Id);
       
  1814 
       
  1815 
       
  1816     mask = sigmask(WJSIGNAL);
       
  1817 
       
  1818     if (first == 0) {
       
  1819 	omask = sigblock(mask);
       
  1820 	while (gotsigjob == 0)
       
  1821 	    sigpause(omask);
       
  1822 	return(1);
       
  1823     }
       
  1824     first = 0;
       
  1825     setutent();	/* just to make sure */
       
  1826 
       
  1827     utp = getutid(wtp);
       
  1828     if (utp == 0) {
       
  1829 	syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
       
  1830 	return(-1);
       
  1831     }
       
  1832     /*
       
  1833      * Nothing to clean up if the user shell was never started.
       
  1834      */
       
  1835     if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0)
       
  1836 	return(1);
       
  1837 
       
  1838     /*
       
  1839      * Block the WJSIGNAL while we are in jobend().
       
  1840      */
       
  1841     omask = sigblock(mask);
       
  1842     ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user);
       
  1843     sigsetmask(omask);
       
  1844     return(ret);
       
  1845 }
       
  1846 
       
  1847 int
       
  1848 jobend(jid, path, user)
       
  1849      int jid;
       
  1850      char *path;
       
  1851      char *user;
       
  1852 {
       
  1853     static int saved_jid = 0;
       
  1854     static int pty_saved_jid = 0;
       
  1855     static char saved_path[sizeof(wtmp.ut_tpath)+1];
       
  1856     static char saved_user[sizeof(wtmp.ut_user)+1];
       
  1857 
       
  1858     /*
       
  1859      * this little piece of code comes into play
       
  1860      * only when ptyreconnect is used to reconnect
       
  1861      * to an previous session.
       
  1862      *
       
  1863      * this is the only time when the
       
  1864      * "saved_jid != jid" code is executed.
       
  1865      */
       
  1866 
       
  1867     if ( saved_jid && saved_jid != jid ) {
       
  1868 	if (!path) {	/* called from signal handler */
       
  1869 	    pty_saved_jid = jid;
       
  1870 	} else {
       
  1871 	    pty_saved_jid = saved_jid;
       
  1872 	}
       
  1873     }
       
  1874 
       
  1875     if (path) {
       
  1876 	strncpy(saved_path, path, sizeof(wtmp.ut_tpath));
       
  1877 	strncpy(saved_user, user, sizeof(wtmp.ut_user));
       
  1878 	saved_path[sizeof(saved_path)] = '\0';
       
  1879 	saved_user[sizeof(saved_user)] = '\0';
       
  1880     }
       
  1881     if (saved_jid == 0) {
       
  1882 	saved_jid = jid;
       
  1883 	return(0);
       
  1884     }
       
  1885 
       
  1886     /* if the jid has changed, get the correct entry from the utmp file */
       
  1887 
       
  1888     if ( saved_jid != jid ) {
       
  1889 	struct utmp *utp = NULL;
       
  1890 	struct utmp *jid_getutid();
       
  1891 
       
  1892 	utp = jid_getutid(pty_saved_jid);
       
  1893 
       
  1894 	if (utp == 0) {
       
  1895 	    syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");
       
  1896 	    return(-1);
       
  1897 	}
       
  1898 
       
  1899 	cleantmpdir(jid, utp->ut_tpath, utp->ut_user);
       
  1900 	return(1);
       
  1901     }
       
  1902 
       
  1903     cleantmpdir(jid, saved_path, saved_user);
       
  1904     return(1);
       
  1905 }
       
  1906 
       
  1907 /*
       
  1908  * Fork a child process to clean up the TMPDIR
       
  1909  */
       
  1910 cleantmpdir(jid, tpath, user)
       
  1911      int jid;
       
  1912      char *tpath;
       
  1913      char *user;
       
  1914 {
       
  1915     switch(fork()) {
       
  1916     case -1:
       
  1917 	syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n",
       
  1918 	       tpath);
       
  1919 	break;
       
  1920     case 0:
       
  1921 	execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0);
       
  1922 	syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n",
       
  1923 	       tpath, CLEANTMPCMD);
       
  1924 	exit(1);
       
  1925     default:
       
  1926 	/*
       
  1927 	 * Forget about child.  We will exit, and
       
  1928 	 * /etc/init will pick it up.
       
  1929 	 */
       
  1930 	break;
       
  1931     }
       
  1932 }
       
  1933 #endif /* CRAY */
       
  1934 #endif	/* defined(PARENT_DOES_UTMP) */