home *** CD-ROM | disk | FTP | other *** search
- /*
- * Attribute bits:
- * d - directory
- * r - read only file
- * h - hidden file
- * s - system file
- * a - archive bit
- *
- * Files within each directory are sorted alphabetically.
- * Directories are listed separate from other files.
- */
-
- #include <stdio.h> /* Standard I/O definitions */
- #include <ctype.h> /* Character type macros */
- #include <dos.h> /* Msdos definitions */
- #include <errno.h> /* error codes */
- #include <string.h>
-
- #define SIZE(x) (sizeof(x)/sizeof(x[0]))
- #define A_RONLY 0x01 /* Read only file */
- #define A_HIDDEN 0x02 /* Hidden file */
- #define A_SYSTEM 0x04 /* System file */
- #define A_DIRECTORY 0x10 /* Directory file */
- #define A_ARCHIVE 0x20 /* Archive bit */
- #define FNLEN 80 /* Maximum filename length */
- #define MAXFILES 512 /* Max number of files/directory */
-
- static char ID[]="## ls.c 2.0 K.van Houten 230987 ##";
- struct date {
- unsigned d_sec: 5; /* Time, 2 second intervals */
- unsigned d_min: 6; /* Time, minutes */
- unsigned d_hour: 5; /* Time, hours */
- unsigned d_day: 5; /* Date, day of month */
- unsigned d_month: 4; /* Date, month of year */
- unsigned d_year: 7; /* Date, year since 1980 */
- };
- struct find {
- char fnd_dosinfo[21]; /* Reserved for dos */
- char fnd_attr; /* File attribute */
- struct date fnd_date; /* Date structure */
- long fnd_size; /* File size */
- char fnd_name[13]; /* File name less path */
- };
- char *nameptr ();
- char *date ();
- char *malloc ();
- char *strrchr ();
- int qscmp ();
- extern int clsize(); /* get cluster size */
- long clust();
- short tmp;
- struct find f; /* Used to return data from msdos */
- union REGS r, o; /* Contains register values for intcall() */
- int count; /* Number of files/directory */
- char *p; /* Pointer to filename */
- int i;
- int j;
- int lflg = 0; /* long */
- int tflg = 0; /* time sort */
- int sflg = 0; /* size in bloks */
- int rflg = 0; /* reverse sort */
- int fflg = 0; /* identify executables and subdirs */
- long dirlen; /* Total length of one dir */
- char line[FNLEN]; /* Filename buffer */
- char dirs[20][50]; /* Subdir buffer */
- int dirc; /* Subdir count */
- int drive; /* drive nr */
- char *file; /* Command line argument */
- struct find *fnd[MAXFILES]; /* Pointers to file structures */
- int bsize; /* size of clusters */
- int spc; /* number of K's per cluster */
-
- static struct atr { /* Attribute structure */
- int a_mask;
- int a_name;
- } atr[] = {
- A_DIRECTORY, 'd',
- A_RONLY, 'r',
- A_HIDDEN, 'h',
- A_SYSTEM, 's',
- A_ARCHIVE, 'a'
- };
-
- main (argc, argv)
- int argc; /* Number of command line arguments */
- char *argv[]; /* Array of pointers to arguments */
- {
- char buf[70];
-
- drive = defdrv();
- bsize=clsize(drive);
- spc=bsize/1024;
- for (argc--,argv++; argc>0; argc--,argv++) {
- if (**argv == '-') {
- while (*++(*argv)) {
- switch (**argv) {
- case 'l':
- lflg++;
- break;
- case 't':
- tflg++;
- break;
- case 's':
- sflg++;
- break;
- case 'r':
- rflg++;
- break;
- case 'F':
- fflg++;
- break;
- default:
- printf("Usage: ls [-Flrst] [file [file ...]]\n");
- exit(1);
- }
- }
- }
- else
- break;
- }
-
- r.h.ah = 0x1a; /* SET DISK TRANSFER ADDRESS FUNCTION */
- r.x.dx = (int) & f;
- tmp = intdos (&r, &o);
- /* Produces error 0 ???
- if (o.x.cflag) {
- perror ("SETTING DTA ");
- exit (1);
- }
- */
- dirc = 0;
- count = 0;
-
- if (argc == 0) {
- strcpy(dirs[dirc++],".");
- }
- else {
- while (file = *argv++, argc--) {
- /* handle relative directorys */
- if (strcmp(file,"..") == 0) {
- strcpy(dirs[dirc++],"..\\.");
- continue;
- }
- if (file[strlen(file)-1] == '.') {
- strcpy(dirs[dirc++],file);
- continue;
- }
- /* handle drive letters */
- if (strlen(file) == 2 && file[1] == ':') {
- strcpy(dirs[dirc],file);
- strcat(dirs[dirc++],".");
- continue;
- }
- /* handle abs. dirs */
- if (file[strlen(file)-1] == '\\') {
- strcpy(dirs[dirc], file);
- strcat(dirs[dirc++],".");
- continue;
- }
- findf ();
- if (o.x.cflag) {
- continue;
- }
- for (;;) {
- if (o.x.cflag) {
- break;
- }
- if (f.fnd_attr & A_DIRECTORY) {
- if (f.fnd_name[0] == '.')
- goto next;
- *dirs[dirc]='\0';
- if (strrchr(file,'\\')!=NULL) {
- strncpy(dirs[dirc],file,((strrchr(file,'\\')-file)+1));
- }
- strcat (dirs[dirc++], f.fnd_name);/* save subdir name */
- }
- else {
- if ((fnd[count] =
- (struct find *)malloc(sizeof(struct find))) == NULL)
- fatal ("out of memory");
- *fnd[count] = f;
- /* Increment total size */
- dirlen += clust(fnd[count]->fnd_size);
- count++;
- }
- next: findn ();
- }
- }
- if (count == 0 && dirc == 0) {
- printf("File not found\n");
- exit(1);
- }
- }
- /* All arguments done, now print simple files */
- qsort (fnd, count, sizeof (struct find *), qscmp);
-
- for (i = 0; i < count; i++) {
- printentry(i);
- if ((lflg==0) && (((i+1) % (sflg?4:5)) == 0) && (i > 1))
- printf("\n");
- }
- for (i = 0; i < dirc; i++)
- printdir(i);
- return (1);
- }
-
- /*
- * Print one entry, format depends on options selected.
- */
- printentry(x)
- int x;
- {
- long sz;
- char pbuf[50]; /* print buffer */
-
- sz = fnd[x] -> fnd_size;
-
- /* block size */
- if (sflg)
- {
- if ((fnd[x] -> fnd_attr & A_DIRECTORY) == 0)
- {
- printf("%3d ",clust(sz));
- }
- else
- printf(" 0 ");
- }
- if (lflg) {
- /* mode bits */
- for (j = 0; j < SIZE (atr); j++)
- if (atr[j].a_mask & fnd[x] -> fnd_attr)
- putchar (atr[j].a_name);
- else
- putchar ('-');
-
- /* file size */
- printf (" %10ld ", sz);
-
- /* file date */
- printf ("%s ", date (&fnd[x] -> fnd_date));
- }
-
- /* file name */
- if (fflg == 0)
- printf ("%-12s " , strlwr (fnd[x] -> fnd_name));
-
- /* executable / subdir info */
- if (fflg)
- {
- if (fnd[x] -> fnd_attr & A_DIRECTORY)
- sprintf (pbuf,"%s/" , strlwr (fnd[x] -> fnd_name));
- else
- {
- if (isexe(fnd[x]->fnd_name))
- sprintf (pbuf,"%s*" , strlwr (fnd[x] -> fnd_name));
- else
- sprintf (pbuf,"%s " , strlwr (fnd[x] -> fnd_name));
- }
- printf ("%-12s " , pbuf);
- }
-
- if (lflg)
- printf("\n");
-
- free (fnd[x]); /* Free find structure */
- }
-
-
- printdir (x)
- int x;
- {
- int i;
- char fbuf[80]; /* to assemble filename */
-
- /* Complex, but needed for DOS 2.11 compatibility */
- if (dirs[x][strlen(dirs[x])-1] == '.') {
- dirs[x][strlen(dirs[x])-1] = '\0';
- strcpy(fbuf,dirs[x]);
- strcat(fbuf,"*.*");
- }
- else {
- strcpy(fbuf,dirs[x]);
- strcat(fbuf,"\\*.*");
- }
- if (dirs[x][1] == ':') { /* other drive */
- drive=tolower(*dirs[x])-'a';
- }
- else {
- drive=defdrv();
- }
- bsize=clsize(drive);
- spc=bsize/1024;
- file = fbuf;
- p = nameptr (file);
- count = p - file;
- if (count + sizeof (f.fnd_name) > FNLEN)
- fatal ("filename too long: %s", file);
- strncpy (line, file, count);
- p = line + count;
- count = 0; /* Init file count */
- dirlen = 0;
-
- findf ();
- for (;;) {
- if (o.x.cflag)
- break;
- if (count >= MAXFILES)
- fatal ("Too many files in one directory");
- if ((fnd[count] =
- (struct find *) malloc (sizeof (struct find))) == NULL)
- fatal ("out of memory");
- if (!((f.fnd_attr & A_DIRECTORY) &&
- ((strcmp (f.fnd_name, ".") == 0) ||
- (strcmp (f.fnd_name, "..") == 0)))) {
- memcpy (fnd[count], &f, sizeof f);
- /* Increment total size */
- dirlen += clust(fnd[count] -> fnd_size);
- count++;
- }
- findn ();
- }
- if (count)
- qsort (fnd, count, sizeof (struct find *), qscmp);
-
- if (*dirs[x] != '\0')
- printf("\n%s:\n", strlwr(dirs[x]));
- if (lflg) {
- printf ("Total %d\n",dirlen);
- }
- for (i = 0; i < count; i++) {
- printentry(i);
- if ((lflg==0) && (((i+1) % (sflg?4:5)) == 0) && (i > 1))
- printf("\n");
- }
- }
-
- /*
- * Find first entry, return info in find structure.
- */
- findf ()
- {
- r.h.ah = 0x4e; /* FINDFIRST function */
- r.x.cx = A_HIDDEN | A_SYSTEM | A_DIRECTORY |
- A_RONLY | A_ARCHIVE;
- r.x.dx = (int) file;
- tmp = intdos (&r, &o); /* Find first */
- }
-
- /*
- * Find next entry
- */
- findn ()
- {
- r.h.ah = 0x4f; /* Now use FINDNEXT function */
- tmp = intdos (&r, &o); /* Find next */
- }
-
- /*
- * Return a pointer to an ascii date, given a pointer
- * to a date structure
- */
- char ad[40];
-
- char *
- date (dp)
- register struct date *dp;
- {
- static char *month[] = {
- "Jan",
- "Feb",
- "Mar",
- "Apr",
- "May",
- "Jun",
- "Jul",
- "Aug",
- "Sep",
- "Oct",
- "Nov",
- "Dec"
- };
-
- sprintf (ad, "%2d %s %4d %02d:%02d:%02d",
- dp -> d_day,
- month[dp -> d_month - 1],
- dp -> d_year + 1980,
- dp -> d_hour,
- dp -> d_min,
- dp -> d_sec * 2);
- return (ad);
- }
-
- /*
- * Qsort compare routine
- * Directories first, other files second, sort alphabetically.
- * This routine is called by qsort and passed two pointers to
- * find structure pointers.
- */
- qscmp (p1, p2)
- struct find **p1;
- struct find **p2;
- {
- register struct find *f1 = *p1;
- register struct find *f2 = *p2;
- register int cmp;
- int inv = 1;
-
- if (rflg)
- inv=-1;
- /*
- if (cmp = (f2 -> fnd_attr & A_DIRECTORY) - (f1 -> fnd_attr & A_DIRECTORY))
- return (cmp);
- */
- if (tflg) {
- if (cmp = (f2->fnd_date.d_year - f1->fnd_date.d_year))
- return(inv * cmp);
- if (cmp = (f2->fnd_date.d_month - f1->fnd_date.d_month))
- return(inv * cmp);
- if (cmp = (f2->fnd_date.d_day - f1->fnd_date.d_day))
- return(inv * cmp);
- if (cmp = (f2->fnd_date.d_hour - f1->fnd_date.d_hour))
- return(inv * cmp);
- if (cmp = (f2->fnd_date.d_min - f1->fnd_date.d_min))
- return(inv * cmp);
- if (cmp = (f2->fnd_date.d_sec - f1->fnd_date.d_sec))
- return(inv * cmp);
- }
- return (inv * strcmp (f1 -> fnd_name, f2 -> fnd_name));
- }
-
- /*
- * Return a pointer to the beginning of the filename (past pathname if any)
- */
- char *
- nameptr (name)
- char *name;
- {
- register char *p1;
-
- if ((p1 = strrchr (name, '\\')) != NULL)
- return (++p1);
- else
- if ((p1 = strrchr (name, ':')) != NULL)
- return (++p1);
- return (name);
- }
-
- /*
- * Fatal error
- * The %r (recursive) printf format specifier is non-portable.
- */
- fatal (p)
- char *p;
- {
- printf ("ls fatal error\n");
- exit (0);
- }
-
- long
- clust(sz)
- long sz;
- {
- return(spc*((sz % bsize) ? (sz / bsize + 1) : (sz / bsize)));
- }
-
- int
- defdrv()
- {
- int tmp;
- union REGS r;
-
- r.h.ah = 0x19; /* get default drive */
- tmp = intdos(&r,&r);
- if (r.x.cflag != 0) {
- printf("Error reading def. drive: %d\n",tmp);
- exit(1);
- }
- return(r.h.al);
- }
-
- int
- isexe(n)
- char *n;
- {
- char *p,*t;
-
- if ((p=strchr(n,'.')) == NULL)
- return(0);
- p++;
- if (strncmp(p,"EXE",3) == 0)
- return(1);
- if (strncmp(p,"COM",3) == 0)
- return(1);
- if (strncmp(p,"BAT",3) == 0)
- return(1);
- return(0);
- }