This is no longer needed after tw is gone.
Approved by: re@ (scottl)
This commit is contained in:
parent
a22a473401
commit
733bde7ebe
@ -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)
|
||||
|
@ -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…
x
Reference in New Issue
Block a user