home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 6 File
/
06-File.zip
/
os2ntree.zip
/
OLDNTREE.C
< prev
next >
Wrap
Text File
|
1987-12-17
|
32KB
|
1,313 lines
/* ***********************************************************************
** NTREE - The search for a better tree program has ended **
** Version 2.3.0 (DOS Version) **
** A hack by Mitch Lichtenberg **
** Main module File: NTREE.C **
*********************************************************************** */
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
/* +-------------------------------------------------------------------+
| Constants |
+-------------------------------------------------------------------+ */
#define switchp(x) ((*x) == '/')
#define FREADONLY 0x01
#define FHIDDEN 0x02
#define FSYSTEM 0x04
#define FLABEL 0x08
#define FDIRECTORY 0x10
#define FARCHIVE 0x20
/*
* switch masks
*/
#define SFILES 0x0001
#define SHIDDEN 0x0002
#define SVERIFY 0x0004
#define SQUERY 0x0008
#define SDELETE 0x0010
#define SARC 0x0020
#define SUPDATE 0x0040
#define SREALLY 0x0080
#define SDATE 0x0100
#define SOVER 0x0200
#define SCALL 0x0400
#define SCOPY 0x0800
#define SDIR 0x1000
#define STOTAL 0x2000
#define SBAT 0x4000
#define SINFO 0x8000
#define SQUIET 0x0001 /* sw. word 2 */
#define SSILENT 0x0002 /* sw. word 2 */
/* +-------------------------------------------------------------------+
| Structures |
+-------------------------------------------------------------------+ */
typedef unsigned char byte;
typedef unsigned int word;
typedef unsigned long dword;
typedef struct FileDate {
unsigned int second : 5;
unsigned int minute : 6;
unsigned int hour : 5;
unsigned int day : 5;
unsigned int month : 4;
unsigned int year : 7;
} FILEDATE;
typedef struct dta {
char reserved[21];
byte attribute;
FILEDATE fd;
dword size;
char name[14];
} DTA;
typedef struct cons {
char *str;
int num;
} CONS;
typedef struct btree {
char *name; /* name of node */
char *subname; /* name of just this file */
struct btree *child; /* children */
struct btree *sibling; /* brothers */
} BTREE;
/* +-------------------------------------------------------------------+
| global variables |
+-------------------------------------------------------------------+ */
DTA fedta;
DTA *dossetdta();
int oldverify = 0;
int fncount = 0;
unsigned int dircount;
unsigned int filecount;
unsigned long total;
unsigned long clus;
unsigned long fclus;
unsigned long allocunit;
char inwildcard[20];
char infnam[64];
char outfnam[64];
char ncallstr[64];
char dbcallstr[64];
char dacallstr[64];
char rawoutfnam[64];
int inlen,outlen;
char temp[64];
char temp2[64];
word switches = 0;
word switches2 = 0;
word verbose = 1; /* 1 means write to stdout */
word showerr = 1; /* 1 means write to stderr */
char *version = "NTREE version 2.3 [DOS version]\n";
CONS switchnames[] = {
{"A",SFILES}, /* enumerate all files */
{"H",SHIDDEN}, /* hidden too */
{"V",SVERIFY}, /* turn on verify */
{"Q",SQUERY}, /* query mode on */
{"D",SDELETE}, /* delete tree */
{"ARC",SARC}, /* use ARC to save tree */
{"U",SUPDATE}, /* update (don't do files already done) */
{"YES",SREALLY}, /* don't ask for confirmation */
{"DATE",SDATE}, /* copy only if source has later date */
{"O",SOVER}, /* overwrite dest */
{"C",SCOPY}, /* needed for copy op */
{"DIR",SDIR}, /* display <DIR> for directories*/
{"T",STOTAL}, /* total space */
{"BAT",SBAT}, /* don't do system commands just echo */
{"I",SINFO}, /* file info too */
{NULL,NULL}};
CONS switchnames2[] = {
{"QUIET",SQUIET}, /* don't write to stdout */
{"SILENT",SSILENT}, /* don't write anywhere */
{NULL,NULL}};
extern unsigned int errno;
/* +-------------------------------------------------------------------+
| main(argc,argv) |
| the beginning of the world |
+-------------------------------------------------------------------+ */
main(argc,argv)
int argc;
char *argv[];
{
int a,b;
char *x,*y;
BTREE *t;
BTREE *maketree();
int inthndlr();
fprintf(stderr,version);
if (argc < 2) usage();
strcpy(ncallstr,"");
strcpy(dacallstr,"");
strcpy(dbcallstr,"");
a = 1;
argv++;
while (a < argc) {
if (strcmpi(*argv,"/CALL") == 0) {
a++; argv++;
strcpy(ncallstr,*argv);
switches |= SCALL | SFILES;
a++; argv++;
continue;
}
if (strcmpi(*argv,"/BEFORE") == 0) {
a++; argv++;
strcpy(dbcallstr,*argv);
switches |= SCALL;
a++; argv++;
continue;
}
if (strcmpi(*argv,"/AFTER") == 0) {
a++; argv++;
strcpy(dacallstr,*argv);
switches |= SCALL;
a++; argv++;
continue;
}
if (switchp(*argv)) setswitches(*argv);
else switch (fncount) {
case 0: strcpy(infnam,*argv); fncount++; break;
case 1: strcpy(outfnam,*argv); fncount++; break;
case 2: fatalerr("Incorrect number of parameters");
}
a++; argv++;
}
/* now, process input file name into wildcard */
strcpy(inwildcard,"*.*"); /* deflt */
strupr(infnam);
if (!strchr(infnam,'\\')) {
if (infnam[1] == ':') {
getdir(infnam[0]-'@',temp);
strcpy(temp2,infnam+2);
pathize(temp,temp2,infnam);
}
else {
getcwd(temp,80);
strcpy(temp2,infnam);
pathize(temp,temp2,infnam);
}
}
x = strchr(infnam,'?');
y = strchr(infnam,'*'); /* find first of either of these */
if (x > y) y = x;
if (y) {
while (y >= infnam) {
if (*y == '\\') break;
if (*y == ':') break;
y--;
}
y++; /* now y points to start of wildcard */
x = strtok(y,"/");
if (y != infnam) strcpy(inwildcard,x);
*y = '\0'; /* zap end of string */
y = strtok(NULL,""); /* get rest of switches */
}
else {
if (x = strchr(infnam,'/')) {
*x = '\0';
y = x+1;
}
}
if (y) {
sprintf(temp,"/%s",y);
setswitches(temp);
}
x = strchr(outfnam,'?');
y = strchr(outfnam,'*'); /* find first of either of these */
if (x && y && (x > y)) y = x;
if (x && !y) y = x;
if (y) {
while (y >= outfnam) {
if (*y == '\\') break;
if (*y == ':') break;
y--;
}
y++; /* now y points to start of wildcard */
y = strtok(y,"/"); /* get switches */
*y = '\0';
y = strtok(NULL,""); /* get rest of switches */
}
else {
if (x = strchr(outfnam,'/')) {
*x = '\0';
y = x+1;
}
}
if (y) {
sprintf(temp,"/%s",y);
setswitches(temp);
}
if ((strlen(infnam) == 2) && (infnam[1] == ':')) {
strupr(infnam);
getdir((*infnam) - '@',infnam);
}
if ((strlen(outfnam) == 2) && (outfnam[1] == ':')) {
strupr(outfnam);
getdir((*outfnam) - '@',outfnam);
}
y = infnam+strlen(infnam)-1; if (*y != '\\') strcat(infnam,"\\");
y = outfnam+strlen(outfnam)-1; if (*y != '\\') strcat(outfnam,"\\");
if (strcmp(infnam,".\\") == 0) {
getdir(curdrive(),infnam);
strcat(infnam,"\\");
}
if (strcmp(outfnam,".\\") == 0) {
getdir(curdrive(),outfnam);
strcat(outfnam,"\\");
}
strcpy(rawoutfnam,outfnam);
rmslash(rawoutfnam);
fixup(infnam); /* add current drive & dir */
fixup(outfnam);
inlen = strlen(infnam);
outlen = strlen(outfnam);
/*
printf("Input filename: %s\n",infnam);
printf("output filename: %s\n",outfnam);
printf("wildcard string: %s\n",inwildcard);
printf("switch mask: %04X\n",switches);
exit(0);
*/
signal(SIGINT,inthndlr);
oldverify = getverify();
if (switches & SVERIFY) setverify(1);
/* switch implicants */
if (switches & SDELETE) switches |= SFILES;
if (switches & SCOPY) switches |= SFILES;
if (switches & STOTAL) switches |= SFILES;
if (switches & SINFO) switches |= SFILES;
if (switches & SDATE) switches |= SOVER;
b = (switches & (SCOPY | SDELETE | SARC | STOTAL | SCALL));
a = 0;
while (b) {
if (b & 1) a++;
b >>= 1;
}
if (a > 1) fatalerr("Cannot do more than one command at a time");
if (switches2 & SQUIET) verbose = 0;
if (switches2 & SSILENT) verbose = showerr = 0;
if (switches & SCOPY) tcopy();
else if (switches & SDELETE) tdelete();
else if (switches & SARC) tarchive();
else if (switches & STOTAL) ttotal();
else if (switches & SCALL) tcall();
else tdisplay();
}
/* +-------------------------------------------------------------------+
| setswitches(cp) |
| sets switches from string ptr |
+-------------------------------------------------------------------+ */
setswitches(cp)
char *cp;
{
static char *brk = "/";
char *tok;
int a;
tok = strtok(cp,brk);
while (tok) {
a = assoc(tok,switchnames);
if (a == 0) {
a = assoc(tok,switchnames2);
if (a == 0) fatalerr("Unrecognized switch: %s",tok);
else switches2 |= a;
}
else switches |= a;
tok = strtok(NULL,brk);
}
}
/* +-------------------------------------------------------------------+
| fixup(string) |
| Fixes up dir/path spec to be fully formed |
+-------------------------------------------------------------------+ */
fixup(str)
char *str;
{
char nstr[70];
char buf[70];
strupr(str);
if (*str == '\\') { /* just add directory */
sprintf(nstr,"%c:%s",curdrive()+'@',str);
strcpy(str,nstr);
return;
}
if ((*(str+1) == ':') && (*(str+2) != '\\')) { /* add directory */
getdir((*str) - '@',buf);
sprintf(nstr,"%c:\\%s\\%s",*str,buf+3,str+2);
strcpy(str,nstr);
return;
}
if ((*(str+1) != ':') && (*str != '\\')) { /* add drive & dir */
getdir(curdrive(),buf);
sprintf(nstr,"%c:\\%s\\%s",curdrive()+'@',buf+3,str);
strcpy(str,nstr);
return;
}
}
/* +-------------------------------------------------------------------+
| fatalerr(a,b,c,d,e) |
| die with fatal error |
+-------------------------------------------------------------------+ */
fatalerr(a,b,c,d,e)
{
fprintf(stderr,"ntree: ");
fprintf(stderr,a,b,c,d,e);
fprintf(stderr,"\n");
exit(1);
}
/* +-------------------------------------------------------------------+
| assoc(str,lst) |
| finds string in list |
+-------------------------------------------------------------------+ */
assoc(str,lst)
char *str;
CONS *lst;
{
while (lst->str) {
if (strcmpi(lst->str,str) == 0) return lst->num;
lst++;
}
return 0;
}
/* +-------------------------------------------------------------------+
| dotree(path) |
| returns BTREE starting at path |
+-------------------------------------------------------------------+ */
BTREE *dotree(path)
char *path;
{
BTREE *node = NULL;
BTREE *list = NULL;
DTA dta;
char npath[64]; /* path with wildcard */
char rpath[64]; /* recursive call path */
static char *stars = "*.*";
int status;
int attrib = FDIRECTORY;
dossetdta(&dta); /* prepare for dir scan */
strcpy(npath,path);
strcat(npath,stars);
if (switches & SHIDDEN) attrib |= FHIDDEN;
status = dosfindfirst(npath,FDIRECTORY); /* get first file */
while (status == 0) {
if ((dta.attribute & FDIRECTORY) &&
(dta.name[0] != '.')) { /* add to tree */
node = (BTREE *) calloc(1,sizeof(BTREE));
node->sibling = list;
list = node;
strcpy(rpath,path);
strcat(rpath,dta.name);
strcat(rpath,"\\");
node->subname = strdup(dta.name);
node->name = strdup(rpath);
node->child = dotree(rpath);
}
dossetdta(&dta);
status = dosfindnext();
}
return list;
}
/* +-------------------------------------------------------------------+
| maketree(path) |
| Returns btree for path, including starting dir |
+-------------------------------------------------------------------+ */
BTREE *maketree(path)
char *path;
{
BTREE *btree;
int flg = 0;
btree = (BTREE *) calloc(1,sizeof(BTREE));
btree->name = strdup(path);
btree->sibling = NULL;
btree->child = dotree(path);
return btree;
}
/* +-------------------------------------------------------------------+
| rmslash(str) |
| removes last char of string if it is a backslash |
+-------------------------------------------------------------------+ */
rmslash(str)
char *str;
{
int len;
len = strlen(str);
if ((len == 3) && (str[1] == ':') && (str[2] == '\\')) return;
if (len == 0) return;
len--;
if (str[len] == '\\') str[len] = '\0';
}
/* +-------------------------------------------------------------------+
| pathize(dir,name,path) |
| makes a good pathname |
+-------------------------------------------------------------------+ */
pathize(dir,name,path)
char *dir;
char *name;
char *path;
{
int len;
strcpy(path,dir);
len = strlen(path);
if (len && (path[len-1] == '\\')) path[len-1] = '\0';
if (*name != '\\') strcat(path,"\\");
strcat(path,name);
}
/* +-------------------------------------------------------------------+
| fexist(name,attrib) |
| test for file exist (returns attrib if yes |
+-------------------------------------------------------------------+ */
fexist(name,attrib)
char *name;
int attrib;
{
int status;
DTA *olddta;
olddta = dossetdta(&fedta);
status = dosfindfirst(name,attrib);
if (status == 0) return (fedta.attribute | 0x8000);
return 0;
}
/* +-------------------------------------------------------------------+
| subtreep(a,b) |
| returns 1 if a and b are subtrees of one another |
+-------------------------------------------------------------------+ */
subtreep(a,b)
char *a,*b;
{
if (strncmp(a,b,strlen(a)) == 0) return 1;
if (strncmp(a,b,strlen(b)) == 0) return 1;
return 0;
}
/* +-------------------------------------------------------------------+
| rootdirp(str) |
| returns 1 if str describes a root directory |
+-------------------------------------------------------------------+ */
rootdirp(str)
char *str;
{
if (strcmp(str+1,":\\") == 0) return 1;
if (strcmp(str,"\\") == 0) return 1;
return 0;
}
/* +-------------------------------------------------------------------+
| printdir(t,fnam) |
| prints a dir file name |
+-------------------------------------------------------------------+ */
printdir(t,fnam)
BTREE *t;
char *fnam;
{
char newname[64];
strcpy(newname,fnam);
rmslash(newname);
if (switches & SDIR) printf("%s\t<DIR>\n",newname);
else if (!(switches & SFILES)) printf("%s\n",newname);
if (switches & SINFO) dircount++;
}
/* +-------------------------------------------------------------------+
| printname(t,str,dta) |
| prints filename |
+-------------------------------------------------------------------+ */
printname(t,str,dta)
BTREE *t;
char *str;
DTA *dta;
{
char fooname[64];
strcpy(fooname,str);
rmslash(fooname);
if (switches & SINFO) {
filecount++;
total += dta->size;
clus += dta->size / allocunit;
fclus += dta->size / 512L;
if ((dta->size % allocunit) != 0) clus++;
if ((dta->size % 512L) != 0) fclus++;
printf("%-50.50s %8lu %02d-%02d-%02d %02d:%02d\n",
str,dta->size,dta->fd.month+1,dta->fd.day,
dta->fd.year+1980,dta->fd.hour,dta->fd.minute);
}
else {
puts(fooname);
}
}
/* +-------------------------------------------------------------------+
| enumfiles(path,t,fn) |
| enumerate all files on path |
+-------------------------------------------------------------------+ */
enumfiles(path,t,fn)
char *path;
BTREE *t;
int (*fn)();
{
DTA dta;
int status;
int attrib = 0;
char npath[64];
char nfile[64];
strcpy(npath,path);
strcat(npath,inwildcard);
if (switches & SHIDDEN) attrib |= FHIDDEN;
dossetdta(&dta);
status = dosfindfirst(npath,attrib);
while (status == 0) {
strcpy(nfile,path);
strcat(nfile,dta.name);
if (dta.name[0] != '.') if (fn) (*fn)(t,nfile,&dta);
dossetdta(&dta);
status = dosfindnext();
}
}
/* +-------------------------------------------------------------------+
| maptree(tree,prefn,postfn,namefn) |
| map out contents of b-tree |
+-------------------------------------------------------------------+ */
maptree(tree,prefn,postfn,namefn)
BTREE *tree;
int (*prefn)();
int (*postfn)();
int (*namefn)();
{
int i;
if (!tree) return;
while (tree) {
if (prefn) (*prefn)(tree,tree->name);
if (switches & SFILES) {
enumfiles(tree->name,tree,namefn);
}
if (tree->child) maptree(tree->child,prefn,postfn,namefn);
if (postfn) (*postfn)(tree,tree->name);
tree = tree->sibling;
}
}
/* +-------------------------------------------------------------------+
| zapdir(name) |
| delete directory |
+-------------------------------------------------------------------+ */
zapdir(t,name)
BTREE *t;
char *name;
{
char newname[64];
strcpy(newname,name);
rmslash(newname);
if (rootdirp(name)) return; /* don't delete root dir */
if (verbose) printf("Deleting directory: %s\n",newname);
if (rmdir(newname) != 0) {
if (showerr) fprintf(stderr,"Could not delete directory: %s\n",newname);
}
}
/* +-------------------------------------------------------------------+
| zapfile(t,name,dta) |
| delete file |
+-------------------------------------------------------------------+ */
zapfile(t,name,dta)
BTREE *t;
char *name;
DTA *dta;
{
if (!doquery("Delete file %s? (Y/N/A/Q): ",name)) return;
if (verbose) printf("Deleting file: %s\n",name);
if (unlink(name) != 0) {
if (showerr) fprintf(stderr,"Could not delete file: %s\n",name);
}
}
/* +-------------------------------------------------------------------+
| copydir(t,name) |
| copy directory (prefn) |
+-------------------------------------------------------------------+ */
copydir(t,name)
BTREE *t;
char *name;
{
char newdir[64];
strcpy(newdir,outfnam);
strcat(newdir,name+inlen);
if (rootdirp(newdir)) return;
rmslash(newdir);
if (fexist(newdir,FDIRECTORY)) {
#ifdef PAUL_DOESNT_LIKE_THIS
printf("Directory already exists: %s\n",newdir);
#endif
return;
}
if (verbose) printf("Creating directory: %s\n",newdir);
if (mkdir(newdir) != 0) {
if (errno != EACCES) fatalerr("Could not create directory: %s\n",newdir);
#ifdef PAUL_DOESNT_LIKE_THIS
else printf("Directory already exists: %s\n",newdir);
#endif
}
}
/* +-------------------------------------------------------------------+
| copyfile(t,name,dta) |
| namefn for copy file |
+-------------------------------------------------------------------+ */
copyfile(t,name,dta)
BTREE *t;
char *name;
DTA *dta;
{
char newname[64];
int attr;
int newatt;
if (switches & SUPDATE) {
if (!(dta->attribute & FARCHIVE)) return;
doschmod(name,dta->attribute & ~FARCHIVE);
newatt = dta->attribute & ~FARCHIVE;
}
else newatt = dta->attribute;
strcpy(newname,outfnam);
strcat(newname,name+inlen);
attr = fexist(newname,0);
if (switches & SDATE) {
if (cmpdate(&(dta->fd),&(fedta.fd)) != 1) return;
}
if (!doquery("Copy file %s? (Y/N/A/Q): ",name)) return;
if (attr && (!(switches & SOVER))) {
if (verbose) printf("File already exists: %s\n",newname);
return;
}
if (attr & FREADONLY) {
if (verbose) printf("File is read-only: %s\n",newname);
return;
}
if (verbose) printf("Copying %s to %s\n",name,newname);
switch (docopyfile(name,newname)) {
case 0: break;
case 1: fatalerr("could not open source file: %s",name);
case 2: fatalerr("could not open destination file: %s",newname);
case 3: fatalerr("could not read source file: %s",name);
case 4: fatalerr("could not write destination file: %s",newname);
case 5: fatalerr("could not allocate memory for copy");
}
doschmod(newname,newatt);
}
/* +-------------------------------------------------------------------+
| totaldir(t,name) |
| totals directories |
+-------------------------------------------------------------------+ */
totaldir(t,name)
BTREE *t;
char *name;
{
dircount++;
}
/* +-------------------------------------------------------------------+
| totalfile(t,name,dta) |
| totals all files |
+-------------------------------------------------------------------+ */
totalfile(t,name,dta)
BTREE *t;
char *name;
DTA *dta;
{
filecount++;
total += dta->size;
clus += dta->size / allocunit;
fclus += dta->size / 512L;
if ((dta->size % allocunit) != 0) clus++;
if ((dta->size % 512L) != 0) fclus++;
}
/* +-------------------------------------------------------------------+
| arcdir(name) |
| archive directory |
+-------------------------------------------------------------------+ */
arcdir(t,name)
BTREE *t;
char *name;
{
char olddir[64];
char arcname[64];
char cmd[128];
char *x;
char *y;
int cancel = 0;
getcwd(olddir,64); /* get current drive/dir */
strcpy(arcname,name); /* temp */
rmslash(arcname);
changedir(arcname); /* change to this new dir */
if (verbose) printf("Now working on directory: %s\n",arcname);
if (strcmp(infnam,name) == 0) strcpy(arcname,rawoutfnam); /* reached end */
else {
sprintf(arcname,"..\\%s.ARC",t->subname);
}
if (!cancel) {
if (fexist(arcname,0)) {
if (verbose) printf("Deleting old archive %s\n",arcname);
unlink(arcname);
}
sprintf(cmd,"arc a %s %s *.arc",arcname,inwildcard);
if (verbose) {
fputs(cmd,stdout);
fputc('\n',stdout);
}
system(cmd);
}
changedir(olddir);
}
/* +-------------------------------------------------------------------+
| tdisplay() |
| Display tree using given switches |
+-------------------------------------------------------------------+ */
tdisplay()
{
BTREE *t;
if (fncount == 0) fatalerr("pathname missing for tree display");
if (fncount != 1) fatalerr("incorrect number of pathnames");
t = maketree(infnam); /* at least this one */
allocunit = (unsigned long) clussize((*infnam) - '@');
total = 0L;
clus = 0L;
fclus = 0L;
dircount = 0;
filecount = 0;
maptree(t,printdir,NULL,printname);
if (switches & SINFO) sayinfo();
}
/* +-------------------------------------------------------------------+
| tdelete() |
| delete all entries in tree |
+-------------------------------------------------------------------+ */
tdelete()
{
BTREE *t;
char line[40];
if (!(switches & SREALLY)) {
fprintf(stderr,"Are you sure you want to delete %s%s? [NO]: ",
infnam,inwildcard);
while (1) {
gets(line);
strupr(line);
if (strcmp(line,"YES") == 0) break;
if (strlen(line) == 0) fatalerr("abort");
if (strcmp(line,"NO") == 0) fatalerr("abort");
fprintf(stderr,"\nYou must type YES to delete the tree\nAre you sure? [NO]:");
}
}
t = maketree(infnam);
maptree(t,NULL,zapdir,zapfile);
}
/* +-------------------------------------------------------------------+
| tarchive() |
| archive all tree entries |
+-------------------------------------------------------------------+ */
tarchive()
{
BTREE *t;
if (fncount != 2) usage();
t = maketree(infnam);
maptree(t,NULL,arcdir,NULL);
}
/* +-------------------------------------------------------------------+
| tcopy() |
| copy all entries in tree |
+-------------------------------------------------------------------+ */
tcopy()
{
BTREE *t;
if (fncount != 2) {
fprintf(stderr,"must supply two pathnames");
usage();
}
if (subtreep(infnam,outfnam)) fatalerr("Trees are not disjoint: %s, %s\n",infnam,outfnam);
t = maketree(infnam);
maptree(t,copydir,NULL,copyfile);
}
/* +-------------------------------------------------------------------+
| ttotal() |
| totals all space in tree |
+-------------------------------------------------------------------+ */
ttotal()
{
BTREE *t;
if (fncount != 1) usage();
t = maketree(infnam);
allocunit = (unsigned long) clussize((*infnam) - '@');
total = 0L;
clus = 0L;
fclus = 0L;
dircount = 0;
filecount = 0;
maptree(t,totaldir,NULL,totalfile);
sayinfo();
}
/* +-------------------------------------------------------------------+
| sayinfo() |
| prints out drive info |
+-------------------------------------------------------------------+ */
sayinfo()
{
printf("Tree %s%s contains %d files in %d directories,\n",
infnam,inwildcard,filecount,dircount);
printf("%lu bytes (%luK)\n",total,(unsigned long) (total / 1024L));
printf("%lu clusters for drive %c: (%luK)\n",
clus,*infnam,(unsigned long) (clus * allocunit)/1024L);
printf("%lu clusters for floppy drive: (%luK)\n",
fclus,(unsigned long) (fclus * 512L)/1024L);
}
/* +-------------------------------------------------------------------+
| mexpand(template,buf,dirname,dta) |
| macroexpand |
+-------------------------------------------------------------------+ */
mexpand(template,buf,dirname,dta)
char *template;
char *buf;
char *dirname;
DTA *dta;
{
char *cp;
cp = template;
while (*cp) {
if (*cp != '$') {
*buf = *cp;
cp++; buf++;
continue;
}
cp++;
if (!*cp) break;
switch (*cp++) {
case '$': *buf++ = '$'; break;
case 's':
case 'S': strcpy(buf,dirname);
buf += strlen(dirname);
break;
case 'd':
case 'D':
strcpy(buf,outfnam);
strcat(buf,dirname+inlen);
buf += strlen(buf);
break;
case 'b':
case 'B':
if (dta) {
sprintf(buf,"%lu",dta->size);
buf += strlen(buf);
}
break;
case 'g':
case 'G': *buf++ = '>'; break;
case 'l':
case 'L': *buf++ = '<'; break;
case 'p':
case 'P': *buf++ = '|'; break;
case 'q':
case 'Q': *buf++ = '"'; break;
case 'f':
case 'F':
if (dta) {
strcpy(buf,dta->name);
buf += strlen(buf);
}
break;
case 'c':
case 'C': getcwd(buf,80);
buf += strlen(buf);
break;
default:
*buf++ = '$';
*buf++ = *(cp-1);
break;
}
}
*buf = '\0';
}
/* +-------------------------------------------------------------------+
| bcalldir(t,name) |
| do call with before directory string |
+-------------------------------------------------------------------+ */
bcalldir(t,name)
BTREE *t;
char *name;
{
char newname[64];
char cmd[128];
if (strlen(dbcallstr) == 0) return;
strcpy(newname,name);
rmslash(newname);
mexpand(dbcallstr,cmd,newname,NULL);
if (switches & SBAT) {
fputs(cmd,stdout);
fputc('\n',stdout);
}
else {
if (verbose) {
fputs(cmd,stderr);
fputc('\n',stderr);
}
system(cmd);
}
}
/* +-------------------------------------------------------------------+
| acalldir(t,name) |
| do call after directory string |
+-------------------------------------------------------------------+ */
acalldir(t,name)
BTREE *t;
char *name;
{
char newname[64];
char cmd[128];
if (strlen(dacallstr) == 0) return;
strcpy(newname,name);
rmslash(newname);
mexpand(dacallstr,cmd,newname,NULL);
if (switches & SBAT) {
fputs(cmd,stdout);
fputc('\n',stdout);
}
else {
if (verbose) {
fputs(cmd,stderr);
fputc('\n',stderr);
}
system(cmd);
}
}
/* +-------------------------------------------------------------------+
| callfile(t,name,dta) |
| do call after directory string |
+-------------------------------------------------------------------+ */
callfile(t,name,dta)
BTREE *t;
char *name;
DTA *dta;
{
char cmd[128];
if (strlen(ncallstr) == 0) return;
mexpand(ncallstr,cmd,name,dta);
if (switches & SBAT) {
fputs(cmd,stdout);
fputc('\n',stdout);
}
else {
if (verbose) {
fputs(cmd,stderr);
fputc('\n',stderr);
}
system(cmd);
}
}
/* +-------------------------------------------------------------------+
| tcall() |
| call function in tree |
+-------------------------------------------------------------------+ */
tcall()
{
BTREE *t;
t = maketree(infnam);
maptree(t,bcalldir,acalldir,callfile);
}
/* +-------------------------------------------------------------------+
| inthndlr() |
| handles ctrl-break interrupt |
+-------------------------------------------------------------------+ */
inthndlr()
{
setverify(oldverify);
fatalerr("interrupted via Ctrl-Break");
}
/* +-------------------------------------------------------------------+
| doquery(ques,file) |
| does query, returns 1 if YES, 0 if no |
+-------------------------------------------------------------------+ */
doquery(ques,file)
char *ques;
char *file;
{
if (!(switches & SQUERY)) return 1;
printf(ques,file);
while (1) {
switch (getchar()) {
case 'y':
case 'Y': printf("YES\n"); return 1;
case 'n':
case 'N': printf("NO\n"); return 0;
case 'q':
case 'Q': printf("QUIT\n");
setverify(oldverify);
fatalerr("exit");
case 'a':
case 'A': printf("ALL\n");
switches &= ~SQUERY;
return 1;
default: break;
}
}
}
/* +-------------------------------------------------------------------+
| usage() |
| does ntree usage |
+-------------------------------------------------------------------+ */
usage()
{
fprintf(stderr,"Usage: ntree {/sw/sw..} path1{wildcard}{/sw/sw..} {path2{/sw/sw..}} \"call\"");
fprintf(stderr,"\n");
fprintf(stderr,"\tntree/C path1{wild} path2 Copy tree\n");
fprintf(stderr,"\tntree/D path1{wild} Delete tree\n");
fprintf(stderr,"\tntree/ARC path1{wild} arcname Archive via ARC\n");
fprintf(stderr,"\tntree/T path1{wild} Total space used\n");
fprintf(stderr,"\tntree path1{wild} Directory display\n");
fprintf(stderr,"\tntree path1{wild} path2 /call \"macro\" /before \"macro\" /after \"macro\"\n");
fprintf(stderr,"\tmacros: $s=source, $d=dest, $g=>, $l=<, $p=|, $c=current dir\n");
fprintf(stderr,"\t $f=filename, $b=filesize, $$=$, $q=\"\n");
fprintf(stderr,"\n\tSwitches:\n");
fprintf(stderr,"\t /A Enumerate files and directories\n");
fprintf(stderr,"\t /H Include hidden files\n");
fprintf(stderr,"\t /V Set verify switch ON\n");
fprintf(stderr,"\t /U (for copy) Copy files with archive bit on\n");
fprintf(stderr,"\t /DATE (for copy) Copy files with later date\n");
fprintf(stderr,"\t /O (for copy) Copy files and overwrite destination\n");
fprintf(stderr,"\t /Q (copy/del) Query before copy or delete\n");
fprintf(stderr,"\t /YES (copy/del) Don't ask any questions..just do it\n");
fprintf(stderr,"\t /DIR (display) Display <DIR> for directories\n");
fprintf(stderr,"\t /BAT (call) Don't do commands, just echo to stdout\n");
fprintf(stderr,"\t /QUIET Don't write informative messages to stdout\n");
fprintf(stderr,"\t /SILENT Don't write messages or errors anywhere!\n");
exit(1);
}
/* +-------------------------------------------------------------------+
| cmpdate(d1,d2) |
| compares two filedates |
+-------------------------------------------------------------------+ */
cmpdate(d1,d2)
FILEDATE *d1;
FILEDATE *d2;
{
if (d1->year > d2->year) return 1;
if (d1->year < d2->year) return -1;
if (d1->month > d2->month) return 1;
if (d1->month < d2->month) return -1;
if (d1->day > d2->day) return 1;
if (d1->day < d2->day) return -1;
if (d1->hour > d2->hour) return 1;
if (d1->hour < d2->hour) return -1;
if (d1->second > d2->second) return 1;
if (d1->second < d2->second) return -1;
return 0;
}