dosutils: add Novell-style paging to FLAG tools and SLIST

- add a shared DOS pager helper for long tool output
- page FLAG wildcard output with the Novell continue prompt
- fix FLAGDIR current-directory handling for "." and volume root
- add FLAGDIR wildcard directory listing support
- page FLAGDIR wildcard output like Novell FLAGDIR
- keep FLAGDIR display formatting aligned with Novell output
- make SLIST /CONTINUE enable continuous output
- keep SLIST bindery scanning compatible with ncpfs behavior
- preserve SLIST NET_ADDRESS display and default server marking
This commit is contained in:
Mario Fetka
2026-05-24 15:51:38 +02:00
parent f940d2d88e
commit fc97eb8d25
5 changed files with 304 additions and 42 deletions

298
flagdir.c
View File

@@ -1,4 +1,4 @@
/* flagdir.c - Novell FLAGDIR-like DOS utility, first Client32 version */
/* flagdir.c - Novell FLAGDIR-like DOS utility, Client32 version */
#include "net.h"
#include "c32ncp.h"
@@ -43,8 +43,12 @@ static int fd_same(char *a, char *b)
static void fd_upcopy(char *dst, char *src, int max)
{
int i = 0;
if (!src) src = "";
while (*src && i < max - 1) {
char c = *src++;
if (c == '/') c = '\\';
if (c >= 'a' && c <= 'z') c -= 32;
dst[i++] = c;
}
@@ -75,7 +79,6 @@ static int fd_current_dhandle(uint8 *dhandle)
return(0);
}
static int fd_current_prefix(char *out, int max)
{
uint8 connid = 0;
@@ -129,6 +132,125 @@ static int fd_current_prefix(char *out, int max)
return(0);
}
static int fd_current_display_path(uint8 dhandle, char *out, int max)
{
char path[260];
char *p;
if (!out || max < 2)
return(-1);
out[0] = '\0';
path[0] = '\0';
if (get_dir_path(dhandle, path) || !path[0])
return(-1);
p = strchr(path, ':');
if (p)
p++;
else
p = path;
if (!*p)
out[0] = '\0';
else
strmaxcpy(out, p, max - 1);
return(0);
}
static int fd_is_current_path(char *path)
{
if (!path || !*path) return(1);
if (fd_same(path, ".")) return(1);
if (fd_same(path, ".\\")) return(1);
if (fd_same(path, "./")) return(1);
return(0);
}
static int fd_has_wildcards(char *s)
{
if (!s) return(0);
while (*s) {
if (*s == '*' || *s == '?')
return(1);
s++;
}
return(0);
}
static void fd_split_pattern(char *spec, char *dir, char *pat)
{
char tmp[260];
char *p;
if (!spec || !*spec) {
strcpy(dir, ".");
strcpy(pat, "*.*");
return;
}
strmaxcpy(tmp, spec, sizeof(tmp) - 1);
p = strrchr(tmp, '\\');
if (!p) p = strrchr(tmp, '/');
if (p) {
*p++ = '\0';
if (tmp[0])
strmaxcpy(dir, tmp, 259);
else
strcpy(dir, ".");
strmaxcpy(pat, p, 259);
} else {
strcpy(dir, ".");
strmaxcpy(pat, tmp, 259);
}
if (!pat[0])
strcpy(pat, "*.*");
}
static void fd_join_path(char *out, char *dir, char *name, int max)
{
int len;
out[0] = '\0';
if (!dir || !dir[0] || fd_same(dir, ".")) {
strmaxcpy(out, name, max - 1);
return;
}
strmaxcpy(out, dir, max - 1);
len = strlen(out);
if (len > 0 && out[len - 1] != '\\' && out[len - 1] != '/' &&
out[len - 1] != ':') {
if (len < max - 1) {
out[len++] = '\\';
out[len] = '\0';
}
}
if ((int)(strlen(out) + strlen(name)) < max - 1)
strcat(out, name);
}
static void fd_basename(char *out, char *path, int max)
{
char up[260];
char *p;
fd_upcopy(up, path, sizeof(up));
p = strrchr(up, '\\');
if (!p) p = strrchr(up, ':');
if (p)
strmaxcpy(out, p + 1, max - 1);
else
strmaxcpy(out, up, max - 1);
}
static void fd_help(void)
{
@@ -166,21 +288,10 @@ static int fd_attr_mask(char *s, uint32 *setbits, uint32 *clearbits)
return(0);
}
static void fd_display(char *path, uint32 attrs)
static void fd_print_attrs(uint32 attrs)
{
char up[260];
int any = 0;
fd_upcopy(up, path, sizeof(up));
{
char prefix[90];
if (fd_current_prefix(prefix, sizeof(prefix)))
prefix[0] = '\0';
fprintf(stdout, "%s%s \n", prefix, up);
}
fprintf(stdout, " %-12.12s ", up);
if (!(attrs & FD_DIR_BITS)) {
fprintf(stdout, "Normal\n");
return;
@@ -210,12 +321,45 @@ static void fd_display(char *path, uint32 attrs)
fprintf(stdout, "\n");
}
static void fd_display_header(char *path)
{
char up[260];
char prefix[90];
fd_upcopy(up, path, sizeof(up));
if (fd_current_prefix(prefix, sizeof(prefix)))
prefix[0] = '\0';
fprintf(stdout, "%s%s \n", prefix, up);
}
static void fd_display_row(char *name, uint32 attrs)
{
char base[260];
fd_basename(base, name, sizeof(base));
fprintf(stdout, " %-12.12s ", base);
fd_print_attrs(attrs);
}
static void fd_display(char *path, uint32 attrs)
{
fd_display_header(path);
fd_display_row(path, attrs);
}
static int fd_is_directory(char *path)
{
struct find_t ff;
unsigned attr = _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_SUBDIR | _A_ARCH;
if (fd_is_current_path(path))
return(1);
if (_dos_findfirst(path, attr, &ff))
return(0);
return((ff.attrib & _A_SUBDIR) != 0);
}
@@ -235,14 +379,103 @@ static int fd_modify(char *path, uint8 dhandle, uint32 attrs)
return(-1);
}
static int fd_process_one(char *path, char *display_path, uint8 dhandle,
uint32 setbits, uint32 clearbits,
int have_change, int show_header)
{
char *ncp_path;
uint32 attrs;
uint32 newattrs;
if (!fd_is_directory(path)) {
fprintf(stderr, "Directory %s not found.\n", path);
return(1);
}
ncp_path = fd_is_current_path(path) ? "" : path;
if (fd_obtain(ncp_path, dhandle, &attrs)) {
if (fd_is_current_path(path) && display_path && !display_path[0] &&
!have_change) {
attrs = 0;
} else {
fprintf(stderr, "Unable to get directory attributes.\n");
return(1);
}
}
if (have_change) {
newattrs = (attrs | setbits) & ~clearbits;
if (newattrs != attrs) {
if (fd_modify(ncp_path, dhandle, newattrs)) {
fprintf(stderr, "Unable to change attributes.\n");
return(1);
}
attrs = newattrs;
fd_obtain(ncp_path, dhandle, &attrs);
}
}
if (show_header)
fd_display(display_path, attrs);
else
fd_display_row(display_path, attrs);
return(0);
}
static int fd_process_wild(char *spec, uint8 dhandle,
uint32 setbits, uint32 clearbits,
int have_change)
{
struct find_t ff;
char dir[260];
char pat[260];
char search[260];
char full[260];
int found = 0;
int rc = 0;
int lines = 0;
int continuous = 0;
unsigned attr = _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_SUBDIR | _A_ARCH;
fd_split_pattern(spec, dir, pat);
fd_join_path(search, dir, pat, sizeof(search));
if (_dos_findfirst(search, attr, &ff) != 0) {
fprintf(stderr, "Directory %s not found.\n", spec);
return(1);
}
fd_display_header(spec);
do {
if ((ff.attrib & _A_SUBDIR) && strcmp(ff.name, ".") &&
strcmp(ff.name, "..")) {
fd_join_path(full, dir, ff.name, sizeof(full));
if (fd_process_one(full, ff.name, dhandle, setbits, clearbits,
have_change, 0))
rc = 1;
found++;
tool_page_line(&lines, &continuous);
}
} while (_dos_findnext(&ff) == 0);
if (!found) {
fprintf(stderr, "Directory %s not found.\n", spec);
return(1);
}
return(rc);
}
int func_flagdir(int argc, char *argv[], int mode)
{
char *path = ".";
char display_path[260];
uint8 dhandle = 0;
uint32 attrs = 0;
uint32 setbits = 0;
uint32 clearbits = 0;
uint32 newattrs;
int have_change = 0;
int i;
@@ -262,35 +495,22 @@ int func_flagdir(int argc, char *argv[], int mode)
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 (fd_has_wildcards(path))
return(fd_process_wild(path, dhandle, setbits, clearbits, have_change));
if (fd_is_current_path(path)) {
if (fd_current_display_path(dhandle, display_path, sizeof(display_path)))
strcpy(display_path, ".");
} else {
strmaxcpy(display_path, path, sizeof(display_path) - 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);
return(fd_process_one(path, display_path, dhandle,
setbits, clearbits, have_change, 1));
}