home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume14 / jove4.9 / part04 / iproc.c < prev    next >
C/C++ Source or Header  |  1988-04-25  |  9KB  |  424 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. #include "jove.h"
  9. #include "re.h"
  10. #include <varargs.h>
  11.  
  12. #ifdef IPROCS
  13.  
  14. int    proc_child();
  15.  
  16. #ifdef PIPEPROCS
  17. #   include "iproc-pipes.c"
  18. #else
  19. #   include "iproc-ptys.c"
  20. #endif
  21.  
  22. char    proc_prompt[128] = "% ";
  23.  
  24. KillProcs()
  25. {
  26.     register Process    *p;
  27.     register int    killem = -1;        /* -1 means undetermined */
  28.     register char    *yorn;
  29.  
  30.     for (p = procs; p != 0; p = p->p_next)
  31.         if (!isdead(p)) {
  32.             if (killem == -1) {
  33.                 yorn = ask("y", "Should I kill your i-processes? ");
  34.                 killem = (CharUpcase(*yorn) == 'Y');
  35.             }
  36.             if (killem)
  37.                 proc_kill(p, SIGKILL);
  38.         }
  39. }
  40.  
  41. pbuftiedp(b)
  42. register Buffer    *b;
  43. {
  44.     register Process    *p = b->b_process;
  45.  
  46.     if (!isdead(p))
  47.         complain("Process %s, attached to %b, is %s.",
  48.              proc_cmd(p), b, pstate(p));
  49. }
  50.  
  51. /* Process receive: receives the characters in buf, and appends them to
  52.    the buffer associated with p. */
  53.  
  54. private
  55. proc_rec(p, buf)
  56. register Process    *p;
  57. char    *buf;
  58. {
  59.     Buffer    *saveb = curbuf;
  60.     register Window    *w;
  61.     register Mark    *savepoint;
  62.     int    sameplace = NO,
  63.         do_disp = NO;
  64.  
  65.     if (curwind->w_bufp == p->p_buffer)
  66.         w = curwind;
  67.     else
  68.         w = windbp(p->p_buffer);    /* Is this window visible? */
  69.     if (w != 0)
  70.         do_disp = (in_window(w, p->p_mark->m_line) != -1);
  71.     SetBuf(p->p_buffer);
  72.     savepoint = MakeMark(curline, curchar, M_FLOATER);
  73.     ToMark(p->p_mark);        /* where output last stopped */
  74.     if (savepoint->m_line == curline && savepoint->m_char == curchar)
  75.         sameplace = YES;
  76.  
  77.     ins_str(buf, YES);
  78.     MarkSet(p->p_mark, curline, curchar);
  79.     if (!sameplace)
  80.         ToMark(savepoint);    /* back to where we were */
  81.     DelMark(savepoint);
  82.     /* redisplay now, instead of right after the ins_str, so that
  83.        we don't get a bouncing effect if point is not the same as
  84.        the process output position */
  85.     if (do_disp) {
  86.         w->w_line = curline;
  87.         w->w_char = curchar;
  88.         redisplay();
  89.     }
  90.     SetBuf(saveb);
  91. }
  92.  
  93. proc_kill(p, sig)
  94. register Process    *p;
  95. {
  96.     if (isdead(p))
  97.         return;
  98.     if (killpg(p->p_pid, sig) == -1)
  99.         s_mess("Cannot kill %s!", proc_buf(p));
  100. }
  101.  
  102. /* Free process CHILD.  Do all the necessary cleaning up (closing fd's,
  103.    etc.). */
  104.  
  105. free_proc(child)
  106. Process    *child;
  107. {
  108.     register Process    *p,
  109.                 *prev = 0;
  110.  
  111.     if (!isdead(child))
  112.         return;    
  113.     for (p = procs; p != child; prev = p, p = p->p_next)
  114.         ;
  115.     if (prev == 0)
  116.         procs = child->p_next;
  117.     else
  118.         prev->p_next = child->p_next;
  119.     proc_close(child);        /* if not already closed */
  120.     
  121.     /* It's possible that the buffer has been given another process
  122.        between the time CHILD dies and CHILD's death is noticed (via
  123.        list-processes).  So we only set it the buffer's process to
  124.        0 if CHILD is still the controlling process. */
  125.     if (child->p_buffer->b_process == child) {
  126.         child->p_buffer->b_process = 0;
  127.         if (curbuf == child->p_buffer)
  128.             PopPBs();
  129.     }
  130.     {
  131.         Buffer    *old = curbuf;
  132.  
  133.         SetBuf(child->p_buffer);
  134.         DelMark(child->p_mark);
  135.         SetBuf(old);
  136.     }
  137.     free((char *) child->p_name);
  138.     free((char *) child);
  139. }
  140.  
  141. ProcList()
  142. {
  143.     register Process    *p,
  144.                 *next;
  145.     char    *fmt = "%-15s  %-15s  %-8s %s",
  146.         pidstr[16];
  147.  
  148.     if (procs == 0) {
  149.         message("[No subprocesses]");
  150.         return;
  151.     }
  152.     TOstart("Process list", TRUE);
  153.  
  154.     Typeout(fmt, "Buffer", "Status", "Pid ", "Command");
  155.     Typeout(fmt, "------", "------", "--- ", "-------");
  156.     for (p = procs; p != 0; p = next) {
  157.         next = p->p_next;
  158.         sprintf(pidstr, "%d", p->p_pid);
  159.         Typeout(fmt, proc_buf(p), pstate(p), pidstr, p->p_name);
  160.         if (isdead(p)) {
  161.             free_proc(p);
  162.             UpdModLine = YES;
  163.         }
  164.     }
  165.     TOstop();
  166. }
  167.  
  168. ProcNewline()
  169. {
  170. #ifdef ABBREV
  171.     MaybeAbbrevExpand();
  172. #endif
  173.     SendData(YES);
  174. }
  175.  
  176. ProcSendData()
  177. {
  178. #ifdef ABBREV
  179.     MaybeAbbrevExpand();
  180. #endif
  181.     SendData(NO);
  182. }
  183.  
  184. private
  185. SendData(newlinep)
  186. {
  187.     register Process    *p = curbuf->b_process;
  188.     register char    *lp,
  189.             *gp;    /* JF fix for better prompt handling */
  190.  
  191.     if (isdead(p))
  192.         return;
  193.     /* If the process mark was involved in a big deletion, because
  194.        the user hit ^W or something, then let's do some magic with
  195.        the process mark.  Problem is that if the user yanks back the
  196.        text he deleted, the mark stays at the beginning of the region,
  197.        and so the next time SendData() is called the entire region
  198.        will be sent.  That's not good.  So, to deal with that we reset
  199.        the mark to the last line, after skipping over the prompt, etc. */
  200.     if (p->p_mark->m_flags & M_BIG_DELETE) {
  201.         Bufpos    bp;
  202.  
  203.         p->p_mark->m_flags &= ~M_BIG_DELETE;
  204.  
  205.         DOTsave(&bp);
  206.         ToLast();
  207.         Bol();
  208.         /* While we're looking at a prompt, and while we're
  209.            moving forward.  This is for people who accidently
  210.            set their process-prompt to ">*" which will always
  211.            match! */
  212.         while ((LookingAt(proc_prompt, linebuf, curchar)) &&
  213.                 (REeom > curchar))
  214.             curchar = REeom;
  215.         MarkSet(p->p_mark, curline, curchar);
  216.         SetDot(&bp);
  217.     }
  218.  
  219.     if (lastp(curline)) {
  220.         Eol();
  221.         if (newlinep)
  222.             LineInsert(1);
  223.         do_rtp(p->p_mark);
  224.         MarkSet(p->p_mark, curline, curchar);
  225.     } else {
  226.         /* Either we're looking at a prompt, or we're not, in
  227.            which case we want to strip off the beginning of the
  228.            line anything that looks like what the prompt at the
  229.            end of the file is.  In other words, if "(dbx) stop in
  230.            ProcessNewline" is the line we're on, and the last
  231.            line in the buffer is "(dbx) ", then we strip off the
  232.            leading "(dbx) " from this line, because we know it's
  233.            part of the prompt.  But this only happens if "(dbx) "
  234.            isn't one of the process prompts ... follow what I'm
  235.            saying? */
  236.         Bol();
  237.         if (LookingAt(proc_prompt, linebuf, curchar)) {
  238.             do
  239.                 curchar = REeom;
  240.             while ((LookingAt(proc_prompt, linebuf, curchar)) &&
  241.                    (REeom > curchar));
  242.             strcpy(genbuf, linebuf + curchar);
  243.             Eof();
  244.             ins_str(genbuf, NO);
  245.         } else {
  246.             strcpy(genbuf, linebuf + curchar);
  247.             Eof();
  248.             gp = genbuf;
  249.             lp = linebuf;
  250.             while (*lp == *gp && *lp != '\0') {
  251.                 lp += 1;
  252.                 gp += 1;
  253.             }
  254.             ins_str(gp, NO);
  255.         }
  256.     }
  257. }
  258.  
  259. ShellProc()
  260. {
  261.     char    *shbuf = "*shell*";
  262.     register Buffer    *b;
  263.  
  264.     b = buf_exists(shbuf);
  265.     if (b == 0 || isdead(b->b_process))
  266.         proc_strt(shbuf, NO, Shell, "-i", (char *) 0);
  267.     pop_wind(shbuf, NO, -1);
  268. }
  269.  
  270. Iprocess()
  271. {
  272.     extern char    ShcomBuf[100],
  273.             *MakeName();
  274.     register char    *command;
  275.     char    scratch[64],
  276.         *bufname;
  277.     int    cnt = 1;
  278.     Buffer    *bp;
  279.  
  280.     command = ask(ShcomBuf, ProcFmt);
  281.     null_ncpy(ShcomBuf, command, (sizeof ShcomBuf) - 1);
  282.     bufname = MakeName(command);
  283.     strcpy(scratch, bufname);
  284.     while ((bp = buf_exists(scratch)) && !isdead(bp->b_process))
  285.         sprintf(scratch, "%s.%d", bufname, cnt++);
  286.     proc_strt(scratch, YES, Shell, ShFlags, command, (char *) 0);
  287. }
  288.  
  289. proc_child()
  290. {
  291.     union wait    w;
  292.     register int    pid;
  293.  
  294.     for (;;) {
  295. #ifndef BSD4_2
  296.         pid = wait2(&w.w_status, (WNOHANG | WUNTRACED));
  297. #else
  298.         pid = wait3(&w, (WNOHANG | WUNTRACED), (struct rusage *) 0);
  299. #endif
  300.         if (pid <= 0)
  301.             break;
  302.         kill_off(pid, w);
  303.     }
  304. }
  305.  
  306. kill_off(pid, w)
  307. register int    pid;
  308. union wait    w;
  309. {
  310.     register Process    *child;
  311.  
  312.     if ((child = proc_pid(pid)) == 0)
  313.         return;
  314.  
  315.     UpdModLine = YES;        /* we're changing state ... */
  316.     if (WIFSTOPPED(w))
  317.         child->p_state = STOPPED;
  318.     else {
  319.         child->p_state = DEAD;
  320.         if (WIFEXITED(w))
  321.             child->p_howdied = EXITED;
  322.         else if (WIFSIGNALED(w)) {
  323.             child->p_reason = w.w_termsig;
  324.             child->p_howdied = KILLED;
  325.         }
  326.         {
  327.             Buffer    *save = curbuf;
  328.             char    mesg[128];
  329.  
  330.             /* insert status message now */
  331.             sprintf(mesg, "[Process %s: %s]\n",
  332.                 proc_cmd(child),
  333.                 pstate(child));
  334.             SetBuf(child->p_buffer);
  335.             ins_str(mesg, NO);
  336.             SetBuf(save);
  337.             redisplay();
  338.         }
  339.     }
  340. }
  341.  
  342. /* Push/pod process bindings.  I openly acknowledge that this is a
  343.    kludge, but I can't be bothered making it right. */
  344.  
  345. struct proc_bind {
  346.     int        pb_key;
  347.     data_obj    **pb_map;
  348.     data_obj    *pb_push;
  349.     data_obj    *pb_cmd;
  350.     struct proc_bind *pb_next;
  351. };
  352.  
  353. struct proc_bind *PBinds = 0;
  354.  
  355. PopPBs()
  356. {
  357.     register struct proc_bind *p;
  358.  
  359.     for (p = PBinds; p != 0; p = p->pb_next)
  360.         p->pb_map[p->pb_key] = p->pb_push;
  361. }
  362.  
  363. PushPBs()
  364. {
  365.     register struct proc_bind *p;
  366.  
  367.     for (p = PBinds; p != 0; p = p->pb_next) {
  368.         p->pb_push = p->pb_map[p->pb_key];
  369.         p->pb_map[p->pb_key] = p->pb_cmd;
  370.     }
  371. }
  372. /* VARARGS0 */
  373.  
  374. ProcBind()
  375. {
  376.     register data_obj    *d;
  377.  
  378.     if ((d = findcom(ProcFmt)) == 0)
  379.         return;
  380.     s_mess(": %f %s ", d->Name);
  381.     ProcB2(mainmap, EOF, d);
  382. }
  383.  
  384. ProcB2(map, lastkey, cmd)
  385. data_obj    **map,
  386.         *cmd;
  387. {
  388.     register struct proc_bind *p;
  389.     register data_obj    **nextmap;
  390.     int    c;
  391.  
  392.     c = addgetc();
  393.     if (c == EOF) {
  394.         if (lastkey == EOF)
  395.             complain("[Empty key sequence]");
  396.         complain("[Unexpected end-of-line]");
  397.     } else {
  398.         if (nextmap = IsPrefix(map[c]))
  399.             ProcB2(nextmap, c, cmd);
  400.         else {
  401.             if (curbuf->b_process)
  402.                 PopPBs();
  403.  
  404.             for (p = PBinds; p != 0; p = p->pb_next)
  405.                 if (p->pb_key == c && p->pb_map == map)
  406.                     break;
  407.             if (p == 0) {
  408.                 p = (struct proc_bind *) emalloc(sizeof *p);
  409.                 p->pb_next = PBinds;
  410.                 PBinds = p;
  411.             }
  412.             p->pb_map = map;
  413.             p->pb_key = c;
  414.             p->pb_cmd = cmd;
  415.  
  416.             if (curbuf->b_process)
  417.                 PushPBs();
  418.         }
  419.     }
  420. }
  421.  
  422. #endif /* IPROCS */
  423.  
  424.