home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 198_02 / spawn.c < prev    next >
C/C++ Source or Header  |  1990-01-23  |  20KB  |  748 lines

  1. /*    Spawn:    various DOS access commands
  2.         for MicroEMACS
  3. */
  4.  
  5. #include        <stdio.h>
  6. #include    "estruct.h"
  7. #include        "edef.h"
  8.  
  9. #if     AMIGA
  10. #define  NEW   1006L
  11. #endif
  12.  
  13. #if        ST520 & MEGAMAX
  14. #include <osbind.h>
  15. #include <string.h>
  16. #define LOAD_EXEC 0     /* load and execute the program */
  17. char    *STcmd,        /* the command filename & path  */
  18.     *STargs,    /* command args (if any)        */
  19.     *STenv,        /* environment                  */
  20.     *STwork;    /* work area            */
  21. #endif
  22.  
  23. #if     VMS
  24. #define EFN     0                               /* Event flag.          */
  25.  
  26. #include        <ssdef.h>                       /* Random headers.      */
  27. #include        <stsdef.h>
  28. #include        <descrip.h>
  29. #include        <iodef.h>
  30.  
  31. extern  int     oldmode[3];                     /* In "termio.c"        */
  32. extern  int     newmode[3];                     /* In "termio.c"        */
  33. extern  short   iochan;                         /* In "termio.c"        */
  34. #endif
  35.  
  36. #if     V7 | USG | BSD
  37. #include        <signal.h>
  38. #endif
  39.  
  40. extern int vttidy();
  41.  
  42. #if    MSDOS & (MSC | TURBO)
  43. #include    <process.h>
  44. #endif
  45.  
  46. /*
  47.  * Create a subjob with a copy of the command intrepreter in it. When the
  48.  * command interpreter exits, mark the screen as garbage so that you do a full
  49.  * repaint. Bound to "^X C". The message at the start in VMS puts out a newline.
  50.  * Under some (unknown) condition, you don't get one free when DCL starts up.
  51.  */
  52. spawncli(f, n)
  53. {
  54. #if     AMIGA
  55.         long newcli;
  56.  
  57. #endif
  58.  
  59. #if     V7 | USG | BSD
  60.         register char *cp;
  61.         char    *getenv();
  62. #endif
  63.  
  64.     /* don't allow this command if restricted */
  65.     if (restflag)
  66.         return(resterr());
  67.  
  68. #if    AMIGA
  69.         mlwrite("[Starting new CLI]");
  70.         sgarbf = TRUE;
  71.         Execute("NEWCLI \"CON:0/0/640/200/MicroEMACS Subprocess\"", 0L, 0L);
  72.         return(TRUE);
  73. #endif
  74.  
  75. #if     VMS
  76.     ttscroll(0, term.t_nrow, 0);        /* undo scrolling region */
  77.     movecursor(term.t_nrow, 0);             /* In last line.        */
  78.     mlputs("[Starting DCL]\r\n");
  79.     TTflush();                          /* Ignore "ttcol".      */
  80.     sgarbf = TRUE;
  81.     return (sys(NULL, NULL, NULL));        /* NULL => DCL.         */
  82. #endif
  83. #if     CPM
  84.         mlwrite("Not in CP/M-86");
  85. #endif
  86. #if    ST520
  87.     mlwrite("Not in TOS");
  88. #endif
  89. #if     MSDOS & (AZTEC | MSC | TURBO | C86)
  90.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  91.         TTflush();
  92.     TTkclose();
  93.     system("command.com");
  94.     TTkopen();
  95.         sgarbf = TRUE;
  96.         return(TRUE);
  97. #endif
  98. #if     MSDOS & LATTICE
  99.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  100.         TTflush();
  101.     TTkclose();
  102.         sys("\\command.com", "");               /* Run CLI.             */
  103.     TTkopen();
  104.         sgarbf = TRUE;
  105.         return(TRUE);
  106. #endif
  107. #if     V7 | USG | BSD
  108. #if    TERMCAP
  109.     ttscroll(0, term.t_nrow, 0);        /* undo scrolling region */
  110. #endif
  111.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  112.         TTflush();
  113.         TTclose();                              /* stty to old settings */
  114.         if ((cp = getenv("SHELL")) != NULL && *cp != '\0')
  115.                 system(cp);
  116.         else
  117. #if    BSD
  118.                 system("exec /bin/csh");
  119. #else
  120.                 system("exec /bin/sh");
  121. #endif
  122.         sgarbf = TRUE;
  123.         sleep(2);
  124.         TTopen();
  125.         return(TRUE);
  126. #endif
  127. }
  128.  
  129. #if    BSD
  130.  
  131. bktoshell()        /* suspend MicroEMACS and wait to wake up */
  132. {
  133.     int pid;
  134.  
  135.     vttidy();
  136.     pid = getpid();
  137.     kill(pid,SIGTSTP);
  138.     return(TRUE);
  139. }
  140.  
  141. rtfrmshell()
  142. {
  143.     TTopen();
  144.     curwp->w_flag = WFHARD;
  145.     sgarbf = TRUE;
  146.     return(TRUE);
  147. }
  148. #endif
  149.  
  150. #if    VMS
  151.  
  152. bktoshell()        /* suspend MicroEMACS and wait to wake up */
  153. {
  154.     int err, code, mypid, ownerpid;
  155.  
  156.     /* don't allow this command if restricted */
  157.     if (restflag)
  158.         return(resterr());
  159.  
  160.     vttidy();
  161.  
  162.     err = 0;
  163.     mypid = 0;
  164.     code = 771;    /* jpi$_owner */
  165.     if (lib$getjpi(&code, &mypid, 0, &ownerpid, 0, 0) != 1) err = 1;
  166.     else if (ownerpid == 0 || mypid == ownerpid) err = 2;
  167.     else if (lib$attach(&ownerpid) != 1) err = 3;
  168.  
  169.     TTopen();
  170.  
  171.     if (err == 0) {
  172.         sgarbf = TRUE;
  173.         curwp->w_flag = WFHARD;
  174.         return(TRUE);
  175.     }
  176.  
  177.     if (err == 1) mlwrite("[Error getting pid]");
  178.     else if (err == 2) mlwrite("[No parent to attach]");
  179.     else mlwrite("[Attach failed]");
  180.     return(FALSE);
  181. }
  182. #endif
  183.  
  184. /*
  185.  * Run a one-liner in a subjob. When the command returns, wait for a single
  186.  * character to be typed, then mark the screen as garbage so a full repaint is
  187.  * done. Bound to "C-X !".
  188.  */
  189. spawn(f, n)
  190. {
  191.         register int    s;
  192.         char            line[NLINE];
  193.  
  194. #if    ST520 & MEGAMAX
  195.     int i,j,k;
  196.     char *sptr,*tptr;
  197. #endif
  198.  
  199. #if     AMIGA
  200.         long newcli;
  201. #endif
  202.  
  203.     /* don't allow this command if restricted */
  204.     if (restflag)
  205.         return(resterr());
  206.  
  207. #if    AMIGA
  208.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  209.                 return (s);
  210.         newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW);
  211.         Execute(line, 0L, newcli);
  212.         Close(newcli);
  213.         tgetc();     /* Pause.               */
  214.         sgarbf = TRUE;
  215.         return(TRUE);
  216. #endif
  217. #if     ST520 & MEGAMAX
  218.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  219.                 return(s);
  220.     movecursor(term.t_nrow - 1, 0);
  221.     TTclose();
  222. /*
  223.  * break the line into the command and its args
  224.  * be cute about it, if there is no '.' in the filename, try
  225.  * to find .prg, .tos or .ttp in that order
  226.  * in any case check to see that the file exists before we run 
  227.  * amok
  228.  */
  229.     STenv = NULL;
  230.     if((tptr = index(&line[0],' ')) == NULL) { /* no args */
  231.         STcmd = (char *)malloc(strlen(line) + 1);
  232.         strcpy(STcmd,line);
  233.         STargs = NULL;
  234.     }
  235.     else {  /* seperate out the args from the command */
  236.         /* resist the temptation to do ptr arithmetic */
  237.         STcmd = (char *)malloc(strlen(line) + 1);
  238.         for(i = 0,sptr = &line[0]; sptr != tptr; sptr++,i++)
  239.             STcmd[i] = *sptr;
  240.         STcmd[i] = '\0';
  241.         for(; *tptr == ' ' || *tptr == '\t'; tptr++);
  242.         if(*tptr == '\0')
  243.             STargs = NULL;
  244.         else {
  245.             STargs = (char *)malloc(strlen(tptr) + 2);
  246. /* first byte of STargs is the length of the string */
  247.             STargs[0] = strlen(tptr);
  248.             STargs[1] = NULL; /* fake it for strcat */
  249.             strcat(STargs,tptr);
  250.         }
  251.     }
  252. /*
  253.  * before we issue the command look for the '.', if it's not there
  254.  * try adding .prg, .tos and .ttp to see if they exist, if not
  255.  * issue the command as is
  256.  */
  257.     if((tptr = index(STcmd,'.')) == NULL) {
  258.          STwork = (char *)malloc(strlen(STcmd) + 4);
  259.          strcpy(STwork,STcmd);
  260.          strcat(STwork,".prg");
  261.          tptr = index(STwork,'.');
  262.          if(Fsfirst(1,STwork) != 0) { /* try .tos */
  263.              strcpy(tptr,".tos");
  264.              if(Fsfirst(1,STwork) != 0) { /* try .ttp */
  265.                  strcpy(tptr,".ttp");
  266.                  if(Fsfirst(1,STwork) != 0) /* never mind */
  267.                      *STwork = NULL;
  268.                  }
  269.              }
  270.      }
  271.      if(*STwork != NULL)
  272.             Pexec(LOAD_EXEC,STwork,STargs,STenv);         
  273.     else
  274.             Pexec(LOAD_EXEC,STcmd,STargs,STenv);
  275.     TTopen();
  276.         mlputs("\r\n\n[End]");                  /* Pause.               */
  277.         TTgetc();                 /* Pause.               */
  278.         sgarbf = TRUE;
  279.         return (TRUE);
  280. #endif
  281. #if     VMS
  282.         ttscroll(0, term.t_nrow, 0);        /* undo scrolling region */
  283.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  284.                 return (s);
  285.         TTputc('\n');                /* Already have '\r'    */
  286.         TTflush();
  287.         s = sys(line, NULL, NULL);        /* Run the command.     */
  288.     /* if we are interactive, pause here */
  289.     if (clexec == FALSE) {
  290.         mlputs("\r\n\n[End]");        /* Pause.               */
  291.         TTflush();
  292.         tgetc();
  293.         }
  294.         sgarbf = TRUE;
  295.         return (s);
  296. #endif
  297. #if     CPM
  298.         mlwrite("Not in CP/M-86");
  299.         return (FALSE);
  300. #endif
  301. #if     MSDOS | (ST520 & LATTICE)
  302.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  303.                 return(s);
  304.     movecursor(term.t_nrow - 1, 0);
  305.     TTkclose();
  306.         system(line);
  307.     TTkopen();
  308.     /* if we are interactive, pause here */
  309.     if (clexec == FALSE) {
  310.             mlputs("\r\n\n[End]");
  311.             tgetc();
  312.         }
  313.         sgarbf = TRUE;
  314.         return (TRUE);
  315. #endif
  316. #if     V7 | USG | BSD
  317. #if    TERMCAP
  318.     ttscroll(0, term.t_nrow, 0);        /* undo scrolling region */
  319. #endif
  320.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  321.                 return (s);
  322.         TTputc('\n');                /* Already have '\r'    */
  323.         TTflush();
  324.         TTclose();                              /* stty to old modes    */
  325.         system(line);
  326.         TTopen();
  327.     /* if we are interactive, pause here */
  328.     if (clexec == FALSE) {
  329.         mlputs("[End]");
  330.         TTflush();
  331.         while ((s = tgetc()) != '\r' && s != ' ')
  332.             ;
  333.     }
  334.     if (f != TRUE || clexec == FALSE) sgarbf = TRUE;
  335.     return (TRUE);
  336. #endif
  337. }
  338.  
  339. /*
  340.  * Pipe a one line command into a window
  341.  * Bound to ^X @
  342.  */
  343. pipecmd(f, n)
  344. {
  345.         register int    s;    /* return status from CLI */
  346.     register WINDOW *wp;    /* pointer to new window */
  347.     register BUFFER *bp;    /* pointer to buffer to zot */
  348.         char    line[NLINE];    /* command line send to shell */
  349.  
  350. #if    AMIGA
  351.     static char filnam[] = "ram:command";
  352.         long newcli;
  353. #endif
  354. #if    VMS
  355.     static char filnam[] = "command.log";
  356. #endif
  357. #if    MSDOS
  358.     char filnam[NSTRING];
  359. #endif
  360. #if    DECUSC
  361.     char *filnam[];
  362. #endif
  363. #if    (AMIGA | VMS | MSDOS | DECUSC)
  364. #else
  365.     static char filnam[] = "command";
  366. #endif
  367.  
  368. #if    MSDOS
  369.     char *tmp;
  370.     char *getenv();
  371.     FILE *fp;
  372.     FILE *fopen();
  373. #endif
  374.  
  375.     /* don't allow this command if restricted */
  376.     if (restflag)
  377.         return(resterr());
  378.  
  379. #if    MSDOS
  380.     if ((tmp = getenv("TMP")) == NULL)
  381.         strcpy(filnam, "command");
  382.     else if (tmp[strlen(tmp)-1] == ':' || tmp[strlen(tmp)-1] == '\\')
  383.         {strcpy(filnam, tmp); strcat(filnam, "command");}
  384.     else {
  385.         strcpy(filnam, tmp);
  386.                 strcat(filnam,"\\command");
  387.         }
  388. #endif
  389.  
  390. #if     CPM | DECUSC
  391.         mlwrite("Not availible under CP/M-86");
  392.         return(FALSE);
  393. #endif
  394.  
  395. #if     VMS | TERMCAP
  396.         ttscroll(0, term.t_nrow, 0);        /* undo scrolling region */
  397. #endif
  398.  
  399.     /* get the command to pipe in */
  400.         if ((s=mlreply("@", line, NLINE)) != TRUE)
  401.                 return(s);
  402.  
  403.     /* get rid of the command output buffer if it exists */
  404.         if ((bp=bfind("command", FALSE, 0)) != FALSE) {
  405.         /* try to make sure we are off screen */
  406.         wp = wheadp;
  407.         while (wp != NULL) {
  408.             if (wp->w_bufp == bp) {
  409.                 onlywind(FALSE, 1);
  410.                 break;
  411.             }
  412.             wp = wp->w_wndp;
  413.         }
  414.         if (zotbuf(bp) != TRUE)
  415.  
  416.             return(FALSE);
  417.     }
  418.  
  419. #if     AMIGA
  420.         newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW);
  421.     strcat(line, " >");
  422.     strcat(line, filnam);
  423.         Execute(line, 0L, newcli);
  424.     s = TRUE;
  425.         Close(newcli);
  426.         sgarbf = TRUE;
  427. #endif
  428. #if     MSDOS
  429.     strcat(line," >>");
  430.     strcat(line,filnam);
  431.     movecursor(term.t_nrow - 1, 0);
  432.     TTkclose();
  433.         system(line);
  434.     TTkopen();
  435.         sgarbf = TRUE;
  436.     if ((fp = fopen(filnam, "r")) == NULL) {
  437.         s = FALSE;
  438.     } else {
  439.         fclose(fp);
  440.         s = TRUE;
  441.     }
  442. #endif
  443. #if     V7 | USG | BSD
  444.         TTputc('\n');                /* Already have '\r'    */
  445.         TTflush();
  446.         TTclose();                              /* stty to old modes    */
  447.     strcat(line,">");
  448.     strcat(line,filnam);
  449.         system(line);
  450.         TTopen();
  451.         TTflush();
  452.         sgarbf = TRUE;
  453.         s = TRUE;
  454. #endif
  455. #if    VMS
  456.         TTputc('\n');                /* Already have '\r'    */
  457.         TTflush();
  458.     s = sys(line, NULL, filnam);    /* Run the command */
  459.         TTflush();
  460.         sgarbf = TRUE;
  461. #endif
  462.  
  463.     if (s != TRUE)
  464.         return(s);
  465.  
  466.     /* split the current window to make room for the command output */
  467.     if (splitwind(FALSE, 1) == FALSE)
  468.             return(FALSE);
  469.     curwp = spltwp; curbp = curwp->w_bufp;
  470.  
  471.     /* and read the stuff in */
  472.     if (getfile(filnam, FALSE) == FALSE)
  473.         return(FALSE);
  474.  
  475.     /* make this window in VIEW mode, update all mode lines */
  476.     curbp->b_mode |= MDVIEW;
  477.     wp = wheadp;
  478.     while (wp != NULL) {
  479.         wp->w_flag |= WFMODE;
  480.         wp = wp->w_wndp;
  481.     }
  482.  
  483.     /* and get rid of the temporary file */
  484.     unlink(filnam);
  485.     return(TRUE);
  486. }
  487.  
  488. /*
  489.  * filter a buffer through an external DOS program
  490.  * Bound to ^X #
  491.  */
  492. filter(f, n)
  493.  
  494. {
  495.         register int    s;    /* return status from CLI */
  496.     register BUFFER *bp;    /* pointer to buffer to zot */
  497.         char line[NLINE];    /* command line send to shell */
  498.     char tmpnam[NFILEN];    /* place to store real file name */
  499.  
  500. #if    AMIGA
  501.     static char filnam1[] = "ram:fltinp";
  502.     static char filnam2[] = "ram:fltout";
  503.         long newcli;
  504. #else
  505. #if    VMS
  506.     static char filnam1[] = "fltinp.com";
  507.     static char filnam2[] = "fltout.log";
  508. #else
  509. #if    DECUSC
  510.     char *filnam1, *filnam2;
  511. #else
  512.     static char filnam1[] = "fltinp";
  513.     static char filnam2[] = "fltout";
  514. #endif
  515. #endif
  516. #endif
  517.  
  518.     /* don't allow this command if restricted */
  519.     if (restflag)
  520.         return(resterr());
  521.  
  522.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  523.         return(rdonly());    /* we are in read only mode    */
  524.  
  525. #if     CPM | DECUSC
  526.         mlwrite("Not available under CP/M-86");
  527.         return(FALSE);
  528. #endif
  529.  
  530. #if     VMS | TERMCAP
  531.         ttscroll(0, term.t_nrow, 0);        /* undo scrolling region */
  532. #endif
  533.  
  534.     /* get the filter name and its args */
  535.         if ((s=mlreply("#", line, NLINE)) != TRUE)
  536.                 return(s);
  537.  
  538.     /* setup the proper file names */
  539.     bp = curbp;
  540.     strcpy(tmpnam, bp->b_fname);    /* save the original name */
  541.     strcpy(bp->b_fname, "fltinp");    /* set it to our new one */
  542.  
  543.     /* write it out, checking for errors */
  544.     if (writeout(filnam1) != TRUE) {
  545.         mlwrite("[Cannot write filter file]");
  546.         strcpy(bp->b_fname, tmpnam);
  547.         return(FALSE);
  548.     }
  549.  
  550. #if     AMIGA
  551.         newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW);
  552.     strcat(line, " <ram:fltinp >ram:fltout");
  553.         Execute(line,0L,newcli);
  554.     s = TRUE;
  555.         Close(newcli);
  556.         sgarbf = TRUE;
  557. #endif
  558. #if     MSDOS
  559.     strcat(line," <fltinp >fltout");
  560.     movecursor(term.t_nrow - 1, 0);
  561.     TTkclose();
  562.         system(line);
  563.     TTkopen();
  564.         sgarbf = TRUE;
  565.     s = TRUE;
  566. #endif
  567. #if     V7 | USG | BSD
  568.         TTputc('\n');                /* Already have '\r'    */
  569.         TTflush();
  570.         TTclose();                              /* stty to old modes    */
  571.     strcat(line," <fltinp >fltout");
  572.         system(line);
  573.         TTopen();
  574.         TTflush();
  575.         sgarbf = TRUE;
  576.         s = TRUE;
  577. #endif
  578. #if    VMS
  579.         TTputc('\n');                /* Already have '\r'    */
  580.         TTflush();
  581.     s = sys(line, filnam1, filnam2);
  582.         TTflush();
  583.         sgarbf = TRUE;
  584.         s = TRUE;
  585. #endif
  586.  
  587.     /* on failure, escape gracefully */
  588.     if (s != TRUE || (readin(filnam2,FALSE,FALSE) == FALSE)) {
  589.         mlwrite("[Execution failed]");
  590.         strcpy(bp->b_fname, tmpnam);
  591.         unlink(filnam1);
  592.         unlink(filnam2);
  593.         return(s);
  594.     }
  595.  
  596.     /* reset file name */
  597.     strcpy(bp->b_fname, tmpnam);    /* restore name */
  598.     bp->b_flag |= BFCHG;        /* flag it as changed */
  599.  
  600.     /* and get rid of the temporary file */
  601.     unlink(filnam1);
  602.     unlink(filnam2);
  603.     return(TRUE);
  604. }
  605.  
  606. #if     VMS
  607. /*
  608.  * Run a command. The "cmd" is a pointer to a command string, or NULL if you
  609.  * want to run a copy of DCL in the subjob (this is how the standard routine
  610.  * LIB$SPAWN works. You have to do wierd stuff with the terminal on the way in
  611.  * and the way out, because DCL does not want the channel to be in raw mode.
  612.  */
  613. sys(cmd, inname, outname)
  614. register char   *cmd, *inname, *outname;
  615. {
  616.         struct  dsc$descriptor  cdsc, idsc, odsc;
  617.         struct  dsc$descriptor  *cdscp, *idscp, *odscp;
  618.         long    status;
  619.         long    substatus;
  620.         long    iosb[2];
  621.  
  622.         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  623.                           oldmode, sizeof(oldmode), 0, 0, 0, 0);
  624.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  625.                 return (FALSE);
  626.         cdscp = NULL;                           /* Assume DCL.          */
  627.         if (cmd != NULL) {                      /* Build descriptor.    */
  628.                 cdsc.dsc$a_pointer = cmd;
  629.                 cdsc.dsc$w_length  = strlen(cmd);
  630.                 cdsc.dsc$b_dtype   = DSC$K_DTYPE_T;
  631.                 cdsc.dsc$b_class   = DSC$K_CLASS_S;
  632.                 cdscp = &cdsc;
  633.         }
  634.         idscp = NULL;                           /* Assume SYS$INPUT:    */
  635.         if (inname != NULL) {            /* Build descriptor.    */
  636.                 idsc.dsc$a_pointer = inname;
  637.                 idsc.dsc$w_length  = strlen(inname);
  638.                 idsc.dsc$b_dtype   = DSC$K_DTYPE_T;
  639.                 idsc.dsc$b_class   = DSC$K_CLASS_S;
  640.                 idscp = &idsc;
  641.         }
  642.         odscp = NULL;                /* Assume SYS$OUTPUT:   */
  643.         if (outname != NULL) {            /* Build descriptor.    */
  644.                 odsc.dsc$a_pointer = outname;
  645.                 odsc.dsc$w_length  = strlen(outname);
  646.                 odsc.dsc$b_dtype   = DSC$K_DTYPE_T;
  647.                 odsc.dsc$b_class   = DSC$K_CLASS_S;
  648.                 odscp = &odsc;
  649.         }
  650.         status = LIB$SPAWN(cdscp, idscp, odscp, 0, 0, 0, &substatus, 0, 0, 0);
  651.         if (status != SS$_NORMAL)
  652.                 substatus = status;
  653.         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  654.                           newmode, sizeof(newmode), 0, 0, 0, 0);
  655.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  656.                 return (FALSE);
  657.         if ((substatus&STS$M_SUCCESS) == 0)     /* Command failed.      */
  658.                 return (FALSE);
  659.         return (TRUE);
  660. }
  661. #endif
  662.  
  663. #if    MSDOS & (MWC86 | LATTICE)
  664.  
  665. /*
  666.  * This routine, once again by Bob McNamara, is a C translation of the "system"
  667.  * routine in the MWC-86 run time library. It differs from the "system" routine
  668.  * in that it does not unconditionally append the string ".exe" to the end of
  669.  * the command name. We needed to do this because we want to be able to spawn
  670.  * off "command.com". We really do not understand what it does, but if you don't
  671.  * do it exactly "malloc" starts doing very very strange things.
  672.  */
  673. sys(cmd, tail)
  674. char    *cmd;
  675. char    *tail;
  676. {
  677. #if MWC86
  678.         register unsigned n;
  679.         extern   char     *__end;
  680.  
  681.         n = __end + 15;
  682.         n >>= 4;
  683.         n = ((n + dsreg() + 16) & 0xFFF0) + 16;
  684.         return(execall(cmd, tail, n));
  685. #endif
  686.  
  687. #if LATTICE
  688.         return(forklp(cmd, tail, (char *)NULL));
  689. #endif
  690. }
  691. #endif
  692.  
  693. #if    MSDOS & LATTICE
  694. /*    System: a modified version of lattice's system() function
  695.         that detects the proper switchar and uses it
  696.         written by Dana Hogget                */
  697.  
  698. system(cmd)
  699.  
  700. char *cmd;    /*  Incoming command line to execute  */
  701.  
  702. {
  703.     char *getenv();
  704.     static char *swchar = "/C";    /*  Execution switch  */
  705.     union REGS inregs;    /*  parameters for dos call  */
  706.     union REGS outregs;    /*  Return results from dos call  */
  707.     char *shell;        /*  Name of system command processor  */
  708.     char *p;        /*  Temporary pointer  */
  709.     int ferr;        /*  Error condition if any  */
  710.  
  711.     /*  get name of system shell  */
  712.     if ((shell = getenv("COMSPEC")) == NULL) {
  713.         return (-1);        /*  No shell located  */
  714.     }
  715.  
  716.     p = cmd;
  717.     while (p && isspace(*p)) {        /*  find out if null command */
  718.         p++;
  719.     }
  720.  
  721.     /**  If the command line is not empty, bring up the shell  **/
  722.     /**  and execute the command.  Otherwise, bring up the     **/
  723.     /**  shell in interactive mode.   **/
  724.  
  725.     if (p && *p) {
  726.         /**  detect current switch character and us it  **/
  727.         inregs.h.ah = 0x37;    /*  get setting data  */
  728.         inregs.h.al = 0x00;    /*  get switch character  */
  729.         intdos(&inregs, &outregs);
  730.         *swchar = outregs.h.dl;
  731.         ferr = forkl(shell, "command", swchar, cmd, (char *)NULL);
  732.     } else {
  733.         ferr = forkl(shell, "command", (char *)NULL);
  734.     }
  735.  
  736.     return (ferr ? ferr : wait());
  737. }
  738. #endif
  739.  
  740. #if MSDOS & C86
  741. char *getenv(str)
  742. char *str;
  743. {
  744.     return(NULL);
  745. }
  746. #endif
  747.  
  748.