Add Client32 NCP support for FLAG and FLAGDIR
Implement a working DOS Client32 NCP87 path using the NIOS resolver, CONNOpenByReference and COMPATNcpRequestReply. Add an initial FLAGDIR implementation for NetWare 386-style directory attributes. Support Normal, System, Hidden, Delete Inhibit, Purge and Rename Inhibit, using the same Client32 NCP87 modify/read helpers. Match the Novell FLAGDIR display style more closely for simple mapped paths. Also add/keep minimal TESTS coverage for the verified Client32 NCP87 attribute path.
This commit is contained in:
@@ -25,6 +25,7 @@ set(MARS_DOSUTILS_PUBLIC_TOOLS
|
||||
logout
|
||||
slist
|
||||
flag
|
||||
flagdir
|
||||
capture
|
||||
endcap
|
||||
)
|
||||
@@ -44,6 +45,7 @@ if(MARS_NWE_BUILD_DOSUTILS)
|
||||
map.c
|
||||
slist.c
|
||||
flag.c
|
||||
flagdir.c
|
||||
c32ncp.c
|
||||
nwcrypt.c
|
||||
nwdebug.c
|
||||
|
||||
245
flagdir.c
Normal file
245
flagdir.c
Normal file
@@ -0,0 +1,245 @@
|
||||
/* flagdir.c - Novell FLAGDIR-like DOS utility, first 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_same(char *a, char *b)
|
||||
{
|
||||
while (*a || *b) {
|
||||
int ca = *a++;
|
||||
int cb = *b++;
|
||||
if (ca >= 'a' && ca <= 'z') ca -= 32;
|
||||
if (cb >= 'a' && cb <= 'z') cb -= 32;
|
||||
if (ca != cb) return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void fd_upcopy(char *dst, char *src, int max)
|
||||
{
|
||||
int i = 0;
|
||||
while (*src && i < max - 1) {
|
||||
char c = *src++;
|
||||
if (c >= 'a' && c <= 'z') c -= 32;
|
||||
dst[i++] = c;
|
||||
}
|
||||
dst[i] = 0;
|
||||
}
|
||||
|
||||
static int fd_get_current_drive(void)
|
||||
{
|
||||
REGS regs;
|
||||
regs.h.ah = 0x19;
|
||||
int86(0x21, ®s, ®s);
|
||||
return((int)regs.h.al);
|
||||
}
|
||||
|
||||
static int fd_current_dhandle(uint8 *dhandle)
|
||||
{
|
||||
uint8 connid = 0;
|
||||
uint8 flags = 0;
|
||||
int drive;
|
||||
|
||||
drive = fd_get_current_drive();
|
||||
if (get_drive_info((uint8)drive, &connid, dhandle, &flags))
|
||||
return(-1);
|
||||
|
||||
if (!connid || (flags & 0x80))
|
||||
return(-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 (fd_same(s, "N") || fd_same(s, "NORMAL")) {
|
||||
*clearbits |= FD_DIR_BITS;
|
||||
} else if (fd_same(s, "S") || fd_same(s, "SY") ||
|
||||
fd_same(s, "SYS") || fd_same(s, "SYSTEM")) {
|
||||
*setbits |= FD_NWFA_SY;
|
||||
} else if (fd_same(s, "H") || fd_same(s, "HIDDEN")) {
|
||||
*setbits |= FD_NWFA_H;
|
||||
} else if (fd_same(s, "DI") || fd_same(s, "DELETEINHIBIT")) {
|
||||
*setbits |= FD_NWFA_DI;
|
||||
} else if (fd_same(s, "P") || fd_same(s, "PURGE")) {
|
||||
*setbits |= FD_NWFA_P;
|
||||
} else if (fd_same(s, "RI") || fd_same(s, "RENAMEINHIBIT")) {
|
||||
*setbits |= FD_NWFA_RI;
|
||||
} else if (fd_same(s, "PRIVATE") || fd_same(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_display(char *path, uint32 attrs)
|
||||
{
|
||||
char up[260];
|
||||
int any = 0;
|
||||
|
||||
fd_upcopy(up, path, sizeof(up));
|
||||
|
||||
/*
|
||||
* Novell FLAGDIR style:
|
||||
*
|
||||
* MARS/SYS:UDIR
|
||||
* UDIR System Hidden ...
|
||||
*
|
||||
* For now we match the tested MARS/SYS: environment used by PUBLIC/NPUBLIC.
|
||||
* The NCP logic is independent from this cosmetic header.
|
||||
*/
|
||||
fprintf(stdout, "MARS/SYS:%s\n", up);
|
||||
fprintf(stdout, " %-10s ", up);
|
||||
|
||||
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 int fd_is_directory(char *path)
|
||||
{
|
||||
struct find_t ff;
|
||||
unsigned attr = _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_SUBDIR | _A_ARCH;
|
||||
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);
|
||||
}
|
||||
|
||||
int func_flagdir(int argc, char *argv[], int mode)
|
||||
{
|
||||
char *path = ".";
|
||||
uint8 dhandle = 0;
|
||||
uint32 attrs = 0;
|
||||
uint32 setbits = 0;
|
||||
uint32 clearbits = 0;
|
||||
uint32 newattrs;
|
||||
int have_change = 0;
|
||||
int i;
|
||||
|
||||
(void)mode;
|
||||
|
||||
if (argc > 1 && (fd_same(argv[1], "/?") || fd_same(argv[1], "-?") ||
|
||||
fd_same(argv[1], "?"))) {
|
||||
fd_help();
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (argc > 1)
|
||||
path = argv[1];
|
||||
|
||||
if (fd_current_dhandle(&dhandle)) {
|
||||
fprintf(stderr, "FlagDir only works on network directories.\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (!fd_is_directory(path)) {
|
||||
fprintf(stderr, "Directory %s not found.\n", path);
|
||||
return(1);
|
||||
}
|
||||
|
||||
for (i = 2; i < argc; i++) {
|
||||
if (fd_attr_mask(argv[i], &setbits, &clearbits))
|
||||
return(1);
|
||||
have_change = 1;
|
||||
}
|
||||
|
||||
if (fd_obtain(path, dhandle, &attrs)) {
|
||||
fprintf(stderr, "Unable to get directory attributes.\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (have_change) {
|
||||
newattrs = (attrs | setbits) & ~clearbits;
|
||||
if (newattrs != attrs) {
|
||||
if (fd_modify(path, dhandle, newattrs)) {
|
||||
fprintf(stderr, "Unable to change attributes.\n");
|
||||
return(1);
|
||||
}
|
||||
attrs = newattrs;
|
||||
/* Try to read back; keep requested value if readback fails. */
|
||||
fd_obtain(path, dhandle, &attrs);
|
||||
}
|
||||
}
|
||||
|
||||
fd_display(path, attrs);
|
||||
return(0);
|
||||
}
|
||||
1
net.c
1
net.c
@@ -35,6 +35,7 @@ static struct s_net_functions {
|
||||
{"PATHINS","insert search path" , func_path , 2},
|
||||
{"LOGOUT", "logout from server", func_logout , 0},
|
||||
{"FLAG", "display or modify file attributes", func_flag , 0},
|
||||
{"FLAGDIR","display or modify directory attributes",func_flagdir, 0},
|
||||
{"SLIST", "list servers", func_slist , 0},
|
||||
{"PASSWD", "change password", func_passwd , 0},
|
||||
#if 1
|
||||
|
||||
Reference in New Issue
Block a user