home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_C / SNIP9404.ZIP / CHMOD.C < prev    next >
C/C++ Source or Header  |  1994-04-03  |  6KB  |  225 lines

  1. /*
  2. **  CHMOD.C - Retrieve or change a DOS file's attributes
  3. **
  4. **  public domain demo by Bob Stout
  5. **
  6. **  Notes: To expand command line arguments with wildcards,
  7. **         TC/TC++/BC++  - Link in WILDARGS.OBJ.
  8. **         MSC/QC        - Link in SETARGV.OBJ.
  9. **         ZTC/C++       - Link in _MAINx.OBJ, where 'x' is the memory model.
  10. **
  11. **         Allows file list(s) using standard "@file_list_name" convention.
  12. */
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <dos.h>
  17. #include <ctype.h>
  18. #include <string.h>
  19.  
  20. #define LAST_CHAR(s) (s)[strlen(s)-1]
  21.  
  22. #if defined(__TURBOC__)
  23.  #include <io.h>
  24.  #define FAR far
  25. #else
  26.  #include <stdarg.h>
  27.  
  28.  #define BOOL(x) (!(!(x)))
  29.  #define FAR _far
  30.  
  31.  #if (defined(_MSC_VER) && (_MSC_VER >= 700)) || (defined(__SC__))
  32.   // Make FP_xxx macros lvalues as in older versions
  33.   #undef FP_SEG
  34.   #undef FP_OFF
  35.   #define FP_SEG(fp)    ((unsigned)((unsigned long)(fp) >> 16))
  36.   #define FP_OFF(fp)    ((unsigned)(fp && 0xffff))
  37.  #endif
  38.  
  39.  int _chmod(const char *path, int func, ...)
  40.  {
  41.        union REGS regs;
  42.        struct SREGS sregs;
  43.        int atr = 0;
  44.        va_list args;
  45.  
  46.        if (0 != (func = BOOL(func)))
  47.        {
  48.             va_start(args, func);
  49.             atr = va_arg(args, int);
  50.        }
  51.        regs.x.ax = 0x4300 + func;
  52.        regs.x.dx = FP_OFF((char FAR *)path);
  53.        regs.x.cx = atr;
  54.        segread(&sregs);
  55.        sregs.ds  = FP_SEG((char FAR *)path);
  56.        intdosx(®s, ®s, &sregs);
  57.        if (regs.x.cflag)
  58.             return -1;
  59.        if (func)
  60.             return atr;
  61.        else return regs.x.cx;
  62.  }
  63.  
  64.  #ifndef FA_RDONLY
  65.   #define FA_RDONLY _A_RDONLY
  66.  #endif
  67.  
  68.  #ifndef FA_HIDDEN
  69.   #define FA_HIDDEN _A_HIDDEN
  70.  #endif
  71.  
  72.  #ifndef FA_SYSTEM
  73.   #define FA_SYSTEM _A_SYSTEM
  74.  #endif
  75.  
  76.  #ifndef FA_ARCH
  77.   #define FA_ARCH   _A_ARCH
  78.  #endif
  79.  
  80.  #ifndef FA_LABEL
  81.   #define FA_LABEL  _A_VOLID
  82.  #endif
  83.  
  84.  #ifndef FA_DIREC
  85.   #define FA_DIREC  _A_SUBDIR
  86.  #endif
  87. #endif
  88.  
  89. int attrib,                   /* Set up new attributes here             */
  90.     atr_setmask = 0,
  91.     atr_clrmask = -1,
  92.     flag = 0;                 /* Passed as func to _chmod()             */
  93.  
  94. void usage(void)              /* Tell 'em they messed up                */
  95. {
  96.       puts("Usage: CHMOD file [file [...file] [+switches] [-switches]");
  97.       puts("Where switches are one or more of:");
  98.       puts("    A: Archive");
  99.       puts("    R: Read only");
  100.       puts("    H: Hidden");
  101.       puts("    S: System");
  102.       puts("File lists may be specified with \"@file_list_name\"");
  103.       puts("With no switches, diplays current attributes.");
  104.       puts("Displayed attributes are as above plus:");
  105.       puts("    D: Subdirectory");
  106.       puts("    V: Volume label");
  107.       exit(1);
  108. }
  109.  
  110. void setattr(char atr)        /* Set bits in attribute                  */
  111. {
  112.       switch (toupper(atr))
  113.       {
  114.       case 'A':
  115.             atr_setmask |= FA_ARCH;
  116.             break;
  117.       case 'R':
  118.             atr_setmask |= FA_RDONLY;
  119.             break;
  120.       case 'S':
  121.             atr_setmask |= FA_SYSTEM;
  122.             break;
  123.       case 'H':
  124.             atr_setmask |= FA_HIDDEN;
  125.             break;
  126.       default:
  127.             usage();
  128.       }
  129. }
  130.  
  131. void clrattr(char atr)        /* Clear bits in attribute                */
  132. {
  133.       switch (toupper(atr))
  134.       {
  135.       case 'A':
  136.             atr_clrmask &= ~FA_ARCH;
  137.             break;
  138.       case 'R':
  139.             atr_clrmask &= ~FA_RDONLY;
  140.             break;
  141.       case 'S':
  142.             atr_clrmask &= ~FA_SYSTEM;
  143.             break;
  144.       case 'H':
  145.             atr_clrmask &= ~FA_HIDDEN;
  146.             break;
  147.       default:
  148.             usage();
  149.       }
  150. }
  151.  
  152. void show_atr(char *path)
  153. {
  154.       char astr[7], *ptr;
  155.  
  156.       if (-1 == (attrib = _chmod(strupr(path), 0)))
  157.       {
  158. ATR_ERR:    printf("\aCHMOD: Error! (file: %s)", path);
  159.             exit(-1);
  160.       }
  161.       attrib |= atr_setmask;
  162.       attrib &= atr_clrmask;
  163.       if (-1 == (attrib = _chmod(path, flag, attrib)))
  164.             goto ATR_ERR;
  165.       ptr = astr;
  166.       *ptr++ = (char)((attrib & FA_ARCH)   ? 'A' : '.');
  167.       *ptr++ = (char)((attrib & FA_RDONLY) ? 'R' : '.');
  168.       *ptr++ = (char)((attrib & FA_SYSTEM) ? 'S' : '.');
  169.       *ptr++ = (char)((attrib & FA_HIDDEN) ? 'H' : '.');
  170.       *ptr++ = (char)((attrib & FA_DIREC)  ? 'D' : '.');
  171.       *ptr++ = (char)((attrib & FA_LABEL)  ? 'V' : '.');
  172.       *ptr = '\0';
  173.       printf("%-15s %s\n", path, astr);
  174. }
  175.  
  176. int main (int argc, char *argv[])
  177. {
  178.       int i, j;
  179.  
  180.       if (2 > argc)
  181.             usage();
  182.       for (i = 1; i < argc; ++i)    /* Build attribute masks            */
  183.       {
  184.             switch (*argv[i])
  185.             {
  186.             case '+':
  187.                   for (j = 1; argv[i][j]; ++j)
  188.                         setattr(argv[i][j]);
  189.                   flag = 1;
  190.                   break;
  191.             case '-':
  192.                   for (j = 1; argv[i][j]; ++j)
  193.                         clrattr(argv[i][j]);
  194.                   flag = 1;
  195.                   break;
  196.             default:
  197.                   break;            /* Assume it's a file name          */
  198.             }
  199.       }
  200.       for (i = 1; i < argc; ++i)    /* Scan filenames                   */
  201.       {
  202.             if (strchr("+-", *argv[i]))
  203.                   continue;
  204.             if ('@' == *argv[i])
  205.             {
  206.                   FILE *fp;
  207.                   char buf[256], *ptr = &argv[i][1];
  208.  
  209.                   if (NULL == (fp = fopen(ptr, "r")))
  210.                   {
  211.                         printf("\aCHMOD: Error opening %s\n", ptr);
  212.                         return -1;
  213.                   }
  214.                   while (NULL != fgets(buf, 255, fp))
  215.                   {
  216.                         LAST_CHAR(buf) = '\0';  /* Strip '\n'           */
  217.                         show_atr(buf);
  218.                   }
  219.                   fclose(fp);
  220.             }
  221.             else  show_atr(argv[i]);
  222.       }
  223.       return 0;
  224. }
  225.