This is no longer needed after tw is gone.

Approved by: re@ (scottl)
This commit is contained in:
Warner Losh 2003-04-27 05:43:42 +00:00
parent 570a2f4ac5
commit b4e225bef1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=114113
10 changed files with 1 additions and 1381 deletions

View File

@ -1,4 +1,4 @@
# @(#)Makefile 8.1 (Berkeley) 6/4/93
@(#)Makefile 8.1 (Berkeley) 6/4/93
# $FreeBSD$
# Present but disabled: kpasswdd
@ -28,7 +28,6 @@ SUBDIR= atrun \
talkd \
tcpd \
tftpd \
xtend \
ypxfr
.if !defined(NO_BIND)

View File

@ -1,14 +0,0 @@
# Makefile for xtend (Stark) 10/30/93
# $FreeBSD$
BINMODE= 555
PROG= xtend
SRCS= xtend.c status.c packet.c user.c
CFLAGS+= -DXTENUNAME=\"xten\" -DXTENGNAME=\"xten\"
DPADD= ${LIBUTIL}
LDADD= -lutil
MAN= xtend.8
.include <bsd.prog.mk>

View File

@ -1,322 +0,0 @@
/*-
* Copyright (c) 1992, 1993, 1995 Eugene W. Stark
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Eugene W. Stark.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY EUGENE W. STARK (THE AUTHOR) ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include <stdio.h>
#include <sys/time.h>
#include "xtend.h"
#include "xten.h"
char *X10housenames[] = {
"A", "B", "C", "D", "E", "F", "G", "H",
"I", "J", "K", "L", "M", "N", "O", "P",
NULL
};
char *X10cmdnames[] = {
"1", "2", "3", "4", "5", "6", "7", "8",
"9", "10", "11", "12", "13", "14", "15", "16",
"AllUnitsOff", "AllLightsOn", "On", "Off", "Dim", "Bright", "AllLightsOff",
"ExtendedCode", "HailRequest", "HailAcknowledge", "PreSetDim0", "PreSetDim1",
"ExtendedData", "StatusOn", "StatusOff", "StatusRequest",
NULL
};
/*
* Log a packet and update device status accordingly
*/
void
logpacket(unsigned char *p)
{
fprintf(Log, "%s: %s %s ", thedate(),
X10housenames[p[1]], X10cmdnames[p[2]]);
if(p[0] & TW_RCV_LOCAL) fprintf(Log, "(loc,");
else fprintf(Log, "(rem,");
if(p[0] & TW_RCV_ERROR) fprintf(Log, "err)");
else fprintf(Log, " ok)");
fprintf(Log, "\n");
}
/*
* Process a received packet p, updating device status information both
* in core and on disk.
*/
void
processpacket(unsigned char *p)
{
int i, j, h, k;
STATUS *s;
/*
* If the packet had the error flag set, there is no other useful info.
*/
if(p[0] & TW_RCV_ERROR) return;
/*
* First update in-core status information for the device.
*/
h = p[1]; k = p[2];
if(k < 16) { /* We received a unit code, to select a particular device */
s = &Status[h][k];
s->selected = SELECTED;
s->lastchange = time(NULL);
s->changed = 1;
} else { /* We received a key code, to execute some function */
/*
* Change in status depends on the key code received
*/
if(k == DIM) {
/*
* We can't really track DIM/BRIGHT properly the way things are right
* now. The TW523 reports the first, fourth, seventh, etc. Dim packet.
* We don't really have any way to tell when gaps occur, to cancel
* selection. For now, we'll assume that successive sequences of
* Dim/Bright commands are never transmitted without some other
* intervening command, and we make a good guess about how many units of
* dim/bright are represented by each packet actually reported by the
* TW523.
*/
for(i = 0; i < 16; i++) {
s = &Status[h][i];
switch(s->selected) {
case SELECTED: /* Selected, but not being dimmed or brightened */
if(s->onoff == 0) {
s->onoff = 1;
s->brightness = 15;
}
s->brightness -= 2;
if(s->brightness < 0) s->brightness = 0;
s->selected = DIMMING;
s->lastchange = time(NULL);
s->changed = 1;
break;
case DIMMING: /* Selected and being dimmed */
s->brightness -=3;
if(s->brightness < 0) s->brightness = 0;
s->lastchange = time(NULL);
s->changed = 1;
break;
case BRIGHTENING: /* Selected and being brightened (an error) */
s->selected = IDLE;
s->lastchange = time(NULL);
s->changed = 1;
break;
default:
break;
}
}
} else if(k == BRIGHT) {
/*
* Same problem here...
*/
for(i = 0; i < 16; i++) {
s = &Status[h][i];
switch(s->selected) {
case SELECTED: /* Selected, but not being dimmed or brightened */
if(s->onoff == 0) {
s->onoff = 1;
s->brightness = 15;
}
s->brightness += 2;
if(s->brightness > 15) s->brightness = 15;
s->selected = BRIGHTENING;
s->lastchange = time(NULL);
s->changed = 1;
break;
case DIMMING: /* Selected and being dimmed (an error) */
s->selected = IDLE;
s->lastchange = time(NULL);
s->changed = 1;
break;
case BRIGHTENING: /* Selected and being brightened */
s->brightness +=3;
if(s->brightness > 15) s->brightness = 15;
s->lastchange = time(NULL);
s->changed = 1;
break;
default:
break;
}
}
} else { /* Other key codes besides Bright and Dim */
/*
* We cancel brightening and dimming on ALL units on ALL house codes,
* because the arrival of a different packet indicates a gap that
* terminates any prior sequence of brightening and dimming
*/
for(j = 0; j < 16; j++) {
for(i = 0; i < 16; i++) {
s = &Status[j][i];
if(s->selected == BRIGHTENING || s->selected == DIMMING) {
s->selected = IDLE;
s->lastchange = time(NULL);
s->changed = 1;
}
}
}
switch(k) {
case ALLUNITSOFF:
for(i = 0; i < 16; i++) {
s = &Status[h][i];
s->onoff = 0;
s->selected = IDLE;
s->brightness = 0;
s->lastchange = time(NULL);
s->changed = 1;
}
break;
case ALLLIGHTSON:
/* Does AllLightsOn cancel selectedness of non-lights? */
for(i = 0; i < 16; i++) {
s = &Status[h][i];
if(s->devcap & ISLIGHT) {
s->onoff = 1;
s->selected = IDLE;
s->brightness = 15;
s->lastchange = time(NULL);
s->changed = 1;
}
}
break;
case UNITON:
for(i = 0; i < 16; i++) {
s = &Status[h][i];
if(s->selected == SELECTED) {
s->onoff = 1;
s->selected = IDLE;
s->brightness = 15;
s->lastchange = time(NULL);
s->changed = 1;
}
}
break;
case UNITOFF:
for(i = 0; i < 16; i++) {
s = &Status[h][i];
if(s->selected == SELECTED) {
s->onoff = 0;
s->selected = IDLE;
s->lastchange = time(NULL);
s->changed = 1;
}
}
break;
case ALLLIGHTSOFF:
/* Does AllLightsOff cancel selectedness of non-lights? */
for(i = 0; i < 16; i++) {
s = &Status[h][i];
if(s->devcap & ISLIGHT) {
s->onoff = 0;
s->selected = IDLE;
s->lastchange = time(NULL);
s->changed = 1;
}
}
break;
case EXTENDEDCODE:
break;
case HAILREQUEST:
for(i = 0; i < 16; i++) {
s = &Status[h][i];
if(s->selected == SELECTED) {
s->selected = HAILED;
s->lastchange = time(NULL);
s->changed = 1;
}
}
break;
case HAILACKNOWLEDGE:
/* Do these commands cancel selection of devices not affected? */
for(i = 0; i < 16; i++) {
s = &Status[h][i];
if(s->selected == HAILED) {
s->selected = IDLE;
s->lastchange = time(NULL);
s->changed = 1;
}
}
break;
case PRESETDIM0:
case PRESETDIM1:
/* I don't really understand these */
for(i = 0; i < 16; i++) {
s = &Status[h][i];
if(s->selected == SELECTED) {
s->selected = IDLE;
s->lastchange = time(NULL);
s->changed = 1;
}
}
break;
case EXTENDEDDATA:
/* Who knows? The TW523 can't receive these anyway. */
break;
case STATUSON:
for(i = 0; i < 16; i++) {
s = &Status[h][i];
if(s->selected == REQUESTED) {
s->onoff = 1;
s->selected = IDLE;
s->lastchange = time(NULL);
s->changed = 1;
}
}
break;
case STATUSOFF:
for(i = 0; i < 16; i++) {
if(s->selected == REQUESTED) {
s = &Status[h][i];
s->onoff = 0;
s->selected = IDLE;
s->brightness = 0;
s->lastchange = time(NULL);
s->changed = 1;
}
}
case STATUSREQUEST:
for(i = 0; i < 16; i++) {
s = &Status[h][i];
if(s->selected) {
s->selected = REQUESTED;
s->lastchange = time(NULL);
s->changed = 1;
}
}
break;
}
}
}
}

View File

@ -1,13 +0,0 @@
/*
* Pathnames for files used by xtend
*
* $FreeBSD$
*/
#define X10DIR "/var/spool/xten"
#define X10LOGNAME "Log"
#define X10STATNAME "Status"
#define X10DUMPNAME "status.out"
#define TWPATH "/dev/tw0"
#define SOCKPATH "/var/run/tw523"
#define PIDPATH "/var/run/xtend.pid"

View File

@ -1,117 +0,0 @@
/*-
* Copyright (c) 1992, 1993, 1995 Eugene W. Stark
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Eugene W. Stark.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY EUGENE W. STARK (THE AUTHOR) ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include <stdio.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/stat.h>
#include "xtend.h"
#include "xten.h"
#include "paths.h"
void printstatus(FILE *, STATUS *);
/*
* Initialize the status table from the status files
*/
void
initstatus(void)
{
if(lseek(status, 0, SEEK_SET) != 0) {
fprintf(Log, "%s: Seek error on status file\n", thedate());
return;
}
if(read(status, Status, 16*16*sizeof(STATUS)) != 16*16*sizeof(STATUS)) {
fprintf(Log, "%s: Read error on status file\n", thedate());
return;
}
}
/*
* Checkpoint status of any devices whose status has changed
* and notify anyone monitoring those devices.
*/
void
checkpoint_status(void)
{
int h, i, k, offset;
offset = 0;
for(h = 0; h < 16; h++) {
for(i = 0; i < 16; i++) {
if(Status[h][i].changed) {
if(lseek(status, offset, SEEK_SET) != offset) {
fprintf(Log, "%s: Seek error on status file\n", thedate());
} else {
if(write(status, &Status[h][i], sizeof(STATUS)) != sizeof(STATUS)) {
fprintf(Log, "%s: Write error on status file\n", thedate());
}
}
Status[h][i].changed = 0;
for(k = 0; k < MAXMON; k++) {
if(Monitor[k].inuse
&& Monitor[k].house == h && Monitor[k].unit == i) {
/*
* Arrange to catch SIGPIPE in case client has gone away.
*/
extern int client;
extern void clientgone();
void (*prev)();
client = k;
prev = signal(SIGPIPE, clientgone);
printstatus(Monitor[k].user, &Status[h][i]);
fflush(Monitor[k].user);
signal(SIGPIPE, prev);
}
}
}
offset += sizeof(STATUS);
}
}
}
int client;
void
clientgone(void)
{
fprintf(Log, "%s: Deleting monitor table entry %d, client gone\n", thedate(), client);
fclose(Monitor[client].user);
Monitor[client].inuse = 0;
}

View File

@ -1,182 +0,0 @@
/*-
* Copyright (c) 1992, 1993, 1995 Eugene W. Stark
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Eugene W. Stark.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY EUGENE W. STARK (THE AUTHOR) ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/time.h>
#include "xtend.h"
#include "xten.h"
#include "paths.h"
MONENTRY Monitor[MAXMON];
int find(char *, char *[]);
void printstatus(FILE *, STATUS *);
/*
* Process a user command
*/
int
user_command(void)
{
char h;
char *m;
int i, k, n, error;
char cmd[512], dumppath[MAXPATHLEN], pkt[3];
FILE *dumpf;
error = 0;
if(fgets(cmd, 512, User) != NULL) {
m = cmd;
while ( *m != '\0' ) {
if(isupper(*m))
*m = tolower(*m);
m++;
}
if(sscanf(cmd, "status %c %d", &h, &i) == 2
&& h >= 'a' && h <= 'p' && i >= 1 && i <= 16) {
h -= 'a';
i--;
printstatus(User, &Status[h][i]);
} else if(sscanf(cmd, "send %c %s %d", &h, cmd, &n) == 3
&& h >= 'a' && h <= 'p' && (i = find(cmd, X10cmdnames)) >= 0) {
h -= 'a';
pkt[0] = h;
pkt[1] = i;
pkt[2] = n;
if(write(tw523, pkt, 3) != 3) {
fprintf(Log, "%s: Transmission error (packet [%s %s]:%d).\n",
thedate(), X10housenames[h], X10cmdnames[i], n);
error++;
} else {
fprintf(User, "OK\n");
}
} else if(!strcmp("dump\n", cmd)) {
snprintf(dumppath, sizeof(dumppath), "%s/%s", X10DIR, X10DUMPNAME);
if((dumpf = fopen(dumppath, "w")) != NULL) {
for(h = 0; h < 16; h++) {
for(i = 0; i < 16; i++) {
if(Status[h][i].lastchange) {
fprintf(dumpf, "%s%d\t", X10housenames[h], i+1);
printstatus(dumpf, &Status[h][i]);
}
}
}
fclose(dumpf);
fprintf(User, "OK\n");
} else {
error++;
}
} else if(sscanf(cmd, "monitor %c %d", &h, &i) == 2
&& h >= 'a' && h <= 'p' && i >= 1 && i <= 16) {
h -= 'a';
i--;
for(k = 0; k < MAXMON; k++) {
if(!Monitor[k].inuse) break;
}
if(k == MAXMON) {
error++;
} else {
Monitor[k].house = h;
Monitor[k].unit = i;
Monitor[k].user = User;
Monitor[k].inuse = 1;
fprintf(Log, "%s: Adding %c %d to monitor list (entry %d)\n",
thedate(), h+'A', i+1, k);
fprintf(User, "OK\n");
fflush(User);
User = NULL;
return(0); /* We don't want caller to close stream */
}
} else if(!strcmp("done\n", cmd)) {
fprintf(User, "OK\n");
fflush(User);
return(1);
} else {
if(feof(User)) {
return(1);
} else {
error++;
}
}
} else {
error++;
}
if(error) {
fprintf(User, "ERROR\n");
}
fflush(User);
return(0);
}
int
find(char *s, char *tab[])
{
int i;
for(i = 0; tab[i] != NULL; i++) {
if(strcasecmp(s, tab[i]) == 0) return(i);
}
return(-1);
}
void
printstatus(FILE *f, STATUS *s)
{
fprintf(f, "%s:%d", s->onoff ? "On" : "Off", s->brightness);
switch(s->selected) {
case IDLE:
fprintf(f, " (normal) "); break;
case SELECTED:
fprintf(f, " (selected) "); break;
case DIMMING:
fprintf(f, " (dimming) "); break;
case BRIGHTENING:
fprintf(f, " (brightening) "); break;
case REQUESTED:
fprintf(f, " (requested) "); break;
case HAILED:
fprintf(f, " (hailed) "); break;
default:
fprintf(f, " (bogus) "); break;
}
fprintf(f, "%s", ctime(&s->lastchange));
}

View File

@ -1,60 +0,0 @@
/*-
* Copyright (c) 1992, 1993, 1995 Eugene W. Stark
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Eugene W. Stark.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY EUGENE W. STARK (THE AUTHOR) ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
extern char *X10housenames[];
extern char *X10cmdnames[];
#define ALLUNITSOFF 16
#define ALLLIGHTSON 17
#define UNITON 18
#define UNITOFF 19
#define DIM 20
#define BRIGHT 21
#define ALLLIGHTSOFF 22
#define EXTENDEDCODE 23
#define HAILREQUEST 24
#define HAILACKNOWLEDGE 25
#define PRESETDIM0 26
#define PRESETDIM1 27
#define EXTENDEDDATA 28
#define STATUSON 29
#define STATUSOFF 30
#define STATUSREQUEST 31
/*
* Flags for first byte of received packet
*/
#define TW_RCV_LOCAL 1 /* The packet arrived during a local transmission */
#define TW_RCV_ERROR 2 /* An invalid/corrupted packet was received */

View File

@ -1,189 +0,0 @@
.\" Copyright (c) 1992, 1993 Eugene W. Stark
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by Eugene W. Stark.
.\" 4. The name of the author may not be used to endorse or promote products
.\" derived from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY EUGENE W. STARK (THE AUTHOR) ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd October 30, 1993
.Dt XTEND 8
.Os
.Sh NAME
.Nm xtend
.Nd X-10 daemon
.Sh SYNOPSIS
.Nm /usr/libexec/xtend
.Sh DESCRIPTION
The
.Nm
utility
interfaces between user-level programs and the TW523 X-10 controller.
It logs all packets received from the TW523, attempts to track the
status of all X-10 devices, and accepts socket connections from user-level
client programs that need to manipulate X-10 devices.
.Pp
When
.Nm
is started, it forks, releases the controlling terminal, then opens
its log file, where it subsequently records all X-10 activity and
diagnostic messages. It then begins processing packets received from
the TW523 and accepting connections one at a time from clients
wishing to issue X-10 commands.
The
.Nm
utility is started from
.Pa /etc/rc.i386
startup script if enabled in
.Pa /etc/rc.conf
script.
.Pp
Sending
.Nm
a
.Dv SIGHUP
causes it to close and reopen its log file. This is useful
in shell scripts that rotate the log files to keep them from growing
indefinitely.
If
.Nm
receives a
.Dv SIGTERM ,
it shuts down gracefully and exits.
A
.Dv SIGPIPE
causes
.Nm
to abort the current client connection.
.Pp
The
.Nm
utility
communicates with client processes by a simple protocol in which a one-line
command is sent by the client, and is acknowledged by a one-line response
from the daemon.
.Pp
The
.Nm
utility understands four types of commands:
.Bl -tag -width "monitor H U
.It Ic status Ar H U
where
.Ar H
is a single letter house code, and
.Ar U
is a numeric unit code,
causes
.Nm
to respond with one line of status information about the specified device.
.It Ic send Ar H U N
where
.Ar H
is a single-letter house code,
.Ar U
is either a numeric unit code
or a function code (see source file
.Pa xtend/packet.c )
for a list, and
.Ar N
is a number indicating the number of times (usually 2)
the packet is to be transmitted without gaps,
causes
.Nm
to perform the specified X-10 transmission. If the transmission was apparently
successful, a single-line response containing
.Sy OK
is issued, otherwise a single-line response containing
.Sy ERROR
is produced.
.It Ic dump
causes
.Nm
to dump the current status of all devices to an
.Tn ASCII
file in the spool
directory. The response
.Sy OK
is issued, regardless of whether the status dump was successful.
.It Ic monitor Ar H U
causes
.Nm
to add the current client socket connection to a list of clients that are to
be notified about activity concerning the specified X-10 device.
The single-line acknowledgement
.Sy OK
is returned if the maximum (currently 5) number of such clients was not
exceeded, otherwise
.Sy ERROR
is returned.
The
.Nm
utility
then returns to its normal mode of accepting connections from clients.
However, each subsequent change in the status of the specified device will
cause
.Nm
to write one line of status information for the device (in the same
format as produced by the
.Ic status
command) to the saved socket. This feature is useful for writing programs
that need to monitor the activity of devices, like motion detectors, that can
perform X-10 transmissions.
.El
.Sh OPTIONS
None.
.Sh SEE ALSO
.Xr xten 1 ,
.Xr tw 4
.Sh FILES
.Bl -tag -width /var/spool/xten/status.out -compact
.It Pa /dev/tw0
the TW523 special file
.It Pa /var/run/tw523
socket for client connections
.It Pa /var/run/xtend.pid
pid file
.It Pa /var/spool/xten/Log
log file
.It Pa /var/spool/xten/Status
device status file (binary)
.It Pa /var/spool/xten/status.out
.Tn ASCII
dump of device status
.El
.Sh BUGS
There is currently no timeout on client socket connections, so a hung
client program can prevent other clients from accessing the daemon.
.Pp
The
.Nm
utility
does the best it can at trying to track device status, but there is
usually no way it can tell when a device has been operated manually.
This is due to the fact that most X-10 devices are not able to
respond to queries about their status.
.Sh AUTHORS
.An Eugene W. Stark Aq stark@cs.sunysb.edu

View File

@ -1,403 +0,0 @@
/*-
* Copyright (c) 1992, 1993, 1995 Eugene W. Stark
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Eugene W. Stark.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY EUGENE W. STARK (THE AUTHOR) ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
/*
* xtend - X-10 daemon
* Eugene W. Stark (stark@cs.sunysb.edu)
* January 14, 1993
*/
#include <err.h>
#include <pwd.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <grp.h>
#include "xtend.h"
#include "xten.h"
#include "paths.h"
FILE *Log; /* Log file */
FILE *User; /* User connection */
STATUS Status[16][16]; /* Device status table */
int status; /* Status file descriptor */
int tw523; /* tw523 controller */
int sock; /* socket for user */
jmp_buf mainloop; /* longjmp point after SIGHUP */
volatile sig_atomic_t hup_flag; /* received SIGHUP flag */
volatile sig_atomic_t term_flag; /* received SIGTERM flag */
volatile sig_atomic_t pipe_flag; /* received SIGPIPE flag */
void checkpoint_status(void);
void dohup(void);
void dopipe(void);
void doterm(void);
void initstatus(void);
void logpacket(unsigned char *);
void onhup(int);
void onpipe(int);
void onterm(int);
void processpacket(unsigned char *);
int user_command(void);
int
main(int argc, char *argv[])
{
char *twpath = TWPATH;
char *sockpath = SOCKPATH;
char logpath[MAXPATHLEN];
char statpath[MAXPATHLEN];
struct sockaddr_un sa;
struct timeval tv;
struct passwd *pw;
struct group *gr;
struct stat sb;
int user;
FILE *pidf;
/*
* Make sure we start out running as root
*/
if(geteuid() != 0)
errx(1, "you must be root");
/*
* Find out what UID/GID we are to run as
*/
if((pw = getpwnam(XTENUNAME)) == NULL)
errx(1, "no such user '%s'", XTENUNAME);
if((gr = getgrnam(XTENGNAME)) == NULL)
errx(1, "no such group '%s'", XTENGNAME);
/*
* Open the log file before doing anything else
*/
if(stat(X10DIR, &sb) == -1 && errno == ENOENT) {
if(mkdir(X10DIR, 0755) != -1) {
chown(X10DIR, pw->pw_uid, gr->gr_gid);
} else {
errx(1, "can't create directory '%s'", X10DIR);
}
}
snprintf(logpath, sizeof(logpath), "%s/%s", X10DIR, X10LOGNAME);
if((Log = fopen(logpath, "a")) == NULL)
errx(1, "can't open log file '%s'", logpath);
chown(logpath, pw->pw_uid, gr->gr_gid);
/*
* Become a daemon
*/
if(daemon(0, 0) == -1) {
fprintf(Log, "%s: Unable to become a daemon\n", thedate());
fclose(Log);
exit(1);
}
fprintf(Log, "%s: %s [%d] started\n", thedate(), argv[0], getpid());
/*
* Get ahold of the TW523 device
*/
if((tw523 = open(twpath, O_RDWR)) < 0) {
fprintf(Log, "%s: Can't open %s\n", thedate(), twpath);
fclose(Log);
exit(1);
}
fprintf(Log, "%s: %s successfully opened\n", thedate(), twpath);
/*
* Put our pid in a file so we can be signalled by shell scripts
*/
if((pidf = fopen(PIDPATH, "w")) == NULL) {
fprintf(Log, "%s: Error writing pid file: %s\n", thedate(), PIDPATH);
fclose(Log);
exit(1);
}
fprintf(pidf, "%d\n", getpid());
fclose(pidf);
/*
* Set up socket to accept user commands
*/
if((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
fprintf(Log, "%s: Can't create socket\n", thedate());
fclose(Log);
exit(1);
}
strcpy(sa.sun_path, sockpath);
sa.sun_family = AF_UNIX;
unlink(sockpath);
if(bind(sock, (struct sockaddr *)(&sa), strlen(sa.sun_path) + 2) < 0) {
fprintf(Log, "%s: Can't bind socket to %s\n", thedate(), sockpath);
fclose(Log);
exit(1);
}
if(listen(sock, 5) < 0) {
fprintf(Log, "%s: Can't listen on socket\n", thedate());
fclose(Log);
exit(1);
}
/*
* Set proper ownership and permissions on the socket
*/
if(chown(sockpath, pw->pw_uid, gr->gr_gid) == -1 ||
chmod(sockpath, 0660) == -1) {
fprintf(Log, "%s: Can't set owner/permissions on socket\n", thedate());
fclose(Log);
exit(1);
}
/*
* Give up root privileges
*/
setgid(pw->pw_gid);
setuid(pw->pw_uid);
/*
* Initialize the status table
*/
strcpy(statpath, X10DIR);
strcat(statpath, "/");
strcat(statpath, X10STATNAME);
if((status = open(statpath, O_RDWR)) < 0) {
if((status = open(statpath, O_RDWR | O_CREAT, 0666)) < 0) {
fprintf(Log, "%s: Can't open %s\n", thedate(), statpath);
fclose(Log);
exit(1);
}
if(write(status, Status, 16 * 16 * sizeof(STATUS))
!= 16 * 16 * sizeof(STATUS)) {
fprintf(Log, "%s: Error initializing status file\n", thedate());
fclose(Log);
exit(1);
}
}
initstatus();
/*
* Return here on SIGHUP after closing and reopening log file.
* Also on SIGPIPE after closing user connection.
*/
signal(SIGHUP, onhup);
signal(SIGPIPE, onpipe);
signal(SIGTERM, onterm);
setjmp(mainloop);
/*
* Now start the main processing loop.
*/
tv.tv_sec = 0;
tv.tv_usec = 250000;
while(1) {
fd_set fs;
unsigned char rpkt[3];
int sel, h, k;
STATUS *s;
if (hup_flag)
dohup();
if (term_flag)
doterm();
if (pipe_flag)
dopipe();
FD_ZERO(&fs);
FD_SET(tw523, &fs);
if(User != NULL) FD_SET(user, &fs);
else FD_SET(sock, &fs);
sel = select(FD_SETSIZE, &fs, 0, 0, &tv);
if(sel == 0) {
/*
* Cancel brightening and dimming on ALL units on ALL house codes,
* because the fact that we haven't gotten a packet for awhile means
* that there was a gap in transmission.
*/
for(h = 0; h < 16; h++) {
for(k = 0; k < 16; k++) {
s = &Status[h][k];
if(s->selected == BRIGHTENING || s->selected == DIMMING) {
s->selected = IDLE;
s->lastchange = time(NULL);
s->changed = 1;
}
}
}
fflush(Log);
checkpoint_status();
/*
* Now that we've done this stuff, we'll set the timeout a little
* longer, so we don't keep looping too frequently.
*/
tv.tv_sec = 60;
tv.tv_usec = 0;
continue;
}
/*
* While there is stuff happening, we keep a short timeout, so we
* don't get stuck for some unknown reason, and so we can keep the
* brightening and dimming data up-to-date.
*/
tv.tv_sec = 0;
tv.tv_usec = 250000;
if(FD_ISSET(tw523, &fs)) { /* X10 data arriving from TW523 */
if(read(tw523, rpkt, 3) < 3) {
fprintf(Log, "%s: Error reading from TW523\n", thedate());
} else {
logpacket(rpkt);
processpacket(rpkt);
}
} else if(FD_ISSET(user, &fs) && User != NULL) {
if(user_command()) {
fprintf(Log, "%s: Closing user connection\n", thedate());
fclose(User);
User = NULL;
}
} else if(FD_ISSET(sock, &fs)) { /* Accept a connection */
if (User == NULL) {
int len = sizeof(struct sockaddr_un);
if((user = accept(sock, (struct sockaddr *)(&sa), &len)) >= 0) {
fprintf(Log, "%s: Accepting user connection\n", thedate());
if((User = fdopen(user, "w+")) == NULL) {
fprintf(Log, "%s: Can't attach socket to stream\n", thedate());
}
} else {
fprintf(Log, "%s: Failure in attempt to accept connection\n", thedate());
}
} else {
/* "Can't happen */
}
}
}
/* Not reached */
}
char *
thedate(void)
{
char *cp, *cp1;
time_t tod;
tod = time(NULL);
cp = cp1 = ctime(&tod);
while(*cp1 != '\n') cp1++;
*cp1 = '\0';
return(cp);
}
void
onhup(int signo)
{
hup_flag = 1;
}
void
onterm(int signo)
{
term_flag = 1;
}
void
onpipe(int signo)
{
pipe_flag = 1;
}
/*
* When SIGHUP received, close and reopen the Log file
*/
void
dohup(void)
{
char logpath[MAXPATHLEN];
fprintf(Log, "%s: SIGHUP received, reopening Log\n", thedate());
fclose(Log);
snprintf(logpath, sizeof(logpath), "%s/%s", X10DIR, X10LOGNAME);
if((Log = fopen(logpath, "a")) == NULL)
errx(1, "can't open log file '%s'", logpath);
hup_flag = 0;
longjmp(mainloop, 1);
/* No return */
}
/*
* When SIGTERM received, just exit normally
*/
void
doterm(void)
{
fprintf(Log, "%s: SIGTERM received, shutting down\n", thedate());
fclose(Log);
term_flag = 0;
exit(0);
}
/*
* When SIGPIPE received, reset user connection
*/
void
dopipe(void)
{
fprintf(Log, "%s: SIGPIPE received, resetting user connection\n",
thedate());
if(User != NULL) {
fclose(User);
User = NULL;
}
pipe_flag = 0;
longjmp(mainloop, 1);
/* No return */
}

View File

@ -1,79 +0,0 @@
/*-
* Copyright (c) 1992, 1993, 1995 Eugene W. Stark
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Eugene W. Stark.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY EUGENE W. STARK (THE AUTHOR) ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* Device capabilities
*/
#define ISLIGHT 1 /* Is device a light? */
#define CANQUERY 2 /* Responds to status query */
/*
* Device status
*/
typedef enum {
IDLE,
SELECTED,
DIMMING,
BRIGHTENING,
REQUESTED,
HAILED
} SELECT;
typedef struct {
unsigned int devcap; /* device capabilities */
unsigned int changed; /* status changed since last checkpoint? */
time_t lastchange; /* time status last changed */
SELECT selected; /* select status of device */
unsigned int onoff; /* nonzero if on */
unsigned int brightness; /* value in range 0-15 */
} STATUS;
typedef struct {
int inuse; /* Is entry in use? */
FILE *user; /* Socket to notify user */
int house; /* House code of device to monitor */
int unit; /* Unit code of device to monitor */
} MONENTRY;
#define MAXMON 5 /* Maximum number of monitor entries */
extern FILE *Log; /* Log file */
extern FILE *User; /* User connection */
extern STATUS Status[16][16]; /* Device status table */
extern int status; /* Status file descriptor */
extern int tw523; /* tw523 controller */
extern MONENTRY Monitor[MAXMON];/* Monitor table */
extern char *thedate(void);