graph_{data,def}_json actions: Don't destroy the graph_config_t object.
[collection4.git] / src / common.c
1 /**
2  * collection4 - common.c
3  * Copyright (C) 2010  Florian octo Forster
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  * 
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA  02110-1301  USA
19  *
20  * Authors:
21  *   Florian octo Forster <ff at octo.it>
22  **/
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <stdint.h>
27 #include <inttypes.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <errno.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <unistd.h>
34 #include <dirent.h>
35 #include <assert.h>
36 #include <math.h>
37
38 #include <rrd.h>
39
40 #include "common.h"
41 #include "graph_list.h"
42 #include "utils_cgi.h"
43
44 #include <fcgiapp.h>
45 #include <fcgi_stdio.h>
46
47 size_t c_strlcat (char *dst, const char *src, size_t size) /* {{{ */
48 {
49   size_t retval;
50   size_t dst_len;
51   size_t src_len;
52
53   dst_len = strlen (dst);
54   src_len = strlen (src);
55   retval = dst_len + src_len;
56
57   if ((dst_len + 1) >= size)
58     return (retval);
59
60   dst  += dst_len;
61   size -= dst_len;
62   assert (size >= 2);
63
64   /* Result will be truncated. */
65   if (src_len >= size)
66     src_len = size - 1;
67
68   memcpy (dst, src, src_len);
69   dst[src_len] = 0;
70
71   return (retval);
72 } /* }}} size_t c_strlcat */
73
74 int ds_list_from_rrd_file (char *file, /* {{{ */
75     size_t *ret_dses_num, char ***ret_dses)
76 {
77   char *rrd_argv[] = { "info", file, NULL };
78   int rrd_argc = (sizeof (rrd_argv) / sizeof (rrd_argv[0])) - 1;
79
80   rrd_info_t *info;
81   rrd_info_t *ptr;
82
83   char **dses = NULL;
84   size_t dses_num = 0;
85
86   info = rrd_info (rrd_argc, rrd_argv);
87   if (info == NULL)
88   {
89     printf ("%s: rrd_info (%s) failed.\n", __func__, file);
90     return (-1);
91   }
92
93   for (ptr = info; ptr != NULL; ptr = ptr->next)
94   {
95     size_t keylen;
96     size_t dslen;
97     char *ds;
98     char **tmp;
99
100     if (strncmp ("ds[", ptr->key, strlen ("ds[")) != 0)
101       continue;
102
103     keylen = strlen (ptr->key);
104     if (keylen < strlen ("ds[?].index"))
105       continue;
106
107     dslen = keylen - strlen ("ds[].index");
108     assert (dslen >= 1);
109
110     if (strcmp ("].index", ptr->key + (strlen ("ds[") + dslen)) != 0)
111       continue;
112
113     ds = malloc (dslen + 1);
114     if (ds == NULL)
115       continue;
116
117     memcpy (ds, ptr->key + strlen ("ds["), dslen);
118     ds[dslen] = 0;
119
120     tmp = realloc (dses, sizeof (*dses) * (dses_num + 1));
121     if (tmp == NULL)
122     {
123       free (ds);
124       continue;
125     }
126     dses = tmp;
127
128     dses[dses_num] = ds;
129     dses_num++;
130   }
131
132   rrd_info_free (info);
133
134   if (dses_num < 1)
135   {
136     assert (dses == NULL);
137     return (ENOENT);
138   }
139
140   *ret_dses_num = dses_num;
141   *ret_dses = dses;
142
143   return (0);
144 } /* }}} int ds_list_from_rrd_file */
145
146 static int hsv_to_rgb (double *hsv, double *rgb) /* {{{ */
147 {
148   double c = hsv[2] * hsv[1];
149   double h = hsv[0] / 60.0;
150   double x = c * (1.0 - fabs (fmod (h, 2.0) - 1));
151   double m = hsv[2] - c;
152
153   rgb[0] = 0.0;
154   rgb[1] = 0.0;
155   rgb[2] = 0.0;
156
157        if ((0.0 <= h) && (h < 1.0)) { rgb[0] = 1.0; rgb[1] = x; rgb[2] = 0.0; }
158   else if ((1.0 <= h) && (h < 2.0)) { rgb[0] = x; rgb[1] = 1.0; rgb[2] = 0.0; }
159   else if ((2.0 <= h) && (h < 3.0)) { rgb[0] = 0.0; rgb[1] = 1.0; rgb[2] = x; }
160   else if ((3.0 <= h) && (h < 4.0)) { rgb[0] = 0.0; rgb[1] = x; rgb[2] = 1.0; }
161   else if ((4.0 <= h) && (h < 5.0)) { rgb[0] = x; rgb[1] = 0.0; rgb[2] = 1.0; }
162   else if ((5.0 <= h) && (h < 6.0)) { rgb[0] = 1.0; rgb[1] = 0.0; rgb[2] = x; }
163
164   rgb[0] += m;
165   rgb[1] += m;
166   rgb[2] += m;
167
168   return (0);
169 } /* }}} int hsv_to_rgb */
170
171 static uint32_t rgb_to_uint32 (double *rgb) /* {{{ */
172 {
173   uint8_t r;
174   uint8_t g;
175   uint8_t b;
176
177   r = (uint8_t) (255.0 * rgb[0]);
178   g = (uint8_t) (255.0 * rgb[1]);
179   b = (uint8_t) (255.0 * rgb[2]);
180
181   return ((((uint32_t) r) << 16)
182       | (((uint32_t) g) << 8)
183       | ((uint32_t) b));
184 } /* }}} uint32_t rgb_to_uint32 */
185
186 static int uint32_to_rgb (uint32_t color, double *rgb) /* {{{ */
187 {
188   uint8_t r;
189   uint8_t g;
190   uint8_t b;
191
192   r = (uint8_t) ((color >> 16) & 0x00ff);
193   g = (uint8_t) ((color >>  8) & 0x00ff);
194   b = (uint8_t) ((color >>  0) & 0x00ff);
195
196   rgb[0] = ((double) r) / 255.0;
197   rgb[1] = ((double) g) / 255.0;
198   rgb[2] = ((double) b) / 255.0;
199
200   return (0);
201 } /* }}} int uint32_to_rgb */
202
203 uint32_t get_random_color (void) /* {{{ */
204 {
205   double hsv[3] = { 0.0, 1.0, 1.0 };
206   double rgb[3] = { 0.0, 0.0, 0.0 };
207
208   hsv[0] = 360.0 * ((double) rand ()) / (((double) RAND_MAX) + 1.0);
209
210   hsv_to_rgb (hsv, rgb);
211
212   return (rgb_to_uint32 (rgb));
213 } /* }}} uint32_t get_random_color */
214
215 uint32_t fade_color (uint32_t color) /* {{{ */
216 {
217   double rgb[3];
218
219   uint32_to_rgb (color, rgb);
220   rgb[0] = 1.0 - ((1.0 - rgb[0]) * 0.1);
221   rgb[1] = 1.0 - ((1.0 - rgb[1]) * 0.1);
222   rgb[2] = 1.0 - ((1.0 - rgb[2]) * 0.1);
223
224   return (rgb_to_uint32 (rgb));
225 } /* }}} uint32_t fade_color */
226
227 int print_debug (const char *format, ...) /* {{{ */
228 {
229   static _Bool have_header = 0;
230
231   va_list ap;
232   int status;
233
234   if (!have_header)
235   {
236     printf ("Content-Type: text/plain\n\n");
237     have_header = 1;
238   }
239
240   va_start (ap, format);
241   status = vprintf (format, ap);
242   va_end (ap);
243
244   return (status);
245 } /* }}} int print_debug */
246
247 char *strtolower (char *str) /* {{{ */
248 {
249   unsigned int i;
250
251   if (str == NULL)
252     return (NULL);
253
254   for (i = 0; str[i] != 0; i++)
255     str[i] = (char) tolower ((int) str[i]);
256
257   return (str);
258 } /* }}} char *strtolower */
259
260 char *strtolower_copy (const char *str) /* {{{ */
261 {
262   if (str == NULL)
263     return (NULL);
264
265   return (strtolower (strdup (str)));
266 } /* }}} char *strtolower_copy */
267
268 int get_time_args (long *ret_begin, long *ret_end, /* {{{ */
269     long *ret_now)
270 {
271   const char *begin_str;
272   const char *end_str;
273   long now;
274   long begin;
275   long end;
276   char *endptr;
277   long tmp;
278
279   if ((ret_begin == NULL) || (ret_end == NULL))
280     return (EINVAL);
281
282   begin_str = param ("begin");
283   end_str = param ("end");
284
285   now = (long) time (NULL);
286   if (ret_now != NULL)
287     *ret_now = now;
288   *ret_begin = now - 86400;
289   *ret_end = now;
290
291   if (begin_str != NULL)
292   {
293     endptr = NULL;
294     errno = 0;
295     tmp = strtol (begin_str, &endptr, /* base = */ 0);
296     if ((endptr == begin_str) || (errno != 0))
297       return (-1);
298     if (tmp <= 0)
299       begin = now + tmp;
300     else
301       begin = tmp;
302   }
303   else /* if (begin_str == NULL) */
304   {
305     begin = now - 86400;
306   }
307
308   if (end_str != NULL)
309   {
310     endptr = NULL;
311     errno = 0;
312     tmp = strtol (end_str, &endptr, /* base = */ 0);
313     if ((endptr == end_str) || (errno != 0))
314       return (-1);
315     end = tmp;
316     if (tmp <= 0)
317       end = now + tmp;
318     else
319       end = tmp;
320   }
321   else /* if (end_str == NULL) */
322   {
323     end = now;
324   }
325
326   if (begin == end)
327     return (-1);
328
329   if (begin > end)
330   {
331     tmp = begin;
332     begin = end;
333     end = tmp;
334   }
335
336   *ret_begin = begin;
337   *ret_end = end;
338
339   return (0);
340 } /* }}} int get_time_args */
341
342 /* vim: set sw=2 sts=2 et fdm=marker : */