home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume26 / screen-3.5 / part06 / screen.c < prev   
C/C++ Source or Header  |  1993-07-25  |  51KB  |  2,347 lines

  1. /* Copyright (c) 1993
  2.  *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  3.  *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  4.  * Copyright (c) 1987 Oliver Laumann
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2, or (at your option)
  9.  * any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program (see the file COPYING); if not, write to the
  18.  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  ****************************************************************
  21.  */
  22.  
  23. #include "rcs.h"
  24. RCS_ID("$Id: screen.c,v 1.9 1993/07/09 12:07:49 jnweiger Exp $ FAU")
  25.  
  26.  
  27. #include <ctype.h>
  28. #ifdef __sgi
  29. # include <stdio.h> /* needed before pwd.h to avoid ansi compiler whining */
  30. #endif /* __sgi */
  31. #include <pwd.h>
  32. #include <fcntl.h>
  33. #ifdef sgi
  34. # include <sys/sysmacros.h>
  35. #endif /* sgi */
  36. #if !defined(sun) && !defined(B43) && !defined(ISC) && !defined(pyr) && !defined(_CX_UX)
  37. # include <time.h>
  38. #endif
  39. #include <sys/time.h>
  40. #if defined(M_XENIX) || defined(M_UNIX)
  41. #include <sys/select.h> /* for timeval */
  42. #endif
  43. #include <sys/types.h>
  44. #ifdef ISC
  45. # include <sys/bsdtypes.h>
  46. #endif
  47. #include <sys/stat.h>
  48. #ifndef sgi
  49. # include <sys/file.h>
  50. #endif /* sgi */
  51. #ifndef sun
  52. # include <sys/ioctl.h>
  53. #endif /* sun */
  54.  
  55. #include <signal.h>
  56.  
  57. #include "config.h"
  58.  
  59. #ifdef SHADOWPW
  60. # include <shadow.h>
  61. #endif /* SHADOWPW */
  62.  
  63. #ifdef SVR4
  64. # include <sys/stropts.h>
  65. #endif
  66.  
  67. #ifdef SYSV
  68. # include <sys/utsname.h>
  69. #endif
  70.  
  71. #if defined(sequent) || defined(SVR4)
  72. # include <sys/resource.h>
  73. #endif /* sequent || SVR4 */
  74.  
  75. #ifdef ISC
  76. # include <sys/tty.h>
  77. # include <sys/sioctl.h>
  78. # include <sys/pty.h>
  79. #endif /* ISC */
  80.  
  81. #include "screen.h"
  82.  
  83. #include "patchlevel.h"
  84.  
  85. #if defined(xelos) || defined(m68k) || defined(M_XENIX)
  86.  struct passwd *getpwuid __P((uid_t));
  87.  struct passwd *getpwnam __P((char *));
  88. #endif
  89.  
  90. #ifdef USEVARARGS
  91. # if defined(__STDC__)
  92. #  include <stdarg.h>
  93. # else
  94. #  include <varargs.h>
  95. # endif
  96. #endif
  97.  
  98. #if defined(_SEQUENT_) 
  99. /* for the FD.. stuff */
  100. # include <sys/select.h>
  101. #endif /* _SEQUENT_ */
  102.  
  103. #ifndef FD_SET
  104. typedef struct fd_set
  105. {
  106.   int fd_bits[1];
  107. }      fd_set;
  108. # define FD_ZERO(fd) ((fd)->fd_bits[0] = 0)
  109. # define FD_SET(b, fd) ((fd)->fd_bits[0] |= 1 << (b))
  110. # define FD_ISSET(b, fd) ((fd)->fd_bits[0] & 1 << (b))
  111. # define FD_SETSIZE 32
  112. #endif
  113.  
  114.  
  115. #ifdef DEBUG
  116. FILE *dfp;
  117. #endif
  118.  
  119.  
  120. extern char *blank, *null, Term[], screenterm[], **environ, Termcap[];
  121. int force_vt = 1, assume_LP = 0;
  122. int VBellWait, MsgWait, MsgMinWait, SilenceWait;
  123.  
  124. extern struct display *displays, *display; 
  125. extern struct layer BlankLayer;
  126.  
  127. /* tty.c */
  128. extern int intrc;
  129.  
  130.  
  131. extern int use_hardstatus;
  132. #ifdef COPY_PASTE
  133. extern char mark_key_tab[];
  134. #endif
  135. extern char version[];
  136. extern char DefaultShell[];
  137.  
  138.  
  139. char *ShellProg;
  140. char *ShellArgs[2];
  141.  
  142. extern struct NewWindow nwin_undef, nwin_default, nwin_options;
  143.  
  144. static char *MakeWinMsg __P((char *, int));
  145. static void  SigChldHandler __P((void));
  146. static sig_t SigChld __P(SIGPROTOARG);
  147. static sig_t SigInt __P(SIGPROTOARG);
  148. static sig_t CoreDump __P((int));
  149. static void  DoWait __P((void));
  150.  
  151.  
  152. #ifdef PASSWORD
  153. extern char Password[];
  154. #endif
  155.  
  156.  
  157. /* the attacher */
  158. struct passwd *ppp;
  159. char *attach_tty;
  160. char *attach_term;
  161. char *LoginName;
  162. struct mode attach_Mode;
  163.  
  164.  
  165. #ifdef SOCKDIR
  166. char *SockDir = SOCKDIR;
  167. #else
  168. char *SockDir = ".iscreen";
  169. #endif
  170. extern char SockPath[], *SockNamePtr, *SockName;
  171. int ServerSocket = -1;
  172. char **NewEnv = NULL;
  173.  
  174. char *RcFileName = NULL;
  175. extern char Esc;
  176. char *home;
  177.  
  178. char *screenlogdir = NULL;
  179. char *hardcopydir = NULL;
  180. char *BellString;
  181. char *VisualBellString;
  182. char *ActivityString;
  183. #ifdef COPY_PASTE
  184. char *BufferFile;
  185. #endif
  186. #ifdef POW_DETACH
  187. char *PowDetachString;
  188. #endif
  189. int auto_detach = 1;
  190. int iflag, rflag, dflag, lsflag, quietflag, wipeflag, xflag;
  191. int adaptflag;
  192.  
  193. time_t Now;
  194.  
  195. #ifdef MULTIUSER
  196. char *multi;
  197. char *multi_home;
  198. int multi_uid;
  199. int own_uid;
  200. int multiattach;
  201. int tty_mode;
  202. int tty_oldmode = -1;
  203. #endif
  204.  
  205. char HostName[MAXSTR];
  206. int MasterPid;
  207. int real_uid, real_gid, eff_uid, eff_gid;
  208. int default_startup;
  209. int slowpaste;
  210.  
  211. #ifdef NETHACK
  212. int nethackflag = 0;
  213. #endif
  214.  
  215.  
  216. struct win *fore = NULL;
  217. struct win *windows = NULL;
  218. struct win *console_window;
  219.  
  220.  
  221. /*
  222.  * Do this last
  223.  */
  224. #include "extern.h"
  225.  
  226. /*
  227.  * XXX: Missing system header files.
  228.  */
  229. #ifdef USEVARARGS
  230. # ifndef VPRNT_DECLARED
  231. int vsprintf __P((char *, char *, va_list));
  232. # endif /* VPRNT_DECLARED */
  233. #endif
  234. #ifndef SELECT_DECLARED
  235. int select __P((int, fd_set *, fd_set *, fd_set *, const struct timeval *));
  236. #endif
  237.  
  238. #ifdef NETHACK
  239. char strnomem[] = "Who was that Maude person anyway?";
  240. #else
  241. char strnomem[] = "Out of memory.";
  242. #endif
  243.  
  244.  
  245. static int InterruptPlease = 0;
  246. static int GotSigChld;
  247.  
  248.  
  249. static void
  250. mkfdsets(rp, wp)
  251. fd_set *rp, *wp;
  252. {
  253.   register struct win *p;
  254.  
  255.   FD_ZERO(rp);
  256.   FD_ZERO(wp);
  257.   for (display = displays; display; display = display->_d_next)
  258.     {
  259.       if (d_obufp != d_obuf)
  260.     FD_SET(d_userfd, wp);
  261.  
  262.       FD_SET(d_userfd, rp);    /* Do that always */
  263.  
  264.       /* read from terminal if there is room in the destination buffer
  265.        *
  266.        * Removed, so we can always input a command sequence
  267.        *
  268.        * if (d_fore == 0)
  269.        *   continue;
  270.        * if (W_UWP(d_fore))
  271.        *   {
  272.        *      check pseudowin buffer
  273.        *      if (d_fore->w_pwin->p_inlen < sizeof(d_fore->w_pwin->p_inbuf))
  274.        *      FD_SET(d_userfd, rp);
  275.        *   }
  276.        * else
  277.        *   {
  278.        *     check window buffer
  279.        *     if (d_fore->w_inlen < sizeof(d_fore->w_inbuf))
  280.        *     FD_SET(d_userfd, rp);
  281.        *   }
  282.        */
  283.     }
  284.   for (p = windows; p; p = p->w_next)
  285.     {
  286. #ifdef COPY_PASTE
  287.       if (p->w_pastelen)
  288.         {
  289.       /* paste to win/pseudo */
  290. # ifdef PSEUDOS
  291.       FD_SET(W_UWP(p) ? p->w_pwin->p_ptyfd : p->w_ptyfd, wp);
  292. # else
  293.       FD_SET(p->w_ptyfd, wp);
  294. # endif
  295.     }
  296. #endif
  297.       /* query window buffer */
  298.       if (p->w_inlen > 0)
  299.     FD_SET(p->w_ptyfd, wp);
  300. #ifdef PSEUDOS
  301.       /* query pseudowin buffer */
  302.       if (p->w_pwin && p->w_pwin->p_inlen > 0)
  303.         FD_SET(p->w_pwin->p_ptyfd, wp);
  304. #endif
  305.  
  306.       display = p->w_display;
  307.       if (p->w_active && d_status && !d_status_bell && !(use_hardstatus && HS))
  308.     continue;
  309.       if (p->w_outlen > 0)
  310.     continue;
  311.       if (p->w_lay->l_block)
  312.     continue;
  313.     /* 
  314.      * Don't accept input from window or pseudowin if there is to much 
  315.      * output pending on display .
  316.      */
  317.       if (p->w_active && (d_obufp - d_obuf) > d_obufmax)
  318.     {
  319.       debug1("too much output pending, window %d\n", p->w_number);
  320.       continue;  
  321.     }
  322. #ifdef PSEUDOS
  323.       if (W_RW(p))
  324.     {
  325.       /* Check free space if we stuff window output in pseudo */
  326.       if (p->w_pwin && W_WTOP(p) && (p->w_pwin->p_inlen >= sizeof(p->w_pwin->p_inbuf)))
  327.         {
  328.           debug2("pseudowin %d buffer full (%d bytes)\n", p->w_number, p->w_pwin->p_inlen);
  329.         }
  330.       else
  331.             FD_SET(p->w_ptyfd, rp);
  332.     }
  333.       if (W_RP(p))
  334.     {
  335.       /* Check free space if we stuff pseudo output in window */
  336.       if (W_PTOW(p) && p->w_inlen >= sizeof(p->w_inbuf))
  337.         {
  338.           debug2("window %d buffer full (%d bytes)\n", p->w_number, p->w_inlen);
  339.         }
  340.       else
  341.             FD_SET(p->w_pwin->p_ptyfd, rp);
  342.     }
  343. #else /* PSEUDOS */
  344.       FD_SET(p->w_ptyfd, rp);
  345. #endif /* PSEUDOS */
  346.     }
  347.   FD_SET(ServerSocket, rp);
  348. }
  349.  
  350. void
  351. main(ac, av)
  352. int ac;
  353. char **av;
  354. {
  355.   register int n, len;
  356.   register struct win *p;
  357.   char *ap;
  358.   char *av0;
  359.   char socknamebuf[2 * MAXSTR];
  360.   fd_set r, w;
  361.   int mflag = 0;
  362.   struct timeval tv;
  363.   int nsel;
  364.   char buf[IOSIZE], *myname = (ac == 0) ? "screen" : av[0];
  365.   struct stat st;
  366.   int buflen, tmp;
  367. #ifdef _MODE_T            /* (jw) */
  368.   mode_t oumask;
  369. #else
  370.   int oumask;
  371. #endif
  372. #ifdef SYSV
  373.   struct utsname utsnam;
  374. #endif
  375.   struct NewWindow nwin;
  376.   int detached = 0;        /* start up detached */
  377.   struct display *ndisplay;
  378. #ifdef MULTIUSER
  379.   char *sockp;
  380. #endif
  381.  
  382.   /*
  383.    *  First, close all unused descriptors
  384.    *  (otherwise, we might have problems with the select() call)
  385.    */
  386.   closeallfiles(0);
  387. #ifdef DEBUG
  388.   (void) mkdir("/tmp/debug", 0777);
  389.   if ((dfp = fopen("/tmp/debug/screen.front", "w")) == NULL)
  390.     dfp = stderr;
  391.   else
  392.     (void) chmod("/tmp/debug/screen.front", 0666);
  393. #endif
  394.   sprintf(version, "%d.%.2d.%.2d%s (%s) %s", REV, VERS,
  395.       PATCHLEVEL, STATE, ORIGIN, DATE);
  396.   debug2("-- screen debug started %s (%s)\n", *av, version);
  397. #ifdef POSIX
  398.   debug("POSIX\n");
  399. #endif
  400. #ifdef TERMIO
  401.   debug("TERMIO\n");
  402. #endif
  403. #ifdef SYSV
  404.   debug("SYSV\n");
  405. #endif
  406. #ifdef SYSVSIGS
  407.   debug("SYSVSIGS\n");
  408. #endif
  409. #ifdef NAMEDPIPE
  410.   debug("NAMEDPIPE\n");
  411. #endif
  412. #if defined(SIGWINCH) && defined(TIOCGWINSZ)
  413.   debug("Window changing enabled\n");
  414. #endif
  415. #ifdef NOREUID
  416.   debug("NOREUID\n");
  417. #endif
  418. #ifdef hpux
  419.   debug("hpux\n");
  420. #endif
  421. #ifdef USEBCOPY
  422.   debug("USEBCOPY\n");
  423. #endif
  424. #ifdef UTMPOK
  425.   debug("UTMPOK\n");
  426. #endif
  427. #ifdef LOADAV
  428.   debug("LOADAV\n");
  429. #endif
  430. #ifdef NETHACK
  431.   debug("NETHACK\n");
  432. #endif
  433. #ifdef TERMINFO
  434.   debug("TERMINFO\n");
  435. #endif
  436. #ifdef SHADOWPW
  437.   debug("SHADOWPW\n");
  438. #endif
  439. #ifdef NAME_MAX
  440.   debug1("NAME_MAX = %d\n", NAME_MAX);
  441. #endif
  442.  
  443.   BellString = SaveStr("Bell in window %");
  444.   VisualBellString = SaveStr("   Wuff,  Wuff!!  ");
  445.   ActivityString = SaveStr("Activity in window %");
  446. #ifdef COPY_PASTE
  447.   BufferFile = SaveStr(DEFAULT_BUFFERFILE);
  448. #endif
  449.   ShellProg = NULL;
  450. #ifdef POW_DETACH
  451.   PowDetachString = 0;
  452. #endif
  453.   default_startup = (ac > 1) ? 0 : 1;
  454.   adaptflag = 0;
  455.   slowpaste = 0;
  456.   VBellWait = VBELLWAIT;
  457.   MsgWait = MSGWAIT;
  458.   MsgMinWait = MSGMINWAIT;
  459.   SilenceWait = SILENCEWAIT;
  460. #ifdef COPY_PASTE
  461.   CompileKeys((char *)NULL, mark_key_tab);
  462. #endif
  463.   nwin = nwin_undef;
  464.   nwin_options = nwin_undef;
  465.  
  466.   av0 = *av;
  467.   /* if this is a login screen, assume -R */
  468.   if (*av0 == '-')
  469.     {
  470.       rflag = 2;
  471. #ifdef MULTI
  472.       xflag = 1;
  473. #endif
  474.       ShellProg = SaveStr(DefaultShell); /* to prevent nasty circles */
  475.     }
  476.   while (ac > 0)
  477.     {
  478.       ap = *++av;
  479.       if (--ac > 0 && *ap == '-')
  480.     {
  481.       switch (ap[1])
  482.         {
  483.         case 'a':
  484.           nwin_options.aflag = 1;
  485.           break;
  486.         case 'A':
  487.           adaptflag = 1;
  488.           break;
  489.         case 'c':
  490.           if (ap[2])
  491.         RcFileName = ap + 2;
  492.           else
  493.         {
  494.           if (--ac == 0)
  495.             exit_with_usage(myname);
  496.           RcFileName = *++av;
  497.         }
  498.           break;
  499.         case 'e':
  500.           if (ap[2])
  501.         ap += 2;
  502.           else
  503.         {
  504.           if (--ac == 0)
  505.             exit_with_usage(myname);
  506.           ap = *++av;
  507.         }
  508.           if (ParseEscape(ap))
  509.         Panic(0, "Two characters are required with -e option.");
  510.           break;
  511.         case 'f':
  512.           switch (ap[2])
  513.         {
  514.         case 'n':
  515.         case '0':
  516.           nwin_options.flowflag = FLOW_NOW * 0;
  517.           break;
  518.         case 'y':
  519.         case '1':
  520.         case '\0':
  521.           nwin_options.flowflag = FLOW_NOW * 1;
  522.           break;
  523.         case 'a':
  524.           nwin_options.flowflag = FLOW_AUTOFLAG;
  525.           break;
  526.         default:
  527.           exit_with_usage(myname);
  528.         }
  529.           break;
  530.             case 'h':
  531.           if (ap[2])
  532.         nwin_options.histheight = atoi(ap + 2);
  533.           else
  534.         {
  535.           if (--ac == 0)
  536.             exit_with_usage(myname);
  537.           nwin_options.histheight = atoi(*++av);
  538.         }
  539.           if (nwin_options.histheight < 0)
  540.         exit_with_usage(myname);
  541.           break;
  542.         case 'i':
  543.           iflag = 1;
  544.           break;
  545.         case 't': /* title is a synonym for AkA */
  546.         case 'k':
  547.           if (ap[2])
  548.         nwin_options.aka = ap + 2;
  549.           else
  550.         {
  551.           if (--ac == 0)
  552.             exit_with_usage(myname);
  553.           nwin_options.aka = *++av;
  554.         }
  555.           break;
  556.         case 'l':
  557.           switch (ap[2])
  558.         {
  559.         case 'n':
  560.         case '0':
  561.           nwin_options.lflag = 0;
  562.           break;
  563.         case 'y':
  564.         case '1':
  565.         case '\0':
  566.           nwin_options.lflag = 1;
  567.           break;
  568.         case 's':
  569.         case 'i':
  570.           lsflag = 1;
  571.           if (ac > 1)
  572.             {
  573.               SockName = *++av;
  574.               ac--;
  575.             }
  576.           break;
  577.         default:
  578.           exit_with_usage(myname);
  579.         }
  580.           break;
  581.         case 'w':
  582.           lsflag = 1;
  583.           wipeflag = 1;
  584.           break;
  585.         case 'L':
  586.           assume_LP = 1;
  587.           break;
  588.         case 'm':
  589.           mflag = 1;
  590.           break;
  591.         case 'O':
  592.           force_vt = 0;
  593.           break;
  594.         case 'T':
  595.               if (ap[2])
  596.         {
  597.           if (strlen(ap+2) < 20)
  598.                     strcpy(screenterm, ap + 2);
  599.         }
  600.               else
  601.                 {
  602.                   if (--ac == 0)
  603.                     exit_with_usage(myname);
  604.           if (strlen(*++av) < 20)
  605.                     strcpy(screenterm, *av);
  606.                 }
  607.           nwin_options.term = screenterm;
  608.               break;
  609.         case 'q':
  610.           quietflag = 1;
  611.           break;
  612.         case 'r':
  613.         case 'R':
  614. #ifdef MULTI
  615.         case 'x':
  616. #endif
  617.           if (ap[2])
  618.         {
  619.           SockName = ap + 2;
  620.           if (ac != 1)
  621.             exit_with_usage(myname);
  622.         }
  623.           else if (ac > 1 && *av[1] != '-')
  624.         {
  625.           SockName = *++av;
  626.           ac--;
  627.         }
  628. #ifdef MULTI
  629.           if (ap[1] == 'x')
  630.         xflag = 1;
  631.           else
  632. #endif
  633.             rflag = (ap[1] == 'r') ? 1 : 2;
  634.           break;
  635. #ifdef REMOTE_DETACH
  636.         case 'd':
  637.           dflag = 1;
  638.           /* FALLTHROUGH */
  639.         case 'D':
  640.           if (!dflag)
  641.         dflag = 2;
  642.           if (ap[2])
  643.         SockName = ap + 2;
  644.           if (ac == 2)
  645.         {
  646.           if (*av[1] != '-')
  647.             {
  648.               SockName = *++av;
  649.               ac--;
  650.             }
  651.         }
  652.           break;
  653. #endif
  654.         case 's':
  655.           if (ap[2])
  656.         {
  657.           if (ShellProg)
  658.             free(ShellProg);
  659.           ShellProg = SaveStr(ap + 2);
  660.         }
  661.           else
  662.         {
  663.           if (--ac == 0)
  664.             exit_with_usage(myname);
  665.           if (ShellProg)
  666.             free(ShellProg);
  667.           ShellProg = SaveStr(*++av);
  668.         }
  669.           debug1("ShellProg: '%s'\n", ShellProg);
  670.           break;
  671.         case 'S':
  672.           if (ap[2])
  673.         SockName = ap + 2;
  674.           else
  675.         {
  676.           if (--ac == 0)
  677.             exit_with_usage(myname);
  678.           SockName = *++av;
  679.           if (!*SockName)
  680.             exit_with_usage(myname);
  681.         }
  682.           break;
  683.         case 'v':
  684.           Panic(0, "Screen version %s", version);
  685.           /* NOTREACHED */
  686.         default:
  687.           exit_with_usage(myname);
  688.         }
  689.     }
  690.       else
  691.     break;
  692.     }
  693.   if (dflag && mflag && SockName && !(rflag || xflag))
  694.     detached = 1;
  695.   nwin = nwin_options;
  696.   if (ac)
  697.     nwin.args = av;
  698.   real_uid = getuid();
  699.   real_gid = getgid();
  700.   eff_uid = geteuid();
  701.   eff_gid = getegid();
  702.   if (eff_uid != real_uid)
  703.     {        
  704.       /* if running with s-bit, we must install a special signal
  705.        * handler routine that resets the s-bit, so that we get a
  706.        * core file anyway.
  707.        */
  708. #ifdef SIGBUS /* OOPS, linux has no bus errors ??? */
  709.       signal(SIGBUS, CoreDump);
  710. #endif /* SIGBUS */
  711.       signal(SIGSEGV, CoreDump);
  712.     }
  713.   if (!ShellProg)
  714.     {
  715.       register char *sh;
  716.  
  717.       sh = getenv("SHELL");
  718.       ShellProg = SaveStr(sh ? sh : DefaultShell);
  719.     }
  720.   ShellArgs[0] = ShellProg;
  721. #ifdef NETHACK
  722.   nethackflag = (getenv("NETHACKOPTIONS") != NULL);
  723. #endif
  724. #ifdef MULTIUSER
  725.   own_uid = multi_uid = real_uid;
  726.   if (SockName && (sockp = index(SockName, '/')))
  727.     {
  728.       if (eff_uid)
  729.         Panic(0, "Must run suid root for multi support.");
  730.       *sockp = 0;
  731.       multi = SockName;
  732.       SockName = sockp + 1;
  733.       if (*multi)
  734.     {
  735.       struct passwd *mppp;
  736.       if ((mppp = getpwnam(multi)) == (struct passwd *) 0)
  737.         Panic(0, "Cannot identify account '%s'.", multi);
  738.       multi_uid = mppp->pw_uid;
  739.       multi_home = SaveStr(mppp->pw_dir);
  740. #ifdef MULTI
  741.       if (rflag || lsflag)
  742.         {
  743.           xflag = 1;
  744.           rflag = 0;
  745.         }
  746. #endif
  747.       detached = 0;
  748.       multiattach = 1;
  749.     }
  750.     }
  751.   if (SockName && *SockName == 0)
  752.     SockName = 0;
  753. #endif
  754.   if ((LoginName = getlogin()) && LoginName[0] != '\0')
  755.     {
  756.       if ((ppp = getpwnam(LoginName)) != (struct passwd *) 0)
  757.     if (ppp->pw_uid != real_uid)
  758.       ppp = (struct passwd *) 0;
  759.     }
  760.   if (ppp == 0)
  761.     {
  762.       if ((ppp = getpwuid(real_uid)) == 0)
  763.         {
  764. #ifdef NETHACK
  765.           if (nethackflag)
  766.         Panic(0, "An alarm sounds through the dungeon...\nWarning, the kops are coming.");
  767.       else
  768. #endif
  769.       Panic(0, "getpwuid() can't identify your account!");
  770.       exit(1);
  771.         }
  772.       LoginName = ppp->pw_name;
  773.     }
  774.   home = getenv("HOME");    /* may or may not return a result. jw. */
  775. #if !defined(SOCKDIR) && defined(MULTIUSER)
  776.   if (multi && !multiattach)
  777.     {
  778.       if (home && strcmp(home, ppp->pw_dir))
  779.         Panic(0, "$HOME must match passwd entry for multi screens");
  780.     }
  781. #endif
  782.   if (home == 0 || *home == '\0')
  783.     home = ppp->pw_dir;
  784.   if (strlen(LoginName) > 20)
  785.     Panic(0, "LoginName too long - sorry.");
  786.   if (strlen(home) > MAXPATHLEN - 25)
  787.     Panic(0, "$HOME too long - sorry.");
  788. #ifdef PASSWORD
  789.   strcpy(Password, ppp->pw_passwd);
  790. #endif
  791.  
  792.   if (!detached && !lsflag)
  793.     {
  794.       /* ttyname implies isatty */
  795.       if (!(attach_tty = ttyname(0)))
  796.     {
  797. #ifdef NETHACK
  798.       if (nethackflag)
  799.         Panic(0, "You must play from a terminal.");
  800.       else
  801. #endif
  802.       Panic(0, "Must be connected to a terminal.");
  803.       exit(1);
  804.     }
  805.       if (strlen(attach_tty) >= MAXPATHLEN)
  806.     Panic(0, "TtyName too long - sorry.");
  807.       if (stat(attach_tty, &st))
  808.     Panic(errno, "Cannot access '%s'", attach_tty);
  809. #ifdef MULTIUSER
  810.       tty_mode = st.st_mode & 0777;
  811. #endif
  812.       if ((n = secopen(attach_tty, O_RDWR, 0)) < 0)
  813.     Panic(0, "Cannot open '%s' - please check.", attach_tty);
  814.       close(n);
  815.       debug1("attach_tty is %s\n", attach_tty);
  816.       if ((attach_term = getenv("TERM")) == 0)
  817.     Panic(0, "Please set a terminal type.");
  818.       if (strlen(attach_term) > sizeof(d_termname) - 1)
  819.     Panic(0, "$TERM too long - sorry.");
  820.       GetTTY(0, &attach_Mode);
  821. #ifdef DEBUGGGGGGGGGGGGGGG
  822.       DebugTTY(&attach_Mode);
  823. #endif /* DEBUG */
  824.     }
  825.   
  826. #ifdef _MODE_T
  827.   oumask = umask(0);        /* well, unsigned never fails? jw. */
  828. #else
  829.   if ((oumask = umask(0)) == -1)
  830.     Panic(errno, "Cannot change umask to zero");
  831. #endif
  832.   if ((SockDir = getenv("ISCREENDIR")) == NULL)
  833.     SockDir = getenv("SCREENDIR");
  834.   if (SockDir)
  835.     {
  836.       if (strlen(SockDir) >= MAXPATHLEN - 1)
  837.     Panic(0, "Ridiculously long $(I)SCREENDIR - try again.");
  838. #ifdef MULTIUSER
  839.       if (multi)
  840.     Panic(0, "No $(I)SCREENDIR with multi screens, please.");
  841. #endif
  842.     }
  843. #ifdef MULTIUSER
  844.   if (multiattach)
  845.     {
  846. # ifndef SOCKDIR
  847.       sprintf(SockPath, "%s/.iscreen", multi_home);
  848.       SockDir = SockPath;
  849. # else
  850.       SockDir = SOCKDIR;
  851.       sprintf(SockPath, "%s/S-%s", SockDir, multi);
  852. # endif
  853.     }
  854.   else
  855. #endif
  856.     {
  857. #ifndef SOCKDIR
  858.       if (SockDir == 0)
  859.     {
  860.       sprintf(SockPath, "%s/.iscreen", home);
  861.       SockDir = SockPath;
  862.     }
  863. #endif
  864.       if (SockDir)
  865.     {
  866.       if (access(SockDir, F_OK))
  867.         {
  868.           debug1("SockDir '%s' missing ...\n", SockDir);
  869.           if (UserContext() > 0)
  870.         {
  871.           if (mkdir(SockDir, 0700))
  872.             UserReturn(0);
  873.           UserReturn(1);
  874.         }
  875.           if (UserStatus() <= 0)
  876.         Panic(0, "Cannot make directory '%s'.", SockDir);
  877.         }
  878.       if (SockDir != SockPath)
  879.         strcpy(SockPath, SockDir);
  880.     }
  881. #ifdef SOCKDIR
  882.       else
  883.     {
  884.       SockDir = SOCKDIR;
  885.       if (stat(SockDir, &st))
  886.         {
  887.           if (mkdir(SockDir, eff_uid ? 0777 : 0755) == -1)
  888.         Panic(errno, "Cannot make directory '%s'", SockDir);
  889.         }
  890.       else
  891.         {
  892.           n = eff_uid ? 0777 : 0755;
  893.           if ((st.st_mode & 0777) != n)
  894.         Panic(0, "Directory '%s' must have mode %03o.", SockDir, n);
  895.         }
  896.       sprintf(SockPath, "%s/S-%s", SockDir, LoginName);
  897.       if (access(SockPath, F_OK))
  898.         {
  899.           if (mkdir(SockPath, 0700) == -1)
  900.         Panic(errno, "Cannot make directory '%s'", SockPath);
  901.           (void) chown(SockPath, real_uid, real_gid);
  902.         }
  903.     }
  904. #endif
  905.     }
  906.  
  907.   if (stat(SockPath, &st) == -1)
  908.     {
  909.       Panic(errno, "Cannot access %s", SockPath);
  910.     }
  911.   else
  912.     {
  913. #ifdef _POSIX_SOURCE
  914.       if (S_ISDIR(st.st_mode) == 0)
  915. #else
  916.       if ((st.st_mode & S_IFMT) != S_IFDIR)
  917. #endif
  918.     Panic(0, "%s is not a directory.", SockPath);
  919. #ifdef MULTIUSER
  920.       if (multi)
  921.     {
  922.       if (st.st_uid != multi_uid)
  923.         Panic(0, "%s is not the owner of %s.", multi, SockPath);
  924.     }
  925.       else
  926. #endif
  927.     {
  928.       if (st.st_uid != real_uid)
  929.         Panic(0, "You are not the owner of %s.", SockPath);
  930.     }
  931.       if ((st.st_mode & 0777) != 0700)
  932.     Panic(0, "Directory %s must have mode 700.", SockPath);
  933.     }
  934.   strcat(SockPath, "/");
  935.   SockNamePtr = SockPath + strlen(SockPath);
  936.   (void) umask(oumask);
  937.   debug2("SockPath: %s  SockName: %s\n", SockPath, SockName ? SockName : "NULL");
  938.  
  939. #if defined(SYSV) && !defined(ISC)
  940.   if (uname(&utsnam) == -1)
  941.     Panic(0, "uname() failed, errno = %d.", errno);
  942.   else
  943.     {
  944.       strncpy(HostName, utsnam.nodename, MAXSTR);
  945.       HostName[(sizeof(utsnam.nodename) <= MAXSTR) ? 
  946.                sizeof(utsnam.nodename) : MAXSTR] = '\0';
  947.     }
  948. #else
  949.   (void) gethostname(HostName, MAXSTR);
  950. #endif
  951.   HostName[MAXSTR - 1] = '\0';
  952.   if ((ap = index(HostName, '.')) != NULL)
  953.     *ap = '\0';
  954.  
  955.   if (lsflag)
  956.     {
  957.       int i;
  958.  
  959. #ifdef MULTIUSER
  960.       if (multi)
  961.     real_uid = multi_uid;
  962.       setuid(real_uid);
  963.       setgid(real_gid);
  964.       eff_uid = real_uid;
  965.       eff_gid = real_gid;
  966. #endif
  967.       i = FindSocket(0, (int *)NULL);
  968.       /* MakeClientSocket appended the last (Sock)Name there: */
  969.       *SockNamePtr = '\0';
  970.       if (i == 0)
  971.     {
  972. #ifdef NETHACK
  973.           if (nethackflag)
  974.         Panic(0, "This room is empty (%s).\n", SockPath);
  975.           else
  976. #endif /* NETHACK */
  977.           Panic(0, "No Sockets found in %s.\n", SockPath);
  978.         }
  979.       Panic(0, "%d Socket%s in %s.\n", i, i > 1 ? "s" : "", SockPath);
  980.       /* NOTREACHED */
  981.     }
  982.   signal(SIG_BYE, AttacherFinit);    /* prevent races */
  983.   if (rflag || xflag)
  984.     {
  985.       debug("screen -r: - is there anybody out there?\n");
  986. #ifdef SHADOWPW
  987.       setspent();  /* open shadow file while we are still root */
  988. #endif /* SHADOWPW */
  989.       if (Attach(MSG_ATTACH))
  990.     {
  991.       Attacher();
  992.       /* NOTREACHED */
  993.     }
  994.       debug("screen -r: backend not responding -- still crying\n");
  995.     }
  996.   else if (dflag && !mflag)
  997.     {
  998.       (void) Attach(MSG_DETACH);
  999.       Msg(0, "[%s %sdetached.]\n", SockName, (dflag > 1 ? "power " : ""));
  1000.       eexit(0);
  1001.       /* NOTREACHED */
  1002.     }
  1003.   if (!SockName && !mflag)
  1004.     {
  1005.       register char *sty;
  1006.       int s;
  1007.  
  1008.       if ((sty = getenv("STY")) != 0 && *sty != '\0')
  1009.     {
  1010.       setuid(real_uid);
  1011.       setgid(real_gid);
  1012.       eff_uid = real_uid;
  1013.       eff_gid = real_gid;
  1014.       if ((s = MakeClientSocket(1, sty)) > 0)
  1015.         {
  1016.           nwin_options.args = av;
  1017.           SendCreateMsg(s, &nwin);
  1018.           close(s);
  1019.         }
  1020.       exit(0);
  1021.       /* NOTREACHED */
  1022.     }
  1023.     }
  1024.   nwin_compose(&nwin_default, &nwin_options, &nwin_default);
  1025.   if (SockName && !*SockName)
  1026.     SockName = NULL;
  1027.   switch (MasterPid = fork())
  1028.     {
  1029.     case -1:
  1030.       Panic(errno, "fork");
  1031.       /* NOTREACHED */
  1032. #ifdef FORKDEBUG
  1033.     default:
  1034.       break;
  1035.     case 0:
  1036.       MasterPid = getppid();
  1037. #else
  1038.     case 0:
  1039.       break;
  1040.     default:
  1041. #endif
  1042.       if (detached)
  1043.         exit(0);
  1044.       if (SockName)
  1045.     {
  1046.       /* user started us with -S option */
  1047.       sprintf(socknamebuf, "%d.%s", MasterPid, SockName);
  1048.     }
  1049.       else
  1050.     {
  1051.       sprintf(socknamebuf, "%d.%s.%s", MasterPid, stripdev(attach_tty),
  1052.           HostName);
  1053.     }
  1054.       for (ap = socknamebuf; *ap; ap++)
  1055.     if (*ap == '/')
  1056.       *ap = '-';
  1057.       SockName = socknamebuf;
  1058. #ifdef SHADOWPW
  1059.       setspent();  /* open shadow file while we are still root */
  1060. #endif /* SHADOWPW */
  1061.       setuid(real_uid);
  1062.       setgid(real_gid);
  1063.       eff_uid = real_uid;
  1064.       eff_gid = real_gid;
  1065.       Attacher();
  1066.       /* NOTREACHED */
  1067.     }
  1068.  
  1069.   ap = av0 + strlen(av0) - 1;
  1070.   while (ap >= av0)
  1071.     {
  1072.       if (!strncmp("screen", ap, 6))
  1073.     {
  1074.       strncpy(ap, "SCREEN", 6); /* name this process "SCREEN-BACKEND" */
  1075.       break;
  1076.     }
  1077.       ap--;
  1078.     }
  1079.   if (ap < av0)
  1080.     *av0 = 'S';
  1081.  
  1082. #ifdef DEBUG
  1083.   if (dfp != stderr)
  1084.     fclose(dfp);
  1085.   if ((dfp = fopen("/tmp/debug/screen.back", "w")) == NULL)
  1086.     dfp = stderr;
  1087.   else
  1088.     (void) chmod("/tmp/debug/screen.back", 0666);
  1089. #endif
  1090.   if (!detached)
  1091.     n = dup(0);
  1092.   else
  1093.     n = -1;
  1094.   freopen("/dev/null", "r", stdin);
  1095.   freopen("/dev/null", "w", stdout);
  1096. #ifdef DEBUG
  1097.   if (dfp != stderr)
  1098. #endif
  1099.   freopen("/dev/null", "w", stderr);
  1100.   debug("-- screen.back debug started\n");
  1101.  
  1102.   if (!detached)
  1103.     {
  1104. #ifdef FORKDEBUG
  1105.       if (MakeDisplay(LoginName, attach_tty, attach_term, n, MasterPid, &attach_Mode) == 0)
  1106. #else
  1107.       if (MakeDisplay(LoginName, attach_tty, attach_term, n, getppid(), &attach_Mode) == 0)
  1108. #endif
  1109.     Panic(0, "Could not alloc display");
  1110.     }
  1111.  
  1112.   if (SockName)
  1113.     {
  1114.       /* user started us with -S option */
  1115.       sprintf(socknamebuf, "%d.%s", getpid(), SockName);
  1116.     }
  1117.   else
  1118.     {
  1119.       sprintf(socknamebuf, "%d.%s.%s", getpid(), stripdev(attach_tty),
  1120.           HostName);
  1121.     }
  1122.   for (ap = socknamebuf; *ap; ap++)
  1123.     if (*ap == '/')
  1124.       *ap = '-';
  1125.   SockName = socknamebuf;
  1126.   ServerSocket = MakeServerSocket();
  1127. #ifdef ETCSCREENRC
  1128.   if ((ap = getenv("SYSSCREENRC")) == NULL)
  1129.     StartRc(ETCSCREENRC);
  1130.   else
  1131.     StartRc(ap);
  1132. #endif
  1133.   StartRc(RcFileName);
  1134. # ifdef UTMPOK
  1135. #  ifndef UTNOKEEP
  1136.   InitUtmp(); 
  1137. #  endif /* UTNOKEEP */
  1138. # endif /* UTMPOK */
  1139.   if (display)
  1140.     {
  1141.       if (InitTermcap(0, 0))
  1142.     {
  1143.       debug("Could not init termcap - exiting\n");
  1144.       fcntl(d_userfd, F_SETFL, 0);    /* Flush sets NDELAY */
  1145.       freetty();
  1146.       if (d_userpid)
  1147.         Kill(d_userpid, SIG_BYE);
  1148.       eexit(1);
  1149.     }
  1150.       InitTerm(0);
  1151. #ifdef UTMPOK
  1152.       RemoveLoginSlot();
  1153. #endif
  1154.     }
  1155.   else
  1156.     {
  1157.       MakeTermcap(1);
  1158.     }
  1159. #ifdef LOADAV
  1160.   InitLoadav();
  1161. #endif /* LOADAV */
  1162.   MakeNewEnv();
  1163.   signal(SIGHUP, SigHup);
  1164.   signal(SIGINT, Finit);
  1165.   signal(SIGQUIT, Finit);
  1166.   signal(SIGTERM, Finit);
  1167. #ifdef BSDJOBS
  1168.   signal(SIGTTIN, SIG_IGN);
  1169.   signal(SIGTTOU, SIG_IGN);
  1170. #endif
  1171.   InitKeytab();
  1172.   if (display)
  1173.     {
  1174.       brktty(d_userfd);
  1175.       SetMode(&d_OldMode, &d_NewMode);
  1176.       /* Note: SetMode must be called _before_ FinishRc. */
  1177.       SetTTY(d_userfd, &d_NewMode);
  1178.       if (fcntl(d_userfd, F_SETFL, FNDELAY))
  1179.     Msg(errno, "Warning: NDELAY fcntl failed");
  1180.     }
  1181.   else
  1182.     brktty(-1);        /* just try */
  1183. #ifdef ETCSCREENRC
  1184.   if ((ap = getenv("SYSSCREENRC")) == NULL)
  1185.     FinishRc(ETCSCREENRC);
  1186.   else
  1187.     FinishRc(ap);
  1188. #endif
  1189.   FinishRc(RcFileName);
  1190.  
  1191.   debug2("UID %d  EUID %d\n", getuid(), geteuid());
  1192.   if (windows == NULL)
  1193.     {
  1194.       debug("We open one default window, as screenrc did not specify one.\n");
  1195.       if (MakeWindow(&nwin) == -1)
  1196.     {
  1197.       AddStr("Sorry, could not find a PTY.");
  1198.       sleep(2);
  1199.       Finit(0);
  1200.       /* NOTREACHED */
  1201.     }
  1202.     }
  1203.   if (default_startup)
  1204.     display_copyright();
  1205.   signal(SIGCHLD, SigChld);
  1206.   signal(SIGINT, SigInt);
  1207.   tv.tv_usec = 0;
  1208.   if (rflag == 2)
  1209.     {
  1210. #ifdef NETHACK
  1211.       if (nethackflag)
  1212.         Msg(0, "I can't seem to find a... Hey, wait a minute!  Here comes a screen now.");
  1213.       else
  1214. #endif
  1215.       Msg(0, "New screen...");
  1216.       rflag = 0;
  1217.     }
  1218.  
  1219.   Now = time((time_t *)0);
  1220.  
  1221.   for (;;)
  1222.     {
  1223.       tv.tv_sec = 0;
  1224.       /*
  1225.        * check for silence
  1226.        */
  1227.       for (p = windows; p; p = p->w_next)
  1228.         {
  1229.       int time_left;
  1230.  
  1231.       if (p->w_tstamp.seconds == 0)
  1232.         continue;
  1233.       debug1("checking silence win %d\n", p->w_number);
  1234.       time_left = p->w_tstamp.lastio + p->w_tstamp.seconds - Now;
  1235.       if (time_left > 0)
  1236.         {
  1237.           if (tv.tv_sec == 0 || time_left < tv.tv_sec)
  1238.             tv.tv_sec = time_left;
  1239.         }
  1240.       else
  1241.         {
  1242.           for (display = displays; display; display = display->_d_next)
  1243.             if (p != d_fore)
  1244.           Msg(0, "Window %d: silence for %d seconds", 
  1245.               p->w_number, p->w_tstamp.seconds);
  1246.           p->w_tstamp.lastio = Now;
  1247.         }
  1248.     }
  1249.  
  1250.       /*
  1251.        * check to see if message line should be removed
  1252.        */
  1253.       for (display = displays; display; display = display->_d_next)
  1254.     {
  1255.       int time_left;
  1256.  
  1257.       if (d_status == 0)
  1258.         continue;
  1259.       debug("checking status...\n");
  1260.       time_left = d_status_time + (d_status_bell?VBellWait:MsgWait) - Now;
  1261.       if (time_left > 0)
  1262.         {
  1263.           if (tv.tv_sec == 0 || time_left < tv.tv_sec)
  1264.             tv.tv_sec = time_left;
  1265.           debug(" not yet.\n");
  1266.         }
  1267.       else
  1268.         {
  1269.           debug(" removing now.\n");
  1270.           RemoveStatus();
  1271.         }
  1272.     }
  1273.       /*
  1274.        * check for I/O on all available I/O descriptors
  1275.        */
  1276. #ifdef DEBUG
  1277.       if (tv.tv_sec)
  1278.         debug1("select timeout %d seconds\n", tv.tv_sec);
  1279. #endif
  1280.       mkfdsets(&r, &w);
  1281.       if (GotSigChld && !tv.tv_sec)
  1282.     {
  1283.       SigChldHandler();
  1284.       continue;
  1285.     }
  1286.       if ((nsel = select(FD_SETSIZE, &r, &w, (fd_set *)0, tv.tv_sec ? &tv : (struct timeval *) 0)) < 0)
  1287.     {
  1288.       debug1("Bad select - errno %d\n", errno);
  1289.       if (errno != EINTR)
  1290.         Panic(errno, "select");
  1291.       errno = 0;
  1292.       nsel = 0;
  1293.     }
  1294. #ifdef SELECT_BROKEN
  1295.       /* 
  1296.        * Sequents select emulation counts an descriptor which is
  1297.        * readable and writeable only as one. waaaaa.
  1298.        */
  1299.       if (nsel)
  1300.     nsel = 2 * FD_SETSIZE;
  1301. #endif
  1302.       if (GotSigChld && !tv.tv_sec)
  1303.     {
  1304.       SigChldHandler();
  1305.       continue;
  1306.     }
  1307.       if (InterruptPlease)
  1308.     {
  1309.       debug("Backend received interrupt\n");
  1310.       if (fore)
  1311.         {
  1312.           char ibuf;
  1313.           ibuf = intrc;
  1314. #ifdef PSEUDOS
  1315.           write(W_UWP(fore) ? fore->w_pwin->p_ptyfd : fore->w_ptyfd, 
  1316.             &ibuf, 1);
  1317.           debug1("Backend wrote interrupt to %d", fore->w_number);
  1318.           debug1("%s\n", W_UWP(fore) ? " (pseudowin)" : "");
  1319. #else
  1320.           write(fore->w_ptyfd, &ibuf, 1);
  1321.           debug1("Backend wrote interrupt to %d\n", fore->w_number);
  1322. #endif
  1323.         }
  1324.       InterruptPlease = 0;
  1325.     }
  1326.  
  1327.       /*
  1328.        *   Process a client connect attempt and message
  1329.        */
  1330.       if (nsel && FD_ISSET(ServerSocket, &r))
  1331.     {
  1332.           nsel--;
  1333.       debug("Knock - knock!\n");
  1334.       ReceiveMsg();
  1335.       continue;
  1336.     }
  1337.  
  1338.       /*
  1339.        * Write the (already processed) user input to the window
  1340.        * descriptors first. We do not want to choke, if he types fast.
  1341.        */
  1342.       if (nsel)
  1343.     {
  1344.       for (p = windows; p; p = p->w_next)
  1345.         {
  1346.           int pastefd = -1;
  1347. #ifdef COPY_PASTE
  1348.           if (p->w_pastelen)
  1349.         {
  1350.           /*
  1351.            *  Write the copybuffer contents first, if any.
  1352.            */
  1353. #ifdef PSEUDOS
  1354.           pastefd = W_UWP(p) ? p->w_pwin->p_ptyfd : p->w_ptyfd;
  1355. #else
  1356.           pastefd = p->w_ptyfd;
  1357. #endif
  1358.           if (FD_ISSET(pastefd, &w))
  1359.             {
  1360.               debug1("writing pastebuffer (%d)\n", p->w_pastelen);
  1361.               len = write(pastefd, p->w_pastebuffer, 
  1362.                           (slowpaste > 0) ? 1 :
  1363.                   (p->w_pastelen > IOSIZE ? 
  1364.                    IOSIZE : p->w_pastelen));
  1365.               if (len < 0)    /* Problems... window is dead */
  1366.             p->w_pastelen = 0;
  1367.               if (len > 0)
  1368.             {
  1369.               p->w_pastebuffer += len;
  1370.               p->w_pastelen -= len;
  1371.             }
  1372.               debug1("%d bytes pasted\n", len);
  1373.               if (slowpaste > 0)
  1374.             {
  1375.               struct timeval t;
  1376.  
  1377.               debug1("slowpaste %d\n", slowpaste);
  1378.               t.tv_sec = (long) (slowpaste / 1000);
  1379.               t.tv_usec = (long) ((slowpaste % 1000) * 1000);
  1380.               select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
  1381.             }
  1382.               if (--nsel == 0)
  1383.                 break;
  1384.               if (p->w_pastelen == 0)
  1385.             pastefd = -1;
  1386.             }
  1387.         }
  1388. #endif
  1389.  
  1390. #ifdef PSEUDOS
  1391.           if (p->w_pwin && p->w_pwin->p_inlen > 0)
  1392.             {
  1393.           /* stuff w_pwin->p_inbuf into pseudowin */
  1394.           tmp = p->w_pwin->p_ptyfd;
  1395.           if (tmp != pastefd && FD_ISSET(tmp, &w))
  1396.             {
  1397.               if ((len = write(tmp, p->w_pwin->p_inbuf, 
  1398.                        p->w_pwin->p_inlen)) > 0)
  1399.                 {
  1400.               if ((p->w_pwin->p_inlen -= len))
  1401.                 bcopy(p->w_pwin->p_inbuf + len, p->w_pwin->p_inbuf,
  1402.                       p->w_pwin->p_inlen);
  1403.             }
  1404.               if (--nsel == 0)
  1405.                 break;
  1406.             }
  1407.         }
  1408. #endif
  1409.           if (p->w_inlen > 0)
  1410.         {
  1411.           /* stuff w_inbuf buffer into window */
  1412.           tmp = p->w_ptyfd;
  1413.           if (tmp != pastefd && FD_ISSET(tmp, &w))
  1414.             {
  1415.               if ((len = write(tmp, p->w_inbuf, p->w_inlen)) > 0)
  1416.             {
  1417.               if ((p->w_inlen -= len))
  1418.                 bcopy(p->w_inbuf + len, p->w_inbuf, p->w_inlen);
  1419.             }
  1420.               if (--nsel == 0)
  1421.             break;
  1422.             }
  1423.         }
  1424.         }
  1425.     }
  1426.       
  1427.       Now = time((time_t *)0);
  1428.  
  1429.       if (nsel)
  1430.     {
  1431.       for (display = displays; display; display = ndisplay)
  1432.         {
  1433.           int maxlen;
  1434.  
  1435.           ndisplay = display->_d_next;
  1436.           /* 
  1437.            * stuff d_obuf into user's tty
  1438.            */
  1439.           if (FD_ISSET(d_userfd, &w)) 
  1440.         {
  1441.           int size = OUTPUT_BLOCK_SIZE;
  1442.  
  1443.           len = d_obufp - d_obuf;
  1444.           if (len < size)
  1445.             size = len;
  1446.           ASSERT(len >= 0);
  1447.           size = write(d_userfd, d_obuf, size);
  1448.           if (size >= 0) 
  1449.             {
  1450.               len -= size;
  1451.               if (len)
  1452.                 {
  1453.               bcopy(d_obuf + size, d_obuf, len);
  1454.                   debug2("ASYNC: wrote %d - remaining %d\n", size, len);
  1455.             }
  1456.               d_obufp -= size;
  1457.               d_obuffree += size;
  1458.             } 
  1459.           else
  1460.             {
  1461.               if (errno != EINTR)
  1462. # ifdef EWOULDBLOCK
  1463.             if (errno != EWOULDBLOCK)
  1464. # endif
  1465.             Msg(errno, "Error writing output to display");
  1466.             }
  1467.           if (--nsel == 0)
  1468.             break;
  1469.         }
  1470.           /*
  1471.            * O.k. All streams are fed, now look what comes back
  1472.            * to us. First of all: user input.
  1473.            */
  1474.           if (! FD_ISSET(d_userfd, &r))
  1475.         continue;
  1476.           if (d_status && !(use_hardstatus && HS))
  1477.         RemoveStatus();
  1478.           if (d_fore == 0)
  1479.         maxlen = IOSIZE;
  1480.           else
  1481.         {
  1482. #ifdef PSEUDOS
  1483.           if (W_UWP(d_fore))
  1484.             maxlen = sizeof(d_fore->w_pwin->p_inbuf) - d_fore->w_pwin->p_inlen;
  1485.           else
  1486. #endif
  1487.             maxlen = sizeof(d_fore->w_inbuf) - d_fore->w_inlen;
  1488.         }
  1489.           if (maxlen > IOSIZE)
  1490.         maxlen = IOSIZE;
  1491.           if (maxlen <= 0)
  1492.         maxlen = 1;    /* Allow one char for command keys */
  1493.           if (d_ESCseen)
  1494.         {
  1495.           if (maxlen == 1)
  1496.             maxlen = 2;    /* Allow one char for command keys */
  1497.           buf[0] = Esc;
  1498.           buflen = read(d_userfd, buf + 1, maxlen - 1) + 1;
  1499.           d_ESCseen = 0;
  1500.         }
  1501.           else
  1502.         buflen = read(d_userfd, buf, maxlen);
  1503.           if (buflen < 0)
  1504.         {
  1505.           if (errno == EINTR)
  1506.             continue;
  1507.           debug1("Read error: %d - SigHup()ing!\n", errno);
  1508.           SigHup(SIGARG);
  1509.           sleep(1);
  1510.         }
  1511.           else if (buflen == 0)
  1512.         {
  1513.           debug("Found EOF - SigHup()ing!\n");
  1514.           SigHup(SIGARG);
  1515.           sleep(1);
  1516.         }
  1517.           else
  1518.         {
  1519.               /* This refills inbuf or p_inbuf */
  1520.               ProcessInput(buf, buflen);
  1521.         }
  1522.           if (--nsel == 0)
  1523.         break;
  1524.         }
  1525.     }
  1526.     
  1527.       /* 
  1528.        * Read and process the output from the window descriptors 
  1529.        */ 
  1530.       for (p = windows; p; p = p->w_next) 
  1531.     {
  1532.       if (p->w_lay->l_block)
  1533.         continue;
  1534.       display = p->w_display;
  1535.       if (p->w_outlen)
  1536.         WriteString(p, p->w_outbuf, p->w_outlen);
  1537.       else 
  1538.         {
  1539. #ifdef PSEUDOS
  1540.           /* gather pseudowin output */
  1541.           if (W_RP(p) && nsel && FD_ISSET(p->w_pwin->p_ptyfd, &r))
  1542.             {
  1543.           nsel--;
  1544.           n = 0;
  1545.           if (W_PTOW(p))
  1546.             {
  1547.               /* Window wants a copy of the pseudowin output */
  1548.               tmp = sizeof(p->w_inbuf) - p->w_inlen;
  1549.               ASSERT(tmp > 0);
  1550.               n++;
  1551.             }
  1552.           else
  1553.             tmp = IOSIZE;
  1554.           if ((len = read(p->w_pwin->p_ptyfd, buf, tmp)) <= 0)
  1555.             {
  1556.               if (errno != EINTR)
  1557. #ifdef EWOULDBLOCK
  1558.                 if (errno != EWOULDBLOCK)
  1559. #endif
  1560.               {
  1561.                 debug2("Window %d: pseudowin read error (errno %d) -- removing pseudowin\n", p->w_number, len ? errno : 0);
  1562.                 FreePseudowin(p);
  1563.               }
  1564.             }
  1565. /* HERE WE ASSUME THAT THERE IS NO PACKET MODE ON PSEUDOWINS */
  1566.           else
  1567.             {
  1568.               if (n)
  1569.             {
  1570.               bcopy(buf, p->w_inbuf + p->w_inlen, len);
  1571.               p->w_inlen += len;
  1572.             }
  1573.               WriteString(p, buf, len);
  1574.             }
  1575.         }
  1576. #endif /* PSEUDOS */
  1577.           /* gather window output */
  1578.           if (nsel && FD_ISSET(p->w_ptyfd, &r))
  1579.         {
  1580.           nsel--;
  1581. #ifdef PSEUDOS
  1582.           n = 0;
  1583.           ASSERT(W_RW(p));
  1584.           if (p->w_pwin && W_WTOP(p))
  1585.             {
  1586.               /* Pseudowin wants a copy of the window output */
  1587.               tmp = sizeof(p->w_pwin->p_inbuf) - p->w_pwin->p_inlen;
  1588.               ASSERT(tmp > 0);
  1589.               n++;
  1590.             }
  1591.           else
  1592. #endif
  1593.             tmp = IOSIZE;
  1594.           if ((len = read(p->w_ptyfd, buf, tmp)) <= 0)
  1595.             {
  1596.               if (errno == EINTR)
  1597.             continue;
  1598. #ifdef EWOULDBLOCK
  1599.               if (errno == EWOULDBLOCK)
  1600.             continue;
  1601. #endif
  1602.               debug2("Window %d: read error (errno %d) - killing window\n", p->w_number, len ? errno : 0);
  1603.               KillWindow(p);
  1604.               nsel = 0;    /* KillWindow may change window order */
  1605.               break;    /* so we just break */
  1606.             }
  1607. #ifdef TIOCPKT
  1608.           if ((p->w_t.flags & TTY_FLAG_PLAIN) == 0)
  1609.             {
  1610.               if (buf[0])
  1611.             {
  1612.               debug1("PAKET %x\n", buf[0]);
  1613.               if (buf[0] & TIOCPKT_NOSTOP)
  1614.                 NewAutoFlow(p, 0);
  1615.               if (buf[0] & TIOCPKT_DOSTOP)
  1616.                 NewAutoFlow(p, 1);
  1617.             }
  1618.               if (len > 1)
  1619.             {
  1620. #ifdef PSEUDOS
  1621.               if (n)
  1622.                 {
  1623.                   bcopy(buf + 1, 
  1624.                     p->w_pwin->p_inbuf + p->w_pwin->p_inlen,
  1625.                     len - 1);
  1626.                   p->w_pwin->p_inlen += len - 1;
  1627.                 }
  1628. #endif
  1629.               WriteString(p, buf + 1, len - 1);
  1630.             }
  1631.             }
  1632.           else
  1633. #endif /* TIOCPKT */
  1634.             {
  1635.               if (len > 0)
  1636.             {
  1637. #ifdef PSEUDOS
  1638.               if (n)
  1639.                 {
  1640.                   bcopy(buf, p->w_pwin->p_inbuf + p->w_pwin->p_inlen,
  1641.                     len);
  1642.                   p->w_pwin->p_inlen += len;
  1643.                 }
  1644. #endif
  1645.               WriteString(p, buf, len);
  1646.             }
  1647.             }
  1648.         }
  1649.         }
  1650.       if (p->w_bell == BELL_ON)
  1651.         {
  1652.           p->w_bell = BELL_MSG;
  1653.           for (display = displays; display; display = display->_d_next)
  1654.             Msg(0, MakeWinMsg(BellString, p->w_number));
  1655.           if (p->w_monitor == MON_FOUND)
  1656.         p->w_monitor = MON_DONE;
  1657.         }
  1658.       else if (p->w_bell == BELL_VISUAL)
  1659.         {
  1660.           if (display && !d_status_bell)
  1661.         {
  1662.           /*
  1663.            * Stop the '!' appearing in the ^A^W display if it is an 
  1664.            * active at the time of the bell. (Tim MacKenzie)
  1665.            */
  1666.           p->w_bell = BELL_OFF; 
  1667.           Msg(0, VisualBellString);
  1668.           if (d_status)
  1669.             d_status_bell = 1;
  1670.         }
  1671.         }
  1672.       if (p->w_monitor == MON_FOUND)
  1673.         {
  1674.           p->w_monitor = MON_MSG;
  1675.           for (display = displays; display; display = display->_d_next)
  1676.             Msg(0, MakeWinMsg(ActivityString, p->w_number));
  1677.         }
  1678.     }
  1679. #if defined(DEBUG) && !defined(_SEQUENT_)
  1680.       if (nsel)
  1681.     debug1("*** Left over nsel: %d\n", nsel);
  1682. #endif
  1683.     }
  1684.   /* NOTREACHED */
  1685. }
  1686.  
  1687. static void
  1688. SigChldHandler()
  1689. {
  1690.   struct stat st;
  1691.   while (GotSigChld)
  1692.     {
  1693.       GotSigChld = 0;
  1694.       DoWait();
  1695. #ifdef SYSVSIGS
  1696.       signal(SIGCHLD, SigChld);
  1697. #endif
  1698.     }
  1699.   if (stat(SockPath, &st) == -1)
  1700.     {
  1701.       debug1("SigChldHandler: Yuck! cannot stat '%s'\n", SockPath);
  1702.       if (!RecoverSocket())
  1703.     {
  1704.       debug("SCREEN cannot recover from corrupt Socket, bye\n");
  1705.       Finit(1);
  1706.     }
  1707.       else
  1708.     debug1("'%s' reconstructed\n", SockPath);
  1709.     }
  1710.   else
  1711.     debug2("SigChldHandler: stat '%s' o.k. (%03o)\n", SockPath, st.st_mode);
  1712. }
  1713.  
  1714. static sig_t
  1715. SigChld(SIGDEFARG)
  1716. {
  1717.   debug("SigChld()\n");
  1718.   GotSigChld = 1;
  1719. #ifndef SIGVOID
  1720.   return((sig_t) 0);
  1721. #endif
  1722. }
  1723.  
  1724. sig_t
  1725. SigHup(SIGDEFARG)
  1726. {
  1727.   if (display == 0)
  1728.     return;
  1729.   debug("SigHup()\n");
  1730.   if (d_userfd >= 0)
  1731.     {
  1732.       close(d_userfd);
  1733.       d_userfd = -1;
  1734.     }
  1735.   if (auto_detach || displays->_d_next)
  1736.     Detach(D_DETACH);
  1737.   else
  1738.     Finit(0);
  1739. #ifndef SIGVOID
  1740.   return((sig_t) 0);
  1741. #endif
  1742. }
  1743.  
  1744. /* 
  1745.  * the backend's Interrupt handler
  1746.  * we cannot d_insert the intrc directly, as we never know
  1747.  * if fore is valid.
  1748.  */
  1749. static sig_t
  1750. SigInt(SIGDEFARG)
  1751. {
  1752. #if HAZARDOUS
  1753.   char buf[1];
  1754.  
  1755.   debug("SigInt()\n");
  1756.   *buf = (char) intrc;
  1757.   if (fore)
  1758.     fore->w_inlen = 0;
  1759.   if (fore)
  1760.     write(fore->w_ptyfd, buf, 1);
  1761. #else
  1762.   signal(SIGINT, SigInt);
  1763.   debug("SigInt() careful\n");
  1764.   InterruptPlease = 1;
  1765. #endif
  1766. #ifndef SIGVOID
  1767.   return((sig_t) 0);
  1768. #endif
  1769. }
  1770.  
  1771. static sig_t
  1772. CoreDump(sig)
  1773. int sig;
  1774. {
  1775.   struct display *disp;
  1776.   char buf[80];
  1777.  
  1778. #ifdef SYSVSIGS
  1779.   signal(sig, SIG_IGN);
  1780. #endif /* SYSV */
  1781.   setgid(getgid());
  1782.   setuid(getuid());
  1783.   unlink("core");
  1784.   sprintf(buf, "\r\n[screen caught signal %d.%s]\r\n", sig,
  1785. #if defined(SHADOWPW) && !defined(DEBUG) && !defined(DUMPSHADOW)
  1786.               ""
  1787. #else /* SHADOWPW  && !DEBUG */
  1788.               " (core dumped)"
  1789. #endif /* SHADOWPW  && !DEBUG */
  1790.               );
  1791.   for (disp = displays; disp; disp = disp->_d_next)
  1792.     {
  1793.       fcntl(disp->_d_userfd, F_SETFL, 0);
  1794.       write(disp->_d_userfd, buf, strlen(buf));
  1795.       Kill(disp->_d_userpid, SIG_BYE);
  1796.     }
  1797. #if defined(SHADOWPW) && !defined(DEBUG) && !defined(DUMPSHADOW)
  1798.   eexit(sig);
  1799. #else /* SHADOWPW && !DEBUG */
  1800.   abort();
  1801. #endif /* SHADOWPW  && !DEBUG */
  1802. #ifndef SIGVOID
  1803.   return((sig_t) 0);
  1804. #endif
  1805. }
  1806.  
  1807. static void
  1808. DoWait()
  1809. {
  1810.   register int pid;
  1811.   struct win *p, *next;
  1812. #ifdef BSDWAIT
  1813.   union wait wstat;
  1814. #else
  1815.   int wstat;
  1816. #endif
  1817.  
  1818. #ifdef BSDJOBS
  1819. # ifndef BSDWAIT
  1820.   while ((pid = waitpid(-1, &wstat, WNOHANG | WUNTRACED)) > 0)
  1821. # else
  1822. # ifdef USE_WAIT2
  1823.   /* 
  1824.    * From: rouilj@sni-usa.com (John Rouillard) 
  1825.    * note that WUNTRACED is not documented to work, but it is defined in
  1826.    * /usr/include/sys/wait.h, so it may work 
  1827.    */
  1828.   while ((pid = wait2(&wstat, WNOHANG | WUNTRACED )) > 0)
  1829. #  else /* USE_WAIT2 */
  1830.   while ((pid = wait3(&wstat, WNOHANG | WUNTRACED, (struct rusage *) 0)) > 0)
  1831. #  endif /* USE_WAIT2 */
  1832. # endif
  1833. #else    /* BSDJOBS */
  1834.   while ((pid = wait(&wstat)) < 0)
  1835.     if (errno != EINTR)
  1836.       break;
  1837.   if (pid > 0)
  1838. #endif    /* BSDJOBS */
  1839.     {
  1840.       for (p = windows; p; p = next)
  1841.     {
  1842.       next = p->w_next;
  1843.       if (pid == p->w_pid)
  1844.         {
  1845. #ifdef BSDJOBS
  1846.           if (WIFSTOPPED(wstat))
  1847.         {
  1848.           debug3("Window %d pid %d: WIFSTOPPED (sig %d)\n", p->w_number, p->w_pid, WSTOPSIG(wstat));
  1849. #ifdef SIGTTIN
  1850.           if (WSTOPSIG(wstat) == SIGTTIN)
  1851.             {
  1852.               Msg(0, "Suspended (tty input)");
  1853.               continue;
  1854.             }
  1855. #endif
  1856. #ifdef SIGTTOU
  1857.           if (WSTOPSIG(wstat) == SIGTTOU)
  1858.             {
  1859.               Msg(0, "Suspended (tty output)");
  1860.               continue;
  1861.             }
  1862. #endif
  1863.           /* Try to restart process */
  1864. # ifdef NETHACK    
  1865.                   if (nethackflag)
  1866.             Msg(0, "You regain consciousness.");
  1867.           else
  1868. # endif /* NETHACK */
  1869.           Msg(0, "Child has been stopped, restarting.");
  1870.           if (killpg(p->w_pid, SIGCONT))
  1871.             kill(p->w_pid, SIGCONT);
  1872.         }
  1873.           else
  1874. #endif
  1875.         KillWindow(p);
  1876.           break;
  1877.         }
  1878. #ifdef PSEUDOS
  1879.       if (p->w_pwin && pid == p->w_pwin->p_pid)
  1880.         {
  1881.           debug2("pseudo of win Nr %d died. pid == %d\n", p->w_number, p->w_pwin->p_pid);
  1882.           FreePseudowin(p);
  1883.           break;
  1884.         }
  1885. #endif
  1886.     }
  1887.       if (p == 0)
  1888.     {
  1889.       debug1("pid %d not found - hope that's ok\n", pid);
  1890.     }
  1891.     }
  1892. }
  1893.  
  1894.  
  1895. sig_t
  1896. Finit(i)
  1897. int i;
  1898. {
  1899.   struct win *p, *next;
  1900.  
  1901.   signal(SIGCHLD, SIG_IGN);
  1902.   signal(SIGHUP, SIG_IGN);
  1903.   debug1("Finit(%d);\n", i);
  1904.   for (p = windows; p; p = next)
  1905.     {
  1906.       next = p->w_next;
  1907.       FreeWindow(p);
  1908.     }
  1909.   if (ServerSocket != -1)
  1910.     {
  1911.       debug1("we unlink(%s)\n", SockPath);
  1912. #ifndef NOREUID
  1913.       setreuid(eff_uid, real_uid);
  1914.       setregid(eff_gid, real_gid);
  1915. #endif
  1916.       (void) unlink(SockPath);
  1917. #ifndef NOREUID
  1918.       setreuid(real_uid, eff_uid);
  1919.       setregid(real_gid, eff_gid);
  1920. #endif
  1921.     }
  1922.   for (display = displays; display; display = display->_d_next)
  1923.     {
  1924.       if (d_status)
  1925.     RemoveStatus();
  1926.       FinitTerm();
  1927. #ifdef UTMPOK
  1928.       RestoreLoginSlot();
  1929. #endif
  1930.       AddStr("[screen is terminating]\r\n");
  1931.       Flush();
  1932.       SetTTY(d_userfd, &d_OldMode);
  1933.       fcntl(d_userfd, F_SETFL, 0);
  1934.       freetty();
  1935.       Kill(d_userpid, SIG_BYE);
  1936.     }
  1937.   /*
  1938.    * we _cannot_ call eexit(i) here, 
  1939.    * instead of playing with the Socket above. Sigh.
  1940.    */
  1941.   exit(i);
  1942. #ifndef SIGVOID
  1943.   return((sig_t) 0);
  1944. #endif
  1945. }
  1946.  
  1947. void
  1948. eexit(e)
  1949. int e;
  1950. {
  1951.   if (ServerSocket != -1)
  1952.     {
  1953.       debug1("we unlink(%s)\n", SockPath);
  1954.       setuid(real_uid);
  1955.       setgid(real_gid);
  1956.       (void) unlink(SockPath);
  1957.     }
  1958.   exit(e);
  1959. }
  1960.  
  1961.  
  1962. /*
  1963.  * Detach now has the following modes:
  1964.  *    D_DETACH    SIG_BYE        detach backend and exit attacher
  1965.  *    D_STOP        SIG_STOP    stop attacher (and detach backend)
  1966.  *    D_REMOTE    SIG_BYE        remote detach -- reattach to new attacher
  1967.  *    D_POWER     SIG_POWER_BYE     power detach -- attacher kills his parent
  1968.  *    D_REMOTE_POWER    SIG_POWER_BYE    remote power detach -- both
  1969.  *    D_LOCK        SIG_LOCK    lock the attacher
  1970.  * (jw)
  1971.  * we always remove our utmp slots. (even when "lock" or "stop")
  1972.  * Note: Take extra care here, we may be called by interrupt!
  1973.  */
  1974. void
  1975. Detach(mode)
  1976. int mode;
  1977. {
  1978.   int sign = 0, pid;
  1979. #ifdef UTMPOK
  1980.   struct win *p;
  1981. #endif
  1982.  
  1983.   if (display == 0)
  1984.     return;
  1985.   signal(SIGHUP, SIG_IGN);
  1986.   debug1("Detach(%d)\n", mode);
  1987.   if (d_status)
  1988.     RemoveStatus();
  1989.   FinitTerm();
  1990.   switch (mode)
  1991.     {
  1992.     case D_DETACH:
  1993.       AddStr("[detached]\r\n");
  1994.       sign = SIG_BYE;
  1995.       break;
  1996. #ifdef BSDJOBS
  1997.     case D_STOP:
  1998.       sign = SIG_STOP;
  1999.       break;
  2000. #endif
  2001. #ifdef REMOTE_DETACH
  2002.     case D_REMOTE:
  2003.       AddStr("[remote detached]\r\n");
  2004.       sign = SIG_BYE;
  2005.       break;
  2006. #endif
  2007. #ifdef POW_DETACH
  2008.     case D_POWER:
  2009.       AddStr("[power detached]\r\n");
  2010.       if (PowDetachString) 
  2011.     {
  2012.       AddStr(expand_vars(PowDetachString));
  2013.       AddStr("\r\n");
  2014.     }
  2015.       sign = SIG_POWER_BYE;
  2016.       break;
  2017. #ifdef REMOTE_DETACH
  2018.     case D_REMOTE_POWER:
  2019.       AddStr("[remote power detached]\r\n");
  2020.       if (PowDetachString) 
  2021.     {
  2022.       AddStr(expand_vars(PowDetachString));
  2023.       AddStr("\r\n");
  2024.     }
  2025.       sign = SIG_POWER_BYE;
  2026.       break;
  2027. #endif
  2028. #endif
  2029.     case D_LOCK:
  2030.       ClearDisplay();
  2031.       sign = SIG_LOCK;
  2032.       /* tell attacher to lock terminal with a lockprg. */
  2033.       break;
  2034.     }
  2035. #ifdef UTMPOK
  2036.   if (displays->_d_next == 0)
  2037.     {
  2038.       for (p = windows; p; p = p->w_next)
  2039.     if (p->w_slot != (slot_t) -1)
  2040.       {
  2041.         RemoveUtmp(p);
  2042.         /*
  2043.          * Set the slot to 0 to get the window
  2044.          * logged in again.
  2045.          */
  2046.         p->w_slot = (slot_t) 0;
  2047.       }
  2048.       if (console_window)
  2049.     {
  2050.       if (TtyGrabConsole(console_window->w_ptyfd, 0, "detach"))
  2051.         {
  2052.           debug("could not release console - killing window\n");
  2053.           KillWindow(console_window);
  2054.           display = displays;
  2055.         }
  2056.     }
  2057.     }
  2058.   RestoreLoginSlot();
  2059. #endif
  2060.   if (d_fore)
  2061.     {
  2062.       d_fore->w_active = 0;
  2063.       d_fore->w_display = 0;
  2064.       d_lay = &BlankLayer;
  2065.       d_layfn = d_lay->l_layfn;
  2066.     }
  2067.   while (d_lay != &BlankLayer)
  2068.     ExitOverlayPage();
  2069.   if (d_userfd >= 0)
  2070.     {
  2071.       Flush();
  2072.       SetTTY(d_userfd, &d_OldMode);
  2073.       fcntl(d_userfd, F_SETFL, 0);
  2074.     }
  2075.   freetty();
  2076.   pid = d_userpid;
  2077.   debug2("display: %#x displays: %#x\n", (unsigned int)display, (unsigned int)displays);
  2078.   FreeDisplay();
  2079.   if (displays == 0)
  2080.     /* Flag detached-ness */
  2081.     (void) chsock();
  2082.   /*
  2083.    * tell father to father what to do. We do that after we
  2084.    * freed the tty, thus getty feels more comfortable on hpux
  2085.    * if it was a power detach.
  2086.    */
  2087.   Kill(pid, sign);
  2088.   debug2("Detach: Signal %d to Attacher(%d)!\n", sign, pid);
  2089.   debug("Detach returns, we are successfully detached.\n");
  2090.   signal(SIGHUP, SigHup);
  2091. }
  2092.  
  2093. static int
  2094. IsSymbol(e, s)
  2095. register char *e, *s;
  2096. {
  2097.   register int l;
  2098.  
  2099.   l = strlen(s);
  2100.   return strncmp(e, s, l) == 0 && e[l] == '=';
  2101. }
  2102.  
  2103. void
  2104. MakeNewEnv()
  2105. {
  2106.   register char **op, **np;
  2107.   static char stybuf[MAXSTR];
  2108.  
  2109.   for (op = environ; *op; ++op)
  2110.     ;
  2111.   if (NewEnv)
  2112.     free(NewEnv);
  2113.   NewEnv = np = (char **) malloc((unsigned) (op - environ + 7 + 1) * sizeof(char **));
  2114.   if (!NewEnv)
  2115.     Panic(0, strnomem);
  2116.   SockName = SockNamePtr;
  2117.   if (strlen(SockNamePtr) > MAXSTR - 5)
  2118.     SockName = "?";
  2119.   sprintf(stybuf, "STY=%s", SockNamePtr);
  2120.   *np++ = stybuf;                    /* NewEnv[0] */
  2121.   *np++ = Term;                    /* NewEnv[1] */
  2122.   np++;        /* room for SHELL */
  2123. #ifdef TIOCSWINSZ
  2124.   np += 2;    /* room for TERMCAP and WINDOW */
  2125. #else
  2126.   np += 4;    /* room for TERMCAP WINDOW LINES COLUMNS */
  2127. #endif
  2128.  
  2129.   for (op = environ; *op; ++op)
  2130.     {
  2131.       if (!IsSymbol(*op, "TERM") && !IsSymbol(*op, "TERMCAP")
  2132.       && !IsSymbol(*op, "STY") && !IsSymbol(*op, "WINDOW")
  2133.       && !IsSymbol(*op, "SCREENCAP") && !IsSymbol(*op, "SHELL")
  2134.       && !IsSymbol(*op, "LINES") && !IsSymbol(*op, "COLUMNS")
  2135.      )
  2136.     *np++ = *op;
  2137.     }
  2138.   *np = 0;
  2139. }
  2140.  
  2141. void
  2142. #ifdef USEVARARGS
  2143. /*VARARGS2*/
  2144. # if defined(__STDC__)
  2145. Msg(int err, char *fmt, ...)
  2146. # else /* __STDC__ */
  2147. Msg(err, fmt, va_alist)
  2148. int err;
  2149. char *fmt;
  2150. va_dcl
  2151. # endif /* __STDC__ */
  2152. {
  2153.   static va_list ap;
  2154. #else /* USEVARARRGS */
  2155. /*VARARGS2*/
  2156. Msg(err, fmt, p1, p2, p3, p4, p5, p6)
  2157. int err;
  2158. char *fmt;
  2159. unsigned long p1, p2, p3, p4, p5, p6;
  2160. {
  2161. #endif /* USEVARARRGS */
  2162.   char buf[MAXPATHLEN*2];
  2163.   char *p = buf;
  2164.  
  2165. #ifdef USEVARARGS
  2166. # if defined(__STDC__)
  2167.   va_start(ap, fmt);
  2168. # else /* __STDC__ */
  2169.   va_start(ap);
  2170. # endif /* __STDC__ */
  2171.   (void) vsprintf(p, fmt, ap);
  2172.   va_end(ap);
  2173. #else /* USEVARARRGS */
  2174.   sprintf(p, fmt, p1, p2, p3, p4, p5, p6);
  2175. #endif /* USEVARARRGS */
  2176.   if (err)
  2177.     {
  2178.       p += strlen(p);
  2179.       if (err > 0 && err < sys_nerr)
  2180.     sprintf(p, ": %s", sys_errlist[err]);
  2181.       else
  2182.     sprintf(p, ": Error %d", err);
  2183.     }
  2184.   debug2("Msg('%s') (%#x);\n", buf, (unsigned int)display);
  2185.   if (display)
  2186.     MakeStatus(buf);
  2187.   else if (displays)
  2188.     {
  2189.       for (display = displays; display; display = display->_d_next)
  2190.     MakeStatus(buf);
  2191.     }
  2192.   else
  2193.     printf("%s\r\n", buf);
  2194. }
  2195.  
  2196. void
  2197. #ifdef USEVARARGS
  2198. /*VARARGS2*/
  2199. # if defined(__STDC__)
  2200. Panic(int err, char *fmt, ...)
  2201. # else /* __STDC__ */
  2202. Panic(err, fmt, va_alist)
  2203. int err;
  2204. char *fmt;
  2205. va_dcl
  2206. # endif /* __STDC__ */
  2207. {
  2208.   static va_list ap;
  2209. #else /* USEVARARRGS */
  2210. /*VARARGS2*/
  2211. Panic(err, fmt, p1, p2, p3, p4, p5, p6)
  2212. int err;
  2213. char *fmt;
  2214. unsigned long p1, p2, p3, p4, p5, p6;
  2215. {
  2216. #endif /* USEVARARRGS */
  2217.   char buf[MAXPATHLEN*2];
  2218.   char *p = buf;
  2219.  
  2220. #ifdef USEVARARGS
  2221. # if defined(__STDC__)
  2222.   va_start(ap, fmt);
  2223. # else /* __STDC__ */
  2224.   va_start(ap);
  2225. # endif /* __STDC__ */
  2226.   (void) vsprintf(p, fmt, ap);
  2227.   va_end(ap);
  2228. #else /* USEVARARRGS */
  2229.   sprintf(p, fmt, p1, p2, p3, p4, p5, p6);
  2230. #endif /* USEVARARRGS */
  2231.   if (err)
  2232.     {
  2233.       p += strlen(p);
  2234.       if (err > 0 && err < sys_nerr)
  2235.     sprintf(p, ": %s", sys_errlist[err]);
  2236.       else
  2237.     sprintf(p, ": Error %d", err);
  2238.     }
  2239.   debug1("Panic('%s');\n", buf);
  2240.   if (displays == 0)
  2241.     printf("%s\r\n", buf);
  2242.   else
  2243.     for (display = displays; display; display = display->_d_next)
  2244.       {
  2245.         if (d_status)
  2246.       RemoveStatus();
  2247.         FinitTerm();
  2248.         Flush();
  2249. #ifdef UTMPOK
  2250.         RestoreLoginSlot();
  2251. #endif
  2252.         SetTTY(d_userfd, &d_OldMode);
  2253.         fcntl(d_userfd, F_SETFL, 0);
  2254.         write(d_userfd, buf, strlen(buf));
  2255.         write(d_userfd, "\n", 1);
  2256.         freetty();
  2257.     if (d_userpid)
  2258.       Kill(d_userpid, SIG_BYE);
  2259.       }
  2260. #ifdef MULTIUSER
  2261.   if (tty_oldmode >= 0)
  2262.     {
  2263. # ifdef NOREUID
  2264.       setuid(eff_uid);
  2265. # else
  2266.       setreuid(real_uid, eff_uid);
  2267. # endif
  2268.       debug1("Panic: changing back modes from %s\n", attach_tty);
  2269.       chmod(attach_tty, tty_oldmode);
  2270.     }
  2271. #endif
  2272.   eexit(1);
  2273. }
  2274.  
  2275.  
  2276. /*
  2277.  * '^' is allowed as an escape mechanism for control characters. jw.
  2278.  */
  2279. static char *
  2280. MakeWinMsg(s, n)
  2281. register char *s;
  2282. int n;
  2283. {
  2284.   static char buf[MAXSTR];
  2285.   register char *p = buf;
  2286.   register int ctrl;
  2287.  
  2288.   ctrl = 0;
  2289.   for (; *s && p < buf + MAXSTR - 1; s++, p++)
  2290.     if (ctrl)
  2291.       {
  2292.         ctrl = 0;
  2293.         if (*s == '^' || *s < 64)
  2294.           *p = *s;
  2295.         else 
  2296.           *p = *s - 64;
  2297.       }
  2298.     else
  2299.       {
  2300.         switch (*s)
  2301.           {
  2302.           case '%':
  2303.         sprintf(p, "%d", n);
  2304.         p += strlen(p) - 1;
  2305.         break;
  2306.           case '~':
  2307.         *p = BELL;
  2308.         break;
  2309.       case '^':
  2310.         ctrl = 1;
  2311.         *p-- = '^';
  2312.         break;
  2313.           default:
  2314.         *p = *s;
  2315.         break;
  2316.           }
  2317.       }
  2318.   *p = '\0';
  2319.   return buf;
  2320. }
  2321.  
  2322. void
  2323. DisplaySleep(n)
  2324. int n;
  2325. {
  2326.   char buf;
  2327.   fd_set r;
  2328.   struct timeval t;
  2329.  
  2330.   if (!display)
  2331.     {
  2332.       debug("DisplaySleep has no display sigh\n");
  2333.       sleep(n);
  2334.       return;
  2335.     }
  2336.   t.tv_usec = 0;
  2337.   t.tv_sec = n;
  2338.   FD_ZERO(&r);
  2339.   FD_SET(d_userfd, &r);
  2340.   if (select(FD_SETSIZE, &r, (fd_set *)0, (fd_set *)0, &t) > 0)
  2341.     {
  2342.       debug("display activity stopped sleep\n");
  2343.       read(d_userfd, &buf, 1);
  2344.     }
  2345.   debug1("DisplaySleep(%d) ending\n", n);
  2346. }
  2347.