summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/SNIP/lsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'reference/C/CONTRIB/SNIP/lsd.c')
-rwxr-xr-xreference/C/CONTRIB/SNIP/lsd.c265
1 files changed, 265 insertions, 0 deletions
diff --git a/reference/C/CONTRIB/SNIP/lsd.c b/reference/C/CONTRIB/SNIP/lsd.c
new file mode 100755
index 0000000..b416846
--- /dev/null
+++ b/reference/C/CONTRIB/SNIP/lsd.c
@@ -0,0 +1,265 @@
+/*
+** LSD - A simple directory lister
+** A public domain C demo program by Bob Stout
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <dos.h>
+
+/* For portability, make everything look like MSC 6+ */
+
+#if defined(__TURBOC__)
+ #include <dir.h>
+ #define _dos_findfirst(f,a,b) findfirst(f,b,a)
+ #define _dos_findnext(b) findnext(b)
+ #define find_t ffblk
+ #define _A_SUBDIR FA_DIREC
+ #define attrib ff_attrib
+ #define name ff_name
+ #define size ff_fsize
+ #define wr_time ff_ftime
+ #define wr_date ff_fdate
+ #define _dos_getdiskfree getdfree
+ #define diskfree_t dfree
+ #define avail_clusters df_avail
+ #define sectors_per_cluster df_sclus
+ #define bytes_per_sector df_bsec
+#else /* assume MSC/QC */
+ #include <errno.h>
+#endif
+
+#ifdef TRUE
+ #undef TRUE
+#endif
+#ifdef FALSE
+ #undef FALSE
+#endif
+#ifdef ERROR
+ #undef ERROR
+#endif
+
+enum LOGICAL {ERROR = -1, SUCCESS, FALSE = 0, TRUE};
+
+#ifndef CAST
+ #define CAST(new_type,old_object) (*((new_type *)&(old_object)))
+#endif
+
+#define LAST_CHAR(s) (((char *)s)[strlen(s) - 1])
+
+struct DOS_TIME {
+ unsigned int ss : 5;
+ unsigned int mm : 6;
+ unsigned int hh : 5;
+ } ;
+#define dos_time(t) CAST(struct DOS_TIME, (t))
+
+struct DOS_DATE {
+ unsigned int da : 5;
+ unsigned int mo : 4;
+ unsigned int yr : 7;
+ } ;
+#define dos_date(t) CAST(struct DOS_DATE, (t))
+
+/*
+** DOS DIR improved work-alike w/ improved formatting & attribute display
+**
+** supports /W switch
+*/
+
+main(int argc, char *argv[])
+{
+ int i, files = 0, dirs = 0, argptr = 0, errflag = FALSE, cols, drive;
+ long siz_tot = 0L;
+ char *p, *fname, *ext, name[13], buf[67], numbuf[12];
+ struct find_t ff;
+#ifndef __ZTC__
+ struct diskfree_t df;
+#endif
+ int one_column(), five_column();
+ int (*display)(char *, char *, long, unsigned, unsigned, unsigned)
+ = one_column;
+ char *sprintfc(char *, long);
+ char *capitalize(const char *);
+
+ strcpy(buf, fname = "*.*");
+ if(argc != 1) for (i = 1; i < argc; ++i)
+ {
+ if ('/' == argv[i][0])
+ {
+ if ('W' == toupper(argv[i][1]))
+ display = five_column;
+ else
+ {
+ puts("\aUsage: LSD [/W] [file]");
+ errflag = TRUE;
+ }
+ }
+ else if (!argptr)
+ argptr = i;
+ }
+ if (argptr)
+ {
+ fname = argv[argptr];
+ strcpy(buf, fname);
+ if ('\\' == LAST_CHAR(buf) || ':' == LAST_CHAR(buf))
+ strcat(buf, "*.*");
+ else
+ {
+ if (SUCCESS == _dos_findfirst(buf, _A_SUBDIR, &ff))
+ {
+ if (ff.attrib & _A_SUBDIR && '.' != *ff.name)
+ {
+ if ('\\' != LAST_CHAR(buf))
+ strcat(buf, "\\");
+ strcat(buf, "*.*");
+ }
+ }
+ else errflag = TRUE;
+ }
+ }
+ if (':' == buf[1])
+ drive = toupper(*buf) - '@';
+ else drive = 0;
+ if (!errflag && !(_dos_findfirst(buf, 0xff, &ff))) do
+ {
+ siz_tot += ff.size;
+ if (ff.attrib & _A_SUBDIR)
+ ++dirs;
+ else ++files;
+ strcpy(name, ff.name);
+ if (NULL != (p = strchr(name, '.')) && p != name)
+ {
+ *p = '\0';
+ ext = ++p;
+ }
+ else ext = "";
+ cols = (*display)(name, ext, ff.size,
+ ff.attrib, ff.wr_date, ff.wr_time);
+ } while (SUCCESS == _dos_findnext(&ff));
+ else
+ {
+ fprintf(stderr, "Cannot do directory on '%s'\n", fname);
+ exit(-1);
+ }
+ if (cols)
+ fputc('\n', stdout);
+ sprintfc(numbuf,siz_tot);
+ printf("\n%3d Files totalling %s bytes\n", files, numbuf);
+ printf("%3d Director%s\n", dirs, (1 == dirs) ? "y" : "ies");
+#ifndef __ZTC__
+ _dos_getdiskfree(drive, &df);
+ sprintfc(numbuf, (long)df.avail_clusters * df.sectors_per_cluster *
+ df.bytes_per_sector);
+#else /* if ZTC */
+ sprintfc(numbuf, dos_getdiskfreespace(drive));
+#endif
+ printf("%s bytes free\n", numbuf);
+ return 0;
+}
+
+/*
+** The single column directory entry display function
+*/
+
+int one_column(char *name,
+ char *ext,
+ long size,
+ unsigned attribs,
+ unsigned date,
+ unsigned time)
+{
+ register int i, mask;
+ static char *atr = "RHSVDA", szbuf[12];
+
+ sprintfc(szbuf, size);
+ printf("%-8s %-3s %12s ", capitalize(name), capitalize(ext), szbuf);
+ for (i = 0, mask = 1; i < 6; ++i, mask <<= 1)
+ {
+ if (attribs & mask)
+ fputc(atr[i], stdout);
+ else fputc('.' , stdout);
+ }
+ printf("%4d-%02d-%02d%4d:%02d:%02d\n",
+ dos_date(date).mo,
+ dos_date(date).da,
+ (dos_date(date).yr + 80) % 100,
+ dos_time(time).hh,
+ dos_time(time).mm,
+ dos_time(time).ss);
+ return 0;
+}
+
+/*
+** The five column directory entry display function
+*/
+
+int five_column(char *name,
+ char *ext,
+ long size,
+ unsigned attribs,
+ unsigned date,
+ unsigned time)
+{
+ static int cols = 0;
+
+ printf("%-8s %-3s%s", capitalize(name), capitalize(ext),
+ (5 > ++cols) ? " " : "");
+ if (0 == (cols %= 5))
+ putchar('\n');
+ return (cols);
+}
+
+/*
+** Display a long int using commas as thousands separators
+*/
+
+char *sprintfc(char *string, long num)
+{
+ if (num > 999999L)
+ {
+ sprintf(string, "%d,%03d,%03d",
+ (int)(num / 1000000L),
+ (int)((num % 1000000L) / 1000L),
+ (int)(num % 1000L));
+ }
+ else
+ {
+ if (num > 999L)
+ {
+ sprintf(string, "%d,%03d",
+ (int)(num / 1000L),
+ (int)(num % 1000L));
+ }
+ else sprintf(string, "%d", (int)num);
+ }
+ return string;
+}
+
+/*
+** Capitalize a name or extension in place
+*/
+
+char *capitalize(const char *string)
+{
+ int flag = 0;
+ char *ptr = (char *)string;
+
+ do
+ {
+ if (isalpha(*ptr))
+ {
+ if (flag)
+ *ptr = (char)tolower(*ptr);
+ else
+ {
+ flag = 1;
+ *ptr = (char)toupper(*ptr);
+ }
+ }
+ else flag = 0;
+ } while (*++ptr);
+ return (char *)string;
+}