home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume14 / jove4.9 / part03 / iproc-pipes.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-04-25  |  5.8 KB  |  308 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is    *
  5.  * included in all the files.                                              *
  6.  ***************************************************************************/
  7.  
  8. #ifdef BSD4_2
  9. #   include <sys/wait.h>
  10. #else
  11. #   include <wait.h>
  12. #endif
  13. #include <signal.h>
  14. #include <sgtty.h>
  15.  
  16. #define DEAD    1    /* Dead but haven't informed user yet */
  17. #define STOPPED    2    /* Job stopped */
  18. #define RUNNING    3    /* Just running */
  19. #define NEW    4    /* This process is brand new */
  20.  
  21. /* If process is dead, flags says how. */
  22. #define EXITED    1
  23. #define KILLED    2
  24.  
  25. #define isdead(p)    (p == 0 || proc_state(p) == DEAD || p->p_toproc == -1)
  26. #define makedead(p)    (proc_state(p) = DEAD)
  27.  
  28. #define proc_buf(p)    (p->p_buffer->b_name)
  29. #define proc_cmd(p)    (p->p_name)
  30. #define proc_state(p)    (p->p_state)
  31.  
  32. private Process    *procs = 0;
  33.  
  34. int    ProcInput,
  35.     ProcOutput,
  36.     NumProcs = 0;
  37.  
  38. char *
  39. pstate(p)
  40. Process    *p;
  41. {
  42.     switch (proc_state(p)) {
  43.     case NEW:
  44.         return "Pre-birth";
  45.  
  46.     case STOPPED:
  47.         return "Stopped";
  48.  
  49.     case RUNNING:
  50.         return "Running";
  51.  
  52.     case DEAD:
  53.         if (p->p_howdied == EXITED) {
  54.             if (p->p_reason == 0)
  55.                 return "Done";
  56.             return sprint("Exit %d", p->p_reason);
  57.         }
  58.         return sprint("Killed %d", p->p_reason);
  59.  
  60.     default:
  61.         return "Unknown state";
  62.     }
  63. }
  64.  
  65. static Process *
  66. proc_pid(pid)
  67. {
  68.     register Process    *p;
  69.  
  70.     for (p = procs; p != 0; p = p->p_next)
  71.         if (p->p_portpid == pid)
  72.             break;
  73.  
  74.     return p;
  75. }
  76.  
  77. procs_read()
  78. {
  79.     struct header {
  80.         int    pid;
  81.         int    nbytes;
  82.     } header;
  83.     int    n;
  84.     long    nbytes;
  85.     static int    here = NO;
  86.  
  87.     if (here)    
  88.         return;
  89.     sighold(SIGCHLD);    /* block any other children */
  90.     here = YES;
  91.     for (;;) {
  92.         (void) ioctl(ProcInput, FIONREAD, (struct sgttyb *) &nbytes);
  93.         if (nbytes < sizeof header)
  94.             break;
  95.         n = read(ProcInput, (char *) &header, sizeof header);
  96.         if (n != sizeof header)
  97.             finish(1);
  98.         read_proc(header.pid, header.nbytes);
  99.     }
  100.     here = NO;
  101.     sigrelse(SIGCHLD);
  102. }
  103.  
  104. read_proc(pid, nbytes)
  105. int    pid;
  106. register int    nbytes;
  107. {
  108.     register Process    *p;
  109.     int    n;
  110.     char    ibuf[512];
  111.  
  112.     if ((p = proc_pid(pid)) == 0) {
  113.         printf("\riproc: unknown pid (%d)", pid);
  114.         return;
  115.     }
  116.     if (proc_state(p) == NEW) {
  117.         int    rpid;
  118.         /* pid of real child, not of portsrv */
  119.  
  120.         doread(ProcInput, (char *) &rpid, nbytes);
  121.         nbytes -= sizeof rpid;
  122.         p->p_pid = rpid;
  123.         p->p_state = RUNNING;
  124.     }
  125.  
  126.     if (nbytes == EOF) {        /* okay to clean up this process */
  127.         proc_close(p);
  128.         makedead(p);
  129.         return;
  130.     }
  131.  
  132.     while (nbytes > 0) {
  133.         n = min((sizeof ibuf) - 1, nbytes);
  134.         doread(ProcInput, ibuf, n);
  135.         ibuf[n] = 0;    /* Null terminate for convenience */
  136.         nbytes -= n;
  137.         proc_rec(p, ibuf);
  138.     }
  139. }
  140.  
  141. ProcKill()
  142. {
  143.     proc_kill(curbuf->b_process, SIGKILL);
  144. }
  145.  
  146. ProcInt()
  147. {
  148.     proc_kill(curbuf->b_process, SIGINT);
  149. }
  150.  
  151. ProcQuit()
  152. {
  153.     proc_kill(curbuf->b_process, SIGQUIT);
  154. }
  155.  
  156. private
  157. proc_close(p)
  158. Process    *p;
  159. {
  160.     sighold(SIGCHLD);
  161.  
  162.     if (p->p_toproc >= 0) {
  163.         (void) close(p->p_toproc);
  164.         p->p_toproc = -1;    /* writes will fail */
  165.         NumProcs -= 1;
  166.     }
  167.  
  168.     sigrelse(SIGCHLD);
  169. }
  170.  
  171. do_rtp(mp)
  172. register Mark    *mp;
  173. {
  174.     register Process    *p = curbuf->b_process;
  175.     Line    *line1 = curline,
  176.         *line2 = mp->m_line;
  177.     int    char1 = curchar,
  178.         char2 = mp->m_char;
  179.     char    *gp;
  180.  
  181.     if (isdead(p) || p->p_buffer != curbuf)
  182.         return;
  183.  
  184.     (void) fixorder(&line1, &char1, &line2, &char2);
  185.     while (line1 != line2->l_next) {
  186.         gp = ltobuf(line1, genbuf) + char1;
  187.         if (line1 == line2)
  188.             gp[char2] = '\0';
  189.         else
  190.             strcat(gp, "\n");
  191.         (void) write(p->p_toproc, gp, strlen(gp));
  192.         line1 = line1->l_next;
  193.         char1 = 0;
  194.     }
  195. }
  196.  
  197. /* VARARGS3 */
  198.  
  199. private
  200. proc_strt(bufname, clobber, va_alist)
  201. char    *bufname;
  202. va_dcl
  203. {
  204.     Window    *owind = curwind;
  205.     int    toproc[2],
  206.         pid;
  207.     Process    *newp;
  208.     Buffer    *newbuf;
  209.         char    *argv[32],
  210.             *cp,
  211.             foo[10],
  212.         cmdbuf[128];
  213.         int    i;
  214.     va_list    ap;
  215.  
  216.     isprocbuf(bufname);    /* make sure BUFNAME is either nonexistant
  217.                    or is of type B_PROCESS */
  218.     dopipe(toproc);
  219.  
  220.     sighold(SIGCHLD);
  221. #ifdef SIGWINCH
  222.     sighold(SIGWINCH);
  223. #endif
  224.     switch (pid = fork()) {
  225.     case -1:
  226.         pclose(toproc);
  227.         complain("[Fork failed.]");
  228.  
  229.     case 0:
  230.         sigrelse(SIGCHLD);
  231. #ifdef SIGWINCH
  232.         sigrelse(SIGWINCH);
  233. #endif
  234.             argv[0] = "portsrv";
  235.             argv[1] = foo;
  236.         sprintf(foo, "%d", ProcInput);
  237.         va_start(ap);
  238.         make_argv(&argv[2], ap);
  239.         va_end(ap);
  240.         (void) dup2(toproc[0], 0);
  241.         (void) dup2(ProcOutput, 1);
  242.         (void) dup2(ProcOutput, 2);
  243.         pclose(toproc);
  244.         execv(Portsrv, argv);
  245.         printf("execl failed\n");
  246.         _exit(1);
  247.     }
  248.  
  249.     newp = (Process *) malloc(sizeof *newp);
  250.     newp->p_next = procs;
  251.     newp->p_state = NEW;
  252.     newp->p_cmd = 0;
  253.  
  254.     cmdbuf[0] = '\0';
  255.     va_start(ap);
  256.     while (cp = va_arg(ap, char *))
  257.         sprintf(&cmdbuf[strlen(cmdbuf)], "%s ", cp);
  258.     va_end(ap);
  259.     newp->p_name = copystr(cmdbuf);
  260.     procs = newp;
  261.     newp->p_portpid = pid;
  262.     newp->p_pid = -1;
  263.  
  264.     newbuf = do_select((Window *) 0, bufname);
  265.     newbuf->b_type = B_PROCESS;
  266.     newp->p_buffer = newbuf;
  267.     newbuf->b_process = newp;    /* sorta circular, eh? */
  268.     pop_wind(bufname, clobber, B_PROCESS);
  269.     ToLast();
  270.     if (!bolp())
  271.         LineInsert(1);
  272.     /* Pop_wind() after everything is set up; important!
  273.        Bindings won't work right unless newbuf->b_process is already
  274.        set up BEFORE NEWBUF is first SetBuf()'d. */
  275.     newp->p_mark = MakeMark(curline, curchar, M_FLOATER);
  276.  
  277.     newp->p_toproc = toproc[1];
  278.     newp->p_reason = 0;
  279.     NumProcs += 1;
  280.     (void) close(toproc[0]);
  281.     SetWind(owind);
  282.     sigrelse(SIGCHLD);
  283. #ifdef SIGWINCH
  284.     sigrelse(SIGWINCH);
  285. #endif
  286. }
  287.  
  288. pinit()
  289. {
  290.     int    p[2];
  291.  
  292.     (void) signal(SIGCHLD, proc_child);
  293.     (void) pipe(p);
  294.     ProcInput = p[0];
  295.     ProcOutput = p[1];
  296.     (void) signal(INPUT_SIG, procs_read);
  297.     sighold(INPUT_SIG);    /* Released during terminal read */
  298. }
  299.  
  300. doread(fd, buf, n)
  301. char    *buf;
  302. {
  303.     int    nread;
  304.  
  305.     if ((nread = read(fd, buf, n)) != n)
  306.         complain("Cannot read %d (got %d) bytes.", n, nread);
  307. }
  308.