home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / pty4 / part05 / ptysigler.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-18  |  7.8 KB  |  313 lines

  1. #include <sys/types.h>
  2. #include <sys/wait.h>
  3. #include <sys/time.h>
  4. #include <sys/resource.h>
  5. #include <signal.h>
  6. #include "sigsched.h"
  7. #include "sigdfl.h"
  8. #include "fmt.h"
  9. #include "sessconnlog.h"
  10. #include "ptytty.h"
  11. #include "ptycomm.h"
  12. #include "ptymisc.h"
  13. #include "ptyerr.h"
  14. #include "config/ttyopts.h"
  15. #include "ptysigler.h"
  16. extern void doconnect(); /* XXX: gaargh */
  17. extern void ckobey();
  18.  
  19. #define verbose 0, /*XXX*/
  20.  
  21. static int firsttime;
  22.  
  23. static char resp6[6];
  24. static char *sremote;
  25. static int sremotelen;
  26.  
  27. static int sflagttymodes; /* must be 0 if !sflagreading */
  28. static struct ttymodes stmotty; /* only valid if sflagttymodes */
  29. static struct ttymodes stmottyzero; /* only valid if sflagttymodes */
  30. static int sflagreading;
  31. static int sflagjobctrl;
  32. static int fdmaster = -1;
  33. static int fdus2master = -1;
  34.  
  35. static int fdtty = -1;
  36.  
  37. static int suid = -1;
  38. static char recoext[2]; /* if null, then unset */
  39.  
  40. void lastmoment(n)
  41. int n;
  42. {
  43.  /* clean up and die! */
  44.  if (sflagttymodes)
  45.    tty_setmodes(fdtty,&stmotty);
  46. }
  47.  
  48. void stop(sig)
  49. int sig;
  50. {
  51.  sigdfl(sig);
  52. }
  53.  
  54. void byebye(sig)
  55. int sig;
  56. {
  57.  lastmoment(0);
  58.  sigdfl(sig);
  59.  die(DIE_IMPOSSIBLE);
  60. }
  61.  
  62. void obey(n)
  63. int n;
  64. {
  65.  int r;
  66.  char c[4];
  67.  
  68.  verbose("sigler entering obey");
  69.  r = bread(fdmaster,c,4);
  70.  verbose("sigler obeyread %d %c %d %d %d",r,c[0],c[1],c[2],c[3]);
  71.  
  72.  if (r <= 0)
  73.    c[0] = 'd'; /* kludge alert! */
  74.  
  75.  switch(c[0])
  76.   {
  77.    case 'z': /* slave stopped, c[1] is stop signal */
  78.      if (sflagjobctrl)
  79.       {
  80.        /* XXX: error checks! */
  81.        if (sflagttymodes)
  82.          tty_setmodes(fdtty,&stmotty);
  83.        sigdfl(c[1]); /* my, we are so trusting... */
  84.        if (sflagreading)
  85.      tty_forcefg(fdtty);
  86.        if (sflagttymodes)
  87.      tty_setmodes(fdtty,&stmottyzero);
  88.        bwrite(fdus2master,"C",1); /* XXX: error checks? */
  89.       }
  90.      break;
  91.    case 'k': /* sesskill */
  92.    case 'd': /* disconnect */
  93.    case 'e': /* slave exited, c[1] is exit status */
  94.    case 's': /* slave terminated by signal, c[1] is signum, c[2] is coredump */
  95.      if (recoext[0])
  96.        doconnect();
  97.      else
  98.       {
  99.        close(fdmaster); fdmaster = -1;
  100.        close(fdus2master); fdus2master = -1;
  101.        ckobey();
  102.        lastmoment(0);
  103.       }
  104.      break;
  105.    case 'r': /* recoext, c[1] and c[2] */
  106.      recoext[0] = c[1];
  107.      recoext[1] = c[2];
  108.      break;
  109.   }
  110. }
  111. static ss_sig *sigobey = 0;
  112. void ckobey()
  113. {
  114.  if (!sigobey && (fdmaster != -1))
  115.   { ss_schedwait(sigobey = ss_sigread(fdmaster),obey,0,1); return; }
  116.  if (sigobey && (fdmaster == -1))
  117.   { ss_unsched(sigobey,obey,0); sigobey = 0; }
  118. }
  119.  
  120. void doconnect()
  121. {
  122.  /* assumptions: */
  123.  /* we are in the foreground if sflagreading */
  124.  /* fd 0 is input, fd 1 is output, fd 2 is error---all open */
  125.  /* tty is in mode smottyzero if sflagttymodes */
  126.  
  127.  int fdcomm;
  128.  int pi[2];
  129.  int sp[2];
  130.  
  131.  if (!firsttime)
  132.   {
  133.    char buf[50]; char *t; t = buf;
  134.    t += fmt_strncpy(t,"reconnecting to ",0);
  135.    *t++ = recoext[0]; *t++ = recoext[1]; *t = 0;
  136.    warn("info",buf);
  137.   }
  138.  verbose("sigler entering doconnect");
  139.  if (fdmaster != -1) { close(fdmaster); fdmaster = -1; }
  140.  if (fdus2master != -1) { close(fdus2master); fdus2master = -1; }
  141.  
  142.  if ((pipe(pi) == -1) || (pipe(sp) == -1))
  143.   {
  144.    lastmoment(0);
  145.    if (firsttime) /* hope not */
  146.      warn("fatal","signaller cannot create internal pipe; master may still be running; use sesslist to check, then try sesskill or reconnect later");
  147.    else
  148.      warn("fatal","signaller cannot create internal pipe");
  149.    die(DIE_IMPOSSIBLE);
  150.   }
  151.  
  152.  fdcomm = comm_write(recoext,suid);
  153.  if (fdcomm == -1) /* hope this isn't the first connect */
  154.   {
  155.    lastmoment(0);
  156.    if (firsttime)
  157.      warn("fatal","signaller cannot connect; master may still be running; use sesslist to check, then try sesskill or reconnect later");
  158.    else
  159.     {
  160.      char buf[100]; char *t; t = buf;
  161.      /* this is a typical case so we print a nice error message */
  162.      t += fmt_strncpy(t,"signaller cannot reconnect to session ",0);
  163.      t += fmt_strncpy(t,recoext,2);
  164.      t += fmt_strncpy(t,"; does it exist?",0);
  165.      *t = 0;
  166.      warn("fatal",buf);
  167.     }
  168.    die(DIE_EXIST);
  169.   }
  170.  verbose("sigler opened connection");
  171.  if (
  172.      (bwrite(fdcomm,"r",1) != 1)
  173.    ||(bread(fdcomm,resp6,6) != 6)
  174.    ||(!respeq(resp6,"shrtng"))
  175.    ||(comm_putfd(fdcomm,sp[1]) == -1)
  176.    ||(comm_putfd(fdcomm,pi[0]) == -1)
  177.    ||(comm_putfd(fdcomm,0) == -1)
  178.    ||(comm_putfd(fdcomm,1) == -1)
  179.    ||(bwrite(fdcomm,(char *) &sflagreading,sizeof(int)) != sizeof(int))
  180.    ||(bwrite(fdcomm,(char *) &sremotelen,sizeof(int)) != sizeof(int))
  181.    ||(bwrite(fdcomm,(char *) sremote,sremotelen) != sremotelen)
  182.    ||(bread(fdcomm,resp6,6) != 6)
  183.    ||(!respeq(resp6,"phew! "))
  184.     )
  185.   {
  186.    lastmoment(0);
  187.    if (firsttime)
  188.      warn("fatal","signaller having trouble; master may still be running; use sesslist to check, then try sesskill or reconnect later");
  189.    else
  190.      if (respeq(resp6,"no-go!")) /* master's already connected */
  191.       {
  192.        warn("fatal","session already connected somewhere else");
  193.        die(DIE_ELSE);
  194.       }
  195.      else
  196.        warn("fatal","signaller having trouble");
  197.    die(DIE_COMM);
  198.   }
  199.  close(sp[1]); fdmaster = sp[0];
  200.  close(pi[0]); fdus2master = pi[1];
  201.  
  202. #ifdef TTY_WINDOWS
  203.  /* Obviously there's a race here between the master reconnecting */
  204.  /* and us telling the pty to change sizes. But will the slave */
  205.  /* ever care? I'm not sure... */
  206.  kill(getpid(),SIGWINCH); /* oh, what a royal kludge */
  207. #endif
  208.  
  209.  close(fdcomm);
  210.  
  211.  verbose("sigler successful doconnect");
  212.  if (!firsttime)
  213.   {
  214.    char buf[50]; char *t; t = buf;
  215.    t += fmt_strncpy(t,"successfully connected to ",0);
  216.    *t++ = recoext[0]; *t++ = recoext[1]; *t = 0;
  217.    warn("info",buf);
  218.   }
  219.  recoext[0] = recoext[1] = 0;
  220.  firsttime = 0;
  221.  
  222.  ckobey();
  223. }
  224.  
  225. static void sigchld(n)
  226. int n;
  227. {
  228.  int w;
  229.  
  230.  while (wait3(&w,WNOHANG | WUNTRACED,(struct rusage *) 0) > 0)
  231.    ; /* [yawn] */
  232. }
  233.  
  234. static void sigwinch(n)
  235. int n;
  236. {
  237. #ifdef TTY_WINDOWS
  238.  struct ttywin twi;
  239.  struct ttymodes tmo;
  240.  
  241.  if (tty_getmodes(fdtty,&tmo) == 0)
  242.   {
  243.    tty_modes2win(&tmo,&twi);
  244.    bwrite(fdus2master,"W",1);
  245.    bwrite(fdus2master,(char *) &twi,sizeof(twi));
  246.    /* XXX: error checks? */
  247.   }
  248. #endif
  249.  ;
  250. }
  251.  
  252. /*
  253. Signal handling:
  254.  
  255. TTIN, TTOU: will never happen, as we don't do I/O; default if they do happen
  256. PIPE: ditto; default if it does happen
  257. HUP, INT, QUIT: default. we'll die, master will see socket close.
  258.   XXX: There's a race here to reconnect to the master initially...
  259. TSTP: default. master won't see it.
  260.  
  261. CHLD: could be master, or a child from before we were execed; ignore both
  262.   XXX: There's a race upon exiting to avoid making zombies...
  263. WINCH, and after every manual continue: tell master to winch
  264.  
  265. when fdmaster != -1 and it's readable: do obey(). This keeps us going.
  266. A side effect of this strategy is that if we ever rest for a moment
  267. without a master to obey, we die. How poetic. Should this be called the
  268. slave process?
  269. */
  270.  
  271. void sigler(ext,uid,pid,flagttymodes,tmotty,tmottyzero,flagreading,flagjobctrl,remote)
  272. char *ext;
  273. int uid;
  274. int pid; /* process id of master---not that we care */
  275. int flagttymodes;
  276. struct ttymodes *tmotty;
  277. struct ttymodes *tmottyzero;
  278. int flagreading;
  279. int flagjobctrl;
  280. char *remote;
  281. {
  282.  /* TTOU, TTIN, PIPE are already SIG_DFL */
  283.  ss_sched(ss_signal(SIGINT),byebye,SIGINT);
  284.  ss_sched(ss_signal(SIGHUP),byebye,SIGHUP);
  285.  ss_sched(ss_signal(SIGTSTP),stop,SIGTSTP);
  286.  ss_sched(ss_signal(SIGQUIT),byebye,SIGQUIT);
  287.  ss_sched(ss_signal(SIGCHLD),sigchld,0);
  288. #ifdef TTY_WINDOWS
  289.  ss_sched(ss_signal(SIGWINCH),sigwinch,0);
  290. #endif
  291.  
  292.  suid = uid;
  293.  
  294.  sremote = remote;
  295.  sremotelen = strlen(remote) + 1;
  296.  if (sremotelen > SESSCONNLOG_REMOTELEN)
  297.    sremotelen = SESSCONNLOG_REMOTELEN;
  298.  sflagttymodes = flagttymodes;
  299.  sflagreading = flagreading;
  300.  sflagjobctrl = flagjobctrl;
  301.  tty_copymodes(&stmotty,tmotty);
  302.  tty_copymodes(&stmottyzero,tmottyzero);
  303.  
  304.  if (flagttymodes)
  305.    fdtty = tty_getctrl();
  306.    /* XXX: what if it's -1? is this even remotely possible? */
  307.  
  308.  firsttime = 1;
  309.  
  310.  recoext[0] = ext[0]; recoext[1] = ext[1];
  311.  doconnect();
  312. }
  313.