home *** CD-ROM | disk | FTP | other *** search
- static char title[] = "Ls.com, file list/find program, version 1.00, (14 January 1988)";
- static char copyright[] = "Copyright 1989 Timothy L. Kay -- non-commercial use permitted";
- static char permission[] = "Permission is hereby granted to distribute freely for non-commercial use only.";
- static char me[] = "Timothy L. Kay\nCaltech, 256-80\nPasadena, CA 91125\ntim@csvax.caltech.edu";
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <alloc.h>
- #include <string.h>
- #include <dir.h>
- #include <dos.h>
- #include <ctype.h>
-
- #define STDERR fprintf(stderr,
-
- int multi;
-
- int flag_1 = 0;
- int flag_F = 0;
- int flag_R = 0;
- int flag_a = 0;
- int flag_d = 0;
- int flag_f = 0;
- int flag_l = 0;
- int flag_t = 0;
- int flag_v = 0;
-
- int value_b = -1;
- int value_f = 0;
- #define vf_archive 0x01
- #define vf_ascii 0x02
- #define vf_size 0x04
- #define vf_bak 0x08
-
- long param_size;
- #define PARAM_SIZE_DEFAULT 10000L
- long param_percent;
- #define PARAM_PERCENT_DEFAULT 90
-
- typedef struct {
- char ff_reserved[21];
- char ff_attrib;
- struct { unsigned x:5; unsigned m:6; unsigned h:5; } ff_ftime;
- struct { unsigned d:5; unsigned m:4; unsigned y:7; } ff_fdate;
- long ff_fsize;
- char ff_name[13];
- } FF;
- #define SFF sizeof(FF)
-
- int ffirst(char *p, FF *f, int m) {
- return findfirst(p, (struct ffblk *)f, m);
- }
- int fnext(FF *f) {
- return findnext((struct ffblk *)f);
- }
-
- void help() {
- printf("Usage: ls [-c] [?] [--] [-?] [-1FRabltv] [-f[abis[#]]] [file ...]\n");
- printf(" where\n");
- printf(" -,? print this message c print copyright message\n");
- printf(" 1 print files in single column with path prepended\n");
- printf(" F enable inverse video for directories (or SET TERM=ansi)\n");
- printf(" R recursively list contents of subdirectories\n");
- printf(" a list all (including hidden and system) files\n");
- printf(" b# print files in single column preceded with %%i, i=1..#\n");
- printf(" f find files that match particular criteria\n");
- printf(" a# find files that contain > #%% ASCII text (default %d%%)\n", PARAM_PERCENT_DEFAULT);
- printf(" b find files with extension .bak\n");
- printf(" i find files with archive bit on\n");
- printf(" s# find files smaller than # bytes (default %ld bytes)\n", PARAM_SIZE_DEFAULT);
- printf(" l long format includes file date, time, size, attributes\n");
- printf(" t list files in time order rather than alphabetic\n");
- printf(" v verbose details of find decisions\n");
- printf("\n");
- printf(" examples\n");
- printf(" ls list files in current directory\n");
- printf(" ls -Rfas1000 / lists all ASCII files smaller than 1000 bytes\n");
- printf(" ls -vRfas1000 / same but explains why some files do not qualify\n");
- printf(" ls -Rfas / | zoo aI /backup backs up all ASCII files of reasonable size\n");
- printf(" ls -b2 *.c > temp.bat ; temp cc -DMSDOS compile all .c files\n");
- exit(0);
- }
-
- void copyr()
- {
- printf("%s\n", title);
- printf("%s\n", copyright);
- printf("%s\n", permission);
- printf("\n");
- printf("%s\n", me);
- exit(0);
- }
-
- /*
- * int cmp(char *s, char *t)
- *
- * Compares strings s and t, and returns an int whose value is
- *
- * < 0 if s < t,
- * 0 s == t, or
- * > 0 s > t.
- *
- * The comparison is more complex than the one performed by strcmp().
- * Any sequences of digits are treated as separate fields. For
- * example, the string "a100-x" is treated as three fields: the
- * string "a", the number 100, and the string "-x". This way, the
- * string "a30" is considered less than the string "a100".
- */
-
- int cmp(char *s, char *t) {
- char *s1, *t1;
- int s0, t0;
- for (s1 = s, t1 = t; *s1 || *t1; s = s1, t = t1) {
- while (*s1 && 0 == isdigit(*s1)) {
- ++s1;
- }
- while (*t1 && 0 == isdigit(*t1)) {
- ++t1;
- }
- s0 = s1 - s;
- t0 = t1 - t;
- if (s0 < t0) {
- int d = strncmp(s, t, s0);
- if (d) {
- return d;
- }
- return -1;
- } else if (s0 > t0) {
- int d = strncmp(s, t, t0);
- if (d) {
- return d;
- }
- return 1;
- } else {
- int d = strncmp(s, t, s0);
- if (d) {
- return d;
- }
- }
- while (*s1 && isdigit(*s1)) {
- ++s1;
- }
- while (*t1 && isdigit(*t1)) {
- ++t1;
- }
- s0 = s1 - s;
- t0 = t1 - t;
- if (s0 != t0) {
- return s0 - t0;
- } else {
- int d = strncmp(s, t, s0);
- if (d) {
- return d;
- }
- }
- }
- return 0;
- }
-
- int ncmp(FF *a, FF *b) {
- return strcmp(a->ff_name, b->ff_name);
- }
-
- int tcmp(FF *a, FF *b) {
- if (a->ff_fdate.y != b->ff_fdate.y) {
- return b->ff_fdate.y - a->ff_fdate.y;
- }
- if (a->ff_fdate.m != b->ff_fdate.m) {
- return b->ff_fdate.m - a->ff_fdate.m;
- }
- if (a->ff_fdate.d != b->ff_fdate.d) {
- return b->ff_fdate.d - a->ff_fdate.d;
- }
- if (a->ff_ftime.h != b->ff_ftime.h) {
- return b->ff_ftime.h - a->ff_ftime.h;
- }
- if (a->ff_ftime.m != b->ff_ftime.m) {
- return b->ff_ftime.m - a->ff_ftime.m;
- }
- if (a->ff_ftime.x != b->ff_ftime.x) {
- return b->ff_ftime.x - a->ff_ftime.x;
- }
- return 0;
- }
-
- /*
- * FF *dir(char *s, int m)
- *
- * Returns a pointer to an array of FF structures consisting of the
- * filenames which match pattern s along with their attributes. The
- * mask m determines what types of files (directories, system, hidden,
- * etc.) are eligible to be matched. The last entry of the array has
- * an empty file name. If an error occurs, 0 is returned.
- */
-
- FF *dir(char *s, int m) {
- int i, n;
- FF *x, *xp;
- FF f;
-
- /* make a first pass to count files */
-
- i = ffirst(s, &f, m);
- while (0 == i && 0 == flag_a && '.' == *f.ff_name) {
- i = fnext(&f);
- }
- if (i != 0) {
- return 0;
- }
- for (n = 0; i == 0; ++n) {
- do {
- i = fnext(&f);
- } while (0 == i && 0 == flag_a && '.' == *f.ff_name);
- }
-
- /* allocate array */
-
- xp = x = malloc(SFF * (n + 1));
- if (x == 0) {
- return 0;
- }
-
- /* collect data */
-
- ffirst(s, &f, m);
- while (0 == flag_a && '.' == *f.ff_name) {
- fnext(&f);
- }
- for (i = 0; i < n; ++i) {
- *xp = f;
- strlwr(xp->ff_name);
- ++xp;
- do {
- fnext(&f);
- } while (0 == flag_a && '.' == *f.ff_name);
- }
- *xp->ff_name = 0;
- /* sort data */
-
- if (flag_t) {
- qsort(x, n, SFF, tcmp);
- } else {
- qsort(x, n, SFF, ncmp);
- }
-
- return x;
- }
-
- void flags(char *s) {
- for (; *s; ++s) {
- switch (*s) {
- case '-':
- case '?': help();
- case '1': flag_1 = 1; flag_l = 0; break;
- case 'C': flag_1 = 0; flag_l = 0; break;
- case 'F': flag_F = 1; break;
- case 'R': flag_R = 1; break;
- case 'a': flag_a = 1; break;
- case 'b':
- flag_1 = 1;
- flag_l = 0;
- if (s[1] && isdigit(s[1])) {
- value_b = s[1] - '0';
- ++s;
- } else {
- value_b = 1;
- }
- break;
- case 'c': copyr();
- case 'd': flag_d = 1; break;
- case 'f':
- flag_f = 1;
- if (0 == flag_1 && 0 == flag_l) {
- flag_1 = 1;
- }
- for (++s; *s; ++s) {
- switch (*s) {
- case 'a':
- value_f |= vf_ascii;
- param_percent = 0;
- while (isdigit(s[1])) {
- param_size = 10 * param_percent + *++s - '0';
- }
- if (0 == param_percent) {
- param_percent = PARAM_PERCENT_DEFAULT;
- }
- break;
- case 'b': value_f |= vf_bak; break;
- case 'i': value_f |= vf_archive; break;
- case 's':
- value_f |= vf_size;
- param_size = 0;
- while (isdigit(s[1])) {
- param_size = 10 * param_size + *++s - '0';
- }
- if (0 == param_size) {
- param_size = PARAM_SIZE_DEFAULT;
- }
- break;
- default:
- STDERR "Unknown switch -f%c\n", *s);
- exit(1);
- }
- }
- --s;
- break;
- case 'l': flag_1 = 0; flag_l = 1; break;
- case 't': flag_t = 1; break;
- case 'v': flag_v = 1; break;
- default:
- STDERR "Unknown switch -%c\n", *s);
- exit(1);
- }
- }
- }
-
- void massage(char *s) {
- if (0 == *s) {
- return;
- }
- for (; *s; ++s) {
- if ('\\' == *s) {
- *s = '/';
- } else if (isupper(*s)) {
- *s = tolower(*s);
- }
- }
- if (*--s == '/') {
- *s = 0;
- }
- }
-
- void path(char *p, char *s) {
- char *pp;
- strcpy(p, s);
- pp = strrchr(p, '/');
- if (0 == pp) {
- *p = 0;
- } else {
- pp[1] = 0;
- }
- }
-
- char month[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
-
- void outputLong_1(FF *f) {
- if (f->ff_attrib & (FA_DIREC | FA_LABEL)) {
- printf("%c%c%c%c%c%c%c%c %d %.3s %2d %2d:%02d %s\n",
- (f->ff_attrib & 0x80) ? '8' : ' ',
- (f->ff_attrib & 0x40) ? '4' : ' ',
- (f->ff_attrib & FA_ARCH) ? 'a' : '-',
- (f->ff_attrib & FA_DIREC) ? 'd' : '-',
- (f->ff_attrib & FA_LABEL) ? 'v' : '-',
- (f->ff_attrib & FA_SYSTEM) ? 's' : '-',
- (f->ff_attrib & FA_HIDDEN) ? 'h' : '-',
- (f->ff_attrib & FA_RDONLY) ? 'r' : '-',
- f->ff_fdate.y + 1980, month + 3 * (f->ff_fdate.m - 1), f->ff_fdate.d,
- f->ff_ftime.h, f->ff_ftime.m,
- f->ff_name);
- } else {
- printf("%c%c%c%c%c%c%c%c %d %.3s %2d %2d:%02d %6ld %s\n",
- (f->ff_attrib & 0x80) ? '8' : ' ',
- (f->ff_attrib & 0x40) ? '4' : ' ',
- (f->ff_attrib & FA_ARCH) ? 'a' : '-',
- (f->ff_attrib & FA_DIREC) ? 'd' : '-',
- (f->ff_attrib & FA_LABEL) ? 'v' : '-',
- (f->ff_attrib & FA_SYSTEM) ? 's' : '-',
- (f->ff_attrib & FA_HIDDEN) ? 'h' : '-',
- (f->ff_attrib & FA_RDONLY) ? 'r' : '-',
- f->ff_fdate.y + 1980, month + 3 * (f->ff_fdate.m - 1), f->ff_fdate.d,
- f->ff_ftime.h, f->ff_ftime.m,
- f->ff_fsize, f->ff_name);
- }
- }
-
- void reverse(char *q, char *p) {
- while (*p) {
- if ('/' == *p) {
- *q++ = '\\';
- } else {
- *q++ = *p;
- }
- ++p;
- }
- *q = 0;
- }
-
- int qualifies(char *p, FF *f) {
- char fn[MAXPATH];
- sprintf(fn, "%s%s", p, f->ff_name);
- if (0 == (value_f & vf_bak)
- && 0 == strcmp(".bak", f->ff_name + strlen(f->ff_name) - 4)) {
- if (flag_v) {
- STDERR "%s -- skipped (.bak)\n", fn);
- }
- return 0;
- }
- if (f->ff_attrib & FA_DIREC) {
- return 0;
- }
- if ((value_f & vf_archive) && 0 == (f->ff_attrib & FA_ARCH)) {
- if (flag_v) {
- STDERR "%s -- skipped (archive bit off)\n", fn);
- }
- return 0;
- }
- if ((value_f & vf_size) && (param_size < f->ff_fsize)) {
- if (flag_v) {
- STDERR "%s -- skipped (%ld bytes)\n", fn, f->ff_fsize);
- }
- return 0;
- }
- if ((value_f & vf_ascii)) {
- int fd, i, j, c;
- char buf[512];
- fd = open(fn, O_RDONLY | O_BINARY);
- if (fd < 0) {
- perror(fn);
- return 0;
- }
- i = read(fd, buf, sizeof buf);
- if (i < 512 && i < f->ff_fsize) {
- STDERR "1 Cannot read %s\n", fn);
- close(fd);
- return 0;
- }
- for (c = 0, j = 0; j < i; ++j) {
- c += isprint(buf[j]) || isspace(buf[j]);
- }
- if (100L * c < param_percent * i) {
- if (flag_v) {
- STDERR "%s -- skipped (%d%% printable)\n", fn, 100L * c / i);
- }
- close(fd);
- return 0;
- }
- if (512 < f->ff_fsize) {
- lseek(fd, -512L, 2);
- i = read(fd, buf, sizeof buf);
- if (i < 512 && i < f->ff_fsize) {
- STDERR "2 Cannot read %s\n", fn);
- close(fd);
- return 0;
- }
- for (c = 0, j = 0; j < i; ++j) {
- c += isprint(buf[j]) || isspace(buf[j]);
- }
- if (100L * c < param_percent * i) {
- if (flag_v) {
- STDERR "%s -- skipped (%d%% printable)\n", fn, 100L * c / i);
- }
- close(fd);
- return 0;
- }
- }
- if (3 * 512 < f->ff_fsize) {
- lseek(fd, f->ff_fsize / 2L - 256L, 0);
- i = read(fd, buf, sizeof buf);
- if (i < 512 && i < f->ff_fsize) {
- STDERR "3 Cannot read %s\n", fn);
- close(fd);
- return 0;
- }
- for (c = 0, j = 0; j < i; ++j) {
- c += isprint(buf[j]) || isspace(buf[j]);
- }
- if (100L * c < param_percent * i) {
- if (flag_v) {
- STDERR "%s -- skipped (%d%% printable)\n", fn, 100L * c / i);
- }
- close(fd);
- return 0;
- }
- }
- close(fd);
- }
- return 1;
- }
-
- void outputLong(char *p, FF *f) {
- char q[MAXPATH];
- reverse(q, p);
- for (; *f->ff_name; ++f) {
- if (0 == flag_f || qualifies(p, f)) {
- outputLong_1(f);
- }
- }
- }
-
- void outputOne(char *p, FF *f) {
- char q[MAXPATH];
- reverse(q, p);
- for (; *f->ff_name; ++f) {
- if (0 == flag_f || qualifies(p, f)) {
- if (0 <= value_b) {
- int i, k;
- for (i = 1; i <= value_b; ++i) {
- printf("%%%d ", i);
- }
- k = 45 - strlen(q);
- if (k < 0) {
- k = 0;
- }
- printf("%s%-*s", q, k, f->ff_name);
- for (; i <= 9; ++i) {
- printf(" %%%d", i);
- }
- printf("\n");
- } else {
- printf("%s%s\n", p, f->ff_name);
- }
- }
- }
- }
-
- #define SCREENWIDTH 80
-
- void outputColumn(FF *f) {
- FF *fp;
- int i, j, n, on_a_line, number_of_lines;
- for (n = 0, fp = f; *fp->ff_name; ++n, ++fp)
- ;
- on_a_line = SCREENWIDTH / 13;
- number_of_lines = (n + on_a_line - 1) / on_a_line;
- for (i = 0; i < number_of_lines; ++i) {
- for (j = 0; j < on_a_line; ++j) {
- int k = j * number_of_lines + i;
- if (k < n) {
- if (flag_F && (f[k].ff_attrib & FA_DIREC) && isatty(1)) {
- printf(" \033[7m%s\033[0m%s", f[k].ff_name,
- " " + strlen(f[k].ff_name));
- } else {
- printf(" %-12.12s", f[k].ff_name);
- }
- }
- }
- printf("\n");
- }
- }
-
- /* -d causes the arguments themselves to be output. This
- * mode isn't very useful unless some globbing code is
- * added to c0?.c
- */
-
- void list_d(char *s) {
- if (flag_1) {
- printf("%s\n", s);
- } else if (flag_l) {
- /*
- outputLong_1(s);
- */
- } else {
- printf("%s\n", s);
- }
- }
-
- /* -R lists the entire directory tree. */
-
- void list_R(char *s) {
- FF *f, *fp;
- char p[MAXPATH];
-
- path(p, s);
- f = dir(s, flag_a ? 0xef : 0x00);
- if (0 == flag_1) {
- printf("%s:\n", p);
- }
- if (f) {
- if (flag_1) {
- outputOne(p, f);
- } else if (flag_l) {
- outputLong(p, f);
- } else {
- outputColumn(f);
- }
- }
- free(f);
- f = dir(s, flag_a ? 0xff : FA_DIREC);
- if (0 == f) {
- return;
- }
- for (fp = f; *fp->ff_name; ++fp) {
- char r[MAXPATH];
- if ((fp->ff_attrib & FA_DIREC) && '.' != *fp->ff_name) {
- sprintf(r, "%s%s/*.*", p, fp->ff_name);
- list_R(r);
- }
- }
- free(f);
- }
-
- /* Without -d and -R, files are listed, and directory contents
- are listed.
- */
-
- void list(char *s) {
- FF *f;
- char p[MAXPATH];
- f = dir(s, flag_a ? 0xff : FA_DIREC);
- if (0 == f) {
- return;
- }
- path(p, s);
- if (flag_1) {
- outputOne(p, f);
- } else if (flag_l) {
- outputLong(p, f);
- } else {
- outputColumn(f);
- }
- free(f);
- }
-
- /* The dir function is called twice. The first time, we add
- * "/*.*" to the end of the pattern. If this fails, we try
- * without. We can't just stat it to see if it is a directory
- * because it may have wildcards, and we'd get its expansion.
- * We can't compare the names because a directory could
- * contain a file of the same name.
- */
-
- void select(char *s) {
- char fn[MAXPATH];
- FF f;
-
- massage(s);
- sprintf(fn, "%s/*.*", s);
- if (ffirst(fn, &f, 0xff)) {
- strcpy(fn, s);
- if (ffirst(fn, &f, 0xff)) {
- return;
- }
- } else if (multi && 0 == flag_R) {
- printf("%s:\n", s);
- }
-
- if (flag_d) {
- list_d(fn);
- } else if (flag_R) {
- list_R(fn);
- } else {
- list(fn);
- }
- }
-
- void set_flag_F()
- {
- char *ep = getenv("TERM");
- if (ep) {
- flag_F = !strcmp(ep, "ansi") || !strcmp(ep, "vt100");
- }
- }
-
- void main(int argc, char *argv[]) {
- int i, j, named = 0;
-
- if (argc == 2 && !strcmp(argv[1], "?")) {
- help();
- }
-
- set_flag_F();
-
- for (j = 0, i = 1; i < argc; ++i) {
- if (argv[i][0] != '-') {
- ++j;
- }
- }
- if (j < 2) {
- multi = 0;
- } else {
- multi = 1;
- }
- for (i = 1; i < argc; ++i) {
- if (argv[i][0] == '-') {
- flags(argv[i] + 1);
- } else {
- named = 1;
- select(argv[i]);
- }
- }
- if (0 == named) {
- select("*.*");
- }
- }