home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <dos.h>
- #include <dir.h>
- #include <io.h>
- #include <time.h>
- #include <string.h>
-
- typedef char Boolean;
- #define False 0
- #define True 1
- #define Null NULL
-
- struct ffblk ff;
- time_t pascal __dostimetou(int ff_fdate, int ff_ftime);
- #define TIMEOF(ff) __dostimetou(ff.ff_fdate, ff.ff_ftime)
-
- char optstr[] = "adlrstu1ACFR";
- char opts[12];
- #define opt_a opts[0]
- #define opt_d opts[1]
- #define opt_l opts[2]
- #define opt_r opts[3]
- #define opt_s opts[4]
- #define opt_t opts[5]
- #define opt_u opts[6]
- #define opt_1 opts[7]
- #define opt_A opts[8]
- #define opt_C opts[9]
- #define opt_F opts[10]
- #define opt_R opts[11]
-
- char dir_d = 0;
- char dir_F = 0;
- char dir_R = FA_DIREC;
- char dot_R = 0xe5;
-
- int maxcols = 0;
- char slash = '\\';
- char findattr= FA_DIREC;
- time_t ltime;
-
- char attrmsk[] = {FA_DIREC, FA_ARCH, FA_SYSTEM, FA_HIDDEN, FA_RDONLY};
-
- struct node {
- struct node *next;
- char attrib;
- long size;
- int csize;
- time_t time;
- char *name;
- };
- struct node *flist;
- int nfiles;
- int nclust;
- int longest;
- unsigned int clust; /* cluster size */
- int lenbase; /* length of -s & -l stuff */
-
- char line[128];
- char currdir[128];
-
- void showfiles(int dirlen, struct node *dlist);
-
- Boolean do_opts(char *p) {
- char *p1;
-
- for (; *p != '\0'; ++p) {
- if ((p1 = strchr(optstr, *p)) == Null) return False;
- opts[p1 - optstr] = True;
- }
- return True;
- }
-
- void setclust(int drive) {
- unsigned int clust1;
-
- _AH = 0x1c;
- _DL = drive;
- geninterrupt(0x21);
- clust1 = _AL * _CX;
- _DS = _SS;
- clust = clust1;
- }
-
- void freelist(struct node *np) {
- struct node *np2;
-
- while (np != Null) {
- np2 = np->next;
- free(np->name);
- free(np);
- np = np2;
- }
- }
-
- int addtolist(struct node **head, char *name, Boolean dtflag) {
- int len;
- struct node *np;
-
- if ((np = malloc(sizeof(struct node))) == Null ||
- (np->name = malloc((len = strlen(name)) + 1)) == Null) {
- fputs("Out of memory.\n", stderr);
- exit(2);
- }
- np->next = *head;
- *head = np;
- np->attrib = ff.ff_attrib;
- np->size = ff.ff_fsize;
- np->time = 0;
- if (dtflag) np->time = TIMEOF(ff);
- strcpy(np->name, name);
- return len;
- }
-
- void addfile(char *name, struct node **dlistp, char dot_a, Boolean dtflag) {
- int len;
-
- if (!(ff.ff_attrib & dir_d) && *name != dot_a) {
- len = addtolist(&flist, name, dtflag);
- ++nfiles;
- if (ff.ff_attrib & dir_F) ++len;
- if (len > longest) longest = len;
- flist->csize = 0;
- if (!(ff.ff_attrib & FA_DIREC) && ff.ff_fsize != 0)
- nclust += (flist->csize = (ff.ff_fsize - 1) / clust + 1);
- }
- if ((ff.ff_attrib & dir_R) && *name != dot_R)
- (void) addtolist(dlistp, name, dtflag);
- }
-
- int opt_findfirst(char *base, int baselen, char *fn) {
- char attr = findattr;
- Boolean nowild = (strchr(fn, '*') == Null && strchr(fn, '?') == Null);
-
- memcpy(line, base, baselen);
- strcpy(line + baselen, fn);
- if (strchr(fn, '.') == Null) {
- if (nowild &&
- findfirst(line, &ff, attr | FA_HIDDEN | FA_SYSTEM) == 0 &&
- ff.ff_attrib & FA_DIREC) return 0;
- strcat(line + baselen, ".*");
- }
- else if (nowild) attr |= FA_HIDDEN | FA_SYSTEM;
- return findfirst(line, &ff, attr);
- }
-
- Boolean processopt(char *base, int baselen, char *fn, struct node **dlistp,
- Boolean showfull) {
- char dot_a;
-
- if (opt_findfirst(base, baselen, fn) != 0) return False;
- dot_a = opt_a || (*fn != '*' && *fn != '?') ? 0 : '.';
- for (;;) {
- char *p1 = ff.ff_name;
- char *p2 = line + baselen;
-
- for (;;) {
- char c = *p1;
- if (c >= 'A' && c <= 'Z') c |= 0x20;
- *p2++ = c;
- if (c == '\0') break;
- ++p1;
- }
- addfile(line + (showfull ? 0 : baselen), dlistp, dot_a, True);
- if (findnext(&ff) != 0) break;
- }
- return True;
- }
-
- struct node *mergesort(struct node *head, Boolean reverse) {
- struct node *p1, *p2, *newhead, *t;
-
- if ((p2 = head->next) == Null) return head;
- p1 = head;
- if (opt_u)
- if (reverse) return head;
- else p2 = Null;
- else {
- for (;;) {
- if ((p2 = p2->next) == Null) break;
- if ((p2 = p2->next) == Null) break;
- p1 = p1->next;
- }
- reverse ^= 1;
- p2 = mergesort(p1->next, reverse);
- p1->next = Null;
- p1 = mergesort(head, reverse);
- }
- /*
- * Now merge p1 and p2.
- */
- newhead = Null;
- while (p2 != Null) {
- if (reverse ^ (opt_t ? p1->time > p2->time :
- strcmp(p1->name, p2->name) < 0)) {
- t = p1;
- p1 = p2;
- }
- else t = p2;
- p2 = t->next;
- t->next = newhead;
- newhead = t;
- }
- while (p1 != Null) {
- t = p1;
- p1 = p1->next;
- t->next = newhead;
- newhead = t;
- }
- return newhead;
- }
-
- void putlong(long value, char *p, int len) {
- char temp[10];
- int i;
-
- (void) ltoa(value, temp, 10);
- i = len - strlen(temp);
- while (--i >= 0) *p++ = ' ';
- strcpy(p, temp);
- }
-
- void showdir(int len) {
- struct node *dlist = Null;
- static char total[] = "Total xxxxxx";
- char drive = 0;
-
- if (len != 0) {
- char c = currdir[len - 1];
-
- if (c != ':' && c != '/' && c != '\\')
- if (c == '.' && (len == 1 || (len == 3 && currdir[1] == ':')))
- --len;
- else currdir[len++] = slash;
- c = *currdir | 0x20;
- if (c >= 'a' && c <= 'z' && currdir[1] == ':')
- drive = c - ('a' - 1);
- }
- setclust(drive);
- processopt(currdir, len, "*.*", &dlist, False);
- if (opt_s | opt_l) {
- (void) ltoa(nclust, total + 6, 10);
- puts(total);
- }
- showfiles(len, dlist);
- }
-
- void showfiles(int dirlen, struct node *dlist) {
- struct node *np;
-
- if (flist != Null) {
- int ncols, nrows;
- struct node *np;
- int i;
-
- flist = mergesort(flist, opt_r);
- longest = (lenbase + longest) / 8 + 1;
- if ((ncols = maxcols / longest) == 0) ncols = 1;
- i = nrows = (nfiles - 1) / ncols + 1;
- np = flist;
- while (i > 0) { /* loop over rows */
- struct node *np1 = np;
- int nleft = nfiles;
-
- for (;;) { /* loop over columns */
- int len = lenbase + strlen(np1->name);
- int i;
-
- if (opt_s | opt_l) {
- char *p = line;
- char *timep;
-
- if (opt_s) {
- if (np1->attrib & FA_DIREC) memset(p, ' ', 5);
- else {
- putlong(np1->csize, p, 4);
- if (np1->csize < 10000) p[4] = ' ';
- }
- p += 5;
- }
- if (opt_l) {
- int i;
-
- for (i = 0; i < sizeof(attrmsk); ++i)
- *p++ = np1->attrib & attrmsk[i] ?
- "dashr"[i] : '-';
- if (np1->attrib & FA_DIREC) memset(p, ' ', 8);
- else putlong(np1->size, p, 8);
- p += 8;
- if (np1->time == 0) memset(p, ' ', 14);
- else {
- timep = ctime(&np1->time);
- memcpy(p, timep + 3, 8);
- memcpy(p + 8,
- timep + (np1->time < ltime ? 19 : 11), 5);
- p[13] = ' ';
- }
- p += 14;
- }
- (void) fwrite(line, 1, p - line, stdout);
- }
- fputs(np1->name, stdout);
- if (np1->attrib & dir_F) {
- putchar('/');
- ++len;
- }
- if ((nleft -= nrows) <= 0) break;
- i = nrows;
- while (--i >= 0) np1 = np1->next;
- len /= 8;
- while (len < longest) {
- putchar('\t');
- ++len;
- }
- }
- putchar('\n');
- np = np->next;
- --nfiles;
- --i;
- }
- freelist(flist);
- flist = Null;
- nfiles = 0;
- nclust = 0;
- longest = 0;
- }
- if (dlist == Null) return;
- dlist = mergesort(dlist, opt_r);
- for (np = dlist; np != Null; np = np->next) {
- int len = strlen(np->name);
-
- memcpy(currdir + dirlen, np->name, len);
- currdir[len += dirlen] = '\0';
- putchar('\n');
- fputs(currdir, stdout);
- puts(":");
- showdir(len);
- }
- freelist(dlist);
- }
-
- void cdecl main(int argc, char **argv) {
- static struct node *dlist = Null;
- char **argvend = argv + argc;
- char *p;
-
- if ((p = getenv("LS")) != Null) {
- if (*p == '-') ++p;
- if (!do_opts(p))
- fputs("Illegal flag in environment variable LS\n", stderr);
- }
- for (++argv; argv < argvend;) {
- if (*(p = *argv) != '-') break;
- ++argv;
- if (*++p == '\0') break;
- if (!do_opts(p)) {
- fputs("Usage: ls -adlrstu1ACFR file1 ...\n", stderr);
- exit(1);
- }
- }
- /* get screen width */
- if (!opt_1 && (opt_C || (!opt_l && isatty(1)))) {
- _AH = 0x0f;
- geninterrupt(0x10);
- maxcols = _AH / 8;
- }
- if (!opt_d) dir_d = FA_DIREC;
- else if (!opt_R) dir_R = 0;
- if (opt_F) dir_F = FA_DIREC;
- if (opt_s) lenbase += 5;
- if (opt_l) {
- lenbase += 27;
- ltime = time(Null) - 180L * 24 * 60 * 60;
- }
- if (opt_a | opt_A) findattr |= FA_HIDDEN | FA_SYSTEM;
- if (getswitchar() != '/') slash = '/';
- if (argv >= argvend) *--argv = ""; /* if no args */
- for (; argv < argvend; ++argv) {
- char *arg;
- char *arg1;
- char c;
-
- arg = arg1 = *argv;
- if ((c = *arg | 0x20) >= 'a' && c <= 'z' && arg[1] == ':') {
- setclust(c - ('a' - 1));
- arg1 += 2;
- }
- else setclust(0);
- if (*arg1 == '\0' || (*arg1 == '.' && arg1[1] == '\0')) {
- static char dotname[] = "x:.";
-
- *dotname = *arg;
- if (findfirst(dotname + (arg + 2 - arg1), &ff, FA_DIREC) == 0) {
- addfile(arg, &dlist, 0, True);
- continue;
- }
- }
- else if ((*arg1 != '/' && *arg1 != '\\') || arg1[1] != '\0') {
- if ((p = strrchr(arg1, '/')) != Null) arg1 = p + 1;
- if ((p = strrchr(arg1, '\\')) != Null) arg1 = p + 1;
- if (!processopt(arg, arg1 - arg, arg1, &dlist, True)) {
- fputs(arg, stderr);
- fputs(": no match.\n", stderr);
- }
- continue;
- }
- /* otherwise, do the root directory */
- {
- /*
- * Get date of disk volume, if possible.
- * No I can't use findfirst: there's a bug in DOS 2.1.
- */
- static struct {
- char xfcb[7];
- char drive;
- char name[11];
- }
- fcb1 = {{-1,0,0,0,0,0,8}, 0, "???????????"};
- struct {
- char xfcb[7];
- char drive;
- char fill[22];
- int time, date;
- char fill2[6];
- } fcb2;
- Boolean dtflag;
-
- fcb1.drive = arg1 > arg ? *arg - ('a' - 1) : 0;
- setdta((char far *) &fcb2);
- _AH = 0x11;
- _DX = (int) &fcb1;
- geninterrupt(0x21);
- dtflag = !_AL;
- ff.ff_fdate = fcb2.date;
- ff.ff_ftime = fcb2.time;
- ff.ff_attrib = FA_DIREC;
- addfile(arg, &dlist, 0, dtflag);
- }
- }
- /*
- * Do the printing.
- */
- if (!opt_R) dir_R = 0;
- dir_d = 0;
- dot_R = '.';
- if (flist == Null && dlist != Null && dlist->next == Null) {
- int len = strlen(dlist->name);
- memcpy(currdir, dlist->name, len);
- showdir(len);
- }
- else showfiles(0, dlist);
- }
-