Move common DOS utility helper code into tools.c and expose it through net.h. This removes duplicated command-local helpers from GRANT, RIGHTS, FLAG, FLAGDIR and the trustee helper layer. The shared helpers cover case-insensitive argument comparison, help and option detection, /FILES and /SUBDIRS parsing, current network directory handle lookup, current volume prefix formatting, uppercase DOS path copying, basename/header-path handling, wildcard detection and simple path joining/splitting. Keep the command frontends smaller and less coupled so the current multicall utility can later be split into smaller grouped multicall binaries, such as trustee tools, login/session tools and file/flag tools. Update the DOS utilities README for the newer Client32 and trustee commands. Document RIGHTS, GRANT, REVOKE and REMOVE in the status, feature, command and install sections. Add command reference entries for the trustee tools, including Novell-style syntax, supported rights, recursive/file options and missing-trustee behavior. Also mention the shared trustee helper layer and common tools.c helpers used by the newer command frontends.
322 lines
7.5 KiB
C
322 lines
7.5 KiB
C
/* flagdir.c - Novell FLAGDIR-like DOS utility, Client32 version */
|
|
|
|
#include "net.h"
|
|
#include "c32ncp.h"
|
|
#include <dos.h>
|
|
|
|
#define FD_NWFA_H 0x00000002UL
|
|
#define FD_NWFA_SY 0x00000004UL
|
|
#define FD_NWFA_P 0x00010000UL
|
|
#define FD_NWFA_RI 0x00020000UL
|
|
#define FD_NWFA_DI 0x00040000UL
|
|
|
|
#define FD_DIR_BITS (FD_NWFA_H | FD_NWFA_SY | FD_NWFA_P | FD_NWFA_RI | FD_NWFA_DI)
|
|
|
|
#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 fd_current_display_path(uint8 dhandle, char *out, int max)
|
|
{
|
|
char path[260];
|
|
char *p;
|
|
|
|
if (!out || max < 2)
|
|
return(-1);
|
|
|
|
out[0] = '\0';
|
|
path[0] = '\0';
|
|
|
|
if (get_dir_path(dhandle, path) || !path[0])
|
|
return(-1);
|
|
|
|
p = strchr(path, ':');
|
|
if (p)
|
|
p++;
|
|
else
|
|
p = path;
|
|
|
|
if (!*p)
|
|
out[0] = '\0';
|
|
else
|
|
strmaxcpy(out, p, max - 1);
|
|
|
|
return(0);
|
|
}
|
|
|
|
static void fd_help(void)
|
|
{
|
|
fprintf(stdout, "386 Usage: Flagdir [path [option...]]\n");
|
|
fprintf(stdout, "Options: Normal\n");
|
|
fprintf(stdout, " System\n");
|
|
fprintf(stdout, " Hidden\n");
|
|
fprintf(stdout, " Deleteinhibit\n");
|
|
fprintf(stdout, " Purge\n");
|
|
fprintf(stdout, " Renameinhibit\n");
|
|
}
|
|
|
|
static int fd_attr_mask(char *s, uint32 *setbits, uint32 *clearbits)
|
|
{
|
|
if (tool_strsame(s, "N") || tool_strsame(s, "NORMAL")) {
|
|
*clearbits |= FD_DIR_BITS;
|
|
} else if (tool_strsame(s, "S") || tool_strsame(s, "SY") ||
|
|
tool_strsame(s, "SYS") || tool_strsame(s, "SYSTEM")) {
|
|
*setbits |= FD_NWFA_SY;
|
|
} else if (tool_strsame(s, "H") || tool_strsame(s, "HIDDEN")) {
|
|
*setbits |= FD_NWFA_H;
|
|
} else if (tool_strsame(s, "DI") || tool_strsame(s, "DELETEINHIBIT")) {
|
|
*setbits |= FD_NWFA_DI;
|
|
} else if (tool_strsame(s, "P") || tool_strsame(s, "PURGE")) {
|
|
*setbits |= FD_NWFA_P;
|
|
} else if (tool_strsame(s, "RI") || tool_strsame(s, "RENAMEINHIBIT")) {
|
|
*setbits |= FD_NWFA_RI;
|
|
} else if (tool_strsame(s, "PRIVATE") || tool_strsame(s, "PR")) {
|
|
fprintf(stderr, "Private is valid on NetWare 2.15 and above, except NetWare 386.\n");
|
|
return(-1);
|
|
} else {
|
|
fprintf(stderr, "Unknown attribute: %s.\n", s);
|
|
return(-1);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
static void fd_print_attrs(uint32 attrs)
|
|
{
|
|
int any = 0;
|
|
|
|
if (!(attrs & FD_DIR_BITS)) {
|
|
fprintf(stdout, "Normal\n");
|
|
return;
|
|
}
|
|
|
|
if (attrs & FD_NWFA_SY) {
|
|
fprintf(stdout, "System");
|
|
any = 1;
|
|
}
|
|
if (attrs & FD_NWFA_H) {
|
|
fprintf(stdout, "%sHidden", any ? " " : "");
|
|
any = 1;
|
|
}
|
|
if (attrs & FD_NWFA_DI) {
|
|
fprintf(stdout, "%sDeleteInhibit", any ? " " : "");
|
|
any = 1;
|
|
}
|
|
if (attrs & FD_NWFA_P) {
|
|
fprintf(stdout, "%sPurge", any ? " " : "");
|
|
any = 1;
|
|
}
|
|
if (attrs & FD_NWFA_RI) {
|
|
fprintf(stdout, "%sRenameInhibit", any ? " " : "");
|
|
any = 1;
|
|
}
|
|
|
|
fprintf(stdout, "\n");
|
|
}
|
|
|
|
static void fd_display_header(char *path)
|
|
{
|
|
char up[260];
|
|
char prefix[90];
|
|
|
|
tool_upcopy(up, path, sizeof(up));
|
|
|
|
if (tool_current_prefix(prefix, sizeof(prefix)))
|
|
prefix[0] = '\0';
|
|
|
|
fprintf(stdout, "%s%s \n", prefix, up);
|
|
}
|
|
|
|
static void fd_display_row(char *name, uint32 attrs)
|
|
{
|
|
char base[260];
|
|
|
|
tool_basename(base, name, sizeof(base));
|
|
fprintf(stdout, " %-12.12s ", base);
|
|
fd_print_attrs(attrs);
|
|
}
|
|
|
|
static void fd_display(char *path, uint32 attrs)
|
|
{
|
|
fd_display_header(path);
|
|
fd_display_row(path, attrs);
|
|
}
|
|
|
|
static int fd_is_directory(char *path)
|
|
{
|
|
struct find_t ff;
|
|
unsigned attr = _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_SUBDIR | _A_ARCH;
|
|
|
|
if (tool_is_current_path(path))
|
|
return(1);
|
|
|
|
if (_dos_findfirst(path, attr, &ff))
|
|
return(0);
|
|
|
|
return((ff.attrib & _A_SUBDIR) != 0);
|
|
}
|
|
|
|
static int fd_obtain(char *path, uint8 dhandle, uint32 *attrs)
|
|
{
|
|
if (c32_ncp87_obtain_rim_attributes(path, (uint16)dhandle,
|
|
attrs, NULL, NULL, NULL) == 0)
|
|
return(0);
|
|
return(-1);
|
|
}
|
|
|
|
static int fd_modify(char *path, uint8 dhandle, uint32 attrs)
|
|
{
|
|
if (c32_ncp87_modify_dos_attributes(path, (uint16)dhandle, attrs,
|
|
NULL, NULL, NULL) == 0)
|
|
return(0);
|
|
return(-1);
|
|
}
|
|
|
|
static int fd_process_one(char *path, char *display_path, uint8 dhandle,
|
|
uint32 setbits, uint32 clearbits,
|
|
int have_change, int show_header)
|
|
{
|
|
char *ncp_path;
|
|
uint32 attrs;
|
|
uint32 newattrs;
|
|
|
|
if (!fd_is_directory(path)) {
|
|
fprintf(stderr, "Directory %s not found.\n", path);
|
|
return(1);
|
|
}
|
|
|
|
ncp_path = tool_is_current_path(path) ? "" : path;
|
|
|
|
if (fd_obtain(ncp_path, dhandle, &attrs)) {
|
|
if (tool_is_current_path(path) && display_path && !display_path[0] &&
|
|
!have_change) {
|
|
attrs = 0;
|
|
} else {
|
|
fprintf(stderr, "Unable to get directory attributes.\n");
|
|
return(1);
|
|
}
|
|
}
|
|
|
|
if (have_change) {
|
|
newattrs = (attrs | setbits) & ~clearbits;
|
|
if (newattrs != attrs) {
|
|
if (fd_modify(ncp_path, dhandle, newattrs)) {
|
|
fprintf(stderr, "Unable to change attributes.\n");
|
|
return(1);
|
|
}
|
|
attrs = newattrs;
|
|
fd_obtain(ncp_path, dhandle, &attrs);
|
|
}
|
|
}
|
|
|
|
if (show_header)
|
|
fd_display(display_path, attrs);
|
|
else
|
|
fd_display_row(display_path, attrs);
|
|
|
|
return(0);
|
|
}
|
|
|
|
static int fd_process_wild(char *spec, uint8 dhandle,
|
|
uint32 setbits, uint32 clearbits,
|
|
int have_change)
|
|
{
|
|
struct find_t ff;
|
|
char dir[260];
|
|
char pat[260];
|
|
char search[260];
|
|
char full[260];
|
|
int found = 0;
|
|
int rc = 0;
|
|
int lines = 0;
|
|
int continuous = 0;
|
|
unsigned attr = _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_SUBDIR | _A_ARCH;
|
|
|
|
tool_parent_pattern(dir, pat, spec, sizeof(dir), sizeof(pat));
|
|
tool_join_path(search, dir, pat, sizeof(search));
|
|
|
|
if (_dos_findfirst(search, attr, &ff) != 0) {
|
|
fprintf(stderr, "Directory %s not found.\n", spec);
|
|
return(1);
|
|
}
|
|
|
|
fd_display_header(spec);
|
|
|
|
do {
|
|
if ((ff.attrib & _A_SUBDIR) && strcmp(ff.name, ".") &&
|
|
strcmp(ff.name, "..")) {
|
|
tool_join_path(full, dir, ff.name, sizeof(full));
|
|
if (fd_process_one(full, ff.name, dhandle, setbits, clearbits,
|
|
have_change, 0))
|
|
rc = 1;
|
|
found++;
|
|
tool_page_line(&lines, &continuous);
|
|
}
|
|
} while (_dos_findnext(&ff) == 0);
|
|
|
|
if (!found) {
|
|
fprintf(stderr, "Directory %s not found.\n", spec);
|
|
return(1);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
int func_flagdir(int argc, char *argv[], int mode)
|
|
{
|
|
char *path = ".";
|
|
char display_path[260];
|
|
uint8 connid = 0;
|
|
uint8 dhandle = 0;
|
|
uint32 setbits = 0;
|
|
uint32 clearbits = 0;
|
|
int have_change = 0;
|
|
int i;
|
|
|
|
(void)mode;
|
|
|
|
if (argc > 1 && (tool_strsame(argv[1], "/?") || tool_strsame(argv[1], "-?") ||
|
|
tool_strsame(argv[1], "?"))) {
|
|
fd_help();
|
|
return(0);
|
|
}
|
|
|
|
if (argc > 1)
|
|
path = argv[1];
|
|
|
|
if (tool_current_dhandle(&connid, &dhandle)) {
|
|
fprintf(stderr, "FlagDir only works on network directories.\n");
|
|
return(1);
|
|
}
|
|
|
|
for (i = 2; i < argc; i++) {
|
|
if (fd_attr_mask(argv[i], &setbits, &clearbits))
|
|
return(1);
|
|
have_change = 1;
|
|
}
|
|
|
|
if (tool_has_wildcards(path))
|
|
return(fd_process_wild(path, dhandle, setbits, clearbits, have_change));
|
|
|
|
if (tool_is_current_path(path)) {
|
|
if (fd_current_display_path(dhandle, display_path, sizeof(display_path)))
|
|
strcpy(display_path, ".");
|
|
} else {
|
|
strmaxcpy(display_path, path, sizeof(display_path) - 1);
|
|
}
|
|
|
|
return(fd_process_one(path, display_path, dhandle,
|
|
setbits, clearbits, have_change, 1));
|
|
}
|