Commit | Line | Data |
---|---|---|
e361428f PR |
1 | /*- |
2 | * Copyright (c) 1992, 1993 Eugene W. Stark | |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * 2. Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in the | |
12 | * documentation and/or other materials provided with the distribution. | |
13 | * 3. All advertising materials mentioning features or use of this software | |
14 | * must display the following acknowledgement: | |
15 | * This product includes software developed by Eugene W. Stark. | |
16 | * 4. The name of the author may not be used to endorse or promote products | |
17 | * derived from this software without specific prior written permission. | |
18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY EUGENE W. STARK (THE AUTHOR) ``AS IS'' AND | |
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, | |
23 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
29 | * SUCH DAMAGE. | |
30 | */ | |
31 | ||
32 | /* | |
33 | * Xten - user command interface to X-10 daemon | |
34 | */ | |
35 | ||
36 | #include <stdio.h> | |
37 | #include <sys/types.h> | |
38 | #include <sys/socket.h> | |
39 | #include <sys/un.h> | |
40 | #include "xtend.h" | |
41 | #include "xten.h" | |
42 | #include "paths.h" | |
43 | ||
44 | #define RETRIES 10 | |
45 | #define CMDLEN 512 | |
46 | ||
47 | char *X10housenames[] = { | |
48 | "A", "B", "C", "D", "E", "F", "G", "H", | |
49 | "I", "J", "K", "L", "M", "N", "O", "P", | |
50 | NULL | |
51 | }; | |
52 | ||
53 | char *X10cmdnames[] = { | |
54 | "1", "2", "3", "4", "5", "6", "7", "8", | |
55 | "9", "10", "11", "12", "13", "14", "15", "16", | |
56 | "AllUnitsOff", "AllLightsOn", "On", "Off", "Dim", "Bright", "AllLightsOff", | |
57 | "ExtendedCode", "HailRequest", "HailAcknowledge", "PreSetDim0", "PreSetDim1", | |
58 | "ExtendedData", "StatusOn", "StatusOff", "StatusRequest", | |
59 | NULL | |
60 | }; | |
61 | ||
62 | main(argc, argv) | |
63 | int argc; | |
64 | char *argv[]; | |
65 | { | |
66 | int c, tmp, h, k, sock, error; | |
67 | FILE *daemon; | |
68 | struct sockaddr_un sa; | |
69 | char *sockpath = SOCKPATH; | |
70 | char reply[CMDLEN], cmd[CMDLEN], *cp; | |
71 | int interactive = 0; | |
72 | ||
73 | if(argc == 2 && !strcmp(argv[1], "-")) interactive++; | |
74 | else if(argc < 3) { | |
75 | fprintf(stderr, "Usage: %s house key[:cnt] [ [house] key[:cnt] ... ]\n", argv[0]); | |
76 | exit(1); | |
77 | } | |
78 | if((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { | |
79 | fprintf(stderr, "%s: Can't create socket\n", argv[0]); | |
80 | exit(1); | |
81 | } | |
82 | strcpy(sa.sun_path, sockpath); | |
83 | sa.sun_family = AF_UNIX; | |
84 | if(connect(sock, (struct sockaddr *)(&sa), strlen(sa.sun_path) + 2) < 0) { | |
85 | fprintf(stderr, "%s: Can't connect to X-10 daemon\n", argv[0]); | |
86 | exit(1); | |
87 | } | |
88 | if((daemon = fdopen(sock, "w+")) == NULL) { | |
89 | fprintf(stderr, "%s: Can't attach stream to socket\n", argv[0]); | |
90 | exit(1); | |
91 | } | |
92 | /* | |
93 | * If interactive, copy standard input to daemon and report results | |
94 | * on standard output. | |
95 | */ | |
96 | if(interactive) { | |
97 | while(!feof(stdin)) { | |
98 | if(fgets(cmd, CMDLEN, stdin) != NULL) { | |
99 | fprintf(daemon, "%s", cmd); | |
100 | fflush(daemon); | |
101 | if(fgets(reply, CMDLEN, daemon) != NULL) { | |
102 | fprintf(stdout, "%s", reply); | |
103 | fflush(stdout); | |
104 | } | |
105 | } | |
106 | } | |
107 | exit(0); | |
108 | } | |
109 | /* | |
110 | * Otherwise, interpret arguments and issue commands to daemon, | |
111 | * handling retries in case of errors. | |
112 | */ | |
113 | if((h = find(argv[1], X10housenames)) < 0) { | |
114 | fprintf(stderr, "Invalid house code: %s\n", argv[1]); | |
115 | exit(1); | |
116 | } | |
117 | argv++; | |
118 | argv++; | |
119 | while(argc >= 3) { | |
120 | cp = argv[0]; | |
121 | if((tmp = find(cp, X10housenames)) >= 0) { | |
122 | h = tmp; | |
123 | argv++; | |
124 | argc--; | |
125 | continue; | |
126 | } | |
127 | while(*cp != '\0' && *cp != ':') cp++; | |
128 | if(*cp == ':') c = atoi(cp+1); | |
129 | else c = 2; | |
130 | *cp = '\0'; | |
131 | if((k = find(argv[0], X10cmdnames)) < 0) { | |
132 | fprintf(stderr, "Invalid key/unit code: %s\n", argv[0]); | |
133 | error++; | |
134 | } | |
135 | error = 0; | |
136 | while(error < RETRIES) { | |
137 | fprintf(daemon, "send %s %s %d\n", X10housenames[h], X10cmdnames[k], c); | |
138 | fflush(daemon); | |
139 | fgets(reply, CMDLEN, daemon); | |
140 | if(strncmp(reply, "ERROR", 5)) break; | |
141 | error++; | |
142 | usleep(200000); | |
143 | } | |
144 | if(error == RETRIES) { | |
145 | fprintf(stderr, "Command failed: send %s %s %d\n", | |
146 | X10housenames[h], X10cmdnames[k], c); | |
147 | } | |
148 | argc--; | |
149 | argv++; | |
150 | } | |
151 | exit(0); | |
152 | } | |
153 | ||
154 | find(s, tab) | |
155 | char *s; | |
156 | char *tab[]; | |
157 | { | |
158 | int i; | |
159 | ||
160 | for(i = 0; tab[i] != NULL; i++) { | |
161 | if(strcmp(s, tab[i]) == 0) return(i); | |
162 | } | |
163 | return(-1); | |
164 | } |