/* prepare for new client arriving on lsocket. * exit if trouble. */ static void newClient() { ClInfo *cp = NULL; int s, cli; /* assign new socket */ s = newClSocket (); /* try to reuse a clinfo slot, else add one */ for (cli = 0; cli < nclinfo; cli++) if (!(cp = &clinfo[cli])->active) break; if (cli == nclinfo) { /* grow clinfo, lock while moving */ pthread_mutex_lock (&client_m); clinfo = (ClInfo *) myrealloc (clinfo, (nclinfo+1)*sizeof(ClInfo)); if (!clinfo) { fprintf (stderr, "%s: no memory for new client\n", me); exit(1); } cp = &clinfo[nclinfo++]; pthread_mutex_unlock (&client_m); } /* rig up new clinfo entry */ memset (cp, 0, sizeof(*cp)); cp->active = 1; cp->s = s; cp->lp = newLilXML(); cp->msgq = newFQ(1); cp->devs = mymalloc (1); /* N.B. beware implied use of malloc */ pthread_mutex_lock (&malloc_m); cp->wfp = fdopen (cp->s, "a"); setbuf (cp->wfp, NULL); pthread_mutex_unlock (&malloc_m); if (verbose > 0) fprintf (stderr, "Client %d: new arrival - welcome!\n", cp->s); /* start the writer thread */ s = pthread_create (&cp->wtid, NULL, clientWThread, (void*)(cp-clinfo)); if (s) { fprintf (stderr, "Thread create error: %s\n", strerror(s)); exit (1); } }
/* start the INDI driver process using the given DvrInfo slot. * exit if trouble. */ static void startDvr (DvrInfo *dp) { int rp[2], wp[2]; int pid; /* build two pipes for r and w */ if (pipe (rp) < 0) { fprintf (stderr, "%s: read pipe: %s\n", me, strerror(errno)); exit(1); } if (pipe (wp) < 0) { fprintf (stderr, "%s: write pipe: %s\n", me, strerror(errno)); exit(1); } /* fork&exec new process */ pid = fork(); if (pid < 0) { fprintf (stderr, "%s: fork: %s\n", me, strerror(errno)); exit(1); } if (pid == 0) { /* child: exec name */ int fd; /* rig up pipes as stdin/out; stderr stays, everything else goes */ dup2 (wp[0], 0); dup2 (rp[1], 1); for (fd = 3; fd < 100; fd++) (void) close (fd); /* go -- should never return */ execlp (dp->name, dp->name, NULL); fprintf (stderr, "Driver %s: %s\n", dp->name, strerror(errno)); _exit (1); /* parent will notice EOF shortly */ } /* don't need child's side of pipes */ close (rp[1]); close (wp[0]); /* record pid, io channel, init lp */ dp->pid = pid; dp->rfd = rp[0]; dp->lp = newLilXML(); /* N.B. beware implied use of malloc */ pthread_mutex_lock (&malloc_m); dp->wfp = fdopen (wp[1], "a"); setbuf (dp->wfp, NULL); pthread_mutex_unlock (&malloc_m); if (verbose > 0) fprintf (stderr, "Driver %s: rfd=%d wfd=%d\n", dp->name, dp->rfd, wp[1]); }
/* start the given remote INDI driver connection. * exit if trouble. */ void startRemoteDvr (DvrInfo *dp) { Msg *mp; char dev[1024]; char host[1024]; char buf[1024]; int indi_port, sockfd; /* extract host and port */ indi_port = INDIPORT; if (sscanf (dp->name, "%[^@]@%[^:]:%d", dev, host, &indi_port) < 2) { fprintf (stderr, "Bad remote device syntax: %s\n", dp->name); Bye(); } /* connect */ sockfd = openINDIServer (host, indi_port); /* record flag pid, io channels, init lp and snoop list */ dp->pid = REMOTEDVR; dp->rfd = sockfd; dp->wfd = sockfd; dp->lp = newLilXML(); dp->msgq = newFQ(1); dp->sprops = (Property*) malloc (1); /* seed for realloc */ dp->nsprops = 0; dp->nsent = 0; dp->active = 1; dp->ndev = 1; dp->dev = (char **) malloc(sizeof(char *)); /* N.B. storing name now is key to limiting outbound traffic to this * dev. */ dp->dev[0] = (char *) malloc(MAXINDIDEVICE * sizeof(char)); strncpy (dp->dev[0], dev, MAXINDIDEVICE-1); dp->dev[0][MAXINDIDEVICE-1] = '\0'; /* Sending getProperties with device lets remote server limit its * outbound (and our inbound) traffic on this socket to this device. */ mp = newMsg(); pushFQ (dp->msgq, mp); sprintf (buf, "<getProperties device='%s' version='%g'/>\n", dp->dev[0], INDIV); setMsgStr (mp, buf); mp->count++; if (verbose > 0) fprintf (stderr, "%s: Driver %s: socket=%d\n", indi_tstamp(NULL), dp->name, sockfd); }
/* prepare for new client arriving on lsocket. * exit if trouble. */ void newClient() { ClInfo *cp = NULL; int s, cli; /* assign new socket */ s = newClSocket (); /* try to reuse a clinfo slot, else add one */ for (cli = 0; cli < nclinfo; cli++) if (!(cp = &clinfo[cli])->active) break; if (cli == nclinfo) { /* grow clinfo */ clinfo = (ClInfo *) realloc (clinfo, (nclinfo+1)*sizeof(ClInfo)); if (!clinfo) { fprintf (stderr, "no memory for new client\n"); Bye(); } cp = &clinfo[nclinfo++]; } /* rig up new clinfo entry */ memset (cp, 0, sizeof(*cp)); cp->active = 1; cp->s = s; cp->lp = newLilXML(); cp->msgq = newFQ(1); cp->props = malloc (1); cp->nsent = 0; if (verbose > 0) { struct sockaddr_in addr; socklen_t len = sizeof(addr); getpeername(s, (struct sockaddr*)&addr, &len); fprintf(stderr,"%s: Client %d: new arrival from %s:%d - welcome!\n", indi_tstamp(NULL), cp->s, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); } #ifdef OSX_EMBEDED_MODE int active = 0; for (int i = 0; i < nclinfo; i++) if (clinfo[i].active) active++; fprintf(stderr, "CLIENTS %d\n", active); fflush(stderr); #endif }
bool INDI::BaseClientQt::connectServer() { client_socket.connectToHost(cServer.c_str(), cPort); if (client_socket.waitForConnected(timeout_sec*1000) == false) { sConnected = false; return false; } clear(); lillp = newLilXML(); sConnected = true; serverConnected(); char * orig = setlocale(LC_NUMERIC,"C"); QString getProp; if (cDeviceNames.empty()) { getProp = QString("<getProperties version='%1'/>\n").arg(QString::number(INDIV)); client_socket.write(getProp.toLatin1()); if (verbose) std::cerr << getProp.toLatin1().constData() << std::endl; } else { vector<string>::const_iterator stri; for ( stri = cDeviceNames.begin(); stri != cDeviceNames.end(); stri++) { getProp = QString("<getProperties version='%1' device='%2'/>\n").arg(QString::number(INDIV)).arg( (*stri).c_str()); client_socket.write(getProp.toLatin1()); if (verbose) std::cerr << getProp.toLatin1().constData() << std::endl; } } setlocale(LC_NUMERIC,orig); return true; }
/* start the given local INDI driver process. * exit if trouble. */ void startLocalDvr (DvrInfo *dp) { Msg *mp; char buf[32]; int rp[2], wp[2], ep[2]; int pid; #ifdef OSX_EMBEDED_MODE fprintf(stderr, "STARTING \"%s\"\n", dp->name); fflush(stderr); #endif /* build three pipes: r, w and error*/ if (pipe (rp) < 0) { fprintf (stderr, "%s: read pipe: %s\n", indi_tstamp(NULL), strerror(errno)); Bye(); } if (pipe (wp) < 0) { fprintf (stderr, "%s: write pipe: %s\n", indi_tstamp(NULL), strerror(errno)); Bye(); } if (pipe (ep) < 0) { fprintf (stderr, "%s: stderr pipe: %s\n", indi_tstamp(NULL), strerror(errno)); Bye(); } /* fork&exec new process */ pid = fork(); if (pid < 0) { fprintf (stderr, "%s: fork: %s\n", indi_tstamp(NULL), strerror(errno)); Bye(); } if (pid == 0) { /* child: exec name */ int fd; /* rig up pipes */ dup2 (wp[0], 0); /* driver stdin reads from wp[0] */ dup2 (rp[1], 1); /* driver stdout writes to rp[1] */ dup2 (ep[1], 2); /* driver stderr writes to e[]1] */ for (fd = 3; fd < 100; fd++) (void) close (fd); if (*dp->envDev) setenv("INDIDEV", dp->envDev, 1); /* Only reset environment variable in case of FIFO */ else if (fifo.fd > 0) unsetenv("INDIDEV"); if (*dp->envConfig) setenv("INDICONFIG", dp->envConfig, 1); else if (fifo.fd > 0) unsetenv("INDICONFIG"); if (*dp->envSkel) setenv("INDISKEL", dp->envSkel, 1); else if (fifo.fd > 0) unsetenv("INDISKEL"); char executable[MAXSBUF]; if (*dp->envPrefix) { setenv("INDIPREFIX", dp->envPrefix, 1); #ifdef OSX_EMBEDED_MODE snprintf(executable, MAXSBUF, "%s/Contents/MacOS/%s", dp->envPrefix, dp->name); #else snprintf(executable, MAXSBUF, "%s/bin/%s", dp->envPrefix, dp->name); #endif fprintf(stderr, "%s\n", executable); execlp (executable, dp->name, NULL); } else { if (fifo.fd > 0) unsetenv("INDIPREFIX"); execlp (dp->name, dp->name, NULL); } #ifdef OSX_EMBEDED_MODE fprintf(stderr, "FAILED \"%s\"\n", dp->name); fflush(stderr); #endif fprintf (stderr, "%s: Driver %s: execlp: %s\n", indi_tstamp(NULL), dp->name, strerror(errno)); _exit (1); /* parent will notice EOF shortly */ } /* don't need child's side of pipes */ close (wp[0]); close (rp[1]); close (ep[1]); /* record pid, io channels, init lp and snoop list */ dp->pid = pid; dp->rfd = rp[0]; dp->wfd = wp[1]; dp->efd = ep[0]; dp->lp = newLilXML(); dp->msgq = newFQ(1); dp->sprops = (Property*) malloc (1); /* seed for realloc */ dp->nsprops = 0; dp->nsent = 0; dp->active = 1; dp->ndev = 0; dp->dev = (char **) malloc(sizeof(char *)); /* first message primes driver to report its properties -- dev known * if restarting */ mp = newMsg(); pushFQ (dp->msgq, mp); sprintf (buf, "<getProperties version='%g'/>\n", INDIV); setMsgStr (mp, buf); mp->count++; if (verbose > 0) fprintf (stderr, "%s: Driver %s: pid=%d rfd=%d wfd=%d efd=%d\n", indi_tstamp(NULL), dp->name, dp->pid, dp->rfd, dp->wfd, dp->efd); }
int main (int ac, char *av[]) { FILE *fp; /* save our name for usage() */ me = av[0]; /* crack args */ while (--ac && **++av == '-') { char *s = *av; while (*++s) { switch (*s) { case 'b': /* beep when true */ bflag++; break; case 'd': if (ac < 2) { fprintf (stderr, "-d requires open fileno\n"); usage(); } directfd = atoi(*++av); ac--; break; case 'e': /* print each updated expression value */ eflag++; break; case 'f': /* print final expression value */ fflag++; break; case 'h': if (directfd >= 0) { fprintf (stderr, "Can not combine -d and -h\n"); usage(); } if (ac < 2) { fprintf (stderr, "-h requires host name\n"); usage(); } host = *++av; ac--; break; case 'i': /* read expression from stdin */ iflag++; break; case 'o': /* print operands as they change */ oflag++; break; case 'p': if (directfd >= 0) { fprintf (stderr, "Can not combine -d and -p\n"); usage(); } if (ac < 2) { fprintf (stderr, "-p requires tcp port number\n"); usage(); } port = atoi(*++av); ac--; break; case 't': if (ac < 2) { fprintf (stderr, "-t requires timeout\n"); usage(); } timeout = atoi(*++av); ac--; break; case 'v': /* verbose */ verbose++; break; case 'w': /* wait for expression to be true */ wflag++; break; default: fprintf (stderr, "Unknown flag: %c\n", *s); usage(); } } } /* now there are ac args starting with av[0] */ /* compile expression from av[0] or stdin */ if (ac == 0) compile (NULL); else if (ac == 1) compile (av[0]); else usage(); /* open connection */ if (directfd >= 0) { fp = fdopen (directfd, "r+"); setbuf (fp, NULL); /* don't absorb next guy's stuff */ if (!fp) { fprintf (stderr, "Direct fd %d: %s\n",directfd,strerror(errno)); exit(1); } if (verbose) fprintf (stderr, "Using direct fd %d\n", directfd); } else { fp = openINDIServer(); if (verbose) fprintf (stderr, "Connected to %s on port %d\n", host, port); } /* build a parser context for cracking XML responses */ lillp = newLilXML(); /* set up to catch an io timeout function */ signal (SIGALRM, onAlarm); /* send getProperties */ getProps(fp); /* initialize all properties */ initProps(fp); /* evaluate expression, return depending on flags */ return (runEval(fp)); }