Files
mars-dosutils/remove.c
Mario Fetka 4cafe16980 dosutils: add Novell-style REVOKE and REMOVE trustee tools
Implement REVOKE and REMOVE for the Client32 DOS utilities.

REVOKE now supports Novell-style syntax:

  REVOKE rightslist* [FOR path] FROM [USER|GROUP] name [options]

and removes rights from explicit trustee assignments.  It scans the
trustee list first, updates the trustee rights mask, and deletes the
trustee entry when no rights remain.

REMOVE now supports Novell-style syntax:

  REMOVE [USER | GROUP] name [FROM path] [option]

and deletes explicit trustee assignments for users or groups.

Both tools support USER/GROUP lookup, /FILES, /SUBDIRS,
/SUBDIRECTORIES, wildcard file targets, recursive directory handling,
Novell-style help text and summary output.  Missing trustee entries are
reported with Novell-style "No trustee for the specified ..." messages.

Add shared trustee helpers and Client32 NCP87 trustee scan/delete
support.  Also adjust GRANT ALL so it matches Novell behavior by not
granting Supervisor implicitly; Supervisor must be granted explicitly.
2026-05-24 20:23:43 +02:00

254 lines
6.3 KiB
C

/* remove.c - Novell REMOVE-like DOS utility */
#include "net.h"
#include "c32ncp.h"
#include "trustee.h"
#include <sys/types.h>
#include <sys/stat.h>
#ifndef _A_NORMAL
#define _A_NORMAL 0x00
#endif
static int remove_last_rc = 0;
static void remove_usage_error(void)
{
fprintf(stdout, "Command line arguments violate grammar defined for REMOVE.\n\n");
}
static void remove_usage(void)
{
fprintf(stdout, "Usage: REMOVE [USER | GROUP] name [FROM path] [option]\n");
fprintf(stdout, "Options: /Subdirs | /Files\n");
}
static int remove_one(char *path, uint16 dhandle, uint32 object_id,
uint16 objtype, char *objname, int forced_is_file)
{
uint16 old_rights = 0;
int is_dir;
int rc;
is_dir = forced_is_file ? 0 : trustee_path_is_dir(path);
rc = c32_ncp87_find_trustee_rights(path, dhandle, object_id, &old_rights,
NULL, NULL, NULL);
remove_last_rc = rc;
if (rc) {
if (rc == 0xff)
fprintf(stdout, "No trustee for the specified %s.\n", is_dir ? "directory" : "file");
else
fprintf(stdout, "Error scanning trustee list.\n");
return(1);
}
rc = c32_ncp87_delete_trustee_rights(path, dhandle, object_id,
NULL, NULL, NULL);
remove_last_rc = rc;
if (rc) {
fprintf(stdout, "Error deleting trustee.\n");
return(1);
}
{
char header[300];
trustee_header_path(header, path, sizeof(header));
fprintf(stdout, "%s\n\n", header);
}
if (objtype == TRUSTEE_BINDERY_GROUP)
fprintf(stdout, "Group \"%s\" no longer a trustee to the specified %s.\n",
objname, is_dir ? "directory" : "file");
else
fprintf(stdout, "User \"%s\" no longer a trustee to the specified %s.\n",
objname, is_dir ? "directory" : "file");
return(0);
}
static int remove_subdirs(char *path, uint16 dhandle, uint32 object_id,
uint16 objtype, char *objname, int *count)
{
struct find_t ff;
char pattern[260];
char child[260];
int rc = 0;
if (remove_one(path, dhandle, object_id, objtype, objname, 0) == 0)
(*count)++;
else
rc = 1;
trustee_join_path(pattern, path, "*.*", sizeof(pattern));
if (_dos_findfirst(pattern, _A_SUBDIR, &ff) == 0) {
do {
if ((ff.attrib & _A_SUBDIR) && !trustee_is_dot_dir(ff.name)) {
trustee_join_path(child, path, ff.name, sizeof(child));
if (remove_subdirs(child, dhandle, object_id, objtype, objname, count))
rc = 1;
}
} while (_dos_findnext(&ff) == 0);
}
return(rc);
}
static int remove_files(char *path, uint16 dhandle, uint32 object_id,
uint16 objtype, char *objname, int *count)
{
struct find_t ff;
char dir[260];
char pat[80];
char spec[260];
char target[260];
int rc = 0;
if (trustee_path_is_dir(path)) {
strmaxcpy(dir, path, sizeof(dir) - 1);
strmaxcpy(pat, "*.*", sizeof(pat) - 1);
} else if (trustee_path_has_wildcards(path)) {
trustee_parent_pattern(dir, pat, path, sizeof(dir), sizeof(pat));
} else {
if (remove_one(path, dhandle, object_id, objtype, objname, 1) == 0)
(*count)++;
else
rc = 1;
return(rc);
}
trustee_join_path(spec, dir, pat, sizeof(spec));
if (_dos_findfirst(spec, _A_NORMAL | _A_HIDDEN | _A_SYSTEM | _A_ARCH, &ff) == 0) {
do {
if (!(ff.attrib & _A_SUBDIR)) {
trustee_join_path(target, dir, ff.name, sizeof(target));
if (remove_one(target, dhandle, object_id, objtype, objname, 1) == 0)
(*count)++;
else
rc = 1;
}
} while (_dos_findnext(&ff) == 0);
}
return(rc);
}
int func_remove(int argc, char *argv[], int mode)
{
char *path = ".";
char *objname = NULL;
char objprint[48];
uint16 objtype = TRUSTEE_BINDERY_USER;
int objtype_given = 0;
uint8 connid = 0;
uint8 dhandle = 0;
uint32 object_id;
int use_subdirs = 0;
int use_files = 0;
int count = 0;
int i = 1;
int rc;
(void)mode;
if (argc < 2 || trustee_is_help(argv[1])) {
if (argc < 2)
remove_usage_error();
remove_usage();
return(argc < 2 ? 1 : 0);
}
if (i < argc && trustee_same(argv[i], "USER")) {
objtype = TRUSTEE_BINDERY_USER;
objtype_given = 1;
i++;
} else if (i < argc && trustee_same(argv[i], "GROUP")) {
objtype = TRUSTEE_BINDERY_GROUP;
objtype_given = 1;
i++;
}
if (i >= argc) {
remove_usage_error();
remove_usage();
return(1);
}
objname = argv[i++];
if (i < argc && trustee_same(argv[i], "FROM")) {
i++;
if (i >= argc) {
remove_usage_error();
remove_usage();
return(1);
}
path = argv[i++];
}
while (i < argc) {
if (!trustee_is_option(argv[i])) {
remove_usage_error();
remove_usage();
return(1);
}
if (trustee_is_files_option(argv[i])) {
use_files = 1;
i++;
continue;
}
if (trustee_is_subdirs_option(argv[i])) {
use_subdirs = 1;
i++;
continue;
}
remove_usage_error();
remove_usage();
return(1);
}
if (use_files && use_subdirs) {
fprintf(stdout, "Remove cannot do both directories and files in a single pass.\n");
return(1);
}
if (trustee_current_dhandle(&connid, &dhandle)) {
fprintf(stdout, "Error: Drive not mapped to network.\n");
return(1);
}
object_id = trustee_lookup_object(objname, &objtype, objtype_given);
if (!object_id) {
if (objtype_given && objtype == TRUSTEE_BINDERY_GROUP)
fprintf(stdout, "Group \"%s\" not found.\n", objname);
else if (objtype_given)
fprintf(stdout, "User \"%s\" not found.\n", objname);
else
fprintf(stdout, "User or group \"%s\" not found.\n", objname);
return(1);
}
trustee_upcopy(objprint, objname, sizeof(objprint));
if (use_subdirs)
rc = remove_subdirs(path, (uint16)dhandle, object_id, objtype, objprint, &count);
else if (use_files)
rc = remove_files(path, (uint16)dhandle, object_id, objtype, objprint, &count);
else {
rc = remove_one(path, (uint16)dhandle, object_id, objtype, objprint, 0);
if (!rc)
count = 1;
}
if (use_subdirs || (!use_files && !rc))
fprintf(stdout, "Trustee \"%s\" removed from %d directories.\n", objprint, count);
else if (use_files)
fprintf(stdout, "Trustee \"%s\" removed from %d files.\n", objprint, count);
return(rc ? (remove_last_rc ? remove_last_rc : 1) : 0);
}