]> git.zerfleddert.de Git - rigol/blame - rigold.c
display some state-informations on the web
[rigol] / rigold.c
CommitLineData
ad9fbc05
MG
1#include <sys/types.h>
2#include <sys/socket.h>
3#include <arpa/inet.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <strings.h>
713be7a4 8#include <unistd.h>
7a226bb8 9#include <signal.h>
78fb0984 10#include <stdarg.h>
659f6954 11
713be7a4 12#include "scope.h"
ad9fbc05
MG
13#include "commands.h"
14
33b7545a
MG
15#define TIMEOUT 4
16
ad9fbc05
MG
17static int send_binary(int s, char *buf, int len)
18{
19 int ret;
20
21 while(len > 0) {
22 ret = write(s, buf, len);
23 if (ret == -1) {
24 perror("write");
25 return ret;
26 }
27 buf += ret;
28 len -= ret;
29 }
30
31 return 0;
32}
33
78fb0984 34static int send_text(int s, char *fmt, ...)
ad9fbc05 35{
78fb0984
MG
36 va_list argp;
37 char buf[4096];
38 int cnt;
39
40 va_start(argp, fmt);
41 cnt = vsnprintf(buf, sizeof(buf), fmt, argp);
42 va_end(argp);
43
44 if (cnt < 0)
45 return cnt;
46
47 return send_binary(s, buf, cnt);
48}
49
50static int send_command_output(int s, struct scope *sc, char *cmd)
51{
52 unsigned char buf[1024*1024];
53 int res;
54
55 res = sendscpi(sc, cmd, buf, sizeof(buf));
56 send_binary(s, (char*)buf, res);
57
58 return res;
ad9fbc05
MG
59}
60
04d383a4 61static void serve_index(int s, struct scope *sc, char *param)
ad9fbc05 62{
33b7545a 63 send_text(s, "HTTP/1.0 200 OK\n");
ad9fbc05 64 send_text(s, "Content-type: text/html\n\n");
78fb0984 65 send_text(s, "<html><head><title>%s</title></head><body bgcolor=\"#ffffff\" text=\"#000000\">\n", scope_idn(sc));
04d383a4 66 send_text(s, "<img src=\"/cgi-bin/lcd\" height=\"234\" width=\"320\">\n");
78fb0984
MG
67 send_text(s, "<br>\n");
68
69 claimscope(sc);
70 update_scope_status(sc);
71
72 send_text(s, "System: Language: %s, Counter: %d, Beep: %d<br>\n",
73 sc->status.system.lang,
74 sc->status.system.counter_enabled,
75 sc->status.system.beep_enabled);
76
77 send_text(s, "Keyboard: Key Lock: %d<br>\n",
78 sc->status.keyboard.key_lock);
79
80 send_text(s, "Acquire: Type: %s, Mode: %s, Averages: %d<br>\n",
81 sc->status.acquire.type,
82 sc->status.acquire.mode,
83 sc->status.acquire.averages);
84
85 send_text(s, "Horizontal: Mode: %s, Offset: %lg, Delayed Offset: %lg, Scale: %lg, Format: %s<br>\n",
86 sc->status.timebase.mode,
87 sc->status.timebase.offset,
88 sc->status.timebase.delayed_offset,
89 sc->status.timebase.scale,
90 sc->status.timebase.format);
91
92 send_text(s, "Display: ");
93 send_command_output(s, sc, ":DISP:TYPE?");
94 send_text(s, ", ");
95 send_command_output(s, sc, ":DISP:SCR?");
96 send_text(s, ", Grid: ");
97 send_command_output(s, sc, ":DISP:GRID?");
98 send_text(s, ", Persistence: ");
99 send_command_output(s, sc, ":DISP:PERS?");
100 send_text(s, ", Menu: ");
101 send_command_output(s, sc, ":DISP:MNUS?");
102 send_text(s, ", Brightness: ");
103 send_command_output(s, sc, ":DISP:BRIG?");
104 send_text(s, ", Intensity: ");
105 send_command_output(s, sc, ":DISP:INT?");
106 send_text(s, "<br>\n");
107
108 send_text(s, "Channel 1: ");
109 send_command_output(s, sc, ":CHAN1:DISP?");
110 send_text(s, ", ");
111 send_command_output(s, sc, ":CHAN1:MEMD?");
112 send_text(s, " sample depth, %.10lg samples/s<br>\n", sc->status.acquire.srate_chan1);
113 send_text(s, "Channel 2: ");
114 send_command_output(s, sc, ":CHAN2:DISP?");
115 send_text(s, ", ");
116 send_command_output(s, sc, ":CHAN2:MEMD?");
117 send_text(s, " sample depth, %.10lg samples/s<br>\n", sc->status.acquire.srate_chan2);
118
119 releasescope(sc);
120
121 send_text(s, sc->status.system.lang);
122
04d383a4
MG
123 send_text(s, "<br>\n");
124 send_text(s, "<form method=\"get\" action=\"\">\n");
125 send_text(s, "<input type=\"text\" name=\"cmd\" value=\"");
126 if (param) {
127 if (strncmp(param, "cmd=", 4) == 0)
128 param += 4;
129
130 send_text(s, param);
131 }
132 send_text(s, "\">\n");
133 send_text(s, "<input type=\"submit\">\n");
134 send_text(s, "</form>\n");
78fb0984
MG
135 send_text(s, "<a href=\"?cmd=:RUN\">RUN</a> ");
136 send_text(s, "<a href=\"?cmd=:STOP\">STOP</a> ");
137 send_text(s, "<a href=\"?cmd=:FORC\">FORCE</a> ");
04d383a4 138 if (param) {
04d383a4
MG
139 claimscope(sc);
140 if (strchr (param, '?')) {
04d383a4
MG
141 send_text(s, "<pre>< ");
142 send_text(s, param);
143 send_text(s, "\n> ");
78fb0984 144 send_command_output(s, sc, param);
04d383a4
MG
145 send_text(s, "</pre>\n");
146 } else {
147 sendscpi(sc, param, NULL, 0);
148 }
149 releasescope(sc);
150 }
ad9fbc05
MG
151 send_text(s, "</body></html>\n");
152}
153
713be7a4 154static void serve_lcd(int s, struct scope *sc)
ad9fbc05
MG
155{
156 char buf[256];
157 int imglen;
158 unsigned char *png;
159
713be7a4 160 claimscope(sc);
ad9fbc05 161 png = get_lcd(sc, &imglen, 0);
713be7a4 162 releasescope(sc);
ad9fbc05
MG
163
164 if (png == NULL)
165 return;
166
167
33b7545a 168 send_text(s, "HTTP/1.0 200 OK\n");
ad9fbc05
MG
169 send_text(s, "Content-type: image/png\n");
170 snprintf(buf, sizeof(buf), "Content-length: %u\n\n", imglen);
171 send_text(s, buf);
172 send_binary(s, (char*)png, imglen);
173 free(png);
174}
175
04d383a4
MG
176static void serve_404(int s)
177{
178 send_text(s, "HTTP/1.0 404 Not found\n");
179 send_text(s, "Content-type: text/html\n\n");
180 send_text(s, "<html><head><title>404</title></head>");
181 send_text(s, "<body bgcolor=\"#ffffff\" text=\"#000000\">\n");
182 send_text(s, "<h1>404</h1>");
183 send_text(s, "</body></html>\n");
184}
185
33b7545a
MG
186int is_eor(char *buf)
187{
188 int eor = 0;
189
190 /* This does not completely work, when the request is split
191 in multiple packets... */
192 if (strstr(buf, "\x0d\x0a\x0d\x0a")) {
193 eor = 1;
194 } else if (strstr(buf, "\x0a\x0a")) {
195 eor = 1;
196 } else if (strcmp(buf, "\x0d\x0a") == 0) {
197 eor = 1;
198 } else if (strcmp(buf, "\x0a") == 0) {
199 eor = 1;
200 }
201
202 return eor;
203}
204
205
713be7a4 206static void parse_request(int s, struct scope *sc)
ad9fbc05
MG
207{
208 int ret;
33b7545a
MG
209 int eor;
210 char buf[4096];
211 char file[4096];
ad9fbc05 212 const char delim[] = " \t\x0d\x0a";
ad9fbc05
MG
213 char *saveptr;
214 char *token;
04d383a4 215 char *param = NULL;
ad9fbc05 216
33b7545a 217 alarm(TIMEOUT);
ad9fbc05
MG
218 ret=read(s, buf, sizeof(buf)-1);
219 if (ret == -1) {
220 perror("read");
221 return;
222 }
223 buf[ret] = 0;
224
33b7545a
MG
225 eor = is_eor(buf);
226
ad9fbc05 227 token = strtok_r(buf, delim, &saveptr);
77385d56
MG
228 if (token == NULL)
229 return;
ad9fbc05
MG
230 /* TODO: Only GET... */
231 token = strtok_r(NULL, delim, &saveptr);
77385d56
MG
232 if (token == NULL)
233 return;
ad9fbc05
MG
234 bzero(&file, sizeof(file));
235 strncpy(file, token, sizeof(file)-1);
236
33b7545a
MG
237 while (!eor) {
238 alarm(TIMEOUT);
239 ret=read(s, buf, sizeof(buf)-1);
240 if (ret == -1) {
241 perror("read");
242 return;
ad9fbc05 243 }
33b7545a
MG
244 buf[ret] = 0;
245 eor = is_eor(buf);
246 }
247 alarm(0);
ad9fbc05 248
04d383a4
MG
249 param = strchr(file, '?');
250 if (param) {
251 *param = 0;
252 param++;
253
254 while ((token = strchr(param, '%')) != NULL) {
255 char buf[3];
256
257 if (strlen(token+1) < 2)
258 break;
259
260 strncpy(buf, token+1, 3);
261 buf[2] = 0;
262
263 *token = (char)strtoul(buf, NULL, 16);
264 memmove(token+1, token+3, strlen(token)-2);
265
266 }
78fb0984
MG
267 while ((token = strchr(param, '+')) != NULL) {
268 *token = ' ';
269 }
04d383a4
MG
270 }
271
ad9fbc05 272 if (strcmp("/", file) == 0) {
04d383a4
MG
273 serve_index(s, sc, param);
274 } else if (strcmp("/cgi-bin/lcd", file) == 0) {
ad9fbc05 275 serve_lcd(s, sc);
04d383a4
MG
276 } else {
277 serve_404(s);
ad9fbc05
MG
278 }
279}
659f6954 280
7a226bb8
MG
281void sighandler(int sig)
282{
33b7545a
MG
283 switch(sig) {
284 case SIGPIPE:
285 break;
286 case SIGALRM:
287 default:
288 printf("Signal %d received\n", sig);
289 break;
290 }
7a226bb8
MG
291}
292
659f6954
MG
293int main(int argc, char **argv)
294{
7a226bb8 295 struct sigaction act;
ad9fbc05
MG
296 int sock, csock;
297 int opt;
298 socklen_t slen;
713be7a4 299 struct scope *sc;
ad9fbc05 300 struct sockaddr_in sin, clientsin;
77385d56 301 unsigned short port = 8088;
659f6954 302
713be7a4 303 sc = initscope();
7a226bb8
MG
304 if (sc == NULL) {
305 printf("Scope not found!\n");
306 exit(EXIT_FAILURE);
307 }
308
309 bzero(&act, sizeof(act));
310 act.sa_handler = sighandler;
311 act.sa_flags = SA_RESTART;
312 if (sigaction(SIGPIPE, &act, NULL) == -1) {
313 perror("sigaction");
314 exit(EXIT_FAILURE);
315 }
ad9fbc05 316
33b7545a
MG
317 bzero(&act, sizeof(act));
318 act.sa_handler = sighandler;
319 if (sigaction(SIGALRM, &act, NULL) == -1) {
320 perror("sigaction");
321 exit(EXIT_FAILURE);
322 }
323
ad9fbc05
MG
324 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
325 perror("socket");
326 exit(EXIT_FAILURE);
327 }
328
329 if (argc == 2) {
330 port=atoi(argv[1]);
331 }
332
333 bzero(&sin, sizeof(sin));
334 sin.sin_addr.s_addr=htonl(INADDR_ANY);
335 sin.sin_family=AF_INET;
336 sin.sin_port=htons(port);
337
338 opt = 1;
339 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt,sizeof(opt));
340
341 if (bind(sock, (struct sockaddr*)&sin, sizeof(sin)) == -1) {
342 perror("bind");
343 exit(EXIT_FAILURE);
344 }
345
346 listen(sock, 32);
347 printf("Listening on Port %u\n", port);
348
349 while(1) {
350 bzero(&clientsin, sizeof(clientsin));
351 slen = sizeof(clientsin);
352 if ((csock = accept(sock, (struct sockaddr*)&clientsin, &slen)) == -1) {
353 perror("accept");
354 }
355
356 parse_request(csock, sc);
357
358 close(csock);
359 }
360
713be7a4 361 closescope(sc);
659f6954
MG
362 return 0;
363}
Impressum, Datenschutz