home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / gnu / src / baseline / jove-4.14.6.lha / jove-4.14.6 / iproc.c < prev    next >
C/C++ Source or Header  |  1992-01-10  |  10KB  |  468 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 "ctype.h"
  11. #include "disp.h"
  12. #ifdef    IPROCS
  13. # include "fp.h"
  14. # include "iproc.h"
  15. #endif
  16.  
  17. #ifdef    STDARGS
  18. # include <stdarg.h>
  19. #else
  20. # include <varargs.h>
  21. #endif
  22.  
  23. #ifdef    IPROCS
  24.  
  25. #include <errno.h>
  26.  
  27. private void
  28.     proc_rec proto ((Process *, char *)),
  29.     proc_close proto ((Process *)),
  30.     proc_kill proto((Process *, int)),
  31.     SendData proto ((int));
  32.  
  33. private SIGRESULT
  34.     proc_child proto((int));
  35.  
  36. #ifdef    PIPEPROCS
  37. #   include "iproc-pipes.c"
  38. #else
  39. #   include "iproc-ptys.c"
  40. #endif
  41.  
  42. char    proc_prompt[128] = "% ";
  43.  
  44. char *
  45. pstate(p)
  46. Process    *p;
  47. {
  48.     switch (proc_state(p)) {
  49.     case NEW:
  50.         return "New";
  51.  
  52.     case STOPPED:
  53.         return "Stopped";
  54.  
  55.     case RUNNING:
  56.         return "Running";
  57.  
  58.     case DEAD:
  59.         if (p->p_howdied == EXITED) {
  60.             if (p->p_reason == 0)
  61.                 return "Done";
  62.             return sprint("Exit %d", p->p_reason);
  63.         }
  64.         return sprint("Killed %d", p->p_reason);
  65.  
  66.     default:
  67.         return "Unknown state";
  68.     }
  69. }
  70.  
  71. void
  72. KillProcs()
  73. {
  74.     register Process    *p;
  75.     register int    killem = -1;        /* -1 means undetermined */
  76.     register char    *yorn;
  77.  
  78.     for (p = procs; p != NULL; p = p->p_next)
  79.         if (!isdead(p)) {
  80.             if (killem == -1) {
  81.                 yorn = ask("y", "Should I kill your i-processes? ");
  82.                 killem = (CharUpcase(*yorn) == 'Y');
  83.             }
  84.             if (killem)
  85.                 proc_kill(p, SIGKILL);
  86.         }
  87. }
  88.  
  89. void
  90. pbuftiedp(b)
  91. register Buffer    *b;
  92. {
  93.     register Process    *p = b->b_process;
  94.  
  95.     if (!isdead(p))
  96.         complain("Process %s, attached to %b, is %s.",
  97.              proc_cmd(p), b, pstate(p));
  98. }
  99.  
  100. char    dbx_parse_fmt[128] = "line \\([0-9]*\\) in \\{file,\\} *\"\\([^\"]*\\)\"";
  101.  
  102. void
  103. DBXpoutput()
  104. {
  105.     if (curbuf->b_process == NULL)
  106.         complain("[Must be in a process buffer to enable dbx mode]");
  107.     curbuf->b_process->p_dbx_mode = !curbuf->b_process->p_dbx_mode;
  108.     UpdModLine = YES;
  109. }
  110.  
  111. private void
  112. watch_input(m)
  113. Mark    *m;
  114. {
  115.     Bufpos    save;
  116.     char    fname[FILESIZE],
  117.         lineno[FILESIZE];
  118.     int    lnum;
  119.     Window    *savew = curwind;
  120.     Buffer    *buf;
  121.  
  122.     DOTsave(&save);
  123.     ToMark(m);
  124.     if (dosearch(dbx_parse_fmt, FORWARD, YES) != NULL) {
  125.         get_FL_info(fname, lineno);
  126.         buf = do_find((Window *)NULL, fname, YES);
  127.         pop_wind(buf->b_name, NO, -1);
  128.         lnum = atoi(lineno);
  129.         SetLine(next_line(buf->b_first, lnum - 1));
  130.         SetWind(savew);
  131.     }
  132.     SetDot(&save);
  133. }
  134.  
  135. /* Process receive: receives the characters in buf, and appends them to
  136.    the buffer associated with p. */
  137.  
  138. private void
  139. proc_rec(p, buf)
  140. register Process    *p;
  141. char    *buf;
  142. {
  143.     Buffer    *saveb = curbuf;
  144.     register Window    *w;
  145.     register Mark    *savepoint;
  146.     int    sameplace = NO,
  147.         do_disp = NO;
  148.  
  149.     if (curwind->w_bufp == p->p_buffer)
  150.         w = curwind;
  151.     else
  152.         w = windbp(p->p_buffer);    /* Is this window visible? */
  153.     if (w != NULL)
  154.         do_disp = (in_window(w, p->p_mark->m_line) != -1);
  155.     SetBuf(p->p_buffer);
  156.     savepoint = MakeMark(curline, curchar, M_FLOATER);
  157.     ToMark(p->p_mark);        /* where output last stopped */
  158.     if (savepoint->m_line == curline && savepoint->m_char == curchar)
  159.         sameplace = YES;
  160.     ins_str(buf, YES);
  161.     if (do_disp == YES && p->p_dbx_mode == YES)
  162.         watch_input(p->p_mark);
  163.     MarkSet(p->p_mark, curline, curchar);
  164.     if (!sameplace)
  165.         ToMark(savepoint);    /* back to where we were */
  166.     DelMark(savepoint);
  167.     /* redisplay now, instead of right after the ins_str, so that
  168.        we don't get a bouncing effect if point is not the same as
  169.        the process output position */
  170.     if (do_disp) {
  171.         w->w_line = curline;
  172.         w->w_char = curchar;
  173.         redisplay();
  174.     }
  175.     SetBuf(saveb);
  176. }
  177.  
  178. private void
  179. proc_kill(p, sig)
  180. register Process    *p;
  181. int    sig;
  182. {
  183.     if (isdead(p))
  184.         return;
  185.     if (killpg(p->p_pid, sig) == -1)
  186.         s_mess("Cannot kill %s!", proc_buf(p));
  187. }
  188.  
  189. /* Free process CHILD.  Do all the necessary cleaning up (closing fd's,
  190.    etc.). */
  191.  
  192. private void
  193. free_proc(child)
  194. Process    *child;
  195. {
  196.     register Process    *p,
  197.                 *prev = NULL;
  198.  
  199.     if (!isdead(child))
  200.         return;
  201.     for (p = procs; p != child; prev = p, p = p->p_next)
  202.         ;
  203.     if (prev == NULL)
  204.         procs = child->p_next;
  205.     else
  206.         prev->p_next = child->p_next;
  207.     proc_close(child);        /* if not already closed */
  208.  
  209.     /* It's possible that the buffer has been given another process
  210.        between the time CHILD dies and CHILD's death is noticed (via
  211.        list-processes).  So we only set it the buffer's process to
  212.        NULL if CHILD is still the controlling process. */
  213.     if (child->p_buffer->b_process == child) {
  214.         child->p_buffer->b_process = NULL;
  215.     }
  216.     {
  217.         Buffer    *old = curbuf;
  218.  
  219.         SetBuf(child->p_buffer);
  220.         DelMark(child->p_mark);
  221.         SetBuf(old);
  222.     }
  223.     free((UnivPtr) child->p_name);
  224.     free((UnivPtr) child);
  225. }
  226.  
  227. void
  228. ProcList()
  229. {
  230.     register Process    *p,
  231.                 *next;
  232.     char    *fmt = "%-15s  %-15s  %-8s %s",
  233.         pidstr[16];
  234.  
  235.     if (procs == NULL) {
  236.         message("[No subprocesses]");
  237.         return;
  238.     }
  239.     TOstart("Process list", TRUE);
  240.  
  241.     Typeout(fmt, "Buffer", "Status", "Pid ", "Command");
  242.     Typeout(fmt, "------", "------", "--- ", "-------");
  243.     for (p = procs; p != NULL; p = next) {
  244.         next = p->p_next;
  245.         swritef(pidstr, sizeof(pidstr), "%d", p->p_pid);
  246.         Typeout(fmt, proc_buf(p), pstate(p), pidstr, p->p_name);
  247.         if (isdead(p)) {
  248.             free_proc(p);
  249.             UpdModLine = YES;
  250.         }
  251.     }
  252.     TOstop();
  253. }
  254.  
  255. private void
  256. do_rtp(mp)
  257. register Mark    *mp;
  258. {
  259.     register Process    *p = curbuf->b_process;
  260.     Line    *line1 = curline,
  261.         *line2 = mp->m_line;
  262.     int    char1 = curchar,
  263.         char2 = mp->m_char;
  264.     char    *gp;
  265.     size_t    nbytes;
  266.  
  267.     if (isdead(p) || p->p_buffer != curbuf)
  268.         return;
  269.  
  270.     (void) fixorder(&line1, &char1, &line2, &char2);
  271.     while (line1 != line2->l_next) {
  272.         gp = ltobuf(line1, genbuf) + char1;
  273.         if (line1 == line2)
  274.             gp[char2] = '\0';
  275.         else
  276.             strcat(gp, "\n");
  277.         if ((nbytes = strlen(gp)) != 0)
  278.             proc_write(p, gp, nbytes);
  279.         line1 = line1->l_next;
  280.         char1 = 0;
  281.     }
  282. }
  283.  
  284. void
  285. ProcNewline()
  286. {
  287. #ifdef    ABBREV
  288.     MaybeAbbrevExpand();
  289. #endif
  290.     SendData(YES);
  291. }
  292.  
  293. void
  294. ProcSendData()
  295. {
  296. #ifdef    ABBREV
  297.     MaybeAbbrevExpand();
  298. #endif
  299.     SendData(NO);
  300. }
  301.  
  302. private void
  303. SendData(newlinep)
  304. int    newlinep;
  305. {
  306.     register Process    *p = curbuf->b_process;
  307.     register char    *lp,
  308.             *gp;    /* JF fix for better prompt handling */
  309.  
  310.     if (isdead(p))
  311.         return;
  312.     /* If the process mark was involved in a big deletion, because
  313.        the user hit ^W or something, then let's do some magic with
  314.        the process mark.  Problem is that if the user yanks back the
  315.        text he deleted, the mark stays at the beginning of the region,
  316.        and so the next time SendData() is called the entire region
  317.        will be sent.  That's not good.  So, to deal with that we reset
  318.        the mark to the last line, after skipping over the prompt, etc. */
  319.     if (p->p_mark->m_flags & M_BIG_DELETE) {
  320.         Bufpos    bp;
  321.  
  322.         p->p_mark->m_flags &= ~M_BIG_DELETE;
  323.  
  324.         DOTsave(&bp);
  325.         ToLast();
  326.         Bol();
  327.         /* While we're looking at a prompt, and while we're
  328.            moving forward.  This is for people who accidently
  329.            set their process-prompt to ">*" which will always
  330.            match! */
  331.         while (LookingAt(proc_prompt, linebuf, curchar)
  332.         && (REeom > curchar))
  333.             curchar = REeom;
  334.         MarkSet(p->p_mark, curline, curchar);
  335.         SetDot(&bp);
  336.     }
  337.  
  338.     if (lastp(curline)) {
  339.         Eol();
  340.         if (newlinep)
  341.             LineInsert(1);
  342.         do_rtp(p->p_mark);
  343.         MarkSet(p->p_mark, curline, curchar);
  344.     } else {
  345.         /* Either we're looking at a prompt, or we're not, in
  346.            which case we want to strip off the beginning of the
  347.            line anything that looks like what the prompt at the
  348.            end of the file is.  In other words, if "(dbx) stop in
  349.            ProcessNewline" is the line we're on, and the last
  350.            line in the buffer is "(dbx) ", then we strip off the
  351.            leading "(dbx) " from this line, because we know it's
  352.            part of the prompt.  But this only happens if "(dbx) "
  353.            isn't one of the process prompts ... follow what I'm
  354.            saying? */
  355.         Bol();
  356.         if (LookingAt(proc_prompt, linebuf, curchar)) {
  357.             do {
  358.                 curchar = REeom;
  359.             } while (LookingAt(proc_prompt, linebuf, curchar)
  360.             && (REeom > curchar));
  361.             strcpy(genbuf, linebuf + curchar);
  362.             Eof();
  363.             ins_str(genbuf, NO);
  364.         }