home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / screen-3.5 / part05 / socket.c < prev   
Encoding:
C/C++ Source or Header  |  1993-07-25  |  28.2 KB  |  1,170 lines

  1. /* Copyright (c) 1993
  2.  *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  3.  *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  4.  * Copyright (c) 1987 Oliver Laumann
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2, or (at your option)
  9.  * any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program (see the file COPYING); if not, write to the
  18.  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  ****************************************************************
  21.  */
  22.  
  23. #include "rcs.h"
  24. RCS_ID("$Id: socket.c,v 1.6 1993/07/21 15:43:26 mlschroe Exp $ FAU")
  25.  
  26. #include "config.h"
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #ifndef sgi
  30. # include <sys/file.h>
  31. #endif
  32. #ifndef NAMEDPIPE
  33. #include <sys/socket.h>
  34. #endif
  35. #include <fcntl.h>
  36. #ifndef NAMEDPIPE
  37. #include <sys/un.h>
  38. #endif
  39. #include <signal.h>
  40. #ifndef M_XENIX
  41. #include <sys/time.h>
  42. #endif /* M_XENIX */
  43. #ifdef DIRENT
  44. # include <dirent.h>
  45. #else
  46. # include <sys/dir.h>
  47. # define dirent direct
  48. #endif
  49.  
  50. #include "screen.h"
  51.  
  52. #ifdef USEVARARGS
  53. # if defined(__STDC__)
  54. #  include <stdarg.h>
  55. # else
  56. #  include <varargs.h>
  57. # endif
  58. #endif
  59.  
  60. #include "extern.h"
  61.  
  62. #if defined(_SEQUENT_) && !defined(NAMEDPIPE)
  63. # define connect sconnect    /* _SEQUENT_ has braindamaged connect */
  64. static int sconnect __P((int, struct sockaddr *, int));
  65. #endif
  66.  
  67. extern char *RcFileName, *extra_incap, *extra_outcap;
  68. extern int ServerSocket, real_uid, real_gid, eff_uid, eff_gid;
  69. extern int dflag, iflag, rflag, lsflag, quietflag, wipeflag, xflag;
  70. extern char *attach_tty, *LoginName, HostName[];
  71. extern struct display *display, *displays;
  72. extern struct win *fore, *console_window, *windows;
  73. extern struct NewWindow nwin_undef;
  74. #ifdef NETHACK
  75. extern nethackflag;
  76. #endif
  77. #ifdef MULTIUSER
  78. extern char *multi;
  79. #endif
  80.  
  81. #ifdef PASSWORD
  82. extern int CheckPassword;
  83. extern char Password[];
  84. #endif
  85. extern char *getenv();
  86.  
  87. char SockPath[MAXPATHLEN];
  88. char *SockNamePtr, *SockName;
  89.  
  90. #ifdef MULTIUSER
  91. # define SOCKMODE (S_IWRITE | S_IREAD | (displays ? S_IEXEC : 0) | (multi ? 1 : 0))
  92. #else
  93. # define SOCKMODE (S_IWRITE | S_IREAD | (displays ? S_IEXEC : 0))
  94. #endif
  95.  
  96. int
  97. RecoverSocket()
  98. {
  99. #ifndef NOREUID
  100.   setreuid(eff_uid, real_uid);
  101.   setregid(eff_gid, real_gid);
  102. #endif
  103.   (void) unlink(SockPath);
  104. #ifndef NOREUID
  105.   setreuid(real_uid, eff_uid);
  106.   setregid(real_gid, eff_gid);
  107. #endif
  108.   close(ServerSocket);
  109.   if ((ServerSocket = MakeServerSocket()) < 0)
  110.     return 0;
  111.   return 1;
  112. }
  113.  
  114. /*
  115.  * Socket mode 700 means we are Attached. 600 is detached.
  116.  * We return how many sockets we found. If it was exactly one, we come
  117.  * back with a SockPath set to it and open it in a fd pointed to by fdp.
  118.  * If fdp == 0 we simply produce a list if all sockets.
  119.  */
  120. /* ARGSUSED */
  121. int
  122. FindSocket(how, fdp)
  123. int how;
  124. int *fdp;
  125. {
  126.   register int s, lasts = 0, found = 0, deadcount = 0, wipecount = 0;
  127.   register int l = 0;
  128.   register DIR *dirp;
  129.   register struct dirent *dp;
  130.   register char *Name;
  131.   struct stat st;
  132.   struct foundsock
  133.     {
  134.       char *name;
  135.       int mode;
  136.     } foundsock[100];    /* 100 is hopefully enough. */
  137.   int foundsockcount = 0;
  138.  
  139.   /* User may or may not give us a (prefix) SockName. We want to search. */
  140.   debug("FindSocket:\n");
  141.   if (SockName)
  142.     {
  143.       debug1("We want to match '%s'\n", SockName);
  144.       l = strlen(SockName);
  145. #ifdef NAME_MAX
  146.       if (l > NAME_MAX)
  147.     l = NAME_MAX;
  148. #endif
  149.     }
  150.  
  151. #ifndef NOREUID
  152.   setreuid(eff_uid, real_uid);
  153.   setregid(eff_gid, real_gid);
  154. #endif
  155.   debug1("FindSock searching... '%s'\n", SockPath);
  156.   /*
  157.    * this is a hack: SockName may point to Filename(Sockpath)...
  158.    */
  159.   found = *SockNamePtr;
  160.   *SockNamePtr = '\0';
  161.   if ((dirp = opendir(SockPath)) == NULL)
  162.     {
  163.       Panic(0, "Cannot opendir %s", SockPath);
  164.       /* NOTREACHED */
  165.     }
  166.   *SockNamePtr = found;
  167.   found = 0;
  168.   while ((dp = readdir(dirp)) != NULL)
  169.     {
  170.       Name = dp->d_name;
  171.       /* 
  172.        * there may be a file ".termcap" here. 
  173.        * Ignore it just like "." and "..". 
  174.        */
  175.       if (Name[0] == '.')
  176.     continue;
  177.       if (SockName && l)
  178.     {
  179.       register char *n = Name;
  180.  
  181.       debug2("Attach found: '%s', needed '%s'\n", Name, SockName);
  182.       /*
  183.        * The SockNames "hf", "ttyhf", "1", "12345.tty", "12345.ttyhf.medusa"
  184.        * all match the Name "12345.ttyhf.medusa".
  185.        */
  186.  
  187.       if ((*SockName <= '0' || *SockName > '9') && (*n > '0' && *n <= '9'))
  188.         {
  189.           while (*++n)
  190.         if (*n == '.')
  191.           {
  192.             n++;
  193.             break;
  194.           }
  195.           if (strncmp("tty", SockName, 3) && !strncmp("tty", n, 3))
  196.         n += 3;
  197.         }
  198.       if (strncmp(n, SockName, l))
  199.         {
  200.           debug3("strncmp('%s', '%s', %d)\n", n, SockName, l);
  201.           continue;
  202.         }
  203.     }
  204.       /*
  205.        * ATTENTION! MakeClientSocket adds SockName to SockPath! 
  206.        * Anyway, we need it earlier.
  207.        */
  208.       strcpy(SockNamePtr, Name);
  209.       if (stat(SockPath, &st))
  210.     continue;
  211. #ifndef SOCK_NOT_IN_FS
  212. # ifdef NAMEDPIPE
  213.       if (!S_ISFIFO(st.st_mode))
  214.     {
  215.       debug1("'%s' is not a pipe, ignored\n", SockPath);
  216.       continue;
  217.     }
  218. # else /* NAMEDPIPE */
  219. #  ifdef S_ISSOCK
  220.       if (!S_ISSOCK(st.st_mode))
  221.     {
  222.       debug1("'%s' is not a socket, ignored\n", SockPath);
  223.       continue;
  224.     }
  225. #  endif
  226. # endif /* NAMEDPIPE */
  227. #endif
  228.       if (st.st_uid != real_uid)
  229.     continue;
  230.       s = st.st_mode & 0777;
  231. #ifdef MULTIUSER
  232.       if (multi && ((s & 0677) == 0600))
  233.     continue;
  234. #endif
  235.       foundsock[foundsockcount].name = SaveStr(Name);
  236. #ifdef MULTIUSER
  237.       foundsock[foundsockcount].mode = s ^ (multi ? 1 : 0);
  238. #else
  239.       foundsock[foundsockcount].mode = s;
  240. #endif
  241.       debug2("FindSocket: %s has mode %04o...\n", Name, s);
  242.       {
  243.     /* 
  244.      * marc parses the socketname again
  245.      */
  246.     int sockmpid = 0;
  247.     char *nam = Name;
  248.  
  249.     while (*nam)
  250.       {
  251.         if (*nam > '9' || *nam < '0')
  252.           break;
  253.         sockmpid = 10 * sockmpid + *nam - '0';
  254.         nam++;
  255.       }
  256.     /*
  257.      * A socket is counted as dead, when there is no
  258.      * process belongin to it. If there is one, and the
  259.      * socket mode indicates "single user detached", then
  260.      * we should be able to connect.
  261.      * If successfull, thats o.k. Otherwise we record that mode as -1.
  262.      * MakeClientSocket() must be careful not to block forever.
  263.      */
  264.     if (((sockmpid > 2) && kill(sockmpid, 0) == -1 && errno == ESRCH) ||
  265.         (((s & 0677) == 0600) && (s = MakeClientSocket(0, Name)) == -1))
  266.       {
  267.         foundsock[foundsockcount].mode = -1;
  268.         deadcount++;
  269.       }
  270.     else
  271.       close(s);
  272.       }
  273.       if (++foundsockcount >= 100)
  274.     break;
  275.     }
  276.   closedir(dirp);
  277.  
  278.   if (wipeflag)
  279.     {
  280.       for (s = 0; s < foundsockcount; s++)
  281.     {
  282.       if (foundsock[s].mode == -1)
  283.         {
  284.               strcpy(SockNamePtr, foundsock[s].name);
  285.           debug1("wiping '%s'\n", SockPath);
  286.           if (unlink(SockPath) == 0)
  287.             {
  288.           foundsock[s].mode = -2;
  289.               wipecount++;
  290.         }
  291.         }
  292.     }
  293.     }
  294. debug3("found=%d, dflag = %d, xflag = %d\n", found, dflag, xflag);
  295.   for (s = 0; s < foundsockcount; s++)
  296.     if ((foundsock[s].mode) == (dflag ? 0700 : 0600)
  297.         || (xflag && foundsock[s].mode == 0700)) 
  298.       {
  299.     found++;
  300. debug2("mode = %d --> found = %d\n", foundsock[s].mode, found);
  301.     lasts = s;
  302.       }
  303.   if (quietflag && (lsflag || (found != 1 && rflag != 2)))
  304.     eexit(10 + found);
  305.   debug2("attach: found=%d, foundsockcount=%d\n", found, foundsockcount);
  306.   if (found == 1 && lsflag == 0)
  307.     {
  308.       if ((lasts = MakeClientSocket(0, SockName = foundsock[lasts].name)) == -1)
  309.         found = 0;
  310.     }
  311.   else if (!quietflag && foundsockcount > 0)
  312.     {
  313.       switch (found)
  314.         {
  315.         case 0:
  316.           if (lsflag)
  317.         {
  318. #ifdef NETHACK
  319.               if (nethackflag)
  320.             printf("Your inventory:\n");
  321.           else
  322. #endif
  323.           printf((foundsockcount > 1) ?
  324.                  "There are screens on:\n" : "There is a screen on:\n");
  325.         }
  326.           else
  327.         {
  328. #ifdef NETHACK
  329.               if (nethackflag)
  330.             printf("Nothing fitting exists in the game:\n");
  331.           else
  332. #endif
  333.           printf((foundsockcount > 1) ?
  334.                  "There are screens on:\n" : "There is a screen on:\n");
  335.         }
  336.           break;
  337.         case 1:
  338. #ifdef NETHACK
  339.           if (nethackflag)
  340.             printf((foundsockcount > 1) ?
  341.                    "Prove thyself worthy or perish:\n" : 
  342.                    "You see here a good looking screen:\n");
  343.           else
  344. #endif
  345.           printf((foundsockcount > 1) ? 
  346.                  "There are several screens on:\n" :
  347.                  "There is a possible screen on:\n");
  348.           break;
  349.         default:
  350. #ifdef NETHACK
  351.           if (nethackflag)
  352.             printf((foundsockcount > 1) ? 
  353.                    "You may whish for a screen, what do you want?\n" : 
  354.                    "You see here a screen:\n");
  355.           else
  356. #endif
  357.           printf((foundsockcount > 1) ?
  358.                  "There are several screens on:\n" : "There is a screen on:\n");
  359.           break;
  360.         }
  361.       for (s = 0; s < foundsockcount; s++)
  362.     {
  363.       switch (foundsock[s].mode)
  364.         {
  365.         case 0700:
  366.           printf("\t%s\t(Attached)\n", foundsock[s].name);
  367.           break;
  368.         case 0600:
  369.           printf("\t%s\t(Detached)\n", foundsock[s].name);
  370.           break;
  371. #ifdef MULTIUSER
  372.         case 0701:
  373.           printf("\t%s\t(Multi, attached)\n", foundsock[s].name);
  374.           break;
  375.         case 0601:
  376.           printf("\t%s\t(Multi, detached)\n", foundsock[s].name);
  377.           break;
  378. #endif
  379.         case -1:
  380. #if defined(__STDC__) || defined(_AIX) || defined(SVR4)
  381.           printf("\t%s\t(Dead ??\?)\n", foundsock[s].name);
  382. #else
  383.           printf("\t%s\t(Dead ???)\n", foundsock[s].name);
  384. #endif
  385.           break;
  386.         case -2:
  387.           printf("\t%s\t(Removed)\n", foundsock[s].name);
  388.           break;
  389.         default:
  390.           printf("\t%s\t(Wrong mode)\n", foundsock[s].name);
  391.           break;
  392.         }
  393.     }
  394.     }
  395.   if (deadcount && !quietflag)
  396.     {
  397.       if (wipeflag)
  398.         {
  399. #ifdef NETHACK
  400.           if (nethackflag)
  401.             printf("You hear%s distant explosion%s.\n",
  402.            (deadcount > 1) ? "" : " a", (deadcount > 1) ? "s" : "");
  403.           else
  404. #endif
  405.           printf("%d Socket%s wiped out.\n", deadcount, (deadcount > 1)?"s":"");
  406.     }
  407.       else
  408.     {
  409. #ifdef NETHACK
  410.           if (nethackflag)
  411.             printf("The dead screen%s touch%s you. Try 'screen -wipe'.\n",
  412.            (deadcount > 1) ? "s" : "", (deadcount > 1) ? "" : "es");
  413.           else
  414. #endif
  415.           printf("Remove dead Sockets with 'screen -wipe'.\n");
  416.     }
  417.     }
  418.  
  419.   for (s = 0; s < foundsockcount; s++)
  420.     Free(foundsock[s].name);
  421.   if (found == 1 && fdp)
  422.     *fdp = lasts;
  423. #ifndef NOREUID
  424.   setreuid(real_uid, eff_uid);
  425.   setregid(real_gid, eff_gid);
  426. #endif
  427.   if (fdp)
  428.     return found;
  429.   return foundsockcount - wipecount;
  430. }
  431.  
  432. #ifdef NAMEDPIPE
  433.  
  434. int
  435. MakeServerSocket()
  436. {
  437.   register int s;
  438.   struct stat st;
  439.  
  440.   strcpy(SockNamePtr, SockName);
  441. # ifdef NAME_MAX
  442.   if (strlen(SockNamePtr) > NAME_MAX)
  443.     {
  444.       debug2("MakeClientSocket: '%s' truncated to %d chars\n",
  445.          SockNamePtr, NAME_MAX);
  446.       SockNamePtr[NAME_MAX] = '\0';
  447.     }
  448. # endif /* NAME_MAX */
  449.  
  450. # ifndef NOREUID
  451.   setreuid(eff_uid, real_uid);
  452.   setregid(eff_gid, real_gid);
  453. # endif /* NOREUID */
  454.   if ((s = open(SockPath, O_WRONLY | O_NDELAY)) >= 0)
  455.     {
  456.       debug("huii, my fifo already exists??\n");
  457.       if (quietflag)
  458.     {
  459.       Kill(d_userpid, SIG_BYE);
  460.       eexit(11);
  461.     }
  462.       printf("There is already a screen running on %s.\n",
  463.          Filename(SockPath));
  464.       if (stat(SockPath, &st) == -1)
  465.     Panic(errno, "stat");
  466.       if (st.st_uid != real_uid)
  467.     Panic(0, "Unfortunatelly you are not its owner.");
  468.       if ((st.st_mode & 0700) == 0600)
  469.     Panic(0, "To resume it, use \"screen -r\"");
  470.       else
  471.     Panic(0, "It is not detached.");
  472.       /* NOTREACHED */
  473.     }
  474. # ifndef NOREUID
  475.   (void) unlink(SockPath);
  476.   if (mknod(SockPath, S_IFIFO | SOCKMODE, 0))
  477.     Panic(0, "mknod fifo %s failed", SockPath);
  478. #  ifdef BROKEN_PIPE
  479.   if ((s = open(SockPath, O_RDWR | O_NDELAY, 0)) < 0)
  480. #  else
  481.   if ((s = open(SockPath, O_RDONLY | O_NDELAY, 0)) < 0)
  482. #  endif
  483.     Panic(errno, "open fifo %s", SockPath);
  484.   setreuid(real_uid, eff_uid);
  485.   setregid(real_gid, eff_gid);
  486.   return s;
  487. # else /* NOREUID */
  488.   if (UserContext() > 0)
  489.     {
  490.       (void) unlink(SockPath);
  491.       if (mknod(SockPath, S_IFIFO | SOCKMODE, 0))
  492.     UserReturn(0);
  493.       UserReturn(1);
  494.     }
  495.   if (UserStatus() <= 0)
  496.     Panic(0, "mknod fifo %s failed", SockPath);
  497. #  ifdef BROKEN_PIPE
  498.   if ((s = secopen(SockPath, O_RDWR | O_NDELAY, 0)) < 0)
  499. #  else
  500.   if ((s = secopen(SockPath, O_RDONLY | O_NDELAY, 0)) < 0)
  501. #  endif
  502.     Panic(errno, "open fifo %s", SockPath);
  503.   return s;
  504. # endif /* NOREUID */
  505. }
  506.  
  507.  
  508. int
  509. MakeClientSocket(err, name)
  510. int err;
  511. char *name;
  512. {
  513.   register int s = 0;
  514.  
  515.   strcpy(SockNamePtr, name);
  516. # ifdef NAME_MAX
  517.   if (strlen(SockNamePtr) > NAME_MAX)
  518.     {
  519.       debug2("MakeClientSocket: '%s' truncated to %d chars\n",
  520.          SockNamePtr, NAME_MAX);
  521.       SockNamePtr[NAME_MAX] = '\0';
  522.     }
  523. # endif /* NAME_MAX */
  524.   
  525.   if ((s = secopen(SockPath, O_WRONLY | O_NDELAY, 0)) >= 0)
  526.     {
  527.       (void) fcntl(s, F_SETFL, 0);
  528.       return s;
  529.     }
  530.   if (err)
  531.     Msg(errno, "open: %s (but continuing...)", SockPath);
  532.   debug1("MakeClientSocket() open %s failed\n", SockPath);
  533.   return -1;
  534. }
  535.  
  536. #else    /* NAMEDPIPE */
  537.  
  538. int
  539. MakeServerSocket()
  540. {
  541.   register int s;
  542.   struct sockaddr_un a;
  543.   struct stat st;
  544.  
  545.   if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
  546.     Panic(errno, "socket");
  547.   a.sun_family = AF_UNIX;
  548.   strcpy(SockNamePtr, SockName);
  549. # ifdef NAME_MAX
  550.   if (strlen(SockNamePtr) > NAME_MAX)
  551.     {
  552.       debug2("MakeServerSocket: '%s' truncated to %d chars\n",
  553.          SockNamePtr, NAME_MAX);
  554.       SockNamePtr[NAME_MAX] = '\0';
  555.     }
  556. # endif /* NAME_MAX */
  557.  
  558.   strcpy(a.sun_path, SockPath);
  559. # ifndef NOREUID
  560.   setreuid(eff_uid, real_uid);
  561.   setregid(eff_gid, real_gid);
  562. # endif /* NOREUID */
  563.   if (connect(s, (struct sockaddr *) &a, strlen(SockPath) + 2) != -1)
  564.     {
  565.       debug("oooooh! socket already is alive!\n");
  566.       if (quietflag)
  567.     { 
  568.       Kill(d_userpid, SIG_BYE);
  569.       /* 
  570.        * oh, well. nobody receives that return code. papa 
  571.        * dies by signal.
  572.        */
  573.       eexit(11);
  574.     }
  575.       printf("There is already a screen running on %s.\n",
  576.          Filename(SockPath));
  577.       if (stat(SockPath, &st) == -1)
  578.     Panic(errno, "stat");
  579.       if (st.st_uid != real_uid)
  580.     Panic(0, "Unfortunatelly you are not its owner.");
  581.       if ((st.st_mode & 0700) == 0600)
  582.     Panic(0, "To resume it, use \"screen -r\"");
  583.       else
  584.     Panic(0, "It is not detached.");
  585.       /* NOTREACHED */
  586.     }
  587. #if defined(m88k) || defined(m68k)
  588.   close(s);    /* we get bind: Invalid argument if this is not done */
  589.   if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
  590.     Panic(errno, "reopen socket");
  591. #endif
  592.   (void) unlink(SockPath);
  593.   if (bind(s, (struct sockaddr *) & a, strlen(SockPath) + 2) == -1)
  594.     Panic(errno, "bind (%s)", SockPath);
  595. #ifdef SOCK_NOT_IN_FS
  596.     {
  597.       int f;
  598.       if ((f = secopen(SockPath, O_RDWR | O_CREAT, SOCKMODE)) < 0)
  599.         Panic(errno, "shadow socket open");
  600.       close(f);
  601.     }
  602. #else
  603.   chmod(SockPath, SOCKMODE);
  604. # ifdef NOREUID
  605.   chown(SockPath, real_uid, real_gid);
  606. # endif /* NOREUID */
  607. #endif /* SOCK_NOT_IN_FS */
  608.   if (listen(s, 5) == -1)
  609.     Panic(errno, "listen");
  610. # ifdef F_SETOWN
  611.   fcntl(s, F_SETOWN, getpid());
  612.   debug1("Serversocket owned by %d\n", fcntl(s, F_GETOWN, 0));
  613. # endif /* F_SETOWN */
  614. # ifndef NOREUID
  615.   setreuid(real_uid, eff_uid);
  616.   setregid(real_gid, eff_gid);
  617. # endif /* NOREUID */
  618.   return s;
  619. }
  620.  
  621. int
  622. MakeClientSocket(err, name)
  623. int err;
  624. char *name;
  625. {
  626.   register int s;
  627.   struct sockaddr_un a;
  628.  
  629.   if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
  630.     Panic(errno, "socket");
  631.   a.sun_family = AF_UNIX;
  632.   strcpy(SockNamePtr, name);
  633. # ifdef NAME_MAX
  634.   if (strlen(SockNamePtr) > NAME_MAX)
  635.     {
  636.       debug2("MakeClientSocket: '%s' truncated to %d chars\n",
  637.          SockNamePtr, NAME_MAX);
  638.       SockNamePtr[NAME_MAX] = '\0';
  639.     }
  640. # endif /* NAME_MAX */
  641.  
  642.   strcpy(a.sun_path, SockPath);
  643. # ifndef NOREUID
  644.   setreuid(eff_uid, real_uid);
  645.   setregid(eff_gid, real_gid);
  646. # else /* NOREUID */
  647.   if (access(SockPath, W_OK))
  648.     {
  649.       if (err)
  650.     Msg(errno, "%s", SockPath);
  651.       debug2("MakeClientSocket: access(%s): %d.\n", SockPath, errno);
  652.       close(s);
  653.       return -1;
  654.     }
  655. # endif /* NOREUID */
  656.   if (connect(s, (struct sockaddr *) &a, strlen(SockPath) + 2) == -1)
  657.     {
  658.       if (err)
  659.     Msg(errno, "%s: connect", SockPath);
  660.       debug("MakeClientSocket: connect failed.\n");
  661.       close(s);
  662.       s = -1;
  663.     }
  664. # ifndef NOREUID
  665.   setreuid(real_uid, eff_uid);
  666.   setregid(real_gid, eff_gid);
  667. # endif /* NOREUID */
  668.   return s;
  669. }
  670. #endif /* NAMEDPIPE */
  671.  
  672.  
  673. void
  674. SendCreateMsg(s, nwin)
  675. int s;
  676. struct NewWindow *nwin;
  677. {
  678.   struct msg m;
  679.   register char *p;
  680.   register int len, n;
  681.   char **av = nwin->args;
  682.  
  683.   debug1("SendCreateMsg() to '%s'\n", SockPath);
  684.   bzero((char *)&m, sizeof(m));
  685.   m.type = MSG_CREATE;
  686.   strcpy(m.m_tty, attach_tty);
  687.   p = m.m.create.line;
  688.   n = 0;
  689.   if (nwin->args != nwin_undef.args)
  690.     for (av = nwin->args; *av && n < MAXARGS - 1; ++av, ++n)
  691.       {
  692.         len = strlen(*av) + 1;
  693.         if (p + len >= m.m.create.line + MAXPATHLEN - 1)
  694.       break;
  695.         strcpy(p, *av);
  696.         p += len;
  697.       }
  698.   if (nwin->aka != nwin_undef.aka && p + strlen(nwin->aka) + 1 < m.m.create.line + MAXPATHLEN)
  699.     strcpy(p, nwin->aka);
  700.   else
  701.     *p = '\0';
  702.   m.m.create.nargs = n;
  703.   m.m.create.aflag = nwin->aflag;
  704.   m.m.create.flowflag = nwin->flowflag;
  705.   m.m.create.lflag = nwin->lflag;
  706.   m.m.create.hheight = nwin->histheight;
  707. #ifdef SYSV
  708.   if (getcwd(m.m.create.dir, sizeof(m.m.create.dir)) == 0)
  709. #else
  710.   if (getwd(m.m.create.dir) == 0)
  711. #endif
  712.     {
  713.       Msg(errno, "%s", m.m.create.dir);
  714.       return;
  715.     }
  716.   if (nwin->term != nwin_undef.term)
  717.     strncpy(m.m.create.screenterm, nwin->term, 19);
  718.   m.m.create.screenterm[19] = '\0';
  719.   debug1("SendCreateMsg writing '%s'\n", m.m.create.line);
  720.   if (write(s, (char *) &m, sizeof m) != sizeof m)
  721.     Msg(errno, "write");
  722. }
  723.  
  724. void
  725. #ifdef USEVARARGS
  726. /*VARARGS1*/
  727. # if defined(__STDC__)
  728. SendErrorMsg(char *fmt, ...)
  729. # else /* __STDC__ */
  730. SendErrorMsg(fmt, va_alist)
  731. char *fmt;
  732. va_dcl
  733. # endif /* __STDC__ */
  734. { /* } */
  735.   static va_list ap;
  736. #else /* USEVARARGS */
  737. /*VARARGS1*/
  738. SendErrorMsg(fmt, p1, p2, p3, p4, p5, p6)
  739. char *fmt;
  740. unsigned long p1, p2, p3, p4, p5, p6;
  741. {
  742. #endif /* USEVARARGS */
  743.   register int s;
  744.   struct msg m;
  745.  
  746. #ifdef USEVARARGS
  747. # if defined(__STDC__)
  748.   va_start(ap, fmt);
  749. # else /* __STDC__ */
  750.   va_start(ap);
  751. # endif /* __STDC__ */
  752.   (void) vsprintf(m.m.message, fmt, ap);
  753.   va_end(ap);
  754. #else /* USEVARARGS */
  755.   sprintf(m.m.message, fmt, p1, p2, p3, p4, p5, p6);
  756. #endif /* USEVARARGS */
  757.   debug1("SendErrorMsg: '%s'\n", m.m.message);
  758.   if (display == 0)
  759.     return;
  760.   s = MakeClientSocket(1, SockName);
  761.   m.type = MSG_ERROR;
  762.   strcpy(m.m_tty, d_usertty);
  763.   debug1("SendErrorMsg(): writing to '%s'\n", SockPath);
  764.   (void) write(s, (char *) &m, sizeof m);
  765.   close(s);
  766.   sleep(2);
  767. }
  768.  
  769. #ifdef PASSWORD
  770. static int
  771. CheckPasswd(pwd, pid, utty)
  772. int pid;
  773. char *pwd, *utty;
  774. {
  775.   if (CheckPassword && 
  776.       strcmp(crypt(pwd, (strlen(Password) > 1) ? Password : "JW"),
  777.          Password))
  778.     {
  779.       if (*pwd)
  780.     {
  781. # ifdef NETHACK
  782.           if (nethackflag)
  783.         Msg(0, "'%s' tries to explode in the sky, but fails. (%s)", utty, pwd);
  784.           else
  785. # endif /* NETHACK */
  786.       Msg(0, "Illegal reattach attempt from terminal %s, \"%s\"", utty, pwd);
  787.     }
  788.       debug1("CheckPass() wrong password kill(%d, SIG_PW_FAIL)\n", pid);
  789.       Kill(pid, SIG_PW_FAIL);
  790.       return 0;
  791.     }
  792.   debug1("CheckPass() from %d happy\n", pid);
  793.   Kill(pid, SIG_PW_OK);
  794.   return 1;
  795. }
  796. #endif    /* PASSWORD */
  797.  
  798. static void
  799. ExecCreate(mp)
  800. struct msg *mp;
  801. {
  802.   struct NewWindow nwin;
  803.   char *args[MAXARGS];
  804.   register int n;
  805.   register char **pp = args, *p = mp->m.create.line;
  806.  
  807.   nwin = nwin_undef;
  808.   for (n = mp->m.create.nargs; n > 0; --n)
  809.     {
  810.       *pp++ = p;
  811.       p += strlen(p) + 1;
  812.     }
  813.   *pp = 0;
  814.   if (*p)
  815.     nwin.aka = p;
  816.   if (*args)
  817.     nwin.args = args;
  818.   nwin.aflag = mp->m.create.aflag;
  819.   nwin.flowflag = mp->m.create.flowflag;
  820.   if (*mp->m.create.dir)
  821.     nwin.dir = mp->m.create.dir;
  822.   nwin.lflag = mp->m.create.lflag;
  823.   nwin.histheight = mp->m.create.hheight;
  824.   if (*mp->m.create.screenterm)
  825.     nwin.term =  mp->m.create.screenterm;
  826.   MakeWindow(&nwin);
  827. }
  828.  
  829. static int
  830. CheckPid(pid)
  831. int pid;
  832. {
  833.   debug1("Checking pid %d\n", pid);
  834.   if (pid < 2)
  835.     return(-1);
  836.   if (eff_uid == real_uid)
  837.     return kill(pid, 0);
  838.   if (UserContext() == 1)
  839.     {
  840.       UserReturn(kill(pid, 0));
  841.     }
  842.   return UserStatus();
  843. }
  844.  
  845. void
  846. ReceiveMsg()
  847. {
  848.   int left, len, i;
  849.   static struct msg m;
  850.   char *p;
  851.   int ns = ServerSocket;
  852.   struct mode Mode;
  853. #ifdef UTMPOK
  854.   struct win *wi;
  855. #endif
  856. #ifdef REMOTE_DETACH
  857.   struct display *next;
  858. #endif
  859.  
  860. #ifdef NAMEDPIPE
  861.   debug("Ha, there was someone knocking on my fifo??\n");
  862.   if (fcntl(ServerSocket, F_SETFL, 0) == -1)
  863.     Panic(errno, "DELAY fcntl");
  864. #else
  865.   struct sockaddr_un a;
  866.  
  867.   len = sizeof(a);
  868.   debug("Ha, there was someone knocking on my socket??\n");
  869.   if ((ns = accept(ns, (struct sockaddr *) &a, &len)) < 0)
  870.     {
  871.       Msg(errno, "accept");
  872.       return;
  873.     }
  874. #endif                /* NAMEDPIPE */
  875.  
  876.   p = (char *) &m;
  877.   left = sizeof(m);
  878.   while (left > 0)
  879.     {
  880.       len = read(ns, p, left);
  881.       if (len < 0 && errno == EINTR)
  882.     continue;
  883.       if (len <= 0)
  884.     break;
  885.       p += len;
  886.       left -= len;
  887.     }
  888.  
  889. #ifdef NAMEDPIPE
  890. # ifndef BROKEN_PIPE
  891.   /* Reopen pipe to prevent EOFs at the select() call */
  892.   close(ServerSocket);
  893.   if ((ServerSocket = secopen(SockPath, O_RDONLY | O_NDELAY, 0)) < 0)
  894.     Panic(errno, "reopen fifo %s", SockPath);
  895. # endif
  896. #else
  897.   close(ns);
  898. #endif
  899.  
  900.   if (len < 0)
  901.     {
  902.       Msg(errno, "read");
  903.       return;
  904.     }
  905.   if (left > 0)
  906.     {
  907.       if (left != sizeof(m))
  908.         Msg(0, "Message %d of %d bytes too small", left, sizeof(m));
  909.       else
  910.     debug("No data on socket.\n");
  911.       return;
  912.     }
  913.   debug2("*** RecMsg: type %d tty %s\n", m.type, m.m_tty);
  914.   for (display = displays; display; display = display->_d_next)
  915.     if (strcmp(d_usertty, m.m_tty) == 0)
  916.       break;
  917.   debug2("display: %s display %sfound\n", m.m_tty, display ? "" : "not ");
  918.   if (!display)
  919.     {
  920.       struct win *w;
  921.  
  922.       for (w = windows; w; w = w->w_next)
  923.         if (!strcmp(m.m_tty, w->w_tty))
  924.       {
  925.             display = w->w_display;
  926.         debug2("but window %s %sfound.\n", m.m_tty, display ? "" : "deatached (ignoring) ");
  927.         break;
  928.           }
  929.     }
  930.  
  931.   /* Remove the status to prevent garbage on the screen */
  932.   if (display && d_status)
  933.     RemoveStatus();
  934.  
  935.   switch (m.type)
  936.     {
  937.     case MSG_WINCH:
  938.       if (display)
  939.         CheckScreenSize(1); /* Change fore */
  940.       break;
  941.     case MSG_CREATE:
  942.       if (display)
  943.     ExecCreate(&m);
  944.       break;
  945.     case MSG_CONT:
  946.     if (display && d_userpid != 0 && kill(d_userpid, 0) == 0)
  947.       break;        /* Intruder Alert */
  948.       debug2("RecMsg: apid=%d,was %d\n", m.m.attach.apid, display ? d_userpid : 0);
  949.       /* FALLTHROUGH */
  950.     case MSG_ATTACH:
  951.       if (CheckPid(m.m.attach.apid))
  952.     {
  953.       debug1("Attach attempt with bad pid(%d)\n", m.m.attach.apid);
  954.       Msg(0, "Attach attempt with bad pid(%d) !", m.m.attach.apid);
  955.           break;
  956.     }
  957.       if ((i = secopen(m.m_tty, O_RDWR | O_NDELAY, 0)) < 0)
  958.     {
  959.       debug1("ALERT: Cannot open %s!\n", m.m_tty);
  960. #ifdef NETHACK
  961.           if (nethackflag)
  962.         Msg(errno, 
  963.             "You can't open (%s). Perhaps there's a Monster behind it",
  964.             m.m_tty);
  965.           else
  966. #endif
  967.       Msg(errno, "Attach: Could not open %s", m.m_tty);
  968.       Kill(m.m.attach.apid, SIG_BYE);
  969.       break;
  970.     }
  971. #ifdef PASSWORD
  972.       if (!CheckPasswd(m.m.attach.password, m.m.attach.apid, m.m_tty))
  973.     {
  974.       debug3("RcvMsg:Checkpass(%s,%d,%s) failed\n",
  975.          m.m.attach.password, m.m.attach.apid, m.m_tty);
  976.       close(i);
  977.       break;
  978.     }
  979. #else
  980. # ifdef MULTIUSER
  981.       Kill(m.m.attach.apid, SIGCONT);
  982. # endif
  983. #endif                /* PASSWORD */
  984.       if (display)
  985.     {
  986.       debug("RecMsg: hey, why you disturb, we are not detached. hangup!\n");
  987.       close(i);
  988.       Kill(m.m.attach.apid, SIG_BYE);
  989.       Msg(0, "Attach msg ignored: We are not detached.");
  990.       break;
  991.     }
  992.  
  993. #ifdef MULTIUSER
  994.       if (strcmp(m.m.attach.auser, LoginName))
  995.         if (*FindUserPtr(m.m.attach.auser) == 0)
  996.       {
  997.               write(i, "Access to session denied.\n", 26);
  998.           close(i);
  999.           Kill(m.m.attach.apid, SIG_BYE);
  1000.           Msg(0, "Attach: access denied for user %s", m.m.attach.auser);
  1001.           break;
  1002.       }
  1003. #endif
  1004.  
  1005.       errno = 0;
  1006.       debug2("RecMsg: apid %d is o.k. and we just opened '%s'\n", m.m.attach.apid, m.m_tty);
  1007.       /* turn off iflag on a multi-attach... */
  1008.       if (iflag && displays)
  1009.     {
  1010.       iflag = 0;
  1011.       display = displays;
  1012. #if defined(TERMIO) || defined(POSIX)
  1013.       d_NewMode.tio.c_cc[VINTR] = VDISABLE;
  1014.       d_NewMode.tio.c_lflag &= ~ISIG;
  1015. #else /* TERMIO || POSIX */
  1016.       d_NewMode.m_tchars.t_intrc = -1;
  1017. #endif /* TERMIO || POSIX */
  1018.       SetTTY(d_userfd, &d_NewMode);
  1019.     }
  1020.  
  1021.       /* create new display */
  1022.       GetTTY(i, &Mode);
  1023.       if (MakeDisplay(m.m.attach.auser, m.m_tty, m.m.attach.envterm, i, m.m.attach.apid, &Mode) == 0)
  1024.         {
  1025.       write(i, "Could not make display.\n", 24);
  1026.       close(i);
  1027.       Msg(errno, "Attach: could not make display for user %s", m.m.attach.auser);
  1028.       Kill(m.m.attach.apid, SIG_BYE);
  1029.       break;
  1030.         }
  1031. #ifdef ultrix
  1032.       brktty(d_userfd);    /* for some strange reason this must be done */
  1033. #endif
  1034. #if defined(pyr) || defined(xelos) || defined(sequent)
  1035.       /*
  1036.        * Kludge for systems with braindamaged termcap routines,
  1037.        * which evaluate $TERMCAP, regardless weather it describes
  1038.        * the correct terminal type or not.
  1039.        */
  1040.       debug("unsetenv(TERMCAP) in case of a different terminal");
  1041.       unsetenv("TERMCAP");
  1042. #endif
  1043.     
  1044.       /*
  1045.        * We reboot our Terminal Emulator. Forget all we knew about
  1046.        * the old terminal, reread the termcap entries in .screenrc
  1047.        * (and nothing more from .screenrc is read. Mainly because
  1048.        * I did not check, weather a full reinit is save. jw) 
  1049.        * and /etc/screenrc, and initialise anew.
  1050.        */
  1051.       if (extra_outcap)
  1052.     free(extra_outcap);
  1053.       if (extra_incap)
  1054.     free(extra_incap);
  1055.       extra_incap = extra_outcap = 0;
  1056.       debug2("Message says size (%dx%d)\n", m.m.attach.columns, m.m.attach.lines);
  1057. #ifdef ETCSCREENRC
  1058.       if ((p = getenv("SYSSCREENRC")) == NULL)
  1059.     StartRc(ETCSCREENRC);
  1060.       else
  1061.     StartRc(p);
  1062. #endif
  1063.       StartRc(RcFileName);
  1064.       if (InitTermcap(m.m.attach.columns, m.m.attach.lines))
  1065.     {
  1066.       FreeDisplay();
  1067.       Kill(m.m.attach.apid, SIG_BYE);
  1068.       break;
  1069.     }
  1070.       InitTerm(m.m.attach.adaptflag);
  1071.       if (displays->_d_next == 0)
  1072.         (void) chsock();
  1073.       signal(SIGHUP, SigHup);
  1074. #ifdef UTMPOK
  1075.       /*
  1076.        * we set the Utmp slots again, if we were detached normally
  1077.        * and if we were detached by ^Z.
  1078.        */
  1079.       RemoveLoginSlot();
  1080.       if (displays->_d_next == 0)
  1081.         for (wi = windows; wi; wi = wi->w_next)
  1082.       if (wi->w_slot != (slot_t) -1)
  1083.         SetUtmp(wi);
  1084. #endif
  1085.       SetMode(&d_OldMode, &d_NewMode);
  1086.       SetTTY(d_userfd, &d_NewMode);
  1087.       if (fore && fore->w_display == 0)
  1088.         SetForeWindow(fore);
  1089.       else
  1090.         d_fore = 0;
  1091.       Activate(0);
  1092.       if (d_fore == 0)
  1093.     ShowWindows();
  1094.       if (displays->_d_next == 0 && console_window)
  1095.     {
  1096.       if (TtyGrabConsole(console_window->w_ptyfd, 1, "reattach") == 0)
  1097.         Msg(0, "console %s is on window %d", HostName, console_window->w_number);
  1098.     }
  1099.       debug("activated...\n");
  1100.       break;
  1101.     case MSG_ERROR:
  1102.       Msg(0, "%s", m.m.message);
  1103.       break;
  1104.     case MSG_HANGUP:
  1105.       SigHup(SIGARG);
  1106.       break;
  1107. #ifdef REMOTE_DETACH
  1108.     case MSG_DETACH:
  1109. # ifdef POW_DETACH
  1110.     case MSG_POW_DETACH:
  1111. # endif                /* POW_DETACH */
  1112.       for (display = displays; display; display = next)
  1113.     {
  1114.       next = display->_d_next;
  1115. # ifdef POW_DETACH
  1116.       if (m.type == MSG_POW_DETACH)
  1117.         Detach(D_REMOTE_POWER);
  1118.       else
  1119. # endif                /* POW_DETACH */
  1120.       if (m.type == MSG_DETACH)
  1121.         Detach(D_REMOTE);
  1122.     }
  1123.       break;
  1124. #endif
  1125.     default:
  1126.       Msg(0, "Invalid message (type %d).", m.type);
  1127.     }
  1128. }
  1129.  
  1130. #if defined(_SEQUENT_) && !defined(NAMEDPIPE)
  1131. #undef connect
  1132.  
  1133. /*
  1134.  *  sequent_ptx socket emulation must have mode 000 on the socket!
  1135.  */
  1136. static int
  1137. sconnect(s, sapp, len)
  1138. int s, len;
  1139. struct sockaddr *sapp;
  1140. {
  1141.   register struct sockaddr_un *sap;
  1142.   struct stat st;
  1143.   int x;
  1144.  
  1145.   sap = (struct sockaddr_un *)sapp;
  1146.   if (stat(sap->sun_path, &st))
  1147.     return -1;
  1148.   chmod(sap->sun_path, 0);
  1149.   x = connect(s, (struct sockaddr *) sap, len);
  1150.   chmod(sap->sun_path, st.st_mode);
  1151.   return x;
  1152. }
  1153. #endif
  1154.  
  1155. int
  1156. chsock()
  1157. {
  1158.   int r, euid = geteuid();
  1159.   if (euid != real_uid)
  1160.     {
  1161.       if (UserContext() <= 0)
  1162.         return UserStatus();
  1163.     }
  1164.   r = chmod(SockPath, SOCKMODE);
  1165.   if (euid != real_uid)
  1166.     UserReturn(r);
  1167.   return r;
  1168. }
  1169.  
  1170.