|
|
1.1 ! root 1: /* ! 2: ********************************************************************** ! 3: * * ! 4: * dired [][dir][files] Stuart Cracraft (mclure@sri-unix) Sept 1980 * ! 5: * * ! 6: * Directory editor. * ! 7: * edit/delete files in a directory or a file list * ! 8: * compile with the berkeley termlib archive * ! 9: * and don't forget to change the 'helpfile' and * ! 10: * 'dirednam' strings to reflect your own setup. * ! 11: * * ! 12: * Note: if you make improvements, I'd like to get them too. * ! 13: * Stuart Cracraft mclure@sri-unix, * ! 14: * ucbvax!menlo70!sri-unix!mclure * ! 15: * so would I: Jay Lepreau lepreau@utah-20, * ! 16: * decvax!randvax!utah-cs!lepreau * ! 17: ********************************************************************** ! 18: */ ! 19: ! 20: /* ! 21: * Enhanced by J.Lepreau, Univ of Utah, 8-10/81: ! 22: * --bunch of stuff, including more cmds, 2 window mode, ! 23: * buffering output, pathname substition in !escapes, ! 24: * initial sort options, ^G escape from sorts, ^U escape ! 25: * from !escapes, empty dir check. ! 26: */ ! 27: ! 28: #ifdef COMMENT ! 29: ! 30: Modified 12/81 by Lepreau: ! 31: 1. Fix up aborting of command escapes, with mildy tricky re-display. ! 32: 2. Make default window size be half-screen (2 window mode). ! 33: Added option -wf to get full screen. ! 34: 3. Add check for too many files to avoid core-dump. ! 35: 4. Fix bug in cmd escapes: must reset caught signals before invocation. ! 36: ! 37: #endif COMMENT ! 38: ! 39: /* ! 40: things to consider ! 41: - perhaps should be able to edit protection field and ! 42: be able to change protection instantly at the ! 43: touch of a key (or queue the change for later exit) ! 44: ! 45: -- Would be nice if there were cmds (e.g. 'c') which would update ! 46: 1) the file-info & re-display it, & 2) update whole ! 47: display's info. ! 48: */ ! 49: ! 50: #ifdef vax /* this does for now */ ! 51: # define VFORK ! 52: #endif ! 53: ! 54: #ifndef VFORK ! 55: # define vfork fork ! 56: #endif ! 57: ! 58: #define FALSE 0 ! 59: #define TRUE 1 ! 60: #define NOTDELETED 0 ! 61: #define DELETED 1 ! 62: ! 63: /* Sort Orders */ ! 64: #define NAME 0 ! 65: #define SIZE 1 ! 66: #define WRITE 2 ! 67: #define READ 3 ! 68: char sortstr[] = "nswr"; /* must be in order by above */ ! 69: ! 70: #define ESC '\033' ! 71: #define CURSOR 48 /* X-coord of cursor, just b4 file */ ! 72: #define CTRL(c) ('c' & 037) ! 73: ! 74: #include <stdio.h> ! 75: #include <sys/types.h> ! 76: #include <signal.h> ! 77: #include <sgtty.h> ! 78: #include <sys/stat.h> ! 79: #ifdef BSD ! 80: #include <sys/dir.h> ! 81: #else ! 82: #include <ndir.h> ! 83: #define index strchr ! 84: #endif ! 85: ! 86: #ifdef UTAH ! 87: char *dirednam = "/usr/local/dired "; /* Where dired lives - need blnk */ ! 88: char *helpfile = "/usr/help/dired.hlp"; /* Where helpfile lives */ ! 89: #else ! 90: char *dirednam = "dired "; /* Where dired lives - need blnk */ ! 91: char *helpfile = "/usr/lib/dired"; /* Where helpfile lives */ ! 92: #endif ! 93: ! 94: char divider[132]; /* divides the windows */ ! 95: #define DIVCHAR '-' /* makes up the divider */ ! 96: ! 97: #define MOREPGM "p " /* program to page thru a file */ ! 98: ! 99: #define MAXFILES 2000 /* Max number of files we can handle */ ! 100: #define MAXN 30 ! 101: ! 102: struct lbuf ! 103: { ! 104: union ! 105: { ! 106: char lname[MAXN]; ! 107: char *namep; ! 108: } ln; ! 109: short deleted; ! 110: char ltype; ! 111: short lnum; ! 112: short lflags; ! 113: short lnl; ! 114: unsigned short luid; ! 115: unsigned short lgid; ! 116: long lsize; ! 117: long latime; ! 118: long lctime; ! 119: long lmtime; ! 120: }; ! 121: ! 122: struct lbuf file[MAXFILES]; ! 123: ! 124: struct stat statbuf; ! 125: struct sgttyb ioctlb; ! 126: ! 127: #define ISARG 0100000 ! 128: ! 129: int gflg, ! 130: iflg, ! 131: lflg, ! 132: sflg; /* Random flags */ ! 133: int splitflg; /* Split screen? */ ! 134: int sortyp; /* Key to sort on */ ! 135: int errcode; /* Error variable used by rm */ ! 136: int rflg = 1; /* Reverse sort flag */ ! 137: int totfiles = 0; /* Total files */ ! 138: int flags; /* Gets flags */ ! 139: int blurb; /* 1=>thing in echo area,0 otherwise */ ! 140: int numdeleted; /* Number of files marked deleted */ ! 141: long ttime; /* Temp time variable */ ! 142: long year; /* Six months ago */ ! 143: long totblocks = 0; /* Total blocks */ ! 144: int lastuid = -1; /* Last uid/gid we handled */ ! 145: char tempbuf[128]; /* Random temporary buffer */ ! 146: char userbuf[35]; /* Temporary buffer for user name */ ! 147: FILE *pwdf; /* Password/group file */ ! 148: ! 149: int curfile = 0; /* Current file */ ! 150: int topfile = 0; /* File at top of screen */ ! 151: int curline = 0; /* Line that we're on */ ! 152: int scrlen = 999; /* Length of screen - dired part: half size */ ! 153: int Worklen = 0; /* Length of 'working window', the other part*/ ! 154: int Worktop = 0; /* Top of " " */ ! 155: int Tscrlen; /*Total length of screen,minus 1 for cmd line*/ ! 156: int scrwid = 79; /* Width of screen */ ! 157: char *CL, ! 158: *UP, /* Termcap strings we'll use */ ! 159: *HO, ! 160: *CM, ! 161: *CD, /* clear to end of display */ ! 162: *CE, ! 163: *AL; /* insert line */ ! 164: char PC; ! 165: char tbuf[1024], ! 166: tcapbuf[128]; ! 167: char *tgetstr (), *tgoto (); ! 168: char *getenv (); ! 169: int compar (); ! 170: char *ctime (); ! 171: char *index(); ! 172: char *makename (); ! 173: char *catargs(); ! 174: char *bldnam(); ! 175: long nblock (); ! 176: int catchint(); ! 177: int sigint; ! 178: ! 179: char bufout[BUFSIZ]; ! 180: ! 181: main (argc, argv) ! 182: int argc; ! 183: char *argv[]; ! 184: { ! 185: register int i, ! 186: cc; ! 187: int numarg, ! 188: special, /* flag says had % or # in cmd */ ! 189: status; ! 190: char nambuf[128]; ! 191: char command; /* Holds last command */ ! 192: char **oldargv; ! 193: register char *t, ! 194: *tt; ! 195: ! 196: /* Get terminal type */ ! 197: ! 198: getcap (); ! 199: ! 200: /* Process arg flags. They must be first! */ ! 201: for (i=1; i<argc; i++) { ! 202: if (argv[i][0] != '-') ! 203: break; ! 204: switch (cc = argv[i][1]) { ! 205: case 'w': /* Window size */ ! 206: if (argv[i][2] == 'h') ! 207: scrlen = 999; /* Half */ ! 208: else if (argv[i][2] == 'f') ! 209: scrlen = 0; /* Full */ ! 210: else ! 211: scrlen = atoi(&argv[i][2]); ! 212: break; ! 213: case 's': /* Initial sort order */ ! 214: case 'r': ! 215: sortyp = index(sortstr, argv[i][2]) - sortstr; ! 216: rflg = (cc == 's') ? 1 : -1; ! 217: break; ! 218: default: ! 219: printf("Unknown option %s, ignored.\n", argv[i]); ! 220: break; ! 221: } ! 222: } ! 223: argc -= (i - 1); ! 224: oldargv = argv; ! 225: argv += (i - 1); ! 226: ! 227: if (scrlen == 0) /* full screen */ ! 228: scrlen = Tscrlen; ! 229: else if (scrlen == 999) /* means split in half */ ! 230: scrlen = (Tscrlen - 1) >> 1; ! 231: if (scrlen < 2) ! 232: scrlen = 2; ! 233: if (Tscrlen < scrlen) ! 234: scrlen = Tscrlen; ! 235: splitflg = (Tscrlen > scrlen+1); /* 1 extra line for separator */ ! 236: if (splitflg) { ! 237: Worklen = Tscrlen - (scrlen+1); /* size of 'working' window */ ! 238: Worktop = scrlen + 1; /* bottom half for now */ ! 239: } ! 240: else ! 241: Worklen = 0; ! 242: ! 243: tt = divider + scrwid - 14; ! 244: for (t = divider; t < tt;) /* arbitrary length */ ! 245: *t++ = DIVCHAR; ! 246: *t = '\0'; ! 247: ! 248: signal (SIGINT, SIG_IGN); ! 249: signal (SIGQUIT, SIG_IGN); ! 250: ! 251: setdpy (); ! 252: printf ("Reading"); ! 253: ! 254: time (&ttime); ! 255: year = ttime - 6L * 30L * 24L * 60L * 60L;/* 6 months ago */ ! 256: ! 257: lflg = 1; ! 258: gflg = iflg = sflg = 0; ! 259: if (lflg) ! 260: { ! 261: t = "/etc/passwd"; ! 262: if (gflg) ! 263: t = "/etc/group"; ! 264: pwdf = fopen (t, "r"); ! 265: } ! 266: ! 267: ! 268: numarg = argc; ! 269: if (argc == 1) ! 270: getdir ("."); ! 271: else ! 272: if (argc == 2) ! 273: getdir (argv[1]); ! 274: else ! 275: { ! 276: while (--argc > 0) ! 277: { ! 278: if (totfiles == MAXFILES) { ! 279: overflow(); ! 280: break; ! 281: } ! 282: if ((totfiles % 10) == 0) ! 283: putchar ('.'); ! 284: if (gstat(*++argv) == 0) { ! 285: file[totfiles].ln.namep = *argv; ! 286: file[totfiles].lflags |= ISARG; ! 287: totfiles++; ! 288: } ! 289: } ! 290: } ! 291: if (totfiles == 0) { ! 292: printf("\n?Empty directory\n"); ! 293: unsetdpy(); ! 294: sleep(1); /* So user can see it - don't worry if less */ ! 295: exit(0); ! 296: } ! 297: qsort (file, totfiles, sizeof (struct lbuf), compar); ! 298: blank (); ! 299: showscreen (); ! 300: curxy (0, Tscrlen); ! 301: ceol (); ! 302: curxy (CURSOR, 0); ! 303: startup: ! 304: while ((command = readchar()) != 'q') ! 305: { ! 306: if (blurb) ! 307: { ! 308: telluser (""); ! 309: blurb = 0; ! 310: } ! 311: switch (command) ! 312: { ! 313: case 'a': /* Abort completely */ ! 314: blank (); ! 315: unsetdpy (); ! 316: exit (1); ! 317: break; ! 318: case 'P': /* Print a file */ ! 319: case 'p': /* do a pr2 */ ! 320: if (file[curfile].ltype == 'd') ! 321: { ! 322: telluser ("?Can only print files"); ! 323: break; ! 324: } ! 325: tempbuf[0] = '\0'; ! 326: bldnam(tempbuf, numarg, curfile, argv); ! 327: telluser ("Printing..."); ! 328: while ((i = vfork ()) == -1) ! 329: sleep (3); ! 330: if (i == 0) { ! 331: #ifdef UTAH ! 332: if (command == 'p') /* little print */ ! 333: execlp("pr2", "pr2", tempbuf, 0); ! 334: else /* big print */ ! 335: #endif ! 336: execlp ("print", "print", tempbuf, 0); ! 337: telluser ("?Can't find program to list file.\n"); ! 338: _exit(1); ! 339: } ! 340: wait (&status); ! 341: break; ! 342: ! 343: case '!': /* Execute a system command */ ! 344: telluser (""); ! 345: curxy (0, Tscrlen); ! 346: unsetdpy (); ! 347: printf ("Command: "); ! 348: tempbuf[0] = 'x'; /* dummy kludge */ ! 349: if (gets(tempbuf) != NULL && tempbuf[0] != '\0') { ! 350: extern char *skipto(); ! 351: register char *op, /* old ptr */ ! 352: *np; /* new ptr */ ! 353: char bldbuf[70]; ! 354: ! 355: bldbuf[0] = '\0'; ! 356: op = tempbuf; ! 357: special = 0; ! 358: while (cc = *(np = skipto(op, "%#"))) { ! 359: special++; /* set flag */ ! 360: *np++ = '\0'; /* zap the %/# and bump past it */ ! 361: strcat(bldbuf, op); /* 1st part */ ! 362: if (cc == '%') /* complete file name */ ! 363: bldnam(bldbuf, numarg, curfile, argv); ! 364: else { /* Had # sign, trailing comp only */ ! 365: if (numarg <= 2) ! 366: strcat (bldbuf, file[curfile].ln.lname); ! 367: else ! 368: strcat (bldbuf, file[curfile].ln.namep); ! 369: } ! 370: ! 371: op = np; ! 372: } ! 373: strcat(bldbuf, op); ! 374: ! 375: blank (); ! 376: if (special) { /* display expanded command */ ! 377: printf( "%s\n", bldbuf); ! 378: } /* "system" takes long enuf for him to see it */ ! 379: signal(SIGINT, SIG_DFL); /* temp kludge here... */ ! 380: signal(SIGQUIT, SIG_DFL); /* should not use 'system' */ ! 381: system (bldbuf); ! 382: signal (SIGINT, SIG_IGN); ! 383: signal (SIGQUIT, SIG_IGN); ! 384: printf ("\nCR to return..."); ! 385: setdpy (); ! 386: readchar(); ! 387: blank (); ! 388: showscreen (); ! 389: telluser (""); ! 390: } ! 391: else { /* CR only, or EOF, or error */ ! 392: /* ! 393: * He changed his mind, skip it. Since we were in ! 394: * cooked mode, the CR ending the gets is echoed and ! 395: * we lost the first line of the display. So we ! 396: * re-insert it. ! 397: */ ! 398: setdpy(); ! 399: if (tempbuf[0] == 'x') /* means EOF */ ! 400: telluser(""); ! 401: /* null entry, normal case */ ! 402: else if (AL == 0) { /* no insert line capability */ ! 403: blank(); ! 404: showscreen(); ! 405: } ! 406: else { /* be a little sneakier */ ! 407: curxy(0, Tscrlen-1); /* go back to where prompt */ ! 408: ceol(); /* is now, and blank it */ ! 409: home(); ! 410: insline(); /* make some room */ ! 411: pentry(topfile); ! 412: putchar('\n'); ! 413: } ! 414: curxy(CURSOR, curline); ! 415: } ! 416: break; ! 417: ! 418: case 'r': /* Reverse sort */ ! 419: curxy (0, Tscrlen); ! 420: printf ("reverse "); ! 421: rflg = -1; ! 422: case 's': /* Normal sort */ ! 423: if (command == 's') ! 424: { ! 425: curxy (0, Tscrlen); ! 426: rflg = 1; ! 427: } ! 428: printf ("sort by [s,n,r,w]: "); ! 429: command = readchar(); ! 430: while ((command == '?') || !((command == 'n') || ! 431: (command == 'r') || (command == 'w') || (command == 's') || ! 432: (command == CTRL(g)))) ! 433: { ! 434: curxy (0, Tscrlen); ! 435: ceol (); ! 436: if (rflg == -1) ! 437: printf ("reverse "); ! 438: printf ("sort by size, name, read or write date: "); ! 439: command = readchar(); ! 440: } ! 441: ! 442: if (command == CTRL(g)) { /* abort */ ! 443: putchar(CTRL(g)); /* echo it */ ! 444: telluser(""); ! 445: curxy(CURSOR, curline); ! 446: break; ! 447: } ! 448: ! 449: if (command == 's') ! 450: sortyp = SIZE; ! 451: else ! 452: if (command == 'w') ! 453: sortyp = WRITE; ! 454: else ! 455: if (command == 'r') ! 456: sortyp = READ; ! 457: else ! 458: sortyp = 0; ! 459: printf ("%c", command); ! 460: qsort (file, totfiles, sizeof (struct lbuf), compar); ! 461: topfile = 0; ! 462: curfile = 0; ! 463: curline = 0; ! 464: blank (); ! 465: showscreen (); ! 466: curxy (CURSOR, 0); ! 467: break; ! 468: ! 469: case 'e': /* Edit a file or directory */ ! 470: if (file[curfile].ltype == 'd') { ! 471: strcpy (tempbuf, dirednam); ! 472: catargs(tempbuf, oldargv); ! 473: } ! 474: else { ! 475: if ((t = getenv("EDITOR")) != NULL) ! 476: strcat(strcpy(tempbuf, t), " "); ! 477: else ! 478: strcpy (tempbuf, "ed "); ! 479: } ! 480: bldnam(tempbuf, numarg, curfile, argv); ! 481: blank (); ! 482: unsetdpy (); ! 483: system (tempbuf); ! 484: setdpy (); ! 485: blank (); ! 486: showscreen (); ! 487: telluser (""); ! 488: break; ! 489: ! 490: case 'm': /* 'more' a file */ ! 491: if (file[curfile].ltype == 'd') ! 492: { ! 493: telluser ("?Can only page thru files"); ! 494: break; ! 495: } ! 496: strcpy (tempbuf, MOREPGM); ! 497: bldnam(tempbuf, numarg, curfile, argv); ! 498: blank (); ! 499: unsetdpy (); ! 500: system (tempbuf); ! 501: /* if (!sigint) { */ ! 502: printf ("\nCR to return..."); ! 503: /* } */ ! 504: setdpy (); ! 505: readchar(); ! 506: blank (); ! 507: showscreen (); ! 508: telluser (""); ! 509: break; ! 510: ! 511: case 'T': /* don't wait at page end */ ! 512: case 't': /* quickly type the file -- added 5/81, J.Lepreau */ ! 513: if (file[curfile].ltype == 'd') ! 514: { ! 515: telluser ("?Can only type files"); ! 516: break; ! 517: } ! 518: tempbuf[0] = '\0'; ! 519: bldnam(tempbuf, numarg, curfile, argv); ! 520: if (type(tempbuf, command == 't')) /* little t means wait */ ! 521: showscreen (); ! 522: curxy (CURSOR, curline); ! 523: break; ! 524: ! 525: case 'l': /* Refresh screen */ ! 526: case CTRL(l): /* added for editor compatibility -fjl */ ! 527: blank (); ! 528: showscreen (); ! 529: telluser (""); ! 530: break; ! 531: case 'c': /* Refresh current line */ ! 532: curxy (0, curline); ! 533: pentry (curfile); ! 534: curxy (CURSOR, curline); ! 535: break; ! 536: case CTRL(v): ! 537: case 'f': /* forward window */ ! 538: fscreen (); ! 539: break; ! 540: /* wish we could do meta-v */ ! 541: case 'b': /* backward window */ ! 542: bscreen (); ! 543: break; ! 544: case CTRL(n): ! 545: case '\r': ! 546: case '\n': /* next file */ ! 547: if (curfile == totfiles - 1) ! 548: telluser ("?At end of files"); ! 549: else ! 550: if (curline == scrlen - 1) ! 551: { ! 552: topfile = curfile; ! 553: curline = 0; ! 554: blank (); ! 555: showscreen (); ! 556: curxy (CURSOR, 0); ! 557: downline (); ! 558: } ! 559: else ! 560: downline (); ! 561: break; ! 562: case '^': /* previous file */ ! 563: case CTRL(h): /* backspace */ ! 564: case '-': ! 565: case CTRL(p): ! 566: if (curfile == 0) ! 567: telluser ("?At start of files"); ! 568: else ! 569: if (curline == 0) ! 570: { ! 571: topfile = curfile - scrlen + 1; ! 572: curline = scrlen - 1; ! 573: blank (); ! 574: showscreen (); ! 575: curxy (CURSOR, curline); ! 576: upline (); ! 577: } ! 578: else ! 579: upline (); ! 580: break; ! 581: case 'h': /* Help */ ! 582: case '?': ! 583: if (type(helpfile, 1)) /* wait */ ! 584: showscreen (); ! 585: curxy (CURSOR, curline); ! 586: break; ! 587: case 'd': /* delete file */ ! 588: if (file[curfile].deleted == DELETED) ! 589: telluser ("?Already marked deleted"); ! 590: else ! 591: { ! 592: numdeleted++; ! 593: file[curfile].deleted = DELETED; ! 594: printf ("D%c", 010); ! 595: if (curline + 1 == scrlen) ! 596: { ! 597: fscreen (); ! 598: downline (); ! 599: } ! 600: else ! 601: if (curfile != totfiles - 1) ! 602: downline (); ! 603: } ! 604: break; ! 605: case 'u': /* undelete file */ ! 606: if (file[curfile].deleted == NOTDELETED) ! 607: telluser ("?Not marked deleted"); ! 608: else ! 609: { ! 610: numdeleted--; ! 611: file[curfile].deleted = NOTDELETED; ! 612: printf (" %c", 010); ! 613: } ! 614: break; ! 615: default: ! 616: telluser ("Unknown command. Type ? or h for help"); ! 617: break; ! 618: } ! 619: } ! 620: if (numdeleted) ! 621: { ! 622: blank (); ! 623: printf ("The following %s marked for deletion:\n", ! 624: (numdeleted == 1) ? "is" : "are"); ! 625: typefiles (); ! 626: printf ("\nShall I delete %s? ", ! 627: (numdeleted == 1) ? "this" : "these"); ! 628: if ((command = readchar()) != 'y') ! 629: { ! 630: blank (); ! 631: showscreen (); ! 632: curxy (0, Tscrlen); ! 633: ceol (); ! 634: curxy (CURSOR, curline); ! 635: goto startup; ! 636: } ! 637: else ! 638: { ! 639: printf ("y\n"); ! 640: for (i = 0; i < totfiles; i++) ! 641: if (file[i].deleted == DELETED) { ! 642: nambuf[0] = '\0'; ! 643: bldnam(nambuf, numarg, i, argv); ! 644: if (file[i].ltype == 'd') ! 645: rm (nambuf, 0); ! 646: else ! 647: if (unlink (nambuf) < 0) ! 648: printf ("Delete of %s failed.\n", nambuf); ! 649: } ! 650: } ! 651: } ! 652: else ! 653: blank (); ! 654: ! 655: unsetdpy (); ! 656: exit(0); ! 657: } ! 658: ! 659: typefiles () ! 660: { ! 661: int longsiz, ! 662: i, ! 663: j, ! 664: maxperln, ! 665: numout, ! 666: longthis; ! 667: longsiz = numout = 0; ! 668: for (i = 0; i < totfiles; i++) ! 669: if (file[i].deleted == DELETED) ! 670: if (file[i].lflags & ISARG) ! 671: { ! 672: if (strlen (file[i].ln.namep) > longsiz) ! 673: { ! 674: longsiz = strlen (file[i].ln.namep); ! 675: } ! 676: } ! 677: else ! 678: { ! 679: if (strlen (file[i].ln.lname) > longsiz) ! 680: { ! 681: longsiz = strlen (file[i].ln.lname); ! 682: } ! 683: } ! 684: maxperln = scrwid / (longsiz + 3); ! 685: for (i = 0; i < totfiles; i++) ! 686: if (file[i].deleted == DELETED) ! 687: { ! 688: if (file[i].lflags & ISARG) ! 689: { ! 690: printf ("%s", file[i].ln.namep); ! 691: longthis = strlen (file[i].ln.namep); ! 692: } ! 693: else ! 694: { ! 695: printf ("%.14s", file[i].ln.lname); ! 696: longthis = strlen (file[i].ln.lname); ! 697: } ! 698: numout++; ! 699: if ((numout % maxperln) == 0) ! 700: putchar ('\n'); ! 701: else if (numout != numdeleted) ! 702: for (j = 0; j < (longsiz + 3 - longthis); j++) ! 703: putchar (' '); ! 704: } ! 705: } ! 706: ! 707: rm (arg, level) ! 708: char arg[]; ! 709: { ! 710: struct stat buf; ! 711: struct direct direct; ! 712: char name[100]; ! 713: int d; ! 714: ! 715: if (stat (arg, &buf)) ! 716: { ! 717: return; ! 718: } ! 719: if ((buf.st_mode & S_IFMT) == S_IFDIR) ! 720: { ! 721: if (access (arg, 02) < 0) ! 722: { ! 723: printf ("%s not deleted.\n", arg); ! 724: return; ! 725: } ! 726: if ((d = open (arg, 0)) < 0) ! 727: { ! 728: printf ("rm: %s: cannot read\n", arg); ! 729: return; ! 730: } ! 731: while (read (d, (char *) & direct, sizeof (direct)) == sizeof (direct)) ! 732: { ! 733: if (direct.d_ino != 0 && !dotname (direct.d_name)) ! 734: { ! 735: sprintf (name, "%s/%.14s", arg, direct.d_name); ! 736: rm (name, level + 1); ! 737: } ! 738: } ! 739: close (d); ! 740: errcode += rmdir (arg); ! 741: return; ! 742: } ! 743: ! 744: if (unlink (arg)) ! 745: { ! 746: ++errcode; ! 747: printf ("%s not deleted.\n", arg); ! 748: } ! 749: } ! 750: ! 751: dotname (s) ! 752: char *s; ! 753: { ! 754: if (s[0] == '.') ! 755: if (s[1] == '.') ! 756: if (s[2] == '\0') ! 757: return (1); ! 758: else ! 759: return (0); ! 760: else ! 761: if (s[1] == '\0') ! 762: return (1); ! 763: return (0); ! 764: } ! 765: ! 766: rmdir (f) ! 767: char *f; ! 768: { ! 769: int status, ! 770: i; ! 771: ! 772: if (dotname (f)) ! 773: return (0); ! 774: while ((i = vfork ()) == -1) ! 775: sleep (3); ! 776: if (i == 0) { ! 777: execl ("/bin/rmdir", "rmdir", f, 0); ! 778: execl ("/usr/bin/rmdir", "rmdir", f, 0); ! 779: printf ("rm: can't find rmdir\n"); ! 780: _exit(1); ! 781: } ! 782: wait (&status); ! 783: return (status); ! 784: } ! 785: ! 786: fscreen () ! 787: { ! 788: if (topfile + scrlen - 1 > totfiles - 1) ! 789: telluser ("?No remaining windows"); ! 790: else ! 791: { ! 792: topfile = topfile + scrlen - 1; ! 793: curfile = topfile; ! 794: curline = 0; ! 795: blank (); ! 796: showscreen (); ! 797: curxy (CURSOR, 0); ! 798: } ! 799: } ! 800: ! 801: bscreen () ! 802: { ! 803: if (topfile - scrlen + 1 < 0) ! 804: telluser ("?No previous windows"); ! 805: else ! 806: { ! 807: topfile = topfile - scrlen + 1; ! 808: curfile = topfile; ! 809: curline = 0; ! 810: blank (); ! 811: showscreen (); ! 812: curxy (CURSOR, 0); ! 813: } ! 814: } ! 815: ! 816: showscreen () ! 817: { ! 818: int i, ! 819: numprint; ! 820: home (); ! 821: numprint = 0; ! 822: for (i = topfile; (numprint < scrlen) && (i < totfiles); i++) ! 823: { ! 824: numprint++; ! 825: pentry (i); ! 826: putchar ('\n'); ! 827: } ! 828: if (splitflg) ! 829: printf ("%s\n", divider); ! 830: } ! 831: ! 832: getdir (dir) /* Reads directory dir */ ! 833: char *dir; ! 834: { ! 835: static struct direct dentry; ! 836: register int j; ! 837: struct direct *dp; ! 838: DIR *dirf; ! 839: ! 840: if ((dirf = opendir (dir)) == NULL) ! 841: { ! 842: printf ("\nSorry, %s unreadable.\n", dir); ! 843: unsetdpy (); ! 844: exit(1); ! 845: } ! 846: for (;;) ! 847: { ! 848: if ((dp = readdir(dirf)) == NULL) ! 849: break; ! 850: dentry = *dp; ! 851: if (dentry.d_ino == 0 ! 852: || dentry.d_name[0] == '.' && (dentry.d_name[1] == '\0' ! 853: || dentry.d_name[1] == '.' && dentry.d_name[2] == '\0')) ! 854: continue; ! 855: ! 856: if (totfiles == MAXFILES) ! 857: overflow(); /* abort, too may files */ ! 858: /* Just ignore if can't find the file, dir may be changing */ ! 859: if (gstat (makename (dir, dentry.d_name)) == 0) { /* 0 == Ok */ ! 860: file[totfiles].lnum = dentry.d_ino; ! 861: strncpy(file[totfiles].ln.lname, dentry.d_name, MAXN); ! 862: totfiles++; ! 863: if (totfiles % 10 == 0) ! 864: putchar ('.'); ! 865: } ! 866: } ! 867: closedir (dirf); ! 868: } ! 869: ! 870: gstat (name) /* Stats the file with name */ ! 871: char *name; ! 872: { ! 873: ! 874: file[totfiles].lflags = 0; ! 875: file[totfiles].lnum = 0; ! 876: file[totfiles].ltype = '-'; ! 877: ! 878: if (stat (name, &statbuf) < 0) ! 879: { ! 880: return(-1); ! 881: } ! 882: file[totfiles].lnum = statbuf.st_ino; ! 883: file[totfiles].lsize = statbuf.st_size; ! 884: switch (statbuf.st_mode & S_IFMT) ! 885: { ! 886: case S_IFLNK: ! 887: file[totfiles].ltype = 'l'; ! 888: break; ! 889: case S_IFDIR: ! 890: file[totfiles].ltype = 'd'; ! 891: break; ! 892: case S_IFBLK: ! 893: file[totfiles] .ltype = 'b'; ! 894: file[totfiles].lsize = statbuf.st_rdev; ! 895: break; ! 896: case S_IFCHR: ! 897: file[totfiles].ltype = 'c'; ! 898: file[totfiles].lsize = statbuf.st_rdev; ! 899: break; ! 900: } ! 901: file[totfiles].lflags = statbuf.st_mode & ~S_IFMT; ! 902: file[totfiles].luid = statbuf.st_uid; ! 903: file[totfiles].lgid = statbuf.st_gid; ! 904: file[totfiles].lnl = statbuf.st_nlink; ! 905: file[totfiles].latime = statbuf.st_atime; ! 906: file[totfiles].lctime = statbuf.st_ctime; ! 907: file[totfiles].lmtime = statbuf.st_mtime; ! 908: totblocks += nblock (statbuf.st_size); ! 909: return(0); ! 910: } ! 911: ! 912: char * ! 913: makename (dir, filen) ! 914: char *dir, ! 915: *filen; ! 916: { ! 917: static char dfile[100]; ! 918: register char *dp, ! 919: *fp; ! 920: register int i; ! 921: ! 922: dp = dfile; ! 923: fp = dir; ! 924: while (*fp) ! 925: *dp++ = *fp++; ! 926: *dp++ = '/'; ! 927: fp = filen; ! 928: strcpy(dp, fp); ! 929: return (dfile); ! 930: } ! 931: ! 932: long ! 933: nblock (size) ! 934: long size; ! 935: { ! 936: return ((size + 511) >> 9); ! 937: } ! 938: ! 939: pentry (whichone) ! 940: int whichone; ! 941: { ! 942: struct ! 943: { ! 944: char dminor, ! 945: dmajor; ! 946: }; ! 947: register t; ! 948: register char *cp; ! 949: ! 950: if (file[whichone].lnum == -1) ! 951: return; ! 952: if (iflg) ! 953: printf ("%5u ", file[whichone].lnum); ! 954: if (sflg) ! 955: printf ("%4D ", nblock (file[whichone].lsize)); ! 956: if (lflg) ! 957: { ! 958: putchar (file[whichone].ltype); ! 959: pmode (file[whichone].lflags); ! 960: printf ("%2d ", file[whichone].lnl); ! 961: t = file[whichone].luid; ! 962: if (gflg) ! 963: t = file[whichone].lgid; ! 964: if (getname (t, userbuf) == 0) ! 965: printf ("%-14.14s", userbuf); ! 966: else ! 967: printf ("%-14d", t); ! 968: if (file[whichone].ltype == 'b' || file[whichone].ltype == 'c') ! 969: printf ("%3d,%3d", major ((int) file[whichone].lsize), ! 970: minor ((int) file[whichone].lsize)); ! 971: else ! 972: printf ("%7ld", file[whichone].lsize); ! 973: if ((sortyp == WRITE) || (sortyp == 0) || (sortyp == SIZE)) ! 974: { ! 975: cp = ctime (&file[whichone].lmtime); ! 976: if (file[whichone].lmtime < year) ! 977: printf (" %-7.7s %-4.4s ", cp + 4, cp + 20); ! 978: else ! 979: printf (" %-12.12s ", cp + 4); ! 980: } ! 981: else ! 982: if (sortyp == READ) ! 983: { ! 984: cp = ctime (&file[whichone].latime); ! 985: if (file[whichone].latime < year) ! 986: printf (" %-7.7s %-4.4s ", cp + 4, cp + 20); ! 987: else ! 988: printf (" %-12.12s ", cp + 4); ! 989: } ! 990: } ! 991: printf ("%c", file[whichone].deleted ? 'D' : ' '); ! 992: if (file[whichone].lflags & ISARG) ! 993: printf (" %s", file[whichone].ln.namep); ! 994: else { ! 995: putchar(' '); ! 996: for (t=0; t<14; t++) { ! 997: register c = file[whichone].ln.lname[t] & 0377;; ! 998: if (c == '\0') ! 999: break; ! 1000: if (c<' ' || c>=0200) { ! 1001: c &= 0177; ! 1002: c |= 0100; ! 1003: putchar('^'); ! 1004: } ! 1005: putchar(c); ! 1006: } ! 1007: } ! 1008: } ! 1009: ! 1010: getname (uid, buf) ! 1011: int uid; ! 1012: char buf[]; ! 1013: { ! 1014: int j, ! 1015: c, ! 1016: n, sign, ! 1017: i; ! 1018: ! 1019: if (uid == lastuid) ! 1020: return (0); ! 1021: if (pwdf == NULL) ! 1022: return (-1); ! 1023: rewind (pwdf); ! 1024: lastuid = -1; ! 1025: do ! 1026: { ! 1027: i = 0; ! 1028: j = 0; ! 1029: n = 0; ! 1030: sign = 0; ! 1031: while ((c = fgetc (pwdf)) != '\n') ! 1032: { ! 1033: if (c == EOF) ! 1034: return (-1); ! 1035: if (c == ':') ! 1036: { ! 1037: j++; ! 1038: c = '0'; ! 1039: } ! 1040: if (j == 0) ! 1041: buf[i++] = c; ! 1042: if (j == 2) { ! 1043: if (c=='-') ! 1044: sign = 1; ! 1045: else ! 1046: n = n * 10 + c - '0'; ! 1047: } ! 1048: } ! 1049: if (sign) ! 1050: n = -n; ! 1051: n = (unsigned short)n; ! 1052: } while (n != uid); ! 1053: buf[i++] = '\0'; ! 1054: lastuid = uid; ! 1055: return (0); ! 1056: } ! 1057: ! 1058: int m1[] = ! 1059: { ! 1060: 1, S_IREAD >> 0, 'r', '-' ! 1061: }; ! 1062: int m2[] = ! 1063: { ! 1064: 1, S_IWRITE >> 0, 'w', '-' ! 1065: }; ! 1066: int m3[] = ! 1067: { ! 1068: 2, S_ISUID, 's', S_IEXEC >> 0, 'x', '-' ! 1069: }; ! 1070: int m4[] = ! 1071: { ! 1072: 1, S_IREAD >> 3, 'r', '-' ! 1073: }; ! 1074: int m5[] = ! 1075: { ! 1076: 1, S_IWRITE >> 3, 'w', '-' ! 1077: }; ! 1078: int m6[] = ! 1079: { ! 1080: 2, S_ISGID, 's', S_IEXEC >> 3, 'x', '-' ! 1081: }; ! 1082: int m7[] = ! 1083: { ! 1084: 1, S_IREAD >> 6, 'r', '-' ! 1085: }; ! 1086: int m8[] = ! 1087: { ! 1088: 1, S_IWRITE >> 6, 'w', '-' ! 1089: }; ! 1090: int m9[] = ! 1091: { ! 1092: 2, 0/*S_ISVTX*/, 't', S_IEXEC >> 6, 'x', '-' ! 1093: }; ! 1094: ! 1095: int *m[] = ! 1096: { ! 1097: m1, m2, m3, m4, m5, m6, m7, m8, m9 ! 1098: }; ! 1099: ! 1100: pmode (aflag) ! 1101: { ! 1102: register int **mp; ! 1103: ! 1104: flags = aflag; ! 1105: for (mp = &m[0]; mp < &m[sizeof (m) / sizeof (m[0])];) ! 1106: select (*mp++); ! 1107: } ! 1108: ! 1109: select (pairp) ! 1110: register int *pairp; ! 1111: { ! 1112: register int n; ! 1113: ! 1114: n = *pairp++; ! 1115: while (--n >= 0 && (flags & *pairp++) == 0) ! 1116: pairp++; ! 1117: putchar (*pairp); ! 1118: } ! 1119: ! 1120: compar (pp1, pp2) ! 1121: struct lbuf *pp1, ! 1122: *pp2; ! 1123: { ! 1124: register struct lbuf *p1, ! 1125: *p2; ! 1126: ! 1127: p1 = pp1; ! 1128: p2 = pp2; ! 1129: if (p1 -> lflags & ISARG && p1 -> ltype == 'd') ! 1130: { ! 1131: if (!(p2 -> lflags & ISARG && p2 -> ltype == 'd')) ! 1132: return (1); ! 1133: } ! 1134: else ! 1135: { ! 1136: if (p2 -> lflags & ISARG && p2 -> ltype == 'd') ! 1137: return (-1); ! 1138: } ! 1139: if (sortyp == SIZE) ! 1140: { ! 1141: if (p2 -> lsize == p1 -> lsize) ! 1142: return (0); ! 1143: if (p2 -> lsize > p1 -> lsize) ! 1144: return (rflg); ! 1145: return (-rflg); ! 1146: } ! 1147: else ! 1148: if (sortyp == WRITE) ! 1149: { ! 1150: if (p2 -> lmtime == p1 -> lmtime) ! 1151: return (0); ! 1152: if (p2 -> lmtime > p1 -> lmtime) ! 1153: return (rflg); ! 1154: return (-rflg); ! 1155: } ! 1156: else ! 1157: if (sortyp == READ) ! 1158: { ! 1159: if (p2 -> latime == p1 -> latime) ! 1160: return (0); ! 1161: if (p2 -> latime > p1 -> latime) ! 1162: return (rflg); ! 1163: return (-rflg); ! 1164: } ! 1165: return (rflg * strcmp (p1 -> lflags & ISARG ? p1 -> ln.namep : p1 -> ln.lname, ! 1166: p2 -> lflags & ISARG ? p2 -> ln.namep : p2 -> ln.lname)); ! 1167: } ! 1168: ! 1169: ceod() ! 1170: { ! 1171: putpad(CD); ! 1172: } ! 1173: ! 1174: ceol () ! 1175: { ! 1176: putpad (CE); ! 1177: } ! 1178: blank () ! 1179: { ! 1180: putpad (CL); ! 1181: } ! 1182: home () ! 1183: { ! 1184: if (HO) ! 1185: putpad (HO); ! 1186: else ! 1187: curxy(0,0); ! 1188: } ! 1189: insline () ! 1190: { ! 1191: putpad (AL); ! 1192: } ! 1193: ! 1194: /* Yes, folks, we use direct cursor addressing to get to next line! ! 1195: Before you mumble "What sort of cretin would do this?" here's ! 1196: the reason. We don't use \n since that obviously won't work. ! 1197: We don't use \012 since virgin version 7 makes that into a crlf. ! 1198: We don't use raw mode since we type out help files efficently, ! 1199: and we don't want to switch modes all the time. So enjoy. -- SMC */ ! 1200: ! 1201: downline () ! 1202: { ! 1203: curxy (CURSOR, ++curline); ! 1204: curfile++; ! 1205: } ! 1206: upline () ! 1207: { ! 1208: putpad (UP); ! 1209: curline--; ! 1210: curfile--; ! 1211: } ! 1212: ! 1213: /*VARARGS1*/ ! 1214: telluser (msg, args) ! 1215: char *msg; ! 1216: { ! 1217: curxy (0, Tscrlen); ! 1218: ceol (); ! 1219: printf (msg, args); ! 1220: curxy (CURSOR, curline); ! 1221: blurb++; ! 1222: } ! 1223: curxy (col, lin) ! 1224: { ! 1225: char *cmstr = tgoto (CM, col, lin); ! 1226: putpad (cmstr); ! 1227: } ! 1228: ! 1229: char *fgets(); ! 1230: ! 1231: type (filestr, waitflg) /* Modified to type help file & others. fjl 5/81 */ ! 1232: char *filestr; /* Kludgy now with split screen stuff! */ ! 1233: { ! 1234: int helpfd = 5; ! 1235: FILE *fd = stdin; ! 1236: char *eof; ! 1237: register int i, n; ! 1238: register int cc = 0; ! 1239: int cur_scrl; /* current screen length */ ! 1240: char helpbuf[512]; ! 1241: ! 1242: if (!splitflg) ! 1243: helpfd = open(filestr, 0); ! 1244: else ! 1245: fd = fopen(filestr, "r"); ! 1246: if (helpfd < 0 || fd == NULL) { ! 1247: telluser("?Unable to open %sfile",strcmp(filestr,helpfile)?"":"help "); ! 1248: return (FALSE); ! 1249: } ! 1250: ! 1251: signal(SIGINT, catchint); ! 1252: sigint = 0; ! 1253: ! 1254: if (!splitflg) { ! 1255: blank(); ! 1256: fflush(stdout); ! 1257: while ((i = read (helpfd, helpbuf, 512)) > 0 && !sigint) ! 1258: write (1, helpbuf, i); ! 1259: close(helpfd); ! 1260: } ! 1261: else { ! 1262: cur_scrl = totfiles - topfile + 1; /* topfile starts at 0 */ ! 1263: Worktop = ((cur_scrl < scrlen) ? cur_scrl : scrlen) + 1; ! 1264: do { ! 1265: curxy(0, Worktop); ! 1266: ceod(); ! 1267: for (i = Worktop; (i < Tscrlen) && !sigint && (cc != EOF); i++) { ! 1268: n = 0; ! 1269: while ((cc = getc(fd)) != EOF) { ! 1270: if (cc == '\t') ! 1271: n |= 07; ! 1272: chklen: if (n++ == scrwid-1) { /* Use most of screen */ ! 1273: if (cc != '\n') { ! 1274: ungetc(cc, fd); ! 1275: cc = '\n'; ! 1276: } ! 1277: } ! 1278: if (cc < ' ' && cc!='\n' && cc!='\t' || cc>=0200) { ! 1279: putchar('^'); ! 1280: cc &= 0177; ! 1281: cc |= 0100; ! 1282: goto chklen; ! 1283: } ! 1284: putchar(cc); ! 1285: if (cc == '\n') ! 1286: break; ! 1287: } ! 1288: } ! 1289: } while (!sigint && (cc != EOF) && waitchk(waitflg)); ! 1290: ! 1291: if (feof(fd)) ! 1292: printf("===== End-of-File =====\n"); ! 1293: fflush(stdout); ! 1294: fclose(fd); ! 1295: return(FALSE); /* means needs no re-display */ ! 1296: } ! 1297: ! 1298: if (!splitflg) { /* redundant now... */ ! 1299: if (!sigint) { ! 1300: curxy(0, Tscrlen); ! 1301: printf ("CR to return..."); ! 1302: readchar(); ! 1303: } ! 1304: blank (); ! 1305: return (TRUE); ! 1306: } ! 1307: } ! 1308: ! 1309: waitchk(waitflg) ! 1310: { ! 1311: if (!waitflg) ! 1312: return(1); ! 1313: fflush(stdout); ! 1314: curxy(0, Tscrlen); ! 1315: printf ("---Continue---"); ! 1316: ceol(); ! 1317: curxy(0, Tscrlen); ! 1318: readchar(); ! 1319: ceol(); ! 1320: if (sigint) ! 1321: return(0); /* avoids clear of screen */ ! 1322: return(1); ! 1323: } ! 1324: ! 1325: setdpy () ! 1326: { ! 1327: ioctl (0, TIOCGETP, &ioctlb); ! 1328: ioctlb.sg_flags |= CBREAK; ! 1329: ioctlb.sg_flags &= ~ECHO; ! 1330: ioctl (0, TIOCSETP, &ioctlb); ! 1331: } ! 1332: ! 1333: unsetdpy () ! 1334: { ! 1335: ioctlb.sg_flags &= ~CBREAK; ! 1336: ioctlb.sg_flags |= ECHO; ! 1337: ioctl (0, TIOCSETP, &ioctlb); ! 1338: } ! 1339: ! 1340: getcap () ! 1341: { ! 1342: char *ap; ! 1343: char *term; ! 1344: char *xPC; ! 1345: ! 1346: term = getenv ("TERM"); ! 1347: if (term == 0) ! 1348: { ! 1349: printf("No TERM in environment\n"); ! 1350: exit(1); ! 1351: } ! 1352: ! 1353: switch (tgetent (tbuf, term)) ! 1354: { ! 1355: case -1: ! 1356: printf("Cannot open termcap file\n"); ! 1357: exit (2); ! 1358: case 0: ! 1359: printf("%s: unknown terminal", term); ! 1360: exit (3); ! 1361: } ! 1362: ! 1363: ap = tcapbuf; ! 1364: ! 1365: Tscrlen = tgetnum ("li") - 1; ! 1366: scrwid = tgetnum ("co") - 1;/* lose 1 so won't scroll in last line */ ! 1367: ! 1368: UP = tgetstr ("up", &ap); ! 1369: CD = tgetstr ("cd", &ap); ! 1370: CE = tgetstr ("ce", &ap); ! 1371: HO = tgetstr ("ho", &ap); ! 1372: CL = tgetstr ("cl", &ap); ! 1373: CM = tgetstr ("cm", &ap); ! 1374: AL = tgetstr ("al", &ap); /* insert line, optional */ ! 1375: ! 1376: xPC = tgetstr ("pc", &ap); ! 1377: if (xPC) ! 1378: PC = *xPC; ! 1379: ! 1380: if ((CM == 0) || (CL == 0) || (UP == 0)) ! 1381: { ! 1382: printf("Tty must have cursor addr, clear, and 4 cursor motions.\n"); ! 1383: exit (1); ! 1384: } ! 1385: if (Tscrlen <= 0 || scrwid <= 0) ! 1386: { ! 1387: printf("Must know the screen size\n"); ! 1388: exit (1); ! 1389: } ! 1390: } ! 1391: ! 1392: outch (c) ! 1393: { ! 1394: putchar (c); ! 1395: } ! 1396: ! 1397: putpad (str) ! 1398: char *str; ! 1399: { ! 1400: if (str) ! 1401: tputs (str, 0, outch); ! 1402: } ! 1403: ! 1404: catchint(sig) ! 1405: { ! 1406: signal(SIGINT, SIG_IGN); /* reset it */ ! 1407: sigint = 1; ! 1408: } ! 1409: ! 1410: char * ! 1411: bldnam(str, numarg, filidx, argv) ! 1412: char *str; ! 1413: char *argv[]; ! 1414: { ! 1415: ! 1416: if (numarg == 1) ! 1417: strcat (str, file[filidx].ln.lname); ! 1418: else ! 1419: if (numarg == 2) { ! 1420: strcat (str, argv[1]); ! 1421: strcat (str, "/"); ! 1422: strcat (str, file[filidx].ln.lname); ! 1423: } ! 1424: else ! 1425: strcat (str, file[filidx].ln.namep); ! 1426: return(str); ! 1427: } ! 1428: ! 1429: char * ! 1430: catargs(str, argv) ! 1431: char *str; ! 1432: char *argv[]; ! 1433: { ! 1434: register int i; ! 1435: ! 1436: for (++argv; *argv; argv++) { ! 1437: if (**argv == '-') { ! 1438: strcat(str, *argv); ! 1439: strcat(str, " "); ! 1440: } ! 1441: } ! 1442: return(str); ! 1443: } ! 1444: ! 1445: overflow() ! 1446: { ! 1447: printf("\n?Too many files\007\n"); ! 1448: fflush(stdout); ! 1449: sleep(1); /* So user can see it - don't worry if less */ ! 1450: } ! 1451: ! 1452: char *skipto (string,charset) ! 1453: char *charset,*string; ! 1454: { ! 1455: register char *setp,*strp; ! 1456: register int found; ! 1457: ! 1458: found = 0; /* not found yet */ ! 1459: strp = string; /* start at first char */ ! 1460: ! 1461: while (*strp && !found) { /* until null or found */ ! 1462: /* find first char in charset matching *strp */ ! 1463: for (setp=charset; (*setp) && (*setp != *strp); setp++) ; ! 1464: if (*setp) found = 1; /* matches a char */ ! 1465: else strp++; /* else keep looking */ ! 1466: } ! 1467: ! 1468: return (strp); ! 1469: } ! 1470: ! 1471: readchar() ! 1472: { ! 1473: static neofs; ! 1474: register c; ! 1475: ! 1476: fflush(stdout); ! 1477: c = getchar(); ! 1478: if (c == EOF) ! 1479: if (++neofs > 100) ! 1480: exit(1); ! 1481: return(c); ! 1482: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.