|
|
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_io.c 7.11 (Berkeley) 6/7/85"; ! 9: #endif not lint ! 10: ! 11: #include "ex.h" ! 12: #include "ex_argv.h" ! 13: #include "ex_temp.h" ! 14: #include "ex_tty.h" ! 15: #include "ex_vis.h" ! 16: ! 17: /* ! 18: * File input/output, source, preserve and recover ! 19: */ ! 20: ! 21: /* ! 22: * Following remember where . was in the previous file for return ! 23: * on file switching. ! 24: */ ! 25: int altdot; ! 26: int oldadot; ! 27: bool wasalt; ! 28: short isalt; ! 29: ! 30: long cntch; /* Count of characters on unit io */ ! 31: #ifndef VMUNIX ! 32: short cntln; /* Count of lines " */ ! 33: #else ! 34: int cntln; ! 35: #endif ! 36: long cntnull; /* Count of nulls " */ ! 37: long cntodd; /* Count of non-ascii characters " */ ! 38: ! 39: /* ! 40: * Parse file name for command encoded by comm. ! 41: * If comm is E then command is doomed and we are ! 42: * parsing just so user won't have to retype the name. ! 43: */ ! 44: filename(comm) ! 45: int comm; ! 46: { ! 47: register int c = comm, d; ! 48: register int i; ! 49: ! 50: d = getchar(); ! 51: if (endcmd(d)) { ! 52: if (savedfile[0] == 0 && comm != 'f') ! 53: error("No file|No current filename"); ! 54: CP(file, savedfile); ! 55: wasalt = (isalt > 0) ? isalt-1 : 0; ! 56: isalt = 0; ! 57: oldadot = altdot; ! 58: if (c == 'e' || c == 'E') ! 59: altdot = lineDOT(); ! 60: if (d == EOF) ! 61: ungetchar(d); ! 62: } else { ! 63: ungetchar(d); ! 64: getone(); ! 65: eol(); ! 66: if (savedfile[0] == 0 && c != 'E' && c != 'e') { ! 67: c = 'e'; ! 68: edited = 0; ! 69: } ! 70: wasalt = strcmp(file, altfile) == 0; ! 71: oldadot = altdot; ! 72: switch (c) { ! 73: ! 74: case 'f': ! 75: edited = 0; ! 76: /* fall into ... */ ! 77: ! 78: case 'e': ! 79: if (savedfile[0]) { ! 80: altdot = lineDOT(); ! 81: CP(altfile, savedfile); ! 82: } ! 83: CP(savedfile, file); ! 84: break; ! 85: ! 86: default: ! 87: if (file[0]) { ! 88: if (c != 'E') ! 89: altdot = lineDOT(); ! 90: CP(altfile, file); ! 91: } ! 92: break; ! 93: } ! 94: } ! 95: if (hush && comm != 'f' || comm == 'E') ! 96: return; ! 97: if (file[0] != 0) { ! 98: lprintf("\"%s\"", file); ! 99: if (comm == 'f') { ! 100: if (value(READONLY)) ! 101: printf(" [Read only]"); ! 102: if (!edited) ! 103: printf(" [Not edited]"); ! 104: if (tchng) ! 105: printf(" [Modified]"); ! 106: } ! 107: flush(); ! 108: } else ! 109: printf("No file "); ! 110: if (comm == 'f') { ! 111: if (!(i = lineDOL())) ! 112: i++; ! 113: printf(" line %d of %d --%ld%%--", lineDOT(), lineDOL(), ! 114: (long) 100 * lineDOT() / i); ! 115: } ! 116: } ! 117: ! 118: /* ! 119: * Get the argument words for a command into genbuf ! 120: * expanding # and %. ! 121: */ ! 122: getargs() ! 123: { ! 124: register int c; ! 125: register char *cp, *fp; ! 126: static char fpatbuf[32]; /* hence limit on :next +/pat */ ! 127: ! 128: pastwh(); ! 129: if (peekchar() == '+') { ! 130: for (cp = fpatbuf;;) { ! 131: c = *cp++ = getchar(); ! 132: if (cp >= &fpatbuf[sizeof(fpatbuf)]) ! 133: error("Pattern too long"); ! 134: if (c == '\\' && isspace(peekchar())) ! 135: c = getchar(); ! 136: if (c == EOF || isspace(c)) { ! 137: ungetchar(c); ! 138: *--cp = 0; ! 139: firstpat = &fpatbuf[1]; ! 140: break; ! 141: } ! 142: } ! 143: } ! 144: if (skipend()) ! 145: return (0); ! 146: CP(genbuf, "echo "); cp = &genbuf[5]; ! 147: for (;;) { ! 148: c = getchar(); ! 149: if (endcmd(c)) { ! 150: ungetchar(c); ! 151: break; ! 152: } ! 153: switch (c) { ! 154: ! 155: case '\\': ! 156: if (any(peekchar(), "#%|")) ! 157: c = getchar(); ! 158: /* fall into... */ ! 159: ! 160: default: ! 161: if (cp > &genbuf[LBSIZE - 2]) ! 162: flong: ! 163: error("Argument buffer overflow"); ! 164: *cp++ = c; ! 165: break; ! 166: ! 167: case '#': ! 168: fp = altfile; ! 169: if (*fp == 0) ! 170: error("No alternate filename@to substitute for #"); ! 171: goto filexp; ! 172: ! 173: case '%': ! 174: fp = savedfile; ! 175: if (*fp == 0) ! 176: error("No current filename@to substitute for %%"); ! 177: filexp: ! 178: while (*fp) { ! 179: if (cp > &genbuf[LBSIZE - 2]) ! 180: goto flong; ! 181: *cp++ = *fp++; ! 182: } ! 183: break; ! 184: } ! 185: } ! 186: *cp = 0; ! 187: return (1); ! 188: } ! 189: ! 190: /* ! 191: * Glob the argument words in genbuf, or if no globbing ! 192: * is implied, just split them up directly. ! 193: */ ! 194: glob(gp) ! 195: struct glob *gp; ! 196: { ! 197: int pvec[2]; ! 198: register char **argv = gp->argv; ! 199: register char *cp = gp->argspac; ! 200: register int c; ! 201: char ch; ! 202: int nleft = NCARGS; ! 203: ! 204: gp->argc0 = 0; ! 205: if (gscan() == 0) { ! 206: register char *v = genbuf + 5; /* strlen("echo ") */ ! 207: ! 208: for (;;) { ! 209: while (isspace(*v)) ! 210: v++; ! 211: if (!*v) ! 212: break; ! 213: *argv++ = cp; ! 214: while (*v && !isspace(*v)) ! 215: *cp++ = *v++; ! 216: *cp++ = 0; ! 217: gp->argc0++; ! 218: } ! 219: *argv = 0; ! 220: return; ! 221: } ! 222: if (pipe(pvec) < 0) ! 223: error("Can't make pipe to glob"); ! 224: pid = fork(); ! 225: io = pvec[0]; ! 226: if (pid < 0) { ! 227: close(pvec[1]); ! 228: error("Can't fork to do glob"); ! 229: } ! 230: if (pid == 0) { ! 231: int oerrno; ! 232: ! 233: close(1); ! 234: dup(pvec[1]); ! 235: close(pvec[0]); ! 236: close(2); /* so errors don't mess up the screen */ ! 237: open("/dev/null", 1); ! 238: execl(svalue(SHELL), "sh", "-c", genbuf, 0); ! 239: oerrno = errno; close(1); dup(2); errno = oerrno; ! 240: filioerr(svalue(SHELL)); ! 241: } ! 242: close(pvec[1]); ! 243: do { ! 244: *argv = cp; ! 245: for (;;) { ! 246: if (read(io, &ch, 1) != 1) { ! 247: close(io); ! 248: c = -1; ! 249: } else ! 250: c = ch & TRIM; ! 251: if (c <= 0 || isspace(c)) ! 252: break; ! 253: *cp++ = c; ! 254: if (--nleft <= 0) ! 255: error("Arg list too long"); ! 256: } ! 257: if (cp != *argv) { ! 258: --nleft; ! 259: *cp++ = 0; ! 260: gp->argc0++; ! 261: if (gp->argc0 >= NARGS) ! 262: error("Arg list too long"); ! 263: argv++; ! 264: } ! 265: } while (c >= 0); ! 266: waitfor(); ! 267: if (gp->argc0 == 0) ! 268: error("No match"); ! 269: } ! 270: ! 271: /* ! 272: * Scan genbuf for shell metacharacters. ! 273: * Set is union of v7 shell and csh metas. ! 274: */ ! 275: gscan() ! 276: { ! 277: register char *cp; ! 278: ! 279: for (cp = genbuf; *cp; cp++) ! 280: if (any(*cp, "~{[*?$`'\"\\")) ! 281: return (1); ! 282: return (0); ! 283: } ! 284: ! 285: /* ! 286: * Parse one filename into file. ! 287: */ ! 288: struct glob G; ! 289: getone() ! 290: { ! 291: register char *str; ! 292: ! 293: if (getargs() == 0) ! 294: error("Missing filename"); ! 295: glob(&G); ! 296: if (G.argc0 > 1) ! 297: error("Ambiguous|Too many file names"); ! 298: str = G.argv[G.argc0 - 1]; ! 299: if (strlen(str) > FNSIZE - 4) ! 300: error("Filename too long"); ! 301: samef: ! 302: CP(file, str); ! 303: } ! 304: ! 305: /* ! 306: * Read a file from the world. ! 307: * C is command, 'e' if this really an edit (or a recover). ! 308: */ ! 309: rop(c) ! 310: int c; ! 311: { ! 312: register int i; ! 313: struct stat stbuf; ! 314: short magic; ! 315: static int ovro; /* old value(READONLY) */ ! 316: static int denied; /* 1 if READONLY was set due to file permissions */ ! 317: ! 318: io = open(file, 0); ! 319: if (io < 0) { ! 320: if (c == 'e' && errno == ENOENT) { ! 321: edited++; ! 322: /* ! 323: * If the user just did "ex foo" he is probably ! 324: * creating a new file. Don't be an error, since ! 325: * this is ugly, and it screws up the + option. ! 326: */ ! 327: if (!seenprompt) { ! 328: printf(" [New file]"); ! 329: noonl(); ! 330: return; ! 331: } ! 332: } ! 333: syserror(); ! 334: } ! 335: if (fstat(io, &stbuf)) ! 336: syserror(); ! 337: switch (stbuf.st_mode & S_IFMT) { ! 338: ! 339: case S_IFBLK: ! 340: error(" Block special file"); ! 341: ! 342: case S_IFCHR: ! 343: if (isatty(io)) ! 344: error(" Teletype"); ! 345: if (samei(&stbuf, "/dev/null")) ! 346: break; ! 347: error(" Character special file"); ! 348: ! 349: case S_IFDIR: ! 350: error(" Directory"); ! 351: ! 352: case S_IFREG: ! 353: #ifdef CRYPT ! 354: if (xflag) ! 355: break; ! 356: #endif ! 357: i = read(io, (char *) &magic, sizeof(magic)); ! 358: lseek(io, 0l, 0); ! 359: if (i != sizeof(magic)) ! 360: break; ! 361: switch (magic) { ! 362: ! 363: case 0405: /* data overlay on exec */ ! 364: case 0407: /* unshared */ ! 365: case 0410: /* shared text */ ! 366: case 0411: /* separate I/D */ ! 367: case 0413: /* VM/Unix demand paged */ ! 368: case 0430: /* PDP-11 Overlay shared */ ! 369: case 0431: /* PDP-11 Overlay sep I/D */ ! 370: error(" Executable"); ! 371: ! 372: /* ! 373: * We do not forbid the editing of portable archives ! 374: * because it is reasonable to edit them, especially ! 375: * if they are archives of text files. This is ! 376: * especially useful if you archive source files together ! 377: * and copy them to another system with ~%take, since ! 378: * the files sometimes show up munged and must be fixed. ! 379: */ ! 380: case 0177545: ! 381: case 0177555: ! 382: error(" Archive"); ! 383: ! 384: default: ! 385: #ifdef mbb ! 386: /* C/70 has a 10 bit byte */ ! 387: if (magic & 03401600) ! 388: #else ! 389: /* Everybody else has an 8 bit byte */ ! 390: if (magic & 0100200) ! 391: #endif ! 392: error(" Non-ascii file"); ! 393: break; ! 394: } ! 395: } ! 396: if (c != 'r') { ! 397: if (value(READONLY) && denied) { ! 398: value(READONLY) = ovro; ! 399: denied = 0; ! 400: } ! 401: if ((stbuf.st_mode & 0222) == 0 || access(file, 2) < 0) { ! 402: ovro = value(READONLY); ! 403: denied = 1; ! 404: value(READONLY) = 1; ! 405: } ! 406: } ! 407: if (value(READONLY)) { ! 408: printf(" [Read only]"); ! 409: flush(); ! 410: } ! 411: if (c == 'r') ! 412: setdot(); ! 413: else ! 414: setall(); ! 415: if (FIXUNDO && inopen && c == 'r') ! 416: undap1 = undap2 = dot + 1; ! 417: rop2(); ! 418: rop3(c); ! 419: } ! 420: ! 421: rop2() ! 422: { ! 423: line *first, *last, *a; ! 424: struct stat statb; ! 425: ! 426: deletenone(); ! 427: clrstats(); ! 428: first = addr2 + 1; ! 429: if (fstat(io, &statb) < 0) ! 430: bsize = LBSIZE; ! 431: else { ! 432: bsize = statb.st_blksize; ! 433: if (bsize <= 0) ! 434: bsize = LBSIZE; ! 435: } ! 436: ignore(append(getfile, addr2)); ! 437: last = dot; ! 438: /* ! 439: * if the modeline variable is set, ! 440: * check the first and last five lines of the file ! 441: * for a mode line. ! 442: */ ! 443: if (value(MODELINE)) { ! 444: for (a=first; a<=last; a++) { ! 445: if (a==first+5 && last-first > 10) ! 446: a = last - 4; ! 447: getline(*a); ! 448: checkmodeline(linebuf); ! 449: } ! 450: } ! 451: } ! 452: ! 453: rop3(c) ! 454: int c; ! 455: { ! 456: ! 457: if (iostats() == 0 && c == 'e') ! 458: edited++; ! 459: if (c == 'e') { ! 460: if (wasalt || firstpat) { ! 461: register line *addr = zero + oldadot; ! 462: ! 463: if (addr > dol) ! 464: addr = dol; ! 465: if (firstpat) { ! 466: globp = (*firstpat) ? firstpat : "$"; ! 467: commands(1,1); ! 468: firstpat = 0; ! 469: } else if (addr >= one) { ! 470: if (inopen) ! 471: dot = addr; ! 472: markpr(addr); ! 473: } else ! 474: goto other; ! 475: } else ! 476: other: ! 477: if (dol > zero) { ! 478: if (inopen) ! 479: dot = one; ! 480: markpr(one); ! 481: } ! 482: if(FIXUNDO) ! 483: undkind = UNDNONE; ! 484: if (inopen) { ! 485: vcline = 0; ! 486: vreplace(0, LINES, lineDOL()); ! 487: } ! 488: } ! 489: } ! 490: ! 491: /* ! 492: * Are these two really the same inode? ! 493: */ ! 494: samei(sp, cp) ! 495: struct stat *sp; ! 496: char *cp; ! 497: { ! 498: struct stat stb; ! 499: ! 500: if (stat(cp, &stb) < 0 || sp->st_dev != stb.st_dev) ! 501: return (0); ! 502: return (sp->st_ino == stb.st_ino); ! 503: } ! 504: ! 505: /* Returns from edited() */ ! 506: #define EDF 0 /* Edited file */ ! 507: #define NOTEDF -1 /* Not edited file */ ! 508: #define PARTBUF 1 /* Write of partial buffer to Edited file */ ! 509: ! 510: /* ! 511: * Write a file. ! 512: */ ! 513: wop(dofname) ! 514: bool dofname; /* if 1 call filename, else use savedfile */ ! 515: { ! 516: register int c, exclam, nonexist; ! 517: line *saddr1, *saddr2; ! 518: struct stat stbuf; ! 519: ! 520: c = 0; ! 521: exclam = 0; ! 522: if (dofname) { ! 523: if (peekchar() == '!') ! 524: exclam++, ignchar(); ! 525: ignore(skipwh()); ! 526: while (peekchar() == '>') ! 527: ignchar(), c++, ignore(skipwh()); ! 528: if (c != 0 && c != 2) ! 529: error("Write forms are 'w' and 'w>>'"); ! 530: filename('w'); ! 531: } else { ! 532: if (savedfile[0] == 0) ! 533: error("No file|No current filename"); ! 534: saddr1=addr1; ! 535: saddr2=addr2; ! 536: addr1=one; ! 537: addr2=dol; ! 538: CP(file, savedfile); ! 539: if (inopen) { ! 540: vclrech(0); ! 541: splitw++; ! 542: } ! 543: lprintf("\"%s\"", file); ! 544: } ! 545: nonexist = stat(file, &stbuf); ! 546: switch (c) { ! 547: ! 548: case 0: ! 549: if (!exclam && (!value(WRITEANY) || value(READONLY))) ! 550: switch (edfile()) { ! 551: ! 552: case NOTEDF: ! 553: if (nonexist) ! 554: break; ! 555: if ((stbuf.st_mode & S_IFMT) == S_IFCHR) { ! 556: if (samei(&stbuf, "/dev/null")) ! 557: break; ! 558: if (samei(&stbuf, "/dev/tty")) ! 559: break; ! 560: } ! 561: io = open(file, 1); ! 562: if (io < 0) ! 563: syserror(); ! 564: if (!isatty(io)) ! 565: serror(" File exists| File exists - use \"w! %s\" to overwrite", file); ! 566: close(io); ! 567: break; ! 568: ! 569: case EDF: ! 570: if (value(READONLY)) ! 571: error(" File is read only"); ! 572: break; ! 573: ! 574: case PARTBUF: ! 575: if (value(READONLY)) ! 576: error(" File is read only"); ! 577: error(" Use \"w!\" to write partial buffer"); ! 578: } ! 579: cre: ! 580: /* ! 581: synctmp(); ! 582: */ ! 583: #ifdef V6 ! 584: io = creat(file, 0644); ! 585: #else ! 586: io = creat(file, 0666); ! 587: #endif ! 588: if (io < 0) ! 589: syserror(); ! 590: writing = 1; ! 591: if (hush == 0) ! 592: if (nonexist) ! 593: printf(" [New file]"); ! 594: else if (value(WRITEANY) && edfile() != EDF) ! 595: printf(" [Existing file]"); ! 596: break; ! 597: ! 598: case 2: ! 599: io = open(file, 1); ! 600: if (io < 0) { ! 601: if (exclam || value(WRITEANY)) ! 602: goto cre; ! 603: syserror(); ! 604: } ! 605: lseek(io, 0l, 2); ! 606: break; ! 607: } ! 608: putfile(0); ! 609: ignore(iostats()); ! 610: if (c != 2 && addr1 == one && addr2 == dol) { ! 611: if (eq(file, savedfile)) ! 612: edited = 1; ! 613: sync(); ! 614: } ! 615: if (!dofname) { ! 616: addr1 = saddr1; ! 617: addr2 = saddr2; ! 618: } ! 619: writing = 0; ! 620: } ! 621: ! 622: /* ! 623: * Is file the edited file? ! 624: * Work here is that it is not considered edited ! 625: * if this is a partial buffer, and distinguish ! 626: * all cases. ! 627: */ ! 628: edfile() ! 629: { ! 630: ! 631: if (!edited || !eq(file, savedfile)) ! 632: return (NOTEDF); ! 633: return (addr1 == one && addr2 == dol ? EDF : PARTBUF); ! 634: } ! 635: ! 636: /* ! 637: * Extract the next line from the io stream. ! 638: */ ! 639: char *nextip; ! 640: ! 641: getfile() ! 642: { ! 643: register short c; ! 644: register char *lp, *fp; ! 645: ! 646: lp = linebuf; ! 647: fp = nextip; ! 648: do { ! 649: if (--ninbuf < 0) { ! 650: ninbuf = read(io, genbuf, bsize) - 1; ! 651: if (ninbuf < 0) { ! 652: if (lp != linebuf) { ! 653: lp++; ! 654: printf(" [Incomplete last line]"); ! 655: break; ! 656: } ! 657: return (EOF); ! 658: } ! 659: #ifdef CRYPT ! 660: if (kflag) { ! 661: fp = genbuf; ! 662: while(fp < &genbuf[ninbuf]) { ! 663: if (*fp++ & 0200) { ! 664: crblock(perm, genbuf, ninbuf+1, ! 665: cntch); ! 666: break; ! 667: } ! 668: } ! 669: } ! 670: #endif ! 671: fp = genbuf; ! 672: cntch += ninbuf+1; ! 673: } ! 674: if (lp >= &linebuf[LBSIZE]) { ! 675: error(" Line too long"); ! 676: } ! 677: c = *fp++; ! 678: if (c == 0) { ! 679: cntnull++; ! 680: continue; ! 681: } ! 682: if (c & QUOTE) { ! 683: cntodd++; ! 684: c &= TRIM; ! 685: if (c == 0) ! 686: continue; ! 687: } ! 688: *lp++ = c; ! 689: } while (c != '\n'); ! 690: *--lp = 0; ! 691: nextip = fp; ! 692: cntln++; ! 693: return (0); ! 694: } ! 695: ! 696: /* ! 697: * Write a range onto the io stream. ! 698: */ ! 699: putfile(isfilter) ! 700: int isfilter; ! 701: { ! 702: line *a1; ! 703: register char *fp, *lp; ! 704: register int nib; ! 705: struct stat statb; ! 706: ! 707: a1 = addr1; ! 708: clrstats(); ! 709: cntln = addr2 - a1 + 1; ! 710: if (cntln == 0) ! 711: return; ! 712: if (fstat(io, &statb) < 0) ! 713: bsize = LBSIZE; ! 714: else { ! 715: bsize = statb.st_blksize; ! 716: if (bsize <= 0) ! 717: bsize = LBSIZE; ! 718: } ! 719: nib = bsize; ! 720: fp = genbuf; ! 721: do { ! 722: getline(*a1++); ! 723: lp = linebuf; ! 724: for (;;) { ! 725: if (--nib < 0) { ! 726: nib = fp - genbuf; ! 727: #ifdef CRYPT ! 728: if(kflag && !isfilter) ! 729: crblock(perm, genbuf, nib, cntch); ! 730: #endif ! 731: if (write(io, genbuf, nib) != nib) { ! 732: wrerror(); ! 733: } ! 734: cntch += nib; ! 735: nib = bsize - 1; ! 736: fp = genbuf; ! 737: } ! 738: if ((*fp++ = *lp++) == 0) { ! 739: fp[-1] = '\n'; ! 740: break; ! 741: } ! 742: } ! 743: } while (a1 <= addr2); ! 744: nib = fp - genbuf; ! 745: #ifdef CRYPT ! 746: if(kflag && !isfilter) ! 747: crblock(perm, genbuf, nib, cntch); ! 748: #endif ! 749: if (write(io, genbuf, nib) != nib) { ! 750: wrerror(); ! 751: } ! 752: cntch += nib; ! 753: } ! 754: ! 755: /* ! 756: * A write error has occurred; if the file being written was ! 757: * the edited file then we consider it to have changed since it is ! 758: * now likely scrambled. ! 759: */ ! 760: wrerror() ! 761: { ! 762: ! 763: if (eq(file, savedfile) && edited) ! 764: change(); ! 765: syserror(); ! 766: } ! 767: ! 768: /* ! 769: * Source command, handles nested sources. ! 770: * Traps errors since it mungs unit 0 during the source. ! 771: */ ! 772: short slevel; ! 773: short ttyindes; ! 774: ! 775: source(fil, okfail) ! 776: char *fil; ! 777: bool okfail; ! 778: { ! 779: jmp_buf osetexit; ! 780: register int saveinp, ointty, oerrno; ! 781: char *saveglobp; ! 782: short savepeekc; ! 783: ! 784: signal(SIGINT, SIG_IGN); ! 785: saveinp = dup(0); ! 786: savepeekc = peekc; ! 787: saveglobp = globp; ! 788: peekc = 0; globp = 0; ! 789: if (saveinp < 0) ! 790: error("Too many nested sources"); ! 791: if (slevel <= 0) ! 792: ttyindes = saveinp; ! 793: close(0); ! 794: if (open(fil, 0) < 0) { ! 795: oerrno = errno; ! 796: setrupt(); ! 797: dup(saveinp); ! 798: close(saveinp); ! 799: errno = oerrno; ! 800: if (!okfail) ! 801: filioerr(fil); ! 802: return; ! 803: } ! 804: slevel++; ! 805: ointty = intty; ! 806: intty = isatty(0); ! 807: oprompt = value(PROMPT); ! 808: value(PROMPT) &= intty; ! 809: getexit(osetexit); ! 810: setrupt(); ! 811: if (setexit() == 0) ! 812: commands(1, 1); ! 813: else if (slevel > 1) { ! 814: close(0); ! 815: dup(saveinp); ! 816: close(saveinp); ! 817: slevel--; ! 818: resexit(osetexit); ! 819: reset(); ! 820: } ! 821: intty = ointty; ! 822: value(PROMPT) = oprompt; ! 823: close(0); ! 824: dup(saveinp); ! 825: close(saveinp); ! 826: globp = saveglobp; ! 827: peekc = savepeekc; ! 828: slevel--; ! 829: resexit(osetexit); ! 830: } ! 831: ! 832: /* ! 833: * Clear io statistics before a read or write. ! 834: */ ! 835: clrstats() ! 836: { ! 837: ! 838: ninbuf = 0; ! 839: cntch = 0; ! 840: cntln = 0; ! 841: cntnull = 0; ! 842: cntodd = 0; ! 843: } ! 844: ! 845: /* ! 846: * Io is finished, close the unit and print statistics. ! 847: */ ! 848: iostats() ! 849: { ! 850: ! 851: (void) fsync(io); ! 852: close(io); ! 853: io = -1; ! 854: if (hush == 0) { ! 855: if (value(TERSE)) ! 856: printf(" %d/%D", cntln, cntch); ! 857: else ! 858: printf(" %d line%s, %D character%s", cntln, plural((long) cntln), ! 859: cntch, plural(cntch)); ! 860: if (cntnull || cntodd) { ! 861: printf(" ("); ! 862: if (cntnull) { ! 863: printf("%D null", cntnull); ! 864: if (cntodd) ! 865: printf(", "); ! 866: } ! 867: if (cntodd) ! 868: printf("%D non-ASCII", cntodd); ! 869: putchar(')'); ! 870: } ! 871: noonl(); ! 872: flush(); ! 873: } ! 874: return (cntnull != 0 || cntodd != 0); ! 875: } ! 876: ! 877: #if USG | USG3TTY ! 878: /* It's so wonderful how we all speak the same language... */ ! 879: # define index strchr ! 880: # define rindex strrchr ! 881: #endif ! 882: ! 883: checkmodeline(line) ! 884: char *line; ! 885: { ! 886: char *beg, *end; ! 887: char cmdbuf[1024]; ! 888: char *index(), *rindex(); ! 889: ! 890: beg = index(line, ':'); ! 891: if (beg == NULL) ! 892: return; ! 893: if (&beg[-3] < line) ! 894: return; ! 895: if (!( ( (beg[-3] == ' ' || beg[-3] == '\t') ! 896: && beg[-2] == 'e' ! 897: && beg[-1] == 'x') ! 898: || ( (beg[-3] == ' ' || beg[-3] == '\t') ! 899: && beg[-2] == 'v' ! 900: && beg[-1] == 'i'))) return; ! 901: strncpy(cmdbuf, beg+1, sizeof cmdbuf); ! 902: end = rindex(cmdbuf, ':'); ! 903: if (end == NULL) ! 904: return; ! 905: *end = 0; ! 906: globp = cmdbuf; ! 907: commands(1, 1); ! 908: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.