Annotation of 43BSDTahoe/ucb/ex/exrecover.c, revision 1.1.1.1

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: char *copyright =
                      9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
                     10:  All rights reserved.\n";
                     11: #endif not lint
                     12: 
                     13: #ifndef lint
                     14: static char *sccsid = "@(#)exrecover.c 7.9 (Berkeley) 6/7/85";
                     15: #endif not lint
                     16: 
                     17: #include <stdio.h>     /* mjm: BUFSIZ: stdio = 512, VMUNIX = 1024 */
                     18: #undef BUFSIZ          /* mjm: BUFSIZ different */
                     19: #undef EOF             /* mjm: EOF and NULL effectively the same */
                     20: #undef NULL
                     21: 
                     22: #include "ex.h"
                     23: #include "ex_temp.h"
                     24: #include "ex_tty.h"
                     25: #include <sys/dir.h>
                     26: #include "uparm.h"
                     27: 
                     28: char xstr[1];          /* make loader happy */
                     29: short tfile = -1;      /* ditto */
                     30: 
                     31: /*
                     32:  *
                     33:  * This program searches through the specified directory and then
                     34:  * the directory usrpath(preserve) looking for an instance of the specified
                     35:  * file from a crashed editor or a crashed system.
                     36:  * If this file is found, it is unscrambled and written to
                     37:  * the standard output.
                     38:  *
                     39:  * If this program terminates without a "broken pipe" diagnostic
                     40:  * (i.e. the editor doesn't die right away) then the buffer we are
                     41:  * writing from is removed when we finish.  This is potentially a mistake
                     42:  * as there is not enough handshaking to guarantee that the file has actually
                     43:  * been recovered, but should suffice for most cases.
                     44:  */
                     45: 
                     46: /*
                     47:  * For lint's sake...
                     48:  */
                     49: #ifndef lint
                     50: #define        ignorl(a)       a
                     51: #endif
                     52: 
                     53: /*
                     54:  * This directory definition also appears (obviously) in expreserve.c.
                     55:  * Change both if you change either.
                     56:  */
                     57: char   mydir[] =       usrpath(preserve);
                     58: 
                     59: /*
                     60:  * Limit on the number of printed entries
                     61:  * when an, e.g. ``ex -r'' command is given.
                     62:  */
                     63: #define        NENTRY  50
                     64: 
                     65: char   *ctime();
                     66: char   nb[BUFSIZ];
                     67: int    vercnt;                 /* Count number of versions of file found */
                     68: 
                     69: main(argc, argv)
                     70:        int argc;
                     71:        char *argv[];
                     72: {
                     73:        register char *cp;
                     74:        register int b, i;
                     75: 
                     76:        /*
                     77:         * Initialize as though the editor had just started.
                     78:         */
                     79:        fendcore = (line *) sbrk(0);
                     80:        dot = zero = dol = fendcore;
                     81:        one = zero + 1;
                     82:        endcore = fendcore - 2;
                     83:        iblock = oblock = -1;
                     84: 
                     85:        /*
                     86:         * If given only a -r argument, then list the saved files.
                     87:         */
                     88:        if (argc == 2 && eq(argv[1], "-r")) {
                     89:                listfiles(mydir);
                     90:                exit(0);
                     91:        }
                     92:        if (argc != 3)
                     93:                error(" Wrong number of arguments to exrecover", 0);
                     94: 
                     95:        CP(file, argv[2]);
                     96: 
                     97:        /*
                     98:         * Search for this file.
                     99:         */
                    100:        findtmp(argv[1]);
                    101: 
                    102:        /*
                    103:         * Got (one of the versions of) it, write it back to the editor.
                    104:         */
                    105:        cp = ctime(&H.Time);
                    106:        cp[19] = 0;
                    107:        fprintf(stderr, " [Dated: %s", cp);
                    108:        fprintf(stderr, vercnt > 1 ? ", newest of %d saved]" : "]", vercnt);
                    109:        H.Flines++;
                    110: 
                    111:        /*
                    112:         * Allocate space for the line pointers from the temp file.
                    113:         */
                    114:        if ((int) sbrk((int) (H.Flines * sizeof (line))) == -1)
                    115:                /*
                    116:                 * Good grief.
                    117:                 */
                    118:                error(" Not enough core for lines", 0);
                    119: #ifdef DEBUG
                    120:        fprintf(stderr, "%d lines\n", H.Flines);
                    121: #endif
                    122: 
                    123:        /*
                    124:         * Now go get the blocks of seek pointers which are scattered
                    125:         * throughout the temp file, reconstructing the incore
                    126:         * line pointers at point of crash.
                    127:         */
                    128:        b = 0;
                    129:        while (H.Flines > 0) {
                    130:                ignorl(lseek(tfile, (long) blocks[b] * BUFSIZ, 0));
                    131:                i = H.Flines < BUFSIZ / sizeof (line) ?
                    132:                        H.Flines * sizeof (line) : BUFSIZ;
                    133:                if (read(tfile, (char *) dot, i) != i) {
                    134:                        perror(nb);
                    135:                        exit(1);
                    136:                }
                    137:                dot += i / sizeof (line);
                    138:                H.Flines -= i / sizeof (line);
                    139:                b++;
                    140:        }
                    141:        dot--; dol = dot;
                    142: 
                    143:        /*
                    144:         * Sigh... due to sandbagging some lines may really not be there.
                    145:         * Find and discard such.  This shouldn't happen much.
                    146:         */
                    147:        scrapbad();
                    148: 
                    149:        /*
                    150:         * Now if there were any lines in the recovered file
                    151:         * write them to the standard output.
                    152:         */
                    153:        if (dol > zero) {
                    154:                addr1 = one; addr2 = dol; io = 1;
                    155:                putfile(0);
                    156:        }
                    157: 
                    158:        /*
                    159:         * Trash the saved buffer.
                    160:         * Hopefully the system won't crash before the editor
                    161:         * syncs the new recovered buffer; i.e. for an instant here
                    162:         * you may lose if the system crashes because this file
                    163:         * is gone, but the editor hasn't completed reading the recovered
                    164:         * file from the pipe from us to it.
                    165:         *
                    166:         * This doesn't work if we are coming from an non-absolute path
                    167:         * name since we may have chdir'ed but what the hay, noone really
                    168:         * ever edits with temporaries in "." anyways.
                    169:         */
                    170:        if (nb[0] == '/')
                    171:                ignore(unlink(nb));
                    172: 
                    173:        /*
                    174:         * Adieu.
                    175:         */
                    176:        exit(0);
                    177: }
                    178: 
                    179: /*
                    180:  * Print an error message (notably not in error
                    181:  * message file).  If terminal is in RAW mode, then
                    182:  * we should be writing output for "vi", so don't print
                    183:  * a newline which would screw up the screen.
                    184:  */
                    185: /*VARARGS2*/
                    186: error(str, inf)
                    187:        char *str;
                    188:        int inf;
                    189: {
                    190: 
                    191:        fprintf(stderr, str, inf);
                    192: #ifndef USG3TTY
                    193:        gtty(2, &tty);
                    194:        if ((tty.sg_flags & RAW) == 0)
                    195: #else
                    196:        ioctl(2, TCGETA, &tty);
                    197:        if (tty.c_lflag & ICANON)
                    198: #endif
                    199:                fprintf(stderr, "\n");
                    200:        exit(1);
                    201: }
                    202: 
                    203: /*
                    204:  * Here we save the information about files, when
                    205:  * you ask us what files we have saved for you.
                    206:  * We buffer file name, number of lines, and the time
                    207:  * at which the file was saved.
                    208:  */
                    209: struct svfile {
                    210:        char    sf_name[FNSIZE + 1];
                    211:        int     sf_lines;
                    212:        char    sf_entry[MAXNAMLEN + 1];
                    213:        time_t  sf_time;
                    214: };
                    215: 
                    216: listfiles(dirname)
                    217:        char *dirname;
                    218: {
                    219:        register DIR *dir;
                    220:        struct direct *dirent;
                    221:        int ecount, qucmp();
                    222:        register int f;
                    223:        char *cp;
                    224:        struct svfile *fp, svbuf[NENTRY];
                    225: 
                    226:        /*
                    227:         * Open usrpath(preserve), and go there to make things quick.
                    228:         */
                    229:        dir = opendir(dirname);
                    230:        if (dir == NULL) {
                    231:                perror(dirname);
                    232:                return;
                    233:        }
                    234:        if (chdir(dirname) < 0) {
                    235:                perror(dirname);
                    236:                return;
                    237:        }
                    238: 
                    239:        /*
                    240:         * Look at the candidate files in usrpath(preserve).
                    241:         */
                    242:        fp = &svbuf[0];
                    243:        ecount = 0;
                    244:        while ((dirent = readdir(dir)) != NULL) {
                    245:                if (dirent->d_name[0] != 'E')
                    246:                        continue;
                    247: #ifdef DEBUG
                    248:                fprintf(stderr, "considering %s\n", dirent->d_name);
                    249: #endif
                    250:                /*
                    251:                 * Name begins with E; open it and
                    252:                 * make sure the uid in the header is our uid.
                    253:                 * If not, then don't bother with this file, it can't
                    254:                 * be ours.
                    255:                 */
                    256:                f = open(dirent->d_name, 0);
                    257:                if (f < 0) {
                    258: #ifdef DEBUG
                    259:                        fprintf(stderr, "open failed\n");
                    260: #endif
                    261:                        continue;
                    262:                }
                    263:                if (read(f, (char *) &H, sizeof H) != sizeof H) {
                    264: #ifdef DEBUG
                    265:                        fprintf(stderr, "culdnt read hedr\n");
                    266: #endif
                    267:                        ignore(close(f));
                    268:                        continue;
                    269:                }
                    270:                ignore(close(f));
                    271:                if (getuid() != H.Uid) {
                    272: #ifdef DEBUG
                    273:                        fprintf(stderr, "uid wrong\n");
                    274: #endif
                    275:                        continue;
                    276:                }
                    277: 
                    278:                /*
                    279:                 * Saved the day!
                    280:                 */
                    281:                enter(fp++, dirent->d_name, ecount);
                    282:                ecount++;
                    283: #ifdef DEBUG
                    284:                fprintf(stderr, "entered file %s\n", dirent->d_name);
                    285: #endif
                    286:        }
                    287:        ignore(closedir(dir));
                    288: 
                    289:        /*
                    290:         * If any files were saved, then sort them and print
                    291:         * them out.
                    292:         */
                    293:        if (ecount == 0) {
                    294:                fprintf(stderr, "No files saved.\n");
                    295:                return;
                    296:        }
                    297:        qsort(&svbuf[0], ecount, sizeof svbuf[0], qucmp);
                    298:        for (fp = &svbuf[0]; fp < &svbuf[ecount]; fp++) {
                    299:                cp = ctime(&fp->sf_time);
                    300:                cp[10] = 0;
                    301:                fprintf(stderr, "On %s at ", cp);
                    302:                cp[16] = 0;
                    303:                fprintf(stderr, &cp[11]);
                    304:                fprintf(stderr, " saved %d lines of file \"%s\"\n",
                    305:                    fp->sf_lines, fp->sf_name);
                    306:        }
                    307: }
                    308: 
                    309: /*
                    310:  * Enter a new file into the saved file information.
                    311:  */
                    312: enter(fp, fname, count)
                    313:        struct svfile *fp;
                    314:        char *fname;
                    315: {
                    316:        register char *cp, *cp2;
                    317:        register struct svfile *f, *fl;
                    318:        time_t curtime, itol();
                    319: 
                    320:        f = 0;
                    321:        if (count >= NENTRY) {
                    322:                /*
                    323:                 * My god, a huge number of saved files.
                    324:                 * Would you work on a system that crashed this
                    325:                 * often?  Hope not.  So lets trash the oldest
                    326:                 * as the most useless.
                    327:                 *
                    328:                 * (I wonder if this code has ever run?)
                    329:                 */
                    330:                fl = fp - count + NENTRY - 1;
                    331:                curtime = fl->sf_time;
                    332:                for (f = fl; --f > fp-count; )
                    333:                        if (f->sf_time < curtime)
                    334:                                curtime = f->sf_time;
                    335:                for (f = fl; --f > fp-count; )
                    336:                        if (f->sf_time == curtime)
                    337:                                break;
                    338:                fp = f;
                    339:        }
                    340: 
                    341:        /*
                    342:         * Gotcha.
                    343:         */
                    344:        fp->sf_time = H.Time;
                    345:        fp->sf_lines = H.Flines;
                    346:        for (cp2 = fp->sf_name, cp = savedfile; *cp;)
                    347:                *cp2++ = *cp++;
                    348:        for (cp2 = fp->sf_entry, cp = fname; *cp && cp-fname < 14;)
                    349:                *cp2++ = *cp++;
                    350:        *cp2++ = 0;
                    351: }
                    352: 
                    353: /*
                    354:  * Do the qsort compare to sort the entries first by file name,
                    355:  * then by modify time.
                    356:  */
                    357: qucmp(p1, p2)
                    358:        struct svfile *p1, *p2;
                    359: {
                    360:        register int t;
                    361: 
                    362:        if (t = strcmp(p1->sf_name, p2->sf_name))
                    363:                return(t);
                    364:        if (p1->sf_time > p2->sf_time)
                    365:                return(-1);
                    366:        return(p1->sf_time < p2->sf_time);
                    367: }
                    368: 
                    369: /*
                    370:  * Scratch for search.
                    371:  */
                    372: char   bestnb[BUFSIZ];         /* Name of the best one */
                    373: long   besttime;               /* Time at which the best file was saved */
                    374: int    bestfd;                 /* Keep best file open so it dont vanish */
                    375: 
                    376: /*
                    377:  * Look for a file, both in the users directory option value
                    378:  * (i.e. usually /tmp) and in usrpath(preserve).
                    379:  * Want to find the newest so we search on and on.
                    380:  */
                    381: findtmp(dir)
                    382:        char *dir;
                    383: {
                    384: 
                    385:        /*
                    386:         * No name or file so far.
                    387:         */
                    388:        bestnb[0] = 0;
                    389:        bestfd = -1;
                    390: 
                    391:        /*
                    392:         * Search usrpath(preserve) and, if we can get there, /tmp
                    393:         * (actually the users "directory" option).
                    394:         */
                    395:        searchdir(dir);
                    396:        if (chdir(mydir) == 0)
                    397:                searchdir(mydir);
                    398:        if (bestfd != -1) {
                    399:                /*
                    400:                 * Gotcha.
                    401:                 * Put the file (which is already open) in the file
                    402:                 * used by the temp file routines, and save its
                    403:                 * name for later unlinking.
                    404:                 */
                    405:                tfile = bestfd;
                    406:                CP(nb, bestnb);
                    407:                ignorl(lseek(tfile, 0l, 0));
                    408: 
                    409:                /*
                    410:                 * Gotta be able to read the header or fall through
                    411:                 * to lossage.
                    412:                 */
                    413:                if (read(tfile, (char *) &H, sizeof H) == sizeof H)
                    414:                        return;
                    415:        }
                    416: 
                    417:        /*
                    418:         * Extreme lossage...
                    419:         */
                    420:        error(" File not found", 0);
                    421: }
                    422: 
                    423: /*
                    424:  * Search for the file in directory dirname.
                    425:  *
                    426:  * Don't chdir here, because the users directory
                    427:  * may be ".", and we would move away before we searched it.
                    428:  * Note that we actually chdir elsewhere (because it is too slow
                    429:  * to look around in usrpath(preserve) without chdir'ing there) so we
                    430:  * can't win, because we don't know the name of '.' and if the path
                    431:  * name of the file we want to unlink is relative, rather than absolute
                    432:  * we won't be able to find it again.
                    433:  */
                    434: searchdir(dirname)
                    435:        char *dirname;
                    436: {
                    437:        struct direct *dirent;
                    438:        register DIR *dir;
                    439:        char dbuf[BUFSIZ];
                    440: 
                    441:        dir = opendir(dirname);
                    442:        if (dir == NULL)
                    443:                return;
                    444:        while ((dirent = readdir(dir)) != NULL) {
                    445:                if (dirent->d_name[0] != 'E')
                    446:                        continue;
                    447:                /*
                    448:                 * Got a file in the directory starting with E...
                    449:                 * Save a consed up name for the file to unlink
                    450:                 * later, and check that this is really a file
                    451:                 * we are looking for.
                    452:                 */
                    453:                ignore(strcat(strcat(strcpy(nb, dirname), "/"), dirent->d_name));
                    454:                if (yeah(nb)) {
                    455:                        /*
                    456:                         * Well, it is the file we are looking for.
                    457:                         * Is it more recent than any version we found before?
                    458:                         */
                    459:                        if (H.Time > besttime) {
                    460:                                /*
                    461:                                 * A winner.
                    462:                                 */
                    463:                                ignore(close(bestfd));
                    464:                                bestfd = dup(tfile);
                    465:                                besttime = H.Time;
                    466:                                CP(bestnb, nb);
                    467:                        }
                    468:                        /*
                    469:                         * Count versions so user can be told there are
                    470:                         * ``yet more pages to be turned''.
                    471:                         */
                    472:                        vercnt++;
                    473:                }
                    474:                ignore(close(tfile));
                    475:        }
                    476:        ignore(closedir(dir));
                    477: }
                    478: 
                    479: /*
                    480:  * Given a candidate file to be recovered, see
                    481:  * if its really an editor temporary and of this
                    482:  * user and the file specified.
                    483:  */
                    484: yeah(name)
                    485:        char *name;
                    486: {
                    487: 
                    488:        tfile = open(name, 2);
                    489:        if (tfile < 0)
                    490:                return (0);
                    491:        if (read(tfile, (char *) &H, sizeof H) != sizeof H) {
                    492: nope:
                    493:                ignore(close(tfile));
                    494:                return (0);
                    495:        }
                    496:        if (!eq(savedfile, file))
                    497:                goto nope;
                    498:        if (getuid() != H.Uid)
                    499:                goto nope;
                    500:        /*
                    501:         * This is old and stupid code, which
                    502:         * puts a word LOST in the header block, so that lost lines
                    503:         * can be made to point at it.
                    504:         */
                    505:        ignorl(lseek(tfile, (long)(BUFSIZ*HBLKS-8), 0));
                    506:        ignore(write(tfile, "LOST", 5));
                    507:        return (1);
                    508: }
                    509: 
                    510: preserve()
                    511: {
                    512: 
                    513: }
                    514: 
                    515: /*
                    516:  * Find the true end of the scratch file, and ``LOSE''
                    517:  * lines which point into thin air.  This lossage occurs
                    518:  * due to the sandbagging of i/o which can cause blocks to
                    519:  * be written in a non-obvious order, different from the order
                    520:  * in which the editor tried to write them.
                    521:  *
                    522:  * Lines which are lost are replaced with the text LOST so
                    523:  * they are easy to find.  We work hard at pretty formatting here
                    524:  * as lines tend to be lost in blocks.
                    525:  *
                    526:  * This only seems to happen on very heavily loaded systems, and
                    527:  * not very often.
                    528:  */
                    529: scrapbad()
                    530: {
                    531:        register line *ip;
                    532:        struct stat stbuf;
                    533:        off_t size, maxt;
                    534:        int bno, cnt, bad, was;
                    535:        char bk[BUFSIZ];
                    536: 
                    537:        ignore(fstat(tfile, &stbuf));
                    538:        size = stbuf.st_size;
                    539:        maxt = (size >> SHFT) | (BNDRY-1);
                    540:        bno = (maxt >> OFFBTS) & BLKMSK;
                    541: #ifdef DEBUG
                    542:        fprintf(stderr, "size %ld, maxt %o, bno %d\n", size, maxt, bno);
                    543: #endif
                    544: 
                    545:        /*
                    546:         * Look for a null separating two lines in the temp file;
                    547:         * if last line was split across blocks, then it is lost
                    548:         * if the last block is.
                    549:         */
                    550:        while (bno > 0) {
                    551:                ignorl(lseek(tfile, (long) BUFSIZ * bno, 0));
                    552:                cnt = read(tfile, (char *) bk, BUFSIZ);
                    553:                while (cnt > 0)
                    554:                        if (bk[--cnt] == 0)
                    555:                                goto null;
                    556:                bno--;
                    557:        }
                    558: null:
                    559: 
                    560:        /*
                    561:         * Magically calculate the largest valid pointer in the temp file,
                    562:         * consing it up from the block number and the count.
                    563:         */
                    564:        maxt = ((bno << OFFBTS) | (cnt >> SHFT)) & ~1;
                    565: #ifdef DEBUG
                    566:        fprintf(stderr, "bno %d, cnt %d, maxt %o\n", bno, cnt, maxt);
                    567: #endif
                    568: 
                    569:        /*
                    570:         * Now cycle through the line pointers,
                    571:         * trashing the Lusers.
                    572:         */
                    573:        was = bad = 0;
                    574:        for (ip = one; ip <= dol; ip++)
                    575:                if (*ip > maxt) {
                    576: #ifdef DEBUG
                    577:                        fprintf(stderr, "%d bad, %o > %o\n", ip - zero, *ip, maxt);
                    578: #endif
                    579:                        if (was == 0)
                    580:                                was = ip - zero;
                    581:                        *ip = ((HBLKS*BUFSIZ)-8) >> SHFT;
                    582:                } else if (was) {
                    583:                        if (bad == 0)
                    584:                                fprintf(stderr, " [Lost line(s):");
                    585:                        fprintf(stderr, " %d", was);
                    586:                        if ((ip - 1) - zero > was)
                    587:                                fprintf(stderr, "-%d", (ip - 1) - zero);
                    588:                        bad++;
                    589:                        was = 0;
                    590:                }
                    591:        if (was != 0) {
                    592:                if (bad == 0)
                    593:                        fprintf(stderr, " [Lost line(s):");
                    594:                fprintf(stderr, " %d", was);
                    595:                if (dol - zero != was)
                    596:                        fprintf(stderr, "-%d", dol - zero);
                    597:                bad++;
                    598:        }
                    599:        if (bad)
                    600:                fprintf(stderr, "]");
                    601: }
                    602: 
                    603: /*
                    604:  * Aw shucks, if we only had a (void) cast.
                    605:  */
                    606: #ifdef lint
                    607: Ignorl(a)
                    608:        long a;
                    609: {
                    610: 
                    611:        a = a;
                    612: }
                    613: 
                    614: Ignore(a)
                    615:        char *a;
                    616: {
                    617: 
                    618:        a = a;
                    619: }
                    620: 
                    621: Ignorf(a)
                    622:        int (*a)();
                    623: {
                    624: 
                    625:        a = a;
                    626: }
                    627: 
                    628: ignorl(a)
                    629:        long a;
                    630: {
                    631: 
                    632:        a = a;
                    633: }
                    634: #endif
                    635: 
                    636: int    cntch, cntln, cntodd, cntnull;
                    637: /*
                    638:  * Following routines stolen mercilessly from ex.
                    639:  */
                    640: putfile()
                    641: {
                    642:        line *a1;
                    643:        register char *fp, *lp;
                    644:        register int nib;
                    645: 
                    646:        a1 = addr1;
                    647:        clrstats();
                    648:        cntln = addr2 - a1 + 1;
                    649:        if (cntln == 0)
                    650:                return;
                    651:        nib = BUFSIZ;
                    652:        fp = genbuf;
                    653:        do {
                    654:                getline(*a1++);
                    655:                lp = linebuf;
                    656:                for (;;) {
                    657:                        if (--nib < 0) {
                    658:                                nib = fp - genbuf;
                    659:                                if (write(io, genbuf, nib) != nib)
                    660:                                        wrerror();
                    661:                                cntch += nib;
                    662:                                nib = 511;
                    663:                                fp = genbuf;
                    664:                        }
                    665:                        if ((*fp++ = *lp++) == 0) {
                    666:                                fp[-1] = '\n';
                    667:                                break;
                    668:                        }
                    669:                }
                    670:        } while (a1 <= addr2);
                    671:        nib = fp - genbuf;
                    672:        if (write(io, genbuf, nib) != nib)
                    673:                wrerror();
                    674:        cntch += nib;
                    675: }
                    676: 
                    677: wrerror()
                    678: {
                    679: 
                    680:        syserror();
                    681: }
                    682: 
                    683: clrstats()
                    684: {
                    685: 
                    686:        ninbuf = 0;
                    687:        cntch = 0;
                    688:        cntln = 0;
                    689:        cntnull = 0;
                    690:        cntodd = 0;
                    691: }
                    692: 
                    693: #define        READ    0
                    694: #define        WRITE   1
                    695: 
                    696: getline(tl)
                    697:        line tl;
                    698: {
                    699:        register char *bp, *lp;
                    700:        register int nl;
                    701: 
                    702:        lp = linebuf;
                    703:        bp = getblock(tl, READ);
                    704:        nl = nleft;
                    705:        tl &= ~OFFMSK;
                    706:        while (*lp++ = *bp++)
                    707:                if (--nl == 0) {
                    708:                        bp = getblock(tl += INCRMT, READ);
                    709:                        nl = nleft;
                    710:                }
                    711: }
                    712: 
                    713: int    read();
                    714: int    write();
                    715: 
                    716: char *
                    717: getblock(atl, iof)
                    718:        line atl;
                    719:        int iof;
                    720: {
                    721:        register int bno, off;
                    722:        
                    723:        bno = (atl >> OFFBTS) & BLKMSK;
                    724:        off = (atl << SHFT) & LBTMSK;
                    725:        if (bno >= NMBLKS)
                    726:                error(" Tmp file too large");
                    727:        nleft = BUFSIZ - off;
                    728:        if (bno == iblock) {
                    729:                ichanged |= iof;
                    730:                return (ibuff + off);
                    731:        }
                    732:        if (bno == oblock)
                    733:                return (obuff + off);
                    734:        if (iof == READ) {
                    735:                if (ichanged)
                    736:                        blkio(iblock, ibuff, write);
                    737:                ichanged = 0;
                    738:                iblock = bno;
                    739:                blkio(bno, ibuff, read);
                    740:                return (ibuff + off);
                    741:        }
                    742:        if (oblock >= 0)
                    743:                blkio(oblock, obuff, write);
                    744:        oblock = bno;
                    745:        return (obuff + off);
                    746: }
                    747: 
                    748: blkio(b, buf, iofcn)
                    749:        short b;
                    750:        char *buf;
                    751:        int (*iofcn)();
                    752: {
                    753: 
                    754:        lseek(tfile, (long) (unsigned) b * BUFSIZ, 0);
                    755:        if ((*iofcn)(tfile, buf, BUFSIZ) != BUFSIZ)
                    756:                syserror();
                    757: }
                    758: 
                    759: syserror()
                    760: {
                    761:        extern int sys_nerr;
                    762:        extern char *sys_errlist[];
                    763: 
                    764:        dirtcnt = 0;
                    765:        write(2, " ", 1);
                    766:        if (errno >= 0 && errno <= sys_nerr)
                    767:                error(sys_errlist[errno]);
                    768:        else
                    769:                error("System error %d", errno);
                    770:        exit(1);
                    771: }
                    772: 
                    773: /*
                    774:  * Must avoid stdio because expreserve uses sbrk to do memory
                    775:  * allocation and stdio uses malloc.
                    776:  */
                    777: fprintf(fp, fmt, a1, a2, a3, a4, a5)
                    778:        FILE *fp;
                    779:        char *fmt;
                    780:        char *a1, *a2, *a3, *a4, *a5;
                    781: {
                    782:        char buf[BUFSIZ];
                    783: 
                    784:        if (fp != stderr)
                    785:                return;
                    786:        sprintf(buf, fmt, a1, a2, a3, a4, a5);
                    787:        write(2, buf, strlen(buf));
                    788: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.