home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / VILE327.ZIP / VILE327.TAR / vile3.27 / spawn.c < prev    next >
C/C++ Source or Header  |  1992-12-14  |  24KB  |  975 lines

  1. /*    Spawn:    various DOS access commands
  2.  *        for MicroEMACS
  3.  *
  4.  * $Log: spawn.c,v $
  5.  * Revision 1.35  1992/12/04  09:51:54  foxharp
  6.  * linux apparently has strict prototypes
  7.  *
  8.  * Revision 1.34  1992/12/04  09:19:17  foxharp
  9.  * reopen and flush the tty after returning from the shell, and
  10.  * don't wait for children at this level when filtering
  11.  *
  12.  * Revision 1.33  1992/12/03  00:32:59  foxharp
  13.  * use new mlreply_no_bs, so backslashes go to commands unchanges.  also,
  14.  * use new system_SHELL routine, and exec_sh_c routine to spawn processes
  15.  *
  16.  * Revision 1.32  1992/08/21  18:18:19  foxharp
  17.  * cleaned up job control -- sort of.  how can I tell if someone wants
  18.  * the arg to getpgrp or not, since if they don't want it, their prototypes
  19.  * will get me...
  20.  *
  21.  * Revision 1.31  1992/08/20  23:40:48  foxharp
  22.  * typo fixes -- thanks, eric
  23.  *
  24.  * Revision 1.30  1992/08/19  23:02:01  foxharp
  25.  * send SIGTSTP to whole pgrp, not just to pid
  26.  *
  27.  * Revision 1.29  1992/07/07  08:37:13  foxharp
  28.  * wait() for child in filterregion()
  29.  *
  30.  * Revision 1.28  1992/06/25  23:00:50  foxharp
  31.  * changes for dos/ibmpc
  32.  *
  33.  * Revision 1.27  1992/06/01  21:23:40  foxharp
  34.  * fix ret codes on bktoshell and rtfrmshell
  35.  *
  36.  * Revision 1.26  1992/06/01  20:43:10  foxharp
  37.  * bktoshell() and rtfrmshell() are now always defined, but may be null
  38.  * if not supported
  39.  *
  40.  * Revision 1.25  1992/05/25  21:34:29  foxharp
  41.  * added f,n args to bktoshell command
  42.  *
  43.  * Revision 1.23  1992/05/19  08:55:44  foxharp
  44.  * more prototype and shadowed decl fixups
  45.  *
  46.  * Revision 1.22  1992/05/16  14:02:55  pgf
  47.  * header/typedef fixups
  48.  *
  49.  * Revision 1.21  1992/05/16  12:00:31  pgf
  50.  * prototypes/ansi/void-int stuff/microsoftC
  51.  *
  52.  * Revision 1.20  1992/05/13  09:13:04  pgf
  53.  * don't need return() from void signal handler (rtfrmshell)
  54.  *
  55.  * Revision 1.19  1992/04/14  08:54:02  pgf
  56.  * removed #if UNIX from pressreturn
  57.  *
  58.  * Revision 1.18  1992/03/19  23:26:04  pgf
  59.  * SIGT for signals
  60.  *
  61.  * Revision 1.17  1992/03/05  09:19:55  pgf
  62.  * changed some mlwrite() to mlforce(), due to new terse support
  63.  *
  64.  * Revision 1.16  1992/01/05  00:06:13  pgf
  65.  * split mlwrite into mlwrite/mlprompt/mlforce to make errors visible more
  66.  * often.  also normalized message appearance somewhat.
  67.  *
  68.  * Revision 1.15  1992/01/03  23:31:49  pgf
  69.  * use new ch_fname() to manipulate filenames, since b_fname is now
  70.  * a malloc'ed sting, to avoid length limits
  71.  *
  72.  * Revision 1.14  1991/11/16  18:38:21  pgf
  73.  * use UNIX ifdef instead of BSD|USG
  74.  *
  75.  * Revision 1.13  1991/11/13  20:09:27  pgf
  76.  * X11 changes, from dave lemke
  77.  *
  78.  * Revision 1.12  1991/11/03  17:46:30  pgf
  79.  * removed f,n args from all region functions -- they don't use them,
  80.  * since they're no longer directly called by the user
  81.  *
  82.  * Revision 1.11  1991/11/01  14:38:00  pgf
  83.  * saber cleanup
  84.  *
  85.  * Revision 1.10  1991/09/13  01:47:59  pgf
  86.  * child now runs and exits correctly if there is no input for it in
  87.  * filterregion
  88.  *
  89.  * Revision 1.9  1991/08/07  12:35:07  pgf
  90.  * added RCS log messages
  91.  *
  92.  * revision 1.8
  93.  * date: 1991/08/06 15:25:58;
  94.  *  global/local values
  95.  * and sprintf changes
  96.  * 
  97.  * revision 1.7
  98.  * date: 1991/06/25 19:53:29;
  99.  * massive data structure restructure
  100.  * 
  101.  * revision 1.6
  102.  * date: 1991/05/30 16:10:14;
  103.  * added extern decl for getenv()
  104.  * 
  105.  * revision 1.5
  106.  * date: 1991/04/22 09:03:37;
  107.  * removed non-portable initialization
  108.  * 
  109.  * revision 1.4
  110.  * date: 1991/04/08 15:46:56;
  111.  * fixed readin() arg count
  112.  * 
  113.  * revision 1.3
  114.  * date: 1991/04/04 09:43:21;
  115.  * added filterregion
  116.  * 
  117.  * revision 1.2
  118.  * date: 1990/12/06 18:53:59;
  119.  * added abortc to list that will terminate pressreturn
  120.  * 
  121.  * revision 1.1
  122.  * date: 1990/09/21 10:26:01;
  123.  * initial vile RCS revision
  124.  */
  125.  
  126. #include    "estruct.h"
  127. #include        "edef.h"
  128. #include        <stdio.h>
  129. #if UNIX
  130. #include    <sys/stat.h>
  131. #endif
  132.  
  133. #if     AMIGA
  134. #define  NEW   1006L
  135. #endif
  136.  
  137. #if        ST520 & MEGAMAX
  138. #include <osbind.h>
  139. #include <string.h>
  140. #define LOAD_EXEC 0     /* load and execute the program */
  141. char    *STcmd,        /* the command filename & path  */
  142.     *STargs,    /* command args (if any)        */
  143.     *STenv,        /* environment                  */
  144.     *STwork;    /* work area            */
  145. #endif
  146.  
  147. #if     VMS
  148. #define EFN     0                               /* Event flag.          */
  149.  
  150. #include        <ssdef.h>                       /* Random headers.      */
  151. #include        <stsdef.h>
  152. #include        <descrip.h>
  153. #include        <iodef.h>
  154.  
  155. extern  int     oldmode[3];                     /* In "termio.c"        */
  156. extern  int     newmode[3];                     /* In "termio.c"        */
  157. extern  short   iochan;                         /* In "termio.c"        */
  158. #endif
  159.  
  160. #if     UNIX
  161. #include        <signal.h>
  162. #include        <string.h>
  163. #endif
  164.  
  165. #if    MSDOS & (MSC | TURBO | ZTC)
  166. #include    <process.h>
  167. #endif
  168.  
  169. /*
  170.  * Create a subjob with a copy of the command interpreter in it. When the
  171.  * command interpreter exits, mark the screen as garbage so that you do a full
  172.  * repaint. The message at the start in VMS puts out a newline.
  173.  * Under some (unknown) condition, you don't get one free when DCL starts up.
  174.  */
  175. /* ARGSUSED */
  176. int
  177. spawncli(f, n)
  178. int f,n;
  179. {
  180. #if     UNIX
  181. # if     NeWS
  182.     mlforce("[Not available under NeWS]");
  183.     return(FALSE);
  184. # else
  185. #  if     X11
  186.     mlforce("[Not available under X11]");
  187.     return(FALSE);
  188. #  else
  189.         char    *getenv();
  190.         
  191.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  192.     ttclean(TRUE);
  193.         TTputc('\n');
  194.     system_SHELL(NULL);
  195.         TTflush();
  196.     ttunclean();
  197.         sgarbf = TRUE;
  198.         return(TRUE);
  199. #  endif /* X11 */
  200. # endif /* News */
  201. #endif /* UNIX */
  202.  
  203. #if    AMIGA
  204.         long newcli;
  205.         mlwrite("[Starting new CLI]");
  206.         Execute("NEWCLI \"CON:0/0/640/200/MicroEMACS Subprocess\"", 0L, 0L);
  207.         sgarbf = TRUE;
  208.         return(TRUE);
  209. #endif
  210.  
  211. #if     VMS
  212.         movecursor(term.t_nrow, 0);             /* In last line.        */
  213.         mlforce("[Starting DCL]\r\n");
  214.         TTflush();                          /* Ignore "ttcol".      */
  215.     s = sys(NULL);                     /* NULL => DCL.         */
  216.         sgarbf = TRUE;
  217.         return (s);
  218. #endif
  219. #if     CPM
  220.         mlforce("[Not in CP/M-86]");
  221.     return FALSE;
  222. #endif
  223. #if    ST520
  224.     mlforce("[Not in TOS]");
  225.     return FALSE;
  226. #endif
  227. #if     MSDOS & (AZTEC | MSC | TURBO | ZTC)
  228.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  229.         TTflush();
  230.     TTkclose();
  231.     system("command.com");
  232.     TTkopen();
  233.         sgarbf = TRUE;
  234.         return(TRUE);
  235. #endif
  236. #if     MSDOS & LATTICE
  237.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  238.         TTflush();
  239.     TTkclose();
  240.         sys("\\command.com", "");               /* Run CLI.             */
  241.     TTkopen();
  242.         sgarbf = TRUE;
  243.         return(TRUE);
  244. #endif
  245. }
  246.  
  247.  
  248. /* ARGSUSED */
  249. int
  250. bktoshell(f,n)        /* suspend and wait to wake up */
  251. int f,n;
  252. {
  253. #if UNIX && defined(SIGTSTP) && !X11  && !NeWS
  254.     vttidy(TRUE);
  255. # if BERK
  256.     killpg(getpgrp(0), SIGTSTP);
  257. # else
  258. #  if AIX || LINUX /* strict prototypes -- doesn't like the (0) */
  259.     kill(-getpgrp(), SIGTSTP);
  260. #  else
  261.     kill(-getpgrp(0), SIGTSTP);
  262. #  endif
  263. #endif
  264.     return TRUE;
  265. #else
  266.     mlforce("[Job control unavailable]");
  267.     return FALSE;
  268. #endif /* SIGTSTP */
  269. }
  270.  
  271. SIGT
  272. rtfrmshell(signo)
  273. int signo;
  274. {
  275. #if UNIX && defined(SIGTSTP)
  276. # if ! X11
  277.     ttunclean();
  278.     curwp->w_flag = WFHARD;  /* is this needed, with sgarbf == TRUE? */
  279.     sgarbf = TRUE;
  280. # if USG
  281.     signal(SIGCONT,rtfrmshell);    /* suspend & restart */
  282.     update(TRUE);
  283. # endif
  284. # endif
  285. #endif
  286.     SIGRET;
  287. }
  288.  
  289. void
  290. pressreturn()
  291. {
  292.     int s;
  293.  
  294.         mlprompt("[Press return to continue]");
  295.         TTflush();
  296.     /* loop for a CR, a space, or a : to do another named command */
  297.         while ((s = kbd_key()) != '\r' && s != ' ' && s != kcod2key(abortc)) {
  298.         extern CMDFUNC f_namedcmd;
  299.                 if (kcod2fnc(s) == &f_namedcmd) {
  300.             tungetc(kcod2key(s));
  301.             break;
  302.         }
  303.     }
  304.     TTputc('\r');
  305.     TTputc('\n');
  306. }
  307.  
  308. /* ARGSUSED */
  309. int
  310. respawn(f,n)
  311. int f,n;
  312. {
  313.     return spawn1(TRUE);
  314. }
  315.  
  316. /* ARGSUSED */
  317. int
  318. spawn(f,n)
  319. int f,n;
  320. {
  321.     return spawn1(FALSE);
  322. }
  323.  
  324. /*
  325.  * Run a one-liner in a subjob. When the command returns, wait for a single
  326.  * character to be typed, then mark the screen as garbage so a full repaint is
  327.  * done.
  328.  */
  329. /* the #ifdefs have been totally separated, for readability */
  330. int
  331. spawn1(rerun)
  332. int rerun;
  333. {
  334.  
  335. #if  UNIX
  336.         register int    s;
  337.         static char oline[NLINE];    /* command line send to shell */
  338.         char    line[NLINE];    /* command line send to shell */
  339.     int cb;
  340.     char prompt[50];
  341.     char *getenv();
  342.  
  343.     if (!rerun) {
  344.         cb = anycb();
  345.         if (cb)
  346.             lsprintf(prompt,"Warning: %d modified buffer%s: !",
  347.                 cb, cb>1 ? "s":"");
  348.         else
  349.             lsprintf(prompt,": !");
  350.  
  351.             if ((s=mlreply_no_bs(prompt, oline, NLINE)) != TRUE)
  352.                     return (s);
  353.     } else {
  354.         if (!oline[0])
  355.             return FALSE;
  356.         mlwrite(": !%s",oline);
  357.     }
  358.     strcpy(line,oline);
  359.  
  360. #if    NeWS || X11
  361.     system_SHELL(line);
  362. #else
  363.     ttclean(TRUE);
  364.     system_SHELL(line);
  365.         TTflush();
  366.     ttunclean();
  367.     pressreturn();
  368.     TTopen();
  369.     TTflush();
  370.         sgarbf = TRUE;
  371. #endif /* NeWS */
  372.         return (TRUE);
  373. #endif /* UNIX */
  374.  
  375. #if     AMIGA
  376.         register int    s;
  377.         static char oline[NLINE];    /* command line send to shell */
  378.         char    line[NLINE];    /* command line send to shell */
  379.     register char    *cp;
  380.     char        line2[NLINE];
  381.         long newcli;
  382.  
  383.  
  384.         if ((s=mlreply("cmd: !", oline, NLINE)) != TRUE)
  385.                 return (s);
  386.     strcpy(line,oline);
  387.         newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW);
  388.         Execute(line, 0L, newcli);
  389.         Close(newcli);
  390.         tgetc();     /* Pause.               */
  391.         sgarbf = TRUE;
  392.         return(TRUE);
  393. #endif
  394. #if    ST520 & MEGAMAX
  395.         register int    s;
  396.         static char oline[NLINE];    /* command line send to shell */
  397.         char    line[NLINE];    /* command line send to shell */
  398.     register char    *cp;
  399.     char        line2[NLINE];
  400.  
  401.     int i,j,k;
  402.     char *sptr,*tptr;
  403.  
  404.         if ((s=mlreply("cmd: !", oline, NLINE)) != TRUE)
  405.                 return(s);
  406.     strcpy(line,oline);
  407.     movecursor(term.t_nrow - 1, 0);
  408.     TTclose();
  409.     /*
  410.      * break the line into the command and its args
  411.      * be cute about it, if there is no '.' in the filename, try
  412.      * to find .prg, .tos or .ttp in that order
  413.      * in any case check to see that the file exists before we run 
  414.      * amok
  415.      */
  416.     STenv = NULL;
  417.     if((tptr = index(&line[0],' ')) == NULL) { /* no args */
  418.         STcmd = malloc(strlen(line) + 1);
  419.         strcpy(STcmd,line);
  420.         STargs = NULL;
  421.     }
  422.     else {  /* separate out the args from the command */
  423.         /* resist the temptation to do ptr arithmetic */
  424.         STcmd = malloc(strlen(line) + 1);
  425.         for(i = 0,sptr = &line[0]; sptr != tptr; sptr++,i++)
  426.             STcmd[i] = *sptr;
  427.         STcmd[i] = '\0';
  428.         for(; *tptr == ' ' || *tptr == '\t'; tptr++);
  429.         if(*tptr == '\0')
  430.             STargs = NULL;
  431.         else {
  432.             STargs = malloc(strlen(tptr) + 2);
  433. /* first byte of STargs is the length of the string */
  434.             STargs[0] = strlen(tptr);
  435.             STargs[1] = NULL; /* fake it for strcat */
  436.             strcat(STargs,tptr);
  437.         }
  438.     }
  439.     /*
  440.      * before we issue the command look for the '.', if it's not there
  441.      * try adding .prg, .tos and .ttp to see if they exist, if not
  442.      * issue the command as is
  443.      */
  444.     if((tptr = index(STcmd,'.')) == NULL) {
  445.          STwork = malloc(strlen(STcmd) + 4);
  446.          strcpy(STwork,STcmd);
  447.          strcat(STwork,".prg");
  448.          tptr = index(STwork,'.');
  449.          if(Fsfirst(1,STwork) != 0) { /* try .tos */
  450.              strcpy(tptr,".tos");
  451.              if(Fsfirst(1,STwork) != 0) { /* try .ttp */
  452.                  strcpy(tptr,".ttp");
  453.                  if(Fsfirst(1,STwork) != 0) /* never mind */
  454.                      *STwork = NULL;
  455.                  }
  456.              }
  457.      }
  458.      if(*STwork != NULL)
  459.             Pexec(LOAD_EXEC,STwork,STargs,STenv);         
  460.     else
  461.             Pexec(LOAD_EXEC,STcmd,STargs,STenv);
  462.     TTopen();
  463.         mlforce("\r\n\n[End]");                  /* Pause.               */
  464.         TTgetc();                 /* Pause.               */
  465.         sgarbf = TRUE;
  466.         return (TRUE);
  467. #endif
  468. #if     VMS
  469.         register int    s;
  470.         static char oline[NLINE];    /* command line send to shell */
  471.         char    line[NLINE];    /* command line send to shell */
  472.     register char    *cp;
  473.     char        line2[NLINE];
  474.  
  475.  
  476.         if ((s=mlreply("cmd: !", oline, NLINE)) != TRUE)
  477.                 return (s);
  478.     strcpy(line,oline);
  479.         TTputc('\n');                /* Already have '\r'    */
  480.         TTflush();
  481.         s = sys(line);                          /* Run the command.     */
  482.         mlforce("\r\n\n[End]");                  /* Pause.               */
  483.         TTflush();
  484.         tgetc();
  485.         sgarbf = TRUE;
  486.         return (s);
  487. #endif
  488. #if     CPM
  489.         mlforce("[Not in CP/M-86]");
  490.         return (FALSE);
  491. #endif
  492. #if     MSDOS | (ST520 & LATTICE)
  493.         register int    s;
  494.         static char oline[NLINE];    /* command line send to shell */
  495.         char    line[NLINE];    /* command line send to shell */
  496.     register char    *cp;
  497.     char        line2[NLINE];
  498.  
  499.  
  500.         if ((s=mlreply("cmd: !", oline, NLINE)) != TRUE)
  501.                 return(s);
  502.     strcpy(line,oline);
  503.     movecursor(term.t_nrow - 1, 0);
  504.     TTkclose();
  505.         system(line);
  506.     TTkopen();
  507.     /* if we are interactive, pause here */
  508.     if (clexec == FALSE) {
  509.             mlforce("\r\n\n[End]");
  510.             tgetc();
  511.         }
  512.         sgarbf = TRUE;
  513.         return (TRUE);
  514. #endif
  515. }
  516.  
  517. #if UNIX
  518. /*
  519.  * Pipe a one line command into a window
  520.  */
  521. /* ARGSUSED */
  522. int
  523. pipecmd(f, n)
  524. int f,n;
  525. {
  526.     register BUFFER *bp;    /* pointer to buffer to zot */
  527.         static char oline[NLINE];    /* command line send to shell */
  528.         register int    s;
  529.     static char bname[] = "[Output]";
  530.     int cb;
  531.     char prompt[50];
  532.  
  533.  
  534.     /* if it doesn't start with '!', or if that's all it is */
  535.     if (oline[0] != '!' || oline[1] == '\0') {
  536.         oline[0] = '!';
  537.         oline[1] = '\0';
  538.     }
  539.  
  540.     cb = anycb();
  541.     if (cb)
  542.         lsprintf(prompt,"Warning: %d modified buffer%s. !",
  543.             cb, cb>1 ? "s":"");
  544.     else
  545.         lsprintf(prompt,"!");
  546.         
  547.     /* get the command to pipe in */
  548.         if ((s=mlreply_no_bs(prompt, &oline[1], NLINE)) != TRUE)
  549.                 return(s);
  550.  
  551.     /* first check if we are already here */
  552.     bp = bfind(bname, OK_CREAT, 0);
  553.     if (bp == NULL)
  554.         return FALSE;
  555.  
  556.     make_local_b_val(bp,MDCMOD);
  557.     set_b_val(bp,MDCMOD,FALSE);
  558.  
  559.     make_local_b_val(bp,MDDOS);
  560.     set_b_val(bp,MDDOS,FALSE);
  561.  
  562.     make_local_b_val(bp,MDVIEW);
  563.     set_b_val(bp,MDVIEW,TRUE);
  564.  
  565.     /* and read the stuff in */
  566.     if (popupbuff(bp) != TRUE || 
  567.         swbuffer(bp) != TRUE ||
  568.         readin(oline, FALSE, bp, TRUE) != TRUE) {
  569.         return(FALSE);
  570.     }
  571.     strcpy(bp->b_bname,bname);
  572.     ch_fname(bp, oline);
  573.  
  574.     return TRUE;
  575. }
  576.  
  577. #else /* ! UNIX */
  578.  
  579. /*
  580.  * Pipe a one line command into a window
  581.  */
  582. int
  583. pipecmd(f, n)
  584. {
  585.         register int    s;    /* return status from CLI */
  586.     register WINDOW *wp;    /* pointer to new window */
  587.     register BUFFER *bp;    /* pointer to buffer to zot */
  588.         static char oline[NLINE];    /* command line send to shell */
  589.         char    line[NLINE];    /* command line send to shell */
  590.     static char bname[] = "[output]";
  591.     WINDOW *ocurwp;        /* save the current window during delete */
  592.  
  593. #if    AMIGA
  594.     static char filnam[] = "ram:command";
  595.         long newcli;
  596. #else
  597.     static char filnam[NSTRING] = "command";
  598. #endif
  599.  
  600. #if    MSDOS
  601.     char *tmp;
  602.     char *getenv();
  603.     FILE *fp;
  604.     FILE *fopen();
  605. #endif
  606.  
  607. #if    MSDOS
  608.     if ((tmp = getenv("TMP")) == NULL)
  609.         strcpy(filnam, "command");
  610.     else {
  611.         strcpy(filnam, tmp);
  612.                 strcat(filnam,"\\command");
  613.         }
  614. #endif
  615. #if     VMS
  616.     mlforce("[Not available under VMS]");
  617.     return(FALSE);
  618. #endif
  619. #if     CPM
  620.         mlforce("[Not available under CP/M-86]");
  621.         return(FALSE);
  622. #endif
  623.     /* get the command to pipe in */
  624.         if ((s=mlreply("cmd: <", oline, NLINE)) != TRUE)
  625.                 return(s);
  626.  
  627.     strcpy(line,oline);
  628.  
  629.     /* get rid of the command output buffer if it exists */
  630.         if ((bp=bfind(bname, NO_CREAT, 0)) != FALSE) {
  631.         /* try to make sure we are off screen */
  632.         wp = wheadp;
  633.         ocurwp = NULL;
  634.         while (wp != NULL) {
  635.             if (wp->w_bufp == bp) {
  636.                 if (curwp != wp) {
  637.                     ocurwp = curwp;
  638.                     curwp = wp;
  639.                 }
  640.                 delwind(FALSE, 1);
  641.                 if (ocurwp != NULL)
  642.                     curwp = ocurwp;
  643.                 break;
  644.             }
  645.             wp = wp->w_wndp;
  646.         }
  647.         if (zotbuf(bp) != TRUE)
  648.  
  649.             return(FALSE);
  650.     }
  651.  
  652. #if     AMIGA
  653.         newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW);
  654.     strcat(line, " >");
  655.     strcat(line, filnam);
  656.         Execute(line, 0L, newcli);
  657.     s = TRUE;
  658.         Close(newcli);
  659.         sgarbf = TRUE;
  660. #endif
  661. #if     MSDOS
  662.     strcat(line," >>");
  663.     strcat(line,filnam);
  664.     movecursor(term.t_nrow - 1, 0);
  665.     TTkclose();
  666.         system(line);
  667.     TTkopen();
  668.         sgarbf = TRUE;
  669.     if ((fp = fopen(filnam, "r")) == NULL) {
  670.         s = FALSE;
  671.     } else {
  672.         fclose(fp);
  673.         s = TRUE;
  674.     }
  675. #endif
  676.  
  677.     if (s != TRUE)
  678.         return(s);
  679.  
  680.     /* split the current window to make room for the command output */
  681.     if (splitwind(FALSE, 1) == FALSE)
  682.             return(FALSE);
  683.  
  684.     /* and read the stuff in */
  685.     if (getfile(filnam, FALSE) == FALSE)
  686.         return(FALSE);
  687.  
  688.     /* make this window in VIEW mode, update all mode lines */
  689.     make_local_b_val(curwp->w_bufp,MDVIEW);
  690.     set_b_val(curwp->w_bufp,MDVIEW,TRUE);
  691.     wp = wheadp;
  692.     while (wp != NULL) {
  693.         wp->w_flag |= WFMODE;
  694.         wp = wp->w_wndp;
  695.     }
  696.  
  697. #if FINDERR
  698.     strcpy(febuff,"[Cmd Output]");
  699.     newfebuff = TRUE;
  700. #endif
  701.  
  702.     /* and get rid of the temporary file */
  703.     unlink(filnam);
  704.     return(TRUE);
  705. }
  706. #endif /* UNIX */
  707.  
  708. /* run a region through an external filter, replace it with its output */
  709. int
  710. filterregion()
  711. {
  712. #if UNIX
  713.         static char oline[NLINE];    /* command line send to shell */
  714.         char    line[NLINE];    /* command line send to shell */
  715.     FILE *fr, *fw;
  716.     int s;
  717.  
  718.     /* get the filter name and its args */
  719.         if ((s=mlreply_no_bs("!", oline, NLINE)) != TRUE)
  720.                 return(s);
  721.     strcpy(line,oline);
  722.     if ((s = inout_popen(&fr, &fw, line)) != TRUE) {
  723.         mlforce("[Couldn't open pipe or command]");
  724.         return s;
  725.     }
  726.  
  727.     killregion();
  728.     if (!softfork()) {
  729.         KILL *kp;        /* pointer into kill register */
  730.         kregcirculate(FALSE);
  731.         kp = kbs[ukb].kbufh;
  732.         while (kp != NULL) {
  733.             if (kp->d_next == NULL)
  734.                 fwrite((char *)kp->d_chunk, 1, kbs[ukb].kused, fw);
  735.             else
  736.                 fwrite((char *)kp->d_chunk, 1, KBLOCK, fw);
  737.             kp = kp->d_next;
  738.         }
  739.         fflush(fw);
  740.         fclose(fw);
  741.         exit (0);
  742.         /* NOTREACHED */
  743.     }
  744.     fclose(fw);
  745.     DOT.l = lback(DOT.l);
  746.     s = ifile(NULL,TRUE,fr);
  747.     npclose(fr);
  748.     firstnonwhite(FALSE,1);
  749.     setmark();
  750.     return s;
  751. #else
  752.     mlforce("[Region filtering not available]");
  753. #endif
  754. }
  755.  
  756. /*
  757.  * filter a buffer through an external DOS program
  758.  * this is obsolete, the filterregion code is better.
  759.  */
  760. /* ARGSUSED */
  761. int
  762. filter(f, n)
  763. int f,n;
  764. {
  765.         register int    s;    /* return status from CLI */
  766.     register BUFFER *bp;    /* pointer to buffer to zot */
  767.         static char oline[NLINE];    /* command line send to shell */
  768.         char    line[NLINE];    /* command line send to shell */
  769.     char tnam[NFILEN];    /* place to store real file name */
  770.     static char bname1[] = "fltinp";
  771.  
  772. #if    AMIGA
  773.     static char filnam1[] = "ram:fltinp";
  774.     static char filnam2[] = "ram:fltout";
  775.         long newcli;
  776. #else
  777.     static char filnam1[] = "fltinp";
  778.     static char filnam2[] = "fltout";
  779. #endif
  780.  
  781. #if     VMS
  782.     mlforce("[Not available under VMS]");
  783.     return(FALSE);
  784. #endif
  785. #if     CPM
  786.         mlforce("[Not available under CP/M-86]");
  787.         return(FALSE);
  788. #endif
  789.     /* get the filter name and its args */
  790.         if ((s=mlreply("cmd: |", oline, NLINE)) != TRUE)
  791.                 return(s);
  792.     strcpy(line,oline);
  793.  
  794.     /* setup the proper file names */
  795.     bp = curbp;
  796.     strcpy(tnam, bp->b_fname);    /* save the original name */
  797.     ch_fname(bp, bname1);        /* set it to our new one */
  798.  
  799.     /* write it out, checking for errors */
  800.     if (writeout(filnam1,curbp,TRUE) != TRUE) {
  801.         mlforce("[Cannot write filter file]");
  802.         ch_fname(bp, tnam);
  803.         return(FALSE);
  804.     }
  805.  
  806. #if     AMIGA
  807.         newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW);
  808.     strcat(line, " <ram:fltinp >ram:fltout");
  809.         Execute(line,0L,newcli);
  810.     s = TRUE;
  811.         Close(newcli);
  812.         sgarbf = TRUE;
  813. #endif
  814. #if     MSDOS
  815.     strcat(line," <fltinp >fltout");
  816.     movecursor(term.t_nrow - 1, 0);
  817.     TTkclose();
  818.         system(line);
  819.     TTkopen();
  820.         sgarbf = TRUE;
  821.     s = TRUE;
  822. #endif
  823. #if     UNIX
  824. #if    ! NeWS
  825.         ttclean(TRUE);
  826. #endif
  827.     strcat(line," <fltinp >fltout");
  828.         system(line);
  829. #if    ! NeWS
  830.         ttunclean();
  831.         TTflush();
  832.         sgarbf = TRUE;
  833. #endif
  834.        s = TRUE;
  835. #endif
  836.  
  837.     /* on failure, escape gracefully */
  838.     if (s != TRUE || (readin(filnam2,FALSE,curbp,TRUE) == FALSE)) {
  839.         mlforce("[Execution failed]");
  840.         ch_fname(bp, tnam);
  841.         unlink(filnam1);
  842.         unlink(filnam2);
  843.         return(s);
  844.     }
  845.  
  846.     ch_fname(bp, tnam); /* restore name */
  847.     bp->b_flag |= BFCHG;        /* flag it as changed */
  848.  
  849.     /* and get rid of the temporary file */
  850.     unlink(filnam1);
  851.     unlink(filnam2);
  852.     return(TRUE);
  853. }
  854.  
  855. #if     VMS
  856. /*
  857.  * Run a command. The "cmd" is a pointer to a command string, or NULL if you
  858.  * want to run a copy of DCL in the subjob (this is how the standard routine
  859.  * LIB$SPAWN works. You have to do wierd stuff with the terminal on the way in
  860.  * and the way out, because DCL does not want the channel to be in raw mode.
  861.  */
  862. int
  863. sys(cmd)
  864. register char   *cmd;
  865. {
  866.         struct  dsc$descriptor  cdsc;
  867.         struct  dsc$descriptor  *cdscp;
  868.         long    status;
  869.         long    substatus;
  870.         long    iosb[2];
  871.  
  872.         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  873.                           oldmode, sizeof(oldmode), 0, 0, 0, 0);
  874.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  875.                 return (FALSE);
  876.         cdscp = NULL;                           /* Assume DCL.          */
  877.         if (cmd != NULL) {                      /* Build descriptor.    */
  878.                 cdsc.dsc$a_pointer = cmd;
  879.                 cdsc.dsc$w_length  = strlen(cmd);
  880.                 cdsc.dsc$b_dtype   = DSC$K_DTYPE_T;
  881.                 cdsc.dsc$b_class   = DSC$K_CLASS_S;
  882.                 cdscp = &cdsc;
  883.         }
  884.         status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0);
  885.         if (status != SS$_NORMAL)
  886.                 substatus = status;
  887.         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  888.                           newmode, sizeof(newmode), 0, 0, 0, 0);
  889.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  890.                 return (FALSE);
  891.         if ((substatus&STS$M_SUCCESS) == 0)     /* Command failed.      */
  892.                 return (FALSE);
  893.         return (TRUE);
  894. }
  895. #endif
  896.  
  897. #if    ~AZTEC & ~MSC & ~TURBO & ~ZTC & MSDOS
  898.  
  899. /*
  900.  * This routine, once again by Bob McNamara, is a C translation of the "system"
  901.  * routine in the MWC-86 run time library. It differs from the "system" routine
  902.  * in that it does not unconditionally append the string ".exe" to the end of
  903.  * the command name. We needed to do this because we want to be able to spawn
  904.  * off "command.com". We really do not understand what it does, but if you don't
  905.  * do it exactly "malloc" starts doing very very strange things.
  906.  */
  907. int
  908. sys(cmd, tail)
  909. char    *cmd;
  910. char    *tail;
  911. {
  912. #if MWC86
  913.         register unsigned n;
  914.         extern   char     *__end;
  915.  
  916.         n = __end + 15;
  917.         n >>= 4;
  918.         n = ((n + dsreg() + 16) & 0xFFF0) + 16;
  919.         return(execall(cmd, tail, n));
  920. #endif
  921.  
  922. #if LATTICE
  923.         return(forklp(cmd, tail, (char *)NULL));
  924. #endif
  925. }
  926. #endif
  927.  
  928. #if    MSDOS & LATTICE
  929. /*    System: a modified version of lattice's system() function
  930.         that detects the proper switchar and uses it
  931.         written by Dana Hogget                */
  932.  
  933. int
  934. system(cmd)
  935.  
  936. char *cmd;    /*  Incoming command line to execute  */
  937.  
  938. {
  939.     char *getenv();
  940.     static char *swchar = "/C";    /*  Execution switch  */
  941.     union REGS inregs;    /*  parameters for dos call  */
  942.     union REGS outregs;    /*  Return results from dos call  */
  943.     char *shell;        /*  Name of system command processor  */
  944.     char *p;        /*  Temporary pointer  */
  945.     int ferr;        /*  Error condition if any  */
  946.  
  947.     /*  get name of system shell  */
  948.     if ((shell = getenv("COMSPEC")) == NULL) {
  949.         return (-1);        /*  No shell located  */
  950.     }
  951.  
  952.     p = cmd;
  953.     while (isspace(*p)) {        /*  find out if null command */
  954.         p++;
  955.     }
  956.  
  957.     /**  If the command line is not empty, bring up the shell  **/
  958.     /**  and execute the command.  Otherwise, bring up the     **/
  959.     /**  shell in interactive mode.   **/
  960.  
  961.     if (p && *p) {
  962.         /**  detect current switch character and us it  **/
  963.         inregs.h.ah = 0x37;    /*  get setting data  */
  964.         inregs.h.al = 0x00;    /*  get switch character  */
  965.         intdos(&inregs, &outregs);
  966.         *swchar = outregs.h.dl;
  967.         ferr = forkl(shell, "command", swchar, cmd, (char *)NULL);
  968.     } else {
  969.         ferr = forkl(shell, "command", (char *)NULL);
  970.     }
  971.  
  972.     return (ferr ? ferr : wait());
  973. }
  974. #endif
  975.