home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1621 / sigler.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  7.9 KB  |  325 lines

  1. /* Copyright 1990, Daniel J. Bernstein. All rights reserved. */
  2.  
  3. #include "config.h"
  4. #include <sys/types.h>
  5. #include <sys/time.h>
  6. #include <stdio.h>
  7. #include <strings.h>
  8. #include "pty.h"
  9. #include "sigler.h"
  10. #include "sig.h"
  11. #include "file.h"
  12. #include "sock.h"
  13. #include "err.h"
  14. #include "misc.h"
  15.  
  16. /* General XXX: In failure cases, sig.* isn't always removed. */
  17.  
  18. static char *glfnsty;
  19.  
  20. static int masterpid;
  21.  
  22. static int flagmaster = 1;
  23. static int flagcont = 0;
  24. static int pi[2];
  25.  
  26. static void deatherrp(i,s)
  27. int i;
  28. char *s;
  29. {
  30.  int e = errno;
  31.  
  32.  (void) kill(masterpid,SIGTERM);
  33.  /* XXX: should wait while flagmaster */
  34.  (void) tty_modifymodes(fdtty,&tmotty,&tmochartty);
  35.  fatalerrp(i,s,e);
  36. }
  37.  
  38. static void finish(i)
  39. sig_num i;
  40. {
  41.  if (i == SIGTERM)
  42.   {
  43.    flagmaster = 0;
  44.    (void) write(pi[1],".",1);
  45.   }
  46.  else
  47.    (void) write(pi[1],",",1);
  48. }
  49.  
  50. /*ARGSUSED*/
  51. static void sig_usr2(i)
  52. sig_num i;
  53. {
  54.  if (flagsession)
  55.   {
  56.    char fnsess[20];
  57.    int fdsess;
  58.    int newuid = uid;
  59.    char newsuid[10];
  60.  
  61.    /* XXX: We should have some error recovery here! */
  62.  
  63.    /* We can make quite a few assumptions, because we only get USR2 */
  64.    /* forwarded from the master. */
  65.  
  66.    (void) sprintf(fnsess,"sess.%s",glfnsty + sizeof(DEVSTY) - 3);
  67.    if ((fdsess = open(fnsess,O_RDONLY,0600)) != -1)
  68.     {
  69.      (void) read(fdsess,(char *) &newuid,sizeof(int));
  70.      (void) sprintf(newsuid,"%d",newuid);
  71.  
  72.      (void) chdir("..");
  73.      (void) chdir(newsuid);
  74.   
  75.      uid = newuid;
  76.      (void) setreuid(uid,euid);
  77.      (void) close(fdsess);
  78.     }
  79.   }
  80. }
  81.  
  82. /*ARGSUSED*/
  83. static void sig_cont(i)
  84. sig_num i;
  85. {
  86.  flagcont = 1;
  87.  (void) write(pi[1]," ",1);
  88. }
  89.  
  90. void sigler(fnsty,master)
  91. char *fnsty;
  92. int master;
  93. {
  94.  char ch;
  95.  char path[100];
  96.  int fd = -1;
  97.  char *ttyn;
  98.  char fntty[TTYNAMELEN];
  99.  
  100.  glfnsty = fnsty;
  101.  masterpid = master;
  102.  /* pid = getpid() is already true */
  103.  (void) sprintf(path,"sig.%s",fnsty + sizeof(DEVSTY) - 3);
  104.  (void) unlink(path);
  105.  
  106.  (void) close(fdmty);
  107.  (void) close(fdsty);
  108.  if (fdre != -1) (void) close(fdre);
  109.  
  110.  if (pipe(pi) == -1) /* clumsy, but stops several races */
  111.    /* This is absolutely impossible. fdmty and fdsty must have been open */
  112.    /* before this, and we just closed them, so there must be two fds */
  113.    /* available for the pipe. */
  114.    deatherrp(10,"pty: fatal: cannot open internal pipe");
  115.  (void) fcntl(pi[1],F_SETFL,FNDELAY);
  116.  
  117.  sig_ignore(SIGCHLD);
  118.  sig_ignore(SIGXCPU);
  119.  sig_ignore(SIGXFSZ);
  120.  sig_ignore(SIGPROF);
  121.  sig_ignore(SIGVTALRM);
  122.  
  123.  sig_default(SIGEMT); /* XXX: really dump? */
  124.  sig_default(SIGIOT);
  125.  sig_default(SIGILL);
  126.  sig_default(SIGSEGV);
  127.  
  128.  sig_default(SIGTTOU);
  129.  sig_default(SIGTTIN);
  130.  sig_default(SIGTSTP);
  131.  sig_default(SIGSTOP);
  132.  
  133.  sig_sethandler(SIGTERM,finish); sig_handle(SIGTERM);
  134.  sig_sethandler(SIGINT,finish); sig_handle(SIGINT);
  135.  sig_sethandler(SIGQUIT,finish); sig_handle(SIGQUIT);
  136.  sig_sethandler(SIGHUP,finish); sig_handle(SIGHUP);
  137.  sig_sethandler(SIGUSR1,finish); sig_handle(SIGUSR1); /* disconnect */
  138.  
  139.  sig_sethandler(SIGCONT,sig_cont); sig_handle(SIGCONT);
  140.  
  141.  sig_sethandler(SIGUSR2,sig_usr2); sig_handle(SIGUSR2);
  142.  
  143.  for (;;)
  144.   {
  145.    if (flagcont)
  146.     {
  147.      flagcont = 0;
  148.      if (tty_modifymodes(fdtty,&tmochartty,&tmotty) == -1)
  149.        ; /* XXX: impossible, but what if it happens? */
  150.      (void) kill(masterpid,SIGUSR1); /* not CONT---see master.c's sig_cont() */
  151.     }
  152. #ifdef NO_FDPASSING
  153.    if (flagmaster == 2)
  154.     {
  155.      static fd_set rfds;
  156.      static fd_set wfds;
  157.      static int r;
  158.      static int w;
  159.      static char foobuf[OUTBUFSIZE];
  160.      int fdnum;
  161.      static char *s;
  162.  
  163.      fdnum = fd; if (fdin > fdnum) fdnum = fdin;
  164.      if (pi[0] > fdnum) fdnum = pi[0]; fdnum++;
  165.  
  166.      FD_ZERO(&rfds);
  167.      FD_ZERO(&wfds);
  168.      FD_SET(fd,&rfds);
  169.      FD_SET(fdin,&rfds);
  170.      FD_SET(pi[0],&rfds);
  171.  
  172.      r = select(fdnum,&rfds,&wfds,(fd_set *) 0,(struct timeval *) 0);
  173.      if (r > 0)
  174.       {
  175.        if (FD_ISSET(fd,&rfds))
  176.     {
  177.      if ((r = read(fd,foobuf,OUTBUFSIZE)) == -1)
  178.        deatherrp(11,"pty: fatal: socket read error");
  179.      s = foobuf;
  180.      /* XXX: r can't be zero, but what if it is? */
  181.      while (r)
  182.       {
  183.        if ((w = write(fdout,s,r)) == -1)
  184.          deatherrp(14,"pty: fatal: output write error");
  185.        r -= w; s += w;
  186.       }
  187.     }
  188.        if (FD_ISSET(fdin,&rfds))
  189.     {
  190.      if ((r = read(fdin,foobuf,OUTBUFSIZE)) == -1)
  191.        deatherrp(13,"pty: fatal: input read error");
  192.      s = foobuf;
  193.      /* XXX: What if r is zero? Can't pass EOF, grrrr */
  194.      while (r)
  195.       {
  196.        if ((w = write(fd,s,r)) == -1)
  197.          deatherrp(12,"pty: fatal: socket write error");
  198.        r -= w; s += w;
  199.       }
  200.     }
  201.        if (FD_ISSET(pi[0],&rfds))
  202.      (void) read(pi[0],&ch,1);
  203.       }
  204.     }
  205.    else
  206.      (void) read(pi[0],&ch,1);
  207. #else
  208.    (void) read(pi[0],&ch,1);
  209. #endif
  210.    if ((ch == '.') || (ch == ','))
  211.     {
  212.      if (fd != -1)
  213.        (void) close(fd);
  214.      if (flagmaster)
  215.       {
  216.        if (kill(masterpid,SIGTERM) == -1)
  217.      flagmaster = 0; /* XXX */
  218.  
  219.        if (fdpass != -1)
  220.      (void) write(fdpass,".",1);
  221.     
  222.        while (flagmaster)
  223.          ;
  224.        while (ch != '.')
  225.          (void) read(pi[0],&ch,1);
  226.       }
  227.  
  228.      /* We don't test at this point whether the killing signal was a HUP. */
  229.      /* This means that hanging up on a reconnecting sigler won't stop */
  230.      /* the reconnect; instead, the new session will be instantly hung */
  231.      /* up. The USR1 used for a manual disconnect could be HUP for this */
  232.      /* reason. */
  233.      if (flagsession
  234.        &&((fd = open(path,O_RDONLY)) != -1)
  235.        &&(read(fd,fnsty,sizeof(DEVSTY) - 1) > 0))
  236.       {
  237.        warnerr2("pty: reconnecting to %s\r\n",fnsty);
  238.        (void) close(fd);
  239.        (void) unlink(path);
  240.        if ((fd = pty_writesock(fnsty)) == -1)
  241.      warnerr2("pty: reconnect failed: cannot talk to %s\r\n",fnsty);
  242.        else
  243.     {
  244.      if ((pty_getch(fd,&ch) != -1) && (ch == 'p'))
  245.        if (pty_putgetint(fd,'p',&masterpid) != -1)
  246.          do
  247.           {
  248. #ifdef NO_FDPASSING
  249.                if (fdtty != -1)
  250.         {
  251.                  if (!(ttyn = real_ttyname(fdtty))) break;
  252.              /* XXX: Should we NXCL here? */
  253.              (void) strncpy(fntty,ttyn,TTYNAMELEN - 1);
  254.                  if (pty_sendstr(fd,'s',fntty) == -1) break;
  255.              if (flagverbose)
  256.            warnerr2("pty: sent parent tty %s\r\n",fntty);
  257.         }
  258. #else
  259.            if (fdtty != -1)
  260.         {
  261.                  if (!(ttyn = real_ttyname(fdtty))) break;
  262.              /* XXX: Should we NXCL here? */
  263.              (void) strncpy(fntty,ttyn,TTYNAMELEN - 1);
  264.                  if (pty_sendstr(fd,'s',fntty) == -1) break;
  265.              if (flagverbose)
  266.              warnerr2("pty: sent parent tty %s\r\n",fntty);
  267.              /* We shouldn't have to send the parent tty name, */
  268.              /* but passing the fd alone doesn't set the control */
  269.              /* terminal of the receiver (grrrr), and a detached */
  270.              /* process effectively has no pgrp. Aargh. */
  271.         }
  272.  
  273.            if (fdpass == -1)
  274.         {
  275.              if (pty_sendfd(fd,'0',&fdin) == -1) break;
  276.              if (pty_sendfd(fd,'1',&fdout) == -1) break;
  277.         }
  278.            else
  279.          if (pty_sendfd(fd,'f',&fdpass) == -1) break;
  280.            if (fdtty != -1)
  281.          if (pty_sendfd(fd,'t',&fdtty) == -1) break;
  282. #endif
  283.            if (pty_sendint(fd,'p',&pid) == -1) break;
  284.            if (pty_sendint(fd,'g',&pgrp) == -1) break;
  285.            if (pty_sendint(fd,'j',&flagjobctrl) == -1) break;
  286.            if (fdtty != -1)
  287.         {
  288.          if (pty_sendtty(fd,'c',&tmochartty) == -1) break;
  289.          if (pty_sendtty(fd,'n',&tmotty) == -1) break;
  290.         }
  291.            if (pty_putch(fd," ") == -1) break;
  292. #ifdef NO_FDPASSING
  293.            flagmaster = 2; /* Success, but pain coming up. */
  294. #else
  295.            flagmaster = 1; /* Successfully reconnected! */
  296. #endif
  297.           }
  298.          while(0);
  299.      if (flagmaster < 2)
  300.       {
  301.            (void) close(fd);
  302.        fd = -1;
  303.       }
  304.     }
  305.        if (flagmaster)
  306.     {
  307.      /* remake path for new pty */
  308.          (void) sprintf(path,"sig.%s",fnsty + sizeof(DEVSTY) - 3);
  309.          (void) unlink(path);
  310.      warnerr2("pty: successfully reconnected to %s\r\n",fnsty);
  311.     }
  312.        else
  313.      warnerr2("pty: reconnect to %s failed\r\n",fnsty);
  314.       }
  315.      if (!flagmaster)
  316.       {
  317.        if (tty_modifymodes(fdtty,&tmotty,&tmochartty) == -1)
  318.          warnerr2("%s","pty: can't restore tty modes\n"); /*XXX*/
  319.        fatal(0);
  320.        /*NOTREACHED*/
  321.       }
  322.     }
  323.   }
  324. }
  325.