Files
mars-dosutils/grant.c
Mario Fetka c50202e93b dosutils: factor shared helpers and update README
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.
2026-05-24 20:45:56 +02:00

346 lines
8.5 KiB
C

/* grant.c - Novell GRANT-like DOS utility, first Client32 implementation */
#include "net.h"
#include "c32ncp.h"
#define GRANT_BINDERY_USER 0x0001
#define GRANT_BINDERY_GROUP 0x0002
#define NCP_RIGHT_READ 0x0001
#define NCP_RIGHT_WRITE 0x0002
#define NCP_RIGHT_OPEN 0x0004
#define NCP_RIGHT_CREATE 0x0008
#define NCP_RIGHT_DELETE 0x0010
#define NCP_RIGHT_OWNER 0x0020
#define NCP_RIGHT_SEARCH 0x0040
#define NCP_RIGHT_MODIFY 0x0080
#define NCP_RIGHT_SUPER 0x0100
/* Novell GRANT ALL assigns all normal trustee rights, not Supervisor. */
#define NCP_RIGHT_ALL_386 (NCP_RIGHT_READ | NCP_RIGHT_WRITE | \
NCP_RIGHT_CREATE | NCP_RIGHT_DELETE | \
NCP_RIGHT_MODIFY | NCP_RIGHT_SEARCH | \
NCP_RIGHT_OWNER)
static void grant_usage_error(void)
{
fprintf(stdout, "Command line arguments violate grammar defined for GRANT.\n\n");
}
static void grant_usage(void)
{
fprintf(stdout, "Usage: GRANT rightslist* [FOR path] TO [USER | GROUP] name [options]\n");
fprintf(stdout, "Options: /SubDirectories | /Files\n\n");
fprintf(stdout, "386 Rights:\n");
fprintf(stdout, "--------------------\n");
fprintf(stdout, "ALL = All\n");
fprintf(stdout, "N = No Rights\n");
fprintf(stdout, "S = Supervisor\n");
fprintf(stdout, "R = Read\n");
fprintf(stdout, "W = Write\n");
fprintf(stdout, "C = Create\n");
fprintf(stdout, "E = Erase\n");
fprintf(stdout, "M = Modify\n");
fprintf(stdout, "F = File Scan\n");
fprintf(stdout, "A = Access Control\n");
}
static void grant_rights_bracket(uint16 rights, char *out)
{
out[0] = (rights & NCP_RIGHT_SUPER) ? 'S' : ' ';
out[1] = (rights & NCP_RIGHT_READ) ? 'R' : ' ';
out[2] = (rights & NCP_RIGHT_WRITE) ? 'W' : ' ';
out[3] = (rights & NCP_RIGHT_CREATE) ? 'C' : ' ';
out[4] = (rights & NCP_RIGHT_DELETE) ? 'E' : ' ';
out[5] = (rights & NCP_RIGHT_MODIFY) ? 'M' : ' ';
out[6] = (rights & NCP_RIGHT_SEARCH) ? 'F' : ' ';
out[7] = (rights & NCP_RIGHT_OWNER) ? 'A' : ' ';
out[8] = '\0';
}
static void grant_rights_string(uint16 rights, char *out)
{
char *p = out;
if (rights == 0) {
strcpy(out, "N");
return;
}
if ((rights & NCP_RIGHT_ALL_386) == NCP_RIGHT_ALL_386) {
strcpy(out, "ALL");
return;
}
if (rights & NCP_RIGHT_SUPER) *p++ = 'S';
if (rights & NCP_RIGHT_READ) *p++ = 'R';
if (rights & NCP_RIGHT_WRITE) *p++ = 'W';
if (rights & NCP_RIGHT_CREATE) *p++ = 'C';
if (rights & NCP_RIGHT_DELETE) *p++ = 'E';
if (rights & NCP_RIGHT_MODIFY) *p++ = 'M';
if (rights & NCP_RIGHT_SEARCH) *p++ = 'F';
if (rights & NCP_RIGHT_OWNER) *p++ = 'A';
*p = '\0';
}
static int grant_add_right_word(char *s, uint16 *rights)
{
if (tool_strsame(s, "ALL")) {
*rights = NCP_RIGHT_ALL_386;
return(0);
}
if (tool_strsame(s, "N") || tool_strsame(s, "NONE")) {
*rights = 0;
return(0);
}
if (tool_strsame(s, "S") || tool_strsame(s, "SUPERVISOR")) {
*rights |= NCP_RIGHT_SUPER;
return(0);
}
if (tool_strsame(s, "R") || tool_strsame(s, "READ")) {
*rights |= NCP_RIGHT_READ;
return(0);
}
if (tool_strsame(s, "W") || tool_strsame(s, "WRITE")) {
*rights |= NCP_RIGHT_WRITE;
return(0);
}
if (tool_strsame(s, "C") || tool_strsame(s, "CREATE")) {
*rights |= NCP_RIGHT_CREATE;
return(0);
}
if (tool_strsame(s, "E") || tool_strsame(s, "ERASE")) {
*rights |= NCP_RIGHT_DELETE;
return(0);
}
if (tool_strsame(s, "M") || tool_strsame(s, "MODIFY")) {
*rights |= NCP_RIGHT_MODIFY;
return(0);
}
if (tool_strsame(s, "F") || tool_strsame(s, "FILESCAN") ||
tool_strsame(s, "FILE") || tool_strsame(s, "SCAN")) {
*rights |= NCP_RIGHT_SEARCH;
return(0);
}
if (tool_strsame(s, "A") || tool_strsame(s, "ACCESS") ||
tool_strsame(s, "CONTROL") || tool_strsame(s, "ACCESSCONTROL")) {
*rights |= NCP_RIGHT_OWNER;
return(0);
}
return(-1);
}
static int grant_last_rc = 0;
static int grant_set_one(char *path, uint16 dhandle,
uint32 object_id, uint16 rights)
{
int rc;
rc = c32_ncp87_add_trustee_rights(path,
dhandle,
object_id,
rights,
0xffff,
NULL, NULL, NULL);
grant_last_rc = rc;
return(rc);
}
/*
* Apply the grant to PATH and every directory below it.
*
* This intentionally walks through the DOS redirector, not through another
* NCP search helper, so it works with the same mapped-drive view that the
* user passed to GRANT.
*/
static int grant_set_subdirs(char *path, uint16 dhandle,
uint32 object_id, uint16 rights)
{
struct find_t ff;
char pattern[260];
char child[260];
int rc = 0;
if (grant_set_one(path, dhandle, object_id, rights))
rc = 1;
tool_join_path(pattern, path, "*.*", sizeof(pattern));
if (_dos_findfirst(pattern, _A_SUBDIR, &ff) == 0) {
do {
if ((ff.attrib & _A_SUBDIR) && !tool_is_dot_dir(ff.name)) {
tool_join_path(child, path, ff.name, sizeof(child));
if (grant_set_subdirs(child, dhandle, object_id, rights))
rc = 1;
}
} while (_dos_findnext(&ff) == 0);
}
return(rc);
}
int func_grant(int argc, char *argv[], int mode)
{
uint16 rights = 0;
char *path = ".";
char *objname = NULL;
uint16 objtype = GRANT_BINDERY_USER;
uint8 connid = 0;
uint8 dhandle = 0;
uint8 namebuf[48];
uint32 object_id;
int recurse_subdirs = 0;
int i = 1;
int have_rights = 0;
int rc;
(void)mode;
if (argc < 2 || tool_is_help_arg(argv[1])) {
if (argc < 2)
grant_usage_error();
grant_usage();
return(argc < 2 ? 1 : 0);
}
/*
* GRANT rightslist* [FOR path] TO [USER|GROUP] name [options]
*/
while (i < argc) {
if (tool_strsame(argv[i], "FOR") || tool_strsame(argv[i], "TO"))
break;
if (tool_is_option(argv[i]))
break;
if (grant_add_right_word(argv[i], &rights)) {
grant_usage_error();
grant_usage();
return(1);
}
have_rights = 1;
i++;
}
if (!have_rights || i >= argc) {
grant_usage_error();
grant_usage();
return(1);
}
if (tool_strsame(argv[i], "FOR")) {
i++;
if (i >= argc) {
grant_usage_error();
grant_usage();
return(1);
}
path = argv[i++];
}
if (i >= argc || !tool_strsame(argv[i], "TO")) {
grant_usage_error();
grant_usage();
return(1);
}
i++;
if (i < argc && tool_strsame(argv[i], "USER")) {
objtype = GRANT_BINDERY_USER;
i++;
} else if (i < argc && tool_strsame(argv[i], "GROUP")) {
objtype = GRANT_BINDERY_GROUP;
i++;
}
if (i >= argc) {
grant_usage_error();
grant_usage();
return(1);
}
objname = argv[i++];
while (i < argc) {
if (!tool_is_option(argv[i])) {
grant_usage_error();
grant_usage();
return(1);
}
/*
* /FILES is harmless because the explicit path is passed to the
* NCP87 trustee-add call. /SUBDIRECTORIES recursively applies the
* same grant to all subdirectories below the given path.
*/
if (tool_strsame(argv[i], "/FILES") || tool_strsame(argv[i], "-FILES") ||
tool_strsame(argv[i], "/F") || tool_strsame(argv[i], "-F")) {
i++;
continue;
}
if (tool_strsame(argv[i], "/SUBDIRECTORIES") ||
tool_strsame(argv[i], "-SUBDIRECTORIES") ||
tool_strsame(argv[i], "/S") || tool_strsame(argv[i], "-S")) {
recurse_subdirs = 1;
i++;
continue;
}
grant_usage_error();
grant_usage();
return(1);
}
if (tool_current_dhandle(&connid, &dhandle)) {
fprintf(stdout, "Specified path not locatable.\n");
return(1);
}
strmaxcpy(namebuf, objname, sizeof(namebuf) - 1);
upstr(namebuf);
object_id = ncp_17_35(namebuf, objtype);
if (!object_id) {
fprintf(stdout, "Object not found.\n");
return(1);
}
if (recurse_subdirs)
rc = grant_set_subdirs(path, (uint16)dhandle, object_id, rights);
else
rc = grant_set_one(path, (uint16)dhandle, object_id, rights);
if (rc) {
fprintf(stdout, "Could not add trustee rights. rc=%d\n", grant_last_rc);
return(grant_last_rc ? grant_last_rc : 1);
}
{
char header[300];
char base[80];
char bracket[10];
tool_header_path(header, path, sizeof(header));
tool_basename(base, path, sizeof(base));
grant_rights_bracket(rights, bracket);
fprintf(stdout, "%s\n", header);
fprintf(stdout, "%-29.29sRights set to [%s]\n", base, bracket);
}
return(0);
}