ipfw: Use netisr wrappers
[dragonfly.git] / usr.bin / evtranalyze / plotter.c
blob260cf7af4b0d339ac30841dc21f4cce4d487d905
1 #include <assert.h>
2 #include <err.h>
3 #include <errno.h>
4 #include <libprop/proplib.h>
5 #include <sys/stat.h>
6 #include <sys/types.h>
7 #include <sys/wait.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
13 #include "trivial.h"
14 #include "plotter.h"
16 struct ploticus_plot {
17 unsigned type;
18 prop_dictionary_t params;
19 FILE *fp;
20 char *path;
23 struct ploticus_plotter {
24 int nr_plots;
25 struct ploticus_plot **plots;
26 const char *basepath;
29 const char *plot_prefabs[] = {
30 [PLOT_TYPE_HIST] = "dist",
31 [PLOT_TYPE_LINE] = "lines",
34 static
35 void *
36 ploticus_init(const char *base)
38 struct ploticus_plotter *ctx;
40 if (!(ctx = calloc(1, sizeof(*ctx))))
41 return ctx;
42 if (!(ctx->basepath = strdup(base)))
43 goto free_ctx;
44 return ctx;
45 free_ctx:
46 free(ctx);
47 return NULL;
50 static
51 int
52 ploticus_new_plot_hist(struct ploticus_plot *plot)
54 prop_dictionary_t params = plot->params;
55 prop_string_t str;
57 if (!(str = prop_string_create_cstring_nocopy("1")))
58 return !0;
59 if (!prop_dictionary_set(params, "x", str)) {
60 prop_object_release(str);
61 return !0;
63 if (!(str = prop_string_create_cstring_nocopy("yes")))
64 return !0;
65 if (!prop_dictionary_set(params, "curve", str)) {
66 prop_object_release(str);
67 return !0;
69 return 0;
72 static
73 int
74 ploticus_new_plot_line(struct ploticus_plot *plot)
76 prop_dictionary_t params = plot->params;
77 prop_string_t str;
79 if (!(str = prop_string_create_cstring_nocopy("1")))
80 return !0;
81 if (!prop_dictionary_set(params, "x", str)) {
82 prop_object_release(str);
83 return !0;
85 if (!(str = prop_string_create_cstring_nocopy("2")))
86 return !0;
87 if (!prop_dictionary_set(params, "y", str)) {
88 prop_object_release(str);
89 return !0;
91 return 0;
94 int (*plot_type_initializers[])(struct ploticus_plot *) = {
95 [PLOT_TYPE_HIST] = ploticus_new_plot_hist,
96 [PLOT_TYPE_LINE] = ploticus_new_plot_line,
99 static
100 plotid_t
101 ploticus_new_plot(void *_ctx, enum plot_type type, const char *title)
103 struct ploticus_plot *plot;
104 prop_dictionary_t params;
105 prop_string_t str;
106 struct ploticus_plotter *ctx = _ctx;
107 struct ploticus_plot **tmp;
108 char *datapath;
110 if ((type <= PLOT_TYPE_START) || (type >= PLOT_TYPE_END))
111 return -1;
112 if (!(tmp = realloc(ctx->plots, sizeof(struct ploticus_plot *) *
113 (ctx->nr_plots + 1))))
114 return -1;
115 ctx->plots = tmp;
117 if (!(params = prop_dictionary_create()))
118 return -1;
119 if (!(plot = calloc(1, sizeof(*plot))))
120 goto free_params;
121 plot->params = params;
122 plot->type = type;
124 if (asprintf(&plot->path, "%s-%d-%s", ctx->basepath, type,
125 title) < 0)
126 goto free_plot;
127 if (asprintf(&datapath, "%s.data", plot->path) < 0)
128 goto free_path;
130 if (!(str = prop_string_create_cstring(title)))
131 goto free_datapath;
132 if (!prop_dictionary_set(params, "title", str)) {
133 prop_object_release(str);
134 goto free_datapath;
136 if (!(str = prop_string_create_cstring(datapath)))
137 goto free_datapath;
138 if (!prop_dictionary_set(params, "data", str)) {
139 prop_object_release(str);
140 goto free_datapath;
143 if (plot_type_initializers[type](plot))
144 goto free_datapath;
145 if (!(plot->fp = fopen(datapath, "w"))) {
146 goto free_datapath;
148 free(datapath);
149 ctx->plots[ctx->nr_plots] = plot;
150 return ctx->nr_plots++;
152 free_datapath:
153 free(datapath);
154 free_path:
155 free(plot->path);
156 free_plot:
157 free(plot);
158 free_params:
159 prop_object_release(params);
160 return -1;
163 static
165 ploticus_plot_histogram(void *_ctx, plotid_t id, double val)
167 struct ploticus_plotter *ctx = _ctx;
168 struct ploticus_plot *plot;
170 if ((id < 0) || (id >= ctx->nr_plots))
171 return ERANGE;
172 plot = ctx->plots[id];
173 assert(plot != NULL);
175 fprintf(plot->fp, "%lf\n", val);
177 return 0;
180 static
182 ploticus_plot_line(void *_ctx, plotid_t id, double x, double y)
184 struct ploticus_plotter *ctx = _ctx;
185 struct ploticus_plot *plot;
187 if ((id < 0) || (id >= ctx->nr_plots))
188 return ERANGE;
189 plot = ctx->plots[id];
190 assert(plot != NULL);
192 fprintf(plot->fp, "%lf %lf\n", x, y);
194 return 0;
197 extern char **environ;
199 static
200 void
201 ploticus_run(struct ploticus_plot *plot)
203 unsigned nr_params;
204 const char **pl_argv;
205 prop_object_iterator_t it;
206 prop_object_t key, val;
207 const char *keystr;
208 const char *output_format = "-svg";
209 int i;
211 printd(PLOT, "ploticus_run\n");
212 nr_params = prop_dictionary_count(plot->params);
213 if (!(pl_argv = calloc(nr_params +
214 1 + /* progname */
215 1 + /* trailing NULL */
216 1 + /* -prefab */
217 1 + /* dist */
218 1 + /* output format */
219 1 + /* -o */
220 1 /* outpath */
221 , sizeof(char *))))
222 err(1, "can't allocate argv");
223 if (!(it = prop_dictionary_iterator(plot->params)))
224 err(1, "can't allocate dictionary iterator");
225 pl_argv[0] = "ploticus";
226 pl_argv[1] = "-prefab";
227 pl_argv[2] = plot_prefabs[plot->type];
228 pl_argv[2 + nr_params + 1] = output_format;
229 pl_argv[2 + nr_params + 2] = "-o";
230 if (asprintf(__DECONST(char **, &pl_argv[2 + nr_params + 3]),
231 "%s.svg", plot->path) < 0)
232 err(1, "Can't allocate args");
233 key = prop_object_iterator_next(it);
234 for (i = 3; key; ++i, key = prop_object_iterator_next(it)) {
235 keystr = prop_dictionary_keysym_cstring_nocopy(key);
236 assert(keystr != NULL);
237 val = prop_dictionary_get_keysym(plot->params, key);
238 assert(val != NULL);
239 printd(PLOT, "%s=%s\n", keystr,
240 prop_string_cstring_nocopy(val));
241 if (asprintf(__DECONST(char **, &pl_argv[i]), "%s=%s", keystr,
242 prop_string_cstring_nocopy(val)) < 0)
243 err(1, "can't allocate exec arguments");
245 prop_object_iterator_release(it);
246 printd(PLOT, "about to exec with args:\n");
247 for (i = 0; pl_argv[i]; ++i)
248 printd(PLOT, "%s\n", pl_argv[i]);
249 execve("/usr/local/bin/ploticus", __DECONST(char * const *, pl_argv), environ);
250 err(1, "failed to exec ploticus");
253 static
255 ploticus_plot_generate(struct ploticus_plot *plot)
257 pid_t pid;
258 int status;
260 fclose(plot->fp);
262 switch ((pid = fork())) {
263 case -1:
264 return -1;
265 case 0: /* child */
266 ploticus_run(plot);
267 assert(!"can't get here");
269 /* parent */
270 if (waitpid(pid, &status, 0) != pid)
271 err(1, "waitpid() failed");
272 if (!WIFEXITED(status))
273 warn("ploticus did not exit!");
274 if (WEXITSTATUS(status))
275 warn("ploticus did not run successfully");
276 return 0;
279 static
281 ploticus_plot_finish(void *_ctx)
283 struct ploticus_plotter *ctx = _ctx;
284 int i;
286 for (i = 0; i < ctx->nr_plots; ++i) {
287 if (ploticus_plot_generate(ctx->plots[i]))
288 return -1;
290 return 0;
293 static struct plotter ploticus_plotter = {
294 .plot_init = ploticus_init,
295 .plot_new = ploticus_new_plot,
296 .plot_histogram = ploticus_plot_histogram,
297 .plot_line = ploticus_plot_line,
298 .plot_finish = ploticus_plot_finish,
301 static const char *ploticus_path = "/usr/local/bin/ploticus";
303 struct plotter *
304 plotter_factory(void)
306 struct stat st;
307 if ((!stat(ploticus_path, &st)) &&
308 S_ISREG(st.st_mode) &&
309 (st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
310 return &ploticus_plotter;
311 warnx("%s does not exist or is not an executable file", ploticus_path);
312 return NULL;