-/*
- * First part of a shell escape,
- * parse the line, expanding # and % and ! and printing if implied.
- */
-unix0(warn)
- bool warn;
-{
- register char *up, *fp;
- register short c;
- char printub, puxb[UXBSIZE + sizeof (int)];
-
- printub = 0;
- CP(puxb, uxb);
- c = getchar();
- if (c == '\n' || c == EOF)
- error("Incomplete shell escape command@- use 'shell' to get a shell");
- up = uxb;
- do {
- switch (c) {
-
- case '\\':
- if (any(peekchar(), "%#!"))
- c = getchar();
- default:
- if (up >= &uxb[UXBSIZE]) {
-tunix:
- uxb[0] = 0;
- error("Command too long");
- }
- *up++ = c;
- break;
-
- case '!':
- fp = puxb;
- if (*fp == 0) {
- uxb[0] = 0;
- error("No previous command@to substitute for !");
- }
- printub++;
- while (*fp) {
- if (up >= &uxb[UXBSIZE])
- goto tunix;
- *up++ = *fp++;
- }
- break;
-
- case '#':
- fp = altfile;
- if (*fp == 0) {
- uxb[0] = 0;
- error("No alternate filename@to substitute for #");
- }
- goto uexp;
-
- case '%':
- fp = savedfile;
- if (*fp == 0) {
- uxb[0] = 0;
- error("No filename@to substitute for %%");
- }
-uexp:
- printub++;
- while (*fp) {
- if (up >= &uxb[UXBSIZE])
- goto tunix;
- *up++ = *fp++ | QUOTE;
- }
- break;
- }
- c = getchar();
- } while (c == '|' || !endcmd(c));
- if (c == EOF)
- ungetchar(c);
- *up = 0;
- if (!inopen)
- resetflav();
- if (warn)
- ckaw();
- if (warn && hush == 0 && chng && xchng != chng && value(WARN) && dol > zero) {
- xchng = chng;
- vnfl();
- printf(mesg("[No write]|[No write since last change]"));
- noonl();
- flush();
- } else
- warn = 0;
- if (printub) {
- if (uxb[0] == 0)
- error("No previous command@to repeat");
- if (inopen) {
- splitw++;
- vclean();
- vgoto(WECHO, 0);
- }
- if (warn)
- vnfl();
- if (hush == 0)
- lprintf("!%s", uxb);
- if (inopen) {
- vclreol();
- vgoto(WECHO, 0);
- } else
- putnl();
- flush();
- }
-}
-
-/*
- * Do the real work for execution of a shell escape.
- * Mode is like the number passed to open system calls
- * and indicates filtering. If input is implied, newstdin
- * must have been setup already.
- */
-unixex(opt, up, newstdin, mode)
- char *opt, *up;
- int newstdin, mode;
-{
- int pvec[2], f;
-
- signal(SIGINT, SIG_IGN);
- if (inopen)
- f = setty(normf);
- if ((mode & 1) && pipe(pvec) < 0) {
- /* Newstdin should be io so it will be closed */
- if (inopen)
- setty(f);
- error("Can't make pipe for filter");
- }
-#ifndef VFORK
- pid = fork();
-#else
- pid = vfork();
-#endif
- if (pid < 0) {
- if (mode & 1) {
- close(pvec[0]);
- close(pvec[1]);
- }
- setrupt();
- error("No more processes");
- }
- if (pid == 0) {
- if (mode & 2) {
- close(0);
- dup(newstdin);
- close(newstdin);
- }
- if (mode & 1) {
- close(pvec[0]);
- close(1);
- dup(pvec[1]);
- if (inopen) {
- close(2);
- dup(1);
- }
- close(pvec[1]);
- }
- if (io)
- close(io);
- if (tfile)
- close(tfile);
- close(erfile);
- signal(SIGHUP, oldhup);
- signal(SIGQUIT, oldquit);
- if (ruptible)
- signal(SIGINT, SIG_DFL);
- execl(svalue(SHELL), "sh", opt, up, (char *) 0);
- printf("No %s!\n", svalue(SHELL));
- error(NOSTR);
- }
- if (mode & 1) {
- io = pvec[0];
- close(pvec[1]);
- }
- if (newstdin)
- close(newstdin);
- return (f);
-}
-
-/*
- * Wait for the command to complete.
- * F is for restoration of tty mode if from open/visual.
- * C flags suppression of printing.
- */
-unixwt(c, f)
- bool c;
- int f;
-{
-
- waitfor();
- if (inopen)
- setty(f);
- setrupt();
- if (!inopen && c && hush == 0) {
- printf("!\n");
- flush();
- termreset();
- gettmode();
- }
-}
-
-/*
- * Setup a pipeline for the filtration implied by mode
- * which is like a open number. If input is required to
- * the filter, then a child editor is created to write it.
- * If output is catch it from io which is created by unixex.
- */
-filter(mode)
- register int mode;
-{
- static int pvec[2];
- register int f;
- register int lines = lineDOL();
-
- mode++;
- if (mode & 2) {
- signal(SIGINT, SIG_IGN);
- if (pipe(pvec) < 0)
- error("Can't make pipe");
- pid = fork();
- io = pvec[0];
- if (pid < 0) {
- setrupt();
- close(pvec[1]);
- error("No more processes");
- }
- if (pid == 0) {
- setrupt();
- io = pvec[1];
- close(pvec[0]);
- putfile();
- exit(0);
- }
- close(pvec[1]);
- io = pvec[0];
- setrupt();
- }
- f = unixex("-c", uxb, (mode & 2) ? pvec[0] : 0, mode);
- if (mode == 3) {
- delete(0);
- addr2 = addr1 - 1;
- }
- if (mode & 1) {
- undap1 = undap2 = addr2+1;
- ignore(append(getfile, addr2));
- }
- close(io);
- io = -1;
- unixwt(!inopen, f);
- netchHAD(lines);
-}
-
-/*
- * Set up to do a recover, getting io to be a pipe from
- * the recover process.
- */
-recover()
-{
- static int pvec[2];
-
- if (pipe(pvec) < 0)
- error(" Can't make pipe for recovery");
- pid = fork();
- io = pvec[0];
- if (pid < 0) {
- close(pvec[1]);
- error(" Can't fork to execute recovery");
- }
- if (pid == 0) {
- close(2);
- dup(1);
- close(1);
- dup(pvec[1]);
- close(pvec[1]);
- execl(EXRECOVER, "exrecover", svalue(DIRECTORY), file, (char *) 0);
- close(1);
- dup(2);
- error(" No recovery routine");
- }
- close(pvec[1]);
-}
-
-/*
- * Wait for the process (pid an external) to complete.
- */
-waitfor()
-{
-
- do
- rpid = wait(&status);
- while (rpid != pid && rpid != -1);
- status = (status >> 8) & 0377;
-}
-
-/*
- * The end of a recover operation. If the process
- * exits non-zero, force not edited; otherwise force
- * a write.
- */
-revocer()
-{
-
- waitfor();
- if (pid == rpid && status != 0)
- edited = 0;
- else
- change();
-}
-