]> git.itanic.dy.fi Git - rrdd/blob - rrdtool.c
sanitize_rrd_update_data: Ensure minus sign is not forgotten
[rrdd] / rrdtool.c
1 #include <time.h>
2
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <unistd.h>
6 #include <string.h>
7
8 #include "rrdtool.h"
9 #include "process.h"
10 #include "parser.h"
11 #include "debug.h"
12 #include "string.h"
13
14 #define MAX_ARGS        512
15 #define ARGSTR_LEN      32768
16
17 #define RRDTOOL_CMD "/usr/bin/rrdtool"
18
19 /*
20  * Add new argument to a argument list
21  *
22  * args         pointer list to arguments
23  * argcnt       argument counter
24  * argstr       array where the actual arguments are stored
25  * idx          index in the argstr where the new argument will be appended
26  */
27 #define add_arg(args, argcnt, argstr, idx, fmt, arg...) \
28         args[argcnt] = argstr + idx;                    \
29         idx += sprintf(argstr + idx, fmt, ##arg);       \
30         argcnt++;                                       \
31         argstr[++idx] = 0
32
33 int rrdtool_draw_image(struct rrd_image *image)
34 {
35         char cmd[] = RRDTOOL_CMD;
36 //      char cmd[] = "echo";
37         char *args[512], argstr[ARGSTR_LEN];
38         int idx = 0, argcnt = 0, i,j;
39         char timestamp[256];
40         char tmp[256];
41         time_t t = time(0);
42
43         pr_info("Drawing image %s\n", image->image_filename);
44
45         strftime(tmp, 256, "%d.%m.%Y %T (%Z) ", localtime(&t));
46         for (i = 0, j = 0; j < 256;) {
47                 if (tmp[i] == ':') {
48                         timestamp[j++] = '\\';
49                 }
50                 timestamp[j++] = tmp[i++];
51                 if (!tmp[i])
52                         break;
53         }
54         timestamp[j] = 0;
55
56
57         add_arg(args, argcnt, argstr, idx, " ");
58         add_arg(args, argcnt, argstr, idx, "graph");
59         add_arg(args, argcnt, argstr, idx, "%s", image->image_filename);
60
61         add_arg(args, argcnt, argstr, idx, "--start");
62         add_arg(args, argcnt, argstr, idx, "%s", image->timestart);
63         add_arg(args, argcnt, argstr, idx, "--end");
64         add_arg(args, argcnt, argstr, idx, "%s", image->timeend);
65         add_arg(args, argcnt, argstr, idx, "--width");
66         add_arg(args, argcnt, argstr, idx, "%d", image->width);
67         add_arg(args, argcnt, argstr, idx, "--height");
68         add_arg(args, argcnt, argstr, idx, "%d", image->height);
69         add_arg(args, argcnt, argstr, idx, "--imgformat");
70         add_arg(args, argcnt, argstr, idx, "%s", image->imageformat);
71
72         for (i = 0; image->options[i]; i++) {
73                 add_arg(args, argcnt, argstr, idx, "%s", image->options[i]);
74         }
75
76         for (i = 0; image->text[i]; i++) {
77                 args[argcnt++] = image->text[i];
78         }
79
80         add_arg(args, argcnt, argstr, idx, "COMMENT:Last update %s\\c", timestamp);
81
82         args[argcnt] = 0;
83
84         run(cmd, args);
85
86         return 0;
87 }
88
89 int rrdtool_draw_images(struct rrd_image **image)
90 {
91         int i;
92         for (i = 0; image[i]; i++)
93                 rrdtool_draw_image(image[i]);
94
95         return 0;
96 }
97
98 static int sanitize_rrd_update_data(char *data)
99 {
100         char clean_data[RRD_DATA_MAX_LEN];
101         int entries = 0;
102         int minus;
103         char *src, *end, *cln;
104
105         data[RRD_DATA_MAX_LEN - 1] = 0;
106         src = data;
107         cln = clean_data;
108
109         while (src < data + RRD_DATA_MAX_LEN && *src) {
110                 minus = 0;
111                 if (*src == '-') {
112                         src++;
113                         minus = 1;
114                 }
115
116                 end = skip_numbers(src);
117
118                 if (*end == '.') {
119                         end++;
120                         end = skip_numbers(end);
121                 }
122
123                 if (*end == ':' || !*end) {
124                         if (minus) {
125                                 *cln = '-';
126                                 cln++;
127                         }
128                         for (; src <= end; src++, cln++)
129                                 *cln = *src;
130
131                         goto next;
132                 }
133
134                 while (*end != ':' && *end)
135                         end++;
136                 *cln = 'U';
137                 cln++;
138                 *cln = ':';
139                 cln++;
140         next:
141                 end++;
142                 src = end;
143                 entries++;
144         }
145
146         strncpy(data, clean_data, RRD_DATA_MAX_LEN);
147         return entries;
148 }
149
150 int rrdtool_update_data(struct rrd_database *rrd)
151 {
152         char data[RRD_DATA_MAX_LEN + 2];
153         char cmd[] = RRDTOOL_CMD;
154 //      char cmd[] = "echo";
155         char *cmdline[] = {
156                 "",
157                 "update",
158                 rrd->filename,
159                 data,
160                 0
161         };
162         int l;
163
164         rrd->last_update = time(0);
165         if (do_fork())
166                 return 0;
167
168         l = sprintf(data, "N:");
169
170         if (rrd->parse) {
171                 rrd->parse(data + l, rrd->parser_data);
172                 sanitize_rrd_update_data(data + l);
173                 run(cmd, cmdline);
174         }
175
176         if (rrd->images)
177                 rrdtool_draw_images(rrd->images);
178
179         while (harvest_zombies(0));
180         exit(0);
181 }
182
183 static int database_exists(struct rrd_database *db)
184 {
185         struct stat s;
186
187         /* If the filename exists, stat will return zero */
188         if (db->filename)
189                 return !stat(db->filename, &s);
190
191         return 1;
192 }
193
194 static int create_database(struct rrd_database *db)
195 {
196         char cmd[] = RRDTOOL_CMD;
197 //      char cmd[] = "echo";
198         char *args[512], argstr[ARGSTR_LEN];
199         int idx = 0, argcnt = 0;
200         int child, i;
201
202         if (!db->sources || !db->archives) {
203                 printf("Cannot create db \"%s\", insufficient source data\n",
204                         db->filename);
205                 return -1;
206         }
207
208         add_arg(args, argcnt, argstr, idx, " ");
209         add_arg(args, argcnt, argstr, idx, "create");
210         add_arg(args, argcnt, argstr, idx, "%s", db->filename);
211         add_arg(args, argcnt, argstr, idx, "--step");
212         add_arg(args, argcnt, argstr, idx, "%d", db->interval);
213
214         for (i = 0; db->sources[i].type; i++) {
215                 add_arg(args, argcnt, argstr, idx, "DS:%s:%s:%d:%f:%f",
216                         db->sources[i].name,
217                         db->sources[i].type,
218                         db->sources[i].heartbeat,
219                         db->sources[i].min,
220                         db->sources[i].max);
221         }
222
223         for (i = 0; db->archives[i].type; i++) {
224                 add_arg(args, argcnt, argstr, idx, "RRA:%s:%f:%d:%d",
225                         db->archives[i].type,
226                         db->archives[i].xff,
227                         db->archives[i].steps,
228                         db->archives[i].rows);
229         }
230
231         child = run(cmd, args);
232
233         harvest_zombies(child);
234
235         return 0;
236 }
237
238 int rrdtool_check_databases(struct rrd_database *dbs[])
239 {
240         struct rrd_database *db;
241         int i;
242
243         for (i = 0, db = dbs[i]; db; i++, db = dbs[i]) {
244                 if (database_exists(db)) {
245                         printf("database %s found\n", db->filename);
246                         continue;
247                 }
248                 printf("Database %s missing, creating\n", db->filename);
249                 create_database(db);
250         }
251         printf("All done\n");
252
253         return 0;
254 }