home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / jove414s.zip / os2proc.c < prev    next >
C/C++ Source or Header  |  1991-07-07  |  21KB  |  853 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. #ifdef OS2
  8. # define INCL_BASE
  9. # include <os2.h>
  10.   int flushall(void);
  11. #include <fcntl.h>
  12.  
  13. struct _iobuf {
  14.     char  *_ptr;
  15.     int   _cnt;
  16.     char  *_base;
  17.     char  _flag;
  18.     char  _file;
  19.     };
  20. typedef struct _iobuf FILE;
  21.  
  22. FILE  *  _cdecl _popen(const char  *,
  23.     const char  *); 
  24. int  _cdecl _pclose(FILE  *);
  25. FILE *fdopen(int handlae, char *mode);
  26. char *strcpy (char *str1, const char *str2);
  27. char *strcat (char *str1, const char *str2);
  28. # define fileno(_stream)   ((int)(unsigned char)(_stream)->_file)
  29. #endif /* OS2 */
  30.  
  31. #include "jove.h"
  32. #include "ctype.h"
  33. #include "fp.h"
  34. #include "re.h"
  35. #include "termcap.h"
  36. #include "disp.h"
  37.  
  38. #include <signal.h>
  39. #ifdef    STDARGS
  40. # include <stdarg.h>
  41. #else
  42. # include <varargs.h>
  43. #endif
  44.  
  45. #ifdef MSDOS
  46. # include <d:\c600\include\io.h>
  47. # include <process.h>
  48. #endif
  49.  
  50. private void
  51.     DoShell proto((char *, char *)),
  52.     com_finish proto((int, char *)),
  53.     toerror proto((int, int));
  54.  
  55. #ifdef    MSDOS
  56. private void
  57.     closepipe proto((void));
  58. #endif
  59.  
  60. private int
  61.     okay_error proto((void));
  62.  
  63. #if defined(MSDOS)
  64. private int
  65.     openforpipe proto((void)),
  66.     reopenforpipe proto((void));
  67. #endif
  68.  
  69. private struct error
  70.     *AddError proto((struct error *, Line *, Buffer *, Line *, int));
  71.  
  72. long    SigMask = 0;
  73.  
  74. /* This disgusting RE search string parses output from the GREP
  75.    family, from the pdp11 compiler, pcc, and lint.  Jay (HACK)
  76.    Fenlasen changed this to work for the lint errors. */
  77. // char    ErrFmtStr[256] = "^\\{\",\\}\\([^:\"( \t]*\\)\\{\"\\, line ,:,(\\} *\\([0-9][0-9]*\\)[:)]\
  78. // \\|::  *\\([^(]*\\)(\\([0-9]*\\))$\
  79. // \\|( \\([^(]*\\)(\\([0-9]*\\)) ),";
  80. char    ErrFmtStr[256]="^[a-z][a-zA-Z2.]*\([0-9][0-9]\)$";
  81.  
  82. struct error {
  83.     Buffer        *er_buf;    /* Buffer error is in */
  84.     Line        *er_mess,    /* Actual error message */
  85.             *er_text;    /* Actual error */
  86.     int        er_char;    /* char pos of error */
  87.     struct error    *er_prev,    /* List of errors */
  88.             *er_next;
  89. };
  90.  
  91. private struct error    *cur_error = NULL,
  92.         *errorlist = NULL;
  93. Buffer        *perr_buf = NULL;    /* Buffer with error messages */
  94.  
  95. int    WtOnMk = 1;        /* Write the modified files when we make */
  96.  
  97. /* Add an error to the end of the list of errors.  This is used for
  98.    parse-{C,LINT}-errors and for the spell-buffer command */
  99. /*********************************************************/
  100. private struct error *
  101. AddError(struct error *laste, Line *errline, Buffer *buf,
  102.      Line *line, int charpos)
  103. /*********************************************************/
  104. {
  105.     struct error    *new = (struct error *) emalloc(sizeof *new);
  106.  
  107.     new->er_prev = laste;
  108.     if (laste)
  109.         laste->er_next = new;
  110.     else {
  111.         if (errorlist)        /* Free up old errors */
  112.             ErrFree();
  113.         cur_error = errorlist = new;
  114.     }
  115.     laste = new;
  116.     new->er_next = 0;
  117.     new->er_buf = buf;
  118.     new->er_text = line;
  119.     new->er_char = charpos;
  120.     new->er_mess = errline;
  121.  
  122.     return new;
  123. }
  124. /****************************************************/
  125. void _fastcall get_FL_info(char *fname, char *lineno)
  126. /****************************************************/
  127. {
  128.     putmatch(1, fname, (size_t)FILESIZE);
  129.     putmatch(2, lineno, (size_t)FILESIZE);
  130.  
  131.     /* error had lineno followed fname, so switch the two */
  132.     if (!isdigit(lineno[0])) {
  133.         char    tmp[FILESIZE];
  134.  
  135.         strcpy(tmp, lineno);
  136.         strcpy(lineno, fname);
  137.         strcpy(fname, tmp);
  138.     }
  139. }
  140.  
  141. /* Free up all the errors */
  142.  
  143. /********************/
  144. void ErrFree (void)
  145. /********************/
  146. {
  147.     /* register */ struct error    *ep;
  148.  
  149.     for (ep = errorlist; ep != 0; ep = ep->er_next)
  150.         free((char *) ep);
  151.     errorlist = cur_error = 0;
  152. }
  153.  
  154. /* Parse errors of the form specified in ErrFmtStr in the current
  155.    buffer.  Do a show error of the first error.  This is neat because this
  156.    will work for any kind of output that prints a file name and a line
  157.    number on the same line. */
  158.  
  159. /********************/
  160. void ErrParse (void)
  161. /********************/
  162. {
  163.     struct RE_block    re_blk;
  164.     Bufpos    *bp;
  165.     char    fname[FILESIZE],
  166.         lineno[FILESIZE];
  167.     int    lnum,
  168.         last_lnum = -1;
  169.     struct error    *ep = 0;
  170.     Buffer    *buf,
  171.         *lastb = 0;
  172.     Line    *err_line;
  173.  
  174.     ErrFree();        /* This is important! */
  175.     ToFirst();
  176.     perr_buf = curbuf;
  177.     REcompile(ErrFmtStr, YES, &re_blk);
  178.     /* Find a line with a number on it. */
  179.     while ((bp = docompiled(FORWARD, &re_blk)) != NULL) {
  180.         SetDot(bp);
  181.         get_FL_info(fname, lineno);
  182.         buf = do_find((Window *) 0, fname, YES);
  183.         if (buf != lastb) {
  184.             lastb = buf;
  185.             last_lnum = -1;        /* signals new file */
  186.             err_line = buf->b_first;
  187.         }
  188.         (void) chr_to_int(lineno, 10, NO, &lnum);
  189.         if (lnum == last_lnum)    /* one error per line is nicer */
  190.             continue;
  191.         if (last_lnum == -1)
  192.             last_lnum = 1;    /* that's where we really are */
  193.         err_line = next_line(err_line, lnum - last_lnum);
  194.         ep = AddError(ep, curline, buf, err_line, 0);
  195.         last_lnum = lnum;
  196.     }
  197.     if (cur_error != 0)
  198.         ShowErr();
  199. }
  200.  
  201. /* Internal next error sets cur_error to the next error, taking the
  202.    argument count, supplied by the user, into consideration. */
  203.  
  204. private char    errbounds[] = "You're at the %s error.",
  205.         noerrs[] = "No errors!";
  206.  
  207. /******************************************/
  208. static void toerror(int forward, int num)
  209. /******************************************/
  210. {
  211.     /* register */ struct error    *e = cur_error;
  212.  
  213.     if (e == 0)
  214.         complain(noerrs);
  215.     if ((forward && (e->er_next == 0)) ||
  216.         (!forward && (e->er_prev == 0)))
  217.         complain(errbounds, forward ? "last" : "first");
  218.  
  219.     while (--num >= 0) {
  220.         if ((e = forward ? e->er_next : e->er_prev) == 0)
  221.             break;
  222.         cur_error = e;
  223.     }
  224. }
  225.  
  226. /********************/
  227. void NextError(void)
  228. /********************/
  229. {
  230.     ToError(1);
  231. }
  232.  
  233. /********************/
  234. void PrevError(void)
  235. /********************/
  236. {
  237.     ToError(0);
  238. }
  239.  
  240. /*****************************/
  241. static int okay_error (void)
  242. /*****************************/
  243. {
  244.     return ((inlist(perr_buf->b_first, cur_error->er_mess)) &&
  245.         (inlist(cur_error->er_buf->b_first, cur_error->er_text)));
  246. }
  247.  
  248. /* Go the the next error, if there is one.  Put the error buffer in
  249.    one window and the buffer with the error in another window.
  250.    It checks to make sure that the error actually exists. */
  251.  
  252. /*************************************/
  253. void _fastcall ToError (int forward)
  254. /*************************************/
  255. {
  256.     do {
  257.         toerror(forward, arg_value());
  258.     } while (!okay_error());
  259.     ShowErr();
  260. }
  261.  
  262. int    EWSize = 20;    /* percentage of screen the error window
  263.                should be */
  264.  
  265. /******************************/
  266. static void set_wsize(int wsize)
  267. /******************************/
  268. {
  269.     wsize = (LI * wsize) / 100;
  270.     if (wsize >= 1 && !one_windp())
  271.         WindSize(curwind, wsize - (curwind->w_height - 1));
  272. }
  273.  
  274. /* Show the current error, i.e. put the line containing the error message
  275.    in one window, and the buffer containing the actual error in another
  276.    window. */
  277.  
  278. /********************/
  279. void ShowErr (void)
  280. /********************/
  281. {
  282.     Window    *err_wind,
  283.         *buf_wind;
  284.  
  285.     if (cur_error == 0)
  286.         complain(noerrs);
  287.     if (!okay_error()) {
  288.         rbell();
  289.         return;
  290.     }
  291.     err_wind = windbp(perr_buf);
  292.     buf_wind = windbp(cur_error->er_buf);
  293.  
  294.     if (err_wind && !buf_wind) {
  295.         SetWind(err_wind);
  296.         pop_wind(cur_error->er_buf->b_name, NO, -1);
  297.         buf_wind = curwind;
  298.     } else if (!err_wind && buf_wind) {
  299.         SetWind(buf_wind);
  300.         pop_wind(perr_buf->b_name, NO, -1);
  301.         err_wind = curwind;
  302.     } else if (!err_wind && !buf_wind) {
  303.         pop_wind(perr_buf->b_name, NO, -1);
  304.         err_wind = curwind;
  305.         pop_wind(cur_error->er_buf->b_name, NO, -1);
  306.         buf_wind = curwind;
  307.     }
  308.  
  309.     /* Put the current error message at the top of its Window */
  310.     SetWind(err_wind);
  311.     SetLine(cur_error->er_mess);
  312.     SetTop(curwind, (curwind->w_line = cur_error->er_mess));
  313.     set_wsize(EWSize);
  314.  
  315.     /* now go to the the line with the error in the other window */
  316.     SetWind(buf_wind);
  317.     DotTo(cur_error->er_text, cur_error->er_char);
  318. }
  319.  
  320. char    ShcomBuf[LBSIZE];
  321.  
  322. /* Make a buffer name given the command `command', i.e. "fgrep -n foo *.c"
  323.    will return the buffer name "fgrep".  */
  324.  
  325. /******************************/
  326. char *MakeName(char *command)
  327. /******************************/
  328. {
  329.     static char    bnm[50];
  330.     /* register */ char    *cp = bnm,
  331.                  c;
  332.  
  333.     while ((c = *command++) != '\0' && (c == ' ' || c == '\t'))
  334.         ;
  335.     do
  336.         *cp++ = c;
  337.     while ((c = *command++) != '\0' && (c != ' ' && c != '\t'));
  338.     *cp = 0;
  339.     strcpy(bnm, basename(bnm));
  340.  
  341.     return bnm;
  342. }
  343.  
  344. /* Run make, first writing all the modified buffers (if the WtOnMk flag is
  345.    non-zero), parse the errors, and go the first error. */
  346.  
  347. private char    make_cmd[LBSIZE] = "make";
  348.  
  349.  
  350. /**********************/
  351. void MakeErrors (void)
  352. /**********************/
  353. {
  354.     Window    *old = curwind;
  355.     int    status,
  356.         compilation;
  357.  
  358.     if (WtOnMk)
  359.         put_bufs(0);
  360.     /* When we're not doing make or cc (i.e., the last command
  361.        was probably a grep or something) and the user just types
  362.        C-X C-E, he probably (possibly, hopefully, usually (in my
  363.        case)) doesn't want to do the grep again but rather wants
  364.        to do a make again; so we ring the bell and insert the
  365.        default command and let the person decide. */
  366.  
  367.     compilation = (sindex("make", make_cmd) || sindex("cc", make_cmd));
  368.     if (is_an_arg() || !compilation) {
  369.         if (!compilation) {
  370.             rbell();
  371.             Inputp = make_cmd;    /* insert the default for the user */
  372.         }
  373.         null_ncpy(make_cmd, ask(make_cmd, "Compilation command: "),
  374.                 sizeof (make_cmd) - 1);
  375.     }
  376.     status = UnixToBuf(MakeName(make_cmd), YES, EWSize, YES, Shell, ShFlags, make_cmd, (char *) 0);
  377.     com_finish(status, make_cmd);
  378.  
  379.     ErrParse();
  380.  
  381.     if (!cur_error)
  382.         SetWind(old);
  383. }
  384.  
  385. #ifdef SPELL
  386.  
  387. /************************************/
  388. static void SpelParse (char *bname)
  389. /************************************/
  390. {
  391.     Buffer    *buftospel,
  392.         *wordsb;
  393.     char    wordspel[100];
  394.     Bufpos    *bp;
  395.     struct error    *ep = 0;
  396.  
  397.     ErrFree();        /* This is important! */
  398.  
  399.     buftospel = curbuf;
  400.     wordsb = buf_exists(bname);
  401.     perr_buf = wordsb;    /* This is important (buffer containing
  402.                    error messages) */
  403.     SetBuf(wordsb);
  404.     ToFirst();
  405.     f_mess("Finding misspelled words ... ");
  406.     while (!lastp(curline)) {
  407.         swritef(wordspel, "\\<%s\\>", linebuf);
  408.         SetBuf(buftospel);
  409.         ToFirst();
  410.         while ((bp = dosearch(wordspel, 1, 1)) != NULL) {
  411.             SetDot(bp);
  412.             ep = AddError(ep, wordsb->b_dot, buftospel,
  413.                       curline, curchar);
  414.         }
  415.         SetBuf(wordsb);
  416.         line_move(FORWARD, 1, NO);
  417.     }
  418.     add_mess("Done.");
  419.     SetBuf(buftospel);
  420.     ShowErr();
  421. }
  422.  
  423.  
  424. /**********************/
  425. void SpelBuffer (void)
  426. /**********************/
  427. {
  428.     char    *Spell = "Spell",
  429.         com[100];
  430.     Window    *savewp = curwind;
  431.  
  432.     put_bufs(0);
  433.     swritef(com, "spell %s", curbuf->b_fname);
  434.     (void) UnixToBuf(Spell, YES, EWSize, YES, Shell, ShFlags, com, (char *) 0);
  435.     message("[Delete the irrelevant words and then type C-X C-C]");
  436.     ToFirst();
  437.     Recur();
  438.     SetWind(savewp);
  439.     SpelParse(Spell);
  440. }
  441.  
  442. /**********************/
  443. void SpelWords (void)
  444. /**********************/
  445. {
  446.     char    *buftospel;
  447.     Buffer    *wordsb = curbuf;
  448.  
  449.     if ((buftospel = ask_buf((Buffer *) 0)) == 0)
  450.         return;
  451.     SetBuf(do_select(curwind, buftospel));
  452.     SpelParse(wordsb->b_name);
  453. }
  454.  
  455. #endif /* SPELL */
  456.  
  457. /********************/
  458. void ShToBuf (void)
  459. /********************/
  460. {
  461.     char    bnm[128],
  462.         cmd[128];
  463.  
  464.     strcpy(bnm, ask((char *) 0, "Buffer: "));
  465.     strcpy(cmd, ask(ShcomBuf, "Command: "));
  466.     DoShell(bnm, cmd);
  467. }
  468.  
  469.  
  470. /********************/
  471. void ShellCom (void)
  472. /********************/
  473. {
  474.     null_ncpy(ShcomBuf, ask(ShcomBuf, ProcFmt), (sizeof ShcomBuf) - 1);
  475.     DoShell(MakeName(ShcomBuf), ShcomBuf);
  476. }
  477.  
  478. /*******************/
  479. void ShNoBuf (void)
  480. /*******************/
  481. {
  482.     int    status;
  483.  
  484.     null_ncpy(ShcomBuf, ask(ShcomBuf, ProcFmt), (sizeof ShcomBuf) - 1);
  485.     status = UnixToBuf((char *) 0, NO, 0, NO, Shell, ShFlags, ShcomBuf,
  486.         curbuf->b_fname, curbuf->b_fname, (char *) 0);
  487.     com_finish(status, ShcomBuf);
  488. }
  489.  
  490. /***********************/
  491. void Shtypeout (void)
  492. /***********************/
  493. {
  494.     int    status;
  495.     void _fastcall screen_buffer_flush (void);
  496.     null_ncpy(ShcomBuf, ask(ShcomBuf, ProcFmt), (sizeof ShcomBuf) - 1);
  497.     status = UnixToBuf((char *) 0, YES, 0, NO, Shell, ShFlags, ShcomBuf,
  498.         curbuf->b_fname, curbuf->b_fname, (char *) 0);
  499.     if (status == 0)
  500.         Typeout("[%s: completed successfully]", ShcomBuf);
  501.     else
  502.         Typeout("[%s: exited (%d)]", ShcomBuf, status);
  503.     TOstop();
  504. }
  505.  
  506. /* Run the shell command into `bnm'.  Empty the buffer except when we
  507.    give a numeric argument, in which case it inserts the output at the
  508.    current position in the buffer.  */
  509.  
  510. /*********************************************/
  511. static void DoShell(char *bnm, char *command)
  512. /*********************************************/
  513. {
  514.     Window    *savewp = curwind;
  515.     int    status;
  516.  
  517.     status = UnixToBuf(bnm, YES, 0, !is_an_arg(), Shell, ShFlags,
  518.         command, curbuf->b_fname, curbuf->b_fname, (char *) 0);
  519.     com_finish(status, command);
  520.     SetWind(savewp);
  521. }
  522.  
  523. /**********************************************/
  524. static void com_finish(int status, char *cmd)
  525. /**********************************************/
  526. {
  527.     s_mess("[%s: ", cmd);
  528.     if (status == 0)
  529.         add_mess("completed successfully");
  530.     else
  531.         add_mess("exited (%d)", status);
  532.     add_mess("]");
  533. }
  534.  
  535. #ifndef MSDOS
  536. /**********************************/
  537. void dowait(int pid, int status)
  538. /**********************************/
  539. {
  540. # ifndef IPROCS
  541.  
  542.     int    rpid;
  543.  
  544.     while ((rpid = wait(status)) != pid)
  545.         ;
  546. # else
  547.  
  548. # include "wait.h"
  549.  
  550.     union wait    w;
  551.     int    rpid;
  552.  
  553.     for (;;) {
  554. #  ifndef WAIT3
  555.         rpid = wait2(&w.w_status, 0);
  556. #  else
  557.         rpid = wait3(&w, 0, (struct rusage *) 0);
  558. #  endif
  559.         if (rpid == -1)
  560.             break;
  561.         else if (rpid == pid) {
  562.             if (status)
  563.                 *status = w.w_status;
  564.             break;
  565.         } else
  566.             kill_off(rpid, w);
  567.     }
  568. # endif /* IPROCS */
  569. }
  570. #endif /* MSDOS */
  571.  
  572. /* Run the command to bnm, erase the buffer if clobber is non-zero,
  573.    and redisplay if disp is non-zero.  Leaves current buffer in `bnm'
  574.    and leaves any windows it creates lying around.  It's up to the caller
  575.    to fix everything up after we're done.  (Usually there's nothing to
  576.    fix up.) */
  577.  
  578. #ifdef OS2
  579.  int    phandle;
  580. #endif /* OS2 */
  581.  
  582. #ifdef    STDARGS
  583.     int
  584. UnixToBuf(char *bnm, int disp, int wsize, int clobber, ...)
  585. #else
  586.     /*VARARGS4*/ int
  587. UnixToBuf(bnm, disp, wsize, clobber, va_alist)
  588. /**********************************/
  589.     char    *bnm;
  590.     int    disp;
  591.     int    wsize;
  592.     int    clobber;
  593.     va_dcl
  594. #endif
  595. {
  596.     int    p[2],
  597.         pid,
  598.         handle,
  599.         status,
  600.         retcode = 0,
  601.         eof,
  602.         errcode;
  603.     va_list    ap;
  604.     char    *argv[32],
  605.         *mess;
  606.     File    *fp;
  607.     FILE    *pipe_stream;
  608.     int     fd_pipe;    
  609.         char    shell_command[80];
  610.     SIGRESULT    (*old_int) proto((int));
  611.  
  612.     void os2_kbd_open( void);
  613.     va_init(ap, clobber);
  614.     make_argv(argv, ap);
  615.     va_end(ap);
  616.     if (bnm != 0 && clobber == YES)
  617.         isprocbuf(bnm);
  618.     if (disp) {
  619.         if (bnm != 0)
  620.             message("Starting up...");
  621.         else {
  622.             TOstart(argv[0], TRUE);
  623.             Typeout("Starting up...");
  624.         }
  625.         if (bnm != 0) {
  626.             pop_wind(bnm, clobber, clobber ? B_PROCESS : B_FILE);
  627.             set_wsize(wsize);
  628.             redisplay();
  629.         }
  630.     }
  631.     /* Now I will attempt to describe how I deal with signals during
  632.        the execution of the shell command.  My desire was to be able
  633.        to interrupt the shell command AS SOON AS the window pops up.
  634.        So, if we have JOB_CONTROL (i.e., the new signal mechanism) I
  635.        hold SIGINT, meaning if we interrupt now, we will eventually
  636.        see the interrupt, but not before we are ready for it.  We
  637.        fork, the child releases the interrupt, it then sees the
  638.        interrupt, and so exits.  Meanwhile the parent ignores the
  639.        signal, so if there was a pending one, it's now lost.
  640.  
  641.        With no JOB_CONTROL, the best behavior you can expect is, when
  642.        you type ^] too very quickly after the window pops up, it may
  643.        be ignored.  The behavior BEFORE was that it would interrupt
  644.        JOVE and then you would have to continue JOVE and wait a
  645.        little while longer before trying again.  Now that is fixed,
  646.        in that you just have to type it twice. */
  647.  
  648. #ifndef MSDOS
  649. # ifdef IPROCS
  650.     SigHold(SIGCHLD);
  651. # endif
  652. # ifdef JOB_CONTROL
  653.     SigHold(SIGINT);
  654. # else
  655.     old_int = signal(SIGINT, SIG_IGN),
  656. # endif
  657.     dopipe(p);
  658.     pid = vfork();
  659.     if (pid == -1) {
  660.         pclose(p);
  661.         complain("[Fork failed]");
  662.     }
  663.     if (pid == 0) {
  664. # ifdef BSD_SIGS
  665.         /*
  666.          * We want to release SIGCHLD and SIGINT in the child, but
  667.          * we can't use SigRelse because that would change Jove's
  668.          * copy of the SigMask variable (because we're in a
  669.          * vfork).  So we simply set set the mask directly.  There
  670.          * are several other forks in Jove, but this is the only
  671.          * one we execute often enough to make it worth using a
  672.          * vfork.
  673.          */
  674.         (void) signal(SIGINT, SIG_DFL);
  675.         (void) sigsetmask(SigMask & ~(sigmask(SIGCHLD)|sigmask(SIGINT)));
  676. # else /* BSD_SIGS */
  677. # ifdef IPROCS
  678.         SigRelse(SIGCHLD);   /* don't know if this matters */
  679. # endif /* IPROCS */
  680.         (void) signal(SIGINT, SIG_DFL);
  681. # ifdef JOB_CONTROL
  682.         SigRelse(SIGINT);
  683. # endif
  684. # endif /* BSD_SIGS */
  685.         (void) close(0);
  686.         (void) open("/dev/null", 0);
  687.         (void) close(1);
  688.         (void) close(2);
  689.         (void) dup(p[1]);
  690.         (void) dup(p[1]);
  691.         pclose(p);
  692.         execv(argv[0], (const char **) &argv[1]);
  693.         (void) write(1, "Execl failed.\n", (size_t) 14);
  694.         _exit(1);
  695.     }
  696. # ifdef JOB_CONTROL
  697.     old_int = signal(SIGINT, SIG_IGN);
  698. # endif
  699.  
  700.     fp = fd_open(argv[1], F_READ, p[0], iobuff, LBSIZE);
  701. #else /* MSDOS */
  702.         strcpy (shell_command, argv[3]);
  703.         strcat (shell_command, " 2>&1"); /* redirect stderr to stdout */
  704.  /*
  705.   * open os2 pipe for system level command.
  706.   */
  707.      //pipe_stream = _popen (argv[3], "rb");   
  708.     pipe_stream = _popen (shell_command, "rb");   
  709.     if (pipe_stream == NULL) 
  710.         complain ("Spawn failed");
  711.     else
  712.         retcode = 0;
  713.     fd_pipe = fileno (pipe_stream);
  714.     fp = fd_open(argv[1], F_READ, fd_pipe, iobuff, LBSIZE);
  715. #endif /* MSDOS */
  716.     do {
  717. #ifndef MSDOS
  718.         inIOread = 1;
  719. #endif
  720.         eof = f_gets(fp, genbuf, (size_t)LBSIZE);
  721. #ifndef MSDOS
  722.         inIOread = 0;
  723. #endif
  724.         if (bnm != 0) {
  725.             ins_str(genbuf, YES);
  726.             if (!eof)
  727.                 LineInsert(1);
  728.         } else if (disp == YES)
  729.             Typeout("%s", genbuf);
  730.         if (bnm != 0 && disp != 0 && fp->f_cnt <= 0) {
  731. #ifdef LOAD_AV
  732.             {
  733.             double    theavg;
  734.  
  735.             get_la(&theavg);
  736.             if (theavg < 2.0)
  737.                 mess = "Screaming along...";
  738.             else if (theavg < 5.0)
  739.                 mess = "Chugging along...";
  740.             else
  741.                 mess = "Crawling along...";
  742.             }
  743. #else
  744.             mess = "Chugging along...";
  745. #endif /* LOAD_AV */
  746.             if (bnm != 0) {
  747.                 message(mess);
  748.                 redisplay();
  749.             }
  750.         }
  751.     } while (!eof);
  752.     if (disp)
  753.         DrawMesg(NO);
  754.     close_file(fp);
  755.     os2_kbd_open();
  756. #ifndef MSDOS
  757.     dowait(pid, &status);
  758. # ifdef JOB_CONTROL
  759.     (void) SigRelse(SIGINT);
  760. # endif
  761. #else /* MSDOS */
  762.         _pclose (pipe_stream);
  763. #endif /* MSDOS */
  764.     (void) signal(SIGINT, old_int);
  765. #ifndef MSDOS
  766. # ifdef IPROCS
  767.     SigRelse(SIGCHLD);
  768. # endif
  769.     return status;
  770. #else /* MSDOS */
  771.     getCWD();
  772.     return retcode ;
  773. #endif /* MSDOS */
  774. }
  775.  
  776. /* Send the current region to CMD and insert the output from the
  777.    command into OUT_BUF. */
  778.  
  779. /****************************************************/
  780. void _fastcall RegToUnix (Buffer *outbuf, char *cmd)
  781. /****************************************************/
  782. {
  783.     Mark    *m = CurMark();
  784.     static char     tnambuf[20];
  785.     char    *tname,
  786.         combuf[128];
  787.     Window    *save_wind = curwind;
  788.     int    status,
  789.         err = NO;
  790.     File    *fp;
  791.  
  792.     strcpy (tnambuf, "/tmp/jfilterXXXXXX");
  793.     tname = mktemp(tnambuf);
  794.     fp = open_file(tname, iobuff, F_WRITE, YES, YES);
  795.     CATCH
  796.     putreg(fp, m->m_line, m->m_char, curline, curchar, YES);
  797.     DelReg();
  798.     swritef(combuf, "%s < %s", cmd, tname);
  799.     status = UnixToBuf(outbuf->b_name, NO, 0, outbuf->b_type == B_SCRATCH,
  800.                Shell, ShFlags, combuf, (char *) 0);
  801.     ONERROR
  802.     err = YES;
  803.     ENDCATCH
  804.     f_close(fp);
  805.     (void) unlink(tname);
  806.     SetWind(save_wind);
  807.     if (err == NO)
  808.     com_finish(status, combuf);
  809. }
  810.  
  811. void
  812. FilterRegion()
  813. {
  814.     static char    FltComBuf[LBSIZE];
  815.  
  816.     null_ncpy(FltComBuf, ask(FltComBuf, ": %f (through command) "),
  817.         (sizeof FltComBuf) - 1);
  818.     RegToUnix(curbuf, FltComBuf);
  819. }
  820.  
  821. /***********************************/
  822. void _fastcall isprocbuf(char *bnm)
  823. /***********************************/
  824. {
  825.     Buffer    *bp;
  826.  
  827.     if ((bp = buf_exists(bnm)) != 0 && bp->b_type != B_PROCESS)
  828.         confirm("Over-write buffer %s?", bnm);
  829. }
  830.  
  831. #ifdef MSDOS
  832.  
  833. private void
  834. closepipe()
  835. {
  836. }
  837.  
  838. openforpipe()
  839. {
  840. }
  841.  
  842. private int
  843. reopenforpipe()
  844. {
  845. }
  846.  
  847. char
  848. switchar()
  849. {
  850.   return ('/');
  851. }
  852. #endif /* MSDOS */
  853.