4.1cBSD/usr/src/usr.bin/uucp/conn.c

Compare this file to the similar file:
Show the results in this format:

static char sccsid[] = "@(#)conn.c	4.1	(Berkeley)	9/11/82";

	/*  conn 2.1  5/23/79  19:07:44  */

/**********************************************************************
* Modified 9/81 by jrl for autodiallers built into a modem.  The table
* "autotbl" below can be expanded to deal with other autodiallers.
* 
* Modifed 2/82 by ctc to add the Port Selector Code.  This allows
* the new \b and \c type constructs.  Also modified to make use of the
* new UCB tty TIOSBRK and TIOCBRK iotcl's.  And last of all increased
* MR from 1000 to 2000 as per Bill Shannon's instructions.
*
* Modified 6/82 by Dave Martindale, U of Waterloo to support the Vadic
* AD3451 autodialing modem and the extended getargs (control chars in
* strings, embedded blanks in strings).  Expect() now takes an argument
* specifying how long the timeout should be - dialing takes a long time.
* sendthem() no longer scribbles on the string it is passed, and appends
* CR rather than NL to end of string by default.
* notin() now calls wprefix, so the expect string can contain '?' to
* match any character. ifdate() handles times which cross midnight.
* 2400 baud is supported.  Finally, a few bugs fixed:  login() closes
* the line's file descriptor on login failure; expect() checks for
* overflow of rdvec before stuffin the null in; a few strings fixed up.
**********************************************************************/

#define CONN
#include "uucp.h"
#include <signal.h>
#include <sgtty.h>
#include <setjmp.h>
#include <ctype.h>
#include <sys/types.h>
#include <time.h>

static char SiD[] = "@(#)conn	2.1";

#ifdef DATAKIT
#include <dk.h>
#endif


#define F_NAME 0
#define F_TIME 1
#define F_LINE 2
#define F_SPEED 3
#define F_PHONE 4
#define F_LOGIN 5

jmp_buf Sjbuf;
int alarmtr();
#define INVOKE(a, r) ret = a; if (ret<0) return(r);
/*******
 *	conn(system)
 *	char *system;
 *
 *	conn - place a telephone call to system and
 *	login, etc.
 *
 *	return codes:
 *		CF_SYSTEM: don't know system
 *		CF_TIME: wrong time to call
 *		CF_DIAL: call failed
 *		CF_LOGIN: login/password dialog failed
 *
 *		>0  - file no.  -  connect ok
 *
 */

conn(system)
char *system;
{
	int ret, nf;
	int fn;
	char *flds[50];
	DEBUG(4, "gdial %s\n", "called");
	INVOKE(gdial(), CF_DIAL)
	DEBUG(4, "finds %s\n", "called");
	INVOKE(nf = finds(system, flds), nf)
	DEBUG(4, "getto %s\n", "called");
	INVOKE(fn = getto(flds), CF_DIAL)
	DEBUG(4, "login %s\n", "called");
	INVOKE(login(nf, flds, fn), CF_LOGIN)
	return(fn);
}

/***
 *	char *
 *	lastc(s)	return pointer to last character
 *	char *s;
 *
 */

char *
lastc(s)
char *s;
{
	while (*s != '\0') s++;
	return(s);
}

#define MAXDEV 10
#define MAXDCH MAXDEV*20
#define MAXCODE 30
#define MAXCCH MAXCODE*20
	/* This array tells us about possible acu's, etc. */
struct Devices {
	char *D_type;
	char *D_line;
	char *D_calldev;
	int   D_speed;
	} Devs [MAXDEV];

char Devbuff[MAXDCH];

struct Codes {
	char *C_locs;
	char *C_prefix;
	} Dialcodes [MAXCODE];

char Codebuff[MAXCCH];


/***
 *	gdial()		get device and dial info
 *
 *	return codes:  0  |  FAIL
 */

gdial()
{
	char *flds[10], *lt;
	char *lb = Devbuff;
	char *lc = Codebuff;
	FILE *fn;
	int nr;
	struct Devices *pd;
	struct Codes *pc;

	fn = fopen(Devfile, "r");
	ASSERT(fn != NULL, "CAN'T OPEN %s", Devfile);
	for (pd = Devs; fgets(lb, 200, fn); pd++) {
		lt = lastc(lb);
		nr = getargs(lb, flds);
		ASSERT(nr == 4, "BAD LINE %s", lb);
		pd->D_type = flds[0];
		pd->D_line = flds[1];
		pd->D_calldev = flds[2];
		pd->D_speed = atoi(flds[3]);
		lb = lt;
		ASSERT(lb < Devbuff + MAXDCH, "TOO LONG %s", Devbuff);
		ASSERT(pd < Devs + MAXDEV, "TOO MANY DEVICES %d", MAXCODE);
	}
	pd->D_line = NULL;
	fclose(fn);
	ASSERT(pd > Devs, "BAD FILE %s", Devfile);
	/* Now dialcodes, same way */
	fn = fopen(Dialfile, "r");
	ASSERT(fn != NULL, "CAN'T OPEN %s", Dialfile);
	for (pc = Dialcodes; fgets(lc, 200, fn); pc++) {
		lt = lastc(lc);
		nr = getargs(lc, flds);
		if (nr == 1) flds[nr++] = "";
		ASSERT(nr == 2, "BAD LINE %s", lc);
		pc->C_locs = flds[0];
		pc->C_prefix = flds[1];
		lc = lt;
		ASSERT(lc < Codebuff + MAXCCH, "TOO LONG %s", Codebuff);
		ASSERT(pc < Dialcodes + MAXCODE, "MANY DEVICES %d", MAXCODE);
	}
	pc->C_locs = 0;
	fclose(fn);
	return(0);
}


/***
 *	ckdev(type, speed, ndev)
 *	char *type, *speed;
 *	int ndev;
 *
 *	ckdev  -  return the device number in table Devs for
 *	a device with proper attributes.
 *
 *	return codes: >= 0 (ok)  |  FAIL
 */

ckdev(type, speed, ndev)
char *type, *speed;
int ndev;
{
	int sp;
	struct Devices *pd;

	sp = atoi(speed);
	for (pd = &Devs[ndev]; pd->D_line != NULL; pd++) {
		if (sp != pd->D_speed)
			continue;
		if ((prefix(type, pd->D_type))  /* allow prefix here */
		    && !mlock(pd->D_line))
			return(ndev = pd - Devs);
		if ((strcmp(pd->D_line, type) == SAME)
		    && !mlock(type))
			return(ndev = pd - Devs);
	}
	return(FAIL);
}


/***
 *	getto(flds)		connect to remote machine
 *	char *flds[];
 *
 *	return codes:
 *		>0  -  file number - ok
 *		FAIL  -  failed
 */

getto(flds)
char *flds[];
{
	DEBUG(4, "call: no. %s ", flds[F_PHONE]);
	DEBUG(4, "for sys %s ", flds[F_NAME]);

	if (prefix("ACU", flds[F_LINE]))
		return(call(flds));

#ifdef DATAKIT
	else if (prefix("DK", flds[F_LINE]))
		return(dkcall(flds));
#endif

	else
		return(direct(flds));
}

/***
 *	call(flds)		call remote machine
 *	char *flds[];
 *
 *	"flds" contains the call information (name, date, type, speed,
 *	phone no. ...
 *	Ndev has the device no.
 *
 *	return codes:
 *		>0  -  file number  -  ok
 *		FAIL  -  failed
 */

call(flds)
char *flds[];
{
	char *pno, pref[20], phone[20];
	char *s1, *s2;
	int dcr, i;
	struct Codes *pc;

	pno = flds[F_PHONE];
	s1 = pref; s2 = pno;
	while (isalpha(*s2))
		*s1++ = *s2++;
	*s1 = '\0';
	for (pc = Dialcodes; pc->C_locs; pc++)
		if (strcmp(pc->C_locs, pref) == SAME) {
			s1 = pc->C_prefix;
			break;
		}
	sprintf(phone, "%s%s", s1, s2);
	for (i = 0; i < TRYCALLS; i++) {
		DEBUG(4, "Dial %s\n", phone);
		dcr = dialup(phone, flds);
		DEBUG(4, "dcr returned as %d\n", dcr);
		if (dcr != FAIL)
			break;
	}
	return(dcr);

}

	/*  file descriptor for call unit  */
int Dnf = 0;

/***
 *	dialup(ph, flds)	dial remote machine
 *	char *ph;
 *	char *flds[];
 *
 *	return codes:
 *		file descriptor  -  succeeded
 *		FAIL  -  failed
 */

int vad3451P(), ven212(), decdial();

struct autotbl {
	char *atb_name;
	int (*atb_fn)();
} autotbl[] = {
	"ACUVADIC3451P",	vad3451P,
	"ACUVENTEL212+",	ven212,
	"ACUDEC",		decdial,
	0,
};

dialup(ph, flds)
char *ph;
char *flds[];
{
	char dcname[20], dnname[20], phone[20];
	register struct Devices *pd;
	int nw, lt, pid, dcf, ndev, timelim;
	extern int Error;

	for (ndev = 0;;ndev++) {
		register struct autotbl *ap;

		ndev = ckdev(flds[F_LINE], flds[F_SPEED], ndev);
		if (ndev < 0) {
			logent("AVAILABLE DEVICE", "NO");
			DEBUG(4, "NO AVAILABLE DEVICE %s\n", "");
			return(FAIL);
		}
		pd = &Devs[ndev];
		sprintf(dcname, "/dev/%s", pd->D_line);

		/* disable logins on the line */
		disable(pd->D_line);

		/* check for autodialler */
		for(ap = autotbl; ap->atb_name; ap++)
			if(!strcmp(ap->atb_name, pd->D_type)) {
				DEBUG(4, "AUTODIAL %s\n", ap->atb_name);
				dcf = (*ap->atb_fn)(dcname, ph, pd->D_speed,
				  pd->D_line);
				if(dcf < 0) { /* dismal failure */
					logent("AUTODIAL FAILED", pd->D_line);
					DEBUG(4, "DIAL %s FAILED\n", pd->D_line);
					break;
				}
				fixline(dcf, pd->D_speed);
				return(dcf);
			}
		/* make sure it's a regular ACU */
		if(strcmp("ACU", pd->D_type) != SAME) {
			delock(pd->D_line);
			reenable();
			continue;
		}
		/* use regular dialler */
		sprintf(dnname, "/dev/%s", pd->D_calldev);
		/*  open call unit  */
		Dnf = open(dnname, 1);
		if (Dnf >= 0)
			break;
		delock(pd->D_line);
		reenable();
	}
	sprintf(phone, "%s%s", ph, ACULAST);
	DEBUG(4, "dc - %s, ", dcname);
	DEBUG(4, "acu - %s\n", dnname);
	if (setjmp(Sjbuf)) {
		DEBUG(1, "DN write %s\n", "timeout");
		logent("DIALUP DN write", "TIMEOUT");
		kill(pid, 9);
		delock(pd->D_line);
		reenable();
		close(Dnf);
		return(FAIL);
	}
	signal(SIGALRM, alarmtr);
	timelim = 5 * strlen(phone);
	alarm(timelim < 30 ? 30 : timelim);
	if ((pid = fork()) == 0) {
		sleep(2);
		fclose(stdin);
		fclose(stdout);
		nw = write(Dnf, phone, lt = strlen(phone));
		if (nw != lt) {
			DEBUG(1, "ACU write %s\n", "error");
			logent("DIALUP ACU write", "FAILED");
			exit(1);
		}
		DEBUG(4, "ACU write ok%s\n", "");
		exit(0);
	}
	/*  open line - will return on carrier */
	dcf = open(dcname, 2);
	DEBUG(4, "dcf is %d\n", dcf);
	if (dcf < 0) {
		DEBUG(1, "Line open %s\n", "failed");
		logent("DIALUP LINE open", "FAILED");
		alarm(0);
		kill(pid, 9);
		close(Dnf);
		return(FAIL);
	}
	ioctl(dcf, TIOCHPCL, 0);
	while ((nw = wait(&lt)) != pid && nw != -1)
		;
	alarm(0);
	fflush(stdout);
	fixline(dcf, pd->D_speed);
	DEBUG(4, "Forked %d ", pid);
	DEBUG(4, "Wait got %d ", nw);
	DEBUG(4, "Status %o\n", lt);
	if (lt != 0) {
		close(dcf);
		close(Dnf);
		reenable();
		return(FAIL);
	}
	return(dcf);
}


/***
 *	clsacu()	close call unit
 *
 *	return codes:  none
 */

clsacu()
{
	if (Dnf > 0) {
		close(Dnf);
		sleep(5);
		Dnf = 0;
	}
	return;
}


/***
 *	direct(flds)	connect to hardware line
 *	char *flds[];
 *
 *	return codes:
 *		>0  -  file number  -  ok
 *		FAIL  -  failed
 */

direct(flds)
char *flds[];
{
	int dcr, ndev;
	char dcname[20];

	ndev = 0;
	if ((ndev = ckdev(flds[F_LINE], flds[F_SPEED], ndev)) < 0) {
		logent("DEVICE", "NOT AVAILABLE");
		return(FAIL);
	}
	sprintf(dcname, "/dev/%s", Devs[ndev].D_line);
	disable(Devs[ndev].D_line);
	signal(SIGALRM, alarmtr);
	alarm(10);
	if (setjmp(Sjbuf)) {
		reenable();
		return(FAIL);
	}
	dcr = open(dcname, 2); /* read/write */
	alarm(0);
	if (dcr < 0) {
		reenable();
		return(FAIL);
	}
	fflush(stdout);
	fixline(dcr, Devs[ndev].D_speed);
	return(dcr);
}

#ifdef DATAKIT

#define DKTRIES 2

/***
 *	dkcall(flds)	make datakit connection
 *
 *	return codes:
 *		>0 - file number - ok
 *		FAIL - failed
 */

dkcall(flds)
char *flds[];
{
	int dkphone;
	register char *cp;
	register ret, i;

	if (setjmp(Sjbuf))
		return(FAIL);
	signal(SIGALRM, alarmtr);
	dkphone = 0;
	cp = flds[F_PHONE];
	while(*cp)
		dkphone = 10 * dkphone + (*cp++ - '0');
	DEBUG(4, "dkphone (%d) ", dkphone);
	for (i = 0; i < DKTRIES; i++) {
		ret = dkdial(D_UU, dkphone, 0);
		DEBUG(4, "dkdial (%d)\n", ret);
		if (ret > -1)
			break;
	}
	return(ret);
}
#endif

#define MAXC 300

/***
 *	finds(sysnam, flds)	set system attribute vector
 *	char *sysnam, *flds[];
 *
 *	return codes:
 *		>0  -  number of arguments in vector - succeeded
 *		CF_SYSTEM  -  system name not found
 *		CF_TIME  -  wrong time to call
 */

finds(sysnam, flds)
char *sysnam, *flds[];
{
	FILE *fsys;
	static char info[MAXC];
	char **fnp;
	int na;
	int fnd = 0;

	for (fnp = Sysfiles; *fnp != NULL && !fnd; fnp++) {
		fsys = fopen(*fnp, "r");
		if (fsys == NULL)
			continue;
		while (!fnd && (fgets(info, MAXC, fsys) != NULL)) {
			na = getargs(info, flds);
			if (prefix(sysnam, flds[F_NAME]))
				fnd = 1;
		}
		fclose(fsys);
	}
	if (fnd == 0)
		return(CF_SYSTEM);
	/* format of fields
	 *	0 name;
	 *	1 time
	 *	2 acu/hardwired/slave
	 *	3 speed
	 *	etc
	 */
	if (ifdate(flds[F_TIME]) == 0) {
		DEBUG(1, "Wrong time to call %s\n", sysnam);
		logent(sysnam, "WRONG TIME TO CALL");
		return(CF_TIME);
	}
	if (strcmp(flds[F_LINE], "Slave") == 0) {
		DEBUG(1, "Slave only, no call to %s tried\n", sysnam);
		logent(sysnam, "NO CALL FROM SLAVE");
		return(CF_TIME);
	}
	return(na);
}


/***
 *	login(nf, flds, dcr)		do log conversation
 *	char *flds[];
 *	int nf;
 *
 *	return codes:  0  |  FAIL
 */

login(nf, flds, fn)
char *flds[];
int nf, fn;
{
	char *want, *altern;
	extern char *index();
	int k, ok;

	ASSERT(nf > 4, "TOO FEW LOG FIELDS %d", nf);
	for (k = F_LOGIN; k < nf; k += 2) {
		want = flds[k];
		ok = FAIL;
		while (ok != 0) {
			altern = index(want, '-');
			if (altern != NULL)
				*altern++ = '\0';
			DEBUG(4, "wanted %s ", want);
			ok = expect(want, fn, MAXCHARTIME);
			DEBUG(4, "got %s\n", ok ? "?" : "that");
			if (ok == 0)
				break;
			if (altern == NULL) {
				logent("LOGIN", "FAILED");
				close(fn);
				return(FAIL);
			}
			want = index(altern, '-');
			if (want != NULL)
				*want++ = '\0';
			sendthem(altern, fn);
		}
		sleep(2);
		sendthem(flds[k+1], fn);
	}
	return(0);
}


struct sg_spds {int sp_val, sp_name;} spds[] = {
	{ 300,  B300},
	{1200, B1200},
	{2400, B2400},
	{4800, B4800},
	{9600, B9600},
	{0, 0} };

/***
 *	fixline(tty, spwant)	set speed/echo/mode...
 *	int tty, spwant;
 *
 *	return codes:  none
 */

fixline(tty, spwant)
int tty, spwant;
{
	struct sgttyb ttbuf;
	struct sg_spds *ps;
	int speed = -1;
	int ret;

	for (ps = spds; ps->sp_val; ps++)
		if (ps->sp_val == spwant)
			speed = ps->sp_name;
	ASSERT(speed >= 0, "BAD SPEED %d", speed);
	ioctl(tty, TIOCGETP, &ttbuf);
	ttbuf.sg_flags =(ANYP|RAW);
	ttbuf.sg_ispeed = ttbuf.sg_ospeed = speed;
	DEBUG(4, "Speed: want %d ", spwant);
	DEBUG(4, "use %o ", speed);
	DEBUG(4, "ps %d\n", ps-spds);
	ret = ioctl(tty, TIOCSETP, &ttbuf);
	ASSERT(ret >= 0, "RETURN FROM STTY %d", ret);
	ioctl(tty, TIOCHPCL, 0);
	ioctl(tty, TIOCEXCL, 0);
	return;
}


/*#define MR 1000 1000 chars should be enough */
/* 2000 is recommend by Bill Shannon */
#define MR 2000

int Error = 0;

/***
 *	expect(str, fn, timeout) look for expected string
 *	char *str;
 *
 *	return codes:
 *		0  -  found
 *		FAIL  -  lost line or too many characters read
 *		some character  -  timed out
 */

expect(str, fn, timeout)
char *str;
int fn;
{
	static char rdvec[MR];
	char *rp = rdvec;
	char nextch = 0;        /* was int /jrl */
	int kr;

	if (*str == '\0')
		return(0);
	*rp = 0;
	if (setjmp(Sjbuf)) {
		return(FAIL);
	}
	signal(SIGALRM, alarmtr);
	while (notin(str, rdvec)) {
		alarm(timeout);
		kr = read(fn, &nextch, 1);
		if (kr <= 0) {
			DEBUG(4, "kr - %d\n", kr);
			alarm(0);
			DEBUG(4, "lost line kr - %d, ", kr);
			DEBUG(4, "fn - %d\n", fn);
			logent("LOGIN", "LOST LINE");
			return(FAIL);
		}
		{
		int c;
		c = nextch & 0177;
		DEBUG(4, "%c", c > 040 ? c : '_');
		}
		if ((*rp = nextch & 0177) != '\0')
			rp++;
		if (rp >= rdvec + MR) {
			alarm(0);
			return(FAIL);
		}
		*rp = '\0';
	}
	alarm(0);
	return(0);
}


/***
 *	alarmtr()  -  catch alarm routine for "expect".
 */

alarmtr()
{
	longjmp(Sjbuf, 1);
}

/***
 *	sendthem(str, fn)	send line of login sequence
 *	char *str;
 *
 *	return codes:  none
 */

sendthem(str, fn)
char *str;
int fn;
{
	int nw, nulls, crw = 1;
	char *strptr;
	register char *outp;

	DEBUG(5, "send %s\n", str);
	if (prefix("BREAK", str)) {
		sscanf(&str[5], "%1d", &nulls);
		if (nulls <= 0 || nulls > 10)
			nulls = 3;
		/* send break */
		genbrk(fn, nulls);
		return;
	}

	if (strcmp(str, "EOT") == SAME) {
		write(fn, EOTMSG, (unsigned) strlen(EOTMSG));
		return;
	}

	for (strptr = str; *strptr; strptr++) {
		if (*(outp = strptr) == '\\')
			switch(*++strptr) {
			case '\\':
				break;
			case 'd':
				DEBUG(5, "DELAY\n", "");
				sleep(1);
				continue;
			case 'r':
				DEBUG(5, "RETURN\n", "");
				outp = "\r";
				break;
			case 'n':
				DEBUG(5, "NEWLINE\n", "");
				outp = "\n";
				break;
			case 'b':
				if (isdigit(*(strptr+1))) {
					nulls = (*++strptr - '0');
					if (nulls <= 0 || nulls > 10)
						nulls = 3;
				} else
					nulls = 3;
				/* send break */
#ifdef	UCBNEWTTY
				DEBUG(5, "BREAK - Hardware Break\n", nulls);
#else
				DEBUG(5, "BREAK (%d nulls)\n", nulls);
#endif
				genbrk(fn, nulls);
				continue;
			case 'c':
				if (*(strptr+1) == '\0') {
				DEBUG(5, "NO CR\n", "");
					crw = 0;
					continue;
				}
				DEBUG(5, "NO CR - MIDDLE (IGNORED)\n", "");
				break;
			default:
				DEBUG(5, "UNKNOWN ESCAPE\n", "");
				strptr--;
		}
		nw = write(fn, outp, 1);
		if (nw != 1) {
			DEBUG(4, "WRITE ERROR nw == %d wanted (1)\n", nw);
		}
		ASSERT(nw == 1, "BAD WRITE %s\n", str);
	}
	if (crw)
		write(fn, "\r", 1);
	return;
}


#define BSPEED B150

/***
 *	genbrk		send a break
 *
 *	return codes;  none
 */

genbrk(fn, bnulls)
{
	struct sgttyb ttbuf;
	int ret, sospeed;

#ifdef	UCBNEWTTY
#define	BRK_WAIT	1	/* Wait one full second before clearing the break line */

	ret = ioctl(fn, TIOCSBRK, 0);
	DEBUG(5, "ioctl ret %d\n", ret);
	sleep(BRK_WAIT);
	ret = ioctl(fn, TIOCCBRK, 0);
	DEBUG(5, "ioctl ret %d\n", ret);
	DEBUG(4, "sent BREAK Using Hardware - %d second wait\n", BRK_WAIT);
#else
	ret = ioctl(fn, TIOCGETP, &ttbuf);
	DEBUG(5, "ioctl ret %d\n", ret);
	sospeed = ttbuf.sg_ospeed;
	ttbuf.sg_ospeed = BSPEED;
	ret = ioctl(fn, TIOCSETP, &ttbuf);
	DEBUG(5, "ioctl ret %d\n", ret);
	ret = write(fn, "\0\0\0\0\0\0\0\0\0\0\0\0", bnulls);
	ASSERT(ret > 0, "BAD WRITE genbrk %d", ret);
	ttbuf.sg_ospeed = sospeed;
	ret = ioctl(fn, TIOCSETP, &ttbuf);
	ret = write(fn, "@", 1);
	ASSERT(ret > 0, "BAD WRITE genbrk %d", ret);
	DEBUG(4, "sent BREAK nulls - %d\n", bnulls);
#endif
	return;
}


/***
 *	notin(sh, lg)	check for occurrence of substring "sh"
 *	char *sh, *lg;
 *
 *	return codes:
 *		0  -  found the string
 *		1  -  not in the string
 */

notin(sh, lg)
char *sh, *lg;
{
	while (*lg != '\0') {
		if (wprefix(sh, lg))
			return(0);
		else
			lg++;
	}
	return(1);
}


/*******
 *	ifdate(s)
 *	char *s;
 *
 *	ifdate  -  this routine will check a string (s)
 *	like "MoTu0800-1730" to see if the present
 *	time is within the given limits.
 *	A time which crosses midnight like 2300-0800
 *	is interpreted as after 2300 or before 0800 on any
 *	suitable day, which may not be what you expected.
 *	(Mo2300-0800 is equivalent to Mo2300-2400,Mo0000-0800
 *	and not to Mo2300-2400,Tu0000-0800)
 *
 *      Now can be a list: Wk0000-0745,Wk1700-2400,Sa,Su
 *
 *	String alternatives:
 *		Wk - Mo thru Fr
 *		zero or one time means all day
 *		Any - any day
 *
 *	return codes:
 *		0  -  not within limits
 *		1  -  within limits
 */

ifdate(xs)
char *xs;
{
	static char *days[]={
		"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", 0
	};
	char sbuf[80];
	long clock;
	int i, tl, th, tn, dayok=0;
	struct tm *localtime();
	register struct tm *tp;
	register char *s;
	char *tptr;


	time(&clock);
	tp = localtime(&clock);
	tn = tp->tm_hour * 100 + tp->tm_min;
	strcpy(sbuf, xs);

	for(s = sbuf; tptr; s = tptr) {
		dayok = 0;
		if(tptr = index(s, ','))
			*tptr++ = 0;

		while (isalpha(*s)) {
			for (i = 0; days[i]; i++) {
				if (prefix(days[i], s))
					if (tp->tm_wday == i)
						dayok = 1;
			}

			if (prefix("Wk", s))
				if (tp->tm_wday >= 1 && tp->tm_wday <= 5)
					dayok = 1;
			if (prefix("Any", s))
				dayok = 1;
			s++;
		}

		if (dayok == 0)
			continue;
		i = sscanf(s, "%d-%d", &tl, &th);
		if (i < 2)
			return(1);
		if (tl <= th) {
			if (tl <= tn && tn < th)
				return(1);
		} else if (tl <= tn || tn < th)
			return(1);
	}
	return(0);
}