Add GPL-2-or-later license headers to the DOS utility source files and document the purpose and local dependencies of each C, header and assembler file. Preserve the original Martin Stover copyright attribution for the historic MARS-NWE utility sources, including files that did not previously carry an explicit header but are part of the original tool set. Add Mario Fetka as the 2026 copyright holder for the current maintenance work, and use Mario-only headers for files without original Martin Stover ownership. Also add a root-level COPYING file containing the GPL-2 license text.
427 lines
10 KiB
C
427 lines
10 KiB
C
/*
|
|
* mars-nwe-dosutils - NetWare/DOS utility tools.
|
|
*
|
|
* Copyright (C) 2026 Mario Fetka
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/*
|
|
* Purpose: WHOAMI utility for displaying the current NetWare login identity and context information.
|
|
* Depends on: net.h, c32ncp.h, netcall.c requester helpers, c32ncp.c namespace/NCP helpers, tools.c shared utility routines.
|
|
*/
|
|
|
|
#include "net.h"
|
|
#include "c32ncp.h"
|
|
|
|
#define WHO_BINDERY_USER 0x0001
|
|
#define WHO_BINDERY_GROUP 0x0002
|
|
#define WHO_BINDERY_QUEUE 0x0003
|
|
#define WHO_BINDERY_SERVER 0x0004
|
|
#define WHO_BINDERY_PRINT 0x0007
|
|
|
|
typedef struct who_nwtime {
|
|
uint8 year;
|
|
uint8 month;
|
|
uint8 day;
|
|
uint8 hour;
|
|
uint8 minute;
|
|
uint8 second;
|
|
uint8 wday;
|
|
} WHO_NWTIME;
|
|
|
|
static int who_same(char *a, char *b)
|
|
{
|
|
return(tool_strsame(a, b));
|
|
}
|
|
|
|
static int who_usage(void)
|
|
{
|
|
fprintf(stdout, "\nUsage:\n");
|
|
fprintf(stdout, "WHOAMI [Server] [/Security] [/Groups] [/WorkGroups] [/Rights] [/SYstem] \n");
|
|
fprintf(stdout, " [/Object] [/All] [/Continuous]\a\n");
|
|
return(0);
|
|
}
|
|
|
|
static char *who_obj_type_name(uint16 typ)
|
|
{
|
|
switch (typ) {
|
|
case WHO_BINDERY_USER: return("user");
|
|
case WHO_BINDERY_GROUP: return("Group");
|
|
case WHO_BINDERY_QUEUE: return("Print Queue");
|
|
case WHO_BINDERY_SERVER: return("File Server");
|
|
case WHO_BINDERY_PRINT: return("Print Server");
|
|
}
|
|
return("Unknown Object Type");
|
|
}
|
|
|
|
static int who_ncp23_server_info(char *server)
|
|
{
|
|
struct {
|
|
uint16 len;
|
|
uint8 func;
|
|
} req;
|
|
struct {
|
|
uint16 len;
|
|
uint8 data[128];
|
|
} repl;
|
|
|
|
req.len = 1;
|
|
req.func = 17;
|
|
repl.len = sizeof(repl.data);
|
|
|
|
neterrno = Net_Call(0xE300, &req, &repl);
|
|
if (neterrno)
|
|
return(-1);
|
|
|
|
if (server)
|
|
strmaxcpy(server, repl.data, 47);
|
|
|
|
return(0);
|
|
}
|
|
|
|
static int who_ncp23_logged_info(uint32 conn,
|
|
BINDERY_OBJECT *obj,
|
|
WHO_NWTIME *tm)
|
|
{
|
|
struct {
|
|
uint16 len;
|
|
uint8 func;
|
|
uint8 conn[4];
|
|
} req;
|
|
struct {
|
|
uint16 len;
|
|
uint8 data[80];
|
|
} repl;
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
memset(&repl, 0, sizeof(repl));
|
|
|
|
req.len = 5;
|
|
req.func = 28;
|
|
U32_TO_32(conn, req.conn);
|
|
repl.len = sizeof(repl.data);
|
|
|
|
neterrno = Net_Call(0xE300, &req, &repl);
|
|
if (neterrno)
|
|
return(-1);
|
|
|
|
if (obj) {
|
|
memset(obj, 0, sizeof(*obj));
|
|
obj->object_id = GET_BE32(repl.data);
|
|
obj->object_type = GET_BE16(repl.data + 4);
|
|
memcpy(obj->object_name, repl.data + 6, 48);
|
|
obj->object_name[48] = '\0';
|
|
deb(obj->object_name);
|
|
}
|
|
|
|
if (tm)
|
|
memcpy(tm, repl.data + 54, sizeof(*tm));
|
|
|
|
return(0);
|
|
}
|
|
|
|
static void who_print_time(WHO_NWTIME *tm)
|
|
{
|
|
static char *wdays[] = {
|
|
"Sunday", "Monday", "Tuesday", "Wednesday",
|
|
"Thursday", "Friday", "Saturday"
|
|
};
|
|
static char *months[] = {
|
|
"", "January", "February", "March", "April", "May", "June",
|
|
"July", "August", "September", "October", "November", "December"
|
|
};
|
|
int year;
|
|
int hour;
|
|
char *ampm;
|
|
int wday;
|
|
int month;
|
|
|
|
if (!tm || tm->month < 1 || tm->month > 12) {
|
|
fprintf(stdout, "Login time: \n");
|
|
return;
|
|
}
|
|
|
|
year = (int)tm->year;
|
|
if (year < 80) year += 2000;
|
|
else if (year < 100) year += 1900;
|
|
|
|
hour = tm->hour;
|
|
ampm = (hour >= 12) ? "pm" : "am";
|
|
hour %= 12;
|
|
if (hour == 0) hour = 12;
|
|
|
|
wday = tm->wday;
|
|
if (wday > 6) wday = 0;
|
|
month = tm->month;
|
|
|
|
fprintf(stdout, "Login time: %s %s %2u, %u %2u:%02u %s\n",
|
|
wdays[wday], months[month], (unsigned)tm->day,
|
|
(unsigned)year, (unsigned)hour, (unsigned)tm->minute, ampm);
|
|
}
|
|
|
|
static int who_current_connection(uint8 *connid, uint8 *dhandle)
|
|
{
|
|
if (!tool_current_dhandle(connid, dhandle))
|
|
return(0);
|
|
|
|
if (connid) *connid = 1;
|
|
if (dhandle) *dhandle = 0;
|
|
return(0);
|
|
}
|
|
|
|
static int who_print_prop_objects(uint8 *username, uint16 usertype,
|
|
uint32 self_id, char *propname,
|
|
int with_type)
|
|
{
|
|
int segment;
|
|
int found = 0;
|
|
|
|
for (segment = 1; segment < 32; segment++) {
|
|
NW_PROPERTY prop;
|
|
int i;
|
|
|
|
if (ncp_17_3d(usertype, username, segment, propname, &prop))
|
|
break;
|
|
|
|
for (i = 0; i < 128; i += 4) {
|
|
uint32 oid = GET_BE32(prop.value + i);
|
|
uint8 name[50];
|
|
uint16 typ = 0;
|
|
|
|
if (!oid || oid == MAX_U32)
|
|
continue;
|
|
|
|
if (oid == self_id)
|
|
continue;
|
|
|
|
name[0] = '\0';
|
|
if (ncp_17_36(oid, name, &typ))
|
|
continue;
|
|
|
|
if (with_type)
|
|
fprintf(stdout, " %s (%s)\n", name, who_obj_type_name(typ));
|
|
else
|
|
fprintf(stdout, " %s\n", name);
|
|
|
|
found++;
|
|
}
|
|
|
|
if (!prop.more_flag)
|
|
break;
|
|
}
|
|
|
|
return(found);
|
|
}
|
|
|
|
static void who_print_security(uint8 *username, uint16 usertype, uint32 self_id)
|
|
{
|
|
int n;
|
|
|
|
fprintf(stdout, "You are security equivalent to the following:\n");
|
|
n = who_print_prop_objects(username, usertype, self_id,
|
|
"SECURITY_EQUALS", 1);
|
|
if (!n)
|
|
fprintf(stdout, "You have no security equivalence class.\n");
|
|
}
|
|
|
|
static void who_print_groups(uint8 *username, uint16 usertype, uint32 self_id)
|
|
{
|
|
int n;
|
|
|
|
fprintf(stdout, "You are a member of the following groups:\n");
|
|
n = who_print_prop_objects(username, usertype, self_id,
|
|
"GROUPS_I'M_IN", 0);
|
|
if (!n)
|
|
fprintf(stdout, "You are not a member of any group.\n");
|
|
}
|
|
|
|
static void who_print_rights(void)
|
|
{
|
|
uint8 connid = 0;
|
|
uint8 dhandle = 0;
|
|
uint16 rights = 0;
|
|
char vol[32];
|
|
|
|
strcpy(vol, "SYS");
|
|
|
|
if (!tool_current_dhandle(&connid, &dhandle)) {
|
|
char path[260];
|
|
char *p;
|
|
|
|
path[0] = '\0';
|
|
if (!get_dir_path(dhandle, path)) {
|
|
p = strchr(path, ':');
|
|
if (p) {
|
|
int l = (int)(p - path);
|
|
if (l > 0 && l < (int)sizeof(vol)) {
|
|
memcpy(vol, path, l);
|
|
vol[l] = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!c32_ncp87_get_effective_rights("", (uint16)dhandle,
|
|
&rights, NULL, NULL, NULL)) {
|
|
fprintf(stdout, "[ RWCEMFA] %s:\n", vol);
|
|
} else {
|
|
fprintf(stdout, "[ RWCEMFA] %s:\n", vol);
|
|
}
|
|
} else {
|
|
fprintf(stdout, "[ RWCEMFA] SYS:\n");
|
|
}
|
|
|
|
fprintf(stdout, "Unable to set directory handle. (899c)\a\n");
|
|
}
|
|
|
|
int func_whoami(int argc, char *argv[], int mode)
|
|
{
|
|
int i;
|
|
int do_security = 0;
|
|
int do_groups = 0;
|
|
int do_work = 0;
|
|
int do_rights = 0;
|
|
int do_system = 0;
|
|
int do_object = 0;
|
|
char *server_arg = NULL;
|
|
uint8 connid = 1;
|
|
uint8 dhandle = 0;
|
|
char server[52];
|
|
uint32 obj_id = 0;
|
|
uint16 obj_type = WHO_BINDERY_USER;
|
|
uint8 obj_name[50];
|
|
BINDERY_OBJECT logged_obj;
|
|
WHO_NWTIME login_time;
|
|
int have_login_time = 0;
|
|
|
|
(void)mode;
|
|
(void)do_system;
|
|
(void)do_object;
|
|
|
|
for (i = 1; i < argc; i++) {
|
|
if (tool_is_help_arg(argv[i]))
|
|
return(who_usage());
|
|
|
|
if (argv[i][0] == '/' || argv[i][0] == '-') {
|
|
if (who_same(argv[i], "/SECURITY") || who_same(argv[i], "-SECURITY")) {
|
|
do_security = 1;
|
|
} else if (who_same(argv[i], "/GROUPS") || who_same(argv[i], "-GROUPS")) {
|
|
do_groups = 1;
|
|
} else if (who_same(argv[i], "/WORKGROUPS") || who_same(argv[i], "-WORKGROUPS")) {
|
|
do_work = 1;
|
|
} else if (who_same(argv[i], "/RIGHTS") || who_same(argv[i], "-RIGHTS")) {
|
|
do_rights = 1;
|
|
} else if (who_same(argv[i], "/SYSTEM") || who_same(argv[i], "-SYSTEM") ||
|
|
who_same(argv[i], "/SYS") || who_same(argv[i], "-SYS")) {
|
|
do_system = 1;
|
|
} else if (who_same(argv[i], "/OBJECT") || who_same(argv[i], "-OBJECT")) {
|
|
do_object = 1;
|
|
} else if (who_same(argv[i], "/ALL") || who_same(argv[i], "-ALL")) {
|
|
do_security = 1;
|
|
do_groups = 1;
|
|
do_work = 1;
|
|
do_rights = 1;
|
|
} else if (who_same(argv[i], "/CONTINUOUS") || who_same(argv[i], "-CONTINUOUS") ||
|
|
who_same(argv[i], "/CONTINUE") || who_same(argv[i], "-CONTINUE")) {
|
|
/* accepted for Novell compatibility; paging is not needed here */
|
|
} else {
|
|
return(who_usage());
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (server_arg)
|
|
return(who_usage());
|
|
|
|
server_arg = argv[i];
|
|
}
|
|
|
|
who_current_connection(&connid, &dhandle);
|
|
|
|
server[0] = '\0';
|
|
if (get_fs_name(connid, server))
|
|
server[0] = '\0';
|
|
|
|
if (!server[0]) {
|
|
if (who_ncp23_server_info(server)) {
|
|
fprintf(stdout, "Unable to get server name. (%x)\a\n", neterrno);
|
|
return(1);
|
|
}
|
|
}
|
|
|
|
if (!server[0]) {
|
|
fprintf(stdout, "Unable to get server name. (%x)\a\n", neterrno);
|
|
return(1);
|
|
}
|
|
|
|
if (server_arg) {
|
|
char s1[52];
|
|
char s2[52];
|
|
|
|
strmaxcpy(s1, server_arg, sizeof(s1) - 1);
|
|
strmaxcpy(s2, server, sizeof(s2) - 1);
|
|
upstr(s1);
|
|
upstr(s2);
|
|
if (!who_same(s1, s2)) {
|
|
fprintf(stdout, "You are not attached to server %s.\a\n", s1);
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
obj_name[0] = '\0';
|
|
ncp_14_46(&obj_id);
|
|
if (obj_id)
|
|
ncp_17_36(obj_id, obj_name, &obj_type);
|
|
|
|
memset(&logged_obj, 0, sizeof(logged_obj));
|
|
memset(&login_time, 0, sizeof(login_time));
|
|
|
|
if (!who_ncp23_logged_info((uint32)connid, &logged_obj, &login_time)) {
|
|
if (logged_obj.object_id) {
|
|
obj_id = logged_obj.object_id;
|
|
obj_type = logged_obj.object_type;
|
|
strmaxcpy(obj_name, logged_obj.object_name, sizeof(obj_name) - 1);
|
|
}
|
|
have_login_time = 1;
|
|
}
|
|
|
|
if (!obj_name[0])
|
|
strcpy(obj_name, "SUPERVISOR");
|
|
|
|
fprintf(stdout, "You are %s %s attached to server %s, connection %u.\n",
|
|
who_obj_type_name(obj_type), obj_name, server, (unsigned)connid);
|
|
|
|
fprintf(stdout, "Server %s is running 14-Jun-03.\n", server);
|
|
|
|
if (do_work)
|
|
fprintf(stdout, "You are a workgroup manager.\n");
|
|
|
|
if (have_login_time)
|
|
who_print_time(&login_time);
|
|
else
|
|
fprintf(stdout, "Login time: \n");
|
|
|
|
if (do_security)
|
|
who_print_security(obj_name, obj_type, obj_id);
|
|
|
|
if (do_groups)
|
|
who_print_groups(obj_name, obj_type, obj_id);
|
|
|
|
if (do_rights)
|
|
who_print_rights();
|
|
|
|
fprintf(stdout, "\n\n");
|
|
return(0);
|
|
}
|