home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / screen3 / part08 / screen.c
Encoding:
C/C++ Source or Header  |  1991-12-18  |  76.7 KB  |  3,721 lines

  1. /* Copyright (c) 1991
  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 1, 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.  * Noteworthy contributors to screen's design and implementation:
  21.  *    Wayne Davison (davison@borland.com)
  22.  *    Patrick Wolfe (pat@kai.com, kailand!pat)
  23.  *    Bart Schaefer (schaefer@cse.ogi.edu)
  24.  *    Nathan Glasser (nathan@brokaw.lcs.mit.edu)
  25.  *    Larry W. Virden (lwv27%cas.BITNET@CUNYVM.CUNY.Edu)
  26.  *    Howard Chu (hyc@hanauma.jpl.nasa.gov)
  27.  *    Tim MacKenzie (tym@dibbler.cs.monash.edu.au)
  28.  *    Markku Jarvinen (mta@{cc,cs,ee}.tut.fi)
  29.  *    Marc Boucher (marc@CAM.ORG)
  30.  *
  31.  ****************************************************************
  32.  */
  33.  
  34. #ifndef lint
  35.   static char rcs_id[] = "$Id: screen.c,v 1.106 91/10/11 11:24:50 jnweiger Exp $ FAU";
  36. #endif
  37.  
  38.  
  39. #if defined(BSD) || defined(sequent) || defined(pyr)
  40. # include <strings.h>
  41. #else
  42. # include <string.h>
  43. #endif
  44. #include <sys/param.h>
  45. #include <signal.h>
  46. #include <ctype.h>
  47. #include <pwd.h>
  48. #include <fcntl.h>
  49. #if defined(SGI)
  50. #include <sys/sysmacros.h>
  51. /* #include <sys/utsname.h> we define SYSV anyway, right? */
  52. #endif
  53. #if !defined(sun) && !defined(B43)
  54. # include <time.h>
  55. #endif
  56. #if defined(sun) || defined(_IBMR2) || defined(sysV68) || defined(MIPS) || defined(GOULD_NP1) || defined(B43)
  57. # include <sys/time.h>
  58. #endif
  59. #ifdef M_XENIX
  60. #include <sys/select.h> /* for timeval */
  61. #endif
  62. #include <sys/types.h>
  63. #if !defined(sysV68) && !defined(M_XENIX)
  64. # include <sys/wait.h>
  65. #endif
  66. #include <sys/stat.h>
  67. #include <sys/file.h>
  68. #ifndef sun
  69. # include <sys/ioctl.h>
  70. #endif /* sun */
  71.  
  72. #include "config.h"
  73.  
  74. #ifdef SVR4
  75. #include <sys/stropts.h>
  76. #endif
  77. #ifdef SYSV
  78. #include <sys/utsname.h>
  79. #endif
  80.  
  81. #if defined(_SEQUENT_) || defined(M_XENIX)
  82. /* for the FD.. stuff */
  83. # include <sys/select.h>
  84. #endif 
  85. #ifdef sequent
  86. # include <sys/resource.h>
  87. #endif /* sequent */
  88.  
  89. #include "screen.h"
  90. #include "patchlevel.h"
  91.  
  92. #if defined(xelos) || defined(sysV68) || defined(M_XENIX)
  93.  struct passwd *getpwuid __P((uid_t));
  94.  struct passwd *getpwnam __P((char *));
  95. #endif
  96.  
  97. #ifdef USEVARARGS
  98. # if defined(__STDC__)
  99. #  include <stdarg.h>
  100. # else
  101. #  include <varargs.h>
  102. # endif
  103. #endif
  104.  
  105. #ifdef DEBUG
  106. FILE *dfp;
  107. #endif
  108.  
  109.  
  110. #ifdef COPY_PASTE
  111. extern char *copybuffer;    /* def in mark.c jw. */
  112. extern copylen;
  113. #endif /* COPY_PASTE */
  114.  
  115. extern char *blank, *null, Term[], screenterm[], **environ, *Termcap;
  116. int force_vt = 1, assume_LP = 0;
  117. extern int in_ovl;
  118. extern int ovl_blockfore;
  119. extern void (*ovl_process)();
  120. extern int help_page;
  121. extern int screenwidth, screenheight;
  122. extern int default_width, default_height;
  123. extern int Z0width, Z1width;
  124. extern int ISO2022;
  125. extern int status, HS;
  126. extern char *Z0, *WS, *LastMsg;
  127. extern time_t TimeDisplayed;
  128. int BellDisplayed;
  129. int VBellWait, MsgWait, MsgMinWait;
  130.  
  131. /* tputs uses that: jw */
  132. extern short ospeed;
  133.  
  134. extern flowctl, wrap, visual_bell, default_monitor;
  135. extern int errno;
  136. extern sys_nerr;
  137. extern char *sys_errlist[];
  138. extern char mark_key_tab[];
  139.  
  140. #ifdef TIOCGWINSZ
  141. extern struct winsize glwz;
  142. #endif
  143.  
  144. static char *MakeWinMsg __P((char *, int));
  145. static void MakeNewEnv __P((void));
  146. static int Attach __P((int));
  147. static void Attacher __P((void));
  148. static void SigHandler __P((void));
  149. static sig_t SigChld __P(SIGPROTOARG);
  150. static sig_t SigInt __P(SIGPROTOARG);
  151. static sig_t CoreDump __P((int));
  152. static void DoWait __P((void));
  153. static sig_t Finit __P((int));
  154. static void InitKeytab __P((void));
  155. static void SetForeWindow __P((int));
  156. static int NextWindow __P((void));
  157. static int PreviousWindow __P((void));
  158. static int MoreWindows __P((void));
  159. static void FreeWindow __P((struct win *));
  160. static void execvpe __P((char *, char **, char **));
  161. static void LogToggle __P((void));
  162. static void ShowWindows __P((void));
  163. static void ShowTime __P((void));
  164. static void ShowInfo __P((void));
  165. static int OpenPTY __P((void));
  166. static void trysend __P((int, struct msg *, char *));
  167. #if defined(SIGWINCH) && defined(TIOCGWINSZ)
  168. static sig_t SigAttWinch __P(SIGPROTOARG);
  169. #endif
  170. static void fgtty __P((void));
  171. static void freetty __P((void));
  172. #ifdef BSDJOBS
  173. static void brktty __P((void));
  174. #endif
  175.  
  176. #if defined(LOCK)
  177. static sig_t DoLock __P(SIGPROTOARG);
  178. static void LockTerminal __P((void));
  179. #endif
  180.  
  181. #ifdef COPY_PASTE
  182. static pastelen;
  183. static char *pastebuffer;
  184. #endif
  185. #ifdef PASSWORD
  186. extern char Password[];
  187. #endif
  188.  
  189. static struct passwd *ppp;
  190. static char PtyName[32], TtyName[32];
  191. char *ShellProg;
  192. char *ShellArgs[2];
  193. static char inbuf[MAXWIN][IOSIZE];
  194. static inlen[MAXWIN];
  195. static inbuf_ct;
  196. static ESCseen;
  197. static GotSignal;
  198.  
  199. static char DefaultShell[] = "/bin/sh";
  200. static char DefaultPath[] = ":/usr/ucb:/bin:/usr/bin";
  201. #if !(defined(sequent) || defined(_SEQUENT_) || defined(SVR4))
  202. static char PtyProto[] = "/dev/ptyXY";
  203. static char TtyProto[] = "/dev/ttyXY";
  204. #endif
  205. int TtyMode = 0622;
  206. #ifdef SOCKDIR
  207. char *SockDir = SOCKDIR;
  208. #else
  209. char *SockDir = ".screen";
  210. #endif
  211. extern char SockPath[], *SockNamePtr, *SockName;
  212. int ServerSocket = -1;
  213. static char **NewEnv;
  214.  
  215. char *RcFileName = NULL;
  216. char Esc = Ctrl('a');
  217. char MetaEsc = 'a';
  218. char *home;
  219.  
  220. int HasWindow;
  221. char *LoginName;
  222. char *BellString;
  223. char *VisualBellString;
  224. char *ActivityString;
  225. char *PowDetachString;
  226. int auto_detach = 1;
  227. int iflag, mflag, rflag, dflag, lsflag, quietflag, wipeflag;
  228. int adaptflag, loginflag = -1;
  229. static intrc, startc, stopc;
  230. char HostName[MAXSTR];
  231. int Detached, Suspended;
  232. int DeadlyMsg = 1;
  233. int AttacherPid;    /* Non-Zero in child if we have an attacher */
  234. int real_uid, real_gid, eff_uid, eff_gid;
  235. int default_histheight;
  236. int default_startup;
  237. int slowpaste;
  238.  
  239. #if !defined(POSIX) && defined(BSDJOBS)
  240. int DevTty = -1;
  241. #endif
  242.  
  243. #ifdef NETHACK
  244. int nethackflag = 0;
  245. #endif
  246.  
  247. struct mode OldMode, NewMode;
  248.  
  249. struct win *fore = NULL;
  250. int WinList = -1;
  251. int ForeNum;
  252. struct win *wtab[MAXWIN];
  253.  
  254. struct key ktab[256];
  255.  
  256. #ifndef FD_SET
  257. typedef struct fd_set
  258. {
  259.   int fd_bits[1];
  260. }      fd_set;
  261. # define FD_ZERO(fd) ((fd)->fd_bits[0] = 0)
  262. # define FD_SET(b,fd) ((fd)->fd_bits[0] |= 1 << (b))
  263. # define FD_ISSET(b,fd) ((fd)->fd_bits[0] & 1 << (b))
  264. # define FD_SETSIZE 32
  265. #endif
  266.  
  267.  
  268. #ifndef WTERMSIG
  269. # ifndef BSDWAIT /* if wait is NOT a union: */
  270. #  define WTERMSIG(status) (status & 0177)
  271. # else
  272. #  define WTERMSIG(status) status.w_T.w_Termsig 
  273. # endif
  274. #endif
  275.  
  276. #ifndef WIFCORESIG
  277. # ifndef BSDWAIT /* if wait is NOT a union: */
  278. #  define WIFCORESIG(status) (status & 0200)
  279. # else
  280. #  define WIFCORESIG(status) status.w_T.w_Coredump
  281. # endif
  282. #endif
  283.  
  284. #ifndef WEXITSTATUS
  285. # ifndef BSDWAIT /* if wait is NOT a union: */
  286. #  define WEXITSTATUS(status) ((status >> 8) & 0377)
  287. # else
  288. #  define WEXITSTATUS(status) status.w_T.w_Retcode
  289. # endif
  290. #endif
  291.  
  292. char *shellaka = NULL;
  293.  
  294. /*
  295.  * Do this last
  296.  */
  297. #include "extern.h"
  298.  
  299. /*
  300.  * XXX: Missing system header files.
  301.  */
  302. #ifdef USEVARARGS
  303. #ifdef SVR4
  304. int vsprintf __P((char *, const char *, va_list));
  305. #else
  306. int vsprintf __P((char *, char *, va_list));
  307. #endif
  308. #endif
  309. int select __P((int, fd_set *, fd_set *, fd_set *, struct timeval *));
  310.  
  311. #ifdef BSDJOBS
  312. static void
  313. brktty()
  314. {
  315. # ifdef POSIX
  316.   setsid();        /* will break terminal affilition */
  317. # else
  318.   if (DevTty)
  319.     if (ioctl(DevTty, TIOCNOTTY, (char *) 0) != 0)
  320.       debug2("brktty: ioctl(DevTty=%d, TIOCNOTTY, 0) = %d\n", DevTty, errno);
  321. # endif
  322. }
  323. #endif
  324.  
  325. static void
  326. freetty()
  327. {
  328. #ifdef BSDJOBS
  329.   brktty();
  330. # ifndef POSIX
  331.   if (DevTty >= 0)
  332.     {
  333.       close(DevTty);
  334.       DevTty = -1;
  335.     }
  336. # endif
  337. #endif
  338.   close(0);
  339.   close(1);
  340.   close(2);
  341. }
  342.  
  343. static void
  344. fgtty()
  345. {
  346. #ifdef BSDJOBS
  347.   int mypid;
  348.  
  349.   mypid = getpid();
  350. # ifdef POSIX
  351.   if (tcsetpgrp(0, mypid))
  352. # else
  353.   if (ioctl(0, TIOCSPGRP, &mypid) != 0)
  354. # endif
  355.     debug1("fgtty: tcsetpgrp: %d\n", errno);
  356. # ifdef POSIX
  357. #  ifdef SVR4
  358.   if (getpgid(0) != mypid)
  359. #   endif
  360.   if (setpgid(0, mypid))
  361. # else
  362.   if (setpgrp(0, mypid))
  363. # endif
  364.     debug1("fgtty: setpgid: %d\n", errno);
  365. #endif
  366. }
  367.  
  368. #ifdef hpux
  369. /*
  370.  * hpux has berkeley signal semantics if we use sigvector,
  371.  * but not, if we use signal, so we define our own signal() routine.
  372.  * (jw)
  373.  */
  374. void (*signal(sig, func)) ()
  375. int sig;
  376. void (*func) ();
  377. {
  378.   struct sigvec osv, sv;
  379.  
  380.   sv.sv_handler = func;
  381.   sv.sv_mask = sigmask(sig);
  382.   sv.sv_flags = SV_BSDSIG;
  383.   if (sigvector(sig, &sv, &osv) < 0)
  384.     return (BADSIG);
  385.   return (osv.sv_handler);
  386. }
  387. #endif    /* hpux */
  388.  
  389. #ifndef USEBCOPY
  390. void bcopy(s1, s2, len)
  391. register char *s1, *s2;
  392. register int len;
  393. {
  394.   if (s1 < s2 && s2 < s1 + len)
  395.     {
  396.       s1 += len;
  397.       s2 += len;
  398.       while (len-- > 0)
  399.     *--s2 = *--s1;
  400.     }
  401.   else
  402.     while (len-- > 0)
  403.       *s2++ = *s1++;
  404. }
  405. #endif    /* USEBCOPY */
  406.  
  407. void bclear(p, n)
  408. int n;
  409. char *p;
  410. {
  411.   bcopy(blank, p, n);
  412. }
  413.  
  414. void main(ac, av)
  415. int ac;
  416. char **av;
  417. {
  418.   register int n, len;
  419.   register struct win *p;
  420.   char *ap, *aka = NULL;
  421.   char *av0;
  422.   int s = 0;
  423.   fd_set r, w;
  424.   int aflag = 0;
  425.   struct timeval tv;
  426.   int nsel;
  427.   char buf[IOSIZE], *bufp, *myname = (ac == 0) ? "screen" : av[0];
  428.   struct stat st;
  429.   int buflen, tmp;
  430. #ifdef _MODE_T            /* (jw) */
  431.   mode_t oumask;
  432. #else
  433.   int oumask;
  434. #endif
  435. #ifdef SYSV
  436.   struct utsname utsnam;
  437. #endif
  438.  
  439. /*
  440.  *  First, close all unused descriptors
  441.  *  (otherwise, we might have problems with the select() call)
  442.  */
  443. #ifdef SYSV
  444.   for (n = NOFILE - 1; n > 2; n--)
  445.     close(n);
  446. #else
  447.   for (n = getdtablesize() - 1; n > 2; n--)
  448.     close(n);
  449. #endif
  450. #ifdef DEBUG
  451.   (void) mkdir("/tmp/debug", 0777);
  452.   if ((dfp = fopen("/tmp/debug/screen.front", "w")) == NULL)
  453.     dfp = stderr;
  454.   else
  455.     (void) chmod("/tmp/debug/screen.front", 0666);
  456. #endif
  457.   debug1("-- screen debug started %s\n", *av);
  458. #ifdef POSIX
  459.   debug("POSIX\n");
  460. #endif
  461. #ifdef TERMIO
  462.   debug("TERMIO\n");
  463. #endif
  464. #ifdef SYSV
  465.   debug("SYSV\n");
  466. #endif
  467. #ifdef NAMEDPIPE
  468.   debug("NAMEDPIPE\n");
  469. #endif
  470. #if defined(SIGWINCH) && defined(TIOCGWINSZ)
  471.   debug("Window changing enabled\n");
  472. #endif
  473. #ifdef NOREUID
  474.   debug("NOREUID\n");
  475. #endif
  476. #ifdef hpux
  477.   debug("hpux\n");
  478. #endif
  479. #ifdef USEBCOPY
  480.   debug("USEBCOPY\n");
  481. #endif
  482. #ifdef UTMPOK
  483.   debug("UTMPOK\n");
  484. #endif
  485. #ifdef LOADAV
  486.   debug("LOADAV\n");
  487. #endif
  488. #ifdef NETHACK
  489.   debug("NETHACK\n");
  490. #endif
  491. #ifdef TERMINFO
  492.   debug("TERMINFO\n");
  493. #endif
  494.  
  495.   BellString = SaveStr("Bell in window %");
  496.   VisualBellString = SaveStr("   Wuff,  Wuff!!  ");
  497.   ActivityString = SaveStr("Activity in window %");
  498.   PowDetachString = 0;
  499.   default_histheight = DEFAULTHISTHEIGHT;
  500.   default_startup = (ac > 1) ? 0 : 1;
  501.   adaptflag = 0;
  502.   slowpaste = 0;
  503.   VBellWait = VBELLWAIT;
  504.   MsgWait = MSGWAIT;
  505.   MsgMinWait = MSGMINWAIT;
  506.   CompileKeys(NULL, mark_key_tab);
  507.  
  508.   av0 = *av;
  509.   while (ac > 0)
  510.     {
  511.       ap = *++av;
  512.       if (--ac > 0 && *ap == '-')
  513.     {
  514.       switch (ap[1])
  515.         {
  516.         case 'a':
  517.           aflag = 1;
  518.           break;
  519.         case 'A':
  520.           adaptflag = 1;
  521.           break;
  522.         case 'c':
  523.           if (ap[2])
  524.         RcFileName = ap + 2;
  525.           else
  526.         {
  527.           if (--ac == 0)
  528.             exit_with_usage(myname);
  529.           RcFileName = *++av;
  530.         }
  531.           break;
  532.         case 'e':
  533.           if (ap[2])
  534.         ap += 2;
  535.           else
  536.         {
  537.           if (--ac == 0)
  538.             exit_with_usage(myname);
  539.           ap = *++av;
  540.         }
  541.           if (!ParseEscape(ap))
  542.         Msg(0, "Two characters are required with -e option.");
  543.           break;
  544.         case 'f':
  545.           switch (ap[2])
  546.         {
  547.         case 'n':
  548.         case '0':
  549.           flowctl = 1;
  550.           break;
  551.         case 'y':
  552.         case '1':
  553.         case '\0':
  554.           flowctl = 2;
  555.           break;
  556.         case 'a':
  557.           flowctl = 3;
  558.           break;
  559.         default:
  560.           exit_with_usage(myname);
  561.         }
  562.           break;
  563.             case 'h':
  564.           if (ap[2])
  565.         default_histheight = atoi(ap + 2);
  566.           else
  567.         {
  568.           if (--ac == 0)
  569.             exit_with_usage(myname);
  570.           default_histheight = atoi(*++av);
  571.         }
  572.           if (default_histheight < 0)
  573.         default_histheight = 0;
  574.           break;
  575.         case 'i':
  576.           iflag = 1;
  577.           break;
  578.         case 't': /* title is a synonym for AkA */
  579.         case 'k':
  580.           if (ap[2])
  581.         aka = ap + 2;
  582.           else
  583.         {
  584.           if (--ac == 0)
  585.             exit_with_usage(myname);
  586.           aka = *++av;
  587.         }
  588.           break;
  589.         case 'l':
  590.           switch (ap[2])
  591.         {
  592.         case 'n':
  593.         case '0':
  594.           loginflag = 0;
  595.           break;
  596.         case 'y':
  597.         case '1':
  598.         case '\0':
  599.           loginflag = 1;
  600.           break;
  601.         case 's':
  602.         case 'i':
  603.           lsflag = 1;
  604.           break;
  605.         default:
  606.           exit_with_usage(myname);
  607.         }
  608.           break;
  609.         case 'w':
  610.           lsflag = 1;
  611.           wipeflag = 1;
  612.           break;
  613.         case 'L':
  614.           assume_LP = 1;
  615.           break;
  616.         case 'm':
  617.           mflag = 1;
  618.           break;
  619.         case 'O':
  620.           force_vt = 0;
  621.           break;
  622.         case 'T':
  623.               if (ap[2])
  624.         {
  625.           if ((unsigned)strlen(ap+2) < 20)
  626.                     strcpy(screenterm, ap + 2);
  627.         }
  628.               else
  629.                 {
  630.                   if (--ac == 0)
  631.                     exit_with_usage(myname);
  632.           if ((unsigned)strlen(*++av) < 20)
  633.                     strcpy(screenterm, *av);
  634.                 }
  635.               break;
  636.         case 'q':
  637.           quietflag = 1;
  638.           break;
  639.         case 'r':
  640.           if (ap[2])
  641.         {
  642.           SockName = ap + 2;
  643.           if (ac != 1)
  644.             exit_with_usage(myname);
  645.         }
  646.           else if (--ac == 1)
  647.         {
  648.           if (*av[1] != '-')
  649.             SockName = *++av;
  650.         }
  651.           else if (ac != 0)
  652.         exit_with_usage(myname);
  653.           rflag = 1;
  654.           break;
  655.         case 'R':
  656.           rflag = 2;
  657.           break;
  658. #ifdef REMOTE_DETACH
  659.         case 'd':
  660.           dflag = 1;
  661.           /* FALLTHRU */
  662.         case 'D':
  663.           if (!dflag)
  664.         dflag = 2;
  665.           if (ap[2])
  666.         SockName = ap + 2;
  667.           if (ac == 2)
  668.         {
  669.           if (*av[1] != '-')
  670.             {
  671.               SockName = *++av;
  672.               ac--;
  673.             }
  674.         }
  675.           break;
  676. #endif
  677.         case 's':
  678.           if (ap[2])
  679.         ShellProg = ap + 2;
  680.           else
  681.         {
  682.           if (--ac == 0)
  683.             exit_with_usage(myname);
  684.           ShellProg = *++av;
  685.         }
  686.           break;
  687.         default:
  688.           exit_with_usage(myname);
  689.         }
  690.     }
  691.       else
  692.     break;
  693.     }
  694.   real_uid = getuid();
  695.   real_gid = getgid();
  696.   eff_uid = geteuid();
  697.   eff_gid = getegid();
  698.   if (!ShellProg && (ShellProg = getenv("SHELL")) == 0)
  699.     ShellProg = DefaultShell;
  700.   ShellArgs[0] = ShellProg;
  701. #ifdef NETHACK
  702.   nethackflag = (getenv("NETHACKOPTIONS") != NULL);
  703. #endif
  704.   home = getenv("HOME");    /* may or may not return a result. jw. */
  705.   if ((LoginName = getlogin()) == 0 || LoginName[0] == '\0')
  706.     {
  707.       if ((ppp = getpwuid(real_uid)) == 0)
  708.         {
  709. #ifdef NETHACK
  710.           if (nethackflag)
  711.         Msg(0, "An alarm sounds through the dungeon...\nWarning, the kops are coming.");
  712.       else
  713. #endif
  714.       Msg(0, "getpwuid() can't identify your account!");
  715.       exit(1);
  716.         }
  717.       LoginName = ppp->pw_name;
  718.     }
  719.   /* is anyone cheating? jw. */
  720.   if (((ppp != (struct passwd *) 0) && (LoginName == ppp->pw_name)) ||
  721.       ((ppp = getpwnam(LoginName)) != (struct passwd *) 0))
  722.     {
  723.       if (ppp->pw_uid != real_uid)
  724.     {
  725. #ifdef NETHACK
  726.           if (nethackflag)
  727.         Msg(0, "You cannot resist to mimic a pile of gold.\nThe system ignores you.");
  728.       else
  729. #endif
  730.       Msg(0, "getuid() and pw_uid don't match!");
  731.       exit(1);
  732.     }
  733.     }
  734.   else
  735.     {
  736. #ifdef NETHACK
  737.       if (nethackflag)
  738.         Msg(0, "An alarm sounds through the dungeon...\nWarning, the kops are after you.");
  739.       else
  740. #endif
  741.       Msg(0, "getpwnam() can't identify your account!");
  742.       exit(1);
  743.     }
  744.   if (home == 0 || *home == '\0')
  745.     home = ppp->pw_dir;
  746.   if ((unsigned)strlen(LoginName) > 20)
  747.     Msg(0, "LoginName too long - sorry.");
  748.   if ((unsigned)strlen(home) > MAXPATH - 25)
  749.     Msg(0, "$HOME too long - sorry.");
  750. #ifdef PASSWORD
  751.   strcpy(Password, ppp->pw_passwd);
  752. #endif
  753.  
  754.   if (!isatty(0))
  755.     {
  756. #ifdef NETHACK
  757.       if (nethackflag)
  758.     Msg(0, "You must play from a terminal.");
  759.       else
  760. #endif
  761.       Msg(0, "Must be connected to a terminal.");
  762.       exit(1);
  763.     }
  764. #ifdef _MODE_T
  765.   oumask = umask(0);        /* well, unsigned never fails? jw. */
  766. #else
  767.   if ((oumask = umask(0)) == -1)
  768.     Msg(errno, "Cannot change umask to zero");
  769. #endif
  770.   if ((SockDir = getenv("ISCREENDIR")) == NULL)
  771.     SockDir = getenv("SCREENDIR");
  772.   if (SockDir && (unsigned)strlen(SockDir) >= MAXPATH - 1)
  773.     Msg(0, "ridiculous long $(I)SCREENDIR - try again.");
  774. #ifndef SOCKDIR
  775.   if (SockDir == 0)
  776.     {
  777.       sprintf(SockPath, "%s/.screen", home);
  778.       SockDir = SockPath;
  779.     }
  780. #endif
  781.   if (SockDir)
  782.     {
  783.       if (access(SockDir, F_OK))
  784.     {
  785.       if (UserContext() > 0)
  786.         {
  787.           if (mkdir(SockDir, 0700))
  788.         UserReturn(0);
  789.           UserReturn(1);
  790.         }
  791.       if (UserStatus() <= 0)
  792.         Msg(0, "Cannot make directory '%s'", SockDir);
  793.     }
  794.       if (SockDir != SockPath)
  795.         strcpy(SockPath, SockDir);
  796.     }
  797. #ifdef SOCKDIR
  798.   else
  799.     {
  800.       SockDir = SOCKDIR;
  801.       if (stat(SockDir, &st))
  802.     {
  803.       if (mkdir(SockDir, eff_uid ? 0777 : 0755) == -1)
  804.         Msg(errno, "Cannot make directory '%s'", SockDir);
  805.     }
  806.       else
  807.     {
  808.           n = eff_uid ? 0777 : 0755;
  809.       if ((st.st_mode & 0777) != n)
  810.         Msg(0, "Directory '%s' must have mode %03o.", SockDir, n);
  811.     }
  812.       sprintf(SockPath, "%s/S-%s", SockDir, LoginName);
  813.       if (access(SockPath, F_OK))
  814.     {
  815.       if (mkdir(SockPath, 0700) == -1)
  816.         Msg(errno, "Cannot make directory '%s'", SockPath);
  817.       (void) chown(SockPath, real_uid, real_gid);
  818.     }
  819.     }
  820. #endif
  821.   if (stat(SockPath, &st) == -1)
  822.     {
  823.       Msg(errno, "Cannot access %s", SockPath);
  824.     }
  825.   else
  826.     {
  827.       if ((st.st_mode & S_IFMT) != S_IFDIR)
  828.     Msg(0, "%s is not a directory.", SockPath);
  829.       if (st.st_uid != real_uid)
  830.     Msg(0, "You are not the owner of %s.", SockPath);
  831.       if ((st.st_mode & 0777) != 0700)
  832.     Msg(0, "Directory %s must have mode 700.", SockPath);
  833.     }
  834.   strcat(SockPath, "/");
  835.   SockNamePtr = SockPath + strlen(SockPath);
  836.   (void) umask(oumask);
  837. #ifdef SYSV
  838.   if (uname(&utsnam) == -1)
  839.     Msg(0, "uname() failed, errno = %d", errno);
  840.   else
  841.     {
  842.       strncpy(HostName, utsnam.nodename, MAXSTR);
  843.       HostName[(sizeof(utsnam.nodename) <= MAXSTR) ? 
  844.                sizeof(utsnam.nodename) : MAXSTR] = '\0';
  845.     }
  846. #else
  847.   (void) gethostname(HostName, MAXSTR);
  848. #endif
  849.   HostName[MAXSTR - 1] = '\0';
  850.   if ((ap = index(HostName, '.')) != NULL)
  851.     *ap = '\0';
  852.   GetTTY(0, &OldMode);
  853. #ifdef POSIX
  854.   ospeed = (short) cfgetospeed(&OldMode.tio);
  855. #else
  856. # ifndef TERMIO
  857.   ospeed = (short) OldMode.m_ttyb.sg_ospeed;
  858. # endif
  859. #endif
  860.   debug1("...setting extern short ospeed = %d\n", ospeed);
  861.  
  862.   if (lsflag)
  863.     {
  864.       int i;
  865.       i = FindSocket(0, NULL);
  866.       /* MakeClientSocket appended the last SockName there: */
  867.       *SockNamePtr = '\0';
  868.       if (i == 0)
  869.     {
  870. #ifdef NETHACK
  871.           if (nethackflag)
  872.         Msg(0, "This room is empty (%s)\n", SockPath);
  873.           else
  874. #endif                /* NETHACK */
  875.           Msg(0, "No Sockets found in %s\n", SockPath);
  876.         }
  877.       else
  878.         Msg(0, "%d Socket%s in %s.\n", i, i > 1 ? "s" : "", SockPath);
  879.         /* NOTREACHED */
  880.     }
  881.   if (rflag)
  882.     {
  883.       debug("screen -r: - is there anybody out there?\n");
  884.       if (Attach(MSG_ATTACH))
  885.     {
  886.       Attacher();
  887.       /* NOTREACHED */
  888.     }
  889.       debug("screen -r: backend not responding -- still crying\n");
  890.     }
  891.   else if (dflag)
  892.     {
  893.       (void) Attach(MSG_DETACH);
  894.       DeadlyMsg = 0;
  895.       Msg(0, "[%s %sdetached.]\n", SockName, (dflag > 1 ? "power " : ""));
  896.       eexit(0);
  897.       /* NOTREACHED */
  898.     }
  899.   if (GetSockName())
  900.     {
  901.       s = MakeClientSocket(1, SockName);
  902.       if (ac == 0)
  903.     {
  904.       ac = 1;
  905.       av = ShellArgs;
  906.     }
  907.       av[ac] = aka;
  908.       SendCreateMsg(s, ac, av, aflag, flowctl, loginflag, default_histheight,
  909.             screenterm);
  910.       close(s);
  911.       exit(0);
  912.     }
  913. #if !defined(POSIX) && defined(BSDJOBS)
  914.   if ((DevTty = open("/dev/tty", O_RDWR | O_NDELAY)) == -1)
  915.     Msg(errno, "/dev/tty");
  916. #endif
  917.   switch (fork())
  918.     {
  919.     case -1:
  920.       Msg(errno, "fork");
  921.       /* NOTREACHED */
  922.     case 0:
  923.       break;
  924.     default:
  925.       Attacher();
  926.       /* NOTREACHED */
  927.     }
  928. #ifdef DEBUG
  929.   if (dfp != stderr)
  930.     fclose(dfp);
  931.   if ((dfp = fopen("/tmp/debug/screen.back", "w")) == NULL)
  932.     dfp = stderr;
  933.   else
  934.     (void) chmod("/tmp/debug/screen.back", 0666);
  935. #endif
  936.   debug("-- screen.back debug started\n");
  937.   ap = av0 + strlen(av0) - 1;
  938.   while (ap >= av0)
  939.     {
  940.       if (!strncmp("screen", ap, 6))
  941.     {
  942.       strncpy(ap, "SCREEN", 6); /* name this process "SCREEN-BACKEND" */
  943.       break;
  944.     }
  945.       ap--;
  946.     }
  947.   if (ap < av0)
  948.     *av0 = 'S';
  949.  
  950.   AttacherPid = getppid();
  951.   ServerSocket = s = MakeServerSocket();
  952. #ifdef ETCSCREENRC
  953.   if ((ap = getenv("SYSSCREENRC")) == NULL)
  954.     StartRc(ETCSCREENRC);
  955.   else
  956.     StartRc(ap);
  957. #endif
  958.   StartRc(RcFileName);
  959.   InitTermcap();
  960.   InitTerm(0);
  961.   MakeNewEnv();
  962. #ifdef UTMPOK
  963.   InitUtmp();
  964. #endif
  965. #ifdef LOADAV
  966.   InitKmem();
  967. #endif
  968.   signal(SIGHUP, SigHup);
  969.   signal(SIGINT, Finit);
  970.   signal(SIGQUIT, Finit);
  971.   signal(SIGTERM, Finit);
  972. #ifdef BSDJOBS
  973.   signal(SIGTTIN, SIG_IGN);
  974.   signal(SIGTTOU, SIG_IGN);
  975. #endif
  976.   if (eff_uid != real_uid)
  977.     {        
  978.       /* if running with s-bit, we must install a special signal
  979.        * handler routine that resets the s-bit, so that we get a
  980.        * core file anyway.
  981.        */
  982.       signal(SIGBUS, CoreDump);
  983.       signal(SIGSEGV, CoreDump);
  984.     }
  985.   InitKeytab();
  986. #ifdef ETCSCREENRC
  987.   if ((ap = getenv("SYSSCREENRC")) == NULL)
  988.     FinishRc(ETCSCREENRC);
  989.   else
  990.     FinishRc(ap);
  991. #endif
  992.   FinishRc(RcFileName);
  993.   SetMode(&OldMode, &NewMode);
  994.   SetTTY(0, &NewMode);
  995.   if (loginflag == -1)
  996.       loginflag = LOGINDEFAULT;
  997.   if (ac == 0)
  998.     {
  999.       ac = 1;
  1000.       av = ShellArgs;
  1001.       if (!aka)
  1002.     aka = shellaka;
  1003.     }
  1004.   if (!HasWindow)
  1005.     {
  1006.       debug("We open one default window, as screenrc did not specify one.\n");
  1007.       if (MakeWindow(aka, av, aflag, flowctl, 0, (char *) 0, loginflag, -1, 0) == -1)
  1008.     {
  1009.       Finit(1);
  1010.       /* NOTREACHED */
  1011.     }
  1012.     }
  1013.   if (default_startup)
  1014.     display_copyright();
  1015. #ifdef SYSV
  1016.   signal(SIGCLD, SigChld);
  1017. #else
  1018.   signal(SIGCHLD, SigChld);
  1019. #endif
  1020.   signal(SIGINT, SigInt);
  1021.   tv.tv_usec = 0;
  1022.   if (rflag == 2)
  1023.     {
  1024. #ifdef NETHACK
  1025.       if (nethackflag)
  1026.         Msg(0, "I can't seem to find a... Hey, wait a minute!  Here comes a screen now.");
  1027.       else
  1028. #endif
  1029.       Msg(0, "New screen...");
  1030.       rflag = 0;
  1031.     }
  1032. #ifdef BSDJOBS
  1033.   brktty();
  1034. #endif
  1035.   for (;;)
  1036.     {
  1037.       /*
  1038.        * check to see if message line should be removed
  1039.        */
  1040.       if (status)
  1041.     {
  1042.       int time_left;
  1043.  
  1044.       debug("checking status...\n");
  1045.       time_left = TimeDisplayed + (BellDisplayed ? VBellWait : MsgWait) - time((time_t *)0);
  1046.       if (time_left > 0)
  1047.         {
  1048.           tv.tv_sec = time_left;
  1049.           debug(" not yet.\n");
  1050.         }
  1051.       else
  1052.         {
  1053.           debug(" removing now.\n");
  1054.           RemoveStatus();
  1055.         }
  1056.     }
  1057.       /*
  1058.        * check for I/O on all available I/O descriptors
  1059.        */
  1060.       FD_ZERO(&r);
  1061.       FD_ZERO(&w);
  1062.       if (inbuf_ct > 0)
  1063.     for (n = 0; n < MAXWIN; n++)
  1064. #ifdef COPY_PASTE        /* wrong here? jw. */
  1065.       if (inlen[n] > 0 || (pastelen > 0 && n == ForeNum))
  1066. #else
  1067.       if (inlen[n] > 0)
  1068. #endif
  1069.         FD_SET(wtab[n]->ptyfd, &w);
  1070.       if (!Detached)
  1071.     FD_SET(0, &r);
  1072.       for (n = WinList; n != -1; n = p->WinLink)
  1073.     {
  1074.       p = wtab[n];
  1075.       if (p->active && status && !BellDisplayed && !HS)
  1076.         continue;
  1077.       if (p->outlen > 0)
  1078.         continue;
  1079.       if (in_ovl && ovl_blockfore && n == ForeNum)
  1080.         continue;
  1081.       FD_SET(p->ptyfd, &r);
  1082.     }
  1083.       FD_SET(s, &r);
  1084.       (void) fflush(stdout);
  1085.       if (GotSignal && !status)
  1086.     {
  1087.       SigHandler();
  1088.       continue;
  1089.     }
  1090.       if ((nsel = select(FD_SETSIZE, &r, &w, 0, status ? &tv : (struct timeval *) 0)) < 0)
  1091.     {
  1092.       debug1("Bad select - errno %d\n",errno);
  1093.       if (errno == EINTR)
  1094.         {
  1095.           errno = 0;
  1096.           continue;
  1097.         }
  1098.       perror("select");
  1099.       Finit(1);
  1100.       /* NOTREACHED */
  1101.     }
  1102.       if (GotSignal && !status)
  1103.     {
  1104.       SigHandler();
  1105.       continue;
  1106.     }
  1107.       /* Process a client connect attempt and message */
  1108.       if (nsel && FD_ISSET(s, &r))
  1109.     {
  1110.           nsel--;
  1111.       if (!HS)
  1112.         RemoveStatus();
  1113.       if (in_ovl)
  1114.         {
  1115.           SetOvlCurr();
  1116.           (*ovl_process)(0,0); /* We have to abort first!! */
  1117.           CheckScreenSize(1); /* Change fore */
  1118. #ifdef NETHACK
  1119.               if (nethackflag)
  1120.             Msg(0, "KAABLAMM!!!  You triggered a land mine!");
  1121.               else
  1122. #endif
  1123.           Msg(0, "Aborted because of window change or message.");
  1124.         }
  1125.       else
  1126.         CheckScreenSize(1); /* Change fore */
  1127.       ReceiveMsg(s);
  1128.       continue;
  1129.     }
  1130.       /* Read, process, and store the user input */
  1131.       if (nsel && FD_ISSET(0, &r))
  1132.     {
  1133.           nsel--;
  1134.       if (!HS)
  1135.         RemoveStatus();
  1136.       if (ESCseen)
  1137.         {
  1138.           buf[0] = Esc;
  1139.           buflen = read(0, buf + 1, IOSIZE - 1) + 1;
  1140.           ESCseen = 0;
  1141.         }
  1142.       else
  1143.         buflen = read(0, buf, IOSIZE);
  1144.       if (buflen < 0)
  1145.         {
  1146.           debug1("Read error: %d - SigHup()ing!\n", errno);
  1147.           SigHup(SIGARG);
  1148.           continue;
  1149.         }
  1150.       if (buflen == 0)
  1151.         {
  1152.           debug("Found EOF - SigHup()ing!\n");
  1153.           SigHup(SIGARG);
  1154.           continue;
  1155.         }
  1156.       bufp = buf;
  1157.           if (in_ovl)
  1158.         {
  1159.           SetOvlCurr();
  1160.           (*ovl_process)(&bufp, &buflen);
  1161.         }
  1162.       while (buflen > 0)
  1163.         {
  1164.           n = ForeNum;
  1165.           len = inlen[n];
  1166.           bufp = ProcessInput(bufp, &buflen, inbuf[n], &inlen[n],
  1167.                   sizeof *inbuf);
  1168.           if (inlen[n] > 0 && len == 0)
  1169.         inbuf_ct++;
  1170.         }
  1171.       if (inbuf_ct > 0)
  1172.         continue;
  1173.     }
  1174.       if (GotSignal && !status)
  1175.     {
  1176.       SigHandler();
  1177.       continue;
  1178.     }
  1179. #ifdef COPY_PASTE
  1180.       /* Write the copybuffer contents first, if any. jw. */
  1181.       if (pastelen > 0)
  1182.     {
  1183.       n = ForeNum;
  1184.       debug1("writing pastebuffer (%d)\n", pastelen);
  1185.       tmp = wtab[n]->ptyfd;
  1186.       if (            /* FD_ISSET(tmp,&w) && */
  1187.           (len = write(tmp, pastebuffer,
  1188.                pastelen > IOSIZE ? IOSIZE : pastelen)) > 0)
  1189.         {
  1190.           pastebuffer += len;
  1191.           pastelen -= len;
  1192.           debug1("%d bytes pasted\n", len);
  1193.           if (slowpaste > 0)
  1194.         {
  1195.           struct timeval t;
  1196.  
  1197.                   debug1("slowpaste %d\n", slowpaste);
  1198.           t.tv_usec = (long) (slowpaste * 1000);
  1199.           t.tv_sec = 0;
  1200.           select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
  1201.         }
  1202.           else
  1203.             continue;
  1204.         }
  1205.       /* 
  1206.        * we have to go further down, process some output, if 
  1207.        * no bytes were written...
  1208.        */
  1209.     }
  1210. #endif
  1211.       /* Write the stored user input to the window descriptors */
  1212.       if ( nsel && inbuf_ct > 0)
  1213.     {
  1214.       for (n = 0; n < MAXWIN ; n++)
  1215.         {
  1216.           if (inlen[n] <= 0 )
  1217.         continue;
  1218.           tmp = wtab[n]->ptyfd;
  1219.               if (FD_ISSET(tmp,&w))
  1220.                 {
  1221.           if ( (len = write(tmp, inbuf[n], inlen[n])) > 0)
  1222.             {
  1223.               if ((inlen[n] -= len) == 0)
  1224.               inbuf_ct--;
  1225.               bcopy(inbuf[n] + len, inbuf[n], inlen[n]);
  1226.             }
  1227.           if (--nsel == 0)
  1228.             break;
  1229.         }
  1230.         }
  1231.     }
  1232.       if (GotSignal && !status)
  1233.     {
  1234.       SigHandler();
  1235.       continue;
  1236.     }
  1237.       /* Read and process the output from the window descriptors */
  1238.       for (n = WinList; n != -1; n = p->WinLink)
  1239.     {
  1240.       p = wtab[n];
  1241.       if (in_ovl && ovl_blockfore && n == ForeNum)
  1242.         continue;
  1243.       if (p->outlen)
  1244.         WriteString(p, p->outbuf, p->outlen);
  1245.       else if (nsel && FD_ISSET(p->ptyfd, &r))
  1246.         {
  1247.           nsel--;
  1248.           if ((len = read(p->ptyfd, buf, IOSIZE)) == -1)
  1249.         {
  1250. #ifdef EWOULDBLOCK
  1251.           if (errno == EWOULDBLOCK)
  1252.             len = 0;
  1253. #endif
  1254.         }
  1255.           if (len > 0)
  1256.         WriteString(p, buf, len);
  1257.         }
  1258.       if (p->bell == BELL_ON)
  1259.         {
  1260.           p->bell = BELL_DONE;
  1261.           Msg(0, MakeWinMsg(BellString, n));
  1262.           if (p->monitor == MON_FOUND)
  1263.         p->monitor = MON_DONE;
  1264.         }
  1265.       else if (p->bell == BELL_VISUAL)
  1266.         {
  1267.           if (!BellDisplayed)
  1268.         {
  1269.           p->bell = BELL_DONE;
  1270.           Msg(0, VisualBellString);
  1271.           BellDisplayed = 1;
  1272.         }
  1273.         }
  1274.       else if (p->monitor == MON_FOUND)
  1275.         {
  1276.           p->monitor = MON_DONE;
  1277.           Msg(0, MakeWinMsg(ActivityString, n));
  1278.         }
  1279.     }
  1280.       if (GotSignal && !status)
  1281.     SigHandler();
  1282. #ifdef DEBUG
  1283.       if (nsel)
  1284.     debug1("Left over nsel: %d\n",nsel);
  1285. #endif
  1286.     }
  1287.   /* NOTREACHED */
  1288. }
  1289.  
  1290. static void SigHandler()
  1291. {
  1292.   struct stat st;
  1293.   while (GotSignal)
  1294.     {
  1295.       GotSignal = 0;
  1296.       DoWait();
  1297. #ifdef SYSV
  1298.       signal(SIGCLD, SigChld);
  1299. #endif
  1300.     }
  1301.   if (stat(SockPath, &st) == -1)
  1302.     {
  1303.       debug1("SigHandler: Yuck! cannot stat '%s'\n", SockPath);
  1304.       if (!RecoverSocket())
  1305.     {
  1306.       debug("SCREEN cannot recover from corrupt Socket,bye\n");
  1307.       Finit(1);
  1308.     }
  1309.       else
  1310.     debug1("'%s' reconstructed\n", SockPath);
  1311.     }
  1312.   else
  1313.     debug2("SigHandler: stat '%s' o.k. (%03o)\n", SockPath, st.st_mode);
  1314. }
  1315.  
  1316. #ifdef DEBUG
  1317. int FEpanic;
  1318.  
  1319. sig_t FEChld(SIGDEFARG)
  1320. {
  1321.   FEpanic=1;
  1322. #ifndef SIGVOID
  1323.   return((sig_t) 0);
  1324. #endif
  1325. }
  1326. #endif
  1327.  
  1328. static sig_t SigChld(SIGDEFARG)
  1329. {
  1330.   debug("SigChld()\n");
  1331.   GotSignal = 1;
  1332. #ifndef SIGVOID
  1333.   return((sig_t) 0);
  1334. #endif
  1335. }
  1336.  
  1337. sig_t SigHup(SIGDEFARG)
  1338. {
  1339.   debug("SigHup()\n");
  1340.   if (auto_detach)
  1341.     Detach(D_DETACH);
  1342.   else
  1343.     Finit(0);
  1344. #ifndef SIGVOID
  1345.   return((sig_t) 0);
  1346. #endif
  1347. }
  1348.  
  1349. static sig_t SigInt(SIGDEFARG)
  1350. {
  1351.   char buf[1];
  1352.  
  1353.   debug("SigInt()\n");
  1354.   *buf = (char) intrc;
  1355.   inlen[ForeNum] = 0;
  1356.   if (fore && !in_ovl)
  1357.     write(fore->ptyfd, buf, 1);
  1358.   signal(SIGINT, SigInt);
  1359. #ifndef SIGVOID
  1360.   return((sig_t) 0);
  1361. #endif
  1362. }
  1363.  
  1364. static sig_t CoreDump(sig)
  1365. int sig;
  1366. {
  1367.   setgid(getgid());
  1368.   setuid(getuid());
  1369.   unlink("core");
  1370.   fprintf(stderr, "\r\n[screen caught signal %d. (core dumped)]\r\n", sig);
  1371.   fflush(stderr);
  1372.   Kill(AttacherPid, SIG_BYE);
  1373.   abort();
  1374. #ifndef SIGVOID
  1375.   return((sig_t) 0);
  1376. #endif
  1377. }
  1378.  
  1379. static void DoWait()
  1380. {
  1381.   register int n, next, pid;
  1382. #ifdef BSDWAIT
  1383.   union wait wstat;
  1384. #else
  1385.   int wstat;
  1386. #endif
  1387.  
  1388. #ifdef BSDJOBS
  1389. # ifndef BSDWAIT
  1390.   while ((pid = waitpid(-1, &wstat, WNOHANG | WUNTRACED)) > 0)
  1391. # else
  1392.   while ((pid = wait3(&wstat, WNOHANG | WUNTRACED, (struct rusage *) 0)) > 0)
  1393. # endif
  1394. #else    /* BSDJOBS */
  1395.   while ((pid = wait(&wstat)) < 0)
  1396.     if (errno != EINTR)
  1397.       break;
  1398.   if (pid >= 0)
  1399. #endif    /* BSDJOBS */
  1400.     {
  1401.       for (n = WinList; n != -1; n = next)
  1402.     {
  1403.       next = wtab[n]->WinLink;
  1404.       if (pid == wtab[n]->wpid)
  1405.         {
  1406. #ifdef BSDJOBS
  1407.           if (WIFSTOPPED(wstat))
  1408.         {
  1409.           Msg(0, "Child has been stopped, restarting.");
  1410.           debug1("WIFSTOPPED: %d SIGCONT\n", wtab[n]->wpid);
  1411.           if (killpg(wtab[n]->wpid, SIGCONT))
  1412.             kill(wtab[n]->wpid, SIGCONT);
  1413.         }
  1414.           else
  1415. #endif
  1416.         KillWindow(n);
  1417.         }
  1418.     }
  1419.     }
  1420. }
  1421.  
  1422. void KillWindow(n)
  1423. int n;
  1424. {
  1425.   register int i;
  1426.   /*
  1427.    * Remove window from linked list.
  1428.    */
  1429.   if (n == WinList)    /* WinList = ForeNum */
  1430.     {
  1431.       RemoveStatus();
  1432.       WinList = fore->WinLink;
  1433.       fore = 0;
  1434.     }
  1435.   else
  1436.     {
  1437.       i = WinList;
  1438.       while (wtab[i]->WinLink != n)
  1439.     i = wtab[i]->WinLink;
  1440.       wtab[i]->WinLink = wtab[n]->WinLink;
  1441.     }
  1442.   FreeWindow(wtab[n]);
  1443.   wtab[n] = 0;
  1444.   if (inlen[n] > 0)
  1445.     {
  1446.       inlen[n] = 0;
  1447.       inbuf_ct--;
  1448.     }
  1449.   /*
  1450.    * If the foreground window disappeared check the head of the linked list
  1451.    * of windows for the most recently used window. If no window is alive at
  1452.    * all, exit.
  1453.    */
  1454.   if (WinList == -1)
  1455.     Finit(0);
  1456.   if (!fore)
  1457.     SwitchWindow(WinList);
  1458. }
  1459.  
  1460. static sig_t Finit(i)
  1461. int i;
  1462. {
  1463.   register int n, next;
  1464.  
  1465. #ifdef SYSV
  1466.   signal(SIGCLD, SIG_IGN);
  1467. #else
  1468.   signal(SIGCHLD, SIG_IGN);
  1469. #endif
  1470.   signal(SIGHUP, SIG_IGN);
  1471.   debug1("Finit(%d);\n", i);
  1472.   for (n = WinList; n != -1; n = next)
  1473.     {
  1474.       next = wtab[n]->WinLink;
  1475.       FreeWindow(wtab[n]);
  1476.     }
  1477.   FinitTerm();
  1478.   SetTTY(0, &OldMode);
  1479. #ifdef UTMPOK
  1480.   RestoreLoginSlot();
  1481. #endif
  1482.   printf("\n[screen is terminating]\n");
  1483.   freetty();
  1484.   if (ServerSocket != -1)
  1485.     {
  1486.       debug1("we unlink(%s)\n", SockPath);
  1487.       (void) unlink(SockPath);
  1488.     }
  1489.   Kill(AttacherPid, SIG_BYE);
  1490.   exit(i);
  1491. #ifndef SIGVOID
  1492.   return((sig_t) 0);
  1493. #endif
  1494. }
  1495.  
  1496. void
  1497. eexit(e)
  1498. int e;
  1499. {
  1500.   if (ServerSocket != -1)
  1501.     {
  1502.       debug1("we unlink(%s)\n", SockPath);
  1503.       (void) unlink(SockPath);
  1504.     }
  1505.   exit(e);
  1506. }
  1507.  
  1508. static void InitKeytab()
  1509. {
  1510.   register int i;
  1511.  
  1512.   for (i = 0; i < sizeof(ktab)/sizeof(*ktab); i++)
  1513.     ktab[i].type = KEY_IGNORE;
  1514.  
  1515.   ktab['h'].type = ktab[Ctrl('h')].type = KEY_HARDCOPY;
  1516. #ifdef BSDJOBS
  1517.   ktab['z'].type = ktab[Ctrl('z')].type = KEY_SUSPEND;
  1518. #endif
  1519.   ktab['c'].type = ktab[Ctrl('c')].type = KEY_SHELL;
  1520.   ktab[' '].type = ktab[Ctrl(' ')].type =
  1521.     ktab['n'].type = ktab[Ctrl('n')].type = KEY_NEXT;
  1522.   ktab['-'].type = ktab['p'].type = ktab[Ctrl('p')].type = KEY_PREV;
  1523.   ktab['k'].type = ktab[Ctrl('k')].type = KEY_KILL;
  1524.   ktab['l'].type = ktab[Ctrl('l')].type = KEY_REDISPLAY;
  1525.   ktab['w'].type = ktab[Ctrl('w')].type = KEY_WINDOWS;
  1526.   ktab['v'].type = ktab[Ctrl('v')].type = KEY_VERSION;
  1527.   ktab['q'].type = ktab[Ctrl('q')].type = KEY_XON;
  1528.   ktab['s'].type = ktab[Ctrl('s')].type = KEY_XOFF;
  1529.   ktab['t'].type = ktab[Ctrl('t')].type = KEY_TIME;
  1530.   ktab['i'].type = ktab[Ctrl('i')].type = KEY_INFO;
  1531.   ktab['m'].type = ktab[Ctrl('m')].type = KEY_LASTMSG;
  1532.   ktab['A'].type = KEY_AKA, ktab['A'].args = NULL;
  1533.   ktab['L'].type = KEY_LOGIN;
  1534.   ktab[','].type = KEY_LICENSE;
  1535.   ktab['W'].type = KEY_WIDTH;
  1536.   ktab['.'].type = KEY_TERMCAP;
  1537.   ktab[Ctrl('\\')].type = KEY_QUIT;
  1538.   ktab['d'].type = ktab[Ctrl('d')].type = KEY_DETACH;
  1539.   ktab['r'].type = ktab[Ctrl('r')].type = KEY_WRAP;
  1540.   ktab['f'].type = ktab[Ctrl('f')].type = KEY_FLOW;
  1541.   ktab['/'].type = KEY_AUTOFLOW;
  1542.   ktab['C'].type = KEY_CLEAR;
  1543.   ktab['Z'].type = KEY_RESET;
  1544.   ktab['H'].type = KEY_LOGTOGGLE;
  1545.   if (Esc != MetaEsc)
  1546.     ktab[Esc].type = KEY_OTHER;
  1547.   else
  1548.     ktab[Esc].type = KEY_IGNORE;
  1549.   ktab['M'].type = KEY_MONITOR;
  1550.   ktab['?'].type = KEY_HELP;
  1551.   for (i = 0; i <= 9; i++)
  1552.     ktab['0' + i].type = (enum keytype) (i + (int)KEY_0);
  1553.   ktab[Ctrl('G')].type = KEY_VBELL;
  1554.   ktab[':'].type = KEY_COLON;
  1555. #ifdef COPY_PASTE
  1556.   ktab['['].type = ktab[Ctrl('[')].type = KEY_COPY;
  1557.   ktab[']'].type = ktab[Ctrl(']')].type = KEY_PASTE;
  1558.   ktab['{'].type = KEY_HISTORY; /* } */
  1559.   ktab['>'].type = KEY_WRITE_BUFFER;
  1560.   ktab['<'].type = KEY_READ_BUFFER;
  1561.   ktab['='].type = KEY_REMOVE_BUFFERS;
  1562. #endif
  1563. #ifdef POW_DETACH
  1564.   ktab['D'].type = KEY_POW_DETACH;
  1565. #endif
  1566. #ifdef LOCK
  1567.   ktab['x'].type = ktab[Ctrl('x')].type = KEY_LOCK;
  1568. #endif
  1569. }
  1570.  
  1571. /*
  1572.  * this is a braindamaged hack: if (obuf == NULL) then we provided
  1573.  * a key_type as a second char in ibuf. not a key.
  1574.  */
  1575. char *ProcessInput(ibuf, pilen, obuf, polen, obuf_size)
  1576. char *ibuf, *obuf;
  1577. register int *pilen, *polen, obuf_size;
  1578. {
  1579.   register int n;
  1580.   register enum keytype k;
  1581.   register char *s, *p;
  1582.   char buf[2];
  1583.   int newwidth;
  1584.  
  1585.   if (!obuf)
  1586.     obuf_size = 0;
  1587.  
  1588.   for (s = ibuf, p = obuf + *polen; *pilen > 0; --*pilen, s++)
  1589.     {
  1590.       if (*s == Esc)
  1591.     {
  1592.       debug2("'%c %c ", s[0], s[1]);
  1593.       debug2("%c %c' ", s[2], s[3]);
  1594.       if (*pilen > 1)
  1595.         {
  1596.           --*pilen;
  1597.           s++;
  1598. #if defined(GOULD_NP1)
  1599.           k = (obuf)?(ktab[*s].type):(enum keytype)(int)(*s);
  1600. #else
  1601.           k = (obuf)?(ktab[*s].type):(enum keytype)(*s);
  1602. #endif
  1603.           debug2("Processinput C-A %02x '%c' ", k, k);
  1604.           debug1("%s\n", (obuf)?"std":"NOOBUF");
  1605.           if (*s == MetaEsc)
  1606.         {
  1607.           if (*polen < obuf_size)
  1608.             {
  1609.               *p++ = Esc;
  1610.               ++*polen;
  1611.             }
  1612.         }
  1613.           else if ((int)k >= (int)KEY_0 && (int)k <= (int)KEY_9)
  1614.         SwitchWindow((int)k - (int)KEY_0);
  1615.           else
  1616.         switch (k)
  1617.           {
  1618.           case KEY_TERMCAP:
  1619.             WriteFile(DUMP_TERMCAP);
  1620.             break;
  1621.           case KEY_HARDCOPY:
  1622.             WriteFile(DUMP_HARDCOPY);
  1623.             break;
  1624.           case KEY_LOGTOGGLE:
  1625.             LogToggle();
  1626.             break;
  1627. #ifdef BSDJOBS
  1628.           case KEY_SUSPEND:
  1629.             *pilen = 0;
  1630.             Detach(D_STOP);
  1631.             break;
  1632. #endif
  1633.           case KEY_SHELL:
  1634.             debug("calling MakeWindow with shell\n");
  1635.             MakeWindow(shellaka, ShellArgs,
  1636.                    0, flowctl, 0, (char *) 0, loginflag, -1, 0);
  1637.             break;
  1638.           case KEY_NEXT:
  1639.             if (MoreWindows())
  1640.               SwitchWindow(NextWindow());
  1641.             break;
  1642.           case KEY_PREV:
  1643.             if (MoreWindows())
  1644.               SwitchWindow(PreviousWindow());
  1645.             break;
  1646.           case KEY_KILL:
  1647.             KillWindow(n = ForeNum);
  1648. #ifdef NETHACK
  1649.                   if (nethackflag)
  1650.               Msg(0, "You destroy poor window %d", n);
  1651. #endif
  1652.             break;
  1653.           case KEY_QUIT:
  1654.             Finit(0);
  1655.             /* NOTREACHED */
  1656.           case KEY_DETACH:
  1657.             *pilen = 0;
  1658.             Detach(D_DETACH);
  1659.             break;
  1660. #ifdef POW_DETACH
  1661.           case KEY_POW_DETACH:
  1662.             *pilen = 0;
  1663.             buf[0] = *s;
  1664.             buf[1] = '\0';
  1665.             Msg(0, buf);
  1666.             read(0, buf, 1);
  1667.             if (*buf == *s)
  1668.               Detach(D_POWER); /* detach and kill Attacher's
  1669.                     * parent     */
  1670.             else
  1671.               {
  1672.             write(1, "\007", 1);
  1673.             RemoveStatus();
  1674. #ifdef NETHACK
  1675.                   if (nethackflag)
  1676.                Msg(0, "The blast of disintegration whizzes by you!");
  1677. #endif
  1678.               }
  1679.             break;
  1680. #endif
  1681.           case KEY_REDISPLAY:
  1682.             Activate();
  1683.             break;
  1684.           case KEY_WINDOWS:
  1685.             ShowWindows();
  1686.             break;
  1687.           case KEY_VERSION:
  1688.             Msg(0, "screen %d.%.2d.%.2d%s (%s) %s",REV, VERS, PATCHLEVEL, STATE, ORIGIN, DATE);
  1689.             break;
  1690.           case KEY_TIME:
  1691.             ShowTime();
  1692.             break;
  1693.           case KEY_INFO:
  1694.             ShowInfo();
  1695.             break;
  1696.           case KEY_OTHER:
  1697.             if (MoreWindows())
  1698.               SwitchWindow(fore->WinLink);
  1699.             break;
  1700.           case KEY_XON:
  1701.             if (*polen < obuf_size)
  1702.               {
  1703.             *p++ = Ctrl('q');
  1704.             ++*polen;
  1705.               }
  1706.             break;
  1707.           case KEY_XOFF:
  1708.             if (*polen < obuf_size)
  1709.               {
  1710.             *p++ = Ctrl('s');
  1711.             ++*polen;
  1712.               }
  1713.             break;
  1714. #ifdef LOCK
  1715.           case KEY_LOCK:
  1716.             Detach(D_LOCK); /* do it micha's way */
  1717.             break;
  1718. #endif
  1719.           case KEY_WIDTH:
  1720.             if (Z0 || WS)
  1721.               {
  1722.             if (fore->width == Z0width)
  1723.               newwidth=Z1width;
  1724.             else if (fore->width == Z1width)
  1725.               newwidth=Z0width;
  1726.             else if (fore->width > (Z0width+Z1width)/2)
  1727.               newwidth=Z0width;
  1728.             else
  1729.               newwidth=Z1width;
  1730.             ChangeWindowSize(fore, newwidth, fore->height);
  1731.             Activate();
  1732.               }
  1733.             else
  1734.               Msg(0, "Your termcap does not specify how to change the terminal's width.");
  1735.             break;
  1736.           case KEY_LOGIN:
  1737.             SlotToggle(0);
  1738.             break;
  1739.           case KEY_AKA:
  1740.             if (!ktab[*s].args)
  1741.               InputAKA();
  1742.             else
  1743.               strncpy(fore->cmd + fore->akapos, ktab[*s].args[0], 20);
  1744.             break;
  1745.           case KEY_COLON:
  1746.             InputColon();
  1747.             break;
  1748.           case KEY_LASTMSG:
  1749.             Msg(0, "%s", LastMsg);
  1750.             break;
  1751.           case KEY_SET:
  1752.             DoSet(ktab[*s].args);
  1753.             break;
  1754.           case KEY_SCREEN:
  1755.             debug3("KEY_SCREEN DoSc(, ktab[%d].args(='%s','%s')...)\n",
  1756.                *s, ktab[*s].args[0], ktab[*s].args[1]);
  1757.             DoScreen("key", ktab[*s].args);
  1758.             break;
  1759.           case KEY_CREATE:
  1760.             debug2("KEY_CREATE MaWi(0, ktab[%d].args(='%s')...)\n",
  1761.                *s, ktab[*s].args);
  1762.             MakeWindow((char *) 0, ktab[*s].args,
  1763.                 0, flowctl, 0, (char *) 0, loginflag, -1, 0);
  1764.             break;
  1765.           case KEY_WRAP:
  1766.             fore->wrap = !fore->wrap;
  1767.             Msg(0, "%cwrap", fore->wrap ? '+' : '-');
  1768.             break;
  1769.           case KEY_FLOW:
  1770.             ToggleFlow();
  1771.             goto flow_msg;
  1772.           case KEY_AUTOFLOW:
  1773.             if ((fore->autoflow = !fore->autoflow) != 0
  1774.             && fore->flow == fore->keypad)
  1775.               ToggleFlow();
  1776.           flow_msg:
  1777.             Msg(0, "%cflow%s", fore->flow ? '+' : '-',
  1778.             fore->autoflow ? "(auto)" : "");
  1779.             break;
  1780.           case KEY_CLEAR:
  1781.             if (fore->state == LIT)
  1782.               WriteString(fore, "\033[H\033[J", 6);
  1783.             break;
  1784.           case KEY_RESET:
  1785.             if (fore->state == LIT)
  1786.               WriteString(fore, "\033c", 2);
  1787.             break;
  1788.           case KEY_MONITOR:
  1789.             if (fore->monitor == MON_OFF)
  1790.               {
  1791.             fore->monitor = MON_ON;
  1792.             Msg(0,
  1793.                 "Window %d is now being monitored for all activity.",
  1794.                 ForeNum);
  1795.               }
  1796.             else
  1797.               {
  1798.             fore->monitor = MON_OFF;
  1799.             Msg(0,
  1800.                 "Window %d is no longer being monitored for activity.",
  1801.                 ForeNum);
  1802.               }
  1803.             break;
  1804.           case KEY_HELP:
  1805.             display_help();
  1806.             break;
  1807.           case KEY_LICENSE:
  1808.             display_copyright();
  1809.             break;
  1810. #ifdef COPY_PASTE
  1811.           case KEY_COPY:
  1812.             /* SetOvlCurr(); */
  1813.             (void) MarkRoutine(PLAIN);
  1814.             break;
  1815.           case KEY_HISTORY:
  1816.             /* SetOvlCurr(); */
  1817.             if (MarkRoutine(TRICKY))
  1818.               if (copybuffer != NULL)
  1819.             {
  1820.               pastelen = copylen;
  1821.               pastebuffer = copybuffer;
  1822.               debug1("history new copylen: %d\n", pastelen);
  1823.             }
  1824.             break;
  1825.           case KEY_PASTE:
  1826.             if (copybuffer == NULL)
  1827.               {
  1828. #ifdef NETHACK
  1829.                   if (nethackflag)
  1830.               Msg(0, "Nothing happens.");
  1831.                   else
  1832. #endif
  1833.             Msg(0, "empty buffer");
  1834.             copylen = 0;
  1835.             break;
  1836.               }
  1837.             pastelen = copylen;
  1838.             pastebuffer = copybuffer;
  1839.             break;
  1840.           case KEY_WRITE_BUFFER:
  1841.             if (copybuffer == NULL)
  1842.               {
  1843. #ifdef NETHACK
  1844.                   if (nethackflag)
  1845.               Msg(0, "Nothing happens.");
  1846.                   else
  1847. #endif
  1848.             Msg(0, "empty buffer");
  1849.             copylen = 0;
  1850.             break;
  1851.               }
  1852.             WriteFile(DUMP_EXCHANGE);
  1853.             break;
  1854.           case KEY_READ_BUFFER:
  1855.             ReadFile();
  1856.             break;
  1857.           case KEY_REMOVE_BUFFERS:
  1858.             KillBuffers();
  1859.             break;
  1860. #endif                /* COPY_PASTE */
  1861.           case KEY_VBELL:
  1862.             if (visual_bell)
  1863.               {
  1864.             visual_bell = 0;
  1865.             Msg(0, ":vbell off");
  1866.               }
  1867.             else
  1868.               {
  1869.             visual_bell = 1;
  1870.             Msg(0, ":vbell on");
  1871.               }
  1872.             break;
  1873.            default:
  1874.             break;
  1875.           }
  1876.         }
  1877.       else
  1878.         ESCseen = 1;
  1879.       --*pilen;
  1880.       s++;
  1881.       break;
  1882.     }
  1883.       else if (*polen < obuf_size)
  1884.     {
  1885.       *p++ = *s;
  1886.       ++*polen;
  1887.     }
  1888.     }
  1889.   return (s);
  1890. }
  1891.  
  1892. /* Send a terminal report as if it were typed. */ 
  1893. void
  1894. Report(wp, fmt, n1, n2)
  1895. struct win *wp;
  1896. char *fmt;
  1897. int n1, n2;
  1898. {
  1899.   register int n, len;
  1900.   char rbuf[40];
  1901.  
  1902.   sprintf(rbuf, fmt, n1, n2);
  1903.   len = strlen(rbuf);
  1904.  
  1905.   for (n = 0; n < MAXWIN; n++)
  1906.     {
  1907.       if (wp == wtab[n])
  1908.     {
  1909.       if (inlen[n] + len <= sizeof *inbuf)
  1910.         {
  1911.           bcopy(rbuf, inbuf[n] + inlen[n], len);
  1912.           if (inlen[n] == 0)
  1913.         inbuf_ct++;
  1914.           inlen[n] += len;
  1915.         }
  1916.       break;
  1917.     }
  1918.     }/* for */
  1919. }
  1920.  
  1921. void
  1922. SwitchWindow(n)
  1923. int n;
  1924. {
  1925.   debug1("SwitchWindow %d\n", n);
  1926.   if (!wtab[n])
  1927.     {
  1928.       ShowWindows();
  1929.       return;
  1930.     }
  1931.   if (wtab[n] == fore)
  1932.     {
  1933.       Msg(0, "This IS window %d.", n);
  1934.       return;
  1935.     }
  1936.   SetForeWindow(n);
  1937.   if (!Detached && !in_ovl)
  1938.     Activate();
  1939. }
  1940.  
  1941. static void SetForeWindow(n)
  1942. int n;
  1943. {
  1944.   /*
  1945.    * If we come from another window, make it inactive.
  1946.    */
  1947.   if (fore)
  1948.     fore->active = 0;
  1949.   ForeNum = n;
  1950.   fore = wtab[n];
  1951.   if (!Detached && !in_ovl)
  1952.     fore->active = 1;
  1953.   /*
  1954.    * Place the window at the head of the most-recently-used list.
  1955.    */
  1956.   if ((n = WinList) != ForeNum)
  1957.     {
  1958.       /*
  1959.        * we had a bug here. we sometimes ran into n = -1; and crashed.
  1960.        * (this is not the perfect fix. "if(...) break;" inserted. jw.)
  1961.        */
  1962.       while (wtab[n]->WinLink != ForeNum)
  1963.     {
  1964.       if (wtab[n]->WinLink == -1)
  1965.         break;
  1966.       n = wtab[n]->WinLink;
  1967.     }
  1968.       wtab[n]->WinLink = fore->WinLink;
  1969.       fore->WinLink = WinList;
  1970.       WinList = ForeNum;
  1971.     }
  1972. }
  1973.  
  1974. static int NextWindow()
  1975. {
  1976.   register struct win **pp;
  1977.  
  1978.   for (pp = wtab + ForeNum + 1; pp != wtab + ForeNum; ++pp)
  1979.     {
  1980.       if (pp == wtab + MAXWIN)
  1981.     pp = wtab;
  1982.       if (*pp)
  1983.     break;
  1984.     }
  1985.   return pp - wtab;
  1986. }
  1987.  
  1988. static int PreviousWindow()
  1989. {
  1990.   register struct win **pp;
  1991.  
  1992.   for (pp = wtab + ForeNum - 1; pp != wtab + ForeNum; --pp)
  1993.     {
  1994.       if (pp < wtab)
  1995.     pp = wtab + MAXWIN - 1;
  1996.       if (*pp)
  1997.     break;
  1998.     }
  1999.   return pp - wtab;
  2000. }
  2001.  
  2002. static int MoreWindows()
  2003. {
  2004.   if (fore->WinLink != -1)
  2005.     return 1;
  2006.   Msg(0, "No other window.");
  2007.   return 0;
  2008. }
  2009.  
  2010. static void FreeWindow(wp)
  2011. struct win *wp;
  2012. {
  2013. #ifdef UTMPOK
  2014.   RemoveUtmp(wp);
  2015. #endif
  2016. #ifdef SUIDROOT
  2017.   (void) chmod(wp->tty, 0666);
  2018.   (void) chown(wp->tty, 0, 0);
  2019. #endif
  2020.   close(wp->ptyfd);
  2021.   if (wp->logfp != NULL)
  2022.     fclose(wp->logfp);
  2023.   ChangeWindowSize(wp, 0, 0);
  2024.   Free(wp);
  2025. }
  2026.  
  2027. int
  2028. MakeWindow(prog, args, aflag, flowflag, StartAt, dir, lflag, histheight, term)
  2029. char *prog, **args, *dir;
  2030. int aflag, flowflag, StartAt, lflag, histheight;
  2031. char *term; /* if term is nonzero we assume it "vt100" or the like.. */
  2032. {
  2033.   register struct win **pp, *p;
  2034.   register int n, f;
  2035.   int tf, tlflag;
  2036.   char ebuf[10];
  2037. #ifndef TIOCSWINSZ
  2038.   char libuf[20], cobuf[20];
  2039. #endif
  2040.   char tebuf[25];
  2041.  
  2042.   pp = wtab + StartAt;
  2043.   do
  2044.     {
  2045.       if (*pp == 0)
  2046.     break;
  2047.       if (++pp == wtab + MAXWIN)
  2048.     pp = wtab;
  2049.     } while (pp != wtab + StartAt);
  2050.   if (*pp)
  2051.     {
  2052.       Msg(0, "No more windows.");
  2053.       return -1;
  2054.     }
  2055.  
  2056.    if (((tlflag = lflag) == -1) && ((tlflag = loginflag) == -1))
  2057.     tlflag = LOGINDEFAULT;
  2058.  
  2059. #ifdef USRLIMIT
  2060.   /*
  2061.    * Count current number of users, if logging windows in.
  2062.    */
  2063.   if (tlflag == 1 && CountUsers() >= USRLIMIT)
  2064.     {
  2065.       Msg(0, "User limit reached.  Window will not be logged in.");
  2066.       tlflag = 0;
  2067.     }
  2068. #endif
  2069.   n = pp - wtab;
  2070.   debug1("Makewin creating %d\n", n);
  2071.   if ((f = OpenPTY()) == -1)
  2072.     {
  2073.       Msg(0, "No more PTYs.");
  2074.       return -1;
  2075.     }
  2076. #ifdef SYSV
  2077.   (void) fcntl(f, F_SETFL, O_NDELAY);
  2078. #else
  2079.   (void) fcntl(f, F_SETFL, FNDELAY);
  2080. #endif
  2081.   if ((p = (struct win *) malloc(sizeof(struct win))) == 0)
  2082.     {
  2083.       close(f);
  2084.       Msg_nomem;
  2085.       return -1;
  2086.     }
  2087.   bzero((char *) p, (int) sizeof(struct win));
  2088.   p->ptyfd = f;
  2089.   p->aflag = aflag;
  2090.   if (!flowflag)
  2091.     flowflag = flowctl;
  2092.   p->flow = (flowflag != 1);
  2093.   p->autoflow = (flowflag == 3);
  2094.   if (!prog)
  2095.     prog = Filename(args[0]);
  2096.   strncpy(p->cmd, prog, MAXSTR - 1);
  2097.   if ((prog = rindex(p->cmd, '|')) != NULL)
  2098.     {
  2099.       *prog++ = '\0';
  2100.       prog += strlen(prog);
  2101.       p->akapos = prog - p->cmd;
  2102.       p->autoaka = 0;
  2103.     }
  2104.   else
  2105.     p->akapos = 0;
  2106.   p->monitor = default_monitor;
  2107.   strncpy(p->tty, TtyName, MAXSTR - 1);
  2108. #ifdef SUIDROOT
  2109.   (void) chown(TtyName, real_uid, real_gid);
  2110. # ifdef UTMPOK
  2111.   (void) chmod(TtyName, tlflag ? TtyMode : (TtyMode & ~022));
  2112. # else
  2113.   (void) chmod(TtyName, TtyMode);
  2114. # endif
  2115. #endif
  2116.  
  2117.   if (histheight < 0)
  2118.     histheight = default_histheight;
  2119.   if (ChangeWindowSize(p, default_width, default_height))
  2120.     {
  2121.       FreeWindow(p);
  2122.       return -1;
  2123.     }
  2124.   ChangeScrollback(p, histheight, default_width);
  2125.   ResetScreen(p);
  2126.   debug("forking...\n");
  2127.   switch (p->wpid = fork())
  2128.     {
  2129.     case -1:
  2130.       Msg(errno, "fork");
  2131.       FreeWindow(p);
  2132.       return -1;
  2133.     case 0:
  2134.       signal(SIGHUP, SIG_DFL);
  2135.       signal(SIGINT, SIG_DFL);
  2136.       signal(SIGQUIT, SIG_DFL);
  2137.       signal(SIGTERM, SIG_DFL);
  2138. #ifdef BSDJOBS
  2139.       signal(SIGTTIN, SIG_DFL);
  2140.       signal(SIGTTOU, SIG_DFL);
  2141. #else
  2142.       setpgrp();
  2143. #endif
  2144.       setuid(real_uid);
  2145.       setgid(real_gid);
  2146.       if (dir && chdir(dir) == -1)
  2147.     {
  2148.       SendErrorMsg("Cannot chdir to %s: %s", dir, sys_errlist[errno]);
  2149.       eexit(1);
  2150.     }
  2151.  
  2152.       freetty();
  2153. #ifdef SYSV
  2154.       setpgrp();
  2155. #endif
  2156.       if ((tf = open(TtyName, O_RDWR)) == -1)
  2157.     {
  2158.       SendErrorMsg("Cannot open %s: %s", TtyName, sys_errlist[errno]);
  2159.       eexit(1);
  2160.     }
  2161. #ifdef SVR4
  2162.       if (ioctl(tf, I_PUSH, "ptem"))
  2163.     {
  2164.       SendErrorMsg("Cannot I_PUSH ptem %s %s", TtyName, sys_errlist[errno]);
  2165.       eexit(1);
  2166.     }
  2167.       if (ioctl(tf, I_PUSH, "ldterm"))
  2168.     {
  2169.       SendErrorMsg("Cannot I_PUSH ldterm %s %s", TtyName, sys_errlist[errno]);
  2170.       eexit(1);
  2171.     }
  2172.       if (ioctl(tf, I_PUSH, "ttcompat"))
  2173.     {
  2174.       SendErrorMsg("Cannot I_PUSH ttcompat %s %s", TtyName, sys_errlist[errno]);
  2175.       eexit(1);
  2176.     }
  2177. #endif
  2178.       (void) dup2(tf, 0);
  2179.       (void) dup2(tf, 1);
  2180.       (void) dup2(tf, 2);
  2181. #ifdef DEBUG
  2182.       dfp = stderr;
  2183. #endif
  2184. #ifdef SYSV
  2185.       for (f = NOFILE - 1; f > 2; f--)
  2186.     close(f);
  2187. #else
  2188.       for (f = getdtablesize() - 1; f > 2; f--)
  2189.     close(f);
  2190. #endif
  2191.       fgtty();
  2192. #ifdef TIOCSWINSZ
  2193.       glwz.ws_col=p->width;
  2194.       glwz.ws_row=p->height;
  2195.       (void) ioctl(0, TIOCSWINSZ, &glwz);
  2196. #else
  2197.       sprintf(libuf, "LINES=%d", p->height);
  2198.       sprintf(cobuf, "COLUMNS=%d", p->width);
  2199.       NewEnv[4] = libuf;
  2200.       NewEnv[5] = cobuf;
  2201. #endif
  2202.       SetTTY(0, &OldMode);
  2203.       if (aflag)
  2204.         NewEnv[2] = MakeTermcap(1);
  2205.       else
  2206.         NewEnv[2] = Termcap;
  2207.       if (term && *term && strcmp(screenterm, term) &&
  2208.       ((unsigned)strlen(term) < 20))
  2209.     {
  2210.           char *s1, *s2, tl;
  2211.  
  2212.       sprintf(tebuf, "TERM=%s", term);
  2213.       debug2("Makewindow %d with %s\n", n, tebuf);
  2214.           tl = strlen(term);
  2215.       NewEnv[1] = tebuf;
  2216.           if (s1 = index(Termcap, '|'))
  2217.         {
  2218.           if (s2 = index(++s1, '|'))
  2219.         {
  2220.           if (strlen(Termcap) - (s2 - s1) + tl < 1024)
  2221.             {
  2222.               bcopy(s2, s1 + tl, strlen(s2) + 1);
  2223.               bcopy(term, s1, tl);
  2224.             }
  2225.         }
  2226.             }
  2227.     }
  2228.       sprintf(ebuf, "WINDOW=%d", n);
  2229.       NewEnv[3] = ebuf;
  2230.  
  2231.       execvpe(*args, args, NewEnv);
  2232.       SendErrorMsg("Cannot exec %s: %s", *args, sys_errlist[errno]);
  2233.       exit(1);
  2234.     } /* end fork switch */
  2235.   /*
  2236.    * Place the newly created window at the head of the most-recently-used list.
  2237.    */
  2238.   *pp = p;
  2239.   p->WinLink = WinList;
  2240.   WinList = n;
  2241.   HasWindow = 1;
  2242. #ifdef UTMPOK
  2243.   debug1("MakeWindow will %slog in.\n", tlflag?"":"not ");
  2244.   if (tlflag == 1)
  2245.     SetUtmp(p, n);
  2246.   else
  2247.     p->slot = (slot_t) -1;
  2248. #endif
  2249.   SetForeWindow(n);
  2250.   Activate();
  2251.   return n;
  2252. }
  2253.  
  2254. static void execvpe(prog, args, env)
  2255. char *prog, **args, **env;
  2256. {
  2257.   register char *path, *p;
  2258.   char buf[1024];
  2259.   char *shargs[MAXARGS + 1];
  2260.   register int i, eaccess = 0;
  2261.  
  2262.   if (prog[0] == '/')
  2263.     path = "";
  2264.   else if ((path = getenv("PATH")) == 0)
  2265.     path = DefaultPath;
  2266.   do
  2267.     {
  2268.       p = buf;
  2269.       while (*path && *path != ':')
  2270.     *p++ = *path++;
  2271.       if (p > buf)
  2272.     *p++ = '/';
  2273.       strcpy(p, prog);
  2274.       if (*path)
  2275.     ++path;
  2276.       execve(buf, args, env);
  2277.       switch (errno)
  2278.     {
  2279.     case ENOEXEC:
  2280.       shargs[0] = DefaultShell;
  2281.       shargs[1] = buf;
  2282.       for (i = 1; (shargs[i + 1] = args[i]) != NULL; ++i)
  2283.         ;
  2284.       execve(DefaultShell, shargs, env);
  2285.       return;
  2286.     case EACCES:
  2287.       eaccess = 1;
  2288.       break;
  2289.     case ENOMEM:
  2290.     case E2BIG:
  2291.     case ETXTBSY:
  2292.       return;
  2293.     }
  2294.     } while (*path);
  2295.   if (eaccess)
  2296.     errno = EACCES;
  2297. }
  2298.  
  2299.  
  2300. static void LogToggle()
  2301. {
  2302.   char buf[1024];
  2303.  
  2304.   sprintf(buf, "screenlog.%d", ForeNum);
  2305.   if (fore->logfp != NULL)
  2306.     {
  2307.       Msg(0, "Logfile \"%s\" closed.", buf);
  2308.       fclose(fore->logfp);
  2309.       fore->logfp = NULL;
  2310.       return;
  2311.     }
  2312.   if ((fore->logfp = secfopen(buf, "a")) == NULL)
  2313.     {
  2314.       Msg(errno, "Error opening logfile \"%s\"", buf);
  2315.       return;
  2316.     }
  2317.   Msg(0, "%s logfile \"%s\"", ftell(fore->logfp) ? "Appending to" : "Creating", buf);
  2318. }
  2319.  
  2320. #ifdef NOREUID
  2321. static int UserPID;
  2322. #endif
  2323. static int UserSTAT;
  2324.  
  2325. int UserContext()
  2326. {
  2327. #ifdef NOREUID
  2328.   if (eff_uid == real_uid)
  2329.     return(1);
  2330.   debug("UserContext: forking.\n");
  2331.   switch (UserPID = fork())
  2332.     {
  2333.     case -1:
  2334.       Msg(errno, "fork");
  2335.       return -1;
  2336.     case 0:
  2337.       signal(SIGHUP, SIG_DFL);
  2338.       signal(SIGINT, SIG_IGN);
  2339.       signal(SIGQUIT, SIG_DFL);
  2340.       signal(SIGTERM, SIG_DFL);
  2341. # ifdef BSDJOBS
  2342.       signal(SIGTTIN, SIG_DFL);
  2343.       signal(SIGTTOU, SIG_DFL);
  2344. # endif
  2345.       setuid(real_uid);
  2346.       setgid(real_gid);
  2347.       return 1;
  2348.     default:
  2349.       return 0;
  2350.     }
  2351. #else
  2352.   setreuid(eff_uid, real_uid);
  2353.   setregid(eff_gid, real_gid);
  2354.   return 1;
  2355. #endif
  2356. }
  2357.  
  2358. void
  2359. UserReturn(val)
  2360. int val;
  2361. {
  2362. #if defined(NOREUID)
  2363.   if (eff_uid == real_uid)
  2364.     UserSTAT = val;
  2365.   else
  2366.     exit(val);
  2367. #else
  2368.   setreuid(real_uid, eff_uid);
  2369.   setregid(real_gid, eff_gid);
  2370.   UserSTAT = val;
  2371. #endif
  2372. }
  2373.  
  2374. int UserStatus()
  2375. {
  2376. #ifdef NOREUID
  2377.   int i;
  2378. # ifdef BSDWAIT
  2379.   union wait wstat;
  2380. # else
  2381.   int wstat;
  2382. # endif
  2383.  
  2384.   if (eff_uid == real_uid)
  2385.     return UserSTAT;
  2386.   if (UserPID < 0)
  2387.     return -1;
  2388.   while ((errno = 0, i = wait(&wstat)) != UserPID)
  2389.     if (i < 0 && errno != EINTR)
  2390.       break;
  2391.   if (i == -1)
  2392.     return -1;
  2393.   return (WEXITSTATUS(wstat));
  2394. #else
  2395.   return UserSTAT;
  2396. #endif
  2397. }
  2398.  
  2399. static void ShowWindows()
  2400. {
  2401.   char buf[1024];
  2402.   register char *s;
  2403.   register struct win **pp, *p;
  2404.   register int i, OtherNum = fore->WinLink;
  2405.   register char *cmd;
  2406.  
  2407.   for (i = 0, s = buf, pp = wtab; pp < wtab + MAXWIN; ++i, ++pp)
  2408.     {
  2409.       if ((p = *pp) == 0)
  2410.     continue;
  2411.  
  2412.       if (p->akapos)
  2413.     {
  2414.       if (*(p->cmd + p->akapos) && *(p->cmd + p->akapos - 1) != ':')
  2415.         cmd = p->cmd + p->akapos;
  2416.       else
  2417.         cmd = p->cmd + strlen(p->cmd) + 1;
  2418.     }
  2419.       else
  2420.     cmd = p->cmd;
  2421.       if (s - buf + 5 + (unsigned)strlen(cmd) > fore->width - 1)
  2422.     break;
  2423.       if (s > buf)
  2424.     {
  2425.       *s++ = ' ';
  2426.       *s++ = ' ';
  2427.     }
  2428.       *s++ = i + '0';
  2429.       if (i == ForeNum)
  2430.     *s++ = '*';
  2431.       else if (i == OtherNum)
  2432.     *s++ = '-';
  2433.       if (p->monitor == MON_DONE)
  2434.     *s++ = '@';
  2435.       if (p->bell == BELL_DONE)
  2436.     *s++ = '!';
  2437. #ifdef UTMPOK
  2438.       if (p->slot != (slot_t) 0 && p->slot != (slot_t) -1)
  2439.     *s++ = '$';
  2440. #endif
  2441.       if (p->logfp != NULL)
  2442.     {
  2443.       strcpy(s, "(L)");
  2444.       s += 3;
  2445.     }
  2446.       *s++ = ' ';
  2447.       strcpy(s, cmd);
  2448.       s += strlen(s);
  2449.       if (i == ForeNum)
  2450.     {
  2451.       /* 
  2452.        * this is usually done by Activate(), but when looking
  2453.        * on your current window, you may get annoyed, as there is still
  2454.        * that temporal '!' and '@' displayed.
  2455.        * So we remove that after displaying it once.
  2456.        */
  2457.       p->bell = BELL_OFF;
  2458.       if (p->monitor != MON_OFF)
  2459.         p->monitor = MON_ON;
  2460.     }
  2461.     }
  2462.   *s++ = ' ';
  2463.   *s = '\0';
  2464.   Msg(0, "%s", buf);
  2465. }
  2466.  
  2467. #ifdef LOADAV_3LONGS
  2468. extern long loadav[3];
  2469. #else
  2470. # ifdef LOADAV_4LONGS
  2471. extern long loadav[4];
  2472. # else
  2473. extern double loadav[3];
  2474. # endif
  2475. #endif
  2476. extern avenrun;
  2477.  
  2478. static void ShowTime()
  2479. {
  2480.   char buf[512];
  2481. #ifdef LOADAV
  2482.   char *p;
  2483. #endif
  2484.   struct tm *tp;
  2485.   time_t now;
  2486.  
  2487.   (void) time(&now);
  2488.   tp = localtime(&now);
  2489.   sprintf(buf, "%2d:%02.2d:%02.2d %s", tp->tm_hour, tp->tm_min, tp->tm_sec,
  2490.       HostName);
  2491. #ifdef LOADAV
  2492.   if (avenrun && GetAvenrun())
  2493.     {
  2494.       p = buf + strlen(buf);
  2495. #ifdef LOADAV_3LONGS
  2496.       sprintf(p, " %2.2f %2.2f %2.2f", (double) loadav[0] / FSCALE,
  2497.           (double) loadav[1] / FSCALE, (double) loadav[2] / FSCALE);
  2498. #else
  2499. #ifdef LOADAV_4LONGS
  2500.       sprintf(p, " %2.2f %2.2f %2.2f %2.2f", (double) loadav[0] / 100,
  2501.           (double) loadav[1] / 100, (double) loadav[2] / 100,
  2502.           (double) loadav[3] / 100);
  2503. #else
  2504.       sprintf(p, " %2.2f %2.2f %2.2f", loadav[0], loadav[1], loadav[2]);
  2505. #endif
  2506. #endif
  2507.     }
  2508. #endif
  2509.   Msg(0, "%s", buf);
  2510. }
  2511.  
  2512. static void ShowInfo()
  2513. {
  2514.   char buf[512], *p;
  2515.   register struct win *wp = fore;
  2516.   register int i;
  2517.  
  2518.   sprintf(buf, "(%d,%d)/(%d,%d)+%d %cflow%s %cins %corg %cwrap %capp %clog %cmon",
  2519.       wp->x + 1, wp->y + 1, wp->width, wp->height,
  2520.       wp->histheight,
  2521.       wp->flow ? '+' : '-', wp->autoflow ? "(auto)" : "",
  2522.       wp->insert ? '+' : '-', wp->origin ? '+' : '-',
  2523.       wp->wrap ? '+' : '-', wp->keypad ? '+' : '-',
  2524.       (wp->logfp != NULL) ? '+' : '-',
  2525.       (wp->monitor != MON_OFF) ? '+' : '-');
  2526.   if (ISO2022)
  2527.     {
  2528.       p = buf + strlen(buf);
  2529.       sprintf(p, " G%1d [", wp->LocalCharset);
  2530.       for (i = 0; i < 4; i++)
  2531.     p[i + 5] = wp->charsets[i] ? wp->charsets[i] : 'B';
  2532.       p[9] = ']';
  2533.       p[10] = '\0';
  2534.     }
  2535.   Msg(0, "%s", buf);
  2536. }
  2537.  
  2538. #if defined(sequent) || defined(_SEQUENT_) || defined(SVR4)
  2539.  
  2540. static int OpenPTY()
  2541. {
  2542.   char *m, *s;
  2543.   register int f;
  2544. # ifdef SVR4
  2545.   char *ptsname();
  2546.   sig_t (*sigcld)();
  2547.  
  2548.   if ((f = open("/dev/ptmx", O_RDWR)) == -1)
  2549.     return(-1);
  2550.  
  2551.   /*
  2552.    * SIGCLD set to SIG_DFL for grantpt() because it fork()s and
  2553.    * exec()s pt_chmod
  2554.    */
  2555.   sigcld = signal(SIGCLD, SIG_DFL);
  2556.        
  2557.   if ((m = ptsname(f)) == NULL || unlockpt(f) || grantpt(f))
  2558.     {
  2559.       signal(SIGCLD, sigcld);
  2560.       close(f);
  2561.       return(-1);
  2562.     } 
  2563.   signal(SIGCLD, sigcld);
  2564.   strncpy(TtyName, m, sizeof TtyName);
  2565. # else /* SVR4 */
  2566.   if ((f = getpseudotty(&s, &m)) < 0)
  2567.     return(-1);
  2568.   strncpy(PtyName, m, sizeof PtyName);
  2569.   strncpy(TtyName, s, sizeof TtyName);
  2570. # endif /* SVR4 */
  2571. # ifdef POSIX
  2572.   tcflush(f,TCIOFLUSH);
  2573. # else
  2574.   (void) ioctl(f, TIOCFLUSH, (char *) 0);
  2575. # endif
  2576. # ifdef LOCKPTY
  2577.   (void) ioctl(f, TIOCEXCL, (char *) 0);
  2578. # endif
  2579.   return (f);
  2580. }
  2581.  
  2582. #else /* defined(sequent) || defined(_SEQUENT_) || defined(SVR4) */
  2583. # if defined(MIPS)
  2584. #  if !defined(SGI)
  2585.  
  2586. static int OpenPTY()
  2587. {
  2588.   register char *p, *l, *d;
  2589.   register f, tf;
  2590.   register my_minor;
  2591.   struct stat buf;
  2592.    
  2593.   strcpy(PtyName, PtyProto);
  2594.   for (p = PtyName; *p != 'X'; ++p)
  2595.     ;
  2596.   for (l = "zyxwvutsrqp"; *p = *l; ++l)
  2597.     {
  2598.       for (d = "0123456789abcdef"; p[1] = *d; ++d)
  2599.     {
  2600.       if ((f = open(PtyName, O_RDWR)) != -1)
  2601.         {
  2602.           fstat(f, &buf);
  2603.           my_minor = minor(buf.st_rdev);
  2604.           sprintf(TtyName, "/dev/ttyq%d", my_minor);
  2605.           if ((tf = open(TtyName, O_RDWR)) != -1)
  2606.         {
  2607.           close(tf);
  2608. #ifdef LOCKPTY
  2609.           (void) ioctl(f, TIOCEXCL, (char *)0);
  2610. #endif
  2611.           return f;
  2612.         }
  2613.           close(f);
  2614.         }
  2615.     }
  2616.     }
  2617.   return -1;
  2618. }
  2619.  
  2620. #  else  /* SGI */
  2621.  
  2622. static int OpenPTY()
  2623. {
  2624.   register f;
  2625.   register my_minor;
  2626.   struct stat buf;
  2627.    
  2628.   strcpy(PtyName, "/dev/ptc");
  2629.   f = open(PtyName, O_RDWR|O_NDELAY);
  2630.   if (f >= 0)
  2631.     {
  2632.       if (fstat(f, &buf) < 0)
  2633.     {
  2634.       close(f);
  2635.       return -1;
  2636.     }
  2637.       my_minor = minor(buf.st_rdev);
  2638.       sprintf(TtyName, "/dev/ttyq%d", my_minor);
  2639.     }
  2640.   return f;
  2641. }
  2642.  
  2643. #  endif /* SGI */
  2644. # else /* MIPS */
  2645.  
  2646. static int OpenPTY()
  2647. {
  2648.   register char *p, *l, *d;
  2649.   register int i, f, tf;
  2650.  
  2651.   strcpy(PtyName, PtyProto);
  2652.   strcpy(TtyName, TtyProto);
  2653.   for (p = PtyName, i = 0; *p != 'X'; ++p, ++i)
  2654.     ;
  2655. #ifdef sequent
  2656.   /* why ask for sequent in #else (not sequent) section? jw. */
  2657.   for (l = "p"; (*p = *l) != '\0'; ++l)
  2658.     {                /* } */
  2659.       for (d = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; (p[1] = *d) != '\0'; ++d)
  2660.     {            /* } */
  2661. #else
  2662.   for (l = "qpr"; (*p = *l) != '\0'; ++l)
  2663.     {
  2664.       for (d = "0123456789abcdef"; (p[1] = *d) != '\0'; ++d)
  2665.     {
  2666. #endif
  2667.       if ((f = open(PtyName, O_RDWR)) != -1)
  2668.         {
  2669.           TtyName[i] = p[0];
  2670.           TtyName[i + 1] = p[1];
  2671.           if ((tf = open(TtyName, O_RDWR)) != -1)
  2672.         {
  2673.           /* close tf, thus we also get rid of an unwanted
  2674.            * controlling terminal! 
  2675.            */
  2676.           close(tf);
  2677. #ifdef LOCKPTY
  2678.           (void) ioctl(f, TIOCEXCL, (char *) 0);
  2679. #endif
  2680.           return f;
  2681.         }
  2682.           close(f);
  2683.         }
  2684.     }
  2685.     }
  2686.   return -1;
  2687. }
  2688. # endif /* MIPS */
  2689. #endif
  2690.  
  2691. void 
  2692. SetTTY(fd, mp)
  2693. int fd;
  2694. struct mode *mp;
  2695. {
  2696.   errno = 0;
  2697. #ifdef POSIX
  2698.   tcsetattr(fd, TCSADRAIN, &mp->tio);
  2699. # ifdef hpux
  2700.   ioctl(fd, TIOCSLTC, &mp->m_ltchars);
  2701. # endif
  2702. #else
  2703. # ifdef TERMIO
  2704.   ioctl(fd, TCSETA, &mp->tio);
  2705. # else
  2706.   /* ioctl(fd, TIOCSETP, &mp->m_ttyb); */
  2707.   ioctl(fd, TIOCSETC, &mp->m_tchars);
  2708.   ioctl(fd, TIOCSLTC, &mp->m_ltchars);
  2709.   ioctl(fd, TIOCLSET, &mp->m_lmode);
  2710.   ioctl(fd, TIOCSETD, &mp->m_ldisc);
  2711.   ioctl(fd, TIOCSETP, &mp->m_ttyb);
  2712. # endif
  2713. #endif
  2714.   if (errno)
  2715.     Msg(0, "SetTTY: ioctl", fd);
  2716. }
  2717.  
  2718. void
  2719. GetTTY(fd, mp)
  2720. int fd;
  2721. struct mode *mp;
  2722. {
  2723.   errno = 0;
  2724. #ifdef POSIX
  2725.   tcgetattr(fd, &mp->tio);
  2726. # ifdef hpux
  2727.   ioctl(fd, TIOCGLTC, &mp->m_ltchars);
  2728. # endif
  2729. #else
  2730. # ifdef TERMIO
  2731.   ioctl(fd, TCGETA, &mp->tio);
  2732. # else
  2733.   ioctl(fd, TIOCGETP, &mp->m_ttyb);
  2734.   ioctl(fd, TIOCGETC, &mp->m_tchars);
  2735.   ioctl(fd, TIOCGLTC, &mp->m_ltchars);
  2736.   ioctl(fd, TIOCLGET, &mp->m_lmode);
  2737.   ioctl(fd, TIOCGETD, &mp->m_ldisc);
  2738. # endif
  2739. #endif
  2740.   if (errno)
  2741.     Msg(0, "GetTTY: ioctl", fd);
  2742. }
  2743.  
  2744. void
  2745. SetMode(op, np)
  2746. struct mode *op, *np;
  2747. {
  2748.   *np = *op;
  2749.  
  2750. #if defined(TERMIO) || defined(POSIX)
  2751.   np->tio.c_iflag &= ~ICRNL;
  2752.   np->tio.c_oflag &= ~ONLCR;
  2753.   np->tio.c_lflag &= ~(ICANON | ECHO);
  2754.   np->tio.c_lflag |= ISIG;
  2755. /* 
  2756.  * careful, careful catche monkey..
  2757.  * never set VMIN and VTIME to zero, if you want blocking io.
  2758.  */
  2759.   np->tio.c_cc[VMIN] = 1;
  2760.   np->tio.c_cc[VTIME] = 0;
  2761. #ifdef VSTART
  2762.   startc = op->tio.c_cc[VSTART];
  2763. #endif
  2764. #ifdef VSTOP
  2765.   stopc = op->tio.c_cc[VSTOP];
  2766. #endif
  2767.   if (iflag)
  2768.     intrc = op->tio.c_cc[VINTR];
  2769.   else
  2770.     intrc = np->tio.c_cc[VINTR] = 0377;
  2771.   np->tio.c_cc[VQUIT] = 0377;
  2772.   if (flowctl == 1)
  2773.     {
  2774.       np->tio.c_cc[VINTR] = 0377;
  2775. #ifdef VSTART
  2776.       np->tio.c_cc[VSTART] = 0377;
  2777. #endif
  2778. #ifdef VSTOP
  2779.       np->tio.c_cc[VSTOP] = 0377;
  2780. #endif
  2781. #ifdef VDISCARD
  2782.       np->tio.c_cc[VDISCARD] = 0377;
  2783. #endif
  2784.       np->tio.c_iflag &= ~IXON;
  2785.     }
  2786. #ifdef VSUSP
  2787.   np->tio.c_cc[VSUSP] = 0377;
  2788. #endif
  2789. # ifdef hpux
  2790.   np->m_ltchars.t_suspc = 0377;
  2791.   np->m_ltchars.t_dsuspc = 0377;
  2792.   np->m_ltchars.t_flushc = 0377;
  2793.   np->m_ltchars.t_lnextc = 0377;
  2794. # else
  2795. #  ifdef VDSUSP
  2796.   np->tio.c_cc[VDSUSP] = 0377;
  2797. #  endif
  2798. # endif
  2799. #else
  2800.   startc = op->m_tchars.t_startc;
  2801.   stopc = op->m_tchars.t_stopc;
  2802.   if (iflag)
  2803.     intrc = op->m_tchars.t_intrc;
  2804.   else
  2805.     intrc = np->m_tchars.t_intrc = -1;
  2806.   np->m_ttyb.sg_flags &= ~(CRMOD | ECHO);
  2807.   np->m_ttyb.sg_flags |= CBREAK;
  2808.   np->m_tchars.t_quitc = -1;
  2809.   if (flowctl == 1)
  2810.     {
  2811.       np->m_tchars.t_intrc = -1;
  2812.       np->m_tchars.t_startc = -1;
  2813.       np->m_tchars.t_stopc = -1;
  2814.     }
  2815.   np->m_ltchars.t_suspc = -1;
  2816.   np->m_ltchars.t_dsuspc = -1;
  2817.   np->m_ltchars.t_flushc = -1;
  2818.   np->m_ltchars.t_lnextc = -1;
  2819. #endif                /* defined(TERMIO) || defined(POSIX) */
  2820. }
  2821.  
  2822. void
  2823. SetFlow(on)
  2824. int on;
  2825. {
  2826. #if defined(TERMIO) || defined(POSIX)
  2827.   if (on)
  2828.     {
  2829.       NewMode.tio.c_cc[VINTR] = intrc;
  2830. #ifdef VSTART
  2831.       NewMode.tio.c_cc[VSTART] = startc;
  2832. #endif
  2833. #ifdef VSTOP
  2834.       NewMode.tio.c_cc[VSTOP] = stopc;
  2835. #endif
  2836.       NewMode.tio.c_iflag |= IXON;
  2837.     }
  2838.   else
  2839.     {
  2840.       NewMode.tio.c_cc[VINTR] = 0377;
  2841. #ifdef VSTART
  2842.       NewMode.tio.c_cc[VSTART] = 0377;
  2843. #endif
  2844. #ifdef VSTOP
  2845.       NewMode.tio.c_cc[VSTOP] = 0377;
  2846. #endif
  2847.       NewMode.tio.c_iflag &= ~IXON;
  2848.     }
  2849. # ifdef POSIX
  2850.   if (tcsetattr(0, TCSADRAIN, &NewMode.tio))
  2851. # else
  2852.   if (ioctl(0, TCSETA, &NewMode.tio) != 0)
  2853. # endif
  2854.     debug1("SetFlow: ioctl errno %d\n", errno);
  2855. #else
  2856.   if (on)
  2857.     {
  2858.       NewMode.m_tchars.t_intrc = intrc;
  2859.       NewMode.m_tchars.t_startc = startc;
  2860.       NewMode.m_tchars.t_stopc = stopc;
  2861.     }
  2862.   else
  2863.     {
  2864.       NewMode.m_tchars.t_intrc = -1;
  2865.       NewMode.m_tchars.t_startc = -1;
  2866.       NewMode.m_tchars.t_stopc = -1;
  2867.     }
  2868.   if (ioctl(0, TIOCSETC, &NewMode.m_tchars) != 0)
  2869.     debug1("SetFlow: ioctl errno %d\n", errno);
  2870. #endif                /* defined(TERMIO) || defined(POSIX) */
  2871. }
  2872.  
  2873. char *GetTtyName()
  2874. {
  2875.   register char *p;
  2876.   register int n;
  2877.  
  2878.   for (p = 0, n = 0; n <= 2 && ((p = ttyname(n)) == 0); n++)
  2879.     ;
  2880.   if (!p || *p == '\0')
  2881.     Msg(0, "screen must run on a tty.");
  2882.   return p;
  2883. }
  2884.  
  2885. /* we return 1 if we could attach one, or 0 if none */
  2886. static int Attach(how)
  2887. int how;
  2888. {
  2889.   int lasts;
  2890.   struct msg m;
  2891.   struct stat st;
  2892.   char *tty, *s;
  2893.  
  2894.   if (how == MSG_WINCH)
  2895.     {
  2896.       bzero((char *) &m, sizeof(m));
  2897.       m.type = how;
  2898.       if ((lasts=MakeClientSocket(0,SockName))>=0)
  2899.     {
  2900.           write(lasts, &m, sizeof(m));
  2901.           close(lasts);
  2902.     }
  2903.       return 0;
  2904.     }
  2905.  
  2906.   switch (FindSocket(how, &lasts))
  2907.     {
  2908.     case 0:
  2909.       if (rflag == 2)
  2910.     return 0;
  2911.       if (quietflag)
  2912.     eexit(10);
  2913.       Msg(0, "There is no screen to be %sed.", dflag ? "detach" : "resum");
  2914.       /* NOTREACHED */
  2915.     case 1:
  2916.       break;
  2917.     default:
  2918.       Msg(0, "Type \"screen [-d] -r host.tty\" to resume one of them.");
  2919.       /* NOTREACHED */
  2920.     }
  2921.   SockName = SockNamePtr;
  2922.   debug1("Attach decided, it is '%s'\n", SockPath);
  2923.   if (stat(SockPath, &st) == -1)
  2924.     Msg(errno, "stat %s", SockPath);
  2925.   if ((st.st_mode & 0700) != (dflag ? 0700 : 0600))
  2926.     Msg(0, "That screen is %sdetached.", dflag ? "already " : "not ");
  2927.   tty = GetTtyName();
  2928.   if ((unsigned)strlen(tty) >= MAXPATH)
  2929.     Msg(0, "TtyName too long - sorry.");
  2930. #ifdef REMOTE_DETACH
  2931.   if (dflag &&
  2932.       (how == MSG_ATTACH || how == MSG_DETACH || how == MSG_POW_DETACH))
  2933.     {
  2934.       strcpy(m.m.detach.tty, tty);
  2935.       m.m.detach.dpid = getpid();
  2936. #ifdef POW_DETACH
  2937.       if (dflag == 2)
  2938.     m.type = MSG_POW_DETACH;
  2939.       else
  2940. #endif
  2941.     m.type = MSG_DETACH;
  2942.       trysend(lasts, &m, m.m.detach.password);
  2943.       if (how != MSG_ATTACH)
  2944.     return 0;        /* we detached it. jw. */
  2945.       sleep(1);            /* we dont want to overrun our poor backend. jw. */
  2946.       if ((lasts = MakeClientSocket(0, SockName)) == -1)
  2947.     Msg(0, "Cannot contact screen again. Shit.");
  2948.     }
  2949. #endif
  2950.   m.type = how;
  2951.   strcpy(m.m.attach.tty, tty);
  2952.   s = getenv("TERM");
  2953.   if (s)
  2954.     {
  2955.       if ((unsigned)strlen(s) >= MAXPATH-5)
  2956.     Msg(0, "$TERM too long - sorry.");
  2957.       sprintf(m.m.attach.envterm, "TERM=%s", s);
  2958.     }
  2959.   else
  2960.     *m.m.attach.envterm = '\0';
  2961.   debug1("attach: sending %d bytes... ", sizeof m);
  2962.  
  2963.   m.m.attach.apid = getpid();
  2964.   m.m.attach.adaptflag = adaptflag;
  2965.   m.m.attach.lines = m.m.attach.columns = 0;
  2966.   if (s = getenv("LINES"))
  2967.     m.m.attach.lines = atoi(s);
  2968.   if (s = getenv("COLUMNS"))
  2969.     m.m.attach.columns = atoi(s);
  2970.  
  2971.   trysend(lasts, &m, m.m.attach.password);
  2972.   debug1("Attach(%d): sent\n", m.type);
  2973.   Suspended = 0;
  2974.   rflag = 0;
  2975.   return 1;
  2976. }
  2977.  
  2978.  
  2979. #ifdef PASSWORD
  2980.  
  2981. static trysendstat;
  2982.  
  2983. static sig_t trysendok(SIGDEFARG)
  2984. {
  2985.   trysendstat = 1;
  2986. }
  2987.  
  2988. static sig_t trysendfail(SIGDEFARG)
  2989. {
  2990.   trysendstat = -1;
  2991. }
  2992.  
  2993. static char screenpw[9];
  2994.  
  2995. static void trysend(fd, m, pwto)
  2996. int fd;
  2997. struct msg *m;
  2998. char *pwto;
  2999. {
  3000.   char *npw = NULL;
  3001.   sig_t (*sighup)();
  3002.   sig_t (*sigusr1)();
  3003.  
  3004.   sigusr1 = signal(SIG_PW_OK, trysendok);
  3005.   sighup = signal(SIG_PW_FAIL, trysendfail);
  3006.   for (;;)
  3007.     {
  3008.       strcpy(pwto, screenpw);
  3009.       trysendstat = 0;
  3010.       if (write(fd, (char *) m, sizeof(*m)) != sizeof(*m))
  3011.     Msg(errno, "write");
  3012.       close(fd);
  3013.       while (trysendstat == 0)
  3014.     pause();
  3015.       if (trysendstat > 0)
  3016.     {
  3017.       signal(SIG_PW_OK, sigusr1);
  3018.       signal(SIG_PW_FAIL, sighup);
  3019.       return;
  3020.     }
  3021.       if (*screenpw || (npw = getpass("Screen Password:")) == 0 || *npw == 0)
  3022.     Msg(0, "Password incorrect");
  3023.       strncpy(screenpw,npw,8);
  3024.       if ((fd = MakeClientSocket(0, SockName)) == -1)
  3025.     Msg(0, "Cannot contact screen again. Shit.");
  3026. #ifdef SYSV
  3027.       signal(SIG_PW_FAIL, trysendfail);
  3028. #endif
  3029.     }
  3030. }
  3031.  
  3032. #else /* PASSWORD */
  3033.  
  3034. static trysend(fd, m, pwto)
  3035. struct msg *m;
  3036. char *pwto;
  3037. {
  3038.   strcpy(pwto, "");
  3039.   if (write(fd, (char *) m, sizeof(*m)) != sizeof(*m))
  3040.     Msg(errno, "write");
  3041.   close(fd);
  3042. }
  3043.  
  3044. #endif /* PASSWORD */
  3045.  
  3046.  
  3047. /*
  3048.  * Unfortunatelly this is also the SIGHUP handler, so we have to
  3049.  * check, if the backend is already detached.
  3050.  */
  3051.  
  3052. static sig_t AttacherFinit(SIGDEFARG)
  3053. {
  3054.   struct stat statb;
  3055.   struct msg m;
  3056.   int s;
  3057.  
  3058.   debug("AttacherFinit();\n");
  3059.   /* Check if signal comes from backend */
  3060.   if (SockName)
  3061.     {
  3062.       strcpy(SockNamePtr, SockName);
  3063.       if (stat(SockPath, &statb) == 0 && (statb.st_mode & 0777) != 0600)
  3064.     {
  3065.       debug("Detaching backend!\n");
  3066.       bzero((char *) &m, sizeof(m));
  3067.       strcpy(m.m.detach.tty, GetTtyName());
  3068.       m.m.detach.dpid = getpid();
  3069. #ifdef PASSWORD
  3070.       strcpy(m.m.detach.password, screenpw);
  3071.       signal(SIG_PW_OK, SIG_IGN);
  3072.       signal(SIG_PW_FAIL, SIG_IGN);
  3073. #endif
  3074.       m.type = MSG_HANGUP;
  3075.       if ((s=MakeClientSocket(0, SockName))>=0)
  3076.         {
  3077.           write(s, &m, sizeof(m));
  3078.           close(s);
  3079.         }
  3080.     }
  3081.     }
  3082.   exit(0);
  3083. #ifndef SIGVOID
  3084.   return((sig_t) 0);
  3085. #endif
  3086. }
  3087.  
  3088. #ifdef POW_DETACH
  3089. static sig_t AttacherFinitBye(SIGDEFARG)
  3090. {
  3091.   int ppid;
  3092.   debug("AttacherFintBye()\n");
  3093.   freetty();
  3094.   setuid(real_uid);
  3095.   setgid(real_gid);
  3096.   /* we don't want to disturb init (even if we were root), eh? jw */
  3097.   if ((ppid = getppid()) > 1)
  3098.     Kill(ppid, SIGHUP);        /* carefully say good bye. jw. */
  3099.   exit(0);
  3100. #ifndef SIGVOID
  3101.   return((sig_t) 0);
  3102. #endif
  3103. }
  3104. #endif
  3105.  
  3106. static SuspendPlease;
  3107.  
  3108. static sig_t SigStop(SIGDEFARG)
  3109. {
  3110.   debug("SigStop()\n");
  3111.   SuspendPlease = 1;
  3112. #ifndef SIGVOID
  3113.   return((sig_t) 0);
  3114. #endif
  3115. }
  3116.  
  3117. #ifdef LOCK
  3118. static LockPlease;
  3119.  
  3120. static sig_t DoLock(SIGDEFARG)
  3121. {
  3122.   debug("DoLock()\n");
  3123.   LockPlease = 1;
  3124. # ifdef SYSV
  3125.   signal(SIG_LOCK, DoLock);
  3126. # endif
  3127. # ifndef SIGVOID
  3128.   return((sig_t) 0);
  3129. # endif
  3130. }
  3131. #endif
  3132.  
  3133. #if defined(SIGWINCH) && defined(TIOCGWINSZ)
  3134. static SigWinchPlease;
  3135.  
  3136. static sig_t SigAttWinch(SIGDEFARG)
  3137. {
  3138.   debug("SigAttWinch()\n");
  3139.   SigWinchPlease = 1;
  3140. # ifndef SIGVOID
  3141.   return((sig_t) 0);
  3142. # endif
  3143. }
  3144. #endif
  3145.  
  3146. static void Attacher()
  3147. {
  3148.   /*
  3149.    * permanent in UserContext. Advantage is, you can kill your attacher
  3150.    * when things go wrong. Any disadvantages? jw.
  3151.    */
  3152.   setuid(real_uid);
  3153.   setgid(real_gid);
  3154.  
  3155.   signal(SIGHUP, AttacherFinit);
  3156.   signal(SIG_BYE, AttacherFinit);
  3157. #ifdef POW_DETACH
  3158.   signal(SIG_POWER_BYE, AttacherFinitBye);
  3159. #endif
  3160. #ifdef LOCK
  3161.   signal(SIG_LOCK, DoLock);
  3162. #endif
  3163.   signal(SIGINT, SIG_IGN);
  3164. #ifdef BSDJOBS
  3165.   signal(SIG_STOP, SigStop);
  3166. #endif
  3167. #if defined(SIGWINCH) && defined(TIOCGWINSZ)
  3168.   signal(SIGWINCH, SigAttWinch);
  3169. #endif
  3170. #ifdef DEBUG
  3171. # ifdef SYSV
  3172.   signal(SIGCLD,FEChld);
  3173. # else
  3174.   signal(SIGCHLD,FEChld);
  3175. # endif
  3176. #endif
  3177.   debug("attacher: going for a nap.\n");
  3178.   dflag = 0;
  3179.   while (1)
  3180.     {
  3181.       pause();
  3182.       debug("attacher: huh! a signal!\n");
  3183. #ifdef DEBUG
  3184.       if (FEpanic)
  3185.         {
  3186.       printf("\n\rSuddenly the Dungeon collapses!! - You die...\n\r");
  3187.       SetTTY(0, &OldMode);
  3188.       eexit(1);
  3189.         }
  3190. #endif
  3191. #ifdef BSDJOBS
  3192.       if (SuspendPlease)
  3193.     {
  3194.       SuspendPlease = 0;
  3195.       signal(SIGTSTP, SIG_DFL);
  3196.       debug("attacher: killing myself SIGTSTP\n");
  3197.       kill(getpid(), SIGTSTP);
  3198.  
  3199.       debug1("attacher: continuing from stop(%d)\n", Suspended);
  3200.       signal(SIG_STOP, SigStop);
  3201.       (void) Attach(MSG_CONT);
  3202.     }
  3203. #endif
  3204. #ifdef LOCK
  3205.       if (LockPlease)
  3206.     {
  3207.       LockPlease = 0;
  3208.       LockTerminal();
  3209. # ifdef SYSV
  3210.       signal(SIG_LOCK, DoLock);
  3211. # endif
  3212.       (void) Attach(MSG_CONT);
  3213.     }
  3214. #endif    /* LOCK */
  3215. #if defined(SIGWINCH) && defined(TIOCGWINSZ)
  3216.       if (SigWinchPlease)
  3217.     {
  3218.       SigWinchPlease = 0;
  3219. # ifdef SYSV
  3220.       signal(SIGWINCH, SigAttWinch);
  3221. # endif
  3222.       (void) Attach(MSG_WINCH);
  3223.     }
  3224. #endif    /* SIGWINCH */
  3225.     }
  3226. }
  3227.  
  3228. #ifdef LOCK
  3229.  
  3230. /* ADDED by Rainer Pruy 10/15/87 */
  3231. /* POLISHED by mls. 03/10/91 */
  3232.  
  3233. static char LockEnd[] = "Welcome back to screen !!\n";
  3234.  
  3235. static void LockTerminal()
  3236. {
  3237.   char *prg;
  3238.   int sig, pid;
  3239.   sig_t (*sigs[NSIG])__P(SIGPROTOARG);
  3240.  
  3241.   for (sig = 1; sig < NSIG; sig++)
  3242.     {
  3243.       sigs[sig] = signal(sig, SIG_IGN);
  3244.     }
  3245.   SetTTY(0, &OldMode);
  3246.   printf("\n");
  3247.  
  3248.   prg = getenv("LOCKPRG");
  3249.   if (prg && strcmp(prg,"builtin") && !access(prg, X_OK))
  3250.     {
  3251.       debug1("lockterminal: '%s' seems executable, execl it!\n", prg);
  3252.       if ((pid = fork()) == 0)
  3253.         {
  3254.           /* Child */
  3255.           setuid(real_uid);    /* this should be done already */
  3256.           setgid(real_gid);
  3257.           execl(prg, "SCREEN-LOCK", NULL);
  3258.           exit(errno);
  3259.         }
  3260.       if (pid == -1)
  3261.         {
  3262. #ifdef NETHACK
  3263.           if (nethackflag)
  3264.             Msg(errno, "Cannot fork terminal - lock failed");
  3265.           else
  3266. #endif
  3267.           Msg(errno, "Cannot lock terminal - fork failed");
  3268.         }
  3269.       else
  3270.         {
  3271. #ifdef BSDWAIT
  3272.           union wait wstat;
  3273. #else
  3274.           int wstat;
  3275. #endif
  3276.           int wret;
  3277.  
  3278. #ifdef hpux
  3279.           signal(SIGCLD, SIG_DFL);
  3280. #endif
  3281.           errno = 0;
  3282.           while (((wret = wait((int *) &wstat)) != pid) ||
  3283.              ((wret == -1) && (errno == EINTR))
  3284.              )
  3285.         errno = 0;
  3286.     
  3287.           if (errno)
  3288.         {
  3289.           perror("Lock");
  3290.           sleep(2);
  3291.         }
  3292.       else if (WTERMSIG(wstat) != 0)
  3293.         {
  3294.           fprintf(stderr, "Lock: %s: Killed by signal: %d%s\n", prg,
  3295.               WTERMSIG(wstat), WIFCORESIG(wstat) ? " (Core dumped)" : "");
  3296.           sleep(2);
  3297.         }
  3298.       else if (WEXITSTATUS(wstat))
  3299.         {
  3300.           debug2("Lock: %s: return code %d\n", prg, WEXITSTATUS(wstat));
  3301.         }
  3302.           else
  3303.         printf(LockEnd);
  3304.         }
  3305.     }
  3306.   else
  3307.     {
  3308.       if (prg)
  3309.     {
  3310.           debug1("lockterminal: '%s' seems NOT executable, we use our builtin\n", prg);
  3311.     }
  3312.       else
  3313.     {
  3314.       debug("lockterminal: using buitin.\n");
  3315.     }
  3316.       screen_builtin_lck();
  3317.     }
  3318.   /* reset signals */
  3319.   for (sig = 1; sig < NSIG; sig++)
  3320.     {
  3321.       if (sigs[sig] != (sig_t(*) ()) - 1)
  3322.     signal(sig, sigs[sig]);
  3323.     }
  3324. }                /* LockTerminal */
  3325.  
  3326. /* -- original copyright by Luigi Cannelloni 1985 (luigi@faui70.UUCP) -- */
  3327. void
  3328. screen_builtin_lck()
  3329. {
  3330.   char fullname[100],*cp1, message[BUFSIZ];
  3331.   char c,*pass,mypass[9];
  3332.   int t;
  3333.  
  3334. #ifdef undef
  3335.   /* get password entry */
  3336.   if ((ppp = getpwuid(real_uid)) == NULL)
  3337.     {
  3338.       fprintf(stderr,"screen_builtin_lck: No passwd entry.\007\n");
  3339.       sleep(2);
  3340.       return;
  3341.     }
  3342.   if (!isatty(0))
  3343.     {
  3344.       fprintf(stderr,"screen_builtin_lck: Not a tty.\007\n");
  3345.       sleep(2);
  3346.       return;
  3347.     }
  3348. #endif
  3349.   for (t=0; t<13; t++)
  3350.     {
  3351.     c=ppp->pw_passwd[t];
  3352.     if (!(c == '.' || c == '/' ||
  3353.           c>='0' && c<='9' || 
  3354.           c>='a' && c<='z' || 
  3355.           c>='A' && c<='Z')) break;
  3356.     }
  3357.   if (t<13)
  3358.     {
  3359.       debug("builtin_lock: ppp->pw_passwd bad, has it a shadow?\n");
  3360.       if (pass=getpass("Key:   "))
  3361.         {
  3362.           strncpy(mypass,pass,8);
  3363.           mypass[8]=0;
  3364.           if (*mypass==0)
  3365.             return;
  3366.           if (pass=getpass("Again: "))
  3367.             {
  3368.               if (strcmp(mypass,pass))
  3369.                 {
  3370.                   fprintf(stderr,"Passwords don't match.\007\n");
  3371.                   sleep(2);
  3372.                   return;
  3373.                 }
  3374.             }
  3375.         }
  3376.       if (pass==0)
  3377.         {
  3378.           fprintf(stderr,"Getpass error.\007\n");
  3379.           sleep(2);
  3380.           return;
  3381.         }
  3382.       pass=0;
  3383.     }
  3384.   else pass=ppp->pw_passwd;
  3385.  
  3386.   debug("screen_builtin_lck looking in gcos field\n");
  3387.   strcpy(fullname,ppp->pw_gecos);
  3388.   if ((cp1 = index(fullname,',')) != NULL)
  3389.     *cp1 = '\0';
  3390.   if ((cp1 = index(fullname,'&')) != NULL)
  3391.     {
  3392.       sprintf(cp1,"%s",ppp->pw_name);
  3393.       *cp1 = islower(*cp1) ? toupper(*cp1) : *cp1;
  3394.     }
  3395.  
  3396.   sprintf(message,"Screen used by %s <%s>.\nPassword:\007",
  3397.           fullname, ppp->pw_name);
  3398.  
  3399.   /* loop here to wait for correct password */
  3400.   for (;;)
  3401.     {
  3402.       debug("screen_builtin_lck awaiting password\n");
  3403.       if (pass)
  3404.         {
  3405.           if(!strcmp(crypt(getpass(message),pass),pass))
  3406.             break;
  3407.         }
  3408.       else
  3409.         {
  3410.           if(!strcmp(getpass(message),mypass))
  3411.             break;
  3412.         }
  3413.       debug("screen_builtin_lck: NO!!!!!\n");
  3414.     }
  3415.   debug("password ok.\n");
  3416. }
  3417.  
  3418. #endif    /* LOCK */
  3419.  
  3420. /*
  3421.  * Detach now has the following modes:
  3422.  *    D_DETACH    SIG_BYE        detach backend and exit attacher
  3423.  *    D_STOP        SIG_STOP    stop attacher (and detach backend)
  3424.  *    D_REMOTE    SIG_BYE        remote detach -- reattach to new attacher
  3425.  *    D_POWER     SIG_POWER_BYE     power detach -- attacher kills his parent
  3426.  *    D_REMOTE_POWER    SIG_POWER_BYE    remote power detach -- both
  3427.  *    D_LOCK        SIG_LOCK    lock the attacher
  3428.  * (jw)
  3429.  * we always remove our utmp slots. (even when "lock" or "stop")
  3430.  * Note: Take extra care here, we may be called by unterrupt!
  3431.  */
  3432. void
  3433. Detach(mode)
  3434. int mode;
  3435. {
  3436.   int sign = 0;
  3437. #ifdef UTMPOK
  3438.   register int n;
  3439. #endif
  3440.  
  3441.   if (Detached)
  3442.     return;
  3443.   debug1("Detach(%d)\n", mode);
  3444.   if (fore && status)
  3445.     RemoveStatus();
  3446.   signal(SIGHUP, SIG_IGN);
  3447.   SetTTY(0, &OldMode);
  3448.   FinitTerm();
  3449.   switch (mode)
  3450.     {
  3451.     case D_DETACH:
  3452.       printf("\n[detached]\n");
  3453.       sign = SIG_BYE;
  3454.       break;
  3455. #ifdef BSDJOBS
  3456.     case D_STOP:
  3457.       (void) fflush(stdout);
  3458.       sign = SIG_STOP;
  3459.       break;
  3460. #endif
  3461. #ifdef REMOTE_DETACH
  3462.     case D_REMOTE:
  3463.       printf("\n[remote detached]\n");
  3464.       sign = SIG_BYE;
  3465.       break;
  3466. #endif
  3467. #ifdef POW_DETACH
  3468.     case D_POWER:
  3469.       printf("\n[power detached]\n");
  3470.       if (PowDetachString) 
  3471.         printf("%s\n",PowDetachString);
  3472.       sign = SIG_POWER_BYE;
  3473.       break;
  3474. #ifdef REMOTE_DETACH
  3475.     case D_REMOTE_POWER:
  3476.       printf("\n[remote power detached]\n");
  3477.       if (PowDetachString) 
  3478.         printf("%s\n",PowDetachString);
  3479.       sign = SIG_POWER_BYE;
  3480.       break;
  3481. #endif
  3482. #endif
  3483.     case D_LOCK:
  3484.       ClearDisplay();
  3485.       sign = SIG_LOCK;
  3486.       /* tell attacher to lock terminal with a lockprg. */
  3487.       break;
  3488.     }
  3489. #ifdef UTMPOK
  3490.   for (n = WinList; n != -1; n = wtab[n]->WinLink)
  3491.     if (wtab[n]->slot != (slot_t) -1)
  3492.       {
  3493.     RemoveUtmp(wtab[n]);
  3494.         /*
  3495.      * Set the slot to 0 to get the window
  3496.          * logged in again.
  3497.      */
  3498.     wtab[n]->slot = (slot_t) 0;
  3499.       }
  3500.   RestoreLoginSlot();
  3501. #endif
  3502.   freetty();
  3503.   debug("Detach: we did freetty().\n");
  3504.   (void) chmod(SockPath, /* S_IFSOCK | */ 0600); /* Flag detached-ness */
  3505.     /*
  3506.      * tell father to father what to do. We do that after we
  3507.      * freed the tty, thus getty feels more comfortable on hpux
  3508.      * if it was a power detach.
  3509.      */
  3510.   Kill(AttacherPid,sign);
  3511.   debug2("Detach: Signal %d to Attacher(%d)!\n", sign, AttacherPid);
  3512.   if (mode != D_LOCK && mode != D_STOP)
  3513.     AttacherPid = 0;
  3514.  
  3515.   Detached = 1;
  3516.   Suspended = (mode == D_STOP) ? 1 : 0;
  3517.   if (fore)
  3518.     fore->active = 0;
  3519.   debug("Detach returns, we are successfully detached.\n");
  3520. }
  3521.  
  3522. int
  3523. CheckPid(pid)
  3524. int pid;
  3525. {
  3526.   if (pid < 2)
  3527.     return(-1);
  3528.   if (eff_uid == real_uid)
  3529.     return kill(pid, 0);
  3530.   if (UserContext() == 1)
  3531.     {
  3532.       UserReturn(kill(pid, 0));
  3533.     }
  3534.   return UserStatus();
  3535. }
  3536.  
  3537. void
  3538. Kill(pid, sig)
  3539. int pid, sig;
  3540. {
  3541.   if (pid < 2)
  3542.     return;
  3543.   (void) kill(pid, sig);
  3544. }
  3545.  
  3546. static int IsSymbol(e, s)
  3547. register char *e, *s;
  3548. {
  3549.   register char *p;
  3550.   register int n;
  3551.  
  3552.   for (p = e; *p && *p != '='; ++p)
  3553.     ;
  3554.   if (*p)
  3555.     {
  3556.       *p = '\0';
  3557.       n = strcmp(e, s);
  3558.       *p = '=';
  3559.       return n == 0;
  3560.     }
  3561.   return 0;
  3562. }
  3563.  
  3564. static void MakeNewEnv()
  3565. {
  3566.   register char **op, **np;
  3567.   static char buf[MAXSTR];
  3568.  
  3569.   for (op = environ; *op; ++op)
  3570.     ;
  3571.   NewEnv = np = (char **) malloc((unsigned) (op - environ + 6 + 1) * sizeof(char **));
  3572.   if (!NewEnv)
  3573.     Msg_nomem;
  3574.   if ((unsigned)strlen(SockName) > MAXSTR - 5)
  3575.     SockName = "?";
  3576.   sprintf(buf, "STY=%s", SockName);
  3577.   *np++ = buf;                    /* NewEnv[0] */
  3578.   *np++ = Term;                    /* NewEnv[1] */
  3579. #ifdef TIOCGWINSZ
  3580.   np += 2;            /* leave room for TERMCAP and WINDOW */
  3581. #else
  3582.   np += 4;    /* room for TERMCAP WINDOW LINES COLUMNS */
  3583. #endif
  3584.  
  3585.   for (op = environ; *op; ++op)
  3586.     {
  3587.       if (!IsSymbol(*op, "TERM") && !IsSymbol(*op, "TERMCAP")
  3588.       && !IsSymbol(*op, "STY") && !IsSymbol(*op, "WINDOW")
  3589.       && !IsSymbol(*op, "SCREENCAP")
  3590. #ifndef TIOCGWINSZ
  3591.       && !IsSymbol(*op, "LINES") && !IsSymbol(*op, "COLUMNS")
  3592. #endif
  3593.       )
  3594.     *np++ = *op;
  3595.     }
  3596.   *np = 0;
  3597. }
  3598.  
  3599. void
  3600. #ifdef USEVARARGS
  3601. /*VARARGS2*/
  3602. # if defined(__STDC__)
  3603. Msg(int err, char *fmt, ...)
  3604. # else
  3605. Msg(err, fmt, va_alist)
  3606. int err;
  3607. char *fmt;
  3608. va_dcl
  3609. # endif
  3610. {
  3611.   static va_list ap = 0;
  3612. #else
  3613. /*VARARGS2*/
  3614. Msg(err, fmt, p1, p2, p3, p4, p5, p6)
  3615. int err;
  3616. char *fmt;
  3617. unsigned long p1, p2, p3, p4, p5, p6;
  3618. {
  3619. #endif
  3620.   char buf[MAXPATH*2];
  3621.   char *p = buf;
  3622.  
  3623.   if (Detached)
  3624.     return;
  3625. #ifdef USEVARARGS
  3626. # if defined(__STDC__)
  3627.   va_start(ap, fmt);
  3628. # else
  3629.   va_start(ap);
  3630. # endif
  3631.   (void) vsprintf(p, fmt, ap);
  3632.   va_end(ap);
  3633. #else
  3634.   sprintf(p, fmt, p1, p2, p3, p4, p5, p6);
  3635. #endif
  3636.   if (err)
  3637.     {
  3638.       p += strlen(p);
  3639.       if (err > 0 && err < sys_nerr)
  3640.     sprintf(p, ": %s", sys_errlist[err]);
  3641.       else
  3642.     sprintf(p, ": Error %d", err);
  3643.     }
  3644.   if (HasWindow)
  3645.     {
  3646.       debug1("Msg('%s');\n", p);
  3647.       MakeStatus(buf);
  3648.     }
  3649.   else
  3650.     {
  3651.       printf("%s\r\n", buf);
  3652.       if (DeadlyMsg)
  3653.     {
  3654.           debug1("Msg('%s') screen is not up, exiting..\n", buf);
  3655.           Kill(AttacherPid, SIG_BYE);
  3656.           eexit(1);
  3657.     }
  3658.       else
  3659.     debug1("Harmless = 0; Msg('%s');\n", buf);
  3660.     }
  3661.   DeadlyMsg = 1;
  3662. }
  3663.  
  3664. char *Filename(s)
  3665. char *s;
  3666. {
  3667.   register char *p;
  3668.  
  3669.   if (s == NULL) 
  3670.     return s;
  3671.   p = s + strlen(s) - 1;
  3672.   while (p >= s && *p != '/')
  3673.     --p;
  3674.   return ++p;
  3675. }
  3676.  
  3677. /*
  3678.  * '^' is allowed as an escape mechanism for control characters. jw.
  3679.  */
  3680. static char *MakeWinMsg(s, n)
  3681. register char *s;
  3682. int n;
  3683. {
  3684.   static char buf[MAXSTR];
  3685.   register char *p = buf;
  3686.   register int ctrl;
  3687.  
  3688.   ctrl = 0;
  3689.   for (; *s && p < buf + MAXSTR - 1; s++, p++)
  3690.     if (ctrl)
  3691.       {
  3692.         ctrl = 0;
  3693.         if (*s == '^' || *s < 64)
  3694.           *p = *s;
  3695.         else 
  3696.           *p = *s - 64;
  3697.       }
  3698.     else
  3699.       {
  3700.         switch (*s)
  3701.           {
  3702.           case '%':
  3703.             *p = n + '0';
  3704.         break;
  3705.           case '~':
  3706.         *p = BELL;
  3707.         break;
  3708.       case '^':
  3709.         ctrl = 1;
  3710.         *p-- = '^';
  3711.         break;
  3712.           default:
  3713.         *p = *s;
  3714.         break;
  3715.           }
  3716.       }
  3717.   *p = '\0';
  3718.   return buf;
  3719. }
  3720.  
  3721.