
/*
 *  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 <stdio.h>
#include <fcntl.h>
#include <local/typedefs.h>
#include "servers.h"
#include "/dnet/channel.h"

int Enable_Abort;

extern struct MsgPort *DListen();

extern void printfile();

_main()
{
    struct MsgPort *port;
    PROC    *myproc = FindTask(NULL);
    long    chan;
    long    mask, rmask;
    short   res;

    Enable_Abort = 0;

    if (myproc->pr_CLI) {
	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);
}

do_password(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);
}

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

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

    while (notdone) {
	n = DRead(chan, &c, 1);
	if (n == 0) {   /*  ioctl, ignore   */
	    short pv;
	    short 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);
}

