23 #include <netinet/in.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
36 {
"defTextVector",
"defText" }, {
"defNumberVector",
"defNumber" }, {
"defSwitchVector",
"defSwitch" },
37 {
"defLightVector",
"defLight" }, {
"defBLOBVector",
"defBLOB" }, {
"setBLOBVector",
"oneBLOB" },
38 {
"setTextVector",
"oneText" }, {
"setNumberVector",
"oneNumber" }, {
"setSwitchVector",
"oneSwitch" },
39 {
"setLightVector",
"oneLight" },
50 {
"_LABEL",
"label" }, {
"_GROUP",
"group" }, {
"_STATE",
"state" },
51 {
"_PERM",
"perm" }, {
"_TO",
"timeout" }, {
"_TS",
"timestamp" },
53 #define NKWA (sizeof(kwattr) / sizeof(kwattr[0]))
66 static void usage(
void);
67 static void crackDPE(
char *spec);
68 static void addSearchDef(
char *dev,
char *prop,
char *ele);
69 static void openINDIServer(
void);
70 static void getprops(
void);
71 static void listenINDI(
void);
72 static int finished(
void);
73 static void onAlarm(
int dummy);
74 static int readServerChar(
void);
75 static void findDPE(
XMLEle *root);
76 static void findEle(
XMLEle *root,
char *dev,
char *nam,
char *defone,
SearchDef *sp);
77 static void enableBLOBs(
char *dev,
char *nam);
78 static void oneBLOB(
XMLEle *root,
char *dev,
char *nam,
char *enam,
char *p,
int plen);
81 static char host_def[] =
"localhost";
82 static char *host = host_def;
93 static int directfd = -1;
98 int main(
int ac,
char *av[])
104 while (--ac && **++av ==
'-')
117 fprintf(stderr,
"-d requires open fileno\n");
120 directfd = atoi(*++av);
126 fprintf(stderr,
"Can not combine -d and -h\n");
131 fprintf(stderr,
"-h requires host name\n");
144 fprintf(stderr,
"Can not combine -d and -p\n");
149 fprintf(stderr,
"-p requires tcp port number\n");
158 fprintf(stderr,
"-t requires timeout\n");
161 timeout = atoi(*++av);
171 fprintf(stderr,
"Unknown flag: %c\n", *s);
184 onematch = nsrchs == 1 && !srchs[0].
wc;
189 svrwfp = fdopen(directfd,
"w");
190 svrrfp = fdopen(directfd,
"r");
191 if (!svrwfp || !svrrfp)
193 fprintf(stderr,
"Direct fd %d: %s\n", directfd, strerror(
errno));
196 setbuf(svrrfp, NULL);
198 fprintf(stderr,
"Using direct fd %d\n", directfd);
204 fprintf(stderr,
"Connected to %s on port %d\n", host, port);
221 fprintf(stderr,
"Purpose: retrieve readable properties from an INDI server\n");
222 fprintf(stderr,
"%s\n", GIT_TAG_STRING);
223 fprintf(stderr,
"Usage: %s [options] [device.property.element ...]\n", me);
224 fprintf(stderr,
" Any component may be \"*\" to match all (beware shell metacharacters).\n");
225 fprintf(stderr,
" Reports all properties if none specified.\n");
226 fprintf(stderr,
" BLOBs are saved in file named device.property.element.format\n");
227 fprintf(stderr,
" In perl try: %s\n",
"%props = split (/[=\\n]/, `getINDI`);");
228 fprintf(stderr,
" Set element to one of following to return property attribute:\n");
229 for (
int i = 0; i < (int)
NKWA; i++)
230 fprintf(stderr,
" %10s to report %s\n", kwattr[i].keyword, kwattr[i].indiattr);
231 fprintf(stderr,
"Output format: output is fully qualified name=value one per line\n");
232 fprintf(stderr,
" or just value if -1 and exactly one query without wildcards.\n");
233 fprintf(stderr,
"Options:\n");
234 fprintf(stderr,
" -1 : print just value if expecting exactly one response\n");
235 fprintf(stderr,
" -d f : use file descriptor f already open to server\n");
236 fprintf(stderr,
" -h h : alternate host, default is %s\n", host_def);
237 fprintf(stderr,
" -m : keep monitoring for more updates\n");
238 fprintf(stderr,
" -p p : alternate port, default is %d\n",
INDIPORT);
239 fprintf(stderr,
" -t t : max time to wait, default is %d secs\n",
TIMEOUT);
240 fprintf(stderr,
" -v : verbose (cumulative)\n");
241 fprintf(stderr,
" -w : show write-only properties too\n");
242 fprintf(stderr,
"Exit status:\n");
243 fprintf(stderr,
" 0: found at least one match for each query\n");
244 fprintf(stderr,
" 1: at least one query returned nothing\n");
245 fprintf(stderr,
" 2: real trouble, try repeating with -v\n");
251 static void crackDPE(
char *spec)
253 char d[1024], p[1024], e[1024];
256 fprintf(stderr,
"looking for %s\n", spec);
257 if (sscanf(spec,
"%[^.].%[^.].%[^.]", d, p, e) != 3)
259 fprintf(stderr,
"Unknown format for property spec: %s\n", spec);
263 addSearchDef(d, p, e);
267 static void addSearchDef(
char *dev,
char *prop,
char *ele)
270 srchs[nsrchs].
d = strdup(dev);
271 srchs[nsrchs].
p = strdup(prop);
272 srchs[nsrchs].
e = strdup(ele);
274 srchs[nsrchs].
ok = 0;
281 static void openINDIServer(
void)
283 struct sockaddr_in serv_addr;
288 hp = gethostbyname(host);
291 herror(
"gethostbyname");
296 (void)memset((
char *)&serv_addr, 0,
sizeof(serv_addr));
297 serv_addr.sin_family = AF_INET;
298 serv_addr.sin_addr.s_addr = ((
struct in_addr *)(hp->h_addr_list[0]))->s_addr;
299 serv_addr.sin_port = htons(port);
300 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
307 if (connect(sockfd, (
struct sockaddr *)&serv_addr,
sizeof(serv_addr)) < 0)
314 svrwfp = fdopen(sockfd,
"w");
315 svrrfp = fdopen(sockfd,
"r");
319 static void getprops()
325 for (i = 0; i < nsrchs; i++)
327 char *d = srchs[i].
d;
328 if (*d ==
WILDCARD || (onedev && strcmp(d, onedev)))
338 fprintf(svrwfp,
"<getProperties version='%g' device='%s'/>\n",
INDIV, onedev);
340 fprintf(svrwfp,
"<getProperties version='%g'/>\n",
INDIV);
344 fprintf(stderr,
"Queried properties from %s\n", onedev ? onedev :
"*");
351 static void listenINDI()
356 signal(SIGALRM, onAlarm);
375 fprintf(stderr,
"Bad XML from %s/%d: %s\n", host, port, msg);
382 static int finished()
389 for (i = 0; i < nsrchs; i++)
390 if (srchs[i].wc || !srchs[i].ok)
398 static void onAlarm(
int dummy)
403 for (
int i = 0; i < nsrchs; i++)
408 fprintf(stderr,
"No %s.%s.%s from %s:%d\n", srchs[i].d, srchs[i].p, srchs[i].e, host, port);
412 exit(trouble ? 1 : 0);
416 static int readServerChar()
418 int c = fgetc(svrrfp);
425 fprintf(stderr,
"INDI server %s/%d disconnected\n", host, port);
430 fprintf(stderr,
"Read %c\n", c);
436 static void findDPE(
XMLEle *root)
440 for (i = 0; i < nsrchs; i++)
443 for (j = 0; j < ndefs; j++)
446 if (strcmp(
tagXMLEle(root), defs[j].vec) == 0)
450 char *idev = srchs[i].
d;
451 if (idev[0] ==
WILDCARD || !strcmp(dev, idev))
455 char *iprop = srchs[i].
p;
456 if (iprop[0] ==
WILDCARD || !strcmp(nam, iprop))
460 if (!wflag && perm[0] && !strchr(perm,
'r'))
463 fprintf(stderr,
"%s.%s is write-only\n", dev, nam);
468 if (!strcmp(defs[j].vec,
"defBLOBVector"))
469 enableBLOBs(dev, nam);
471 findEle(root, dev, nam, defs[j].one, &srchs[i]);
474 if (!strncmp(defs[j].vec,
"def", 3))
487 static void findEle(
XMLEle *root,
char *dev,
char *nam,
char *defone,
SearchDef *sp)
493 for (
int i = 0; i < (int)
NKWA; i++)
495 if (strcmp(iele, kwattr[i].keyword) == 0)
500 if (onematch && justvalue)
503 printf(
"%s.%s.%s=%s\n", dev, nam, kwattr[i].keyword, s);
515 if (iele[0] ==
WILDCARD || !strcmp(enam, iele))
520 if (!strcmp(defone,
"oneBLOB"))
522 else if (onematch && justvalue)
525 printf(
"%s.%s.%s=%s\n", dev, nam, enam, p);
535 static void enableBLOBs(
char *dev,
char *nam)
538 fprintf(stderr,
"sending enableBLOB %s.%s\n", dev, nam);
539 fprintf(svrwfp,
"<enableBLOB device='%s' name='%s'>Also</enableBLOB>\n", dev, nam);
545 static void oneBLOB(
XMLEle *root,
char *dev,
char *nam,
char *enam,
char *p,
int plen)
559 fprintf(stderr,
"%s.%s.%s reports uncompressed size as %d\n", dev, nam, enam, ucs);
563 isz = !strncmp(&format[strlen(format) - 2],
".z", 2);
566 blob = (
unsigned char *)malloc(3 * plen / 4);
570 fprintf(stderr,
"%s.%s.%s bad base64\n", dev, nam, enam);
578 unsigned char *uncomp = (
unsigned char *)malloc(ucs);
579 int ok = uncompress(uncomp, &nuncomp, blob, bloblen);
582 fprintf(stderr,
"%s.%s.%s uncompress error %d\n", dev, nam, enam, ok);
591 i = sprintf(fn,
"%s.%s.%s%s", dev, nam, enam, format);
600 fprintf(stderr,
"Wrote %s\n", fn);
601 fwrite(blob, bloblen, 1, fp);
606 fprintf(stderr,
"%s: %s\n", fn, strerror(
errno));
int from64tobits_fast(char *out, const char *in, int inlen)
int main(int ac, char *av[])
Constants and Data structure definitions for the interface to the reference INDI C API implementation...
LilXML * newLilXML()
Create a new lilxml parser.
const char * findXMLAttValu(XMLEle *ep, const char *name)
Find an XML element's attribute value.
char * pcdataXMLEle(XMLEle *ep)
Return the pcdata of an XML element.
char * tagXMLEle(XMLEle *ep)
Return the tag of an XML element.
void prXMLEle(FILE *fp, XMLEle *ep, int level)
Print an XML element.
XMLEle * readXMLEle(LilXML *lp, int newc, char ynot[])
Process an XML one char at a time.
XMLEle * nextXMLEle(XMLEle *ep, int init)
Iterate an XML element for a list of nesetd XML elements.
void delXMLEle(XMLEle *ep)
delXMLEle Delete XML element.
int pcdatalenXMLEle(XMLEle *ep)
Return the number of characters in pcdata in an XML element.
A little DOM-style library to handle parsing and processing an XML file.