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