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
clrstats defined in line 681; used 2 times
enter defined in line 310; used 1 times
findtmp defined in line 379; used 1 times
  • in line 98
getblock defined in line 714; used 2 times
getline defined in line 694; used 1 times
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
qucmp defined in line 355; used 2 times
scrapbad defined in line 527; used 1 times
searchdir defined in line 432; used 2 times
syserror defined in line 757; used 2 times
wrerror defined in line 675; used 2 times
yeah defined in line 482; used 1 times

Defined variables

bestfd defined in line 372; used 5 times
bestnb defined in line 370; used 3 times
besttime defined in line 371; used 2 times
cntch defined in line 634; used 3 times
cntln defined in line 634; used 3 times
cntnull defined in line 634; used 1 times
cntodd defined in line 634; used 1 times
copyright defined in line 8; never used
mydir defined in line 55; used 3 times
nb defined in line 64; used 7 times
sccsid defined in line 12; never used
tfile defined in line 27; used 18 times
vercnt defined in line 65; used 3 times
xstr defined in line 26; never used

Defined struct's

svfile defined in line 207; used 8 times

Defined macros

NENTRY defined in line 61; used 3 times
READ defined in line 691; used 3 times
WRITE defined in line 692; never used
ignorl defined in line 48; used 4 times
Last modified: 1996-10-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 6570
Valid CSS Valid XHTML 1.0 Strict