[net.sources] y

campbell@maynard.UUCP (Larry Campbell) (09/14/86)

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	data.c
#	date.c
#	delete.c
#	diagnostic.c
#	dump.c
#	fdump.c
#	finfo.c
#	fload.c
#	info.c
#	getslot.c
#	message.c
#	miniexch.c
#	monitor.c
#	prints.c
#	readid.c
#	reset.c
#	schedule.c
#	setclock.c
#	tty.c
#	unit.c
#	x10.c
#	xread.c
# This archive created: Sat Sep 13 22:38:59 1986
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'data.c'
then
	echo shar: "will not over-write existing file 'data.c'"
else
cat << \SHAR_EOF > 'data.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include <ctype.h>
#include "x10.h"

extern int tty;
extern char flag;
extern struct hstruct
    housetab[];

c_data(argc, argv)
char *argv[];
{
unsigned datano, id, unit;
unsigned char buf[6];
char hletter;
int n, hcode;

if (argc != 5) usage(E_WNA);

/* parse the housecode */
hletter = argv[2][0];
if (isupper(hletter)) hletter = tolower(hletter);
for (n = 0, hcode = -1; n < 16; n++)
    if (housetab[n].h_letter == hletter)
	{
	hcode = housetab[n].h_code;
	break;
	}
if (hcode == -1) error("invalid house code");

/* parse the unit number */
if (!sscanf(&argv[2][1], "%d", &unit) || unit < 1 || unit > 16)
    error("bad unit number, must be between 1 and 16");

/* parse the description id */
if (!sscanf(argv[4], "%d", &id) || id < 1 || id > 255)
    error("bad description id, must be a number between 1 and 255");

/* parse the state */
if (strcmp(argv[3], "on") == 0)
    id |= 0x80;
else if (strcmp(argv[3], "off") == 0);
else error("bad state, must be 'on' or 'off'");

/* get first available slot number from the x10 */
datano = getslot(GETDATA);

/* get descriptions for all id's */
readid();

buf[0] = DATALOAD;
buf[1] = datano << 1;
buf[2] = datano >> 7 | 0x4;
buf[3] = hcode | unit - 1;
buf[4] = id;
buf[5] = 0;

for (n = 3; n < DICMD - 1; n++)			/* compute checksum */
    buf[DICMD - 1] += buf[n];

sendsync();
(void) write(tty, (char *) buf, sizeof(buf));
chkack();

flag = 0;				/* header wanted */
pdata(&buf[3], datano);			/* reassure user */
}
SHAR_EOF
fi
if test -f 'date.c'
then
	echo shar: "will not over-write existing file 'date.c'"
else
cat << \SHAR_EOF > 'date.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include <time.h>
#ifdef SYSV
#include <sys/types.h>
#endif
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <sys/param.h>
#include <sys/filsys.h>
#include "x10.h"

extern struct tm *localtime();

extern long lseek();

extern int
    Idays,
    Ihours,
    Iminutes;

/* ARGSUSED */

c_date(argc, argv)
char *argv[];
{
struct filsys f;
int rf, today;
struct tm *tp;

if (argc != 2) usage(E_2MANY);
rf = open(ROOTNAME, 0);
if (rf < 0) error("can't open root filesystem");
if (lseek(rf, 512L, 0) == -1L) error("can't lseek on root");
if (read(rf, (char *) &f, 512) != 512) error("can't read root");
(void) close(rf);
if (f.s_time < 515000000L) error("root has unreasonable timestamp");
tp = localtime(&f.s_time);
today = dowX2U(Idays);
while (tp->tm_wday % 7 != today)
    tp->tm_wday++, tp->tm_mday++;

#ifdef VENIX
(void) printf("%2d%02d%02d%02d%02d\n",
       tp->tm_year, tp->tm_mon+1, tp->tm_mday, Ihours, Iminutes);
#else
(void) printf("%02d%02d%02d%02d%2d\n",
       tp->tm_mon+1, tp->tm_mday, Ihours, Iminutes, tp->tm_year);
#endif
}
SHAR_EOF
fi
if test -f 'delete.c'
then
	echo shar: "will not over-write existing file 'delete.c'"
else
cat << \SHAR_EOF > 'delete.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include "x10.h"

extern int tty;

c_delete(argc, argv)
char *argv[];
{
register unsigned cmdsize, n, arg;
unsigned number;
char buf[12];

if (argc < 4) usage(E_NMA);

if (strncmp(argv[2], EVENTS, sizeof(EVENTS) - 2) == 0)
    cmdsize = EVCMD;
else if (strcmp(argv[2], DATA) == 0)
    cmdsize = DICMD;
else error("unknown delete request");

buf[0] = DATALOAD;

for (arg = 3; arg < argc; arg++)
    {
    if (!sscanf(argv[arg], "%d", &number))
	(void) fprintf(stderr,
	    "ignored non-numeric event number\n");

    if (cmdsize == EVCMD)
	{
	if (number > ETOTAL - 1)
	    {
	    (void) fprintf(stderr,
		"ignored event number greater than 127\n");
	    continue;
	    }
	buf[1] = number << 3;
	buf[2] = (number >> 5) & 0x3;
	}
    else
	{
	if (number > DTOTAL - 1)
	    {
	    (void) fprintf(stderr,
		"ignored data slot number greater than 255\n");
	    continue;
	    }
	buf[1] = number << 1;
	buf[2] = (number >> 7) | 0x4;
	}

    for (n = 3; n < cmdsize; n++)
	buf[n] = 0;

    sendsync();
    (void) write(tty, buf, cmdsize);

    chkack();
    }
}
SHAR_EOF
fi
if test -f 'diagnostic.c'
then
	echo shar: "will not over-write existing file 'diagnostic.c'"
else
cat << \SHAR_EOF > 'diagnostic.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include "x10.h"

extern int tty, timeout;

/* ARGSUSED */

c_diagnostic(argc, argv)
char *argv[];
{
char buf[1];

if (argc != 2) usage(E_2MANY);
buf[0] = DIAGNOSE;
sendsync();
(void) write(tty, buf, 1);
timeout = DTIMEOUT;
chkack();
timeout = TIMEOUT;
}
SHAR_EOF
fi
if test -f 'dump.c'
then
	echo shar: "will not over-write existing file 'dump.c'"
else
cat << \SHAR_EOF > 'dump.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include "x10.h"

extern char flag;
extern int tty, timeout;
extern int pevent();
extern int pdata();
extern struct id id[];

c_dump(argc, argv)
char *argv[];
{
if (argc != 3) usage(E_WNA);

if (strcmp(argv[2], EVENTS) == 0)
    dumpcontents(pevent, GETEVENTS);
else if (strcmp(argv[2], DATA) == 0)
    dumpcontents(pdata, GETDATA);
else if (strcmp(argv[2], "all") == 0)
    {
    dumpcontents(pdata, GETDATA);
    (void) putchar('\n');
    dumpcontents(pevent, GETEVENTS);
    }
else error("unknown dump request");
}

dumpcontents(handler, type)
int (*handler) ();
{
register unsigned i, total;
register scnt, dcnt;
char *msgstr;
unsigned char buf[8];
unsigned n, cksum, count;

flag = 0;		/* set print header indicator */

if (type == GETEVENTS)
    {
    scnt = ETOTAL;
    dcnt = ESIZE;
    msgstr = EVENTS;
    }
else
    {
    readid();
    scnt = DTOTAL;
    dcnt = DSIZE;
    msgstr = DATA;
    }

sendsync();
buf[0] = type;
(void) write(tty, (char *) buf, 1);
getsync();
n = xread(tty, buf, 1, timeout);
if (n != 1) error("UPLOAD: no response");
cksum = 0;
count = 0;
total = 0;
for (i = 0; i < scnt; i++)
    {
    n = xread(tty, buf, 1, timeout);
    if (n != 1) error("UPLOAD: reply truncated");
    total++;
    if (buf[0] == 0xFF) continue;
    n = xread(tty, &buf[1], dcnt - 1, timeout);
    if (n != dcnt - 1) error("UPLOAD: information truncated");
    for (n = 0; n < dcnt; n++)
    	cksum += buf[n];
    (*handler) (buf, i, dcnt);
    count++;
    }
n = xread(tty, buf, 1, timeout);
if (n != 1) error("UPLOAD: checksum not received");
if (count && (cksum & 0xFF) != buf[0]) error("UPLOAD: bad checksum received");
if (! count)
(void) printf("No %s currently stored in interface (%d replies)\n",
    msgstr, total);
}
SHAR_EOF
fi
if test -f 'fdump.c'
then
	echo shar: "will not over-write existing file 'fdump.c'"
else
cat << \SHAR_EOF > 'fdump.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include "x10.h"

int dcontents();

c_fdump(argc, argv)
char *argv[];
{
if (argc != 3) usage(E_WNA);

if (strcmp(argv[2], EVENTS) == 0)
    dumpcontents(dcontents, GETEVENTS);
else if (strcmp(argv[2], DATA) == 0)
    dumpcontents(dcontents, GETDATA);
else error("unknown fdump request");
}

dcontents(buf, i, n)
unsigned char *buf;
unsigned i, n;
{
(void) write(1, (char *) &i, sizeof(unsigned));
(void) write(1, (char *) buf, n);
}
SHAR_EOF
fi
if test -f 'finfo.c'
then
	echo shar: "will not over-write existing file 'finfo.c'"
else
cat << \SHAR_EOF > 'finfo.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include "x10.h"

struct evitem event;
struct ditem data;

c_finfo(argc, argv)
char *argv[];
{
if (argc != 3) usage(E_WNA);

if (strcmp(argv[2], EVENTS) == 0)
    while (read(0, (char *) &event, EVSIZE) == EVSIZE)
	{
	if (event.e_buf[0] & 0xF0) error("invalid MODE field in file");
	if (event.e_buf[1] & 0x80) error("invalid DAYS field in file");
	if (event.e_buf[2] > 23) error("invalid HOUR field in file");
	if (event.e_buf[3] > 59) error("invalid MINUTE field in file");
	if (event.e_buf[6] & 0x0F) error("invalid HOUSECODE field in file");
	pevent(event.e_buf, event.e_num);
	}
else if (strcmp(argv[2], DATA) == 0)
    {
    readid();
    while (read(0, (char *) &data, DISIZE) == DISIZE)
	pdata(data.d_buf, data.d_num);
    }
else error("unknown finfo request");
}
SHAR_EOF
fi
if test -f 'fload.c'
then
	echo shar: "will not over-write existing file 'fload.c'"
else
cat << \SHAR_EOF > 'fload.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include "x10.h"

extern int tty;
struct evitem event;
struct ditem data;

c_fload(argc, argv)
char *argv[];
{
unsigned char buf[12];
char *cptr;
register unsigned i, size, cmdsize;

if (argc != 3) usage(E_WNA);

if (strcmp(argv[2], EVENTS) == 0)
    {
    size = EVSIZE;
    cmdsize = EVCMD;
    cptr = (char *) &event;
    }
else if (strcmp(argv[2], DATA) == 0)
    {
    size = DISIZE;
    cmdsize = DICMD;
    cptr = (char *) &data;
    }
else error("unknown fload request");

while (read(0, cptr, size) == size)
    {
    buf[0] = DATALOAD;

    if (size == EVSIZE)
	{
	if (event.e_buf[0] & 0xF0) error("invalid MODE field in file");
	if (event.e_buf[1] & 0x80) error("invalid DAYS field in file");
	if (event.e_buf[2] > 23) error("invalid HOUR field in file");
	if (event.e_buf[3] > 59) error("invalid MINUTE field in file");
	if (event.e_buf[6] & 0x0F) error("invalid HOUSECODE field in file");
	buf[1] = event.e_num << 3;
	buf[2] = (event.e_num >> 5) & 0x3;
	for (i = 0; i < ESIZE; i++)
	    buf[i+3] = event.e_buf[i];
	}
    else
	{
	buf[1] = data.d_num << 1;
	buf[2] = data.d_num >> 7 | 0x4;
	buf[3] = data.d_buf[0];
	buf[4] = data.d_buf[1];
	}

    buf[cmdsize - 1] = 0;
    for (i = 3; i < cmdsize - 1; i++)		/* compute checksum */
    	buf[cmdsize - 1] += buf[i];

    sendsync();
    (void) write(tty, (char *) buf, cmdsize);

    chkack();
    }
}
SHAR_EOF
fi
if test -f 'info.c'
then
	echo shar: "will not over-write existing file 'info.c'"
else
cat << \SHAR_EOF > 'info.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include "x10.h"

extern char hc2char();

extern int
    Iloaded,
    Idays,
    Ihours,
    Iminutes;

extern unsigned char
    Ihcode;

extern char *wdays[];

/* ARGSUSED */

c_info(argc, argv)
char *argv[];
{
if (argc != 2) usage(E_2MANY);
if (Iloaded)
    (void) printf("Interface clock: %s, %2d:%02d\n",
           wdays[dowX2U(Idays)], Ihours, Iminutes);
else
    (void) printf("Interface clock not yet set\n");
(void) printf("Housecode = %c\n", hc2char(Ihcode));
}
SHAR_EOF
fi
if test -f 'getslot.c'
then
	echo shar: "will not over-write existing file 'getslot.c'"
else
cat << \SHAR_EOF > 'getslot.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include "x10.h"

extern int
    tty,
    timeout;

getslot(type)
{
register scnt, dcnt;
unsigned char buf[8];
unsigned i, n, cksum, count;
int firstfree;

if (type == GETEVENTS)
    {
    scnt = ETOTAL;
    dcnt = ESIZE;
    }
else
    {
    scnt = DTOTAL;
    dcnt = DSIZE;
    }

sendsync();
buf[0] = type;
(void) write(tty, (char *) buf, 1);
getsync();
n = xread(tty, buf, 1, timeout);
if (n != 1) error("UPLOAD: no response");
cksum = 0;
count = 0;
firstfree = -1;
for (i = 0; i < scnt; i++)
    {
    n = xread(tty, buf, 1, timeout);
    if (n != 1) error("UPLOAD: reply truncated");
    if (buf[0] == 0xFF)
    	{
    	if (firstfree == -1) firstfree = i;
    	continue;
    	}
    n = xread(tty, &buf[1], dcnt - 1, timeout);
    if (n != dcnt - 1) error("UPLOAD: information truncated");
    for (n = 0; n < dcnt; n++)
    	cksum += buf[n];
    }
n = xread(tty, buf, 1, timeout);
if (n != 1) error("UPLOAD: checksum not received");
if (count && (cksum & 0xFF) != buf[0]) error("UPLOAD: bad checksum received");
if (firstfree == -1) error("No more storage slots available");
return(firstfree);
}
SHAR_EOF
fi
if test -f 'message.c'
then
	echo shar: "will not over-write existing file 'message.c'"
else
cat << \SHAR_EOF > 'message.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include "x10.h"

char *E_2MANY = EM_2MANY;
char *E_INVCN = EM_INVCN;
char *E_WNA   = EM_WNA;
char *E_NMA   = EM_NMA;
char *E_NOCMD = EM_NOCMD;

void exit();

usage(s)
char *s;
{

/*
 * Don't combine the two calls to fputs or my compiler will
 * gag with "token too long"
 */

(void) fprintf(stderr, "Command error: %s\n", s);
(void) fputs("Usage:\n\
 x10 data ann on|off id      store id with housecode a, unit nn and state\n\
 x10 date                    returns date in date(1) input format\n\
 x10 delete events|data nums deletes specified events or data slots\n\
 x10 diagnostic              run interface self-test diagnostics\n\
 x10 dump   events|data|all  dumps events or data or both\n\
 x10 fdump  events|data      dumps binary events or data to stdout\n", stderr);
(void) fputs("\
 x10 finfo  events|data      displays contents of event or data file on stdin\n\
 x10 fload  events|data      loads interface from event file on stdin\n\
 x10 info                    gets current settings\n\
 x10 monitor                 monitor X10 activity (end with <BREAK>)\n\
 x10 reset  [housecode]      reset interface to 'A' or specified housecode\n\
 x10 schedule ann[,nn...] mode [day] hh:mm on|off|dim [vv]     schedule event\n\
 x10 setclock                sets X10 clock to system clock\n\
 x10 unit ann[,nn...] on|off|dim [vv]    turns unit nn, housecode a, to state\n\
", stderr);
exit(1);
}

error(s)
char *s;
{
(void) fprintf(stderr, "x10: %s\n", s);
quit();
}
SHAR_EOF
fi
if test -f 'miniexch.c'
then
	echo shar: "will not over-write existing file 'miniexch.c'"
else
cat << \SHAR_EOF > 'miniexch.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include <sgtty.h>
#include "x10.h"

extern int tty;

/*
 * mxconnect(port)
 *
 *	Connect to specified port on DEC Mini-Exchange
 */

#ifdef MINIEXCH
mxconnect(port)
{
static char
    mx1[] = "//",
    mx2[] = " P",		/* port number goes here before P */
    mx3[] = "\r";

#define PORTID mx2[0]
#define MXLEN sizeof(mxmsg)
#define MRLEN 5
#define MRACKOFFSET (MRLEN-1)

unsigned char
    mxrply[MRLEN];

int n;

sleep(SMALLPAUSE);
PORTID = '0' + port;
(void) write(tty, mx1, 2);
sleep(SMALLPAUSE);
(void) write(tty, mx2, 2);
sleep(SMALLPAUSE);
(void) write(tty, mx3, 1);
n = xread(tty, mxrply, MRLEN, 3);		/* 2-second timeout */
if (n != MRLEN)
    {
    (void) fprintf(stderr, "Mini-exchange replied with %d bytes\n", n);
    for (n = 0; n < MRLEN; n++)
    	(void) fprintf(stderr, "reply[%2d] = 0x%x\n", n, mxrply[n]);
    error("Mini-exchange timeout");
    }
if (mxrply[MRACKOFFSET] != 'A') error("Port 3 busy or disconnected");
}
#endif
SHAR_EOF
fi
if test -f 'monitor.c'
then
	echo shar: "will not over-write existing file 'monitor.c'"
else
cat << \SHAR_EOF > 'monitor.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include "x10.h"

extern int timeout;

void iquit();
jmp_buf mjb;

void iquit()
{
longjmp(mjb, 1);
}

c_monitor()
{
(void) signal(SIGINT, iquit);
timeout = 0;
if (setjmp(mjb))
    return;
while (1)
    chkrpt(1);
}
SHAR_EOF
fi
if test -f 'prints.c'
then
	echo shar: "will not over-write existing file 'prints.c'"
else
cat << \SHAR_EOF > 'prints.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#ifdef SYSV
#include <string.h>
#else
#include <strings.h>
#endif
#include "x10.h"

extern char flag, hc2char();
extern struct nstruct dtab[];
extern struct hstruct housetab[];
extern struct id id[];

/*
 * print unit numbers as specified in bitmap
 * bitmap is jammed into int backwards from X10 manual depiction:
 *
 *	 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16
 *
 * instead of
 *
 *	 9 10 11 12 13 14 15 16  1  2  3  4  5  6  7  8 
 */

punits(bitmap)
unsigned bitmap;
{
register nf, unitno, saveno, seq;
char c;

saveno = -1;
for (unitno = 1, nf = seq = 0; unitno <= 16; unitno++)
    if ((1 << (16 - unitno)) & bitmap)
	{
	if (seq++) c = '-';
	else c = ',';
	if (saveno + 1 != unitno)
	    {
	    if (nf++) (void) printf("%c", c);
	    if (seq == 1) (void) printf("%d", unitno);
	    else (void) printf("%d,%d", saveno, unitno);
	    seq = 0;
	    }
	saveno = unitno;
	}
if (seq) (void) printf("-%d", saveno);
}

/*
 * Names must have a capitalized first letter for mode2code().
 * C_schedule() expects the first two modes listed to require
 * an argument of specific days.
 */

struct nstruct
    modnames[] =
	{
	"Normal",   0x08,
	"Security", 0x09,
	"Today",    0x04,
	"Tomorrow", 0x02,
	"",         0x00
	},
    funcnames[] =
	{
	"On",  0x02,
	"Off", 0x03,
	"DIM", 0x04,
	"Dim", 0x05,
	"",    0x00
	};

/*
 * Print out an event
 */

pevent(p, i)
unsigned i;
unsigned char p[];
{
char *modestr, *funcstr, *daystr, levelstr[8];
int j, mode, func;

/* decode mode */
mode = p[0] & 0x0F;
for (j = 0, modestr = NULL; modnames[j].n_code != 0; j++)
    if (modnames[j].n_code == mode)
	modestr = modnames[j].n_name;
if (modestr == NULL)
    modestr = "Unknown";

/* decode state */
func = p[7] & 0x0F;
for (j = 0, funcstr = NULL; funcnames[j].n_code != 0; j++)
    if (funcnames[j].n_code == func)
	funcstr = funcnames[j].n_name;
if (funcstr == NULL)
    funcstr = "Unknown";
if (func == 4 || func == 5)
    {
    (void) strcpy(levelstr, funcstr);
    (void) sprintf(levelstr+3, " %2d", (p[7] >> 4) & 0x0f);
    funcstr = levelstr;
    }

/* decode days */
for (j = 0, daystr = NULL; dtab[j].n_code != 0; j++)
    if (dtab[j].n_code == p[1])
	daystr = dtab[j].n_name;

/* print timer event header first */
if (!flag)
    (void) printf(
	"   EVENT   STATE    MODE       DAYS        TIME     UNITS\n");
flag++;		/* indicate header was printed */

/* print timer event */
(void) printf("     %3d   %-7s  %-8s   %-9s   %2d:%02d    %c",
       i, funcstr, modestr, daystr, p[2], p[3], hc2char(p[6]));
punits((p[4] << 8) | p[5]);
(void) printf("\n");
}

/*
 * Print out graphics data
 */

pdata(p, i)
unsigned i;
unsigned char p[];
{
char hletter, ucode, *state, icode;
unsigned char hcode;
int j;

hcode = p[0] & 0xf0;
for (j = 0; housetab[j].h_code != hcode; j++);
hletter = housetab[j].h_letter;
ucode = (p[0] & 0x0f) + 1;

if (p[1] & 0x80) state = funcnames[0].n_name;
else state = funcnames[1].n_name;

icode = p[1] & 0x7f;

if (!flag)
(void) printf("    SLOT    UNIT    STATE    ID    DESCRIPTION\n");
flag++;
(void) printf("     %3d    %c%-2d     %-3s      %03d   %s\n",
    i, hletter, ucode, state, icode, id[icode].describe);
}
SHAR_EOF
fi
if test -f 'readid.c'
then
	echo shar: "will not over-write existing file 'readid.c'"
else
cat << \SHAR_EOF > 'readid.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#ifdef SYSV
#include <string.h>
#else
#include <strings.h>
#endif
#include "x10.h"

struct id id[DTOTAL];

readid()
{
register n, cnt = 0, c;
unsigned num;
char xfile[100];
int noskip;
FILE *idfile;

(void) strcat(strcpy(xfile, XDIR), IDFILE);

if ((idfile = fopen(xfile, "r")) == NULL)
    {
    (void) fprintf(stderr,
	"Warning: cannot open description file %s\n", xfile);
    return;
    }

while(++cnt)
    {
    if (fscanf(idfile, "%d%*[ \t]", &num) == EOF)
	break;
    if (num < 1 || num > DTOTAL -1) (void) fprintf(stderr,
	"Warning: id number out of range, ignored line %d in %s\n",
	cnt, xfile), noskip = 0;
    else noskip = 1;
    for (n = 0; (c = fgetc(idfile)) != EOF; n++)
	{
	if (c == '\n') break;
	if (n < DLENGTH - 1 && noskip)
	    id[num].describe[n] = (char) c;
	}
    if (n >= DLENGTH - 1) (void) fprintf(stderr,
	"Warning: description truncated, line %d in %s\n",
	cnt, xfile);
    }
    (void) fclose(idfile);
}
SHAR_EOF
fi
if test -f 'reset.c'
then
	echo shar: "will not over-write existing file 'reset.c'"
else
cat << \SHAR_EOF > 'reset.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include <ctype.h>
#include "x10.h"

extern int tty;
extern struct hstruct
    housetab[];

/* ARGSUSED */

c_reset(argc, argv)
char *argv[];
{
int hcode, hletter, n;
char buf[2];

if (argc > 3) usage(E_WNA);

buf[0] = SETHCODE;
buf[1] = HC_A;		/* default house code */

if (argc == 3)
    {
    hletter = argv[2][0];
    if (isupper(hletter)) hletter = tolower(hletter);
    for (n = 0, hcode = -1; n < 16; n++)
	if (housetab[n].h_letter == hletter)
	    {
	    buf[1] = hcode = housetab[n].h_code;
	    break;
	    }
    if (hcode == -1) error("invalid house code");
    }

sendsync();
(void) write(tty, buf, 2);
chkack();
}
SHAR_EOF
fi
if test -f 'schedule.c'
then
	echo shar: "will not over-write existing file 'schedule.c'"
else
cat << \SHAR_EOF > 'schedule.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include <ctype.h>
#include "x10.h"

extern int tty;
extern char flag;
extern struct hstruct
    housetab[];

c_schedule(argc, argv)
char *argv[];
{
register n;
int bits, daybits = 0, hcode, dim, mode;
unsigned eventno, hh, mm;
unsigned char buf[12];
char hletter;

if (argc < 6 || argc > 8) usage(EM_WNA);

/* parse the housecode */
hletter = argv[2][0];
if (isupper(hletter)) hletter = tolower(hletter);
for (n = 0, hcode = -1; n < 16; n++)
    if (housetab[n].h_letter == hletter)
	{
	hcode = housetab[n].h_code;
	break;
	}
if (hcode == -1) error("invalid house code");

/* parse the unit numbers */
bits = getunits(&argv[2][1]);

/* parse the mode */
n = 3;  /* used because argv[4] to argv[8] can vary by one */
mode = mode2code(argv[n++]);

/* parse the day if mode requires it */
if (flag < 2)  /* first two modes require days */
    daybits = day2bits(argv[n++]);

/* parse the time */
if (sscanf(argv[n++], "%d:%d", &hh, &mm) != 2)
    error("bad time format");
if (hh > 23) error("bad hours, must be between 0 and 23");
if (mm > 59) error("bad minutes, must be between 0 and 59");

/* parse the state */
dim = dimstate(argv[n], argc == n+2 ? argv[n+1] : "");

/* get first available event number from the X10 */
eventno = getslot(GETEVENTS);

buf[0] = DATALOAD;
buf[1] = eventno << 3;
buf[2] = (eventno >> 5) & 0x3;
buf[3] = mode;
buf[4] = daybits;
buf[5] = hh;
buf[6] = mm;
buf[7] = bits >> 8;
buf[8] = bits & 0xFF;
buf[9] = hcode;
buf[10]= dim;
buf[11]= 0;

for (n = 3; n <= 10; n++)		/* compute checksum */
    buf[11] += buf[n];

sendsync();
(void) write(tty, (char *) buf, sizeof(buf));
chkack();

flag = 0;				/* header wanted */
pevent(&buf[3], eventno);		/* reassure user */
}
SHAR_EOF
fi
if test -f 'setclock.c'
then
	echo shar: "will not over-write existing file 'setclock.c'"
else
cat << \SHAR_EOF > 'setclock.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include <time.h>
#include "x10.h"

extern struct tm *localtime();
extern long time();
extern int tty;
extern char *wdays[];

/* ARGSUSED */

c_setclock(argc, argv)
char *argv[];
{
unsigned char data[5];
struct tm *tp;
long dtime;

if (argc != 2) usage(E_2MANY);
dtime = time((long *) 0);
tp = localtime(&dtime);
data[0] = SETCLK;
data[1] = tp->tm_min;
data[2] = tp->tm_hour;
data[3] = dowU2X(tp->tm_wday);
data[4] = CHKSUM(data);
sendsync();
(void) write(tty, (char *) data, 5);
chkack();
(void) printf("X10 clock set to %s, %d:%02d\n",
    wdays[tp->tm_wday], tp->tm_hour, tp->tm_min);
}
SHAR_EOF
fi
if test -f 'tty.c'
then
	echo shar: "will not over-write existing file 'tty.c'"
else
cat << \SHAR_EOF > 'tty.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#ifndef SYSV
#include <sgtty.h>
#else
#include <termio.h>
#endif
#include "x10.h"

void exit();

int tty = -1;
#ifndef SYSV
struct sgttyb
#else
struct termio
#endif
    oldsb,
    newsb;

setup_tty()
{
tty = open(DEVNAME, 2);
if (tty < 0) error("can't open terminal line (line probably in use)");

#ifndef SYSV
(void) ioctl(tty, TIOCFLUSH, (struct sgttyb *) NULL);
(void) ioctl(tty, TIOCGETP, &oldsb);
newsb = oldsb;
newsb.sg_flags |= RAW;
newsb.sg_flags &= ~(ECHO|EVENP|ODDP);
hangup();
newsb.sg_ispeed = newsb.sg_ospeed = B600;	/* raise DTR & set speed */
(void) ioctl(tty, TIOCSETN, &newsb);
#else
(void) ioctl(tty, TCGETA, &oldsb);
newsb = oldsb;
newsb.c_lflag &= ~(ICANON | ECHO | ECHONL | ISIG);
newsb.c_oflag &= ~OPOST;
newsb.c_iflag &= ~(ISTRIP | IXON | IXOFF);
newsb.c_cflag &= ~(CBAUD | PARENB);
newsb.c_cflag |= (B600 | CS8 | CREAD);
newsb.c_cc[VEOF] = 1;
newsb.c_cc[VEOL] = 0;
(void) ioctl(tty, TCSETAF, &newsb);
#endif
}

restore_tty()
{
#ifndef SYSV
hangup();
(void) ioctl(tty, TIOCSETN, &oldsb);
#else
(void) ioctl(tty, TCSETAF, &oldsb);
#endif
}

#ifndef SYSV
hangup()
{
newsb.sg_ispeed = newsb.sg_ospeed = B0;		/* drop DTR */
(void) ioctl(tty, TIOCSETN, &newsb);
sleep(SMALLPAUSE);
}
#endif

quit()
{
if (tty == -1) exit(1);
restore_tty();
exit(1);
}
SHAR_EOF
fi
if test -f 'unit.c'
then
	echo shar: "will not over-write existing file 'unit.c'"
else
cat << \SHAR_EOF > 'unit.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include <ctype.h>
#include "x10.h"

extern int tty;

extern struct hstruct
    housetab[];

c_unit(argc, argv)
char *argv[];
{
register n;
int hcode, hletter, dim, bits;
unsigned char buf[6];

if (argc < 4 || argc > 5) usage(E_WNA);
hletter = argv[2][0];
if (isupper(hletter)) hletter = tolower(hletter);

bits = getunits(&argv[2][1]);

for (n = 0, hcode = -1; n < 16; n++)
    if (housetab[n].h_letter == hletter)
	{
	hcode = housetab[n].h_code;
	break;
	}
if (hcode == -1) error("invalid house code");

dim = dimstate(argv[3], (argc == 5) ? argv[4] : "");

buf[0] = DIRCMD;
buf[1] = dim;
buf[2] = hcode;
buf[3] = bits & 0xFF;;
buf[4] = bits >> 8;
buf[5] = CHKSUM(buf);

sendsync();
(void) write(tty, (char *) buf, sizeof(buf));
chkack();
chkrpt(0);
}
SHAR_EOF
fi
if test -f 'x10.c'
then
	echo shar: "will not over-write existing file 'x10.c'"
else
cat << \SHAR_EOF > 'x10.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include <ctype.h>
#ifdef SYSV
#include <string.h>
#else
#include <strings.h>
#endif
#include <time.h>
#include "x10.h"

extern long time();
extern struct tm *localtime();
extern struct nstruct modnames[];
extern int tty;

void sigtimer();
char hc2char();

char
    syncmsg[SYNCN],
    flag;

struct hstruct			/* table to map housecodes into letters */
    housetab[] =
	{
	    {HC_A, 'a'}, {HC_B, 'b'}, {HC_C, 'c'}, {HC_D, 'd'},
	    {HC_E, 'e'}, {HC_F, 'f'}, {HC_G, 'g'}, {HC_H, 'h'},
	    {HC_I, 'i'}, {HC_J, 'j'}, {HC_K, 'k'}, {HC_L, 'l'},
	    {HC_M, 'm'}, {HC_N, 'n'}, {HC_O, 'o'}, {HC_P, 'p'}
	};

char *wdays[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
		 "Thursday", "Friday", "Saturday", "<day not set>"};

unsigned char		/* table to map unit numbers into unit bit mask */
    maphibyt[] =
	{
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
	},
    maplobyt[] =
	{
	0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
	};

int
    timeout = TIMEOUT,
    Iloaded,
    Iminutes,
    Ihours,
    Idays;

unsigned char
    Ihcode;

extern int
    c_data(),
    c_date(),
    c_delete(),
    c_diagnostic(),
    c_dump(),
    c_fdump(),
    c_finfo(),
    c_fload(),
    c_info(),
    c_monitor(),
    c_reset(),
    c_schedule(),
    c_setclock(),
    c_unit();

struct cmdentry
    {
    char *cmd_name;
    int (*cmd_routine) ();
    } cmdtab[] =
	{
	"data", c_data,
	"date", c_date,
	"delete", c_delete,
	"diagnostic", c_diagnostic,
	"dump", c_dump,
	"fdump", c_fdump,
	"finfo", c_finfo,
	"fload", c_fload,
	"info", c_info,
	"monitor", c_monitor,
	"reset", c_reset,
	"schedule", c_schedule,
	"setclock", c_setclock,
	"unit", c_unit,
	"", NULL
	};

main(argc, argv)
char *argv[];
{
register i;
int (*rtn) ();
struct cmdentry *c;

if (argc < 2) usage(E_NOCMD);
rtn = NULL;
for (c = cmdtab; c->cmd_routine != NULL; c++)
    if (strcmp(argv[1], c->cmd_name) == 0)
	{
	rtn = c->cmd_routine;
	break;
	}
if (rtn == NULL) usage(E_INVCN);
setup_tty();

#ifdef MINIEXCH
mxconnect(MINIXPORT);
#endif

for (i = 0; i < SYNCN; i++)
    syncmsg[i] = i < 11 ? 0xEF : 0xFF;
init();
(*rtn) (argc, argv);
restore_tty();
return 0;
}

/*
 * Convert X10-style day of week (bit map, bit 0=monday, 6=sunday)
 * to UNIX localtime(3) style day of week (integer, 0=sunday)
 */

dowX2U(b)
register char b;
{
register n;

for (n = 1; (! (b & 1)) && n < 8; n++, b = b >> 1)
    ;
if (n == 7) n = 0;
if (n == 8) n = 7;
return(n);
}

dowU2X(d)
register d;
{
if (d == 0) d = 7;
return(1 << (d-1));
}

init()
{
int n;
unsigned char buf[6];

sendsync();
(void) write(tty, "\004", 1);		/* GETINFO command */
getsync();
n = xread(tty, buf, 6, timeout);

if (n != 6)
    error("invalid Clock and Base Housecode message length");
if (CHKSUM(buf) != buf[5])
    error("checksum error");

Iloaded = buf[0] & 1;
Iminutes = buf[1];
Ihours = buf[2];
Idays = buf[3];
Ihcode = buf[4];
}

chkack()
{
unsigned char buf[7];
int n;

n = xread(tty, buf, 7, timeout);
if (n != 7)
    {
    int i;

    (void) fprintf(stderr, "chkack dump (%d bytes):\n", n);
    for (i = 0; i < n; i++)
    	(void) fprintf(stderr, "buf[%d] = 0x%x\n", i, buf[i]);
    error("timeout while awaiting ACK message");
    }
}

/*
 * Check command report ("Command Upload", the manual calls it).
 * If argument supplied is non-zero, print the report in human-readable
 * form.
 */

chkrpt(printflag)
{
static char *statetab[] = {"?", "?", "ON", "OFF", "DIM", "DIM", "?", "?"};
int n;
unsigned char buf[6];
long dtime;
struct tm *tp;

getsync();
n = xread(tty, buf, 6, timeout);

if (n != 6)
    error("chkrpt: invalid event report length");
if (CHKSUM(buf) != buf[5])
    {
    (void) fprintf(stderr,
	"Checksum computed: 0x%x, received: 0x%x\n", CHKSUM(buf), buf[5]);
    error("chkrpt: checksum error");
    }
if (! printflag) return;

dtime = time((long *) 0);
tp = localtime(&dtime);

(void) printf("%2d:%02d:%02d: housecode %c, units: ",
       tp->tm_hour, tp->tm_min, tp->tm_sec, hc2char(buf[1] & 0xF0));
punits((buf[3] << 8) | buf[2]);
(void) printf(", state %s\n", statetab[buf[1] & 0x07]);
}

getsync()
{
unsigned char buf[RCVSYNC];

if (xread(tty, buf, RCVSYNC, timeout) < RCVSYNC)
    error("Failed to get sync characters");
}

sendsync()
{
(void) write(tty, syncmsg, SYNCN);
}

chksum(buf, size)
unsigned char *buf;
{
register i, sum;

for (i = 1, sum = 0; i < (size-1); i++)
    sum += buf[i];
return(sum & 0xFF);
}

char hc2char(code)
unsigned code;
{
register i;

for (i = 0; i < 16; i++)
    if (housetab[i].h_code == code)
	return (housetab[i].h_letter);
return('?');
}

/*
 * Parse string of comma-separated unit numbers and return bitmap
 * (big-endian) of units specified.  '*' means "all units".
 */

getunits(p)
register char *p;
{

#define DIGBUFN 80

unsigned lobits, hibits, n, unit;
char digbuf[DIGBUFN];

lobits = 0;
hibits = 0;
while (*p)
    {
    if (*p == '*')
    	{
    	lobits = 0xFF;
    	hibits = 0xFF;
    	break;
    	}
    for (n = 0; n < DIGBUFN && isdigit(*p); n++, p++)
    	digbuf[n] = *p;
    digbuf[n] = '\0';
    if ((unit = atoi(digbuf)) < 1 || unit > 16)
    	error("bad unit code, must be between 1 and 16");
    lobits |= maplobyt[unit-1];
    hibits |= maphibyt[unit-1];
    if (*p)
    	if (*p != ',')
    	    error("bad unit separator, use comma please");
    	else
    	    p++;
    }
return((lobits << 8) | hibits);
}

dimstate(p, level)
register char *p, *level;
{
unsigned levelnum;

if (strcmp(p, "on") == 0) return(2);
if (strcmp(p, "off") == 0) return(3);
if (strcmp(p, "dim") != 0) error("bad state keyword");
if (sscanf(level, "%d", &levelnum) == 0) error("dim value must be numeric");
if (levelnum > 15) error("dim value out of range, must be between 0 and 15");
timeout = DTIMEOUT;
return((levelnum << 4) | 5);
}

/* names must have first letter capitalized for day2bits() */
struct nstruct
    dtab[] =
	{
	"Monday",    0x01,
	"Tuesday",   0x02,
	"Wednesday", 0x04,
	"Thursday",  0x08,
    	"Friday",    0x10,
    	"Saturday",  0x20,
    	"Sunday",    0x40,
    	"Everyday",  0x7f,
    	"Weekdays",  0x1f,
    	"Weekend",   0x60,
    	"",          0x00
    	};

day2bits(p)
char *p;
{
char c, buf[4];
int n, mask, length;

n = 0;
while (n < 5)
    if (c = *p++)
	{
	if (n) {if (isupper(c)) c = tolower(c);}
	else if (islower(c)) c = toupper(c);
	buf[n++] = c;
	}
    else
	break;
buf[n] = '\0';
length = strlen(buf);
mask = 0;
for (n = 0; dtab[n].n_code != 0; n++)
    {
    if (strncmp(dtab[n].n_name, buf, length) == 0)
    	{
    	if (mask != 0) error("ambiguous day abbreviation");
    	mask = dtab[n].n_code;
    	}
    }
if (mask == 0) error("bad day keyword");
return(mask);
}

mode2code(p)
char *p;
{
char *np, *sp;
int n, mode, pos;

sp = p;
for (mode = n = 0; *modnames[n].n_name != 0; n++)
    {
    p = sp;
    np = modnames[n].n_name; /* names have first letter capitalized */
    if ((isupper(*p) ? *p : toupper(*p)) != *np) continue;
    for (p++, np++; *p; p++, np++)
	if ((isupper(*p) ? tolower(*p) : *p) != *np) break;
    if (*p == 0)
	{
	if (mode) error("ambiguous mode abbreviation");
	mode = modnames[n].n_code;
	pos = n;
	}
    }
if (mode == 0) error("bad mode keyword");
flag = pos;	/* position of function name in table */
return(mode);
}
SHAR_EOF
fi
if test -f 'xread.c'
then
	echo shar: "will not over-write existing file 'xread.c'"
else
cat << \SHAR_EOF > 'xread.c'
/*
 * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA
 * (maynard!campbell).  You may freely copy, use, and distribute this software
 * subject to the following restrictions:
 *
 *  1)	You may not charge money for it.
 *  2)	You may not remove or alter this copyright notice.
 *  3)	You may not claim you wrote it.
 *  4)	If you make improvements (or other changes), you are requested
 *	to send them to me, so there's a focal point for distributing
 *	improved versions.
 *
 * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted
 * by doing the System V port and adding some nice features.  Thanks!
 */

#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include "x10.h"

unsigned alarm();
void sigtimer();

/*
 * xread(fd, buf, count, timeout)
 *
 *	Timed read.  Works just like read(2) but gives up after
 *	timeout seconds, returning whatever's been read so far.
 */

static jmp_buf jb;

xread(fd, buf, count, timeout)
unsigned char *buf;
{
int total;

total = 0;
if (setjmp(jb))
    return(total);

(void) signal(SIGALRM, sigtimer);
(void) alarm((unsigned) timeout);

while (count--)
    {
    if (read(fd, (char *) buf, 1) < 1)
    	{
    	(void) alarm(0);
    	(void) signal(SIGALRM, SIG_IGN);
    	return(total);
    	}
    buf++;
    total++;
    }
(void) alarm(0);
(void) signal(SIGALRM, SIG_IGN);
return(total);
}

void
sigtimer()
{
longjmp(jb, 1);
}
SHAR_EOF
fi
exit 0
#	End of shell archive
-- 
Larry Campbell                             The Boston Software Works, Inc.
ARPA: campbell%maynard.uucp@harvard.ARPA   120 Fulton Street, Boston MA 02109
UUCP: {alliant,wjh12}!maynard!campbell     (617) 367-6846