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.
408 lines
10 KiB
C
408 lines
10 KiB
C
/*
|
|
* mars-nwe-dosutils - NetWare/DOS utility tools.
|
|
*
|
|
* Copyright (C) 2026 Mario Fetka
|
|
* Copyright (C) 1993,1996 Martin Stover, Marburg, Germany
|
|
*
|
|
* 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: Low-level NCP bindery, filesystem and server helper routines used by multiple commands.
|
|
* Depends on: net.h, netcall.c requester glue, kern_wasm.asm/kern.asm Net_Call entry point, tools.c shared utility routines.
|
|
*/
|
|
|
|
#include "net.h"
|
|
|
|
/* ---------------- 0x16 ----------------------------------- */
|
|
int ncp_16_02(int dirhandle,
|
|
uint8 *path,
|
|
int *sub_dir,
|
|
uint8 *resultpath,
|
|
uint32 *creattime,
|
|
uint32 *owner_id)
|
|
|
|
/* returns max. rights or -1 if failed */
|
|
{
|
|
struct {
|
|
uint16 len;
|
|
uint8 func;
|
|
uint8 dirhandle;
|
|
uint8 sub_dir[2];
|
|
uint8 pathlen;
|
|
uint8 path[256];
|
|
} req;
|
|
struct {
|
|
uint16 len;
|
|
uint8 sub_dir_name[16];
|
|
uint8 create_date_time[4];
|
|
uint8 owner_id[4]; /* HI LOW */
|
|
uint8 max_right_mask;
|
|
uint8 reserved; /* Reserved by Novell */
|
|
uint8 sub_dir_nmbr[2]; /* HI LOW */
|
|
} repl = { sizeof(repl) - sizeof(uint16) };
|
|
req.func = 0x02;
|
|
U16_TO_BE16((sub_dir) ? *sub_dir : 1, req.sub_dir);
|
|
req.dirhandle = (uint8) dirhandle;
|
|
req.pathlen = (uint8) ((path) ? strlen(path) : 0);
|
|
req.len = 5 + req.pathlen;
|
|
strmaxcpy(req.path, path, req.pathlen);
|
|
neterrno = Net_Call(0xE200, &req, &repl);
|
|
if (neterrno) return(-1);
|
|
if (resultpath) strmaxcpy(resultpath, repl.sub_dir_name, 16);
|
|
if (sub_dir) *sub_dir = GET_BE16(repl.sub_dir_nmbr);
|
|
if (creattime) *creattime = GET_BE32(repl.create_date_time);
|
|
if (owner_id) *owner_id = GET_BE32(repl.owner_id);
|
|
return((int) repl.max_right_mask);
|
|
}
|
|
|
|
/* ---------------- 0x17 ----------------------------------- */
|
|
int ncp_17_02(int module, int debuglevel)
|
|
/* debuglevel fuer module setzen */
|
|
{
|
|
struct {
|
|
uint16 len;
|
|
uint8 func;
|
|
uint8 module;
|
|
uint8 debug;
|
|
} req = { sizeof(req) - sizeof(uint16) };
|
|
struct {
|
|
uint16 len;
|
|
uint8 olddebug;
|
|
} repl = { sizeof(repl) - sizeof(uint16) };
|
|
req.func = 0x2;
|
|
req.module = (uint8) module;
|
|
req.debug = (uint8) debuglevel;
|
|
neterrno = Net_Call(0xE300, &req, &repl);
|
|
if (neterrno) return(-1);
|
|
return((int) repl.olddebug);
|
|
}
|
|
|
|
int ncp_17_14(uint8 *objname, uint16 objtyp, uint8 *password)
|
|
/* login unencreypted */
|
|
{
|
|
struct {
|
|
uint16 len;
|
|
uint8 func;
|
|
uint8 typ[2];
|
|
uint8 namlen;
|
|
uint8 buff[48+1+128];
|
|
} req;
|
|
struct {
|
|
uint16 len;
|
|
} repl= { 0 };
|
|
uint8 *p=req.buff;
|
|
req.func = 0x14;
|
|
U16_TO_BE16(objtyp, req.typ);
|
|
req.namlen = min(47, strlen(objname));
|
|
memcpy(p, objname, req.namlen);
|
|
p += req.namlen;
|
|
*p = (uint8) min(128, strlen(password));
|
|
req.len = 4 + req.namlen + 1 + *p;
|
|
memcpy(p+1, password, (int) *p);
|
|
neterrno = Net_Call(0xE300, &req, &repl);
|
|
if (neterrno) return(-1);
|
|
return(0);
|
|
}
|
|
|
|
int ncp_17_17(uint8 *key)
|
|
/* get crypt key */
|
|
{
|
|
struct {
|
|
uint16 len;
|
|
uint8 func;
|
|
} req;
|
|
struct {
|
|
uint16 len;
|
|
uint8 key[8];
|
|
} repl;
|
|
req.len = 1;
|
|
req.func = 0x17;
|
|
repl.len = 8;
|
|
neterrno = Net_Call(0xE300, &req, &repl);
|
|
if (neterrno) return(-1);
|
|
else {
|
|
memcpy(key, repl.key, 8);
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
int ncp_17_18(uint8 *cryptkey, uint8 *objname, uint16 objtyp)
|
|
/* keyed login */
|
|
{
|
|
struct {
|
|
uint16 len;
|
|
uint8 func;
|
|
uint8 key[8];
|
|
uint8 typ[2];
|
|
uint8 namlen;
|
|
uint8 name[48];
|
|
} req;
|
|
struct {
|
|
uint16 len;
|
|
} repl={ 0 };
|
|
req.len = sizeof(req) - sizeof(uint16);
|
|
req.func = 0x18;
|
|
U16_TO_BE16(objtyp, req.typ);
|
|
req.namlen = min(sizeof(req.name), strlen(objname));
|
|
memcpy(req.key, cryptkey, 8);
|
|
memcpy(req.name, objname, (int) req.namlen);
|
|
neterrno = Net_Call(0xE300, &req, &repl);
|
|
if (neterrno) return(-1);
|
|
return(0);
|
|
}
|
|
|
|
uint32 ncp_17_35(uint8 *objname, uint16 objtyp)
|
|
/* get bindery object id */
|
|
{
|
|
struct {
|
|
uint16 len;
|
|
uint8 func;
|
|
uint8 typ[2];
|
|
uint8 namlen;
|
|
uint8 name[48];
|
|
} req;
|
|
struct {
|
|
uint16 len;
|
|
uint8 object_id[4];
|
|
uint8 object_type[2];
|
|
uint8 object_name[48];
|
|
} repl;
|
|
req.len = sizeof(req) - sizeof(uint16);
|
|
repl.len = sizeof(repl) - sizeof(uint16);
|
|
req.func = 0x35;
|
|
U16_TO_BE16(objtyp, req.typ);
|
|
req.namlen = min(sizeof(req.name), strlen(objname));
|
|
memcpy(req.name, objname, (int) req.namlen);
|
|
neterrno = Net_Call(0xE300, &req, &repl);
|
|
if (neterrno) return(0L);
|
|
strmaxcpy(objname, repl.object_name, 47);
|
|
return(GET_BE32(repl.object_id));
|
|
}
|
|
|
|
int ncp_17_36(uint32 obj_id, uint8 *objname, uint16 *objtyp)
|
|
/* get bindery object name */
|
|
{
|
|
struct {
|
|
uint16 len;
|
|
uint8 func;
|
|
uint8 id[4];
|
|
} req;
|
|
struct {
|
|
uint16 len;
|
|
uint8 object_id[4];
|
|
uint8 object_type[2];
|
|
uint8 object_name[48];
|
|
} repl;
|
|
req.len = sizeof(req) - sizeof(uint16);
|
|
repl.len = sizeof(repl) - sizeof(uint16);
|
|
req.func = 0x36;
|
|
U32_TO_BE32(obj_id, req.id);
|
|
neterrno = Net_Call(0xE300, &req, &repl);
|
|
if (neterrno) return(-1);
|
|
if (objname) strmaxcpy(objname, repl.object_name, 47);
|
|
if (objtyp) *objtyp = GET_BE16(repl.object_type);
|
|
return(0);
|
|
}
|
|
|
|
|
|
int ncp_17_40(uint8 *objname, uint16 objtyp,
|
|
uint8 *password, uint8 *newpassword)
|
|
/* change password unencreypted */
|
|
{
|
|
struct {
|
|
uint16 len;
|
|
uint8 func;
|
|
uint8 typ[2];
|
|
uint8 namlen;
|
|
uint8 buff[48+1+128+1+128];
|
|
} req;
|
|
struct {
|
|
uint16 len;
|
|
} repl = { 0 };
|
|
uint8 *p=req.buff;
|
|
req.func = 0x40;
|
|
U16_TO_BE16(objtyp, req.typ);
|
|
req.namlen = min(47, strlen(objname));
|
|
memcpy(p, objname, req.namlen);
|
|
p += req.namlen;
|
|
*p = (uint8) min(128, strlen(password));
|
|
req.len = 4 + req.namlen + 1 + *p;
|
|
memcpy(p+1, password, (int) *p);
|
|
p += (1 + *p);
|
|
*p = (uint8) min(128, strlen(newpassword));
|
|
req.len += (1 + *p);
|
|
memcpy(p+1, newpassword, (int) *p);
|
|
neterrno = Net_Call(0xE300, &req, &repl);
|
|
if (neterrno) return(-1);
|
|
return(0);
|
|
}
|
|
|
|
int ncp_14_46(uint32 *obj_id)
|
|
/* get bindery access level & actual ID */
|
|
{
|
|
struct {
|
|
uint16 len;
|
|
uint8 func;
|
|
} req;
|
|
struct {
|
|
uint16 len;
|
|
uint8 access;
|
|
uint8 id[4];
|
|
} repl;
|
|
req.len = 1;
|
|
req.func = 0x46;
|
|
repl.len = 5;
|
|
neterrno = Net_Call(0xE300, &req, &repl);
|
|
if (neterrno) return(-1);
|
|
else {
|
|
if (obj_id) *obj_id = GET_BE32(repl.id);
|
|
return(repl.access);
|
|
}
|
|
}
|
|
|
|
|
|
int ncp_17_4b(uint8 *cryptkey, uint8 *objname, uint16 objtyp,
|
|
int passwx, uint8 *newpassword)
|
|
/* keyed change password */
|
|
{
|
|
struct {
|
|
uint16 len;
|
|
uint8 func;
|
|
uint8 key[8];
|
|
uint8 typ[2];
|
|
uint8 namlen;
|
|
uint8 buff[48+1+16];
|
|
} req;
|
|
struct {
|
|
uint16 len;
|
|
} repl = { 0 };
|
|
uint8 *p = req.buff;
|
|
req.func = 0x4b;
|
|
memcpy(req.key, cryptkey, 8);
|
|
U16_TO_BE16(objtyp, req.typ);
|
|
req.namlen = (uint8) min(48, strlen(objname));
|
|
req.len = 12 + req.namlen + 1 + 16;
|
|
memcpy(p, objname, (int) req.namlen);
|
|
p += req.namlen;
|
|
*p++ = (uint8) passwx;
|
|
memcpy(p, newpassword, 16);
|
|
neterrno = Net_Call(0xE300, &req, &repl);
|
|
if (neterrno) return(-1);
|
|
return(0);
|
|
}
|
|
|
|
|
|
int ncp_17_37(uint32 last_id, uint16 objtyp, uint8 *pattern,
|
|
BINDERY_OBJECT *target)
|
|
/* scan bindery object */
|
|
{
|
|
struct {
|
|
uint16 len;
|
|
uint8 func;
|
|
uint8 last_id[4];
|
|
uint8 typ[2];
|
|
uint8 patlen;
|
|
uint8 pattern[48];
|
|
} req;
|
|
struct {
|
|
uint16 len;
|
|
uint8 object_id[4];
|
|
uint8 object_type[2];
|
|
uint8 object_name[48];
|
|
uint8 object_flags;
|
|
uint8 object_security;
|
|
uint8 object_has_prop;
|
|
} repl;
|
|
int patlen = (pattern) ? min(48, strlen(pattern)) : 1;
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
memset(&repl, 0, sizeof(repl));
|
|
|
|
req.func = 0x37;
|
|
U32_TO_BE32(last_id, req.last_id);
|
|
U16_TO_BE16(objtyp, req.typ);
|
|
req.patlen = (uint8)patlen;
|
|
if (pattern) memcpy(req.pattern, pattern, patlen);
|
|
else req.pattern[0] = '*';
|
|
req.len = 8 + patlen;
|
|
|
|
repl.len = sizeof(repl) - sizeof(uint16);
|
|
|
|
neterrno = Net_Call(0xE300, &req, &repl);
|
|
if (neterrno) return(-1);
|
|
|
|
if (target) {
|
|
target->object_id = GET_BE32(repl.object_id);
|
|
target->object_type = GET_BE16(repl.object_type);
|
|
memcpy(target->object_name, repl.object_name, 48);
|
|
target->object_name[48] = '\0';
|
|
deb(target->object_name);
|
|
target->object_flags = repl.object_flags;
|
|
target->object_security = repl.object_security;
|
|
target->object_has_prop = repl.object_has_prop;
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
int ncp_17_3d(uint16 objtyp, uint8 *objname, int segment,
|
|
uint8 *propname, NW_PROPERTY *target)
|
|
/* read bindery property value */
|
|
{
|
|
struct {
|
|
uint16 len;
|
|
uint8 func;
|
|
uint8 typ[2];
|
|
uint8 buff[1+48+1+1+16];
|
|
} req;
|
|
struct {
|
|
uint16 len;
|
|
uint8 value[128];
|
|
uint8 more_flag;
|
|
uint8 property_flag;
|
|
} repl;
|
|
uint8 *p = req.buff;
|
|
int objlen = min(48, strlen(objname));
|
|
int proplen = min(16, strlen(propname));
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
memset(&repl, 0, sizeof(repl));
|
|
|
|
req.func = 0x3d;
|
|
U16_TO_BE16(objtyp, req.typ);
|
|
|
|
*p++ = (uint8)objlen;
|
|
memcpy(p, objname, objlen);
|
|
p += objlen;
|
|
|
|
*p++ = (uint8)segment;
|
|
|
|
*p++ = (uint8)proplen;
|
|
memcpy(p, propname, proplen);
|
|
|
|
req.len = 6 + objlen + proplen;
|
|
repl.len = sizeof(repl) - sizeof(uint16);
|
|
|
|
neterrno = Net_Call(0xE300, &req, &repl);
|
|
if (neterrno) return(-1);
|
|
|
|
if (target) {
|
|
memcpy(target->value, repl.value, 128);
|
|
target->more_flag = repl.more_flag;
|
|
target->property_flag = repl.property_flag;
|
|
}
|
|
return(0);
|
|
}
|
|
|