This is no longer needed after tw is gone.
Approved by: re@ (scottl)
This commit is contained in:
parent
570a2f4ac5
commit
b4e225bef1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=114113
@ -1,4 +1,4 @@
|
|||||||
# @(#)Makefile 8.1 (Berkeley) 6/4/93
|
@(#)Makefile 8.1 (Berkeley) 6/4/93
|
||||||
# $FreeBSD$
|
# $FreeBSD$
|
||||||
|
|
||||||
# Present but disabled: kpasswdd
|
# Present but disabled: kpasswdd
|
||||||
@ -28,7 +28,6 @@ SUBDIR= atrun \
|
|||||||
talkd \
|
talkd \
|
||||||
tcpd \
|
tcpd \
|
||||||
tftpd \
|
tftpd \
|
||||||
xtend \
|
|
||||||
ypxfr
|
ypxfr
|
||||||
|
|
||||||
.if !defined(NO_BIND)
|
.if !defined(NO_BIND)
|
||||||
|
@ -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>
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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"
|
|
@ -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;
|
|
||||||
}
|
|
@ -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));
|
|
||||||
}
|
|
||||||
|
|
@ -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 */
|
|
||||||
|
|
@ -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
|
|
@ -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 */
|
|
||||||
}
|
|
@ -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);
|
|
Loading…
Reference in New Issue
Block a user