Category : Miscellaneous Language Source Code
Archive   : MTD.ZIP
Filename : LS.C

 
Output of file : LS.C contained in archive : MTD.ZIP
/*
** Purpose: List files (WITH BUGS!)
** Author: (c) 1990 by Tom Swan.
*/

/* ---- Include header files */
#include
#include
#include
#include

/* ---- Define constants */
#define NUM_COLUMNS 5
#define COLUMN_WIDTH 15
#define FNAMESTR_LEN 12

/* ---- File date bit fields */
typedef struct DATEFIELD {
unsigned day : 5;
unsigned month : 4;
unsigned year : 7;
} dateField;

/* ---- File time bit fields */

typedef struct TIMEFIELD {
unsigned int hour : 5;
unsigned int minute : 6;
unsigned int second : 5;
} timeField;

/* ---- Linked list entries */
typedef struct ITEM *itemPtr;
typedef struct ITEM {
itemPtr next;
char attr;
timeField time;
dateField date;
long size;
char name[13];
} item;

/* ---- Function prototypes */
void getOptions(int argc, char *argv[]);
void instruct(void);
int isFile(char *path);
void fixPath(char *path);
itemPtr newItem();
void readDirectory(void);
int itemCmp(const void*, const void*);
void sortDirectory(void);
void writeBlanks(int numBlanks);
void writeDate(dateField date);
void writeTime(timeField time);
void writeAttributes(char attr);
void writeItem(itemPtr p);
void displayByRows(void);
void displayByCols(void);

/* ---- Options and their default values */
enum boolean { FALSE, TRUE };
enum boolean OPT_ALLFILES = FALSE;
enum boolean OPT_HELP = FALSE;
enum boolean OPT_LONG = TRUE;
enum boolean OPT_ROWORDER = FALSE;
enum boolean OPT_SORT = FALSE;
enum boolean OPT_UPPERCASE = FALSE;

/* ---- Global variables */
itemPtr *indexArray; /* Pointer array for sorting */
char path[79] = "*.*"; /* Path name and default value */
itemPtr root; /* Directory list pointer */
int dirCount; /* Number of list entries */

/* ---- The main program function */
main(int argc, char *argv[])
{
getOptions(argc, argv);
if (OPT_HELP)
instruct();
readDirectory();
if (dirCount == 0)
printf("\n%s\n", "No files");
else {
sortDirectory();
if (OPT_ROWORDER || OPT_LONG)
displayByRows();
else
displayByCols();
}
return 0;
}

/* ---- Interpret command-line options */
void getOptions(int argc, char *argv[])
{
unsigned char ch;
char *p;

while (--argc > 0) {
p = *++argv;
if (*p != '-' && *p != '/')
strcpy(path, p); /* Set path or wild card */
else {
if (strlen(p) == 1)
ch = '?'; /* If no option letter */
else
ch = *(p + 1); /* else ch == option letter */
switch (toupper(ch)) {
case 'A' :
OPT_ALLFILES = TRUE;
break;
case 'H' :
OPT_HELP = TRUE;
break;
case 'N' :
OPT_SORT = FALSE;
break;
case 'R' :
OPT_ROWORDER = TRUE;
break;
case 'W' :
OPT_LONG = FALSE;
break;
case 'U' :
OPT_UPPERCASE = TRUE;
break;
default:
OPT_HELP = TRUE;
break;
}
}
}
}

/* ---- Display instructions and halt */
void instruct(void)
{
printf("\nUseage: LS [option...] [argument] [option...]\n");
printf("\nLS displays a list of files in the current\n");
printf("directory, or in the directory specified by\n");
printf("an optional path and wild-card argument.\n");
printf("Options are:\n\n");
printf("-a All files\n");
printf("-h Display this help message\n");
printf("-n Do not sort file names\n");
printf("-r Row order (implies -w)\n");
printf("-u Uppercase display\n");
printf("-w Wide listing\n");
printf("-? Same as -h\n\n");
printf("Example: ls -a -w \\mywork\\*.c\n");
exit(0);
}

/* Return TRUE if path is a file or contains wild cards */
int isFile(char *path)
{
FILE *f;

if (strchr(path, '*') != NULL || strchr(path, '?') != NULL)
return(TRUE);
else {
if ((f = fopen(path, "r")) == NULL)
return(FALSE);
else {
fclose(f);
return(TRUE);
}
}
}

/* ---- Prepare path for directory search */
void fixPath(char *path)
{
unsigned char lastch; /* Last char in path */

if (!isFile(path)) {
lastch = path[strlen(path)-1];
if (lastch != ':') /* e.g. "a:" */
if (lastch != '\\') /* e.g. "\path\" */
strcat(path, "\\"); /* Append '\' */
strcat(path, "*.*"); /* Append wild card */
}
}

/* ---- Return pointer to new list item */
itemPtr newItem()
{
return ((itemPtr) malloc(sizeof(item)));
}

/* ---- Read directory into linked list */
void readDirectory(void)
{
struct ffblk fb; /* File search block */
int searchAttr; /* Search attribute */
int done; /* True when search is done */
itemPtr p; /* Pointer to list items */

root = NULL; /* Start new list */
if (OPT_ALLFILES) /* Determine search attribute */
searchAttr = 0x3F; /* All files and directories */
else
searchAttr = 0x10; /* Normal files and directories */
fixPath(path);
done = findfirst(path, &fb, searchAttr);
while (!done) {
if (root == NULL) {
root = newItem(); /* Insert first list item */
p = root; /* Address item with p */
} else {
p->next = newItem(); /* Insert other list items */
p = p->next; /* Move p to new item */
}
p->next = NULL; /* Mark end of list */
memcpy(&p->attr, &fb,
sizeof(item) - sizeof(itemPtr)); /* Copy item to list */
if (!OPT_UPPERCASE)
strlwr(p->name); /* Convert name to lowercase */
dirCount++; /* Count entries in list */
done = findnext(&fb);
}
}

/* ---- Compare two directory names for qsort() */
int itemCmp(const void *item1, const void *item2)
{
return(strcmp(
(*(itemPtr *)item1)->name,
(*(itemPtr *)item2)->name ));
}

/* ---- Prepare directory index and sort entries */
void sortDirectory(void)
{
itemPtr p; /* Pointer to list items */
unsigned int i; /* Array index */

/* Prepare array of pointers to listed items */
if (dirCount > 0) {
indexArray =
(itemPtr *) malloc(dirCount * sizeof(itemPtr));
p = root;
i = 0;
while (p != NULL) {
indexArray[i++] = p; /* Add pointer to index */
p = p->next; /* Move p to next item */
}

/* Sort the pointers array by file name */
if (OPT_SORT && dirCount > 1)
qsort(&indexArray, dirCount, sizeof(itemPtr), itemCmp);
}
}

/* ---- Send numBlanks blanks to std out */
void writeBlanks(int numBlanks)
{
while (--numBlanks >= 0)
putchar(' ');
}

/* ---- Write a file's date */
void writeDate(dateField date)
{
printf("%4d-%02d-%02d",
date.month, date.day, date.year + 80);
}

/* ---- Write a file's time */
void writeTime(timeField time)
{
unsigned hour;
char *ampm;

hour = time.hour;
if (hour >= 12) {
if (hour != 12)
hour = hour - 12;
ampm = " pm";
} else
ampm = " am";
printf("%4d:%02d%s", hour, time.minute, ampm);
}

/* ---- Write a file's attributes */
void writeAttributes(char attr)
{
char *s = " ------";

if (attr & FA_RDONLY) s[2] = 'r';
if (attr & FA_HIDDEN) s[3] = 'h';
if (attr & FA_SYSTEM) s[4] = 's';
if (attr & FA_LABEL) s[5] = 'v';
if (attr & FA_DIREC) s[6] = 'd';
if (attr & FA_ARCH) s[7] = 'a';
printf("%s", s);
}

/* ---- Write one directory item */
void writeItem(itemPtr p)
{
unsigned int width;

if (!OPT_LONG)
width = COLUMN_WIDTH;
else
width = FNAMESTR_LEN + 1;
printf("%s", p->name);
writeBlanks(width - strlen(p->name));
if (OPT_LONG) {
if (p->attr & FA_DIREC)
printf(" "); /* + 3 blanks */
else
printf("%8ld", p->size);
writeDate(p->date);
writeTime(p->time);
writeAttributes(p->attr);
}
}

/* ---- Display directory in row order */
void displayByRows(void)
{
unsigned int i;

if (dirCount > 0) {
printf("\n");
for (i = 1; i <= dirCount; i++) {
writeItem(indexArray[i - 1]);
if (i % NUM_COLUMNS == 0 || OPT_LONG)
printf("\n");
}
if (!OPT_LONG && dirCount % NUM_COLUMNS != 0)
printf("\n");
}
}

/* ---- Display directory in column order */
void displayByCols(void)
{
unsigned int rows, i, j;

if (dirCount > 0) {
printf("\n");
rows = (dirCount / NUM_COLUMNS);
if (dirCount % NUM_COLUMNS != 0)
rows++;
for (i = 1; i <= rows; i++) {
j = i;
while (j <= dirCount) {
writeItem(indexArray[j - 1]);
j += rows;
}
if (j > dirCount)
printf("\n");
}
}
}


  3 Responses to “Category : Miscellaneous Language Source Code
Archive   : MTD.ZIP
Filename : LS.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/