/* Spawn: various DOS access commands for MicroEMACS */ #include #include "estruct.h" #include "edef.h" #if AMIGA #define NEW 1006L #endif #if ST520 & MEGAMAX #include #include #define LOAD_EXEC 0 /* load and execute the program */ char *STcmd, /* the command filename & path */ *STargs, /* command args (if any) */ *STenv, /* environment */ *STwork; /* work area */ #endif #if VMS #define EFN 0 /* Event flag. */ #include /* Random headers. */ #include #include #include extern int oldmode[3]; /* In "termio.c" */ extern int newmode[3]; /* In "termio.c" */ extern short iochan; /* In "termio.c" */ #endif #if V7 | USG | BSD #include extern int vttidy(); #endif #if MSDOS & (MSC | TURBO) #include #endif /* * Create a subjob with a copy of the command intrepreter in it. When the * command interpreter exits, mark the screen as garbage so that you do a full * repaint. Bound to "^X C". The message at the start in VMS puts out a newline. * Under some (unknown) condition, you don't get one free when DCL starts up. */ spawncli(f, n) { #if AMIGA long newcli; #endif #if V7 | USG | BSD register char *cp; char *getenv(); #endif /* don't allow this command if restricted */ if (restflag) return(resterr()); #if AMIGA mlwrite("[Starting new CLI]"); sgarbf = TRUE; Execute("NEWCLI \"CON:0/0/640/200/MicroEMACS Subprocess\"", 0L, 0L); return(TRUE); #endif #if VMS movecursor(term.t_nrow, 0); /* In last line. */ mlputs("[Starting DCL]\r\n"); TTflush(); /* Ignore "ttcol". */ sgarbf = TRUE; return (sys(NULL)); /* NULL => DCL. */ #endif #if CPM mlwrite("Not in CP/M-86"); #endif #if ST520 mlwrite("Not in TOS"); #endif #if MSDOS & (AZTEC | MSC | TURBO) movecursor(term.t_nrow, 0); /* Seek to last line. */ TTflush(); TTkclose(); system("command.com"); TTkopen(); sgarbf = TRUE; return(TRUE); #endif #if MSDOS & LATTICE movecursor(term.t_nrow, 0); /* Seek to last line. */ TTflush(); TTkclose(); sys("\\command.com", ""); /* Run CLI. */ TTkopen(); sgarbf = TRUE; return(TRUE); #endif #if (V7 | USG | BSD) #if NeWS mlwrite("Not availible under NeWS"); return(FALSE); #else movecursor(term.t_nrow, 0); /* Seek to last line. */ TTflush(); TTclose(); /* stty to old settings */ if ((cp = getenv("SHELL")) != NULL && *cp != '\0') system(cp); else #if BSD system("exec /bin/csh"); #else system("exec /bin/sh"); #endif sgarbf = TRUE; sleep(2); TTopen(); return(TRUE); #endif #endif } #if BSD bktoshell() /* suspend MicroEMACS and wait to wake up */ { #if NeWS mlwrite("Not availible under NeWS"); return(FALSE); #else int pid; vttidy(); pid = getpid(); kill(pid,SIGTSTP); #endif } rtfrmshell() { #if NeWS mlwrite("Not availible under NeWS"); return(FALSE); #else TTopen(); curwp->w_flag = WFHARD; sgarbf = TRUE; #endif } #endif /* * Run a one-liner in a subjob. When the command returns, wait for a single * character to be typed, then mark the screen as garbage so a full repaint is * done. Bound to "C-X !". */ spawn(f, n) { register int s; char line[NLINE]; register char *cp; char line2[NLINE]; #if ST520 & MEGAMAX int i,j,k; char *sptr,*tptr; #endif #if AMIGA long newcli; #endif /* don't allow this command if restricted */ if (restflag) return(resterr()); #if AMIGA if ((s=mlreply("!", line, NLINE)) != TRUE) return (s); newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW); Execute(line, 0L, newcli); Close(newcli); tgetc(); /* Pause. */ sgarbf = TRUE; return(TRUE); #endif #if ST520 & MEGAMAX if ((s=mlreply("!", line, NLINE)) != TRUE) return(s); movecursor(term.t_nrow - 1, 0); TTclose(); /* * break the line into the command and its args * be cute about it, if there is no '.' in the filename, try * to find .prg, .tos or .ttp in that order * in any case check to see that the file exists before we run * amok */ STenv = NULL; if((tptr = index(&line[0],' ')) == NULL) { /* no args */ STcmd = (char *)malloc(strlen(line) + 1); strcpy(STcmd,line); STargs = NULL; } else { /* seperate out the args from the command */ /* resist the temptation to do ptr arithmetic */ STcmd = (char *)malloc(strlen(line) + 1); for(i = 0,sptr = &line[0]; sptr != tptr; sptr++,i++) STcmd[i] = *sptr; STcmd[i] = '\0'; for(; *tptr == ' ' || *tptr == '\t'; tptr++); if(*tptr == '\0') STargs = NULL; else { STargs = (char *)malloc(strlen(tptr) + 2); /* first byte of STargs is the length of the string */ STargs[0] = strlen(tptr); STargs[1] = NULL; /* fake it for strcat */ strcat(STargs,tptr); } } /* * before we issue the command look for the '.', if it's not there * try adding .prg, .tos and .ttp to see if they exist, if not * issue the command as is */ if((tptr = index(STcmd,'.')) == NULL) { STwork = (char *)malloc(strlen(STcmd) + 4); strcpy(STwork,STcmd); strcat(STwork,".prg"); tptr = index(STwork,'.'); if(Fsfirst(1,STwork) != 0) { /* try .tos */ strcpy(tptr,".tos"); if(Fsfirst(1,STwork) != 0) { /* try .ttp */ strcpy(tptr,".ttp"); if(Fsfirst(1,STwork) != 0) /* never mind */ *STwork = NULL; } } } if(*STwork != NULL) Pexec(LOAD_EXEC,STwork,STargs,STenv); else Pexec(LOAD_EXEC,STcmd,STargs,STenv); TTopen(); mlputs("\r\n\n[End]"); /* Pause. */ TTgetc(); /* Pause. */ sgarbf = TRUE; return (TRUE); #endif #if VMS if ((s=mlreply("!", line, NLINE)) != TRUE) return (s); TTputc('\n'); /* Already have '\r' */ TTflush(); s = sys(line); /* Run the command. */ mlputs("\r\n\n[End]"); /* Pause. */ TTflush(); tgetc(); sgarbf = TRUE; return (s); #endif #if CPM mlwrite("Not in CP/M-86"); return (FALSE); #endif #if MSDOS | (ST520 & LATTICE) if ((s=mlreply("!", line, NLINE)) != TRUE) return(s); movecursor(term.t_nrow - 1, 0); TTkclose(); system(line); TTkopen(); /* if we are interactive, pause here */ if (clexec == FALSE) { mlputs("\r\n\n[End]"); tgetc(); } sgarbf = TRUE; return (TRUE); #endif #if (V7 | USG | BSD) if ((s=mlreply("!", line, NLINE)) != TRUE) return (s); #if ! NeWS TTputc('\n'); /* Already have '\r' */ TTflush(); TTclose(); /* stty to old modes */ #endif if ((cp = getenv("SHELL")) == NULL || *cp == '\0') #if BSD cp = "/bin/csh"; #else cp = "/bin/sh"; #endif sprintf(line2, "%s -c \"%s\"", cp, line); system(line2); #if ! NeWS TTopen(); mlputs("[End]"); /* Pause. */ TTflush(); while ((s = tgetc()) != '\r' && s != ' ') ; sgarbf = TRUE; #endif return (TRUE); #endif } /* * Pipe a one line command into a window * Bound to ^X @ */ pipecmd(f, n) { register int s; /* return status from CLI */ register WINDOW *wp; /* pointer to new window */ register BUFFER *bp; /* pointer to buffer to zot */ char line[NLINE]; /* command line send to shell */ static char bname[] = "command"; #if AMIGA static char filnam[] = "ram:command"; long newcli; #else static char filnam[NSTRING] = "command"; #endif #if MSDOS char *tmp; char *getenv(); FILE *fp; FILE *fopen(); #endif /* don't allow this command if restricted */ if (restflag) return(resterr()); #if MSDOS if ((tmp = getenv("TMP")) == NULL) strcpy(filnam, "command"); else { strcpy(filnam, tmp); strcat(filnam,"\\command"); } #endif #if VMS mlwrite("Not availible under VMS"); return(FALSE); #endif #if CPM mlwrite("Not availible under CP/M-86"); return(FALSE); #endif /* get the command to pipe in */ if ((s=mlreply("@", line, NLINE)) != TRUE) return(s); /* get rid of the command output buffer if it exists */ if ((bp=bfind(bname, FALSE, 0)) != FALSE) { /* try to make sure we are off screen */ wp = wheadp; while (wp != NULL) { if (wp->w_bufp == bp) { onlywind(FALSE, 1); break; } wp = wp->w_wndp; } if (zotbuf(bp) != TRUE) return(FALSE); } #if AMIGA newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW); strcat(line, " >"); strcat(line, filnam); Execute(line, 0L, newcli); s = TRUE; Close(newcli); sgarbf = TRUE; #endif #if MSDOS strcat(line," >>"); strcat(line,filnam); movecursor(term.t_nrow - 1, 0); TTkclose(); system(line); TTkopen(); sgarbf = TRUE; if ((fp = fopen(filnam, "r")) == NULL) { s = FALSE; } else { fclose(fp); s = TRUE; } #endif #if V7 | USG | BSD #if ! NeWS fprintf(stderr, "closing\n") ; TTputc('\n'); /* Already have '\r' */ TTflush(); TTclose(); /* stty to old modes */ #endif strcat(line,">"); strcat(line,filnam); system(line); #if ! NeWS TTopen(); TTflush(); sgarbf = TRUE; #endif s = TRUE; #endif if (s != TRUE) return(s); /* split the current window to make room for the command output */ if (splitwind(FALSE, 1) == FALSE) return(FALSE); /* and read the stuff in */ if (getfile(filnam, FALSE) == FALSE) return(FALSE); /* make this window in VIEW mode, update all mode lines */ curwp->w_bufp->b_mode |= MDVIEW; wp = wheadp; while (wp != NULL) { wp->w_flag |= WFMODE; wp = wp->w_wndp; } /* and get rid of the temporary file */ unlink(filnam); return(TRUE); } /* * filter a buffer through an external DOS program * Bound to ^X # */ filter(f, n) { register int s; /* return status from CLI */ register BUFFER *bp; /* pointer to buffer to zot */ char line[NLINE]; /* command line send to shell */ char tmpnam[NFILEN]; /* place to store real file name */ static char bname1[] = "fltinp"; #if AMIGA static char filnam1[] = "ram:fltinp"; static char filnam2[] = "ram:fltout"; long newcli; #else static char filnam1[] = "fltinp"; static char filnam2[] = "fltout"; #endif /* don't allow this command if restricted */ if (restflag) return(resterr()); if (curbp->b_mode&MDVIEW) /* don't allow this command if */ return(rdonly()); /* we are in read only mode */ #if VMS mlwrite("Not availible under VMS"); return(FALSE); #endif #if CPM mlwrite("Not availible under CP/M-86"); return(FALSE); #endif /* get the filter name and its args */ if ((s=mlreply("#", line, NLINE)) != TRUE) return(s); /* setup the proper file names */ bp = curbp; strcpy(tmpnam, bp->b_fname); /* save the original name */ strcpy(bp->b_fname, bname1); /* set it to our new one */ /* write it out, checking for errors */ if (writeout(filnam1) != TRUE) { mlwrite("[Cannot write filter file]"); strcpy(bp->b_fname, tmpnam); return(FALSE); } #if AMIGA newcli = Open("CON:0/0/640/200/MicroEMACS Subprocess", NEW); strcat(line, " ram:fltout"); Execute(line,0L,newcli); s = TRUE; Close(newcli); sgarbf = TRUE; #endif #if MSDOS strcat(line," fltout"); movecursor(term.t_nrow - 1, 0); TTkclose(); system(line); TTkopen(); sgarbf = TRUE; s = TRUE; #endif #if V7 | USG | BSD #if ! NeWS TTputc('\n'); /* Already have '\r' */ TTflush(); TTclose(); /* stty to old modes */ #endif strcat(line," fltout"); system(line); #if ! NeWS TTopen(); TTflush(); sgarbf = TRUE; #endif s = TRUE; #endif /* on failure, escape gracefully */ if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) { mlwrite("[Execution failed]"); strcpy(bp->b_fname, tmpnam); unlink(filnam1); unlink(filnam2); return(s); } /* reset file name */ strcpy(bp->b_fname, tmpnam); /* restore name */ bp->b_flag |= BFCHG; /* flag it as changed */ /* and get rid of the temporary file */ unlink(filnam1); unlink(filnam2); return(TRUE); } #if VMS /* * Run a command. The "cmd" is a pointer to a command string, or NULL if you * want to run a copy of DCL in the subjob (this is how the standard routine * LIB$SPAWN works. You have to do wierd stuff with the terminal on the way in * and the way out, because DCL does not want the channel to be in raw mode. */ sys(cmd) register char *cmd; { struct dsc$descriptor cdsc; struct dsc$descriptor *cdscp; long status; long substatus; long iosb[2]; status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, oldmode, sizeof(oldmode), 0, 0, 0, 0); if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) return (FALSE); cdscp = NULL; /* Assume DCL. */ if (cmd != NULL) { /* Build descriptor. */ cdsc.dsc$a_pointer = cmd; cdsc.dsc$w_length = strlen(cmd); cdsc.dsc$b_dtype = DSC$K_DTYPE_T; cdsc.dsc$b_class = DSC$K_CLASS_S; cdscp = &cdsc; } status = LIB$SPAWN(cdscp, 0, 0, 0, 0, 0, &substatus, 0, 0, 0); if (status != SS$_NORMAL) substatus = status; status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, newmode, sizeof(newmode), 0, 0, 0, 0); if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) return (FALSE); if ((substatus&STS$M_SUCCESS) == 0) /* Command failed. */ return (FALSE); return (TRUE); } #endif #if ~AZTEC & ~MSC & ~TURBO & MSDOS /* * This routine, once again by Bob McNamara, is a C translation of the "system" * routine in the MWC-86 run time library. It differs from the "system" routine * in that it does not unconditionally append the string ".exe" to the end of * the command name. We needed to do this because we want to be able to spawn * off "command.com". We really do not understand what it does, but if you don't * do it exactly "malloc" starts doing very very strange things. */ sys(cmd, tail) char *cmd; char *tail; { #if MWC86 register unsigned n; extern char *__end; n = __end + 15; n >>= 4; n = ((n + dsreg() + 16) & 0xFFF0) + 16; return(execall(cmd, tail, n)); #endif #if LATTICE return(forklp(cmd, tail, (char *)NULL)); #endif } #endif #if MSDOS & LATTICE /* System: a modified version of lattice's system() function that detects the proper switchar and uses it written by Dana Hogget */ system(cmd) char *cmd; /* Incoming command line to execute */ { char *getenv(); static char *swchar = "/C"; /* Execution switch */ union REGS inregs; /* parameters for dos call */ union REGS outregs; /* Return results from dos call */ char *shell; /* Name of system command processor */ char *p; /* Temporary pointer */ int ferr; /* Error condition if any */ /* get name of system shell */ if ((shell = getenv("COMSPEC")) == NULL) { return (-1); /* No shell located */ } p = cmd; while (isspace(*p)) { /* find out if null command */ p++; } /** If the command line is not empty, bring up the shell **/ /** and execute the command. Otherwise, bring up the **/ /** shell in interactive mode. **/ if (p && *p) { /** detect current switch character and us it **/ inregs.h.ah = 0x37; /* get setting data */ inregs.h.al = 0x00; /* get switch character */ intdos(&inregs, &outregs); *swchar = outregs.h.dl; ferr = forkl(shell, "command", swchar, cmd, (char *)NULL); } else { ferr = forkl(shell, "command", (char *)NULL); } return (ferr ? ferr : wait()); } #endif