|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 6678 (0x1a16) Types: TextFile Notes: UNIX file Names: »lc.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─⟦this⟧ »cmd/lc.c«
/* * List files in categories (and columns) */ #include <stdio.h> #include <stat.h> #include <dir.h> #define WIDTH 79 /* Default line width */ #define GAP 1 /* Minimum gap between columns */ #define INDENT1 4 /* Indent for multiple directories */ #define INDENT2 4 /* Indent for files in a category */ #define NFNAME 400 /* Maximum a filename can expand to */ int oneflag; /* One per line */ int aflag; /* Do all entries, including `.' and `..' */ int bflag; /* Do block special */ int cflag; /* Do character special */ int dflag; /* Do directories */ int fflag; /* Do regular files */ int mflag; /* Do multiplexor files */ int pflag; /* Do pipes */ int allflag = 1; /* Do all types */ int ndir; int printed = 0; /* Set when we have printed something */ int maxwidth; /* Maximum width of a filename */ int lwidth = WIDTH-INDENT2; struct stat sb; char iobuf[BUFSIZ]; char obuf[BUFSIZ]; char fname[NFNAME]; typedef struct ENTRY { struct ENTRY *e_fp; char e_name[DIRSIZ]; } ENTRY; ENTRY *files, *dirs, *blocks, *chars, *pipes, *mults; main(argc, argv) char *argv[]; { register char *ap; register int i; register int estat = 0; while (argc>1 && *argv[1]=='-') { for (ap = &argv[1][1]; *ap!='\0'; ap++) switch (*ap) { case 'f': fflag = 1; allflag = 0; break; case 'd': dflag = 1; allflag = 0; break; case 'm': mflag = 1; allflag = 0; break; case 'b': bflag = 1; allflag = 0; break; case 'c': cflag = 1; allflag = 0; break; case 'p': pflag = 1; allflag = 0; break; case '1': oneflag = 1; break; case 'a': aflag = 1; break; default: usage(); } argv++; argc--; } if (allflag) fflag = dflag = cflag = bflag = mflag = pflag = 1; setbuf(stdout, obuf); if (argc < 2) { ndir = 1; estat = lc("."); } else { if (argc > 2) lwidth -= INDENT1; ndir = argc-1; for (i=1; i<argc; i++) { estat |= lc(argv[i]); fflush(stdout); } } exit(estat); } /* * Do `lc' on a single name. */ lc(name) char *name; { char *type; if (stat(name, &sb) < 0) { fprintf(stderr, "%s: not found\n", name); return (1); } switch (sb.st_mode & S_IFMT) { case S_IFDIR: return (lcdir(name)); case S_IFREG: type = "file"; break; case S_IFBLK: type = "block special file"; break; case S_IFCHR: type = "character special file"; break; case S_IFMPB: case S_IFMPC: type = "multiplexed file"; break; case S_IFPIP: type = "pipe"; break; default: printf("%s: unknown file type\n", name); return (1); } printf("%s: %s\n", name, type); return (0); } /* * Process one directory. */ lcdir(dname) char *dname; { register struct direct *dp; register int nb; register int fd; clearlist(&files); clearlist(&dirs); clearlist(&blocks); clearlist(&chars); clearlist(&pipes); clearlist(&mults); maxwidth = 0; if (ndir > 1) { if (printed) putchar('\n'); printf("%s:\n", dname); } printed = 0; if ((fd = open(dname, 0)) < 0) { fprintf(stderr, "Cannot open directory `%s'\n", dname); return (1); } while ((nb = read(fd, iobuf, BUFSIZ)) > 0) for (dp = iobuf; dp < &iobuf[nb]; dp++) { if (dp->d_ino == 0) continue; doentry(dname, dp); } close(fd); prnames(); if (nb < 0) { fprintf(stderr, "%s: directory read error\n", dname); return (1); } return (0); } /* * Do a stat on one filename in the * indicated directory. * and then sort into the appropriate table. */ doentry(dirname, dp) char *dirname; struct direct *dp; { int width = 0; { register char *p = dp->d_name; if (!aflag && *p++=='.' && (*p=='\0' || (*p++=='.' && *p=='\0'))) return (0); } { register char *p1, *p2; register unsigned n = DIRSIZ; p1 = fname; p2 = dirname; while (*p1++ = *p2++) ; p1--; if (*p1 != '/') *p1++ = '/'; p2 = dp->d_name; do { if (*p2 == '\0') break; width++; *p1++ = *p2++; } while (--n); *p1 = '\0'; } if (width > maxwidth) maxwidth = width; if (stat(fname, &sb) < 0) { prindent("%.*s: cannot stat\n", DIRSIZ, dp->d_name); return (1); } { register ENTRY *ep; register ENTRY **list; if ((ep = (ENTRY *)malloc(sizeof (ENTRY))) == NULL) { fprintf(stderr, "Out of memory\n"); exit (1); } strncpy(ep->e_name, dp->d_name, DIRSIZ); switch (sb.st_mode & S_IFMT) { case S_IFREG: list = &files; break; case S_IFDIR: list = &dirs; break; case S_IFBLK: list = &blocks; break; case S_IFCHR: list = &chars; break; case S_IFMPC: case S_IFMPB: list = &mults; break; case S_IFPIP: list = &pipes; break; default: prindent("%.*s: unknown file type\n", DIRSIZ, dp->d_name); return (1); } addlist(list, ep); } return (0); } /* * Add an entry to the list. * Sort the list at insertion time * into lexicographic order. */ addlist(lpp, ep) ENTRY **lpp; ENTRY *ep; { register ENTRY *rp; register ENTRY *pp; for (pp=NULL, rp=*lpp; rp!=NULL; pp=rp, rp=rp->e_fp) if (strncmp(ep->e_name, rp->e_name, DIRSIZ) <= 0) break; if (pp == NULL) { ep->e_fp = *lpp; *lpp = ep; } else { ep->e_fp = pp->e_fp; pp->e_fp = ep; } } /* * Clear out the list, a pointer to which is * the argument. */ clearlist(lpp) ENTRY **lpp; { register ENTRY *rp, *op; rp = *lpp; while (rp != NULL) { op = rp; rp = rp->e_fp; free(op); } *lpp = NULL; } /* * Print out the appropriate names. */ prnames() { if (dflag) prtype(dirs, "Directories"); if (fflag) prtype(files, "Files"); if (cflag) prtype(chars, "Character special files"); if (bflag) prtype(blocks, "Block special files"); if (pflag) prtype(pipes, "Pipes"); if (mflag) prtype(mults, "Multiplexed files"); } /* * Print out one type of files */ prtype(list, type) ENTRY *list; char *type; { register char *cp; register ENTRY *ep; register int n; register int i; int npl; if (list == NULL) return; if (printed) putchar('\n'); prindent("%s:\n", type); if (oneflag) npl = 1; else npl = lwidth/(maxwidth+GAP); ep = list; i = 0; for (ep = list; ep != NULL; ep = ep->e_fp) { if (i == 0) { printf("%*s", INDENT2, ""); prindent(""); } n = DIRSIZ; for (cp=ep->e_name; *cp!='\0' && n; n--) putchar(*cp++); if (++i!=npl && ep->e_fp!=NULL) { n -= DIRSIZ-GAP-maxwidth; while (n-- > 0) putchar(' '); } else { i = 0; putchar('\n'); } } } /* * Print a line with possible indent. */ /* VARARGS */ prindent(x) { if (ndir > 1) printf("%*s", INDENT1, ""); printf("%r", &x); printed = 1; } usage() { fprintf(stderr, "Usage: lc [-afdcbp] [-1] [name ...]\n"); exit(1); }