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: ttymode f; /* mjm: was register */ 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(1); 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: if (!(status & 0377)) { 321: status = (status >> 8) & 0377; 322: } else { 323: printf("%d: terminated with signal %d",pid,status & 0177); 324: if (status & 0200) 325: printf(" -- core dumped"); 326: putchar('\n'); 327: } 328: } 329: 330: /* 331: * The end of a recover operation. If the process 332: * exits non-zero, force not edited; otherwise force 333: * a write. 334: */ 335: revocer() 336: { 337: 338: waitfor(); 339: if (pid == rpid && status != 0) 340: edited = 0; 341: else 342: change(); 343: }