46 |
46 |
47 typedef struct DPokeSource_st DPokeSource; |
47 typedef struct DPokeSource_st DPokeSource; |
48 |
48 |
49 #define LENGTH(X) (sizeof X / sizeof X[0]) |
49 #define LENGTH(X) (sizeof X / sizeof X[0]) |
50 |
50 |
51 char* smprintf(char *fmt, ...) { |
51 char * |
52 va_list fmtargs; |
52 smprintf(char *fmt, ...) |
53 char *ret; |
53 { |
54 int len; |
54 va_list fmtargs; |
55 |
55 char *ret; |
56 va_start(fmtargs, fmt); |
56 int len; |
57 len = vsnprintf(NULL, 0, fmt, fmtargs); |
57 |
58 va_end(fmtargs); |
58 va_start(fmtargs, fmt); |
59 |
59 len = vsnprintf(NULL, 0, fmt, fmtargs); |
60 ret = malloc(++len); |
60 va_end(fmtargs); |
61 if (ret == NULL) { |
61 |
62 perror("malloc"); |
62 ret = malloc(++len); |
63 exit(1); |
63 if (ret == NULL) { |
64 } |
64 perror("malloc"); |
65 |
65 exit(1); |
66 va_start(fmtargs, fmt); |
66 } |
67 vsnprintf(ret, len, fmt, fmtargs); |
67 |
68 va_end(fmtargs); |
68 va_start(fmtargs, fmt); |
69 |
69 vsnprintf(ret, len, fmt, fmtargs); |
70 return ret; |
70 va_end(fmtargs); |
71 } |
71 |
72 |
72 return ret; |
73 |
73 } |
74 void display(); |
74 |
|
75 void display(char *v[], size_t vc); |
|
76 void setup(void); |
|
77 void cleanup(int exitcode); |
75 |
78 |
76 extern char* v[]; |
79 extern char* v[]; |
77 #include "config.h" |
80 #include "config.h" |
78 #ifdef DEBUG |
81 #ifdef DEBUG |
79 #define errprintf(...) fprintf(stderr,...) |
82 #define errprintf(...) fprintf(stderr,__VA_ARGS__) |
80 #else |
83 #else |
81 #define errprintf(...) |
84 #define errprintf(...) |
82 #endif |
85 #endif |
83 |
86 |
84 char* v[LENGTH(sources)]; |
87 char* v[LENGTH(sources)]; |
85 |
88 |
86 static struct pollfd source_fds[LENGTH(sources)]; |
89 static struct pollfd source_fds[LENGTH(sources)]; |
|
90 |
|
91 void die(int exitcode) { |
|
92 fprintf(stderr, "Dying with exit code %d\n", exitcode); |
|
93 cleanup(exitcode); |
|
94 exit(exitcode); |
|
95 } |
87 |
96 |
88 void source_open(int source_id) { |
97 void source_open(int source_id) { |
89 DPokeSource *src = &sources[source_id]; |
98 DPokeSource *src = &sources[source_id]; |
90 //FILE* stream; |
99 //FILE* stream; |
91 int p_stdout[2]; |
100 int p_stdout[2]; |
92 switch (src->type) { |
101 switch (src->type) { |
93 case DPOKE_PROGRAM: |
102 case DPOKE_PROGRAM: |
94 //stream = popen(src->path, "r"); |
103 //stream = popen(src->path, "r"); |
95 if (pipe(p_stdout)!=0) { |
104 if (pipe(p_stdout)!=0) { |
96 perror("pipe"); |
105 perror("pipe"); |
97 exit(7); |
106 die(7); |
98 } |
107 } |
99 pid_t pid = fork(); |
108 pid_t pid = fork(); |
100 if (pid < 0) { |
109 if (pid < 0) { |
101 perror("fork"); |
110 perror("fork"); |
102 exit(7); |
111 die(7); |
103 } else if (pid == 0) { |
112 } else if (pid == 0) { |
104 dup2(open("/dev/null",O_RDONLY),0); |
113 dup2(open("/dev/null",O_RDONLY),0); |
105 close(p_stdout[0]); |
114 close(p_stdout[0]); |
106 dup2(p_stdout[1],1); |
115 dup2(p_stdout[1],1); |
107 execl("/bin/sh", "sh", "-c", src->path, NULL); |
116 execl("/bin/sh", "sh", "-c", src->path, NULL); |
111 src->fd = p_stdout[0]; |
120 src->fd = p_stdout[0]; |
112 src->pid = pid; |
121 src->pid = pid; |
113 break; |
122 break; |
114 default: |
123 default: |
115 errprintf("Don't know how to handle source type %d.\n",src->type); |
124 errprintf("Don't know how to handle source type %d.\n",src->type); |
116 exit(2); |
125 die(2); |
117 } |
126 } |
118 //src->stream = stream; |
127 //src->stream = stream; |
119 //src->fd = fileno(stream); |
128 //src->fd = fileno(stream); |
120 src->buffer_usage = 0; |
129 src->buffer_usage = 0; |
121 src->status = DPOKE_STARTED; |
130 src->status = DPOKE_STARTED; |
153 |
162 |
154 double dpoke_time() { |
163 double dpoke_time() { |
155 struct timespec tp; |
164 struct timespec tp; |
156 if (clock_gettime(CLOCK_MONOTONIC,&tp)) { |
165 if (clock_gettime(CLOCK_MONOTONIC,&tp)) { |
157 perror("clock_gettime"); |
166 perror("clock_gettime"); |
158 exit(5); |
167 die(5); |
159 } |
168 } |
160 return tp.tv_sec + tp.tv_nsec*1E-9; |
169 return tp.tv_sec + tp.tv_nsec*1E-9; |
161 } |
170 } |
162 |
171 |
163 int main(int argc, char* argv[]) { |
172 int main(int argc, char* argv[]) { |
|
173 setup(); |
164 struct sigaction act; |
174 struct sigaction act; |
165 |
175 |
166 memset (&act, 0, sizeof(act)); |
176 memset (&act, 0, sizeof(act)); |
167 act.sa_handler = sigchld_hdl; |
177 act.sa_handler = sigchld_hdl; |
168 if (sigaction(SIGCHLD, &act, 0)) { |
178 if (sigaction(SIGCHLD, &act, 0)) { |
169 perror ("sigaction"); |
179 perror ("sigaction"); |
170 exit(6); |
180 die(6); |
171 } |
181 } |
172 |
182 |
173 for (int i = 0; i < LENGTH(sources); i++ ) { |
183 for (int i = 0; i < LENGTH(sources); i++ ) { |
174 source_open(i); |
184 source_open(i); |
175 v[i] = sources[i].current; |
185 v[i] = sources[i].current; |
184 continue; |
194 continue; |
185 } |
195 } |
186 for (int i = 0; i < LENGTH(sources); i++) { |
196 for (int i = 0; i < LENGTH(sources); i++) { |
187 DPokeSource *src = sources+i; |
197 DPokeSource *src = sources+i; |
188 if (source_fds[i].revents & POLLIN) { |
198 if (source_fds[i].revents & POLLIN) { |
|
199 errprintf("Event: %d\n", source_fds[i].revents); |
189 int data_read = read(src->fd,src->buffer+src->buffer_usage,DPOKE_BUFFER-src->buffer_usage); |
200 int data_read = read(src->fd,src->buffer+src->buffer_usage,DPOKE_BUFFER-src->buffer_usage); |
190 if (data_read>0) { |
201 if (data_read>0) { |
191 src->buffer_usage += data_read; |
202 src->buffer_usage += data_read; |
192 if (src->buffer_usage==DPOKE_BUFFER) { |
203 if (src->buffer_usage>=DPOKE_BUFFER) { |
193 errprintf("Buffer is full for #%d.\n",i); |
204 fprintf(stderr, "Buffer is full for #%d. Resetting.\n",i); |
|
205 src->buffer_usage = 0; |
194 } |
206 } |
195 src->buffer[src->buffer_usage] = '\0'; |
207 src->buffer[src->buffer_usage] = '\0'; |
196 char* eolpos = strchr(src->buffer + src->buffer_usage - data_read,'\n'); |
208 char* eolpos = strchr(src->buffer + src->buffer_usage - data_read,'\n'); |
197 if (eolpos) { |
209 if (eolpos) { |
198 memcpy(src->current,src->buffer,eolpos-src->buffer); |
210 memcpy(src->current,src->buffer,eolpos-src->buffer); |
201 memmove(src->buffer,eolpos + 1,src->buffer_usage + 1); |
213 memmove(src->buffer,eolpos + 1,src->buffer_usage + 1); |
202 } |
214 } |
203 if (src->status == DPOKE_STARTED) |
215 if (src->status == DPOKE_STARTED) |
204 src->status = DPOKE_RUNNING; |
216 src->status = DPOKE_RUNNING; |
205 } else { |
217 } else { |
|
218 fprintf(stderr, "Buffer usage: %d\n", src->buffer_usage); |
206 perror("read"); |
219 perror("read"); |
207 exit(3); |
220 die(3); |
208 } |
221 } |
209 } else if ((source_fds[i].revents & POLLHUP)||(src->status==DPOKE_DIED)) { |
222 } else if ((source_fds[i].revents & POLLHUP)||(src->status==DPOKE_DIED)) { |
210 errprintf("#%d HUP\n",i); |
223 errprintf("#%d HUP\n",i); |
211 source_close(i); |
224 source_close(i); |
212 if (src->status==DPOKE_STARTED) |
225 if (src->status==DPOKE_STARTED) |
222 strcpy(src->current,FAILURE_MSG); |
235 strcpy(src->current,FAILURE_MSG); |
223 } |
236 } |
224 } |
237 } |
225 double curtime = dpoke_time(); |
238 double curtime = dpoke_time(); |
226 if ((curtime-prevtime)>MINTIME) { |
239 if ((curtime-prevtime)>MINTIME) { |
227 display(); |
240 display(v,LENGTH(sources)); |
228 prevtime = curtime; |
241 prevtime = curtime; |
229 sleeptime = 10000; |
242 sleeptime = 10000; |
230 } else { |
243 } else { |
231 double sleepd = (prevtime+MINTIME - curtime)*1000; |
244 double sleepd = (prevtime+MINTIME - curtime)*1000; |
232 sleeptime = ceil(sleepd); |
245 sleeptime = ceil(sleepd); |
233 errprintf("%f %f %f %f\n",prevtime,curtime,MINTIME,sleepd); |
246 errprintf("%f %f %f %f\n",prevtime,curtime,MINTIME,sleepd); |
234 } |
247 } |
235 errprintf("Will sleep for %d\n",sleeptime); |
248 errprintf("Will sleep for %d\n",sleeptime); |
236 } |
249 } |
|
250 cleanup(0); |
237 return 0; |
251 return 0; |
238 } |
252 } |
239 /* |
253 /* |
240 ABCnDEF0 |
254 ABCnDEF0 |
241 01234567 |
255 01234567 |