home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 001-099 / ff093.lzh / MicroEmacs / source / src.arc / spawn.c < prev    next >
C/C++ Source or Header  |  1987-08-16  |  17KB  |  641 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   1006
  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. extern int vttidy();
  39. #endif
  40.  
  41. #if    MSDOS & MSC
  42. #include    <process.h>
  43. #define    system(a)    spawnlp(P_WAIT, a, NULL)
  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.         newcli = Open("CON:0/0/639/199/MicroEmacs Subprocess", NEW);
  70.         mlwrite("[Starting new CLI]");
  71.         sgarbf = TRUE;
  72.         Execute("", newcli, 0);
  73.         Close(newcli);
  74.         return(TRUE);
  75. #endif
  76.  
  77. #if     VMS
  78.         movecursor(term.t_nrow, 0);             /* In last line.        */
  79.         mlputs("[Starting DCL]\r\n");
  80.         TTflush();                          /* Ignore "ttcol".      */
  81.         sgarbf = TRUE;
  82.         return (sys(NULL));                     /* NULL => DCL.         */
  83. #endif
  84. #if     CPM
  85.         mlwrite("Not in CP/M-86");
  86. #endif
  87. #if    ST520
  88.     mlwrite("Not in TOS");
  89. #endif
  90. #if     MSDOS & AZTEC
  91.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  92.         TTflush();
  93.     TTkclose();
  94.     system("command.com");
  95.     TTkopen();
  96.         sgarbf = TRUE;
  97.         return(TRUE);
  98. #endif
  99. #if     MSDOS & LATTICE
  100.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  101.         TTflush();
  102.     TTkclose();
  103.         sys("\\command.com", "");               /* Run CLI.             */
  104.     TTkopen();
  105.         sgarbf = TRUE;
  106.         return(TRUE);
  107. #endif
  108. #if     V7 | USG | BSD
  109.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  110.         TTflush();
  111.         TTclose();                              /* stty to old settings */
  112.         if ((cp = getenv("SHELL")) != NULL && *cp != '\0')
  113.                 system(cp);
  114.         else
  115. #if    BSD
  116.                 system("exec /bin/csh");
  117. #else
  118.                 system("exec /bin/sh");
  119. #endif
  120.         sgarbf = TRUE;
  121.         sleep(2);
  122.         TTopen();
  123.         return(TRUE);
  124. #endif
  125. }
  126.  
  127. #if    BSD
  128.  
  129. bktoshell()        /* suspend MicroEMACS and wait to wake up */
  130. {
  131.     int pid;
  132.  
  133.     vttidy();
  134.     pid = getpid();
  135.     kill(pid,SIGTSTP);
  136. }
  137.  
  138. rtfrmshell()
  139. {
  140.     TTopen();
  141.     curwp->w_flag = WFHARD;
  142.     sgarbf = TRUE;
  143. }
  144. #endif
  145.  
  146. /*
  147.  * Run a one-liner in a subjob. When the command returns, wait for a single
  148.  * character to be typed, then mark the screen as garbage so a full repaint is
  149.  * done. Bound to "C-X !".
  150.  */
  151. spawn(f, n)
  152. {
  153.         register int    s;
  154.         char            line[NLINE];
  155.  
  156. #if    ST520 & MEGAMAX
  157.     int i,j,k;
  158.     char *sptr,*tptr;
  159. #endif
  160.  
  161. #if     AMIGA
  162.         long newcli;
  163. #endif
  164.  
  165.     /* don't allow this command if restricted */
  166.     if (restflag)
  167.         return(resterr());
  168.  
  169. #if    AMIGA
  170.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  171.                 return (s);
  172.         newcli = Open("CON:0/0/639/199/MicroEmacs Subprocess", NEW);
  173.         Execute(line,0,newcli);
  174.         Close(newcli);
  175.         tgetc();     /* Pause.               */
  176.         sgarbf = TRUE;
  177.         return(TRUE);
  178. #endif
  179. #if     ST520 & MEGAMAX
  180.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  181.                 return(s);
  182.     movecursor(term.t_nrow - 1, 0);
  183.     TTclose();
  184. /*
  185.  * break the line into the command and its args
  186.  * be cute about it, if there is no '.' in the filename, try
  187.  * to find .prg, .tos or .ttp in that order
  188.  * in any case check to see that the file exists before we run 
  189.  * amok
  190.  */
  191.     STenv = NULL;
  192.     if((tptr = index(&line[0],' ')) == NULL) { /* no args */
  193.         STcmd = (char *)malloc(strlen(line) + 1);
  194.         strcpy(STcmd,line);
  195.         STargs = NULL;
  196.     }
  197.     else {  /* seperate out the args from the command */
  198.         /* resist the temptation to do ptr arithmetic */
  199.         STcmd = (char *)malloc(strlen(line) + 1);
  200.         for(i = 0,sptr = &line[0]; sptr != tptr; sptr++,i++)
  201.             STcmd[i] = *sptr;
  202.         STcmd[i] = '\0';
  203.         for(; *tptr == ' ' || *tptr == '\t'; tptr++);
  204.         if(*tptr == '\0')
  205.             STargs = NULL;
  206.         else {
  207.             STargs = (char *)malloc(strlen(tptr) + 2);
  208. /* first byte of STargs is the length of the string */
  209.             STargs[0] = strlen(tptr);
  210.             STargs[1] = NULL; /* fake it for strcat */
  211.             strcat(STargs,tptr);
  212.         }
  213.     }
  214. /*
  215.  * before we issue the command look for the '.', if it's not there
  216.  * try adding .prg, .tos and .ttp to see if they exist, if not
  217.  * issue the command as is
  218.  */
  219.     if((tptr = index(STcmd,'.')) == NULL) {
  220.          STwork = (char *)malloc(strlen(STcmd) + 4);
  221.          strcpy(STwork,STcmd);
  222.          strcat(STwork,".prg");
  223.          tptr = index(STwork,'.');
  224.          if(Fsfirst(1,STwork) != 0) { /* try .tos */
  225.              strcpy(tptr,".tos");
  226.              if(Fsfirst(1,STwork) != 0) { /* try .ttp */
  227.                  strcpy(tptr,".ttp");
  228.                  if(Fsfirst(1,STwork) != 0) /* never mind */
  229.                      *STwork = NULL;
  230.                  }
  231.              }
  232.      }
  233.      if(*STwork != NULL)
  234.             Pexec(LOAD_EXEC,STwork,STargs,STenv);         
  235.     else
  236.             Pexec(LOAD_EXEC,STcmd,STargs,STenv);
  237.     TTopen();
  238.         mlputs("\r\n\n[End]");                  /* Pause.               */
  239.         TTgetc();                 /* Pause.               */
  240.         sgarbf = TRUE;
  241.         return (TRUE);
  242. #endif
  243. #if     VMS
  244.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  245.                 return (s);
  246.         TTputc('\n');                /* Already have '\r'    */
  247.         TTflush();
  248.         s = sys(line);                          /* Run the command.     */
  249.         mlputs("\r\n\n[End]");                  /* Pause.               */
  250.         TTflush();
  251.         tgetc();
  252.         sgarbf = TRUE;
  253.         return (s);
  254. #endif
  255. #if     CPM
  256.         mlwrite("Not in CP/M-86");
  257.         return (FALSE);
  258. #endif
  259. #if     MSDOS | (ST520 & LATTICE)
  260.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  261.                 return(s);
  262.     movecursor(term.t_nrow - 1, 0);
  263.     TTkclose();
  264.         system(line);
  265.     TTkopen();
  266.     /* if we are interactive, pause here */
  267.     if (clexec == FALSE) {
  268.             mlputs("\r\n\n[End]");
  269.             tgetc();
  270.         }
  271.         sgarbf = TRUE;
  272.         return (TRUE);
  273. #endif
  274. #if     V7 | USG | BSD
  275.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  276.                 return (s);
  277.         TTputc('\n');                /* Already have '\r'    */
  278.         TTflush();
  279.         TTclose();                              /* stty to old modes    */
  280.         system(line);
  281.         TTopen();
  282.         mlputs("[End]");                        /* Pause.               */
  283.         TTflush();
  284.         while ((s = tgetc()) != '\r' && s != ' ')
  285.                 ;
  286.         sgarbf = TRUE;
  287.         return (TRUE);
  288. #endif
  289. }
  290.  
  291. /*
  292.  * Pipe a one line command into a window
  293.  * Bound to ^X @
  294.  */
  295. pipecmd(f, n)
  296. {
  297.         register int    s;    /* return status from CLI */
  298.     register WINDOW *wp;    /* pointer to new window */
  299.     register BUFFER *bp;    /* pointer to buffer to zot */
  300.         char    line[NLINE];    /* command line send to shell */
  301.     static char bname[] = "command";
  302.  
  303. #if    AMIGA
  304.     static char filnam[] = "ram:command";
  305.         long newcli;
  306. #else
  307.     static char filnam[] = "command";
  308. #endif
  309.  
  310. #if    MSDOS
  311.     char *tmp;
  312.     char *getenv();
  313.     FILE *fp;
  314.     FILE *fopen();
  315. #endif
  316.  
  317.     /* don't allow this command if restricted */
  318.     if (restflag)
  319.         return(resterr());
  320.  
  321. #if    MSDOS
  322.     if ((tmp = getenv("TMP")) == NULL)
  323.         strcpy(filnam, "command");
  324.     else
  325.         strcpy(filnam, tmp);
  326. #endif
  327.  
  328. #if     VMS
  329.     mlwrite("Not availible under VMS");
  330.     return(FALSE);
  331. #endif
  332. #if     CPM
  333.         mlwrite("Not availible under CP/M-86");
  334.         return(FALSE);
  335. #endif
  336.  
  337.     /* get the command to pipe in */
  338.         if ((s=mlreply("@", line, NLINE)) != TRUE)
  339.                 return(s);
  340.  
  341.     /* get rid of the command output buffer if it exists */
  342.         if ((bp=bfind(bname, FALSE, 0)) != FALSE) {
  343.         /* try to make sure we are off screen */
  344.         wp = wheadp;
  345.         while (wp != NULL) {
  346.             if (wp->w_bufp == bp) {
  347.                 onlywind(FALSE, 1);
  348.                 break;
  349.             }
  350.             wp = wp->w_wndp;
  351.         }
  352.         if (zotbuf(bp) != TRUE)
  353.  
  354.             return(FALSE);
  355.     }
  356.  
  357. #if     AMIGA
  358.         newcli = Open("CON:0/0/639/199/MicroEmacs Subprocess", NEW);
  359.     strcat(line, " >");
  360.     strcat(line, filnam);
  361.         Execute(line,0,newcli);
  362.     s = TRUE;
  363.         Close(newcli);
  364.         sgarbf = TRUE;
  365. #endif
  366. #if     MSDOS
  367.     strcat(line," >>");
  368.     strcat(line,filnam);
  369.     movecursor(term.t_nrow - 1, 0);
  370.     TTkclose();
  371.         system(line);
  372.     TTkopen();
  373.         sgarbf = TRUE;
  374.     if ((fp = fopen(filnam, "r")) == NULL) {
  375.         s = FALSE;
  376.     } else {
  377.         fclose(fp);
  378.         s = TRUE;
  379.     }
  380. #endif
  381. #if     V7 | USG | BSD
  382.         TTputc('\n');                /* Already have '\r'    */
  383.         TTflush();
  384.         TTclose();                              /* stty to old modes    */
  385.     strcat(line,">");
  386.     strcat(line,filnam);
  387.         system(line);
  388.         TTopen();
  389.         TTflush();
  390.         sgarbf = TRUE;
  391.         s = TRUE;
  392. #endif
  393.  
  394.     if (s != TRUE)
  395.         return(s);
  396.  
  397.     /* split the current window to make room for the command output */
  398.     if (splitwind(FALSE, 1) == FALSE)
  399.             return(FALSE);
  400.  
  401.     /* and read the stuff in */
  402.     if (getfile(filnam, FALSE) == FALSE)
  403.         return(FALSE);
  404.  
  405.     /* make this window in VIEW mode, update all mode lines */
  406.     curwp->w_bufp->b_mode |= MDVIEW;
  407.     wp = wheadp;
  408.     while (wp != NULL) {
  409.         wp->w_flag |= WFMODE;
  410.         wp = wp->w_wndp;
  411.     }
  412.  
  413.     /* and get rid of the temporary file */
  414.     unlink(filnam);
  415.     return(TRUE);
  416. }
  417.  
  418. /*
  419.  * filter a buffer through an external DOS program
  420.  * Bound to ^X #
  421.  */
  422. filter(f, n)
  423.  
  424. {
  425.         register int    s;    /* return status from CLI */
  426.     register BUFFER *bp;    /* pointer to buffer to zot */
  427.         char line[NLINE];    /* command line send to shell */
  428.     char tmpnam[NFILEN];    /* place to store real file name */
  429.     static char bname1[] = "fltinp";
  430.  
  431. #if    AMIGA
  432.     static char filnam1[] = "ram:fltinp";
  433.     static char filnam2[] = "ram:fltout";
  434.         long newcli;
  435. #else
  436.     static char filnam1[] = "fltinp";
  437.     static char filnam2[] = "fltout";
  438. #endif
  439.  
  440.     /* don't allow this command if restricted */
  441.     if (restflag)
  442.         return(resterr());
  443.  
  444.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  445.         return(rdonly());    /* we are in read only mode    */
  446.  
  447. #if     VMS
  448.     mlwrite("Not availible under VMS");
  449.     return(FALSE);
  450. #endif
  451. #if     CPM
  452.         mlwrite("Not availible under CP/M-86");
  453.         return(FALSE);
  454. #endif
  455.  
  456.     /* get the filter name and its args */
  457.         if ((s=mlreply("#", line, NLINE)) != TRUE)
  458.                 return(s);
  459.  
  460.     /* setup the proper file names */
  461.     bp = curbp;
  462.     strcpy(tmpnam, bp->b_fname);    /* save the original name */
  463.     strcpy(bp->b_fname, bname1);    /* set it to our new one */
  464.  
  465.     /* write it out, checking for errors */
  466.     if (writeout(filnam1) != TRUE) {
  467.         mlwrite("[Cannot write filter file]");
  468.         strcpy(bp->b_fname, tmpnam);
  469.         return(FALSE);
  470.     }
  471.  
  472. #if     AMIGA
  473.         newcli = Open("CON:0/0/639/199/MicroEmacs Subprocess", NEW);
  474.     strcat(line, " <ram:fltinp >ram:fltout");
  475.         Execute(line,0,newcli);
  476.     s = TRUE;
  477.         Close(newcli);
  478.         sgarbf = TRUE;
  479. #endif
  480. #if     MSDOS
  481.     strcat(line," <fltinp >fltout");
  482.     movecursor(term.t_nrow - 1, 0);
  483.     TTkclose();
  484.         system(line);
  485.     TTkopen();
  486.         sgarbf = TRUE;
  487.     s = TRUE;
  488. #endif
  489. #if     V7 | USG | BSD
  490.         TTputc('\n');                /* Already have '\r'    */
  491.         TTflush();
  492.         TTclose();                              /* stty to old modes    */
  493.     strcat(line," <fltinp >fltout");
  494.         system(line);
  495.         TTopen();
  496.         TTflush();
  497.         sgarbf = TRUE;
  498.         s = TRUE;
  499. #endif
  500.  
  501.     /* on failure, escape gracefully */
  502.     if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) {
  503.         mlwrite("[Execution failed]");
  504.         strcpy(bp->b_fname, tmpnam);
  505.         unlink(filnam1);
  506.         unlink(filnam2);
  507.         return(s);
  508.     }
  509.  
  510.     /* reset file name */
  511.     strcpy(bp->b_fname, tmpnam);    /* restore name */
  512.     bp->b_flag |= BFCHG;        /* flag it as changed */
  513.  
  514.     /* and get rid of the temporary file */
  515.     unlink(filnam1);
  516.     unlink(filnam2);
  517.     return(TRUE);
  518. }
  519.  
  520. #if     VMS
  521. /*
  522.  * Run a command. The "cmd" is a pointer to a command string, or NULL if you
  523.  * want to run a copy of DCL in the subjob (this is how the standard routine
  524.  * LIB$SPAWN works. You have to do wierd stuff with the terminal on the way in
  525.  * and the way out, because DCL does not want the channel to be in raw mode.
  526.  */
  527. sys(cmd)
  528. register char   *cmd;
  529. {
  530.         struct  dsc$descriptor  cdsc;
  531.         struct  dsc$descriptor  *cdscp;
  532.         long    status;
  533.         long    substatus;
  534.         long    iosb[2];
  535.  
  536.         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  537.                           oldmode, sizeof(oldmode), 0, 0, 0, 0);
  538.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  539.                 return (FALSE);
  540.         cdscp = NULL;                           /* Assume DCL.          */
  541.         if (cmd != NULL) {                      /* Build descriptor.    */
  542.                 cdsc.dsc$a_pointer = cmd;
  543.                 cdsc.dsc$w_length  = strlen(cmd);
  544.                 cdsc.dsc$b_dtype   = DSC$K_DTYPE_T;
  545.                 cdsc.dsc$b_class   = DSC$K_CLASS_S;
  546.                 cdscp = &cdsc;
  547.         }
  548.         status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0);
  549.         if (status != SS$_NORMAL)
  550.                 substatus = status;
  551.         status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
  552.                           newmode, sizeof(newmode), 0, 0, 0, 0);
  553.         if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
  554.                 return (FALSE);
  555.         if ((substatus&STS$M_SUCCESS) == 0)     /* Command failed.      */
  556.                 return (FALSE);
  557.         return (TRUE);
  558. }
  559. #endif
  560.  
  561. #if    ~AZTEC & MSDOS
  562.  
  563. /*
  564.  * This routine, once again by Bob McNamara, is a C translation of the "system"
  565.  * routine in the MWC-86 run time library. It differs from the "system" routine
  566.  * in that it does not unconditionally append the string ".exe" to the end of
  567.  * the command name. We needed to do this because we want to be able to spawn
  568.  * off "command.com". We really do not understand what it does, but if you don't
  569.  * do it exactly "malloc" starts doing very very strange things.
  570.  */
  571. sys(cmd, tail)
  572. char    *cmd;
  573. char    *tail;
  574. {
  575. #if MWC_86
  576.         register unsigned n;
  577.         extern   char     *__end;
  578.  
  579.         n = __end + 15;
  580.         n >>= 4;
  581.         n = ((n + dsreg() + 16) & 0xFFF0) + 16;
  582.         return(execall(cmd, tail, n));
  583. #endif
  584.  
  585. #if LATTICE
  586.         return(forklp(cmd, tail, (char *)NULL));
  587. #endif
  588.  
  589. #if    MSC
  590.     return(spawnlp(P_WAIT, cmd, tail, NULL));
  591. #endif
  592. }
  593. #endif
  594.  
  595. #if    MSDOS & LATTICE
  596. /*    System: a modified version of lattice's system() function
  597.         that detects the proper switchar and uses it
  598.         written by Dana Hogget                */
  599.  
  600. system(cmd)
  601.  
  602. char *cmd;    /*  Incoming command line to execute  */
  603.  
  604. {
  605.     char *getenv();
  606.     static char *swchar = "/C";    /*  Execution switch  */
  607.     union REGS inregs;    /*  parameters for dos call  */
  608.     union REGS outregs;    /*  Return results from dos call  */
  609.     char *shell;        /*  Name of system command processor  */
  610.     char *p;        /*  Temporary pointer  */
  611.     int ferr;        /*  Error condition if any  */
  612.  
  613.     /*  get name of system shell  */
  614.     if ((shell = getenv("COMSPEC")) == NULL) {
  615.         return (-1);        /*  No shell located  */
  616.     }
  617.  
  618.     p = cmd;
  619.     while (isspace(*p)) {        /*  find out if null command */
  620.         p++;
  621.     }
  622.  
  623.     /**  If the command line is not empty, bring up the shell  **/
  624.     /**  and execute the command.  Otherwise, bring up the     **/
  625.     /**  shell in interactive mode.   **/
  626.  
  627.     if (p && *p) {
  628.         /**  detect current switch character and us it  **/
  629.         inregs.h.ah = 0x37;    /*  get setting data  */
  630.         inregs.h.al = 0x00;    /*  get switch character  */
  631.         intdos(&inregs, &outregs);
  632.         *swchar = outregs.h.dl;
  633.         ferr = forkl(shell, "command", swchar, cmd, (char *)NULL);
  634.     } else {
  635.         ferr = forkl(shell, "command", (char *)NULL);
  636.     }
  637.  
  638.     return (ferr ? ferr : wait());
  639. }
  640. #endif
  641.