# 2.11BSD#431 - /usr/src/ucb/ex/exrecover.c

##### Functions

    Ignore            X
    Ignorf            X
    Ignorl            X
    blkio             X
    clrstats          X
    enter             X
    error             X
    findtmp           X
    fprintf           X
    getblock          X
    getline           X
    ignorl            X
    listfiles         X
    main              X
    preserve          X
    putfile           X
    qucmp             X
    scrapbad          X
    searchdir         X
    syserror          X
    wrerror           X
    yeah              X

##### Variables

    bestfd            X
    bestnb            X
    besttime          X
    cntch             X
    cntln             X
    cntnull           X
    cntodd            X
    copyright         X
    mydir             X
    nb                X
    tfile             X
    vercnt            X
    xstr              X

##### Macros

    NENTRY            X
    READ              X
    WRITE             X
    ignorl            X

##### struct's

    svfile            X

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

#### Defined functions

Ignore defined in line 612; never used
Ignorf defined in line 619; never used
Ignorl defined in line 605; never used
blkio defined in line 746; used 3 times

- in line 734-741(3)

clrstats defined in line 681; used 2 times

- in line 645
- in /usr/src/ucb/ex/ex_cmdsub.c line 508

enter defined in line 310; used 1 times

- in line 279

error defined in line 184; used 158 times

- in line 91, 116, 418, 724, 762
- in /usr/src/ucb/ex/ex_addr.c line 53, 76, 123, 172, 232, 239, 251, 266-269(2), 288-290(2)
- in /usr/src/ucb/ex/ex_cmds.c line 65, 213, 349, 433-435(2), 490, 598, 756, 779, 887
- in /usr/src/ucb/ex/ex_cmdsub.c line 52, 229, 299, 312, 357, 457, 500-502(2), 633, 677, 690, 782-788(3), 817, 917, 1066-1068(2), 1093, 1124, 1131, 1190, 1199-1204(2), 1211, 1230, 1241-1246(2)
- in /usr/src/ucb/ex/ex_get.c line 200
- in /usr/src/ucb/ex/ex_io.c line 53, 133, 163, 170, 176, 223-228(2), 255, 262, 268, 294-300(3), 340-350(4), 366, 378, 388, 525-529(2), 567-573(3), 659, 766
- in /usr/src/ucb/ex/ex_put.c line 889
- in /usr/src/ucb/ex/ex_re.c line 41-46(2), 77, 195, 210, 233, 247-249(2), 337, 484, 547, 556, 562-573(4), 648-650(2), 751, 921
- in /usr/src/ucb/ex/ex_set.c line 101, 119, 144
- in /usr/src/ucb/ex/ex_subr.c line 407, 423, 552, 652, 776, 837, 921
- in /usr/src/ucb/ex/ex_temp.c line 161, 286, 410, 478-483(2), 640, 646
- in /usr/src/ucb/ex/ex_unix.c line 35, 47, 56, 70, 78, 108, 152, 165, 196, 251, 257, 306-311(2), 322
- in /usr/src/ucb/ex/ex_v.c line 87, 145-147(2), 194-209(4), 336, 357-359(2)
- in /usr/src/ucb/ex/ex_vadj.c line 449, 546, 626
- in /usr/src/ucb/ex/ex_vget.c line 119, 495
- in /usr/src/ucb/ex/ex_vmain.c line 163, 664
- in /usr/src/ucb/ex/ex_vops2.c line 479, 826, 901
- in /usr/src/ucb/ex/ex_vput.c line 80, 299, 314, 484

findtmp defined in line 379; used 1 times

- in line 98

fprintf defined in line 770; used 112 times

- in line 105-106(2), 118, 189, 197, 246, 257, 263, 271, 282, 292, 299-302(3), 540, 564, 575, 582-585(3), 591-598(4)
- in /usr/src/ucb/ex/ex_cmdsub.c line 1179
- in /usr/src/ucb/ex/ex_vadj.c line 40, 231, 312, 356, 384, 414, 446, 472, 617, 743, 781, 832, 904, 928
- in /usr/src/ucb/ex/ex_vget.c line 148, 392, 406, 412, 426, 440-445(2), 459, 467, 492, 526-532(3), 544-556(7), 607, 615, 624, 631-636(2)
- in /usr/src/ucb/ex/ex_vmain.c line 106, 133, 147, 322, 335-340(2), 812
- in /usr/src/ucb/ex/ex_voper.c line 228
- in /usr/src/ucb/ex/ex_vops.c line 196, 202
- in /usr/src/ucb/ex/ex_vops2.c line 300
- in /usr/src/ucb/ex/ex_vput.c line 26, 625-627(2), 1232, 1315, 1326-1336(6), 1346-1352(4)
- in /usr/src/ucb/ex/ex_vwind.c line 359, 398, 449
- in /usr/src/ucb/ex/expreserve.c line 103, 185, 194, 200, 206, 212, 302, 349-373(12)

getblock defined in line 714; used 2 times

- in line 701-706(2)

getline defined in line 694; used 1 times

- in line 652

ignorl defined in line 626; never used
listfiles defined in line 214; used 1 times

- in line 87

main defined in line 67; never used
preserve defined in line 508; never used
putfile defined in line 638; used 2 times

- in line 153
- in /usr/src/ucb/ex/ex_unix.c line 263

qucmp defined in line 355; used 2 times

- in line 219, 295

scrapbad defined in line 527; used 1 times

- in line 145

searchdir defined in line 432; used 2 times

- in line 393-395(2)

syserror defined in line 757; used 2 times

- in line 678, 754

wrerror defined in line 675; used 2 times

- in line 658, 671

yeah defined in line 482; used 1 times

- in line 452

#### Defined variables

bestfd defined in line 372; used 5 times

- in line 387, 396, 403, 461-462(2)

bestnb defined in line 370; used 3 times

- in line 386, 404, 464

besttime defined in line 371; used 2 times

- in line 457, 463

cntch defined in line 634; used 3 times

- in line 659, 672, 685

cntln defined in line 634; used 3 times

- in line 646-647(2), 686

cntnull defined in line 634; used 1 times

- in line 687

cntodd defined in line 634; used 1 times

- in line 688

copyright defined in line 8; never used
mydir defined in line 55; used 3 times

- in line 87, 394-395(2)

nb defined in line 64; used 7 times

- in line 132, 168-169(2), 404, 451-452(2), 464

sccsid defined in line 12; never used
tfile defined in line 27; used 18 times

- in line 128-131(2), 403-405(2), 411, 462, 472, 486-491(4), 503-504(2), 535, 549-550(2), 752-753(2)

vercnt defined in line 65; used 3 times

- in line 106(2), 470

xstr defined in line 26; never used

#### Defined struct's

svfile defined in line 207; used 8 times

- in line 222(2), 311-315(4), 356(2)

#### Defined macros

NENTRY defined in line 61; used 3 times

- in line 222, 319, 328

READ defined in line 691; used 3 times

- in line 701-706(2), 732

WRITE defined in line 692; never used
ignorl defined in line 48; used 4 times

- in line 128, 405, 503, 549

Last modified: 1996-10-27 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2725 |