summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/SNIP/chmod.c
diff options
context:
space:
mode:
Diffstat (limited to 'reference/C/CONTRIB/SNIP/chmod.c')
-rwxr-xr-xreference/C/CONTRIB/SNIP/chmod.c224
1 files changed, 224 insertions, 0 deletions
diff --git a/reference/C/CONTRIB/SNIP/chmod.c b/reference/C/CONTRIB/SNIP/chmod.c
new file mode 100755
index 0000000..d74bef8
--- /dev/null
+++ b/reference/C/CONTRIB/SNIP/chmod.c
@@ -0,0 +1,224 @@
+/*
+** CHMOD.C - Retrieve or change a DOS file's attributes
+**
+** public domain demo by Bob Stout
+**
+** Notes: To expand command line arguments with wildcards,
+** TC/TC++/BC++ - Link in WILDARGS.OBJ.
+** MSC/QC - Link in SETARGV.OBJ.
+** ZTC/C++ - Link in _MAINx.OBJ, where 'x' is the memory model.
+**
+** Allows file list(s) using standard "@file_list_name" convention.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dos.h>
+#include <ctype.h>
+#include <string.h>
+
+#define LAST_CHAR(s) (s)[strlen(s)-1]
+
+#if defined(__TURBOC__)
+ #include <io.h>
+ #define FAR far
+#else
+ #include <stdarg.h>
+
+ #define BOOL(x) (!(!(x)))
+ #define FAR _far
+
+ #if (defined(_MSC_VER) && (_MSC_VER >= 700)) || (defined(__SC__))
+ // Make FP_xxx macros lvalues as in older versions
+ #undef FP_SEG
+ #undef FP_OFF
+ #define FP_SEG(fp) ((unsigned)((unsigned long)(fp) >> 16))
+ #define FP_OFF(fp) ((unsigned)(fp && 0xffff))
+ #endif
+
+ int _chmod(const char *path, int func, ...)
+ {
+ union REGS regs;
+ struct SREGS sregs;
+ int atr = 0;
+ va_list args;
+
+ if (0 != (func = BOOL(func)))
+ {
+ va_start(args, func);
+ atr = va_arg(args, int);
+ }
+ regs.x.ax = 0x4300 + func;
+ regs.x.dx = FP_OFF((char FAR *)path);
+ regs.x.cx = atr;
+ segread(&sregs);
+ sregs.ds = FP_SEG((char FAR *)path);
+ intdosx(&regs, &regs, &sregs);
+ if (regs.x.cflag)
+ return -1;
+ if (func)
+ return atr;
+ else return regs.x.cx;
+ }
+
+ #ifndef FA_RDONLY
+ #define FA_RDONLY _A_RDONLY
+ #endif
+
+ #ifndef FA_HIDDEN
+ #define FA_HIDDEN _A_HIDDEN
+ #endif
+
+ #ifndef FA_SYSTEM
+ #define FA_SYSTEM _A_SYSTEM
+ #endif
+
+ #ifndef FA_ARCH
+ #define FA_ARCH _A_ARCH
+ #endif
+
+ #ifndef FA_LABEL
+ #define FA_LABEL _A_VOLID
+ #endif
+
+ #ifndef FA_DIREC
+ #define FA_DIREC _A_SUBDIR
+ #endif
+#endif
+
+int attrib, /* Set up new attributes here */
+ atr_setmask = 0,
+ atr_clrmask = -1,
+ flag = 0; /* Passed as func to _chmod() */
+
+void usage(void) /* Tell 'em they messed up */
+{
+ puts("Usage: CHMOD file [file [...file] [+switches] [-switches]");
+ puts("Where switches are one or more of:");
+ puts(" A: Archive");
+ puts(" R: Read only");
+ puts(" H: Hidden");
+ puts(" S: System");
+ puts("File lists may be specified with \"@file_list_name\"");
+ puts("With no switches, diplays current attributes.");
+ puts("Displayed attributes are as above plus:");
+ puts(" D: Subdirectory");
+ puts(" V: Volume label");
+ exit(1);
+}
+
+void setattr(char atr) /* Set bits in attribute */
+{
+ switch (toupper(atr))
+ {
+ case 'A':
+ atr_setmask |= FA_ARCH;
+ break;
+ case 'R':
+ atr_setmask |= FA_RDONLY;
+ break;
+ case 'S':
+ atr_setmask |= FA_SYSTEM;
+ break;
+ case 'H':
+ atr_setmask |= FA_HIDDEN;
+ break;
+ default:
+ usage();
+ }
+}
+
+void clrattr(char atr) /* Clear bits in attribute */
+{
+ switch (toupper(atr))
+ {
+ case 'A':
+ atr_clrmask &= ~FA_ARCH;
+ break;
+ case 'R':
+ atr_clrmask &= ~FA_RDONLY;
+ break;
+ case 'S':
+ atr_clrmask &= ~FA_SYSTEM;
+ break;
+ case 'H':
+ atr_clrmask &= ~FA_HIDDEN;
+ break;
+ default:
+ usage();
+ }
+}
+
+void show_atr(char *path)
+{
+ char astr[7], *ptr;
+
+ if (-1 == (attrib = _chmod(strupr(path), 0)))
+ {
+ATR_ERR: printf("\aCHMOD: Error! (file: %s)", path);
+ exit(-1);
+ }
+ attrib |= atr_setmask;
+ attrib &= atr_clrmask;
+ if (-1 == (attrib = _chmod(path, flag, attrib)))
+ goto ATR_ERR;
+ ptr = astr;
+ *ptr++ = (char)((attrib & FA_ARCH) ? 'A' : '.');
+ *ptr++ = (char)((attrib & FA_RDONLY) ? 'R' : '.');
+ *ptr++ = (char)((attrib & FA_SYSTEM) ? 'S' : '.');
+ *ptr++ = (char)((attrib & FA_HIDDEN) ? 'H' : '.');
+ *ptr++ = (char)((attrib & FA_DIREC) ? 'D' : '.');
+ *ptr++ = (char)((attrib & FA_LABEL) ? 'V' : '.');
+ *ptr = '\0';
+ printf("%-15s %s\n", path, astr);
+}
+
+int main (int argc, char *argv[])
+{
+ int i, j;
+
+ if (2 > argc)
+ usage();
+ for (i = 1; i < argc; ++i) /* Build attribute masks */
+ {
+ switch (*argv[i])
+ {
+ case '+':
+ for (j = 1; argv[i][j]; ++j)
+ setattr(argv[i][j]);
+ flag = 1;
+ break;
+ case '-':
+ for (j = 1; argv[i][j]; ++j)
+ clrattr(argv[i][j]);
+ flag = 1;
+ break;
+ default:
+ break; /* Assume it's a file name */
+ }
+ }
+ for (i = 1; i < argc; ++i) /* Scan filenames */
+ {
+ if (strchr("+-", *argv[i]))
+ continue;
+ if ('@' == *argv[i])
+ {
+ FILE *fp;
+ char buf[256], *ptr = &argv[i][1];
+
+ if (NULL == (fp = fopen(ptr, "r")))
+ {
+ printf("\aCHMOD: Error opening %s\n", ptr);
+ return -1;
+ }
+ while (NULL != fgets(buf, 255, fp))
+ {
+ LAST_CHAR(buf) = '\0'; /* Strip '\n' */
+ show_atr(buf);
+ }
+ fclose(fp);
+ }
+ else show_atr(argv[i]);
+ }
+ return 0;
+}