Files
mars-dosutils/login.c
Mario Fetka 50524cf759 dosutils: add GPL-2 headers and file descriptions
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.
2026-05-29 08:07:09 +02:00

1163 lines
28 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: LOGIN, LOGOUT, PASSWD and PROFILE command implementation for NetWare servers.
* Depends on: net.h, nwcrypt.h/nwcrypt.c password encryption helpers, netcall.c requester helpers, tools.c shared utility routines.
*/
#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 int login_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) {
if (server) server[0] = '\0';
return(-1);
}
if (server)
strmaxcpy(server, repl.data, 47);
return(0);
}
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 SERVER/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);
script_file_server[0] = '\0';
if (get_fs_name(1, script_file_server) || !script_file_server[0])
login_ncp23_server_info(script_file_server);
if (!script_file_server[0]) {
fprintf(stdout, "No known file server.\n");
#ifdef MAINTAINER_BUILD
memset(hidden_passwd, 0, sizeof(hidden_passwd));
#endif
memset(upasswd, 0, sizeof(upasswd));
return(1);
}
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);
}