3 * @brief Sensor run by an external process and sent to this one through a pipe
4 * PURELY INCLUDED FOR TESTING PURPOSES
5 * This will work with any sensor that can unbuffer stdout
6 * ... So, although it's not recommended, you could write a sensor purely in something like python
7 * The FastCGI process will handle all the time stamps and stuff
11 #include "../common.h"
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <sys/signal.h>
20 #include <float.h> // Defines DBL_MAX_10_EXP
31 static Piped g_piped[PIPED_MAX];
32 static int g_num_piped = 0;
34 bool Piped_Init(const char * name, int id)
36 if (++g_num_piped > PIPED_MAX)
38 Fatal("Too many sensors; Increase PIPED_MAX from %d in piped.h and recompile", PIPED_MAX);
41 if (socketpair(AF_UNIX, SOCK_STREAM, 0, g_piped[id].sv) != 0)
42 Fatal("socketpair failed - %s", strerror(errno));
44 g_piped[id].pid = fork();
45 if (g_piped[id].pid == 0)
47 dup2(g_piped[id].sv[0], fileno(stdin));
48 dup2(g_piped[id].sv[0], fileno(stdout));
50 if (access(name, X_OK) == 0) //Check we STILL have permissions to start the file
52 execl(name, name, (char*)(NULL)); ///Replace process with desired executable
53 //execv(executablePath,arguments); ///Replace process with desired executable
57 Fatal("Can't execute file %s", name);
59 Fatal("execl error - %s", strerror(errno));
63 g_piped[id].stream = fdopen(g_piped[id].sv[1], "r");
64 setbuf(g_piped[id].stream, NULL);
70 * This function looks evil, but I swear it's legit
71 * @param id - The Piped process to read from
72 * @param value - Stores the value read (if successful)
73 * @returns true on success, false on failure
75 bool Piped_Read(int id, double * value)
77 if (g_piped[id].stream == NULL)
80 // So need a buffer size big enough to fit all doubles but not too much bigger
81 static char buf[DBL_MAX_10_EXP+1];
83 // Using BUFSIZ is a bad idea, since we want to read near the end of the file
85 // Seek back from the end of the file
86 fseek(g_piped[id].stream, -DBL_MAX_10_EXP, SEEK_END);
87 int len = fread(buf, 1, DBL_MAX_10_EXP, g_piped[id].stream); // Fill the buffer, note the length count
90 for (i = len-1; i >= 0; --i) // Search for the last non-empty line in the buffer
103 // Now sscanf a double from the string
104 if (sscanf(buf+i, "%lf", value) != 1)
106 Log(LOGDEBUG, "Can't interpret %s as double", buf);
112 bool Piped_Cleanup(int id)
114 fclose(g_piped[id].stream);
115 if (kill(g_piped[id].pid, 15) != 0)
117 Log(LOGWARN, "Couldn't kill piped %d - %s", g_piped[id].pid, strerror(errno));