home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
S12442.ZIP
/
LS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-07-31
|
17KB
|
534 lines
/* ls.c RHS 4/6/85 rev. 10/10/85, rev. again 7/10/88, rev. again 7/89
* this module contains ls(), like the UNIX ls
*
* modified for OS/2 7/10/88
* modified for OS/2 directory server 7/15/89
*
*
LS is a directory utility patterned after the UNIX counterpart by the
same name. Run it with:
LS [-flscpternda<rhsad>?] [<list of files>]
The options are explained by running:
LS -?
The list of files are any filespecs (with paths if not in default dir).
*/
#define INCL_SUB
#define INCL_DOS
#include<os2.h>
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
#include<stddef.h>
#include<malloc.h>
#include<conio.h>
#include"di.h"
#define A_NORMAL 0x0000
#define A_READONLY 0x0001
#define A_HIDDEN 0x0002
#define A_SYSTEM 0x0004
#define A_VOLLABEL 0x0008
#define A_DIRECTORY 0x0010
#define A_ARCHIVE 0x0020
#define A_UNUSED0 0x0040
#define A_UNUSED1 0x0080
#define A_UNUSED2 0x0100
#define A_UNUSED3 0x0200
#define A_UNUSED4 0x0400
#define A_UNUSED5 0x0800
#define A_UNUSED6 0x1000
#define A_UNUSED7 0x2000
#define A_UNUSED8 0x4000
#define A_UNUSED9 0x8000
#define MAXENTRIES 2000
#define MAXPATH 66
#define MAXDIRS 60
#define PAGELEN 23
#define NUMCOLS 5
#define EXTSIZE 4
#define ERROR -1
#define newline() printf("\n")
#define opposite(val) (Options.reverse_order ? -val : val)
unsigned Pagelen;
unsigned entries = 0; /* offset into entryptrs */
PFILEFINDBUF entryptrs[MAXENTRIES]; /* ptrs to entries */
unsigned dirdrive = 0;
char *wild_arg = "*.*";
char *blanks = " ";
struct _options
{
USHORT ext_sort;
USHORT long_format;
USHORT time_sort;
USHORT reverse_order;
USHORT dir_format;
USHORT column_format;
USHORT file_format;
USHORT paging;
USHORT single_column;
USHORT no_sort;
USHORT attrval;
} Options;
long totalspace = 0L;
long availspace = 0L;
void main(int argc,char **argv);
void ls(int argc, char **argv);
void get_freespace(unsigned drive, long *totalspace, long *availspace);
void print_entries(void);
int qscmp(PFILEFINDBUF *p1, PFILEFINDBUF *p2);
int set_options(char *opt);
void dopage(USHORT c);
void usage(void);
int haswild(char *str);
void makedirname(char *to,char *from);
void set_attribute_values(char *str, unsigned attribute);
unsigned get_attrval(char *c);
int column_lines(int num);
BOOL read_options(int *argc, char ***argv);
void main(int argc,char **argv)
{
ls(argc,argv);
}
void ls(int argc, char **argv)
{
VIOMODEINFO v;
PVOID header = NULL, resulthdl;
USHORT i, j, numresults, numrequests;
PCH curdir;
if(!read_options(&argc, &argv)) /* read/set the options */
return;
for( i = 1; i < argc; i++) /* get each filespec */
DiMakeRequest(&header, argv[i], Options.attrval);
DiSendRequest(header); /* send the request */
DiGetNumResults(header, &numresults, &numrequests);
for( i = 0; i < numrequests; i++) /* for each request */
{
DiGetResultHdl(header, i, &numresults, &resulthdl);
if(!i)
{
curdir = DiGetResultDir(resulthdl);
get_freespace((*curdir-'A'+1), &totalspace, &availspace);
}
for( j = 0; j < numresults; j++) /* get each filename in req.*/
if(!j)
DiGetFirstResultPtr(resulthdl,&entryptrs[entries++]);
else
DiGetNextResultPtr(resulthdl,&entryptrs[entries++]);
}
if(!Options.no_sort) /* if sort required, do it */
qsort(entryptrs, entries, sizeof(PFILEFINDBUF), qscmp);
if(!Options.column_format && !Options.single_column)
Options.long_format = TRUE;
if(Options.paging) /* if paging required */
{
v.cb = sizeof(v);
VioGetMode(&v,0);
Pagelen = v.row-2; /* set page length */
}
print_entries(); /* print the results */
DiDestroyRequest(&header); /* throw out results */
DosExit(EXIT_PROCESS,0); /* I'm outta here */
}
BOOL read_options(int *argc, char ***argv)
{
int nargc;
char **nargv;
static char *wargv[3];
memset(&Options,FALSE,sizeof(Options)); /* init options to FALSE */
nargv = *argv;
nargc = *argc;
if(nargc > 1 && *nargv[1] == '-') /* if options present */
{
if(!set_options(nargv[1])) /* if only usage message */
return FALSE;
/* shift pointers down one */
memmove(&nargv[1],&nargv[2],(nargc-2)*sizeof(char *));
nargc--; /* adjust nargc */
nargv[nargc] = NULL;
}
if(nargc == 1) /* if only the programname */
{
wargv[0] = *argv[0]; /* set up new argv array */
wargv[1] = wild_arg;
wargv[2] = NULL;
nargv = wargv; /* set nargv and narc */
nargc = 2;
}
*argc = nargc; /* now set the originals */
*argv = nargv;
}
int set_options(char *opt)
{
for( ; *opt ; opt++)
switch(tolower(*opt))
{
case 'f':
Options.file_format = TRUE;
break;
case 'l':
Options.long_format = TRUE;
break;
case 't':
Options.time_sort = TRUE;
break;
case 'r':
Options.reverse_order = TRUE;
break;
case 's':
Options.long_format = FALSE;
Options.single_column = TRUE;
break;
case 'c':
Options.column_format = TRUE;
break;
case 'd':
Options.dir_format = TRUE;
break;
case 'p':
Options.paging = TRUE;
break;
case 'e':
Options.ext_sort = TRUE;
break;
case 'n':
Options.no_sort = TRUE;
break;
case 'a':
Options.attrval = get_attrval(++opt);
Options.dir_format = Options.file_format = FALSE;
return TRUE;
break;
case '?':
usage();
return FALSE;
break;
}
return TRUE;
}
void usage(void)
{
printf("Usage: ls [-flscpternda<rhsad>?] [<list of files>]\n");
printf("<list of files> := <file> | <file> <list of files>\n");
printf(" -f: files (non-directories) only\n");
printf(" -l: long listing (default)\n");
printf(" -s: single column listing\n");
printf(" -c: columnar format\n");
printf(" -p: pause at the end of every screen page\n");
printf(" -t: time sort\n");
printf(" -e: extension sort\n");
printf(" -r: reverse sort order\n");
printf(" -n: no sort listing\n");
printf(" -d: directory entries only\n");
printf(" -a: attributes: only files with <attr>\n");
printf(" -?: this message\n");
printf(" [by R.H.Shaw 07/29/89]\n");
}
void get_freespace(unsigned drive, long *totalspace, long *availspace)
{
int flag = FALSE;
FSALLOCATE fs;
DosQFSInfo(drive, 1, (PBYTE)&fs, sizeof(fs));
*totalspace = (fs.cSectorUnit * fs.cUnit * fs.cbSector);
*availspace = (fs.cSectorUnit * fs.cUnitAvail * fs.cbSector);
}
int qscmp(PFILEFINDBUF *p1, PFILEFINDBUF *p2)
{
PFILEFINDBUF f1 = *p1;
PFILEFINDBUF f2 = *p2;
int cmp,val = 0,c2,c1,len,len1,len2;
char *ext1, *ext2, *name1, *name2;
register USHORT d, t;
if(Options.time_sort) /* if time sort */
{
d = MAKETYPE(f1->fdateLastWrite,USHORT);/* get date1 */
t = MAKETYPE(f2->fdateLastWrite,USHORT);/* get date2 */
if(d > t) /* compare */
val = -1;
else if(d < t)
val = 1;
else /* dates equal, check time */
{
d = MAKETYPE(f1->ftimeLastWrite,USHORT);
t = MAKETYPE(f2->ftimeLastWrite,USHORT);
if(d > t)
val = -1;
else if(d < t)
val = 1;
else
val = 0;
}
return opposite(val);
}
else /* name or extension sort */
{
c2 = f2->attrFile & A_DIRECTORY; /* see either is a directory*/
c1 = f1->attrFile & A_DIRECTORY;
if(cmp = (c2-c1)) /* one is, but not the other*/
return opposite(cmp); /* directories are lesser */
name1 = f1->achName;
name2 = f2->achName;
/* either both are directories or both are files to get here */
if(Options.ext_sort) /* if extension sort */
{
ext1 = strchr(name1,'.'); /* get the extension */
ext2 = strchr(name2,'.');
if(ext1 && ext2) /* if both have extensions */
{
/* get length of both: lesser length used in strncmp() */
len = ( ((len1 = strlen(ext1)) > (len2 = strlen(ext2))) ? len2 : len1);
return opposite(strncmp(ext1, ext2, len));
}
else /* at least one doesn't have extension */
return (opposite((ext1 != NULL) ? -1 : 1));
}
else /* boring old name sort */
{
/* get length of both: lesser length used */
len = ( ((len1 = strlen(name1)) > (len2 = strlen(name2))) ? len2 : len1);
return opposite(strncmp(name1, name2, len));
}
}
}
void print_entries(void)
{
int reps, lines, max_lines, col_line, col, item, bal, pagelines;
char e_buf[100],short_format = FALSE;
long total_used = 0L, total_alloced = 0L;
char attrstr[9], ap;
FILEFINDBUF *p;
unsigned writehours, i;
pagelines = max_lines = col_line = lines = reps = col = 0;
if(Options.column_format) /* for column formatting */
{
/* if Options.paging and more than a pageful set for a pageful */
if(Options.paging && (entries>(Pagelen*NUMCOLS)) )
max_lines = Pagelen;
else /* if not Options.paging, or if Options.paging and less than a pageful */
max_lines = column_lines(entries);
}
/* printf("\nmax_lines=%d,entries/NUMCOLS=%d,entries%NUMCOLS=%d",max_lines,entries/NUMCOLS,entries%NUMCOLS); */
/* main loop to print file info */
for(i = 0; i < entries; i++)
{
p = entryptrs[i];
/* if directory, put name in [] */
if(p->attrFile & A_DIRECTORY)
makedirname(e_buf,p->achName);
else
strcpy(e_buf,p->achName);
if(Options.long_format) /* vertical column, with full information */
{
/* set attribute chars */
set_attribute_values(attrstr,p->attrFile);
writehours = (p->ftimeLastWrite.hours > 12 ? p->ftimeLastWrite.hours - 12 : p->ftimeLastWrite.hours);
ap = (char)(p->ftimeLastWrite.hours > 12 ? 'p' : 'a');
printf("\n"
"%8s "
"%12ld "
/* Create Last Access */
/* "%02d-%02d-%02d %02d:%02d %02d-%02d-%02d %02d:%02d " */
/* Last Update */
"%2d-%02d-%02d %2d:%02d%c "
/* size name */
"%s",
attrstr,
p->cbFile,
/*
p->fdateCreation.month,p->fdateCreation.day,p->fdateCreation.year+80,
p->ftimeCreation.hours,p->ftimeCreation.minutes,
p->fdateLastAccess.month,p->fdateLastAccess.day,p->fdateLastAccess.year+80,
p->ftimeLastAccess.hours,p->ftimeLastAccess.minutes,
*/
p->fdateLastWrite.month,p->fdateLastWrite.day,p->fdateLastWrite.year+80,
writehours,p->ftimeLastWrite.minutes,ap,
strlwr(e_buf));
}
else
{ /* if !Options.long_format */
if(!Options.column_format)
{ /* vertical format, filenames only */
newline();
printf("%-30.30s", strlwr(e_buf));
}
else
{ /* column format */
if(!i) /* initial newline */
newline();
/* item is offset into array, col_line is actual line down screen in cols */
/* col is current screen column, max_lines is number of column lines to do */
item = col_line + (max_lines * col); /* item is offset */
/* printf("\nitem=%d,col_line=%d,col=%d ",item,col_line,col); */
if(item < entries)
{
/* printf("%d ",item); */
if(entryptrs[item]->attrFile & A_DIRECTORY)
makedirname(e_buf,entryptrs[item]->achName);
else
strcpy(e_buf,entryptrs[item]->achName);
printf("%-14.14s", strlwr(e_buf));
}
else
i--;
col++;
if(col >= NUMCOLS)
{ /* if we're at last column on this line */
newline(); /* write newline() */
col = 0; /* set for 1st column */
pagelines++;
col_line++; /* go to next column line */
}
}
}
lines++;
if(Options.paging)
if(Options.column_format && pagelines == Pagelen)
{
pagelines = 0;
col_line = item+1;
bal = (entries-i);
max_lines = column_lines( (bal > (Pagelen*NUMCOLS)) ? (Pagelen*NUMCOLS) : bal );
/* printf("bal=%d,i=%d,max_lines=%d",bal,i,max_lines); */
dopage(!Options.column_format);
}
else if(lines == Pagelen && !Options.column_format)
{
dopage(!Options.column_format);
lines = 0;
}
total_alloced += p->cbFileAlloc;
total_used += p->cbFile;
}
if(reps != 0) /* only executed on short format (lc) */
newline();
if(!short_format)
newline();
printf("%u Files occupy %ld bytes(%ld Allocated), ", entries, total_used, total_alloced);
printf("%ld of %ld free on %c:", availspace, totalspace, dirdrive+'A'-1);
newline();
}
void dopage(USHORT c)
{
if(c)
newline();
printf("\nPress any key to continue...");
getch();
newline();
}
/* places from into to with [] if a directory */
void makedirname(char *to,char *from)
{
strcpy(to,"[");
strcat(to,from);
strcat(to, "]");
}
const char *attrs = "--advshr";
unsigned attrvals[8] =
{
A_UNUSED1, A_UNUSED0, A_ARCHIVE, A_DIRECTORY,
A_VOLLABEL, A_SYSTEM, A_HIDDEN, A_READONLY
};
/* sets the string to "-----" or "drhsa", etc. */
void set_attribute_values(char *str, unsigned attribute)
{
unsigned i, attrvals = A_UNUSED1, len = strlen(attrs);
memset(str,'-',len); /* initialize attribute value string */
str[len] = 0;
for( i = 0; i < len; i++, attrvals >>= 1)
if(attrvals & attribute)
str[i] = attrs[i];
}
unsigned get_attrval(char *attrstr)
{
unsigned *i,newattr = 0;
const char *p;
char *q;
for( q = attrstr; *q ; q++)
for( p = attrs, i = attrvals; *p ; p++, i++)
if(*q == *p)
newattr |= *i;
return newattr;
}
int column_lines(int num)
{
int max_lines;
max_lines = num/NUMCOLS; /* set the maximum lines */
if(num%NUMCOLS) /* increment for leftovers */
max_lines++;
return max_lines;
}
/************ end of ls.c *********************/