|
|
1.1 ! root 1: /* Copyright (c) 1979 Regents of the University of California */ ! 2: static char *sccsid = "@(#)ex_unix.c 6.1 10/18/80"; ! 3: #include "ex.h" ! 4: #include "ex_temp.h" ! 5: #include "ex_tty.h" ! 6: #include "ex_vis.h" ! 7: ! 8: /* ! 9: * Unix escapes, filtering ! 10: */ ! 11: ! 12: /* ! 13: * First part of a shell escape, ! 14: * parse the line, expanding # and % and ! and printing if implied. ! 15: */ ! 16: unix0(warn) ! 17: bool warn; ! 18: { ! 19: register char *up, *fp; ! 20: register short c; ! 21: char printub, puxb[UXBSIZE + sizeof (int)]; ! 22: ! 23: printub = 0; ! 24: CP(puxb, uxb); ! 25: c = getchar(); ! 26: if (c == '\n' || c == EOF) ! 27: error("Incomplete shell escape command@- use 'shell' to get a shell"); ! 28: up = uxb; ! 29: do { ! 30: switch (c) { ! 31: ! 32: case '\\': ! 33: if (any(peekchar(), "%#!")) ! 34: c = getchar(); ! 35: default: ! 36: if (up >= &uxb[UXBSIZE]) { ! 37: tunix: ! 38: uxb[0] = 0; ! 39: error("Command too long"); ! 40: } ! 41: *up++ = c; ! 42: break; ! 43: ! 44: case '!': ! 45: fp = puxb; ! 46: if (*fp == 0) { ! 47: uxb[0] = 0; ! 48: error("No previous command@to substitute for !"); ! 49: } ! 50: printub++; ! 51: while (*fp) { ! 52: if (up >= &uxb[UXBSIZE]) ! 53: goto tunix; ! 54: *up++ = *fp++; ! 55: } ! 56: break; ! 57: ! 58: case '#': ! 59: fp = altfile; ! 60: if (*fp == 0) { ! 61: uxb[0] = 0; ! 62: error("No alternate filename@to substitute for #"); ! 63: } ! 64: goto uexp; ! 65: ! 66: case '%': ! 67: fp = savedfile; ! 68: if (*fp == 0) { ! 69: uxb[0] = 0; ! 70: error("No filename@to substitute for %%"); ! 71: } ! 72: uexp: ! 73: printub++; ! 74: while (*fp) { ! 75: if (up >= &uxb[UXBSIZE]) ! 76: goto tunix; ! 77: *up++ = *fp++ | QUOTE; ! 78: } ! 79: break; ! 80: } ! 81: c = getchar(); ! 82: } while (c == '"' || c == '|' || !endcmd(c)); ! 83: if (c == EOF) ! 84: ungetchar(c); ! 85: *up = 0; ! 86: if (!inopen) ! 87: resetflav(); ! 88: if (warn) ! 89: ckaw(); ! 90: if (warn && hush == 0 && chng && xchng != chng && value(WARN) && dol > zero) { ! 91: xchng = chng; ! 92: vnfl(); ! 93: printf(mesg("[No write]|[No write since last change]")); ! 94: noonl(); ! 95: flush(); ! 96: } else ! 97: warn = 0; ! 98: if (printub) { ! 99: if (uxb[0] == 0) ! 100: error("No previous command@to repeat"); ! 101: if (inopen) { ! 102: splitw++; ! 103: vclean(); ! 104: vgoto(WECHO, 0); ! 105: } ! 106: if (warn) ! 107: vnfl(); ! 108: if (hush == 0) ! 109: lprintf("!%s", uxb); ! 110: if (inopen && Outchar != termchar) { ! 111: vclreol(); ! 112: vgoto(WECHO, 0); ! 113: } else ! 114: putnl(); ! 115: flush(); ! 116: } ! 117: } ! 118: ! 119: /* ! 120: * Do the real work for execution of a shell escape. ! 121: * Mode is like the number passed to open system calls ! 122: * and indicates filtering. If input is implied, newstdin ! 123: * must have been setup already. ! 124: */ ! 125: ttymode ! 126: unixex(opt, up, newstdin, mode) ! 127: char *opt, *up; ! 128: int newstdin, mode; ! 129: { ! 130: int pvec[2]; ! 131: ttymode f; ! 132: ! 133: signal(SIGINT, SIG_IGN); ! 134: #ifdef SIGTSTP ! 135: if (dosusp) ! 136: signal(SIGTSTP, SIG_DFL); ! 137: #endif ! 138: if (inopen) ! 139: f = setty(normf); ! 140: if ((mode & 1) && pipe(pvec) < 0) { ! 141: /* Newstdin should be io so it will be closed */ ! 142: if (inopen) ! 143: setty(f); ! 144: error("Can't make pipe for filter"); ! 145: } ! 146: #ifndef VFORK ! 147: pid = fork(); ! 148: #else ! 149: pid = vfork(); ! 150: #endif ! 151: if (pid < 0) { ! 152: if (mode & 1) { ! 153: close(pvec[0]); ! 154: close(pvec[1]); ! 155: } ! 156: setrupt(); ! 157: error("No more processes"); ! 158: } ! 159: if (pid == 0) { ! 160: if (mode & 2) { ! 161: close(0); ! 162: dup(newstdin); ! 163: close(newstdin); ! 164: } ! 165: if (mode & 1) { ! 166: close(pvec[0]); ! 167: close(1); ! 168: dup(pvec[1]); ! 169: if (inopen) { ! 170: close(2); ! 171: dup(1); ! 172: } ! 173: close(pvec[1]); ! 174: } ! 175: if (io) ! 176: close(io); ! 177: if (tfile) ! 178: close(tfile); ! 179: #ifndef VMUNIX ! 180: close(erfile); ! 181: #endif ! 182: signal(SIGHUP, oldhup); ! 183: signal(SIGQUIT, oldquit); ! 184: if (ruptible) ! 185: signal(SIGINT, SIG_DFL); ! 186: execl(svalue(SHELL), "sh", opt, up, (char *) 0); ! 187: printf("No %s!\n", svalue(SHELL)); ! 188: error(NOSTR); ! 189: } ! 190: if (mode & 1) { ! 191: io = pvec[0]; ! 192: close(pvec[1]); ! 193: } ! 194: if (newstdin) ! 195: close(newstdin); ! 196: return (f); ! 197: } ! 198: ! 199: /* ! 200: * Wait for the command to complete. ! 201: * F is for restoration of tty mode if from open/visual. ! 202: * C flags suppression of printing. ! 203: */ ! 204: unixwt(c, f) ! 205: bool c; ! 206: ttymode f; ! 207: { ! 208: ! 209: waitfor(); ! 210: #ifdef SIGTSTP ! 211: if (dosusp) ! 212: signal(SIGTSTP, onsusp); ! 213: #endif ! 214: if (inopen) ! 215: setty(f); ! 216: setrupt(); ! 217: if (!inopen && c && hush == 0) { ! 218: printf("!\n"); ! 219: flush(); ! 220: termreset(); ! 221: gettmode(); ! 222: } ! 223: } ! 224: ! 225: /* ! 226: * Setup a pipeline for the filtration implied by mode ! 227: * which is like a open number. If input is required to ! 228: * the filter, then a child editor is created to write it. ! 229: * If output is catch it from io which is created by unixex. ! 230: */ ! 231: filter(mode) ! 232: register int mode; ! 233: { ! 234: static int pvec[2]; ! 235: register ttymode f; ! 236: register int lines = lineDOL(); ! 237: ! 238: mode++; ! 239: if (mode & 2) { ! 240: signal(SIGINT, SIG_IGN); ! 241: if (pipe(pvec) < 0) ! 242: error("Can't make pipe"); ! 243: pid = fork(); ! 244: io = pvec[0]; ! 245: if (pid < 0) { ! 246: setrupt(); ! 247: close(pvec[1]); ! 248: error("No more processes"); ! 249: } ! 250: if (pid == 0) { ! 251: setrupt(); ! 252: io = pvec[1]; ! 253: close(pvec[0]); ! 254: putfile(); ! 255: exit(0); ! 256: } ! 257: close(pvec[1]); ! 258: io = pvec[0]; ! 259: setrupt(); ! 260: } ! 261: f = unixex("-c", uxb, (mode & 2) ? pvec[0] : 0, mode); ! 262: if (mode == 3) { ! 263: delete(0); ! 264: addr2 = addr1 - 1; ! 265: } ! 266: if (mode & 1) { ! 267: if(FIXUNDO) ! 268: undap1 = undap2 = addr2+1; ! 269: ignore(append(getfile, addr2)); ! 270: #ifdef TRACE ! 271: if (trace) ! 272: vudump("after append in filter"); ! 273: #endif ! 274: } ! 275: close(io); ! 276: io = -1; ! 277: unixwt(!inopen, f); ! 278: netchHAD(lines); ! 279: } ! 280: ! 281: /* ! 282: * Set up to do a recover, getting io to be a pipe from ! 283: * the recover process. ! 284: */ ! 285: recover() ! 286: { ! 287: static int pvec[2]; ! 288: ! 289: if (pipe(pvec) < 0) ! 290: error(" Can't make pipe for recovery"); ! 291: pid = fork(); ! 292: io = pvec[0]; ! 293: if (pid < 0) { ! 294: close(pvec[1]); ! 295: error(" Can't fork to execute recovery"); ! 296: } ! 297: if (pid == 0) { ! 298: close(2); ! 299: dup(1); ! 300: close(1); ! 301: dup(pvec[1]); ! 302: close(pvec[1]); ! 303: execl(EXRECOVER, "exrecover", svalue(DIRECTORY), file, (char *) 0); ! 304: close(1); ! 305: dup(2); ! 306: error(" No recovery routine"); ! 307: } ! 308: close(pvec[1]); ! 309: } ! 310: ! 311: /* ! 312: * Wait for the process (pid an external) to complete. ! 313: */ ! 314: waitfor() ! 315: { ! 316: ! 317: do ! 318: rpid = wait(&status); ! 319: while (rpid != pid && rpid != -1); ! 320: status = (status >> 8) & 0377; ! 321: } ! 322: ! 323: /* ! 324: * The end of a recover operation. If the process ! 325: * exits non-zero, force not edited; otherwise force ! 326: * a write. ! 327: */ ! 328: revocer() ! 329: { ! 330: ! 331: waitfor(); ! 332: if (pid == rpid && status != 0) ! 333: edited = 0; ! 334: else ! 335: change(); ! 336: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.