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 >
C/C++ Source or Header  |  1994-01-01  |  6KB  |  223 lines

  1. /*
  2.  * ATTRIB command for MS-DOS
  3.  *
  4.  * This is an ATTRIB command that pretty much works exactly like the
  5.  * one from Microsoft with the following enhancements:
  6.  *
  7.  * More flexible parsing: accepts +RS +R-S +RS-HA -H/S etc.
  8.  * Parameters can be in any order.
  9.  *
  10.  * Better error reporting, instead of just saying parameters are wrong,
  11.  * it tells you exactly what it didn't like.
  12.  * 
  13.  * /V option for verbose output
  14.  * /F option for "full" listing. Shows directories & volume labels
  15.  *
  16.  * Walks the directory tree in a more natural manner. Ie, processes
  17.  * the files in a directory FIRST, then moves on to the subdirs.
  18.  *
  19.  * Unambiguous specification of directories. ie: append '\' to a directory
  20.  * name, otherwise it is assumed to be a filename. Microsofts ATTRIB will
  21.  * happily change all files in a directory if you happen to mistype it's
  22.  * name instead of a filename.
  23.  *
  24.  * Copyright 1995 Dave Dunfield
  25.  * Freely Distributable.
  26.  */
  27.  
  28. #include <stdio.h>
  29. #include <file.h>
  30.  
  31. #define    DIRS    500        /* Depth of directory stacking */
  32.  
  33. char
  34.     *pattern = "",        /* Pattern we are searching for */
  35.     path[66],            /* Path we are searching */
  36.     subdir = 0,            /* Indicates we are to search sub-dirs */
  37.     verbose = 0,        /* Be talky */
  38.     full = 0,            /* Full listing */
  39.     badopt = 0,            /* A bad command option was detected */
  40.     set = 0,            /* Indicates we are setting attributes */
  41.     dirstack[DIRS][13];    /* Stack of subdirectory names */
  42.  
  43. unsigned
  44.     setmask = 0,        /* Attribute bits to set */
  45.     clrmask = -1,        /* Attribute bits to clear */
  46.     dircount = 0,        /* Count of directories processed */
  47.     filecount = 0,        /* Count of files processed */
  48.     dirptr = 0;            /* Current position in directory stack */
  49.  
  50. static char
  51.     attribs[] = { "RHSVDA" };    /* Letters for attributes */
  52.  
  53. static char help_text[] = { "\n\
  54. Displays or changes file attributes.\n\n\
  55. ATTRIB [+/-RASH ...] [[drive:][path]filename] [/F][/S][/V]\n\
  56. \n\
  57.   +/- Set/Clear attribute(s).\n\
  58.   R   Read-only file attribute.\n\
  59.   A   Archive file attribute.\n\
  60.   S   System file attribute.\n\
  61.   H   Hidden file attribute.\n\
  62.   /F  Full listing, show dirs and volume labels\n\
  63.   /S  Processes files in all subdirectories.\n\
  64.   /V  Verbose command operation.\n\n\
  65. Copyright 1995 Dave Dunfield - Freely Distributable.\n" };
  66.  
  67. /*
  68.  * Process all the files in one directory
  69.  */
  70. void process_dir(void)
  71. {
  72.     unsigned plen, i, attrs, dirbase;
  73.     char name[13], *ptr;
  74.  
  75.     plen = strlen(path);
  76.     strcpy(path+plen, pattern);
  77.     ++dircount;
  78.  
  79.     if(verbose && !set)
  80.         printf("\nListing %s\n\n", path);
  81.  
  82.     /* Search for files & handle show/set attributes */
  83.     if(!find_first(path, -1, name, &i, &i, &attrs, &i, &i)) do {
  84.         if((attrs & (DIRECTORY|VOLUME)) && !full)
  85.             continue;
  86.         ++filecount;
  87.         strcpy(path+plen, name);
  88.         if(set) {    /* Setting attributes */
  89.             if(set_attr(path, (attrs & clrmask) | setmask)) 
  90.                 printf("%s: Unable to set attributes\n", path); }
  91.         else {
  92.             i = 0x01;
  93.             for(ptr = attribs; *ptr; ++ptr) {
  94.                 putc((attrs & i) ? *ptr : ' ', stdout);
  95.                 i <<= 1; }
  96.             printf("       %s\n", path); } }
  97.         while(!find_next(name, &i, &i, &attrs, &i, &i));
  98.  
  99.     if(subdir) {
  100.         dirbase = dirptr;
  101.         strcpy(path+plen, "*.*");
  102.         if(!find_first(path, -1, name, &i, &i, &attrs, &i, &i)) do {
  103.             if(*name == '.')
  104.                 continue;
  105.             if(attrs & DIRECTORY)
  106.                 strcpy(dirstack[dirptr++], name); }
  107.         while(!find_next(name, &i, &i, &attrs, &i, &i));
  108.  
  109.         for(i=dirbase; i < dirptr; ++i) {
  110.             strcpy(path+plen, dirstack[i]);
  111.             strcat(path, "\\");
  112.             process_dir(); }
  113.         dirptr = dirbase; }
  114.  
  115.     path[plen] = 0;
  116. }
  117.  
  118. /*
  119.  * Main program - Parse options and call process_dir
  120.  */
  121. main(int argc, char *argv[])
  122. {
  123.     int i, j;
  124.     char *ptr, *ptr1, c, mode;
  125.  
  126.     /* Parse command options */
  127.     for(i=1; (i < argc) && !badopt; ++i) {
  128.         ptr = argv[i];
  129.         mode = 0;
  130.         while(*ptr) switch(c = toupper(*ptr++)) {
  131.             case '/' :        /* Option switch */
  132.                 mode = 0;
  133.                 switch(c = toupper(*ptr++)) {
  134.                     case 'F' :    /* Full listing */
  135.                         full = -1;
  136.                         continue;
  137.                     case 'S' :    /* Process subdirs */
  138.                         subdir = -1;
  139.                         continue;
  140.                     case 'V' :
  141.                         verbose = -1;
  142.                         continue;
  143.                     case '?' :    /* Help request */
  144.                         argc = 0;
  145.                         badopt = -1;
  146.                         continue; }
  147.                 printf("Unknown switch: '/%c'\n", c);
  148.                 badopt = -1;
  149.                 continue;
  150.             case '+' :            /* Add these options */
  151.                 mode = 1;
  152.                 continue;
  153.             case '-' :            /* Subtract these options */
  154.                 mode = -1;
  155.                 continue;
  156.             default:            /* Default */
  157.                 if(mode) {
  158.                     set = -1;
  159.                     ptr1 = attribs;
  160.                     for(j=1; *ptr1; j <<= 1)
  161.                         if(*ptr1++ == c)
  162.                             goto founda;
  163.                     printf("Unknown attribute bit: '%c'\n", c);
  164.                     badopt = -1;
  165.                 founda:
  166.                     if(mode > 0)
  167.                         setmask |= j;
  168.                     else
  169.                         clrmask &= ~j;
  170.                     continue; }
  171.                 if(*pattern) {
  172.                     printf("Too many file specifications.\n");
  173.                     badopt = -1; }
  174.                 else
  175.                     pattern = ptr-1;
  176.                 ptr = ""; } }
  177.  
  178.     if(setmask & ~clrmask) {
  179.         printf("Cannot Set & Clear same attribute\n");
  180.         badopt = -1; }
  181.  
  182.     if((setmask | ~clrmask) & (DIRECTORY|VOLUME)) {
  183.         printf("Cannot alter DIRECTORY and VOLUME attributes\n");
  184.         badopt = -1; }
  185.  
  186.     if(!argc)
  187.         fputs(help_text, stdout);
  188.  
  189.     if(badopt)
  190.         exit(-1);
  191.  
  192.     /* Separate directory and path, establish defaults */
  193.     strcpy(path, pattern);
  194.     for(i=j=0; c = path[i]; ++i) switch(c) {
  195.         case ':' :
  196.         case '\\' :
  197.             j = i+1; }
  198.     if(j) {
  199.         path[j] = 0;
  200.         pattern += j; }
  201.     else {
  202.         *path = get_drive() + 'A';
  203.         strcpy(path+1, ":\\");
  204.         if(getdir(path+3))
  205.             *path = 0;
  206.         else if(path[3])
  207.             strcat(path, "\\"); }
  208.  
  209.     if(!*pattern)
  210.         pattern = "*.*";
  211.  
  212.     process_dir();
  213.  
  214.     /* Display result messages */
  215.     if(!filecount)
  216.         printf("File not found - %s\n", pattern);
  217.     else if(verbose) {
  218.         putc('\n', stdout);
  219.         if(subdir)
  220.             printf("%u directories and ", dircount);
  221.         printf("%u files were processed.\n", filecount); }
  222. }
  223.