/* x10.c (c) Copyright Daniel D. Lanciani 1995-1999 All rights reserved. x10.c is licensed free of charge for non-commercial distribution and for personal and internal business use only. x10.c may not be distributed for profit, nor may it be included in products or otherwise distributed by commercial entities to their clients or customers without the prior written permission of the author. TO THE EXTENT ALLOWED BY APPLICABLE LAW, x10.c IS PROVIDED "AS IS", WITH NO EXPRESS OR IMPLIED WARRANTY, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL THE AUTHOR BE LIABLE FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE x10.c EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. These copyright, license, and disclaimer notices must be included with all copies of x10.c. Modified versions of x10.c must be marked as such. ddl@danlan.com */ #include #include #include #include #include #include char buf[128]; char hc[2] = "A"; int mflag, qflag; #define X10_ALL_UNITS_OFF 17 #define X10_ALL_LIGHTS_ON 18 #define X10_ON 19 #define X10_OFF 20 #define X10_DIM 21 #define X10_BRIGHT 22 #define X10_EXTENDED 24 #define X10_STATUS_ON 30 #define X10_STATUS_OFF 31 #define X10_STATUS_REQUEST 32 struct x10aliases { char *name; int code; } x10aliases[] = { { "ALLUNITSOFF", X10_ALL_UNITS_OFF }, { "ALLLIGHTSON", X10_ALL_LIGHTS_ON }, { "ON", X10_ON }, { "OFF", X10_OFF }, { "DIM", X10_DIM }, { "BRIGHT", X10_BRIGHT }, { "STATUSREQUEST", X10_STATUS_REQUEST }, { 0, 0 } }, xtdaliases[] = { { "INCLUDECURRENT", 0x30 }, { "PRESET", 0x31 }, { "INCLUDESET", 0x32 }, { "ALLUNITSON", 0x33 }, { "XALLUNITSOFF", 0x34 }, { "REMOVE", 0x35 }, { "EXECUTE", 0x36 }, { "OUTPUTSTATUS", 0x37 }, { "OUTPUTSTATUSACK", 0x38 }, { "GROUPSTATUSACK", 0x39 }, { "GROUPSTATUSNAK", 0x3a }, { "CONFIGURE", 0x3b }, { "GROUPBRIDIM", 0x3c }, { 0, 0 } }; onalarm() { exit(1); } main(argc, argv) char **argv; { static struct sockaddr_in sin; register int i, s; register char *p, *q; register struct x10aliases *xp; struct hostent *hp; struct servent *sp; FILE *n; for(i = 1; i < argc && *argv[i] == '-'; i++) switch(argv[i][1]) { case 'm': mflag = 1; break; case 'q': qflag = 1; break; default: goto usage; } if(i >= argc && !mflag) { usage: fprintf(stderr,"Usage: %s [-m] [-q] functions\n", argv[0]); exit(1); } if(!(hp = gethostbyname("hamx10.ddl"))) { fprintf(stderr, "hamx10: unknown host\n"); exit(1); } if(!(sp = getservbyname("hamx10", "tcp"))) { fprintf(stderr, "Unknown service hamx10\n"); exit(1); } sin.sin_family = hp->h_addrtype; bcopy(hp->h_addr, &sin.sin_addr, hp->h_length); sin.sin_port = sp->s_port; if((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); exit(1); } if(connect(s, &sin, sizeof(sin))) { perror("connect"); exit(1); } if(!(n = fdopen(s, "r"))) { perror("fdopen"); exit(1); } if(mflag && i >= argc) { while(fgets(buf, sizeof(buf), n)) if(*buf == 'R') printf("%s", buf + 2); fprintf(stderr, "Communication terminated\n"); exit(1); } for(q = buf; i < argc; i++) { for(p = argv[i]; *p; ) { for(xp = x10aliases; xp->name; xp++) if(!strncasecmp(xp->name, p, strlen(xp->name))){ sprintf(q, "%s%d", hc, xp->code); q += strlen(q); p += strlen(xp->name); goto cont; } for(xp = xtdaliases; xp->name; xp++) if(!strncasecmp(xp->name, p, strlen(xp->name))){ sprintf(q, "t%d%s24", xp->code, hc); q += strlen(q); p += strlen(xp->name); goto cont; } if(*p >= '0' && *p <= '9') { *q++ = *hc; while(*p >= '0' && *p <= '9') *q++ = *p++; } else if(*p >= 'A' && *p <= 'P') *hc = *p++; else if(*p >= 'a' && *p <= 'p') *hc = *p++ - 'a' + 'A'; else if(*p == 'r' || *p == 'R' || *p == 'u' || *p == 'U' || *p == 'v' || *p == 'V') { *q++ = *p++; while(*p >= '0' && *p <= '9') *q++ = *p++; } else if(*p == 's' || *p == 'S') { *q++ = *p++; if(*p) *q++ = *p++; while(*p >= '0' && *p <= '9') *q++ = *p++; } else if(*p == 't' || *p == 'T') { *q++ = *p++; for(xp = xtdaliases; xp->name; xp++) if(!strncasecmp(xp->name, p, strlen(xp->name))) { sprintf(q, "%d", xp->code); q += strlen(q); p += strlen(xp->name); goto cont; } while(*p >= '0' && *p <= '9') *q++ = *p++; } else { fprintf(stderr, "Syntax error near %s\n", p); exit(1); } cont:; } } strcat(buf, "\r\n"); write(s, buf, strlen(buf)); if(qflag) { signal(SIGALRM, onalarm); alarm(20); } while(fgets(buf, sizeof(buf), n)) { if(*buf == 'A') { if(qflag) goto waitstatus; exit(0); } else if(*buf == 'E') { fprintf(stderr, "Error: %s", buf + 2); exit(1); } else if(mflag && *buf == 'R') printf("%s", buf + 2); } fprintf(stderr, "Communication terminated\n"); exit(1); waitstatus: while(fgets(buf, sizeof(buf), n)) { if(*buf != 'R') continue; if(mflag) printf("%s", buf + 2); if(buf[2] != *hc) continue; if((i = atoi(buf + 3)) == X10_STATUS_ON) exit(0); else if(i == X10_STATUS_OFF) exit(2); } fprintf(stderr, "Communication terminated\n"); exit(1); }