graph_instance.[ch]: Move the graph_instance_t code into an own module.
[collection4.git] / common.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <stdint.h>
4 #include <inttypes.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <unistd.h>
10 #include <dirent.h>
11 #include <assert.h>
12 #include <math.h>
13
14 #include <rrd.h>
15
16 #include "common.h"
17 #include "graph_list.h"
18
19 #include <fcgiapp.h>
20 #include <fcgi_stdio.h>
21
22 static int foreach_rrd_file (const char *dir, /* {{{ */
23     int (*callback) (const char *, void *),
24     void *user_data)
25 {
26   DIR *dh;
27   struct dirent *entry;
28   int status;
29
30   if (callback == NULL)
31     return (EINVAL);
32
33   dh = opendir (dir);
34   if (dh == NULL)
35     return (errno);
36
37   while ((entry = readdir (dh)) != NULL)
38   {
39     struct stat statbuf;
40     char abspath[PATH_MAX + 1];
41     size_t d_name_len;
42
43     if (entry->d_name[0] == '.')
44       continue;
45
46     d_name_len = strlen (entry->d_name);
47     if (d_name_len <= 4)
48       continue;
49
50     if (strcasecmp (".rrd", entry->d_name + (d_name_len - 4)) != 0)
51       continue;
52
53     snprintf (abspath, sizeof (abspath), "%s/%s", dir, entry->d_name);
54     abspath[sizeof (abspath) - 1] = 0;
55
56     memset (&statbuf, 0, sizeof (statbuf));
57
58     status = stat (abspath, &statbuf);
59     if (status != 0)
60       continue;
61
62     if (!S_ISREG (statbuf.st_mode))
63       continue;
64
65     entry->d_name[d_name_len - 4] = 0;
66
67     status = (*callback) (entry->d_name, user_data);
68     if (status != 0)
69       break;
70   } /* while (readdir) */
71
72   closedir (dh);
73   return (status);
74 } /* }}} int foreach_rrd_file */
75
76 static int foreach_dir (const char *dir, /* {{{ */
77     int (*callback) (const char *, void *),
78     void *user_data)
79 {
80   DIR *dh;
81   struct dirent *entry;
82   int status;
83
84   if (callback == NULL)
85     return (EINVAL);
86
87   dh = opendir (dir);
88   if (dh == NULL)
89     return (errno);
90
91   while ((entry = readdir (dh)) != NULL)
92   {
93     struct stat statbuf;
94     char abspath[PATH_MAX + 1];
95
96     if (entry->d_name[0] == '.')
97       continue;
98
99     snprintf (abspath, sizeof (abspath), "%s/%s", dir, entry->d_name);
100     abspath[sizeof (abspath) - 1] = 0;
101
102     memset (&statbuf, 0, sizeof (statbuf));
103
104     status = stat (abspath, &statbuf);
105     if (status != 0)
106       continue;
107
108     if (!S_ISDIR (statbuf.st_mode))
109       continue;
110
111     status = (*callback) (entry->d_name, user_data);
112     if (status != 0)
113       break;
114   } /* while (readdir) */
115
116   closedir (dh);
117   return (status);
118 } /* }}} int foreach_dir */
119
120 int foreach_type (const char *host, const char *plugin, /* {{{ */
121     callback_type_t callback, void *user_data)
122 {
123   char abspath[PATH_MAX + 1];
124
125   if ((host == NULL) || (plugin == NULL))
126     return (EINVAL);
127
128   snprintf (abspath, sizeof (abspath), "%s/%s/%s", DATA_DIR, host, plugin);
129   abspath[sizeof (abspath) - 1] = 0;
130
131   return (foreach_rrd_file (abspath, callback, user_data));
132 } /* }}} int foreach_type */
133
134 int foreach_plugin (const char *host, /* {{{ */
135     callback_plugin_t callback,
136     void *user_data)
137 {
138   char abspath[PATH_MAX + 1];
139
140   if (host == NULL)
141     return (EINVAL);
142
143   snprintf (abspath, sizeof (abspath), "%s/%s", DATA_DIR, host);
144   abspath[sizeof (abspath) - 1] = 0;
145
146   return (foreach_dir (abspath, callback, user_data));
147 } /* }}} int foreach_plugin */
148
149 int foreach_host (callback_host_t callback, /* {{{ */
150     void *user_data)
151 {
152   return (foreach_dir (DATA_DIR, callback, user_data));
153 } /* }}} int foreach_host */
154
155 size_t c_strlcat (char *dst, const char *src, size_t size) /* {{{ */
156 {
157   size_t retval;
158   size_t dst_len;
159   size_t src_len;
160
161   dst_len = strlen (dst);
162   src_len = strlen (src);
163   retval = dst_len + src_len;
164
165   if ((dst_len + 1) >= size)
166     return (retval);
167
168   dst  += dst_len;
169   size -= dst_len;
170   assert (size >= 2);
171
172   /* Result will be truncated. */
173   if (src_len >= size)
174     src_len = size - 1;
175
176   memcpy (dst, src, src_len);
177   dst[src_len] = 0;
178
179   return (retval);
180 } /* }}} size_t c_strlcat */
181
182 int ds_list_from_rrd_file (char *file, /* {{{ */
183     size_t *ret_dses_num, char ***ret_dses)
184 {
185   char *rrd_argv[] = { "info", file, NULL };
186   int rrd_argc = (sizeof (rrd_argv) / sizeof (rrd_argv[0])) - 1;
187
188   rrd_info_t *info;
189   rrd_info_t *ptr;
190
191   char **dses = NULL;
192   size_t dses_num = 0;
193
194   info = rrd_info (rrd_argc, rrd_argv);
195   if (info == NULL)
196   {
197     printf ("%s: rrd_info (%s) failed.\n", __func__, file);
198     return (-1);
199   }
200
201   for (ptr = info; ptr != NULL; ptr = ptr->next)
202   {
203     size_t keylen;
204     size_t dslen;
205     char *ds;
206     char **tmp;
207
208     if (strncmp ("ds[", ptr->key, strlen ("ds[")) != 0)
209       continue;
210
211     keylen = strlen (ptr->key);
212     if (keylen < strlen ("ds[?].index"))
213       continue;
214
215     dslen = keylen - strlen ("ds[].index");
216     assert (dslen >= 1);
217
218     if (strcmp ("].index", ptr->key + (strlen ("ds[") + dslen)) != 0)
219       continue;
220
221     ds = malloc (dslen + 1);
222     if (ds == NULL)
223       continue;
224
225     memcpy (ds, ptr->key + strlen ("ds["), dslen);
226     ds[dslen] = 0;
227
228     tmp = realloc (dses, sizeof (*dses) * (dses_num + 1));
229     if (tmp == NULL)
230     {
231       free (ds);
232       continue;
233     }
234     dses = tmp;
235
236     dses[dses_num] = ds;
237     dses_num++;
238   }
239
240   rrd_info_free (info);
241
242   if (dses_num < 1)
243   {
244     assert (dses == NULL);
245     return (ENOENT);
246   }
247
248   *ret_dses_num = dses_num;
249   *ret_dses = dses;
250
251   return (0);
252 } /* }}} int ds_list_from_rrd_file */
253
254 static int hsv_to_rgb (double *hsv, double *rgb) /* {{{ */
255 {
256   double c = hsv[2] * hsv[1];
257   double h = hsv[0] / 60.0;
258   double x = c * (1.0 - fabs (fmod (h, 2.0) - 1));
259   double m = hsv[2] - c;
260
261   rgb[0] = 0.0;
262   rgb[1] = 0.0;
263   rgb[2] = 0.0;
264
265        if ((0.0 <= h) && (h < 1.0)) { rgb[0] = 1.0; rgb[1] = x; rgb[2] = 0.0; }
266   else if ((1.0 <= h) && (h < 2.0)) { rgb[0] = x; rgb[1] = 1.0; rgb[2] = 0.0; }
267   else if ((2.0 <= h) && (h < 3.0)) { rgb[0] = 0.0; rgb[1] = 1.0; rgb[2] = x; }
268   else if ((3.0 <= h) && (h < 4.0)) { rgb[0] = 0.0; rgb[1] = x; rgb[2] = 1.0; }
269   else if ((4.0 <= h) && (h < 5.0)) { rgb[0] = x; rgb[1] = 0.0; rgb[2] = 1.0; }
270   else if ((5.0 <= h) && (h < 6.0)) { rgb[0] = 1.0; rgb[1] = 0.0; rgb[2] = x; }
271
272   rgb[0] += m;
273   rgb[1] += m;
274   rgb[2] += m;
275
276   return (0);
277 } /* }}} int hsv_to_rgb */
278
279 static uint32_t rgb_to_uint32 (double *rgb) /* {{{ */
280 {
281   uint8_t r;
282   uint8_t g;
283   uint8_t b;
284
285   r = (uint8_t) (255.0 * rgb[0]);
286   g = (uint8_t) (255.0 * rgb[1]);
287   b = (uint8_t) (255.0 * rgb[2]);
288
289   return ((((uint32_t) r) << 16)
290       | (((uint32_t) g) << 8)
291       | ((uint32_t) b));
292 } /* }}} uint32_t rgb_to_uint32 */
293
294 uint32_t get_random_color (void) /* {{{ */
295 {
296   double hsv[3] = { 0.0, 1.0, 1.0 };
297   double rgb[3] = { 0.0, 0.0, 0.0 };
298
299   hsv[0] = 360.0 * ((double) rand ()) / (((double) RAND_MAX) + 1.0);
300
301   hsv_to_rgb (hsv, rgb);
302
303   return (rgb_to_uint32 (rgb));
304 } /* }}} uint32_t get_random_color */
305
306 int print_debug (const char *format, ...) /* {{{ */
307 {
308   static _Bool have_header = 0;
309
310   va_list ap;
311   int status;
312
313   if (!have_header)
314   {
315     printf ("Content-Type: text/plain\n\n");
316     have_header = 1;
317   }
318
319   va_start (ap, format);
320   status = vprintf (format, ap);
321   va_end (ap);
322
323   return (status);
324 } /* }}} int print_debug */
325
326 /* vim: set sw=2 sts=2 et fdm=marker : */