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