|
|
1.1 ! root 1: /* ! 2: * List files in categories (and columns) ! 3: */ ! 4: ! 5: #include <stdio.h> ! 6: #include <sys/stat.h> ! 7: #include <sys/dir.h> ! 8: ! 9: #define WIDTH 79 /* Default line width */ ! 10: #define GAP 1 /* Minimum gap between columns */ ! 11: #define INDENT1 4 /* Indent for multiple directories */ ! 12: #define INDENT2 4 /* Indent for files in a category */ ! 13: #define NFNAME 400 /* Maximum a filename can expand to */ ! 14: ! 15: int oneflag; /* One per line */ ! 16: int aflag; /* Do all entries, including `.' and `..' */ ! 17: int bflag; /* Do block special */ ! 18: int cflag; /* Do character special */ ! 19: int dflag; /* Do directories */ ! 20: int fflag; /* Do regular files */ ! 21: int mflag; /* Do multiplexor files */ ! 22: int pflag; /* Do pipes */ ! 23: int allflag = 1; /* Do all types */ ! 24: int ndir; ! 25: int printed = 0; /* Set when we have printed something */ ! 26: int maxwidth; /* Maximum width of a filename */ ! 27: int lwidth = WIDTH-INDENT2; ! 28: ! 29: struct stat sb; ! 30: char iobuf[BUFSIZ]; ! 31: char obuf[BUFSIZ]; ! 32: char fname[NFNAME]; ! 33: ! 34: typedef struct ENTRY { ! 35: struct ENTRY *e_fp; ! 36: char e_name[DIRSIZ]; ! 37: } ENTRY; ! 38: ! 39: ENTRY *files, *dirs, *blocks, *chars, *pipes, *mults; ! 40: ! 41: main(argc, argv) ! 42: char *argv[]; ! 43: { ! 44: register char *ap; ! 45: register int i; ! 46: register int estat = 0; ! 47: ! 48: while (argc>1 && *argv[1]=='-') { ! 49: for (ap = &argv[1][1]; *ap!='\0'; ap++) ! 50: switch (*ap) { ! 51: case 'f': ! 52: fflag = 1; ! 53: allflag = 0; ! 54: break; ! 55: ! 56: case 'd': ! 57: dflag = 1; ! 58: allflag = 0; ! 59: break; ! 60: ! 61: case 'm': ! 62: mflag = 1; ! 63: allflag = 0; ! 64: break; ! 65: ! 66: case 'b': ! 67: bflag = 1; ! 68: allflag = 0; ! 69: break; ! 70: ! 71: case 'c': ! 72: cflag = 1; ! 73: allflag = 0; ! 74: break; ! 75: ! 76: case 'p': ! 77: pflag = 1; ! 78: allflag = 0; ! 79: break; ! 80: ! 81: case '1': ! 82: oneflag = 1; ! 83: break; ! 84: ! 85: case 'a': ! 86: aflag = 1; ! 87: break; ! 88: ! 89: default: ! 90: usage(); ! 91: } ! 92: argv++; ! 93: argc--; ! 94: } ! 95: if (allflag) ! 96: fflag = dflag = cflag = bflag = mflag = pflag = 1; ! 97: setbuf(stdout, obuf); ! 98: if (argc < 2) { ! 99: ndir = 1; ! 100: estat = lc("."); ! 101: } else { ! 102: if (argc > 2) ! 103: lwidth -= INDENT1; ! 104: ndir = argc-1; ! 105: for (i=1; i<argc; i++) { ! 106: estat |= lc(argv[i]); ! 107: fflush(stdout); ! 108: } ! 109: } ! 110: exit(estat); ! 111: } ! 112: ! 113: /* ! 114: * Do `lc' on a single name. ! 115: */ ! 116: lc(name) ! 117: char *name; ! 118: { ! 119: char *type; ! 120: ! 121: if (stat(name, &sb) < 0) { ! 122: fprintf(stderr, "%s: not found\n", name); ! 123: return (1); ! 124: } ! 125: switch (sb.st_mode & S_IFMT) { ! 126: case S_IFDIR: ! 127: return (lcdir(name)); ! 128: ! 129: case S_IFREG: ! 130: type = "file"; ! 131: break; ! 132: ! 133: case S_IFBLK: ! 134: type = "block special file"; ! 135: break; ! 136: ! 137: case S_IFCHR: ! 138: type = "character special file"; ! 139: break; ! 140: ! 141: case S_IFMPB: ! 142: case S_IFMPC: ! 143: type = "multiplexed file"; ! 144: break; ! 145: ! 146: case S_IFPIP: ! 147: type = "pipe"; ! 148: break; ! 149: ! 150: default: ! 151: printf("%s: unknown file type\n", name); ! 152: return (1); ! 153: } ! 154: printf("%s: %s\n", name, type); ! 155: return (0); ! 156: } ! 157: ! 158: /* ! 159: * Process one directory. ! 160: */ ! 161: lcdir(dname) ! 162: char *dname; ! 163: { ! 164: register struct direct *dp; ! 165: register int nb; ! 166: register int fd; ! 167: ! 168: clearlist(&files); ! 169: clearlist(&dirs); ! 170: clearlist(&blocks); ! 171: clearlist(&chars); ! 172: clearlist(&pipes); ! 173: clearlist(&mults); ! 174: maxwidth = 0; ! 175: if (ndir > 1) { ! 176: if (printed) ! 177: putchar('\n'); ! 178: printf("%s:\n", dname); ! 179: } ! 180: printed = 0; ! 181: if ((fd = open(dname, 0)) < 0) { ! 182: fprintf(stderr, "Cannot open directory `%s'\n", dname); ! 183: return (1); ! 184: } ! 185: while ((nb = read(fd, iobuf, BUFSIZ)) > 0) ! 186: for (dp = iobuf; dp < &iobuf[nb]; dp++) { ! 187: if (dp->d_ino == 0) ! 188: continue; ! 189: doentry(dname, dp); ! 190: } ! 191: close(fd); ! 192: prnames(); ! 193: if (nb < 0) { ! 194: fprintf(stderr, "%s: directory read error\n", dname); ! 195: return (1); ! 196: } ! 197: return (0); ! 198: } ! 199: ! 200: /* ! 201: * Do a stat on one filename in the ! 202: * indicated directory. ! 203: * and then sort into the appropriate table. ! 204: */ ! 205: doentry(dirname, dp) ! 206: char *dirname; ! 207: struct direct *dp; ! 208: { ! 209: int width = 0; ! 210: ! 211: { ! 212: register char *p = dp->d_name; ! 213: ! 214: if (!aflag ! 215: && *p++=='.' && (*p=='\0' || (*p++=='.' && *p=='\0'))) ! 216: return (0); ! 217: } { ! 218: register char *p1, *p2; ! 219: register unsigned n = DIRSIZ; ! 220: ! 221: p1 = fname; ! 222: p2 = dirname; ! 223: while (*p1++ = *p2++) ! 224: ; ! 225: p1--; ! 226: if (*p1 != '/') ! 227: *p1++ = '/'; ! 228: p2 = dp->d_name; ! 229: do { ! 230: if (*p2 == '\0') ! 231: break; ! 232: width++; ! 233: *p1++ = *p2++; ! 234: } while (--n); ! 235: *p1 = '\0'; ! 236: } ! 237: if (width > maxwidth) ! 238: maxwidth = width; ! 239: if (stat(fname, &sb) < 0) { ! 240: prindent("%.*s: cannot stat\n", DIRSIZ, dp->d_name); ! 241: return (1); ! 242: } { ! 243: register ENTRY *ep; ! 244: register ENTRY **list; ! 245: ! 246: if ((ep = (ENTRY *)malloc(sizeof (ENTRY))) == NULL) { ! 247: fprintf(stderr, "Out of memory\n"); ! 248: exit (1); ! 249: } ! 250: strncpy(ep->e_name, dp->d_name, DIRSIZ); ! 251: switch (sb.st_mode & S_IFMT) { ! 252: case S_IFREG: ! 253: list = &files; ! 254: break; ! 255: ! 256: case S_IFDIR: ! 257: list = &dirs; ! 258: break; ! 259: ! 260: case S_IFBLK: ! 261: list = &blocks; ! 262: break; ! 263: ! 264: case S_IFCHR: ! 265: list = &chars; ! 266: break; ! 267: ! 268: case S_IFMPC: ! 269: case S_IFMPB: ! 270: list = &mults; ! 271: break; ! 272: ! 273: case S_IFPIP: ! 274: list = &pipes; ! 275: break; ! 276: ! 277: default: ! 278: prindent("%.*s: unknown file type\n", DIRSIZ, ! 279: dp->d_name); ! 280: return (1); ! 281: } ! 282: addlist(list, ep); ! 283: } ! 284: return (0); ! 285: } ! 286: ! 287: /* ! 288: * Add an entry to the list. ! 289: * Sort the list at insertion time ! 290: * into lexicographic order. ! 291: */ ! 292: addlist(lpp, ep) ! 293: ENTRY **lpp; ! 294: ENTRY *ep; ! 295: { ! 296: register ENTRY *rp; ! 297: register ENTRY *pp; ! 298: ! 299: for (pp=NULL, rp=*lpp; rp!=NULL; pp=rp, rp=rp->e_fp) ! 300: if (strncmp(ep->e_name, rp->e_name, DIRSIZ) <= 0) ! 301: break; ! 302: if (pp == NULL) { ! 303: ep->e_fp = *lpp; ! 304: *lpp = ep; ! 305: } else { ! 306: ep->e_fp = pp->e_fp; ! 307: pp->e_fp = ep; ! 308: } ! 309: } ! 310: ! 311: /* ! 312: * Clear out the list, a pointer to which is ! 313: * the argument. ! 314: */ ! 315: clearlist(lpp) ! 316: ENTRY **lpp; ! 317: { ! 318: register ENTRY *rp, *op; ! 319: ! 320: rp = *lpp; ! 321: while (rp != NULL) { ! 322: op = rp; ! 323: rp = rp->e_fp; ! 324: free(op); ! 325: } ! 326: *lpp = NULL; ! 327: } ! 328: ! 329: /* ! 330: * Print out the appropriate names. ! 331: */ ! 332: prnames() ! 333: { ! 334: if (dflag) ! 335: prtype(dirs, "Directories"); ! 336: if (fflag) ! 337: prtype(files, "Files"); ! 338: if (cflag) ! 339: prtype(chars, "Character special files"); ! 340: if (bflag) ! 341: prtype(blocks, "Block special files"); ! 342: if (pflag) ! 343: prtype(pipes, "Pipes"); ! 344: if (mflag) ! 345: prtype(mults, "Multiplexed files"); ! 346: } ! 347: ! 348: /* ! 349: * Print out one type of files ! 350: */ ! 351: prtype(list, type) ! 352: ENTRY *list; ! 353: char *type; ! 354: { ! 355: register char *cp; ! 356: register ENTRY *ep; ! 357: register int n; ! 358: register int i; ! 359: int npl; ! 360: ! 361: if (list == NULL) ! 362: return; ! 363: if (printed) ! 364: putchar('\n'); ! 365: if(!oneflag) ! 366: prindent("%s:\n", type); ! 367: if (oneflag) ! 368: npl = 1; ! 369: else ! 370: npl = lwidth/(maxwidth+GAP); ! 371: ep = list; ! 372: i = 0; ! 373: for (ep = list; ep != NULL; ep = ep->e_fp) { ! 374: if (!oneflag && (i == 0)) { ! 375: printf("%*s", INDENT2, ""); ! 376: prindent(""); ! 377: } ! 378: n = DIRSIZ; ! 379: for (cp=ep->e_name; *cp!='\0' && n; n--) ! 380: putchar(*cp++); ! 381: if (++i!=npl && ep->e_fp!=NULL) { ! 382: n -= DIRSIZ-GAP-maxwidth; ! 383: while (n-- > 0) ! 384: putchar(' '); ! 385: } else { ! 386: i = 0; ! 387: putchar('\n'); ! 388: } ! 389: } ! 390: } ! 391: ! 392: /* ! 393: * Print a line with possible indent. ! 394: */ ! 395: /* VARARGS */ ! 396: prindent(x) ! 397: { ! 398: if (ndir > 1) ! 399: printf("%*s", INDENT1, ""); ! 400: printf("%r", &x); ! 401: printed = 1; ! 402: } ! 403: ! 404: usage() ! 405: { ! 406: fprintf(stderr, "Usage: lc [-afdcbp] [-1] [name ...]\n"); ! 407: exit(1); ! 408: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.