From 9cf6814f6a540f9c1b078dd667afe748fe022304 Mon Sep 17 00:00:00 2001 From: Mark Horton Date: Fri, 1 Aug 1980 07:41:11 -0800 Subject: [PATCH] date and time created 80/08/01 00:41:11 by mark SCCS-vsn: usr.bin/ex/ex_unix.c 4.1 --- usr/src/usr.bin/ex/ex_unix.c | 331 +++++++++++++++++++++++++++++++++++ 1 file changed, 331 insertions(+) create mode 100644 usr/src/usr.bin/ex/ex_unix.c diff --git a/usr/src/usr.bin/ex/ex_unix.c b/usr/src/usr.bin/ex/ex_unix.c new file mode 100644 index 0000000000..20757f182a --- /dev/null +++ b/usr/src/usr.bin/ex/ex_unix.c @@ -0,0 +1,331 @@ +/* Copyright (c) 1979 Regents of the University of California */ +#include "ex.h" +#include "ex_temp.h" +#include "ex_tty.h" +#include "ex_vis.h" + +/* + * Unix escapes, filtering + */ + +/* + * 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 == '"' || 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 && Outchar != termchar) { + 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. + */ +ttymode +unixex(opt, up, newstdin, mode) + char *opt, *up; + int newstdin, mode; +{ + int pvec[2]; + ttymode f; + + signal(SIGINT, SIG_IGN); +#ifdef TIOCLGET + if (dosusp) + signal(SIGTSTP, SIG_DFL); +#endif + 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); +#ifndef VMUNIX + close(erfile); +#endif + 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; + ttymode f; +{ + + waitfor(); +#ifdef TIOCLGET + if (dosusp) + signal(SIGTSTP, onsusp); +#endif + 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 ttymode 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) { + if(FIXUNDO) + 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(); +} -- 2.20.1