home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / screen3 / part04 / socket.c < prev   
Encoding:
C/C++ Source or Header  |  1991-12-18  |  25.0 KB  |  1,030 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: socket.c,v 1.55 91/10/11 11:24:38 jnweiger Exp $ FAU";
  36. #endif
  37.  
  38. #include "config.h"
  39. #if defined(MIPS) || defined(GOULD_NP1) || defined(B43)
  40. extern int errno;
  41. #endif
  42. #if defined(BSD) || defined(sequent) || defined(pyr)
  43. # include <strings.h>
  44. #else
  45. # include <string.h>
  46. #endif
  47. #include <sys/types.h>
  48. #include <sys/stat.h>
  49. #include <sys/file.h>
  50. #ifndef NAMEDPIPE
  51. #include <sys/socket.h>
  52. #endif
  53. #include <fcntl.h>
  54. #ifndef NAMEDPIPE
  55. #include <sys/un.h>
  56. #endif
  57. #include <signal.h>
  58. #include <sys/time.h>
  59. #ifdef DIRENT
  60. # include <sys/param.h>
  61. # include <dirent.h>
  62. #else
  63. # include <sys/dir.h>
  64. # define dirent direct
  65. #endif
  66. #ifdef USEVARARGS
  67. # if defined(__STDC__)
  68. #  include <stdarg.h>
  69. # else
  70. #  include <varargs.h>
  71. # endif
  72. #endif
  73. #include "screen.h"
  74. #include "extern.h"
  75.  
  76. #if defined(_SEQUENT_) && !defined(NAMEDPIPE)
  77. # define connect sconnect    /* _SEQUENT_ has braindamaged connect */
  78. #endif
  79.  
  80. extern char *RcFileName, *extra_incap, *extra_outcap;
  81. extern WinList, Detached, ServerSocket, real_uid, real_gid, eff_uid, eff_gid;
  82. #ifdef BSDJOBS
  83. extern int Suspended;
  84. #endif
  85. extern AttacherPid, dflag, mflag, rflag, lsflag, quietflag, wipeflag;
  86. extern char HostName[];
  87. extern struct mode OldMode, NewMode;
  88. extern struct win *wtab[], *fore;
  89. #ifdef NETHACK
  90. extern nethackflag;
  91. #endif
  92.  
  93. #ifdef PASSWORD
  94. extern int CheckPassword;
  95. extern char Password[];
  96. #endif
  97. #if !defined(POSIX) && defined(BSDJOBS)
  98. extern DevTty;
  99. #endif
  100. extern char *getenv(), *GetTtyName();
  101.  
  102. char SockPath[MAXPATH];
  103. char *SockNamePtr, *SockName;
  104.  
  105. char *strdup(str)
  106. const char *str;
  107. {
  108.   char *ret;
  109.  
  110.   if ((ret = (char *) malloc((unsigned) (strlen(str) + 1))) == 0)
  111.     {
  112.       Msg_nomem;
  113.       return (0);
  114.     }
  115.   (void) strcpy(ret, str);
  116.   return (ret);
  117. }
  118.  
  119. int RecoverSocket()
  120. {
  121.   int s = 0, d;
  122.  
  123.   (void) unlink(SockPath);
  124.   s = MakeServerSocket();
  125.   if (s != ServerSocket)
  126.     {
  127.       debug2("Oh, Serversocket was %d, now %d, let's dup!\n", ServerSocket, s);
  128.       d = dup2(s, ServerSocket);
  129.       close(s);
  130.       if (d != ServerSocket)
  131.     {
  132.       debug2("Hmm, dup2() failed, Serversocket was %d, now %d, bye\n",
  133.          ServerSocket, d);
  134.       return 0;
  135.     }
  136.     }
  137.   if (Detached)
  138.     (void) chmod(SockPath, /* S_IFSOCK | */ 0600); /* Flag detached-ness */
  139.   return 1;
  140. }
  141.  
  142.  
  143. /* socket mode 700 means we are Attached. 600 is detached.
  144.  * we return how many sockets we found. if it was exactly one, we come
  145.  * back with a SockPath set to it and open it in a fd pointed to by fdp.
  146.  * if fdp == 0 we simply produce a list if all sockets.
  147.  */
  148. int FindSocket(how, fdp)
  149. int how;
  150. int *fdp;
  151. {
  152.   register int s, lasts = 0, found = 0, deadcount = 0, wipecount = 0;
  153.   register DIR *dirp;
  154.   register struct dirent *dp;
  155.   struct stat st;
  156.   struct foundsock
  157.     {
  158.       char *name;
  159.       int mode;
  160.     }         foundsock[100];    /* 100 is hopefully enough. */
  161.   int foundsockcount = 0;
  162.  
  163.   if (SockName && fdp)
  164.     {
  165.       if ((lasts = MakeClientSocket(0, SockName)) == -1)
  166.     {
  167.       if (quietflag)
  168.         eexit(10);
  169.       else
  170.         {
  171.           if (how == MSG_CONT)
  172.             Msg(0, "Attach failed.");
  173.           else
  174.             Msg(0, "There is no screen to be %sed from %s.",
  175.                 dflag ? "detach" : "resum", SockName);
  176.         }
  177.     }
  178.       debug1("FindSocket likes what You specified('%s');\n", SockPath);
  179.       *fdp = lasts;
  180.       return 1;
  181.     }
  182.  
  183.   /* user gave no SockName, so we really have to search */
  184. #ifdef NFS_HACK
  185.   setreuid(eff_uid, real_uid);
  186. #endif
  187.   debug1("FindSock searching... '%s'\n", SockPath);
  188.   if ((dirp = opendir(SockPath)) == NULL)
  189.     Msg(0, "Cannot opendir %s", SockPath);
  190.   while ((dp = readdir(dirp)) != NULL)
  191.     {
  192.       SockName = dp->d_name;
  193.       if (SockName[0] == '.')
  194.     continue;
  195.       debug1("Attach found: '%s'\n", SockName);
  196.       /*
  197.        * ATTENTION! MakeClientSocket adds SockName to SockPath! anyway, we
  198.        * need it earlier.
  199.        */
  200.       strcpy(SockNamePtr, SockName);
  201.       if (stat(SockPath, &st) == -1)
  202.     Msg(errno, "stat");
  203.       if (st.st_uid != real_uid)
  204.     continue;
  205.       foundsock[foundsockcount].name = strdup(SockName);
  206.       foundsock[foundsockcount].mode = s = st.st_mode & 0777;
  207.       debug2("FindSocket: %s has mode %04o...\n", SockName, s);
  208.       if (s == 0700 || s == 0600)
  209.     {
  210.       /* we try to connect through the socket. if successfull, 
  211.        * thats o.k. otherwise we record that mode as -1.
  212.        */
  213.       if ((s = MakeClientSocket(0, SockName)) == -1)
  214.         { 
  215.           foundsock[foundsockcount].mode = -1;
  216.           deadcount++;
  217.         }
  218.       else
  219.         close(s);
  220.     }
  221.       if (++foundsockcount >= 100)
  222.     break;
  223.     }
  224.   closedir(dirp);
  225. #ifdef NFS_HACK
  226.   setreuid(real_uid, eff_uid);
  227. #endif
  228.  
  229.   if (wipeflag)
  230.     {
  231.       for (s = 0; s < foundsockcount; s++)
  232.     {
  233.       if (foundsock[s].mode == -1)
  234.         {
  235.               strcpy(SockNamePtr, foundsock[s].name);
  236.           debug1("wiping '%d'\n", SockPath);
  237.           if (unlink(SockPath) == 0)
  238.             {
  239.           foundsock[s].mode = -2;
  240.               wipecount++;
  241.         }
  242.         }
  243.     }
  244.     }
  245.   for (s = 0; s < foundsockcount; s++)
  246.     if ((foundsock[s].mode) == (dflag ? 0700 : 0600))
  247.       {
  248.     found++;
  249.     lasts = s;
  250.       }
  251.   if (quietflag && (lsflag || (found != 1 && rflag !=2)))
  252.     eexit(10+found);
  253.   debug2("attach: found=%d, foundsockcount=%d\n", found, foundsockcount);
  254.   if (found == 1 && lsflag == 0)
  255.     {
  256.       if ((lasts = MakeClientSocket(0, foundsock[lasts].name)) == -1)
  257.         found = 0;
  258.     }
  259.   else if (!quietflag && foundsockcount > 0)
  260.     {
  261.       switch (found)
  262.         {
  263.         case 0:
  264.           if (lsflag)
  265.         {
  266. #ifdef NETHACK
  267.               if (nethackflag)
  268.             printf("Your inventory:\n");
  269.           else
  270. #endif
  271.           printf((foundsockcount>1) ? "There are screens on:\n" : "There is a screen on:\n");
  272.         }
  273.           else
  274.         {
  275. #ifdef NETHACK
  276.               if (nethackflag)
  277.             printf("Nothing fitting exists in the game:\n");
  278.           else
  279. #endif
  280.           printf((foundsockcount>1) ? "There are screens on:\n" : "There is a screen on:\n");
  281.         }
  282.           break;
  283.         case 1:
  284. #ifdef NETHACK
  285.           if (nethackflag)
  286.             printf((foundsockcount>1) ? "Prove thyself worthy or perish:\n" : "You see here a good looking screen:\n");
  287.           else
  288. #endif
  289.           printf((foundsockcount>1) ? "There are several screens on:\n" : "There is a possible screen on:\n");
  290.           break;
  291.         default:
  292. #ifdef NETHACK
  293.           if (nethackflag)
  294.             printf((foundsockcount>1) ? "You may whish for a screen, what do you want?\n" : "You see here a screen:\n");
  295.           else
  296. #endif
  297.           printf((foundsockcount>1) ? "There are several screens on:\n" : "There is a screen on:\n");
  298.           break;
  299.         }
  300.       for (s = 0; s < foundsockcount; s++)
  301.     {
  302.       switch (foundsock[s].mode)
  303.         {
  304.         case 0700:
  305.           printf("\t%s\t(Attached)\n", foundsock[s].name);
  306.           break;
  307.         case 0600:
  308.           printf("\t%s\t(Detached)\n", foundsock[s].name);
  309.           break;
  310.         case -1:
  311. #if defined(__STDC__)
  312.           printf("\t%s\t(Dead \?\?\?)\n", foundsock[s].name);
  313. #else
  314.           printf("\t%s\t(Dead ???)\n", foundsock[s].name);
  315. #endif
  316.           break;
  317.         case -2:
  318.           printf("\t%s\t(Removed)\n", foundsock[s].name);
  319.           break;
  320.         default:
  321.           printf("\t%s\t(Wrong mode)\n", foundsock[s].name);
  322.           break;
  323.         }
  324.     }
  325.     }
  326.   if (deadcount && !quietflag)
  327.     {
  328.       if (wipeflag)
  329.         {
  330. #ifdef NETHACK
  331.           if (nethackflag)
  332.             printf("You hear%s distant explosion%s.\n",
  333.            (deadcount > 1)?"":" a", (deadcount > 1)?"s":"");
  334.           else
  335. #endif
  336.           printf("%d Socket%s wiped out.\n", deadcount, (deadcount > 1)?"s":"");
  337.     }
  338.       else
  339.     {
  340. #ifdef NETHACK
  341.           if (nethackflag)
  342.             printf("The dead screen%s touch%s you. Try 'screen -wipe'.\n",
  343.            (deadcount > 1)?"s":"", (deadcount >1)?"":"es");
  344.           else
  345. #endif
  346.           printf("Remove dead Sockets with 'screen -wipe'.\n");
  347.     }
  348.     }
  349.  
  350.   for (s = 0; s < foundsockcount; s++)
  351.     Free(foundsock[s].name);
  352.   if (found == 1 && fdp)
  353.     *fdp = lasts;
  354.   if (fdp)
  355.     return found;
  356.   SockName = NULL;
  357.   return foundsockcount - wipecount;
  358. }
  359.  
  360. int
  361. GetSockName()
  362. {
  363.   register int client;
  364.   static char buf[2 * MAXSTR];
  365.  
  366.   if (!mflag && (SockName = getenv("STY")) != 0 && *SockName != '\0')
  367.     {
  368.       client = 1;
  369.       setuid(real_uid);
  370.       setgid(real_gid);
  371.     }
  372.   else
  373.     {
  374.       sprintf(buf, "%s.%s", HostName, Filename(GetTtyName()));
  375.       SockName = buf;
  376.       client = 0;
  377.     }
  378.   return client;
  379. }
  380.  
  381. #ifdef NAMEDPIPE
  382.  
  383. int
  384. MakeServerSocket()
  385. {
  386.   register int s;
  387.   struct stat st;
  388.  
  389.   strcpy(SockNamePtr, SockName);
  390.  
  391.   if ((s = open(SockPath, O_WRONLY | O_NDELAY)) >= 0)
  392.     {
  393.       debug("huii, my fifo already exists??\n");
  394.       if (quietflag)
  395.     {
  396.       Kill(AttacherPid, SIG_BYE);
  397.       eexit(11);
  398.     }
  399.       printf("There is already a screen running on %s.\n",
  400.          Filename(SockPath));
  401.       if (stat(SockPath, &st) == -1)
  402.     Msg(errno, "stat");
  403.       if (st.st_uid != real_uid)
  404.     Msg(0, "Unfortunatelly you are not its owner.");
  405.       if ((st.st_mode & 0700) == 0600)
  406.     Msg(0, "To resume it, use \"screen -r\"");
  407.       else
  408.     Msg(0, "It is not detached.");
  409.       /* NOTREACHED */
  410.     }
  411.   (void) unlink(SockPath);
  412.   if (UserContext() > 0)
  413.     {
  414.       if (mknod(SockPath, S_IFIFO | S_IEXEC | S_IWRITE | S_IREAD, 0))
  415.     UserReturn(0);
  416.       UserReturn(1);
  417.     }
  418.   if (UserStatus() <= 0)
  419.     Msg(0, "mknod fifo %s failed", SockPath);
  420.   /*
  421.    * MUST be RDWR because otherwise we will get EOF's if
  422.    * nobody has opened the pipe for writing
  423.    */
  424.   if ((s = secopen(SockPath, O_RDWR | O_NDELAY, 0)) < 0)
  425.     Msg(errno, "open fifo %s", SockPath);
  426.   return s;
  427. }
  428.  
  429.  
  430. int
  431. MakeClientSocket(err, name)
  432. int err;
  433. char *name;
  434. {
  435.   register int s = 0;
  436.  
  437.   strcpy(SockNamePtr, name);
  438.  
  439.   
  440.   if ((s = secopen(SockPath, O_WRONLY | O_NDELAY, 0)) >= 0)
  441.     {
  442.       (void) fcntl(s, F_SETFL, 0);
  443.       return s;
  444.     }
  445.   if (err)
  446.     {
  447.       Msg(errno, "open: %s (but continuing...)", SockPath);
  448.       debug1("MakeClientSocket() open %s failed\n", SockPath);
  449.     }
  450.   else
  451.     {
  452.       debug1("MakeClientSocket() open %s failed\n", SockPath);
  453.     }
  454.   return -1;
  455. }
  456.  
  457. #else    /* NAMEDPIPE */
  458.  
  459. int
  460. MakeServerSocket()
  461. {
  462.   register int s;
  463.   struct sockaddr_un a;
  464.   struct stat st;
  465.  
  466.   if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
  467.     Msg(errno, "socket");
  468.   a.sun_family = AF_UNIX;
  469.   strcpy(SockNamePtr, SockName);
  470.   strcpy(a.sun_path, SockPath);
  471.   if (connect(s, (struct sockaddr *) & a, strlen(SockPath) + 2) != -1)
  472.     {
  473.       debug("oooooh! socket already is alive!\n");
  474.       if (quietflag)
  475.     { 
  476.       Kill(AttacherPid, SIG_BYE);
  477.       /* 
  478.        * oh, well. nobody receives that return code. papa 
  479.        * dies by signal.
  480.        */
  481.       eexit(11);
  482.     }
  483.       printf("There is already a screen running on %s.\n",
  484.          Filename(SockPath));
  485.       if (stat(SockPath, &st) == -1)
  486.     Msg(errno, "stat");
  487.       if (st.st_uid != real_uid)
  488.     Msg(0, "Unfortunatelly you are not its owner.");
  489.       if ((st.st_mode & 0700) == 0600)
  490.     Msg(0, "To resume it, use \"screen -r\"");
  491.       else
  492.     Msg(0, "It is not detached.");
  493.       /* NOTREACHED */
  494.     }
  495.   (void) unlink(SockPath);
  496. #ifndef NOREUID
  497.   setreuid(eff_uid, real_uid);
  498.   setregid(eff_gid, real_gid);
  499. #endif
  500.   if (bind(s, (struct sockaddr *) & a, strlen(SockPath) + 2) == -1)
  501.     Msg(errno, "bind");
  502.   (void) chmod(SockPath, /* S_IFSOCK | */ 0700);
  503. #ifdef NOREUID
  504.   chown(SockPath, real_uid, real_gid);
  505. #else
  506.   setreuid(real_uid, eff_uid);
  507.   setregid(real_gid, eff_gid);
  508. #endif
  509.   if (listen(s, 5) == -1)
  510.     Msg(errno, "listen");
  511. #ifdef F_SETOWN
  512.   fcntl(s, F_SETOWN, getpid());
  513.   debug1("Serversocket owned by %d\n",fcntl(s, F_GETOWN, 0));
  514. #endif /* F_SETOWN */
  515.   return s;
  516. }
  517.  
  518. int
  519. MakeClientSocket(err, name)
  520. int err;
  521. char *name;
  522. {
  523.   register int s;
  524.   struct sockaddr_un a;
  525.  
  526.   if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
  527.     Msg(errno, "socket");
  528.   a.sun_family = AF_UNIX;
  529.   strcpy(SockNamePtr, name);
  530.   strcpy(a.sun_path, SockPath);
  531. #ifndef NOREUID
  532.   setreuid(eff_uid, real_uid);
  533.   setregid(eff_gid, real_gid);
  534. #else
  535.   if (access(SockPath, W_OK))
  536.     {
  537.       if (err)
  538.     Msg(errno, "%s", SockPath);
  539.       else
  540.     debug2("MakeClientSocket: access(%s): %d.\n", SockPath, errno);
  541.       close(s);
  542.       return -1;
  543.     }
  544. #endif
  545.   if (connect(s, (struct sockaddr *) & a, strlen(SockPath) + 2) == -1)
  546.     {
  547.       if (err)
  548.     Msg(errno, "%s: connect", SockPath);
  549.       else
  550.     debug("MakeClientSocket: connect failed.\n");
  551.       close(s);
  552.       s = -1;
  553.     }
  554. #ifndef NOREUID
  555.   setreuid(real_uid, eff_uid);
  556.   setregid(real_gid, eff_gid);
  557. #endif
  558.   return s;
  559. }
  560. #endif
  561.  
  562.  
  563. void
  564. SendCreateMsg(s, ac, av, aflag, flowflag, lflag, histheight, sterm)
  565. int s, ac, aflag, flowflag, lflag, histheight;
  566. char **av;
  567. char *sterm;
  568. {
  569.   struct msg m;
  570.   register char *p;
  571.   register int len, n;
  572.  
  573.   debug1("SendCreateMsg() to '%s'\n", SockPath);
  574.   m.type = MSG_CREATE;
  575.   p = m.m.create.line;
  576.   for (n = 0; ac > 0 && n < MAXARGS - 1; ++av, --ac, ++n)
  577.     {
  578.       len = strlen(*av) + 1;
  579.       if (p + len >= m.m.create.line + MAXPATH - 1)
  580.     break;
  581.       strcpy(p, *av);
  582.       p += len;
  583.     }
  584.   if (!ac && *av && p + strlen(*av) + 1 < m.m.create.line + MAXPATH)
  585.     strcpy(p, *av);
  586.   else
  587.     *p = '\0';
  588.   m.m.create.nargs = n;
  589.   m.m.create.aflag = aflag;
  590.   m.m.create.flowflag = flowflag;
  591.   m.m.create.lflag = lflag;
  592.   m.m.create.hheight = histheight;
  593. #ifdef SYSV
  594.   if (getcwd(m.m.create.dir, sizeof(m.m.create.dir)) == 0)
  595. #else
  596.     if (getwd(m.m.create.dir) == 0)
  597. #endif
  598.       Msg(0, "%s", m.m.create.dir);
  599.   strncpy(m.m.create.screenterm, sterm, 19);
  600.   m.m.create.screenterm[19] = '\0';
  601.   debug1("SendCreateMsg writing '%s'\n", m.m.create.line);
  602.   if (write(s, (char *) &m, sizeof m) != sizeof m)
  603.     Msg(errno, "write");
  604. }
  605.  
  606. void
  607. #ifdef USEVARARGS
  608. /*VARARGS1*/
  609. # if defined(__STDC__)
  610. SendErrorMsg(char *fmt, ...)
  611. # else
  612. SendErrorMsg(fmt, va_alist)
  613. char *fmt;
  614. va_dcl
  615. #endif
  616. { /* } */
  617.   static va_list ap = 0;
  618. #else
  619. /*VARARGS1*/
  620. SendErrorMsg(fmt, p1, p2, p3, p4, p5, p6)
  621. char *fmt;
  622. unsigned long p1, p2, p3, p4, p5, p6;
  623. {
  624. #endif
  625.   register int s;
  626.   struct msg m;
  627.  
  628.   s = MakeClientSocket(1, SockName);
  629.   debug1("SendErrorMsg() to '%s'\n", SockPath);
  630.   m.type = MSG_ERROR;
  631. #ifdef USEVARARGS
  632. # if defined(__STDC__)
  633.   va_start(ap, fmt);
  634. # else
  635.   va_start(ap);
  636. # endif
  637.   (void) vsprintf(m.m.message, fmt, ap);
  638.   va_end(ap);
  639. #else
  640.   sprintf(m.m.message, fmt, p1, p2, p3, p4, p5, p6);
  641. #endif
  642.   debug1("SendErrorMsg writing '%s'\n", m.m.message);
  643.   (void) write(s, (char *) &m, sizeof m);
  644.   close(s);
  645.   sleep(2);
  646. }
  647.  
  648. #ifdef PASSWORD
  649. static int CheckPasswd(pwd, pid, tty)
  650. int pid;
  651. char *pwd, *tty;
  652. {
  653.   if (CheckPassword && 
  654.       strcmp(crypt(pwd, ((unsigned)strlen(Password) > 1) ? Password : "JW"),
  655.          Password))
  656.     {
  657.       if (*pwd)
  658.     {
  659. #ifdef NETHACK
  660.           if (nethackflag)
  661.         Msg(0, "'%s' tries to explode in the sky, but fails. (%s)", tty, pwd);
  662.           else
  663. #endif
  664.       Msg(0, "Illegal reattach attempt from terminal %s, \"%s\"", tty, pwd);
  665.     }
  666.       debug1("CheckPass() wrong password kill(%d, SIG_PW_FAIL)\n", pid);
  667.       Kill(pid, SIG_PW_FAIL);
  668.       return 0;
  669.     }
  670.   debug1("CheckPass() from %d happy\n", pid);
  671.   Kill(pid, SIG_PW_OK);
  672.   return 1;
  673. }
  674. #endif    /* PASSWORD */
  675.  
  676. static void ExecCreate(mp)
  677. struct msg *mp;
  678. {
  679.   char *args[MAXARGS];
  680.   register int n;
  681.   register char **pp = args, *p = mp->m.create.line;
  682.  
  683.   for (n = mp->m.create.nargs; n > 0; --n)
  684.     {
  685.       *pp++ = p;
  686.       p += strlen(p) + 1;
  687.     }
  688.   *pp = 0;
  689.   if (!*p)
  690.     p = 0;
  691.   MakeWindow(p, args, mp->m.create.aflag, mp->m.create.flowflag,
  692.               0, mp->m.create.dir, mp->m.create.lflag,
  693.               mp->m.create.hheight, mp->m.create.screenterm);
  694. }
  695.  
  696. void
  697. ReceiveMsg(s)
  698. int s;
  699. {
  700.   int left, len, i;
  701.   struct msg m;
  702.   char *p;
  703.   char buf[20];
  704. #ifdef NAMEDPIPE
  705.   /*
  706.    * we may be called if there are no pending messages, so we will have to
  707.    * block on first read.
  708.    */
  709.   debug("Ha, there was someone knocking on my fifo??\n");
  710.   if (fcntl(s, F_SETFL, 0) == -1)
  711.     {
  712.       Msg(errno, "fcntl no O_NDELAY");
  713.       exit(1);
  714.     }
  715.   p = (char *) &m;
  716.   left = sizeof(m);
  717.   while (left > 0 && (len = read(s, p, left)) > 0)
  718.     {
  719.       /*        if (p == (char *)&m)
  720.        *        {    if (fcntl(s,F_SETFL,O_NDELAY) == -1)
  721.        *            {    Msg(errno, "fcntl O_NDELAY !");
  722.        *                return;
  723.        *            }
  724.        *        }
  725.        */
  726.       p += len;
  727.       left -= len;
  728.     }
  729. # ifdef DEBUG
  730.   if (len == 0)
  731.     debug("ReceiveMsg: Yucc! Got an EOF !!\n");
  732. # endif
  733. #else
  734.   register int ns;
  735.   struct sockaddr_un a;
  736.  
  737.   len = sizeof(struct sockaddr_un);
  738.   debug("Ha, there was someone knocking on my socket??\n");
  739.   if ((ns = accept(s, (struct sockaddr *) & a, &len)) == -1)
  740.     {
  741.       Msg(errno, "accept");
  742.       return;
  743.     }
  744.   p = (char *) &m;
  745.   left = sizeof m;
  746.   while (left > 0 && (len = read(ns, p, left)) > 0)
  747.     {
  748.       p += len;
  749.       left -= len;
  750.     }
  751.   close(ns);
  752. #endif                /* NAMEDPIPE */
  753.  
  754.   if (len == -1)
  755.     Msg(errno, "read");
  756.   if (left > 0)
  757.     return;
  758.   debug1("RecMsg: type %d !, ", m.type);
  759.   switch (m.type)
  760.     {
  761.     case MSG_WINCH:
  762.       /* Already processed in screen.c */
  763. #ifdef notdef
  764.       CheckScreenSize(1); /* Change fore */
  765. #endif
  766.       break;
  767.     case MSG_CREATE:
  768.       if (!Detached)
  769.     ExecCreate(&m);
  770.       break;
  771.     case MSG_CONT:
  772.       debug3("RecMsg: apid=%d,was %d, Detached=%d\n", m.m.attach.apid, AttacherPid, Detached);
  773.  
  774. #ifdef SECURE_MSG_CONT
  775.       if (m.m.attach.apid != AttacherPid || !Detached)
  776.     /*
  777.      * now we realize, that there is something strange happening.
  778.      * First, there was some idiot who said "CONT" and thought
  779.      * "ATTACH". This is, when we have (AttacherPid == 0). Harmless.
  780.      * Let him in. Second, we are waiting for a certain AttacherPid,
  781.      * and not for "any" attacher. This is when (AttacherPid != 0).
  782.      * But Darwin's rule says "survival of the fittest", thus: Look
  783.      * weather "our" AttacherPid is still alive and well, and let the
  784.      * new one only in, if the old Attacher has been killed. jw.
  785.      */
  786.     if (AttacherPid != 0 && kill(AttacherPid, 0) == 0)
  787.       break;        /* Intruder Alert */
  788.     else
  789. #endif                /* SECURE_MSG_CONT */
  790.       AttacherPid = 0;    /* we dont want to kill ourselves
  791.                  * later. jw. */
  792.       /* FALLTHROUGH */
  793.     case MSG_ATTACH:
  794.       if (CheckPid(m.m.attach.apid))
  795.     {
  796.       debug1("Attach attempt with bad pid(%d)\n", m.m.attach.apid);
  797.       Msg(0, "Attach attempt with bad pid(%d) !", m.m.attach.apid);
  798.           break;
  799.     }
  800. #ifdef PASSWORD
  801.       if (!CheckPasswd(m.m.attach.password, m.m.attach.apid, m.m.attach.tty))
  802.     {
  803.       debug3("RcvMsg:Checkpass(%s,%d,%s) failed\n",
  804.          m.m.attach.password, m.m.attach.apid, m.m.attach.tty);
  805.       break;
  806.     }
  807. #endif                /* PASSWORD */
  808.       if (!Detached)
  809.     {
  810.       debug("RecMsg: hey, why you disturb, we are not detached. hangup!\n");
  811.       Kill(m.m.attach.apid, SIG_BYE);
  812.       Msg(0, "Attach msg ignored: We are not detached.");
  813.       break;
  814.     }
  815.       if ((i = secopen(m.m.attach.tty, O_RDWR | O_NDELAY, 0)) < 0)
  816.     {
  817.       debug1("ALERT: Cannot open %s!\n", m.m.attach.tty);
  818. #ifdef NETHACK
  819.           if (nethackflag)
  820.         Msg(errno, "You can't open (%s). Perhaps there's a Monster behind it."
  821.           ,m.m.attach.tty);
  822.           else
  823. #endif
  824.       Msg(errno, "Attach: Could not open %s", m.m.attach.tty);
  825.       Kill(m.m.attach.apid, SIG_BYE);
  826.       break;
  827.     }
  828.       errno = 0;
  829.       if (i)
  830.     {
  831.       debug("PANIC: open did not return fd 0!\n");
  832.       close(0);
  833.       dup(i);
  834.       close(i);
  835.       close(1);
  836.       close(2);
  837.     }
  838.       debug2("RecMsg: apid %d is o.k. and we just opened '%s'\n", m.m.attach.apid, m.m.attach.tty);
  839.  
  840. #ifdef hpux_and_it_still_does_not_work
  841.       {
  842.     int pgrp, zero = 0;
  843.  
  844.     if (ioctl(0, TIOCGPGRP, &pgrp) == -1)
  845.       debug1("tcgetpgrp: %d\n", errno);    /* save old pgrp from
  846.                            tty */
  847.  
  848.     if (ioctl(0, TIOCSPGRP, &zero) == -1)
  849.       debug1("tcsetpgrp: %d\n", errno);    /* detach tty from proc
  850.                            grp */
  851. #ifdef hpux
  852.     setpgrp();
  853. #else
  854.     if (setpgrp(0, getpid()) == -1)
  855.       debug1("setpgrp: %d\n", errno);    /* make me process group
  856.                                  leader */
  857. #endif
  858.  
  859.     close(0);    /* reopen tty, now we should get it as our
  860.              * tty */
  861.     (void) secopen(m.m.attach.tty, O_RDWR | O_NDELAY, 0);    /* */
  862.  
  863. #ifdef hpux
  864.     setpgrp2(0, pgrp);
  865. #else
  866.     setpgrp(0, pgrp);
  867. #endif
  868.     ioctl(0, TIOCSPGRP, &pgrp);
  869.       }
  870. #endif  /* hpux_and_it_still_does_not_work */
  871.  
  872.       (void) dup(0);
  873.       (void) dup(0);
  874.       GetTTY(0, &OldMode);
  875.       SetMode(&OldMode, &NewMode);
  876.       SetTTY(0, &NewMode);
  877. #if !defined(POSIX) && defined(BSDJOBS)
  878.       if ((DevTty = open("/dev/tty", O_RDWR | O_NDELAY)) == -1)
  879.     {
  880.       debug1("DevTty not opened: %d.\n", errno);
  881.       Msg(errno, "/dev/tty");
  882.     }
  883. #endif
  884.       signal(SIGHUP, SigHup);
  885. #ifdef BSDJOBS
  886.       if (Suspended && m.type == MSG_ATTACH)
  887.     if (kill(AttacherPid, SIG_BYE) == 0)
  888.       kill(AttacherPid, SIGCONT);
  889. #endif
  890.  
  891.       AttacherPid = m.m.attach.apid;
  892. #ifdef UTMPOK
  893.       /*
  894.        * we set the Utmp slots again, if we were detached normally
  895.        * and if we were detached by ^Z.
  896.        */
  897.       ReInitUtmp();
  898.       for (i = WinList; i != -1; i = wtab[i]->WinLink)
  899.     if (wtab[i]->slot != (slot_t) -1)
  900.       SetUtmp(wtab[i], i);
  901. #endif
  902.       (void) chmod(SockPath, /* S_IFSOCK | */ 0700);
  903.       Detached = 0;
  904. #ifdef BSDJOBS
  905.       Suspended = 0;
  906. #endif
  907.       /*
  908.        * we like to have always the valid termcap, even if we are
  909.        * reattached from a different tty type. thus attacher had to
  910.        * tell us, what TERM we have. The attacher has correct env
  911.        * setting. we (the backend may be wrong).
  912.        */
  913.       if (*m.m.attach.envterm)
  914.     {
  915. #if defined(pyr) || defined(xelos) || defined(sequent)
  916.       /*
  917.        * Kludge for systems with braindamaged termcap routines,
  918.        * which evaluate $TERMCAP, regardless weather it describes
  919.        * the correct terminal type or not.
  920.        */
  921.       if (strcmp(getenv("TERM"), m.m.attach.envterm + 5))
  922.         {
  923.           debug("a different terminal, so unsetenv(TERMCAP)");
  924.           unsetenv("TERMCAP");
  925.         }
  926. #endif
  927.     
  928. #if !defined(sequent) && !defined(MIPS)
  929.       putenv(m.m.attach.envterm);
  930. #else
  931.       setenv("TERM", m.m.attach.envterm + 5, 1);
  932. #endif
  933.     }
  934. #if !defined(sequent) && !defined(MIPS)
  935.       sprintf(buf, "LINES=%d", m.m.attach.lines);
  936.       if (m.m.attach.lines > 0 || getenv("LINES"))
  937.         putenv(buf);
  938.       sprintf(buf, "COLUMNS=%d", m.m.attach.columns);
  939.       if (m.m.attach.columns > 0 || getenv("COLUMNS"))
  940.         putenv(buf);
  941. #else
  942.       sprintf(buf, "%d", m.m.attach.lines);
  943.       if (m.m.attach.lines > 0 || getenv("LINES"))
  944.         setenv("LINES", buf);
  945.       sprintf(buf, "%d", m.m.attach.columns);
  946.       if (m.m.attach.columns > 0 || getenv("COLUMNS"))
  947.         setenv("COLUMNS", buf);
  948. #endif
  949.       
  950.       /*
  951.        * We reboot our Terminal Emulator. Forget all we knew about
  952.        * the old terminal, reread the termcap entries in .screenrc
  953.        * (and nothing more from .screenrc is read. Mainly because
  954.        * I did not check, weather a full reinit is save. jw) 
  955.        * and /etc/screenrc, and initialise anew.
  956.        */
  957.       if (extra_outcap)
  958.     Free(extra_outcap);
  959.       if (extra_incap)
  960.     Free(extra_incap);
  961. #ifdef ETCSCREENRC
  962.       if ((p = getenv("SYSSCREENRC")) == NULL)
  963.     StartRc(ETCSCREENRC);
  964.       else
  965.     StartRc(p);
  966. #endif
  967.       StartRc(RcFileName);
  968.       InitTermcap();
  969.       InitTerm(m.m.attach.adaptflag);
  970.       fore->active = 1;
  971.       Activate();
  972.       debug("activated...\n");
  973.       break;
  974.     case MSG_ERROR:
  975.       Msg(0, "%s", m.m.message);
  976.       break;
  977.     case MSG_HANGUP:
  978. #ifdef REMOTE_DETACH
  979.     case MSG_DETACH:
  980. # ifdef POW_DETACH
  981.     case MSG_POW_DETACH:
  982. # endif                /* POW_DETACH */
  983. #endif
  984.       if (CheckPid(m.m.detach.dpid))
  985.     {
  986.       Msg(0, "Detach/Hup attempt with bad pid !!");
  987.           break;
  988.     }
  989. #ifdef PASSWORD
  990.       if (!CheckPasswd(m.m.detach.password, m.m.detach.dpid, m.m.detach.tty))
  991.     return;
  992. #endif                /* PASSWORD */
  993. #ifdef REMOTE_DETACH
  994. # ifdef POW_DETACH
  995.       if (m.type == MSG_POW_DETACH)
  996.     Detach(D_REMOTE_POWER);
  997.       else
  998. # endif                /* POW_DETACH */
  999.       if (m.type == MSG_DETACH)
  1000.     Detach(D_REMOTE);
  1001.       else
  1002. #endif
  1003.       SigHup(SIGARG);
  1004.       break;
  1005.     default:
  1006.       Msg(0, "Invalid message (type %d).", m.type);
  1007.     }
  1008. }
  1009.  
  1010. #if defined(_SEQUENT_) && !defined(NAMEDPIPE)
  1011. #undef connect
  1012.  
  1013. sconnect(s,sapp,len)
  1014. int s,len;
  1015. struct sockaddr *sapp;
  1016. {
  1017.   register struct sockaddr_un *sap;
  1018.   struct stat st;
  1019.   int x;
  1020.  
  1021.   sap=(struct sockaddr_un *)sapp;
  1022.   if (stat(sap->sun_path,&st))
  1023.     return(-1);
  1024.   chmod(sap->sun_path,0);
  1025.   x=connect(s, (struct sockaddr *) sap, len);
  1026.   chmod(sap->sun_path,st.st_mode);
  1027.   return(x);
  1028. }
  1029. #endif
  1030.