Files
mars-dosutils/login.c
Mario Fetka 4ad455c6df dosutils: add maintainer helpers and compare-ready tools
Add maintainer-only support used by the automated DOS compatibility
tests.

This introduces the MAINTAINER_BUILD option for the DOS tools. In
maintainer builds, LOGIN accepts the hidden /PWD: and /PASSWORD:
arguments for automated test relogin, and the DLYSTRT helper is built to
delay-start DOS batch files after the invoking batch has returned to the
prompt.

Add the WHOAMI utility and wire it into the NET command dispatch. Also
adjust SLIST and RIGHTS output to match Novell behavior more closely,
including server-not-found handling, path formatting, Supervisor rights,
missing-path errors and usage text.

Extend the test scripts to compare NPUBLIC Novell baselines against the
PUBLIC implementations. LOGIN/LOGOUT can now run automatically via
DLYSTRT and the maintainer LOGIN password option. RIGHTS gains an
additional NOPASSUSER effective-rights matrix that covers single rights,
mixed rights, Supervisor rights, ALL/N and file trustee cases.

Normal builds remain free of maintainer-only helpers and hidden password
handling.
2026-05-27 20:14:01 +02:00

1108 lines
26 KiB
C

/* login.c 21-May-96 */
/****************************************************************
* (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany *
****************************************************************/
#include "net.h"
#include "nwcrypt.h"
#include <time.h>
#ifndef BLACK
#define BLACK 0
#endif
#ifndef BLUE
#define BLUE 1
#endif
#ifndef LIGHTGRAY
#define LIGHTGRAY 7
#endif
#ifndef WHITE
#define WHITE 15
#endif
static uint8 script_login_name[64];
static uint8 script_file_server[52];
static char **build_argv(char *buf, int bufsize, char *str);
extern int read_command_file(char *fstr);
extern int get_fs_name(int connid, char *name);
static uint8 login_video_attr = 0x07;
static void login_gotoxy(int x, int y)
{
REGS regs;
regs.h.ah = 0x02;
regs.h.bh = 0x00;
regs.h.dh = (uint8)(y - 1);
regs.h.dl = (uint8)(x - 1);
int86(0x10, &regs, &regs);
}
static void login_cls_attr(uint8 attr)
{
REGS regs;
regs.h.ah = 0x06;
regs.h.al = 0x00;
regs.h.bh = attr;
regs.h.ch = 0;
regs.h.cl = 0;
regs.h.dh = 24;
regs.h.dl = 79;
int86(0x10, &regs, &regs);
login_gotoxy(1, 1);
}
static void login_write_attr(int x, int y, const char *s, uint8 attr)
{
REGS regs;
int col = x;
while (*s) {
login_gotoxy(col++, y);
regs.h.ah = 0x09;
regs.h.al = (uint8)*s++;
regs.h.bh = 0;
regs.h.bl = attr;
regs.x.cx = 1;
int86(0x10, &regs, &regs);
}
login_gotoxy(col, y);
}
static void login_fill_line(int y, uint8 attr)
{
REGS regs;
login_gotoxy(1, y);
regs.h.ah = 0x09;
regs.h.al = ' ';
regs.h.bh = 0;
regs.h.bl = attr;
regs.x.cx = 80;
int86(0x10, &regs, &regs);
}
static void login_screen_normal(void)
{
login_video_attr = 0x07;
}
static int login_help(void)
{
fprintf(stdout, "\n");
fprintf(stdout, " LOGIN General Help Mars NWE\n");
fprintf(stdout, " ------------------------------------------------------------------------\n");
fprintf(stdout, " Purpose: To gain access to the network.\n");
fprintf(stdout, " Syntax: LOGIN [/VER] [[Server | Tree/][Username] [/options]\n");
fprintf(stdout, "\n");
fprintf(stdout, " To: Use:\n");
fprintf(stdout, " Login without running login scripts /NS\n");
fprintf(stdout, " Clear the screen before executing /CLS\n");
fprintf(stdout, " Specify a script file /S filename\n");
fprintf(stdout, " Display version information /VER\n");
fprintf(stdout, "\n");
fprintf(stdout, " Examples:\n");
fprintf(stdout, " LOGIN SUPERVISOR\n");
fprintf(stdout, " LOGIN MARS/SUPERVISOR\n");
fprintf(stdout, "\n");
return(0);
}
static void login_banner(void)
{
login_cls_attr(0x07); /* normal black background */
/*
* NetWare-like header, but blue for Mars NWE:
* blue separator
* blue title line
* blue separator
* then normal black prompt area.
*/
login_fill_line(1, 0x1f); /* white on blue */
login_fill_line(2, 0x1f); /* white on blue */
login_write_attr(36, 2, "Mars NWE", 0x1f);
login_fill_line(3, 0x1f); /* white on blue */
login_screen_normal();
login_gotoxy(1, 4);
}
static char *skip_spaces(char *p)
{
while (*p == 32 || *p == '\t') p++;
return(p);
}
static void strip_quotes(char *s)
{
char *d = s;
char quote = 0;
while (*s) {
if (!quote && (*s == '"' || *s == '\'')) {
quote = *s++;
continue;
}
if (quote && *s == quote) {
quote = 0;
s++;
continue;
}
*d++ = *s++;
}
*d = '\0';
}
static void script_get_timevar(char *name, char *out, int outlen)
{
time_t now;
struct tm *tmv;
int hour;
static char *months[] = {
"JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
"JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"
};
static char *days[] = {
"SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY",
"THURSDAY", "FRIDAY", "SATURDAY"
};
*out = '\0';
time(&now);
tmv = localtime(&now);
if (!tmv) return;
upstr(name);
if (!strcmp(name, "GREETING_TIME")) {
if (tmv->tm_hour < 12) strcpy(out, "MORNING");
else if (tmv->tm_hour < 18) strcpy(out, "AFTERNOON");
else strcpy(out, "EVENING");
} else if (!strcmp(name, "MONTH_NAME")) {
strmaxcpy(out, months[tmv->tm_mon], outlen - 1);
} else if (!strcmp(name, "MONTH")) {
sprintf(out, "%02d", tmv->tm_mon + 1);
} else if (!strcmp(name, "DAY")) {
sprintf(out, "%02d", tmv->tm_mday);
} else if (!strcmp(name, "YEAR")) {
sprintf(out, "%04d", tmv->tm_year + 1900);
} else if (!strcmp(name, "DAY_OF_WEEK")) {
strmaxcpy(out, days[tmv->tm_wday], outlen - 1);
} else if (!strcmp(name, "HOUR")) {
hour = tmv->tm_hour % 12;
if (!hour) hour = 12;
sprintf(out, "%d", hour);
} else if (!strcmp(name, "MINUTE")) {
sprintf(out, "%02d", tmv->tm_min);
} else if (!strcmp(name, "SECOND")) {
sprintf(out, "%02d", tmv->tm_sec);
} else if (!strcmp(name, "AM_PM")) {
strcpy(out, tmv->tm_hour >= 12 ? "PM" : "AM");
}
}
static void script_expand_var(char *name, char *out, int outlen)
{
upstr(name);
*out = '\0';
if (!strcmp(name, "LOGIN_NAME")) {
strmaxcpy(out, script_login_name, outlen - 1);
} else if (!strcmp(name, "FILE_SERVER")) {
strmaxcpy(out, script_file_server, outlen - 1);
} else if (!strcmp(name, "P_STATION") || !strcmp(name, "STATION")) {
strcpy(out, "000000000000");
} else {
script_get_timevar(name, out, outlen);
if (!*out) {
strcpy(out, "%");
strncat(out, name, outlen - strlen(out) - 1);
}
}
}
static void script_put_expanded(char *s)
{
while (s && *s) {
if (*s == '%') {
char name[64];
char value[128];
int i = 0;
s++;
while ((*s == '_' ||
(*s >= 'A' && *s <= 'Z') ||
(*s >= 'a' && *s <= 'z') ||
(*s >= '0' && *s <= '9')) &&
i < (int)sizeof(name) - 1) {
name[i++] = *s++;
}
name[i] = '\0';
if (i) {
script_expand_var(name, value, sizeof(value));
fprintf(stdout, "%s", value);
} else {
fputc('%', stdout);
}
} else {
fputc(*s++, stdout);
}
}
}
static void script_write(char *p)
{
p = skip_spaces(p);
strip_quotes(p);
script_put_expanded(p);
fputc('\n', stdout);
}
static void script_join_args(char **argv, int argc)
{
if (argc > 2) {
char *p = argv[argc-1];
while (p-- > argv[1]) {
if (*p == '\0') *p = 32;
}
}
}
static void script_call_line(char *line)
{
char *buf;
char **argv;
int argc = 0;
char **pp;
buf = xmalloc(512);
argv = build_argv(buf, 512, line);
if (argv != NULL) {
pp = argv;
while (*pp) {
argc++;
pp++;
}
if (argc > 0) {
upstr(argv[0]);
call_func_entry(argc, argv);
}
}
xfree(buf);
}
static int script_eval_if(char *line)
{
char tmp[512];
char *p;
char *q;
int neg = 0;
strmaxcpy(tmp, line, sizeof(tmp) - 1);
upstr(tmp);
if (strstr(tmp, "MEMBER OF") != NULL) {
if (strstr(tmp, "EVERYONE") != NULL) return(1);
return(0);
}
p = strstr(tmp, "LOGIN_NAME");
if (p != NULL) {
q = strstr(p, "<>");
if (q != NULL) neg = 1;
else q = strchr(p, '=');
if (q != NULL) {
char want[64];
char have[64];
int i = 0;
q += neg ? 2 : 1;
q = skip_spaces(q);
if (*q == '"' || *q == '\'') q++;
while (*q && *q != '"' && *q != '\'' && *q != 32 && *q != '\t' && i < 63)
want[i++] = *q++;
want[i] = '\0';
strmaxcpy(have, script_login_name, sizeof(have) - 1);
upstr(have);
if (neg) return(strcmp(have, want) != 0);
return(strcmp(have, want) == 0);
}
}
p = strstr(tmp, "DAY_OF_WEEK");
if (p != NULL) {
q = strchr(p, '=');
if (q != NULL) {
char want[64];
char have[64];
int i = 0;
q++;
q = skip_spaces(q);
if (*q == '"' || *q == '\'') q++;
while (*q && *q != '"' && *q != '\'' && *q != 32 && *q != '\t' && i < 63)
want[i++] = *q++;
want[i] = '\0';
strcpy(have, "DAY_OF_WEEK");
script_get_timevar(have, have, sizeof(have));
upstr(have);
return(strcmp(have, want) == 0);
}
}
return(0);
}
static int login_strnicmp(char *a, char *b, int n)
{
while (n-- > 0) {
int ca = *a++;
int cb = *b++;
if (ca >= 'a' && ca <= 'z') ca -= 32;
if (cb >= 'a' && cb <= 'z') cb -= 32;
if (ca != cb) return(ca - cb);
if (!ca) return(0);
}
return(0);
}
static int script_execute_line(char *line)
{
char work[512];
char cmd[32];
char *p;
char *arg;
int i;
strmaxcpy(work, line, sizeof(work) - 1);
p = skip_spaces(work);
if (!*p || *p == ';') return(0);
i = 0;
while (p[i] && p[i] != 32 && p[i] != '\t' && i < 31) {
cmd[i] = p[i];
i++;
}
cmd[i] = '\0';
upstr(cmd);
arg = skip_spaces(p + i);
if (!strcmp(cmd, "WRITE") || !strcmp(cmd, "ECHO")) {
script_write(arg);
return(0);
}
if (!strcmp(cmd, "PAUSE")) {
fprintf(stdout, "Strike any key when ready . . .");
fflush(stdout);
getch();
fprintf(stdout, "\n");
return(0);
}
if (!strcmp(cmd, "CLS")) {
login_cls_attr(0x07);
return(0);
}
if (!strcmp(cmd, "BREAK")) {
return(0);
}
if (!strcmp(cmd, "SET")) {
if (*arg) putglobenv(arg);
return(0);
}
if (!strcmp(cmd, "DRIVE")) {
arg = skip_spaces(arg);
if ((*arg >= 'A' && *arg <= 'Z') || (*arg >= 'a' && *arg <= 'z')) {
if (*arg >= 'a') setdisk(*arg - 'a');
else setdisk(*arg - 'A');
}
return(0);
}
if (!strcmp(cmd, "MAP")) {
char up[512];
strmaxcpy(up, arg, sizeof(up) - 1);
upstr(up);
if (!strncmp(up, "DISPLAY", 7)) {
return(0);
}
if (!strncmp(up, "ROOT ", 5)) {
char callbuf[512];
sprintf(callbuf, "MAP %s", skip_spaces(arg + 5));
script_call_line(callbuf);
return(0);
}
if (!strncmp(up, "INS ", 4) || !strncmp(up, "INSERT ", 7)) {
char callbuf[512];
char *a = arg;
if (!login_strnicmp(up, "INS ", 4)) a += 4;
else a += 7;
sprintf(callbuf, "PATHINS %s", skip_spaces(a));
script_call_line(callbuf);
return(0);
}
if (!strncmp(up, "DEL ", 4) || !strncmp(up, "DELETE ", 7)) {
char callbuf[512];
char *a = arg;
if (!login_strnicmp(up, "DEL ", 4)) a += 4;
else a += 7;
sprintf(callbuf, "PATHDEL %s", skip_spaces(a));
script_call_line(callbuf);
return(0);
}
}
if (!strcmp(cmd, "ATTACH")) {
return(0);
}
if (!strcmp(cmd, "EXIT")) {
return(1);
}
script_call_line(p);
return(0);
}
static int try_login_script_file(char *name)
{
return(read_command_file(name));
}
static int run_login_script(void)
{
char profile[200];
char drive;
/*
* Novell LOGIN looks for the system login script using server based paths,
* for example \\SERVER\SYS\PUBLIC\NET$LOG.DAT. Try that first.
*/
if (*script_file_server) {
sprintf(profile, "\\\\%s\\SYS\\PUBLIC\\NET$LOG.DAT", script_file_server);
if (try_login_script_file(profile) != -2) return(0);
sprintf(profile, "\\\\%s\\SYS\\PUBLIC\\net$log.dat", script_file_server);
if (try_login_script_file(profile) != -2) return(0);
sprintf(profile, "\\\\%s\\SYS\\LOGIN\\LOGIN", script_file_server);
if (try_login_script_file(profile) != -2) return(0);
sprintf(profile, "\\\\%s\\SYS\\LOGIN\\NET$LOG.DAT", script_file_server);
if (try_login_script_file(profile) != -2) return(0);
}
/*
* Then try current directory and the executable path. LOGIN.EXE is often
* executed from PUBLIC, so this covers SYS:PUBLIC\NET$LOG.DAT without
* relying on an absolute drive path.
*/
if (try_login_script_file("NET$LOG.DAT") != -2) return(0);
if (try_login_script_file("net$log.dat") != -2) return(0);
if (try_login_script_file("LOGIN") != -2) return(0);
if (try_login_script_file("login") != -2) return(0);
if (*prgpath) {
sprintf(profile, "%sNET$LOG.DAT", prgpath);
if (try_login_script_file(profile) != -2) return(0);
sprintf(profile, "%snet$log.dat", prgpath);
if (try_login_script_file(profile) != -2) return(0);
sprintf(profile, "%sLOGIN", prgpath);
if (try_login_script_file(profile) != -2) return(0);
sprintf(profile, "%slogin", prgpath);
if (try_login_script_file(profile) != -2) return(0);
}
/*
* Fallbacks for requesters/runtimes that cannot open UNC from C fopen().
*/
if (try_login_script_file("\\PUBLIC\\NET$LOG.DAT") != -2) return(0);
if (try_login_script_file("\\public\\net$log.dat") != -2) return(0);
if (try_login_script_file("\\PUBLIC\\LOGIN") != -2) return(0);
if (try_login_script_file("\\public\\login") != -2) return(0);
if (try_login_script_file("\\LOGIN\\LOGIN") != -2) return(0);
if (try_login_script_file("\\login\\login") != -2) return(0);
if (try_login_script_file("\\LOGIN\\NET$LOG.DAT") != -2) return(0);
if (try_login_script_file("\\login\\net$log.dat") != -2) return(0);
for (drive = 'C'; drive <= 'Z'; drive++) {
sprintf(profile, "%c:\\PUBLIC\\NET$LOG.DAT", drive);
if (try_login_script_file(profile) != -2) return(0);
sprintf(profile, "%c:\\public\\net$log.dat", drive);
if (try_login_script_file(profile) != -2) return(0);
sprintf(profile, "%c:\\PUBLIC\\LOGIN", drive);
if (try_login_script_file(profile) != -2) return(0);
sprintf(profile, "%c:\\LOGIN\\LOGIN", drive);
if (try_login_script_file(profile) != -2) return(0);
sprintf(profile, "%c:\\LOGIN\\NET$LOG.DAT", drive);
if (try_login_script_file(profile) != -2) return(0);
}
return(-2);
}
static int do_change_object_passwd(char *name,
uint16 objtyp,
char *oldpassword,
char *newpassword)
{
uint8 key[8];
if (!ncp_17_17(key)) {
uint32 objid = ncp_17_35(name, objtyp);
if (objid) {
uint8 oldpwd[16]; /* old passwd as stored by server */
uint8 newpwd[16]; /* new passwd as stored by server */
uint8 cryptkey[8];
uint8 tmpid[4];
uint8 passwdx;
int newlen;
memcpy(cryptkey, key, 8);
U32_TO_BE32(objid, tmpid);
shuffle(tmpid, oldpassword, strlen(oldpassword), oldpwd);
shuffle(tmpid, newpassword, strlen(newpassword), newpwd);
nw_encrypt(cryptkey, oldpwd, cryptkey);
/*
* Same keyed change password transformation as ncpfs
* ncp_change_login_passwd(): encrypt both 8-byte halves of the
* stored new password using the stored old password as key material.
* newpassencrypt() intentionally mutates oldpwd; the passwd length
* byte must be calculated afterwards, just like ncpfs does it.
*/
newpassencrypt(oldpwd, newpwd);
newpassencrypt(oldpwd + 8, newpwd + 8);
newlen = strlen(newpassword);
if (newlen > 63) newlen = 63;
passwdx = (uint8)(((newlen ^ oldpwd[0] ^ oldpwd[1]) & 0x7f) | 0x40);
if (!ncp_17_4b(cryptkey, name, objtyp, passwdx, newpwd)) {
;;
return(0);
}
}
}
/*
* Fallback for old servers/requesters where Get Encryption Key is not
* available. Keep the original unencrypted behavior as fallback only.
*/
if (!ncp_17_40(name, objtyp, oldpassword, newpassword)) {
;;
return(0);
}
return(-1);
}
static int do_object_login(char *name, uint16 objtyp, char *password, int option)
{
uint8 key[8];
if (!(option & 1) && !ncp_17_17(key)) {
uint32 objid = ncp_17_35(name, objtyp);
if (objid) {
uint8 buff[128];
uint8 encrypted[8];
uint8 tmpid[4];
U32_TO_BE32(objid, tmpid);
shuffle(tmpid, password, strlen(password), buff);
nw_encrypt(key, buff, encrypted);
if (!ncp_17_18(encrypted, name, objtyp)) {
;;
return(0);
}
}
} else { /* now we use old unencrypted algorithmus */
if (!ncp_17_14(name, objtyp, password)) {
return(0);
}
}
return(-1);
}
static void beep(void)
{
fprintf(stdout, "\007");
}
static int get_raw_str(uint8 *s, int maxlen, int doecho)
/* returns len of readed str */
{
int len = 0;
while (len < maxlen){
int key = getch();
if (key == '\r' || key == '\n') break;
switch (key) {
case 8 : if (len) {
--len;
--s;
if (doecho) {
fprintf(stdout, "\010 \010");
fflush(stdout);
}
} else beep();
continue;
case '\t': beep();
continue;
default : *s++=(uint8)key;
len++;
break;
} /* switch */
if (doecho) {
fprintf(stdout, "%c", (uint8)key);
fflush(stdout);
}
}
*s='\0';
return(len);
}
static void getstr(char *what, char *str, int rsize, int doecho)
{
fprintf(stdout, "%s: ", what);
fflush(stdout);
get_raw_str(str, rsize, doecho);
fprintf(stdout, "\n");
}
static int login_usage(void)
{
return(login_help());
}
#ifdef MAINTAINER_BUILD
static int login_hidden_password_arg(char *arg, uint8 *passwd, int passwd_size)
{
char *value = NULL;
if (!strnicmp(arg, "/PASSWORD:", 10) || !strnicmp(arg, "-PASSWORD:", 10))
value = arg + 10;
else if (!strnicmp(arg, "/PWD:", 5) || !strnicmp(arg, "-PWD:", 5))
value = arg + 5;
if (value != NULL) {
strmaxcpy(passwd, value, passwd_size - 1);
memset(arg, 0, strlen(arg));
return(1);
}
return(0);
}
static int login_extract_hidden_password(int *argc, char *argv[],
uint8 *passwd, int passwd_size)
{
int i;
passwd[0] = '\0';
for (i = 1; i < *argc; i++) {
if (login_hidden_password_arg(argv[i], passwd, passwd_size)) {
int j;
for (j = i; j < (*argc - 1); j++)
argv[j] = argv[j + 1];
argv[*argc - 1] = NULL;
(*argc)--;
return(1);
}
}
return(0);
}
#endif
int func_login(int argc, char *argv[], int mode)
{
int result=-1;
int option=0;
uint8 uname[200];
uint8 upasswd[200];
#ifdef MAINTAINER_BUILD
uint8 hidden_passwd[200];
int have_hidden_passwd = 0;
#endif
SEARCH_VECTOR save_drives;
int interactive_login = 0;
int no_script = 0;
if (argc > 1) {
if (!strcmp(argv[1], "/?") || !strcmp(argv[1], "-?") || !strcmp(argv[1], "?"))
return(login_help());
if (!strcmp(argv[1], "/VER") || !strcmp(argv[1], "-VER")) {
fprintf(stdout, "Mars NWE LOGIN 0.99\n");
return(0);
}
}
#ifdef MAINTAINER_BUILD
have_hidden_passwd = login_extract_hidden_password(&argc, argv,
hidden_passwd,
sizeof(hidden_passwd));
#endif
if (argc > 1) {
if (argv[1][0] == '-' || argv[1][0] == '/') {
if (argv[1][1] == 'u' || argv[1][1] == 'U') option |= 1;
else if (!strcmp(argv[1], "/NS") || !strcmp(argv[1], "-NS")) no_script = 1;
else if (!strcmp(argv[1], "/CLS") || !strcmp(argv[1], "-CLS")) login_cls_attr(0x07);
else return(login_usage());
argc--;
argv++;
}
}
get_search_drive_vektor(save_drives);
remove_nwpathes();
if (argc > 1) strmaxcpy(uname, argv[1], sizeof(uname) -1);
else uname[0]='\0';
#ifdef MAINTAINER_BUILD
if (have_hidden_passwd) strmaxcpy(upasswd, hidden_passwd, sizeof(upasswd) -1);
else
#endif
if (argc > 2) strmaxcpy(upasswd, argv[2], sizeof(upasswd) -1);
else upasswd[0]='\0';
if (!uname[0]) {
interactive_login = 1;
login_banner();
}
while (result) {
if (!uname[0]) getstr("Enter your login name", uname, sizeof(uname)-1, 1);
if (uname[0]) {
upstr(uname);
upstr(upasswd);
if ((result = do_object_login(uname, 0x1, upasswd, option)) < 0 && !*upasswd) {
getstr("Enter your password", upasswd, sizeof(upasswd)-1, 0);
upstr(upasswd);
result = do_object_login(uname, 0x1, upasswd, option);
}
if (result < 0) {
fprintf(stdout, "Login incorrect\n\n");
uname[0] = '\0';
upasswd[0] = '\0';
}
} else break;
}
if (result > -1) {
strmaxcpy(script_login_name, uname, sizeof(script_login_name) - 1);
if (get_fs_name(1, script_file_server))
strcpy(script_file_server, "MARS");
if (interactive_login)
fprintf(stdout, "You are attached to server %s.\n", script_file_server);
remove_nwpathes();
if (!no_script)
run_login_script();
} else {
(void)set_search_drive_vektor(save_drives);
}
#ifdef MAINTAINER_BUILD
memset(hidden_passwd, 0, sizeof(hidden_passwd));
#endif
memset(upasswd, 0, sizeof(upasswd));
return(result);
}
int func_logout(int argc, char *argv[], int mode)
{
remove_nwpathes();
if (logout()) {
fprintf(stderr, "logout=%d\n", neterrno);
return(1);
}
return(0);
}
int func_passwd(int argc, char *argv[], int mode)
{
int result=0;
uint8 uname[100];
uint8 upasswd[130];
uint32 my_obj_id;
if (ncp_14_46(&my_obj_id) < 0 || my_obj_id == MAX_U32 || !my_obj_id) {
fprintf(stderr, "Cannot get actual user id\n");
result = -1;
}
if (!result && argc > 1) {
uint32 obj_id;
strmaxcpy(uname, argv[1], sizeof(uname) -1);
upstr(uname);
obj_id = ncp_17_35(uname, 1);
if (!obj_id) {
fprintf(stderr, "Unkwown user: %s\n", uname);
return(-1);
}
} else if (!result) {
uint16 obj_typ;
if (ncp_17_36(my_obj_id, uname, &obj_typ) || obj_typ != 1) {
fprintf(stderr, "Cannot get actual username\n");
result=-1;
}
}
if (!result && *uname) {
uint8 newpasswd[130];
uint8 newpasswd2[130];
if (my_obj_id == 1L) *upasswd='\0';
else {
getstr("Old password", upasswd, sizeof(upasswd)-1, 0);
upstr(upasswd);
}
getstr("New password", newpasswd, sizeof(newpasswd)-1, 0);
getstr("New password again", newpasswd2, sizeof(newpasswd2)-1, 0);
if (!strcmp(newpasswd, newpasswd2)) {
upstr(uname);
upstr(newpasswd);
if (do_change_object_passwd(uname, 1, upasswd, newpasswd) < 0)
result = -1;
} else {
result = -1;
fprintf(stderr, "Password misspelled\n");
}
}
if (result < 0) fprintf(stderr, "Password not changed");
return(result);
}
static int get_line(FILE *f, char *buff, int bufsize, uint8 *str, int strsize)
/* returns command line or -1 if ends */
{
if ((FILE*) NULL != f) {
while (fgets(buff, bufsize, f) != NULL){
char *p = buff;
char *beg = NULL;
char c;
int len=0;
while (0 != (c = *p++) && c != '\n' && c != '\r' && c != '#') {
if (!beg){
if (c != '\t' && c != 32) {
beg = p - 1;
len = 1;
}
} else ++len;
}
if (len) {
strmaxcpy((uint8*)str, (uint8*)beg, min(len, strsize-1));
return(0);
}
}
}
return(-1);
}
static char **build_argv(char *buf, int bufsize, char *command)
/* routine returns **argv for use with execv routines */
/* buf will contain the path component */
{
int len = strlen(command);
int offset = ((len+4) / 4) * 4; /* aligned offset for **argv */
int components = (bufsize - offset) / 4;
if (components > 1) { /* minimal argv[0] + NULL */
char **argv = (char **)(buf+offset);
char **pp = argv;
char *p = buf;
char c;
int i=0;
--components;
memcpy(buf, command, len);
memset(buf+len, 0, bufsize - len);
*pp = p;
while ((0 != (c = *p++)) && i < components) {
if (c == 32 || c == '\t') {
*(p-1) = '\0';
if (*p != 32 && *p != '\t') {
*(++pp)=p;
i++;
}
} else if (!i && c == '/') { /* here i must get argv[0] */
*pp=p;
}
}
return(argv);
}
return(NULL);
}
int read_command_file(char *fstr)
{
FILE *f=fopen(fstr, "r");
int result=-1;
if (f != NULL) {
char *linebuf = xmalloc(512);
char *buf = xmalloc(512);
int stack[16];
int level = 0;
int active = 1;
while (get_line(f, buf, 512, linebuf, 512) > -1) {
char tmp[512];
char *p;
strmaxcpy(tmp, linebuf, sizeof(tmp) - 1);
p = skip_spaces(tmp);
upstr(p);
if (!strncmp(p, "IF ", 3)) {
if (level < 16) {
stack[level++] = active;
active = active && script_eval_if(linebuf);
}
result = 0;
continue;
}
if (!strcmp(p, "END") || !strncmp(p, "END ", 4)) {
if (level > 0) active = stack[--level];
result = 0;
continue;
}
if (!active) {
result = 0;
continue;
}
if (script_execute_line(linebuf))
break;
result = 0;
}
fclose(f);
xfree(linebuf);
xfree(buf);
} else result=-2;
return(result);
}
int func_profile(int argc, char *argv[], int mode)
{
if (argc < 2) {
fprintf(stderr, "usage:\t%s fn\n", funcname);
return(-1);
}
if (read_command_file(argv[1]) == -2) {
fprintf(stderr, "command file %s not found\n", argv[1]);
}
return(0);
}
int func_cwd(int argc, char *argv[], int mode)
{
char pathname[65];
int len;
if (argc < 2) {
fprintf(stderr, "usage:\t%s path\n", funcname);
return(-1);
}
strmaxcpy(pathname, argv[1], sizeof(pathname) -1);
korrpath(pathname);
if (0 != (len = strlen(pathname))) {
char *p=pathname+len-1;
if (*p == '/' || *p == ':') {
*(++p) = '.';
*(++p) = '\0';
len++;
}
if (!chdir(pathname)) {
if (len > 2 && *(pathname+1) == ':') /* device changed */
setdisk(*pathname - 'a' );
} else {
fprintf(stderr, "cannot chdir to %s\n", pathname);
return(1);
}
return(0);
} else return(-1);
}
int func_echo(int argc, char *argv[], int mode)
{
if (argc > 1)
fprintf(stdout, "%s\n", argv[1]);
return(0);
}
int func_exec(int argc, char *argv[], int mode)
{
if (argc > 1) {
char *buf = xmalloc(512);
char *buff = xmalloc(512);
char *p = buff;
int k = 0;
char **nargv;
while (++k < argc) {
strcpy(p, argv[k]);
p += strlen(argv[k]);
*p++ = 32;
*p = '\0';
}
nargv=build_argv(buf, 512, buff);
xfree(buff);
if (nargv != NULL) {
if (!mode)
spawnvp(P_WAIT, buf, (const char *const *)nargv);
else
execvp(buf, (const char *const *)nargv);
}
xfree(buf);
}
return(0);
}