#include "ded.h" #include "char.h" #include "signal.h" /************************************************************************ * * * copyright Richard Bornat 1981 * * * ************************************************************************/ /* Interactive Compile facility added - PLS UMIST 1983 * Compile with flag "-DINTCOMP" to enable. */ #ifdef INTCOMP int cpipe[2] = {-1,-1}; #endif extern char *fillin(); /************************************************************************ * * * this procedure allows the processing of command lines * * which may contain control characters, all kinds of other * * gibberish, but also may contain percent (%) characters. * * A percent is replaced by the current filename - and * * awfully inconsistently, '% means a percent character * * in the command string. I bow to popular pressure in this, * * although strictly '% should be a filename, % a percent char. * * * ************************************************************************/ do_unix(comm, shc) char *comm; char shc; /* shc == '@' means newsh or csh, '-' means sh */ /* shc == '!' means unix cmd, '+' means w then unix cmd UMIST */ /* shc == '#' means w then unix cmd with pipe for errors UMIST */ { register int pid; int filepercent=false, changed=false; char combuf[512]; char *comlim = combuf+511; if (comm != 0) /* zero parameter means @ or - command */ { char c, *lp=combuf, *fp; comm = fillin(comm, (shc == '!') ? unixbuffer : plusbuffer, "no command"); /* copy command into buffer */ do { if ((c = *comm++) == '%') /* percent replaced by filename */ { changed = filepercent = true; fp = filename; while ((*lp++ = *fp++)) if (lp>comlim) goto disaster; /* sorry */ lp--; } else if (c == '\'' && *comm=='%' ) /* prime, percent */ { changed = true; *lp++ = *comm++; } else *lp++ = c; /* everything else */ } while (c != '\0' && lpcomlim) { disaster: fdiag("command too long"); } } if (check_replay("do you want to execute this command?")) /* Get ready to fork. First, do ttyreset in parent so * as not to mess up dlog file. * On return, use ttysetmode so as not to flush the input * buffer - ded will have read ahead * when reading from an old dlog file. */ { savescreen(); if (filepercent && tmp_changed && !query("file has changed - ok to execute???")) return; /* ok to run the command */ /* this next line is no longer a cheat - the expanded command * is redrawn properly (and before the fork) so that ded knows * about it. In this way, rowmap is updated and 'redraw' can * be called again to clear the line and print the compiler * error message for the UMIST interactive compile facility. */ if (changed) { diag_clear(); redraw(EDITROW, 2, combuf); blobit(); } #ifdef INTCOMP if (shc == '#') { close(cpipe[0]); /* close previous pipe (if any) */ pipe(cpipe); } else #endif ttyreset(); if ((pid = fork()) == 0) { /* I am now the child */ extern int f_tmp; #ifdef INTCOMP if (shc != '#') #endif printf("\n"); /* set default signal handling in child */ signal(SIGQUIT, SIG_DFL); signal(SIGINT, SIG_DFL); /* close open files */ close(dlogger); close(f_tmp); if (comm) { tranline(combuf, combuf, false); /* allow control characters etc. */ #ifdef INTCOMP if (shc == '#') /* Redirect stdout & stderr of child into pipe */ { close(1); close(2); dup(cpipe[1]); dup(cpipe[1]); #if !vax close(0); /* can't have input */ #endif close(cpipe[0]); /* child does not read pipe */ } #endif #ifdef V7 execl("/bin/sh", "sh", "-ce", combuf, 0); #else execl("/bin/sh", "sh", "-c", combuf, 0); #endif } else if ( shc=='-' ) #ifdef V7 execl("/bin/sh", "sh", 0); #else execl("/bin/sh", "-", 0); #endif #ifdef QMC # ifdef V6 else if ( shc=='@' ) execl("/usr/new/newsh", "-", 0); # endif #else # if vax /* PLS BRISTOL 1982 */ else if ( shc=='@' ) execl("/bin/csh", "csh", 0); # endif #endif else editerror("garbage parameters to do_unix"); /* if you return from that, there is something wrong */ editerror("!?can't find or execute shell?!"); } else if(pid == -1) { /* it failed */ ttysetmode(); tdiag("!! try again !!"); } else { /* I am the parent */ #ifdef INTCOMP if (shc == '#') { close(cpipe[1]); showerror(); leave_command(OK); } else #endif { #ifdef RUNSTACK pwait(pid); #else int status, w; while ((w=wait(&status)) != pid && w != -1) ; if (status & 0200) { printf("\nError - core dumped"); comm = ""; } #endif ttysetmode(); if (comm != 0 && NORMAL_INPUT) /* zero parameter means @ or - command */ { extern char qread(); complain(); printf("\n(ded here) - type any character to redisplay screen"); qread(); } setupscreen(); } } } } #ifdef RUNSTACK /* procedure that interprets error signals from activated process */ pwait(i) /* i - process no */ { register p; int s; if (i != 0) while ((p=wait(&s)) != i && p != -1) if(s&0200) runstack(s); } runstack(s) { char *flag; register pid, rpid; int status; flag = "-sx"; flag[2] = s&0377; if( (pid = fork()) == 0 ) { /* actually, stack does its own signals... */ signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_IGN); /* no more core dumps...*/ execl("/usr/bin/stack", "stack", flag, 0); exit(3); } while( (rpid = wait(&status)) != pid && rpid != -1 ); } #endif #ifdef INTCOMP /* Interactive compile facility PLS, UMIST 15/2/83 * Read and process (next) compiler error message from child process. * This routine reads one line from pipe, deduces the line and column * number, moves the cursor there and then prints the diagnostic part * of the message on the command line. * Format of full error line is: * :[][-][:] * If the line does not match this spec, if or are out * of range, or if is not that of the file being edited, * it is printed as a whole and no cursor movement occurs. * This function is called from do_unix() above, and also from * mainloop() on receipt of the READPIPE input character. */ showerror() { char ebuff[ENOUGH]; char fbuff[ENOUGH]; register char *ep = ebuff; register char *fp = fbuff; int eline = 0, ecol = 0; while (read(cpipe[0],ep,1) > 0 && *ep != '\n' && ep < &ebuff[ENOUGH]) ep++; *ep = 0; ep = ebuff; while ((*fp++ = *ep) && *ep != ':' && *ep != ',') ep++; *--fp = 0; if (*--fp == '"') *fp = 0; /* allow for quotes round the filename */ if (*(fp = fbuff) == '"') fp++; /* ugh! */ while (*ep && !digit(*ep)) ep++; while (digit(*ep)) eline = eline*10 + *ep++ - '0'; if (*ep == '-') { ep++; while (digit(*ep)) ecol = ecol*10 + *ep++ - '0'; } if (*ep == ':') ep++; while (*ep == ' ') ep++; /* ep now points at beginning of diagnostic */ redraw(EDITROW, 1, ""); eline--; ecol += (ecol==0) ? MARGIN : MARGIN-1; if (eline < 0 || eline > maxl || ecol < MARGIN || ecol > RIGHTCOL || !streq(fp, filename)) cdiag(ebuff); /* print whole line */ else { i_display(eline); set_c(eline-topl, ecol, &in_c); cdiag(ep); /* print compiler diagnostic */ } } #endif