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