home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Zodiac Super OZ
/
MEDIADEPOT.ISO
/
FILES
/
16
/
FREEDOS.ZIP
/
FD_A4PRE.ZIP
/
SOURCE
/
MICROC.ZIP
/
ATTRIB.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-01
|
6KB
|
223 lines
/*
* ATTRIB command for MS-DOS
*
* This is an ATTRIB command that pretty much works exactly like the
* one from Microsoft with the following enhancements:
*
* More flexible parsing: accepts +RS +R-S +RS-HA -H/S etc.
* Parameters can be in any order.
*
* Better error reporting, instead of just saying parameters are wrong,
* it tells you exactly what it didn't like.
*
* /V option for verbose output
* /F option for "full" listing. Shows directories & volume labels
*
* Walks the directory tree in a more natural manner. Ie, processes
* the files in a directory FIRST, then moves on to the subdirs.
*
* Unambiguous specification of directories. ie: append '\' to a directory
* name, otherwise it is assumed to be a filename. Microsofts ATTRIB will
* happily change all files in a directory if you happen to mistype it's
* name instead of a filename.
*
* Copyright 1995 Dave Dunfield
* Freely Distributable.
*/
#include <stdio.h>
#include <file.h>
#define DIRS 500 /* Depth of directory stacking */
char
*pattern = "", /* Pattern we are searching for */
path[66], /* Path we are searching */
subdir = 0, /* Indicates we are to search sub-dirs */
verbose = 0, /* Be talky */
full = 0, /* Full listing */
badopt = 0, /* A bad command option was detected */
set = 0, /* Indicates we are setting attributes */
dirstack[DIRS][13]; /* Stack of subdirectory names */
unsigned
setmask = 0, /* Attribute bits to set */
clrmask = -1, /* Attribute bits to clear */
dircount = 0, /* Count of directories processed */
filecount = 0, /* Count of files processed */
dirptr = 0; /* Current position in directory stack */
static char
attribs[] = { "RHSVDA" }; /* Letters for attributes */
static char help_text[] = { "\n\
Displays or changes file attributes.\n\n\
ATTRIB [+/-RASH ...] [[drive:][path]filename] [/F][/S][/V]\n\
\n\
+/- Set/Clear attribute(s).\n\
R Read-only file attribute.\n\
A Archive file attribute.\n\
S System file attribute.\n\
H Hidden file attribute.\n\
/F Full listing, show dirs and volume labels\n\
/S Processes files in all subdirectories.\n\
/V Verbose command operation.\n\n\
Copyright 1995 Dave Dunfield - Freely Distributable.\n" };
/*
* Process all the files in one directory
*/
void process_dir(void)
{
unsigned plen, i, attrs, dirbase;
char name[13], *ptr;
plen = strlen(path);
strcpy(path+plen, pattern);
++dircount;
if(verbose && !set)
printf("\nListing %s\n\n", path);
/* Search for files & handle show/set attributes */
if(!find_first(path, -1, name, &i, &i, &attrs, &i, &i)) do {
if((attrs & (DIRECTORY|VOLUME)) && !full)
continue;
++filecount;
strcpy(path+plen, name);
if(set) { /* Setting attributes */
if(set_attr(path, (attrs & clrmask) | setmask))
printf("%s: Unable to set attributes\n", path); }
else {
i = 0x01;
for(ptr = attribs; *ptr; ++ptr) {
putc((attrs & i) ? *ptr : ' ', stdout);
i <<= 1; }
printf(" %s\n", path); } }
while(!find_next(name, &i, &i, &attrs, &i, &i));
if(subdir) {
dirbase = dirptr;
strcpy(path+plen, "*.*");
if(!find_first(path, -1, name, &i, &i, &attrs, &i, &i)) do {
if(*name == '.')
continue;
if(attrs & DIRECTORY)
strcpy(dirstack[dirptr++], name); }
while(!find_next(name, &i, &i, &attrs, &i, &i));
for(i=dirbase; i < dirptr; ++i) {
strcpy(path+plen, dirstack[i]);
strcat(path, "\\");
process_dir(); }
dirptr = dirbase; }
path[plen] = 0;
}
/*
* Main program - Parse options and call process_dir
*/
main(int argc, char *argv[])
{
int i, j;
char *ptr, *ptr1, c, mode;
/* Parse command options */
for(i=1; (i < argc) && !badopt; ++i) {
ptr = argv[i];
mode = 0;
while(*ptr) switch(c = toupper(*ptr++)) {
case '/' : /* Option switch */
mode = 0;
switch(c = toupper(*ptr++)) {
case 'F' : /* Full listing */
full = -1;
continue;
case 'S' : /* Process subdirs */
subdir = -1;
continue;
case 'V' :
verbose = -1;
continue;
case '?' : /* Help request */
argc = 0;
badopt = -1;
continue; }
printf("Unknown switch: '/%c'\n", c);
badopt = -1;
continue;
case '+' : /* Add these options */
mode = 1;
continue;
case '-' : /* Subtract these options */
mode = -1;
continue;
default: /* Default */
if(mode) {
set = -1;
ptr1 = attribs;
for(j=1; *ptr1; j <<= 1)
if(*ptr1++ == c)
goto founda;
printf("Unknown attribute bit: '%c'\n", c);
badopt = -1;
founda:
if(mode > 0)
setmask |= j;
else
clrmask &= ~j;
continue; }
if(*pattern) {
printf("Too many file specifications.\n");
badopt = -1; }
else
pattern = ptr-1;
ptr = ""; } }
if(setmask & ~clrmask) {
printf("Cannot Set & Clear same attribute\n");
badopt = -1; }
if((setmask | ~clrmask) & (DIRECTORY|VOLUME)) {
printf("Cannot alter DIRECTORY and VOLUME attributes\n");
badopt = -1; }
if(!argc)
fputs(help_text, stdout);
if(badopt)
exit(-1);
/* Separate directory and path, establish defaults */
strcpy(path, pattern);
for(i=j=0; c = path[i]; ++i) switch(c) {
case ':' :
case '\\' :
j = i+1; }
if(j) {
path[j] = 0;
pattern += j; }
else {
*path = get_drive() + 'A';
strcpy(path+1, ":\\");
if(getdir(path+3))
*path = 0;
else if(path[3])
strcat(path, "\\"); }
if(!*pattern)
pattern = "*.*";
process_dir();
/* Display result messages */
if(!filecount)
printf("File not found - %s\n", pattern);
else if(verbose) {
putc('\n', stdout);
if(subdir)
printf("%u directories and ", dircount);
printf("%u files were processed.\n", filecount); }
}