diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c7f42b..ce128c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,7 @@ set(MARS_DOSUTILS_PUBLIC_TOOLS mapdel logout slist + flag capture endcap ) @@ -42,6 +43,7 @@ if(MARS_NWE_BUILD_DOSUTILS) login.c map.c slist.c + flag.c nwcrypt.c nwdebug.c nwtests.c diff --git a/flag.c b/flag.c new file mode 100644 index 0000000..b2467e2 --- /dev/null +++ b/flag.c @@ -0,0 +1,252 @@ +/* flag.c - Novell FLAG-like DOS utility, stage 1 */ + +#include "net.h" +#include + +#ifndef _A_NORMAL +#define _A_NORMAL 0x00 +#endif +#ifndef _A_RDONLY +#define _A_RDONLY 0x01 +#endif +#ifndef _A_HIDDEN +#define _A_HIDDEN 0x02 +#endif +#ifndef _A_SYSTEM +#define _A_SYSTEM 0x04 +#endif +#ifndef _A_SUBDIR +#define _A_SUBDIR 0x10 +#endif +#ifndef _A_ARCH +#define _A_ARCH 0x20 +#endif + +static int flag_same(char *a, char *b) +{ + while (*a || *b) { + int ca = *a++; + int cb = *b++; + if (ca >= 'a' && ca <= 'z') ca -= 32; + if (cb >= 'a' && cb <= 'z') cb -= 32; + if (ca != cb) return(0); + } + return(1); +} + +static void flag_help(void) +{ + fprintf(stdout, "USAGE: FLAG [path [ option | [+|-] attribute(s) ] [SUB]]\n"); + fprintf(stdout, "\n"); + fprintf(stdout, "386 Attributes:\n"); + fprintf(stdout, "--------------\n"); + fprintf(stdout, "\n"); + fprintf(stdout, "RO Read Only\n"); + fprintf(stdout, "RW Read Write\n"); + fprintf(stdout, "S Sharable\n"); + fprintf(stdout, "H Hidden\n"); + fprintf(stdout, "Sy System\n"); + fprintf(stdout, "T Transactional\n"); + fprintf(stdout, "P Purge\n"); + fprintf(stdout, "A Archive Needed\n"); + fprintf(stdout, "RA Read Audit\n"); + fprintf(stdout, "WA Write Audit\n"); + fprintf(stdout, "CI Copy Inhibit\n"); + fprintf(stdout, "DI Delete Inhibit\n"); + fprintf(stdout, "RI Rename Inhibit\n"); + fprintf(stdout, "\n"); + fprintf(stdout, "All All\n"); + fprintf(stdout, "N Normal\n"); + fprintf(stdout, "SUB\n"); +} + +static int flag_attr_mask(char *s, unsigned *setbits, unsigned *clearbits) +{ + int set = 1; + char *p = s; + + if (*p == '+') { + set = 1; + p++; + } else if (*p == '-') { + set = 0; + p++; + } + + if (!*p) return(-1); + + if (flag_same(p, "RO")) { + if (set) *setbits |= _A_RDONLY; + else *clearbits |= _A_RDONLY; + } else if (flag_same(p, "RW")) { + *clearbits |= _A_RDONLY; + } else if (flag_same(p, "H")) { + if (set) *setbits |= _A_HIDDEN; + else *clearbits |= _A_HIDDEN; + } else if (flag_same(p, "SY") || flag_same(p, "SYS") || flag_same(p, "SYSTEM")) { + if (set) *setbits |= _A_SYSTEM; + else *clearbits |= _A_SYSTEM; + } else if (flag_same(p, "A")) { + if (set) *setbits |= _A_ARCH; + else *clearbits |= _A_ARCH; + } else if (flag_same(p, "N") || flag_same(p, "NORMAL")) { + *clearbits |= (_A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH); + } else if (flag_same(p, "ALL")) { + /* + * Stage 1: Only DOS-visible bits are supported. NetWare-only bits + * like S/T/P/RA/WA/CI/DI/RI need NCP support later. + */ + *setbits |= (_A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH); + } else if (flag_same(p, "S") || flag_same(p, "T") || flag_same(p, "P") || + flag_same(p, "RA") || flag_same(p, "WA") || flag_same(p, "CI") || + flag_same(p, "DI") || flag_same(p, "RI")) { + fprintf(stderr, "Attribute not supported on this version of NetWare\n"); + return(1); + } else { + fprintf(stderr, "Unknown attribute encountered in command line.\n"); + return(-1); + } + + return(0); +} + +static void flag_print_attrs(unsigned attr) +{ + fprintf(stdout, "[ "); + fprintf(stdout, "%s ", (attr & _A_RDONLY) ? "RO" : "Rw"); + fprintf(stdout, "- "); /* S Shareable */ + fprintf(stdout, "%c ", (attr & _A_HIDDEN) ? 'H' : '-'); + fprintf(stdout, "%s ", (attr & _A_SYSTEM) ? "Sy" : "-"); + fprintf(stdout, "- "); /* T */ + fprintf(stdout, "- "); /* P */ + fprintf(stdout, "%c ", (attr & _A_ARCH) ? 'A' : '-'); + fprintf(stdout, "-- "); /* RA */ + fprintf(stdout, "-- "); /* WA */ + fprintf(stdout, "-- "); /* CI */ + fprintf(stdout, "-- "); /* DI */ + fprintf(stdout, "-- "); /* RI */ + fprintf(stdout, "]"); +} + +static void flag_display_one(char *name, unsigned attr) +{ + fprintf(stdout, " %-23s ", name); + flag_print_attrs(attr); + fprintf(stdout, "\n"); +} + +static int flag_has_wildcards(char *s) +{ + while (*s) { + if (*s == '*' || *s == '?') return(1); + s++; + } + return(0); +} + +static int flag_list(char *pattern) +{ + struct find_t ff; + unsigned findattr = _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH; + int found = 0; + + if (_dos_findfirst(pattern, findattr, &ff)) + return(-1); + + do { + if (!(ff.attrib & _A_SUBDIR)) { + flag_display_one(ff.name, ff.attrib); + found++; + } + } while (!_dos_findnext(&ff)); + + return(found); +} + +static int flag_apply(char *pattern, unsigned setbits, unsigned clearbits) +{ + struct find_t ff; + unsigned findattr = _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH; + int changed = 0; + + if (_dos_findfirst(pattern, findattr, &ff)) + return(-1); + + do { + unsigned attr; + unsigned newattr; + char fname[260]; + + if (ff.attrib & _A_SUBDIR) continue; + + strmaxcpy(fname, ff.name, sizeof(fname) - 1); + + if (_dos_getfileattr(fname, &attr)) { + attr = ff.attrib; + } + + newattr = (attr | setbits) & ~clearbits; + + if (newattr != attr) { + if (!_dos_setfileattr(fname, newattr)) + changed++; + else + fprintf(stderr, "You don't have rights to change : %s\n", fname); + } + + } while (!_dos_findnext(&ff)); + + return(changed); +} + +int func_flag(int argc, char *argv[], int mode) +{ + char *path = "*.*"; + int i; + unsigned setbits = 0; + unsigned clearbits = 0; + int have_change = 0; + int rc; + + (void)mode; + + if (argc > 1 && (flag_same(argv[1], "/?") || flag_same(argv[1], "-?") || + flag_same(argv[1], "?"))) { + flag_help(); + return(0); + } + + if (argc > 1) { + path = argv[1]; + if (flag_same(path, "SUB")) path = "*.*"; + } + + for (i = 2; i < argc; i++) { + if (flag_same(argv[i], "SUB")) continue; + + rc = flag_attr_mask(argv[i], &setbits, &clearbits); + if (rc < 0) return(1); + if (rc > 0) continue; + have_change = 1; + } + + if (have_change) { + rc = flag_apply(path, setbits, clearbits); + if (rc < 0) { + fprintf(stderr, "Files could not be found with pattern \"%s\"\n", path); + return(1); + } + + if (rc) fprintf(stdout, "Changed some\n"); + else fprintf(stdout, "None changed\n"); + return(0); + } + + rc = flag_list(path); + if (rc < 0) { + fprintf(stderr, "Files could not be found with pattern \"%s\"\n", path); + return(1); + } + + return(0); +} diff --git a/net.c b/net.c index 4d66987..9e403a5 100644 --- a/net.c +++ b/net.c @@ -34,6 +34,7 @@ static struct s_net_functions { {"PATHDEL","removes search path" , func_path , 1}, {"PATHINS","insert search path" , func_path , 2}, {"LOGOUT", "logout from server", func_logout , 0}, +{"FLAG", "display or modify file attributes", func_flag , 0}, {"SLIST", "list servers", func_slist , 0}, {"PASSWD", "change password", func_passwd , 0}, #if 1 diff --git a/net.h b/net.h index 85f3bbe..d6041c2 100644 --- a/net.h +++ b/net.h @@ -252,6 +252,9 @@ extern int func_tests (int argc, char *argv[], int mode); /* capture.c */ extern int func_capture(int argc, char *argv[], int mode); +/* flag.c */ +extern int func_flag (int argc, char *argv[], int mode); + extern int ncp_17_37(uint32 last_id, uint16 objtyp, uint8 *pattern, BINDERY_OBJECT *target);