home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / jove414s.zip / os2iproc.c < prev    next >
C/C++ Source or Header  |  1991-07-07  |  23KB  |  924 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. #ifdef OS2
  10. # define INCL_DOS
  11. # include <os2.h>
  12. # include <process.h>
  13. # include <d:\c600\include\io.h>
  14. # include <fcntl.h>
  15. # include <string.h>
  16. // prevent inheritance of files
  17. #  define no_inherit(fd) DosSetFHandState (fd, OPEN_FLAGS_NOINHERIT);
  18. struct _iobuf {
  19.     char _FAR_ *_ptr;
  20.     int   _cnt;
  21.     char _FAR_ *_base;
  22.     char  _flag;
  23.     char  _file;
  24.     };
  25. typedef struct _iobuf FILE;
  26. int fputs( char *string, FILE *stream );
  27. /* declare _iob[] array */
  28.  
  29. # ifndef _STDIO_DEFINED
  30. # ifdef _DLL
  31. extern FILE _FAR_ _cdecl _iob[];
  32. #else
  33. extern FILE _near _cdecl _iob[];
  34. #endif
  35. #endif
  36.  
  37.  
  38. /* define file position type */
  39.  
  40. #ifndef _FPOS_T_DEFINED
  41. typedef long fpos_t;
  42. #define _FPOS_T_DEFINED
  43. #endif
  44.  
  45.  
  46. /* standard file pointers */
  47.  
  48. #define stdin  (&_iob[0])
  49. #define stderr (&_iob[2])
  50. #define stdaux (&_iob[3])
  51. #define stdprn (&_iob[4])
  52.  
  53. #endif
  54.  
  55. #include "re.h"
  56. #include "ctype.h"
  57. #include "disp.h"
  58. #if ( defined( IPROCS ) || defined( OS2IPROCS ) )
  59. # include "fp.h"
  60. # include "iproc.h"
  61. #endif
  62.  
  63. #ifdef    STDARGS
  64. # include <stdarg.h>
  65. #else
  66. # include <varargs.h>
  67. #endif
  68.  
  69. #if ( defined( IPROCS ) || defined( OS2IPROCS ) )
  70.  
  71. private void
  72.     _fastcall proc_rec( register Process *p, char *buf ),
  73.     proc_close( Process *p ),
  74.     proc_kill( Process *p, int sig ),
  75.     _fastcall SendData( int newlinep );
  76. static int kill( int pid, int sig );
  77.  
  78. private SIGRESULT
  79.     proc_child proto((int));
  80.  
  81. /***************************************************************************
  82.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  83.  * is provided to you without charge, and with no warranty.  You may give  *
  84.  * away copies of JOVE, including sources, provided that this notice is    *
  85.  * included in all the files.                                              *
  86.  ***************************************************************************/
  87.  
  88. /* NOTE WELL:
  89.  * This file is "included" into iproc.c -- it is not compiled separately!
  90.  */
  91.  
  92. #include <signal.h>
  93. //#include <stdlib.h>
  94. #include "wait.h"
  95.  
  96. #define DEAD    1    /* Dead but haven't informed user yet */
  97. #define STOPPED    2    /* Job stopped */
  98. #define RUNNING    3    /* Just running */
  99. #define NEW    4    /* This process is brand new */
  100.  
  101. /* If process is dead, flags says how. */
  102. #define EXITED    1
  103. #define KILLED    2
  104.  
  105. #define isdead(p)    ((p) == NULL || proc_state((p)) == DEAD || (p)->p_toproc == -1)
  106. #define makedead(p)    { proc_state((p)) = DEAD; }
  107.  
  108. #define proc_buf(p)    ((p)->p_buffer->b_name)
  109. #define proc_cmd(p)    ((p)->p_name)
  110. #define proc_state(p)    ((p)->p_state)
  111.  
  112. static Process    *procs = (Process *)0;
  113.  
  114. File    *ProcInput ;
  115. int    ProcOutput,
  116.     kbd_pid = 0,
  117.     NumProcs = 0;
  118. /************************************/
  119. static Process *proc_pid( int pid)
  120. /************************************/
  121. {
  122.     register Process    *p;
  123.  
  124.     for (p = procs; p != (Process *)0; p = p->p_next)
  125.         if (p->p_portpid == pid)
  126.             break;
  127.  
  128.     return (p);
  129. }
  130.  
  131. /******************************************************/
  132. void _fastcall read_proc (int pid, register int nbytes)
  133. /******************************************************/
  134. {
  135.     int _fastcall f_readn( File *fp, char *addr, int n );
  136.     register Process    *p;
  137.     int    n;
  138.     char    ibuf[512];
  139.  
  140.     p = proc_pid ( pid );
  141.     if (p == (Process *)0) {
  142.         writef( "\riproc: unknown pid (%d)", pid );
  143.         return;
  144.     }
  145.  
  146.     if (proc_state( p ) == NEW) {
  147.         int    rpid;
  148.         /* pid of real child, not of portsrv */
  149.  
  150.         f_readn (ProcInput, (char *) &rpid, sizeof (int));
  151.         p->p_pid = rpid;
  152.         p->p_state = RUNNING;
  153.         return;
  154.     }
  155.  
  156.     if (nbytes == EOF) {        /* okay to clean up this process */
  157.         int     pid;
  158.         union wait  status;
  159.  
  160.         f_readn( ProcInput, (int *)& status, sizeof ( int ) );
  161.         do {
  162.             pid = wait((int *) 0);
  163.             if (pid < 0)
  164.                 break;
  165.             kill_off( pid, status.w_status );
  166.         } while( pid != p->p_portpid );
  167.         proc_close( p );
  168.         makedead( p );
  169.         return;
  170.     }
  171.  
  172.     while (nbytes > 0) {
  173.         n = min( (sizeof ibuf) - 1, nbytes );
  174.         f_readn( ProcInput, ibuf, n );
  175.         ibuf[n] = 0;    /* Null terminate for convenience */
  176.         nbytes -= n;
  177.         proc_rec( p, ibuf );
  178.     }
  179. }
  180.  
  181. /********************/
  182. void ProcKill (void)
  183. /********************/
  184. {
  185.     proc_kill (curbuf->b_process, SIGKILL);
  186. }
  187.  
  188. /******************/
  189. void ProcInt(void)
  190. /******************/
  191. {
  192.     proc_kill(curbuf->b_process, SIGINT);
  193. }
  194.  
  195. /********************/
  196. void ProcQuit (void)
  197. /********************/
  198. {
  199.     proc_kill(curbuf->b_process, SIGQUIT);
  200. }
  201. /***********************************/
  202. static void proc_close( Process *p )
  203. /***********************************/
  204. {
  205.     if ( p->p_toproc >= 0 ) {
  206.         DosClose( p->p_toproc );
  207.         p->p_toproc = -1;    /* writes will fail */
  208.         NumProcs -= 1;
  209.     }
  210. }
  211. /********************************************************/
  212. size_t _fastcall fix_new_line (char *buf, size_t nbytes)
  213. /********************************************************/
  214. /* replace LF with CR-LF at the end of line. Return the new */
  215. /* number of bytes */
  216. #define CR 0x0D
  217. #define LF 0x0A
  218. {
  219.     if (buf[nbytes - 1] == LF && buf[nbytes - 2] != CR) {
  220.         buf[nbytes - 1] = CR;
  221.         buf[nbytes] = LF;
  222.     }
  223.     return (nbytes+1);
  224. }
  225.  
  226. /********************************************************/
  227. void proc_write ( Process *p, char *buf, size_t nbytes )
  228. /********************************************************/
  229. {
  230.     size_t    _fastcall fix_new_line (char *buf, size_t nbytes);
  231.     int    n_written;
  232.     size_t  fixed_nbytes;
  233.  
  234.     fixed_nbytes = fix_new_line (buf, nbytes);
  235.     n_written = write (p->p_toproc, buf, fixed_nbytes);
  236.     // n_written = write( p->p_toproc, buf, nbytes );
  237. }
  238.  
  239. /*****************************************************************/
  240. void make_cmd (char *argv[], char cmd[])
  241. /*****************************************************************/
  242. /* prepare command line from ARGV. stop in a NULL element */
  243. {
  244.     int arg = 0;
  245.     char *ptcom;
  246.  
  247.  
  248.     ptcom = cmd;
  249.     while ( argv[arg] != NULL )  {
  250.         strcpy ( ptcom, argv[arg] );
  251.         ptcom += strlen ( argv[arg] );
  252.         if ( arg == 0 )
  253.         ptcom ++;    // leave a null byte before arguments
  254.          else {
  255.         *ptcom = ' ';    // leave a space between arguments
  256.         ptcom++;
  257.         };
  258.         arg++;
  259.     }
  260.     *ptcom = *(ptcom+1) = '\0';   // two null bytes at the end of arguments
  261. }
  262.  
  263. #ifdef    STDARGS
  264.     static void
  265. proc_strt(char *bufname, int clobber, ...)
  266. #else
  267.     static /*VARARGS3*/ void
  268. proc_strt(bufname, clobber, va_alist)
  269. /*************************************/
  270.     char    *bufname;
  271.     int    clobber;
  272.     va_dcl
  273. #endif
  274. {
  275.     Window    *owind = curwind;
  276.     int    toproc[2],
  277.         pid,
  278.               spawn_code;
  279.     HFILE          hRead, hWrite;             // pipe handles
  280.     char          portsrv_cmd[80], objbuf[80], cmd_name[80];
  281.     RESULTCODES   result_codes;
  282.  
  283.     Process    *newp;
  284.     Buffer    *newbuf;
  285.     char    *argv[32],
  286.         *cp,
  287.         foo[10],
  288.         cmdbuf[128];
  289.     int    i, fd;
  290.     va_list    ap;
  291.     FILE    *toproc_fp;
  292.  
  293.     isprocbuf (bufname);    /* make sure BUFNAME is either nonexistant
  294.                    or is of type B_PROCESS */
  295.     _pipe (toproc, 512, O_BINARY);
  296.     no_inherit (toproc[1]);
  297. /* launching child process */
  298. launch:
  299.   {
  300.     int fd_stdin, fd_stdout, fd_stderr, fd_std;
  301.     int err_code;
  302.  
  303.     fd_stdin  = dup (fileno (stdin));
  304.     fd_stdout = dup (fileno (stdout));
  305.     fd_stderr = dup (fileno (stderr));
  306.  
  307.     argv[0] = "portsrv.exe";
  308.     va_init(ap, clobber);
  309.     make_argv (&argv[1], ap);
  310.     va_end(ap);
  311.  
  312.     err_code = dup2 (toproc[0],  0);
  313.     err_code = dup2 (ProcOutput, 1);
  314.     err_code = dup2 (ProcOutput, 2);
  315.  
  316.     make_cmd (argv, portsrv_cmd);    // make command line
  317.     for (fd = 3; fd <= 20; fd++) no_inherit (fd);
  318.     err_code = DosExecPgm (objbuf, 80, 2, portsrv_cmd,
  319.                   NULL, &result_codes, portsrv_cmd);
  320.     //spawn_code = spawnv (P_NOWAIT, "portsrv.exe", argv);
  321.     spawn_code = (err_code == 0) ? result_codes.codeTerminate : -1;
  322.     switch (spawn_code) {
  323.     case (-1):
  324.         writef ("spawn failed\n");
  325.         _exit (1);
  326.         break;
  327.     default:
  328.         pid = spawn_code;
  329.         break;
  330.     }
  331. /* return standard fd to their original state */
  332.     err_code = dup2 (fd_stdin,  fileno (stdin));
  333.     err_code = dup2 (fd_stdout, fileno (stdout));
  334.     err_code = dup2 (fd_stderr, fileno (stderr));
  335.  
  336.     DosClose (fd_stdin);
  337.     DosClose (fd_stdout);
  338.     DosClose (fd_stderr);
  339.   }
  340.     newp = (Process *) malloc (sizeof *newp);
  341.     newp->p_next = procs;
  342.     newp->p_state = NEW;
  343.  
  344.     cmdbuf[0] = '\0';
  345.     va_init (ap, clobber);
  346.     while (cp = va_arg (ap, char *))
  347.         swritef (&cmdbuf[strlen( cmdbuf )], "%s ", cp);
  348.     va_end (ap);
  349.     va_init (ap, clobber);
  350.     newp->p_name = copystr (cmdbuf);
  351.     procs = newp;
  352.     newp->p_portpid = pid;
  353.     newp->p_pid = -1;
  354.  
  355.     newbuf = do_select ((Window *) 0, bufname);
  356.     newbuf->b_type = B_PROCESS;
  357.     newp->p_buffer = newbuf;
  358.     newbuf->b_process = newp;    /* sorta circular, eh? */
  359.     pop_wind (bufname, clobber, B_PROCESS);
  360.     ToLast();
  361.     if (!bolp())
  362.         LineInsert(1);
  363.     /* Pop_wind() after everything is set up; important!
  364.        Bindings won't work right unless newbuf->b_process is already
  365.        set up BEFORE NEWBUF is first SetBuf()'d. */
  366.     newp->p_mark = MakeMark( curline, curchar, M_FLOATER );
  367.     newp->p_dbx_mode = NO;
  368.  
  369.     newp->p_toproc = toproc[1];
  370.     newp->p_reason = 0;
  371.     NumProcs += 1;
  372.     if (NumProcs == 1)
  373.           kbd_strt();
  374.     DosClose(toproc[0]);
  375.     SetWind(owind );
  376. }
  377.  
  378. /****************/
  379. void pinit(void)
  380. /****************/
  381. {
  382.     int        p[2];
  383.     int        fd;
  384.     HFILE        new_handle;
  385.     HFILE        hRead, hWrite;         // pipe handles
  386.     int        err_code;
  387.     RESULTCODES    result_codes;
  388.     char        kbd_cmd[80], objbuf[80];
  389.  
  390.     _pipe( p, 512, O_BINARY );
  391.     ProcInput = fd_open( "process-input", F_READ | F_LOCKED, p[0],
  392.                 (char *) 0, 512 );
  393.  
  394.     ProcOutput = p[1];
  395.  
  396. /* launching the kbd process */
  397. launch:
  398.   {
  399.     int spawn_code;
  400.     int fd_stdin, fd_stdout, fd_stderr, fd_std;
  401. /* store original handles of stdin,out,err */
  402.  
  403.     fd_stdin  = dup ( fileno (stdin)  );
  404.     fd_stdout = dup ( fileno (stdout) );
  405.     fd_stderr = dup ( fileno (stderr) );
  406.  
  407.     signal(SIGINT, SIG_IGN);
  408.  
  409.     err_code = dup2( ProcOutput, 1 );
  410.     err_code = dup2( ProcOutput, 2 );
  411. /* no iheritance */
  412.  
  413.     for (fd = 3; fd <=20; fd++) no_inherit( fd );
  414.     strcpy ( kbd_cmd,"d:\\tmp\\jove\\kbd.exe" );
  415.     err_code = DosExecPgm ( objbuf, 80, 2, kbd_cmd, NULL,
  416.                    &result_codes, kbd_cmd );
  417.     spawn_code = ( err_code == 0 ) ? result_codes.codeTerminate : -1;
  418.     //spawn_code = spawnl ( P_NOWAIT, "kbd.exe", "kbd", NULL );
  419.     switch ( spawn_code ) {
  420.     case (-1):
  421.         write( 2, "kdb spawn failed\n", 16 );
  422.         exit(-1);
  423.         break;
  424.     default:
  425.         kbd_pid = spawn_code;
  426.         break;
  427.     }
  428. /* restore original handles of std/in/out/err */
  429.     dup2 ( fd_stdin,  fileno ( stdin) );
  430.     dup2 ( fd_stdout, fileno ( stdout) );
  431.     dup2 ( fd_stderr, fileno ( stderr) );
  432.  
  433.     DosClose ( fd_stdin );
  434.     DosClose ( fd_stdout );
  435.     DosClose ( fd_stderr );
  436.   }
  437. }
  438.  
  439. static int    kbd_state = OFF;
  440.  
  441. /* kbd_strt() and kbd_stop() return true if they changed the state
  442.    of the keyboard process.  E.g., kbd_strt() returns TRUE if the
  443.    kbd process was previously stopped.  This is so kbd starting and
  444.    stopping in pairs works - see finish() in jove.c. */
  445. /*****************/
  446. int kbd_strt(void)
  447. /*****************/
  448. {
  449.     if ( kbd_state == OFF ) {
  450.         kbd_state = ON;
  451.         kill( kbd_pid, SIGQUIT );
  452.         return TRUE;
  453.     }
  454.     return FALSE;
  455. }
  456. /********************/
  457. int kbd_stop(void)
  458. /********************/
  459. {
  460.     if (kbd_state == ON) {
  461.         kbd_state = OFF;
  462.         kill( kbd_pid, SIGQUIT );
  463.         return TRUE;
  464.     }
  465.     return FALSE;
  466. }
  467. /********************/
  468. int kbd_kill( void )
  469. /********************/
  470. {
  471.     if (kbd_pid != 0) {
  472.         kill( kbd_pid, SIGKILL );
  473.         kbd_pid = 0;
  474.     }
  475. }
  476.  
  477. char    proc_prompt[128] = "]";
  478.  
  479. /************************/
  480. char *pstate(Process *p)
  481. /************************/
  482. {
  483.     switch (proc_state(p)) {
  484.     case NEW:
  485.         return "New";
  486.  
  487.     case STOPPED:
  488.         return "Stopped";
  489.  
  490.     case RUNNING:
  491.         return "Running";
  492.  
  493.     case DEAD:
  494.         if (p->p_howdied == EXITED) {
  495.             if (p->p_reason == 0)
  496.                 return "Done";
  497.             return sprint("Exit %d", p->p_reason);
  498.         }
  499.         return sprint( "Killed %d", p->p_reason );
  500.  
  501.     default:
  502.         return "Unknown state";
  503.     }
  504. }
  505.  
  506. /**********************/
  507. void KillProcs( void )
  508. /**********************/
  509. {
  510.     register  Process    *p;
  511.     register  int    killem = -1;        /* -1 means undetermined */
  512.     register  char    *yorn;
  513.  
  514.     for (p = procs; p != 0; p = p->p_next)
  515.         if (!isdead(p)) {
  516.             if (killem == -1) {
  517.                 yorn = ask("y", "Should I kill your i-processes? ");
  518.                 killem = (CharUpcase(*yorn) == 'Y');
  519.             }
  520.             if (killem)
  521.                 proc_kill (p, SIGKILL);
  522.         }
  523. }
  524.  
  525. /*********************************/
  526. void pbuftiedp(register Buffer *b)
  527. /*********************************/
  528. {
  529.     register Process *p = b->b_process;
  530.  
  531.     if (!isdead(p))
  532.         complain("Process %s, attached to %b, is %s.",
  533.              proc_cmd(p), b, pstate(p));
  534. }
  535.  
  536. char    dbx_parse_fmt[128] = "line \\([0-9]*\\) in \\{file,\\} *\"\\([^\"]*\\)\"";
  537.  
  538. /**********************/
  539. void DBXpoutput(void)
  540. /**********************/
  541. {
  542.     if (curbuf->b_process == 0)
  543.         complain("[Must be in a process buffer to enable dbx mode]");
  544.     curbuf->b_process->p_dbx_mode = !curbuf->b_process->p_dbx_mode;
  545.     UpdModLine = YES;
  546. }
  547. /********************************/
  548. static void watch_input(Mark *m)
  549. /********************************/
  550. {
  551.     Bufpos    save;
  552.     char    fname[FILESIZE],
  553.         lineno[FILESIZE];
  554.     int    lnum;
  555.     Window    *savew = curwind;
  556.     Buffer    *buf;
  557.  
  558.     DOTsave(&save);
  559.     ToMark(m);
  560.     if (dosearch(dbx_parse_fmt, FORWARD, YES) != NULL) {
  561.         get_FL_info (fname, lineno);
  562.         buf = do_find ((Window *) 0, fname, YES);
  563.         pop_wind (buf->b_name, NO, -1);
  564.         lnum = atoi(lineno);
  565.         SetLine(next_line(buf->b_first, lnum - 1));
  566.         SetWind(savew);
  567.     }
  568.     SetDot(&save);
  569. }
  570.  
  571. /* Process receive: receives the characters in buf, and appends them to
  572.    the buffer associated with p. */
  573. /*************************************************************/
  574. static    void _fastcall proc_rec (register Process *p, char *buf)
  575. /*************************************************************/
  576. {
  577.     Buffer    *saveb = curbuf;
  578.     register  Window    *w;
  579.     register  Mark    *savepoint;
  580.     int    sameplace = NO,
  581.         do_disp = NO;
  582.  
  583.     if (curwind->w_bufp == p->p_buffer)
  584.         w = curwind;
  585.     else
  586.         w = windbp(p->p_buffer);    /* Is this window visible? */
  587.     if (w != 0)
  588.         do_disp = (in_window(w, p->p_mark->m_line) != -1);
  589.     SetBuf(p->p_buffer);
  590.     savepoint = MakeMark(curline, curchar, M_FLOATER);
  591.     ToMark(p->p_mark);        /* where output last stopped */
  592.     if (savepoint->m_line == curline && savepoint->m_char == curchar)
  593.         sameplace = YES;
  594.     ins_str(buf, YES);
  595.     if (do_disp == YES && p->p_dbx_mode == YES)
  596.         watch_input(p->p_mark);
  597.     MarkSet(p->p_mark, curline, curchar);
  598.     if (!sameplace)
  599.         ToMark(savepoint);    /* back to where we were */
  600.     DelMark(savepoint);
  601.     /* redisplay now, instead of right after the ins_str, so that
  602.        we don't get a bouncing effect if point is not the same as
  603.        the process output position */
  604.     if (do_disp) {
  605.         w->w_line = curline;
  606.         w->w_char = curchar;
  607.         redisplay();
  608.     }
  609.     SetBuf(saveb);
  610. }
  611. /***************************************************/
  612. static void proc_kill(Process *p, int sig)
  613. /***************************************************/
  614. {
  615.     if (isdead(p))
  616.         return;
  617.     if (killpg (p->p_pid, sig) == -1) {
  618.     //if (killpg (p->p_portpid, sig) == -1) {
  619.         s_mess("Cannot kill %s!", proc_buf(p));
  620.         return;
  621.     }
  622. }
  623. /*************************************/
  624. static int kill (int pid, int sig)
  625. /*************************************/
  626. /* imitate the unix kill command for OS2 */
  627. {
  628.     int err_code;
  629.     switch (sig) {
  630.     case (SIGKILL) : err_code = DosKillProcess (DKP_PROCESS, pid);
  631.         break;
  632. //    case (SIGQUIT) : err_code = DosFlagProcess (pid, DCWA_PROCESSTREE,
  633. //                              PFLG_A, 0);
  634.     case (SIGQUIT) : err_code = DosFlagProcess (pid, FLGP_PID,
  635.                               PFLG_A, 0);
  636.         break;
  637.     case (SIGINT)  : err_code = DosSendSignal (pid, SIGINT);
  638.     }
  639.     if (err_code != 0) return (-1);
  640.     else
  641.         return (0);
  642.  
  643.  
  644. }
  645. /* Free process CHILD.  Do all the necessary cleaning up (closing fd's,
  646.    etc.). */
  647. /**************************************/
  648. static void free_proc (Process *child)
  649. /**************************************/
  650. {
  651.     register  Process    *p,
  652.                 *prev = 0;
  653.  
  654.     if (!isdead(child))
  655.         return;
  656.     for (p = procs; p != child; prev = p, p = p->p_next)
  657.         ;
  658.     if (prev == 0)
  659.         procs = child->p_next;
  660.     else
  661.         prev->p_next = child->p_next;
  662.     proc_close(child);        /* if not already closed */
  663.  
  664.     /* It's possible that the buffer has been given another process
  665.        between the time CHILD dies and CHILD's death is noticed (via
  666.        list-processes).  So we only set it the buffer's process to
  667.        0 if CHILD is still the controlling process. */
  668.     if (child->p_buffer->b_process == child) {
  669.         child->p_buffer->b_process = 0;
  670.     }
  671.     {
  672.         Buffer    *old = curbuf;
  673.  
  674.         SetBuf(child->p_buffer);
  675.         DelMark(child->p_mark);
  676.         SetBuf(old);
  677.     }
  678.     free((char *) child->p_name);
  679.     free((char *) child);
  680. }
  681.  
  682. /*********************/
  683. void ProcList(void)
  684. /*********************/
  685. {
  686.     register  Process    *p,
  687.                 *next;
  688.     char    *fmt = "%-15s  %-15s  %-8s %s",
  689.         pidstr[16];
  690.     void _fastcall screen_buffer_flush (void);
  691.  
  692.     if (procs == 0) {
  693.         message("[No subprocesses]");
  694.         return;
  695.     }
  696.     TOstart("Process list", TRUE);
  697.  
  698.     Typeout(fmt, "Buffer", "Status", "Pid ", "Command");
  699.     Typeout(fmt, "------", "------", "--- ", "-------");
  700.     for (p = procs; p != 0; p = next) {
  701.         next = p->p_next;
  702.         swritef(pidstr, "%d", p->p_pid);
  703.         Typeout(fmt, proc_buf(p), pstate(p), pidstr, p->p_name);
  704.         if (isdead(p)) {
  705.             free_proc(p);
  706.             UpdModLine = YES;
  707.         }
  708.     }
  709.     TOstop();
  710. }
  711. /*************************************/
  712. static void do_rtp (register Mark *mp)
  713. /*************************************/
  714. {
  715.     register  Process *p = curbuf->b_process;
  716.     Line    *line1 = curline,
  717.         *line2 = mp->m_line;
  718.     int    char1 = curchar,
  719.         char2 = mp->m_char;
  720.     char    *gp;
  721.     size_t    nbytes;
  722.  
  723.     if (isdead(p) || p->p_buffer != curbuf)
  724.         return;
  725.  
  726.     (void) fixorder(&line1, &char1, &line2, &char2);
  727.     while (line1 != line2->l_next) {
  728.         gp = ltobuf(line1, genbuf) + char1;
  729.         if (line1 == line2)
  730.             gp[char2] = '\0';
  731.         else
  732.             strcat(gp, "\n");
  733.         if ((nbytes = strlen(gp)) != 0)
  734.             proc_write(p, gp, nbytes);
  735.         line1 = line1->l_next;
  736.         char1 = 0;
  737.     }
  738. }
  739.  
  740. /***********************/
  741. void ProcNewline (void)
  742. /***********************/
  743. {
  744. #ifdef ABBREV
  745.     MaybeAbbrevExpand();
  746. #endif
  747.     SendData(YES);
  748. }
  749.  
  750. /***********************/
  751. void ProcSendData (void)
  752. /***********************/
  753. {
  754. #ifdef ABBREV
  755.     MaybeAbbrevExpand();
  756. #endif
  757.     SendData(NO);
  758. }
  759. /**********************************************/
  760. static void _fastcall SendData (int newlinep )
  761. /**********************************************/
  762. {
  763.     register Process    *p = curbuf->b_process;
  764.     register char    *lp,
  765.             *gp;    /* JF fix for better prompt handling */
  766.  
  767.     if (isdead(p))
  768.         return;
  769.     /* If the process mark was involved in a big deletion, because
  770.        the user hit ^W or something, then let's do some magic with
  771.        the process mark.  Problem is that if the user yanks back the
  772.        text he deleted, the mark stays at the beginning of the region,
  773.        and so the next time SendData() is called the entire region
  774.        will be sent.  That's not good.  So, to deal with that we reset
  775.        the mark to the last line, after skipping over the prompt, etc. */
  776.     if (p->p_mark->m_flags & M_BIG_DELETE) {
  777.         Bufpos    bp;
  778.  
  779.         p->p_mark->m_flags &= ~M_BIG_DELETE;
  780.  
  781.         DOTsave(&bp);
  782.         ToLast();
  783.         Bol();
  784.         /* While we're looking at a prompt, and while we're
  785.            moving forward.  This is for people who accidently
  786.            set their process-prompt to ">*" which will always
  787.            match! */
  788.         while ((LookingAt(proc_prompt, linebuf, curchar)) &&
  789.                (REeom > curchar))
  790.             curchar = REeom;
  791.         MarkSet(p->p_mark, curline, curchar);
  792.         SetDot(&bp);
  793.     }
  794.  
  795.     if (lastp(curline)) {
  796.         Eol();
  797.         if (newlinep)
  798.             LineInsert(1);
  799.         do_rtp(p->p_mark);
  800.         MarkSet(p->p_mark, curline, curchar);
  801.     } else {
  802.         /* Either we're looking at a prompt, or we're not, in
  803.            which case we want to strip off the beginning of the
  804.            line anything that looks like what the prompt at the
  805.            end of the file is.  In other words, if "(dbx) stop in
  806.            ProcessNewline" is the line we're on, and the last
  807.            line in the buffer is "(dbx) ", then we strip off the
  808.            leading "(dbx) " from this line, because we know it's
  809.            part of the prompt.  But this only happens if "(dbx) "
  810.            isn't one of the process prompts ... follow what I'm
  811.            saying? */
  812.         Bol();
  813.         if (LookingAt(proc_prompt, linebuf, curchar)) {
  814.             do
  815.                 curchar = REeom;
  816.             while ((LookingAt(proc_prompt, linebuf, curchar)) &&
  817.                    (REeom > curchar));
  818.             strcpy(genbuf, linebuf + curchar);
  819.             Eof();
  820.             ins_str(genbuf, NO);
  821.         } else {
  822.             strcpy(genbuf, linebuf + curchar);
  823.             Eof();
  824.             gp = genbuf;
  825.             lp = linebuf;
  826.             while (*lp == *gp && *lp != '\0') {
  827.                 lp += 1;
  828.                 gp += 1;
  829.             }
  830.             ins_str(gp, NO);
  831.         }
  832.     }
  833. }
  834.  
  835. /********************/
  836. void ShellProc(void)
  837. /********************/
  838. {
  839.     char    *shbuf = "*shell*";
  840.     register  Buffer *b;
  841.  
  842.     b = buf_exists(shbuf);
  843.     if (b == 0 || isdead(b->b_process))
  844.         //proc_strt(shbuf, NO, Shell, "-i", (char *) 0);
  845.         proc_strt(shbuf, NO, Shell, "/K", (char *) 0);
  846.     pop_wind(shbuf, NO, -1);
  847. }
  848.  
  849. /*******************/
  850. void Iprocess(void)
  851. /*******************/
  852. {
  853.     register  char    *command;
  854.     char    scratch[64],
  855.         *bnm;
  856.     int    cnt = 1;
  857.     Buffer    *bp;
  858.  
  859.     command = ask(ShcomBuf, ProcFmt);
  860.     null_ncpy(ShcomBuf, command, (sizeof ShcomBuf) - 1);
  861.     bnm = MakeName(command);
  862.     strcpy(scratch, bnm);
  863.     while ((bp = buf_exists(scratch)) != NIL && !isdead(bp->b_process))
  864.         swritef(scratch, "%s.%d", bnm, cnt++);
  865.     proc_strt(scratch, YES, Shell, ShFlags, command, (char *) 0);
  866. }
  867.  
  868. static SIGRESULT proc_child(int junk)
  869.       /* JUNK needed for signal handler; not used */
  870. {
  871.     union wait    w;
  872.     register  int    pid;
  873.  
  874.     for (;;) {
  875. #ifndef WAIT3
  876.         pid = wait2(&w.w_status, (WNOHANG | WUNTRACED));
  877. #else
  878.         pid = wait3(&w, (WNOHANG | WUNTRACED), (struct rusage *) 0);
  879. #endif
  880.         if (pid <= 0)
  881.             break;
  882.         kill_off(pid, w.w_status);
  883.     }
  884.     SIGRETURN;
  885. }
  886.  
  887. /***********************************************/
  888. void _fastcall kill_off( int pid, union wait w )
  889. /***********************************************/
  890. {
  891.     register  Process  *child;
  892.  
  893.     if ((child = proc_pid( pid )) == 0)
  894.         return;
  895.  
  896.     UpdModLine = YES;        /* we're changing state ... */
  897.     if (WIFSTOPPED( w ))
  898.         child->p_state = STOPPED;
  899.     else {
  900.         child->p_state = DEAD;
  901.         if (WIFEXITED(w))
  902.             child->p_howdied = EXITED;
  903.         else if (WIFSIGNALED(w)) {
  904.             child->p_reason = w_termsignum(w);
  905.             child->p_howdied = KILLED;
  906.         }
  907.         {
  908.             Buffer    *save = curbuf;
  909.             char    mesg[128];
  910.  
  911.             /* insert status message now */
  912.             swritef(mesg, "[Process %s: %s]\n",
  913.                 proc_cmd(child),
  914.                 pstate(child));
  915.             SetBuf(child->p_buffer);
  916.             ins_str(mesg, NO);
  917.             SetBuf(save);
  918.             redisplay();
  919.         }
  920.     }
  921. }
  922.  
  923. #endif /* IPROCS */
  924.