
/*
 *  SPASSWD.C
 *
 *  DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
 *
 *  PASSWORD SERVER
 *
 *  user-password entry.  USER entries in s:dnet.config are scanned for
 *  a match and the various dnet enviroment variables are set accordingly.
 */

#include "defs.h"

int do_password ARGS((void *));
void DPuts ARGS((void *, char *));
int DGetLine ARGS((void *, char *, short));

int
brk()
{
    return(0);
}

void
#ifdef LATTICE
_main(str)
#else
_main(len,str)
#endif
char *str;
{
    struct MsgPort *port;
    PROC    *myproc = (PROC *)FindTask(NULL);
    void    *chan;
    long    mask, rmask;
    short   res;

    onbreak(brk);

    if (strncmp(str, "__dnet", 6) != 0) {
	Version("SPasswd", VERSION, SPASSWD_VERSION);
	_exit(0);
    }

    port = DListen(PORT_PASSWD);
    WaitPort(&myproc->pr_MsgPort);
    ReplyMsg(GetMsg(&myproc->pr_MsgPort));

    mask = SIGBREAKF_CTRL_C|(1 << port->mp_SigBit);
    for (;;) {
	rmask = Wait(mask);
	if (rmask & SIGBREAKF_CTRL_C)
	    break;
	while (chan = DAccept(port)) {
	    res = do_password(chan);
	    Delay(10L);     /*  prevent name scan   */
	    if (res)
		DPuts(chan, "user-password accepted\n");
	    else
		DPuts(chan, "user-password failed\n");
	    Delay(50L);     /*  prevent name scan   */
	    DClose(chan);
	}
    }
    DUnListen(port);
}

int
do_password(chan)
void *chan;
{
    static char user[64];
    static char pass[64];
    static char buf[128];
    static char suser[64];
    static char spass[64];
    short res;
    long fh;
    short i, n;
    int s_level, s_read, s_write;

    DPuts(chan, "User Name: ");
    res = DGetLine(chan, user, 64);
    if (res < 0)
	return(0);
    DIoctl(chan, CIO_MODE, 0, 0);
    DPuts(chan, "Password : ");
    res = DGetLine(chan, pass, 64);
    DIoctl(chan, CIO_MODE, 7, 0);
    if (res < 0)
	return(0);

    /*
     *	search for USER entry in s:dnet.config
     */

    fh = Open("s:dnet.config", 1005);
    if (fh == NULL) {
	DPuts(chan, "s:dnet.config does not exist\n");
	return(0);
    }
    while ((n = Read(fh, buf, 256)) > 0) {
	for (i = 0; i < n - 1; ++i) {
	    if (buf[i] == '\n')
		break;
	}
	buf[i] = 0;
	Seek(fh, (i + 1) - n, 0);
	if (strncmp(buf, "USER", 4) == 0) {
	    suser[0] = spass[0] = 0;
	    s_level = s_read = s_write = 0;
	    sscanf(buf + 4, "%s %s %d %d %d", suser, spass, &s_level, &s_read, &s_write);
	    if (strcmp(user, suser) == 0 && strcmp(pass, spass) == 0) {
		Close(fh);
		sprintf(buf, "%d", s_level);
		SetDEnv(DNET_LEVEL, buf);
		sprintf(buf, "%d", s_read);
		SetDEnv(DNET_READ, buf);
		sprintf(buf, "%d", s_write);
		SetDEnv(DNET_WRITE, buf);
		return(1);
	    }
	}
    }
    Close(fh);
    return(0);
}

void
DPuts(chan, str)
void *chan;
char *str;
{
    DWrite(chan, str, strlen(str));
}

int
DGetLine(chan, buf, max)
void *chan;
char *buf;
short max;
{
    short i = 0;
    short n;
    short notdone = 1;
    char c;

    while (notdone) {
	n = DRead(chan, &c, 1);
	if (n == 0) {   /*  ioctl, ignore   */
	    short pv;
	    char pa;
	    DGetIoctl(chan, &pv, &pa);
	    continue;
	}
	if (n < 0) {
	    buf[i] = 0;
	    return(-1);
	}
	switch(c) {
	case 8:     /*	BS  */
	    if (i)
		--i;
	    break;
	case 10:    /*	eol */
	case 13:
	    notdone = 0;
	    break;
	default:
	    if (i < max - 1)
		buf[i++] = c;
	    break;
	}
    }
    buf[i] = 0;
    return(1);
}

