Files
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

1 line
14 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* -*-c,save,tab:8,indent:4-*- */
/************************************************************************
* XDIR.C - eXtended DIRectory program. Does all kinds of good stuff *
* Robert Heller 16-FEB-1985 - Media Research, Ltd. *
* (c) 1985 Media Research, Ltd. *
* (part of Media Research, Ltd UTILS-68K package) *
************************************************************************
*
* Usage:
* xdir [-r ][-cN ][-s ][-a ][-f ][-to ][-tr+/- ][-h+/- ][fname [fname ...]][>outfile]
* -r - reverse alpha ordered
* -cN - columns (default=5 iff -s,-a and -f NOT specified, else 1. also
* iff -tr- and -h- BOTH specified then columns=1)
* -s - size
* -a - attributes (ie SYS/DIR, RW/RO, ARC/NOARC, etc.)
* -f - fill (same as -s & -a)
* -to - total - lists totals (incl. size if -s or -f)
* -tr+/- - trailer (-tr+ [default]) or notrailer (-tr-)
* -h+/- - header (-h+ [default]) or noheader (-h-)
* fname - file name(s) format dr:name.type[user] - default spec is
* curdrive:*.*[curuser]
* >outfile - output file (CON: by default)
*
************************************************************************
*/
#include <stdio.h> /* standard I/O defs */
#include <ctype.h> /* character types */
#include <osif.h> /* O/S interface defs */
#include <osiferr.h> /* O/S interface error handling */
#include <option.h> /* option defs */
NOWILDCARDS /* let use take care of wild cards ourselves */
/* missing OSIF functions: */
#define GETDRV 25 /* get current drive # */
#define GETLOG 24 /* get login vector */
#define GETDPB 31 /* get disk parameters */
#define SELDRV 14 /* select drive */
/* storage classes */
#define FAST register
#define LOCAL static
#define GLOBAL extern
/* linked list - for file name list */
typedef struct names {
char *name;
struct names *next;
} NAMES,*NAMESP;
/* format for header */
#define HFORMAT "\nDirectory %c:[%d]\n\n"
/* trailer formats */
#define TFORMAT1 (sflag?\
"\nTotal of %d files, %ld KBytes/%ld directory entries.\n":\
"\nTotal of %d files.\n")
#define TFORMAT2 (sflag?\
"\nGrand Total of %d files in %d directories, %ld KBytes/%ld directory entries.\n":\
"\nGrand Total of %d files in %d directories.\n")
/* file name format */
#define FLEN1 15
#define FLEN2 20
/* size format */
#define SFORMAT "%6ld/%-4ld "
/* file search DMA block structure */
typedef struct {
char dr;
char xf[8];
char t[3];
char fill[20];
} SEABLK;
/* DPB structure */
typedef struct {
short int spt; /* sectors per track */
char bsh; /* block shift factor */
char blm; /* block mask */
char exm; /* extent mask */
char z; /* reserved byte */
short int dsm; /* disk storage mask (max block count - 1) */
short int drm; /* directory mask (max directory entry count - 1) */
short int zz; /* reserved word */
short int cks; /* size of the checksum vector */
short int off; /* number of reserved tracks */
} DPB;
/* sign macro */
#define sign(i) (((i)<0)?(-1):(((i)>0)?(1):(0)))
/* isfilech macro */
#define isfilech(c) ((index(" <>=,!|*?&/[]().:;+-\\",c) == NULL) &&\
(isprint(c)))
/* search dir signs */
#define ASSENDING (-1)
#define DESSENDING (1)
#define DEFAULTCOLS 5
/* "global vars" */
int sortflg = ASSENDING; /* sort direction */
NAMESP filelist = NULL; /* file name list */
int columns = DEFAULTCOLS, /* # columns */
sflag = FALSE, /* size flag */
aflag = FALSE, /* attributes flag */
header = TRUE, /* header flag */
trailer = TRUE, /* trailer flag */
tflag = FALSE; /* totals flag */
/* attribute names */
char *attoffnames[] = {"","","","","","","","","RW","DIR",""},
*attonnames[] = {"F1","F2","F3","F4","F5","F6","F7","F8","RO","SYS","ARC"};
#define attname(num,ch) (((ch & 0x080) != 0)?attonnames[num]:attoffnames[num])
/* commonly used functions: */
long int __BDOS(); /* BDOS hook */
char *index(); /* index function */
/* main routine - process command line, fetch file names, and print results */
main(argc,argv)
FAST int argc;
FAST char **argv;
{
FAST NAMESP innames,x;
NAMESP cons(); /* list constructor funs */
innames = NULL;
while ((--argc)>0) {
if (**(++argv) == '-') { /* switch? */
switch(*(++(*argv))) {
case 'r' : sortflg = DESSENDING; break;
case 'c' : columns = atoi(++(*argv)); break;
case 's' : sflag = TRUE; break;
case 'a' : aflag = TRUE; break;
case 'f' : sflag = TRUE; aflag = TRUE; break;
case 'h' : switch (*(++(*argv))) {
case '-' : header = FALSE; break;
case '+' : header = TRUE; break;
default : usage();
} break;
case 't' : switch (*(++(*argv))) {
case 'o' : tflag = TRUE; break;
case 'r' : switch (*(++(*argv))) {
case '-' : trailer = FALSE;
break;
case '+' : trailer = TRUE;
break;
default : usage();
} break;
default : usage();
} break;
default : usage();
}
}
else innames = cons(*argv,innames);
}
if (innames == NULL) innames = cons("*.*",innames);
while (innames != NULL) {
fsearch(innames->name);
innames = innames->next;
}
flushdu();
if (!header && !trailer) columns = 1;
if (sflag || aflag) print1files();
else printfiles();
}
NAMESP cons(nm,nml)
FAST char *nm;
FAST NAMESP nml;
{
FAST char *p;
FAST int len;
char *calloc();
FAST NAMESP newnl;
p = calloc(strlen(nm)+1,sizeof(char));
if (p == NULL) {perror("xdir");abort(0);}
strcpy(p,nm);
newnl = (NAMESP) calloc(1,sizeof(NAMES));
if (newnl == NULL) {perror("xdir");abort(0);}
newnl->name = p;
newnl->next = nml;
return(newnl);
}
fsearch(nm)
FAST char *nm;
{
LOCAL struct fcbtab seafcb;
FAST char *p,*q;
FAST int i,j;
FAST int user;
FAST char dev;
FAST int loginv;
FAST int curuser;
FAST char curdev;
curuser = __OSIF(USER, 0x000000FFL);
curdev = (__OSIF(GETDRV, 0L) + 'A');
loginv = __OSIF(GETLOG, 0L);
j = 0;
if (isalpha(*nm) && strlen(nm)>1 && *(nm+1) == ':') {
dev = toupper(*nm);
if (dev < 'A' || dev > 'P') badfile(q,0);
nm = nm+2; j+=2;
}
else if (*nm == '*' && strlen(nm)>1 && *(nm+1) == ':') {
dev = '*';
nm = nm+2; j+=2;
}
else dev = curdev;
i=8+3;
for(p=(&seafcb.fname[0]);i>0;i--) *p++='?';
p=(&seafcb.fname[0]); i = 0;
while ((isfilech(*nm) || *nm == '?') && i<8) {
*p++ = toupper(*nm); nm++; i++; j++;
}
if (*nm == '*') {nm++;j++;}
else if (i>0 && i<8) while (i<8) {*p++ = ' '; i++;}
while ((index(".[",*nm) == NULL) && (*nm != '\0')) {nm++;j++;}
if (*nm == '.') {
nm++;j++;
p=(&seafcb.ftype[0]); i=0;
while ((isfilech(*nm) || *nm == '?') && i<3) {
*p++ = toupper(*nm); nm++; i++; j++;
}
if (*nm == '*') {nm++;j++;}
else if (i>0 && i<3) while (i<3) {*p++ = ' '; i++;}
}
if (*nm == '[') {nm++;j++;
p=nm;
while (isdigit(*nm) || *nm == '*') {nm++;j++;}
if (*nm != ']') badfile(q,j);
*nm = '\0';
if (strlen(p) == 0) user = curuser;
else if (strcmp(p,"*") == 0) user = -1;
else user = atoi(p);
*nm = ']';
nm++;j++;
}
else user = curuser;
if (*nm != '\0') badfile(q,j);
if (dev == '*') {
for (i=0;i<16;i++)
if ((loginv & (1 << i)) != 0) {
seafcb.drive = i+1;
sealop0(&seafcb,user,i+'A');
}
}
else {
seafcb.drive = (dev - 'A')+1;
sealop0(&seafcb,user,dev);
}
__OSIF(USER, curuser);
}
sealop0(fcb,user,dev)
FAST struct fcbtab *fcb;
FAST int user;
FAST char dev;
{
int i;
if (user == (-1))
for (i=0;i<16;i++) sealop(fcb,i,dev);
else sealop(fcb,user,dev);
}
sealop(fcb,user,dev)
FAST struct fcbtab *fcb;
FAST int user;
FAST char dev;
{
LOCAL SEABLK seadma[4];
FAST int status,i;
FAST char *p,*q;
LOCAL char nbuff[20];
NAMESP orderin(); /* list constructor funs */
__OSIF(USER, user);
__OSIF(SETDMA, (&seadma[0]));
status = __OSIF(SEARCHF, fcb);
while (status != 0x00FF) {
p = (&nbuff[0]);
*p++ = dev;
*p++ = ':';
q = (&seadma[status].xf[0]);
i = 0;
while ((*q & 0x7F) != ' ' && i <8) {
*p++ = (*q++);
i++;
}
*p++ = '.';
q = (&seadma[status].t[0]);
i=0;
while ((*q & 0x7F) != ' ' && i < 3) {
*p++ = (*q++);
i++;
}
*p++ = '[';
if (user > 9) {
*p++ = (user / 10) + '0';
*p++ = (user % 10) + '0';
}
else {
*p++ = '0';
*p++ = user + '0';
}
*p++ = ']';
*p='\0';
filelist = orderin((&nbuff[0]),filelist);
status = __OSIF(SEARCHN, 0L);
}
}
NAMESP orderin(innm,nlist)
FAST char *innm;
FAST NAMESP nlist;
{
FAST NAMESP newnl,p,q;
if (nlist == NULL) return(cons(innm,nlist));
else if (alfcmp(innm,nlist->name)) return(cons(innm,nlist));
else {
p = nlist;
q = nlist->next;
while (q != NULL && !alfcmp(innm,q->name)) {
p=q;q=p->next;
}
p->next = cons(innm,q);
return(nlist);
}
}
alfcmp(s1,s2)
FAST char *s1,*s2;
{
FAST *u1,*u2;
FAST int cmp,ucmp;
u1 = index(s1,'['); u2 = index(s2,'[');
cmp = strcmp(s1,s2);
ucmp = strcmp(u1,u2);
if (ucmp == 0) return(sign(cmp) == sortflg);
else return(sign(ucmp) == sortflg);
}
flushdu()
{
FAST NAMESP p,*q;
p = filelist; q = (&filelist);
while (p!=NULL && (p->next) != NULL) {
if (strcmp(p->name,(p->next)->name) == 0) {
*q = p->next;
q = &(p->next);
p = p->next;
}
else {
q = &(p->next);
p = p->next;
}
}
}
printfiles()
{
FAST NAMESP p;
FAST int curcol;
FAST char curdev,dev,*t;
FAST int curuser,user;
FAST int dir,files,tfiles;
curdev = '@'; curuser = (-1); curcol = 0; dir=0; files=0; tfiles=0;
for (p=filelist;p!=NULL;p=p->next) {
if (curcol == columns && !tflag) {printf("\n");curcol=0;}
dev = *(p->name);
t = index(p->name,'[')+1;
user = ((*t - '0')*10) + (*(t+1) -'0');
if ((dev != curdev) || (user != curuser)) {
if (curcol > 0 && !tflag) printf("\n");
curcol = 0;
if (trailer && files>0) printf(TFORMAT1,files);
dir++; curdev=dev; curuser=user; files=0;
if (header) printf(HFORMAT,dev,user);
}
if ((header || trailer) && !tflag) {
*(--t) = '\0';
prinfl((p->name)+2,FLEN1);
*t = '[';
}
else if (!tflag) prinfl(p->name,FLEN2);
curcol++;files++;tfiles++;
}
if (curcol>0 && !tflag) printf("\n");
if (trailer && files > 0) printf(TFORMAT1,files);
if (trailer && dir >1) printf(TFORMAT2,tfiles,dir);
}
print1files()
{
FAST NAMESP p;
FAST char curdev,dev,*t,*u;
FAST int curuser,user;
FAST int ai,comma;
FAST int dir,files,tfiles;
FAST long int size,fsize,tsize;
FAST long int dire,fdire,tdire;
LOCAL struct fcbtab fcb;
LOCAL DPB dpb;
int olduser,olddrv;
olduser = __OSIF(USER, 0x00FF);
olddrv = __OSIF(GETDRV, 0);
fsize = 0L; tsize = 0L;
fdire = 0L; tdire = 0L;
curdev = '@'; curuser = (-1); dir=0; files=0; tfiles=0;
for (p=filelist;p!=NULL;p=p->next) {
dev = *(p->name);
t = index(p->name,'[')+1;
user = ((*t - '0')*10) + (*(t+1) -'0');
if ((dev != curdev) || (user != curuser)) {
if (trailer && files>0) printf(TFORMAT1,files,fsize,fdire);
dir++; curdev=dev; curuser=user; files=0; fsize = 0L; fdire=0L;
if (header) printf(HFORMAT,dev,user);
}
if ((header || trailer) && !tflag) {
*(--t) = '\0';
prinfl((p->name)+2,FLEN1);
*t = '[';
}
else if (!tflag) prinfl(p->name,FLEN2);
fcb.drive = (dev - 'A') + 1;
t = (&fcb.fname[0]); for (ai=0;ai<(8+3);ai++) *t++ = ' ';
t = (p->name)+2; u = (&fcb.fname[0]);
while (*t != '.') *u++ = *t++;
t++; u = (&fcb.ftype[0]);
while (*t != '[') *u++ = *t++;
if (sflag) {
__OSIF(USER, user);
__OSIF(FILSIZ ,&fcb);
__OSIF(USER, olduser);
__OSIF(SELDRV, dev - 'A');
__OSIF(GETDPB, &dpb);
__OSIF(SELDRV, olddrv);
size = (fcb.record + ((long) dpb.blm)) >> dpb.bsh;
if (dpb.dsm > 255) dire = (size + 7L) >> 3;
else dire = (size + 15L) >> 4;
if (dpb.bsh>3) size = size << (dpb.bsh - 3);
if (!tflag) printf(SFORMAT,size,dire);
fsize += size; tsize += size;
fdire += dire; tdire += dire;
}
if (aflag && !tflag) {
__OSIF(USER, user);
__OSIF(OPEN ,&fcb);
/* __OSIF(CLOSE ,&fcb);*/
__OSIF(USER, olduser);
t = (&fcb.fname[0]);
printf("("); comma = FALSE;
for(ai = 0;ai<(8+3);ai++) {
if (comma && strlen(attname(ai,*t))>0) printf(",");
printf("%s",attname(ai,*t));
if (strlen(attname(ai,*t))>0) comma = TRUE;
t++;
}
printf(")");
}
if (!tflag) printf("\n");
files++;tfiles++;
}
if (trailer && files > 0) printf(TFORMAT1,files,fsize,fdire);
if (trailer && dir >1) printf(TFORMAT2,tfiles,dir,tsize,tdire);
}
usage()
{
fprintf(stderr,
"Usage: xdir [-r ][-cN ][-s ][-a ][-f ][-to ][-tr+/- ][-h+/- ][fname [fname ...]][>outfile]\n");
abort(2);
}
badfile(n,np)
FAST char *n;
FAST int np;
{
fprintf(stderr,"Illegal file name: %s\n ",n);
while ((np--)>0) fprintf(stderr," ");
fprintf(stderr,"^- parse stoped here\n");
abort(1);
}
prinfl(s,l)
FAST char *s;
FAST int l;
{
while (*s != '\0') {
printf("%c",(*s++) & 0x7F);
l--;
}
while ((l--)>0) putchar(' ');
}