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