home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume23 / pty / part03 / sigler.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-01-08  |  7.9 KB  |  326 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.    ch = '0';
  146.    if (flagcont)
  147.     {
  148.      flagcont = 0;
  149.      if (tty_modifymodes(fdtty,&tmochartty,&tmotty) == -1)
  150.        ; /* XXX: impossible, but what if it happens? */
  151.      (void) kill(masterpid,SIGUSR1); /* not CONT---see master.c's sig_cont() */
  152.     }
  153. #ifdef NO_FDPASSING
  154.    if (flagmaster == 2)
  155.     {
  156.      static fd_set rfds;
  157.      static fd_set wfds;
  158.      static int r;
  159.      static int w;
  160.      static char foobuf[OUTBUFSIZE];
  161.      int fdnum;
  162.      static char *s;
  163.  
  164.      fdnum = fd; if (fdin > fdnum) fdnum = fdin;
  165.      if (pi[0] > fdnum) fdnum = pi[0]; fdnum++;
  166.  
  167.      FD_ZERO(&rfds);
  168.      FD_ZERO(&wfds);
  169.      FD_SET(fd,&rfds);
  170.      FD_SET(fdin,&rfds);
  171.      FD_SET(pi[0],&rfds);
  172.  
  173.      r = select(fdnum,&rfds,&wfds,(fd_set *) 0,(struct timeval *) 0);
  174.      if (r > 0)
  175.       {
  176.        if (FD_ISSET(fd,&rfds))
  177.     {
  178.      if ((r = read(fd,foobuf,OUTBUFSIZE)) == -1)
  179.        deatherrp(11,"pty: fatal: socket read error");
  180.      s = foobuf;
  181.      /* XXX: r can't be zero, but what if it is? */
  182.      while (r)
  183.       {
  184.        if ((w = write(fdout,s,r)) == -1)
  185.          deatherrp(14,"pty: fatal: output write error");
  186.        r -= w; s += w;
  187.       }
  188.     }
  189.        if (FD_ISSET(fdin,&rfds))
  190.     {
  191.      if ((r = read(fdin,foobuf,OUTBUFSIZE)) == -1)
  192.        deatherrp(13,"pty: fatal: input read error");
  193.      s = foobuf;
  194.      /* XXX: What if r is zero? Can't pass EOF, grrrr */
  195.      while (r)
  196.       {
  197.        if ((w = write(fd,s,r)) == -1)
  198.          deatherrp(12,"pty: fatal: socket write error");
  199.        r -= w; s += w;
  200.       }
  201.     }
  202.        if (FD_ISSET(pi[0],&rfds))
  203.      (void) read(pi[0],&ch,1);
  204.       }
  205.     }
  206.    else
  207.      (void) read(pi[0],&ch,1);
  208. #else
  209.    (void) read(pi[0],&ch,1);
  210. #endif
  211.    if ((ch == '.') || (ch == ','))
  212.     {
  213.      if (fd != -1)
  214.        (void) close(fd);
  215.      if (flagmaster)
  216.       {
  217.        if (kill(masterpid,SIGTERM) == -1)
  218.      flagmaster = 0; /* XXX */
  219.  
  220.        if (fdpass != -1)
  221.      (void) write(fdpass,".",1);
  222.     
  223.        while (flagmaster)
  224.          ;
  225.        while (ch != '.')
  226.          (void) read(pi[0],&ch,1);
  227.       }
  228.  
  229.      /* We don't test at this point whether the killing signal was a HUP. */
  230.      /* This means that hanging up on a reconnecting sigler won't stop */
  231.      /* the reconnect; instead, the new session will be instantly hung */
  232.      /* up. The USR1 used for a manual disconnect could be HUP for this */
  233.      /* reason. */
  234.      if (flagsession
  235.        &&((fd = open(path,O_RDONLY)) != -1)
  236.        &&(read(fd,fnsty,sizeof(DEVSTY) - 1) > 0))
  237.       {
  238.        warnerr2("pty: reconnecting to %s\r\n",fnsty);
  239.        (void) close(fd);
  240.        (void) unlink(path);
  241.        if ((fd = pty_writesock(fnsty)) == -1)
  242.      warnerr2("pty: reconnect failed: cannot talk to %s\r\n",fnsty);
  243.        else
  244.     {
  245.      if ((pty_getch(fd,&ch) != -1) && (ch == 'p'))
  246.        if (pty_putgetint(fd,'p',&masterpid) != -1)
  247.          do
  248.           {
  249. #ifdef NO_FDPASSING
  250.                if (fdtty != -1)
  251.         {
  252.                  if (!(ttyn = real_ttyname(fdtty))) break;
  253.              /* XXX: Should we NXCL here? */
  254.              (void) strncpy(fntty,ttyn,TTYNAMELEN - 1);
  255.                  if (pty_sendstr(fd,'s',fntty) == -1) break;
  256.              if (flagverbose)
  257.            warnerr2("pty: sent parent tty %s\r\n",fntty);
  258.         }
  259. #else
  260.            if (fdtty != -1)
  261.         {
  262.                  if (!(ttyn = real_ttyname(fdtty))) break;
  263.              /* XXX: Should we NXCL here? */
  264.              (void) strncpy(fntty,ttyn,TTYNAMELEN - 1);
  265.                  if (pty_sendstr(fd,'s',fntty) == -1) break;
  266.              if (flagverbose)
  267.              warnerr2("pty: sent parent tty %s\r\n",fntty);
  268.              /* We shouldn't have to send the parent tty name, */
  269.              /* but passing the fd alone doesn't set the control */
  270.              /* terminal of the receiver (grrrr), and a detached */
  271.              /* process effectively has no pgrp. Aargh. */
  272.         }
  273.  
  274.            if (fdpass == -1)
  275.         {
  276.              if (pty_sendfd(fd,'0',&fdin) == -1) break;
  277.              if (pty_sendfd(fd,'1',&fdout) == -1) break;
  278.         }
  279.            else
  280.          if (pty_sendfd(fd,'f',&fdpass) == -1) break;
  281.            if (fdtty != -1)
  282.          if (pty_sendfd(fd,'t',&fdtty) == -1) break;
  283. #endif
  284.            if (pty_sendint(fd,'p',&pid) == -1) break;
  285.            if (pty_sendint(fd,'g',&pgrp) == -1) break;
  286.            if (pty_sendint(fd,'j',&flagjobctrl) == -1) break;
  287.            if (fdtty != -1)
  288.         {
  289.          if (pty_sendtty(fd,'c',&tmochartty) == -1) break;
  290.          if (pty_sendtty(fd,'n',&tmotty) == -1) break;
  291.         }
  292.            if (pty_putch(fd," ") == -1) break;
  293. #ifdef NO_FDPASSING
  294.            flagmaster = 2; /* Success, but pain coming up. */
  295. #else
  296.            flagmaster = 1; /* Successfully reconnected! */
  297. #endif
  298.           }
  299.          while(0);
  300.      if (flagmaster < 2)
  301.       {
  302.            (void) close(fd);
  303.        fd = -1;
  304.       }
  305.     }
  306.        if (flagmaster)
  307.     {
  308.      /* remake path for new pty */
  309.          (void) sprintf(path,"sig.%s",fnsty + sizeof(DEVSTY) - 3);
  310.          (void) unlink(path);
  311.      warnerr2("pty: successfully reconnected to %s\r\n",fnsty);
  312.     }
  313.        else
  314.      warnerr2("pty: reconnect to %s failed\r\n",fnsty);
  315.       }
  316.      if (!flagmaster)
  317.       {
  318.        if (tty_modifymodes(fdtty,&tmotty,&tmochartty) == -1)
  319.          warnerr2("%s","pty: can't restore tty modes\n"); /*XXX*/
  320.        fatal(0);
  321.        /*NOTREACHED*/
  322.       }
  323.     }
  324.   }
  325. }
  326.