"graph" action: Print the "X-Generator" header on generated graphs, too.
[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
43 #include <fcgiapp.h>
44 #include <fcgi_stdio.h>
45
46 size_t c_strlcat (char *dst, const char *src, size_t size) /* {{{ */
47 {
48   size_t retval;
49   size_t dst_len;
50   size_t src_len;
51
52   dst_len = strlen (dst);
53   src_len = strlen (src);
54   retval = dst_len + src_len;
55
56   if ((dst_len + 1) >= size)
57     return (retval);
58
59   dst  += dst_len;
60   size -= dst_len;
61   assert (size >= 2);
62
63   /* Result will be truncated. */
64   if (src_len >= size)
65     src_len = size - 1;
66
67   memcpy (dst, src, src_len);
68   dst[src_len] = 0;
69
70   return (retval);
71 } /* }}} size_t c_strlcat */
72
73 int ds_list_from_rrd_file (char *file, /* {{{ */
74     size_t *ret_dses_num, char ***ret_dses)
75 {
76   char *rrd_argv[] = { "info", file, NULL };
77   int rrd_argc = (sizeof (rrd_argv) / sizeof (rrd_argv[0])) - 1;
78
79   rrd_info_t *info;
80   rrd_info_t *ptr;
81
82   char **dses = NULL;
83   size_t dses_num = 0;
84
85   info = rrd_info (rrd_argc, rrd_argv);
86   if (info == NULL)
87   {
88     printf ("%s: rrd_info (%s) failed.\n", __func__, file);
89     return (-1);
90   }
91
92   for (ptr = info; ptr != NULL; ptr = ptr->next)
93   {
94     size_t keylen;
95     size_t dslen;
96     char *ds;
97     char **tmp;
98
99     if (strncmp ("ds[", ptr->key, strlen ("ds[")) != 0)
100       continue;
101
102     keylen = strlen (ptr->key);
103     if (keylen < strlen ("ds[?].index"))
104       continue;
105
106     dslen = keylen - strlen ("ds[].index");
107     assert (dslen >= 1);
108
109     if (strcmp ("].index", ptr->key + (strlen ("ds[") + dslen)) != 0)
110       continue;
111
112     ds = malloc (dslen + 1);
113     if (ds == NULL)
114       continue;
115
116     memcpy (ds, ptr->key + strlen ("ds["), dslen);
117     ds[dslen] = 0;
118
119     tmp = realloc (dses, sizeof (*dses) * (dses_num + 1));
120     if (tmp == NULL)
121     {
122       free (ds);
123       continue;
124     }
125     dses = tmp;
126
127     dses[dses_num] = ds;
128     dses_num++;
129   }
130
131   rrd_info_free (info);
132
133   if (dses_num < 1)
134   {
135     assert (dses == NULL);
136     return (ENOENT);
137   }
138
139   *ret_dses_num = dses_num;
140   *ret_dses = dses;
141
142   return (0);
143 } /* }}} int ds_list_from_rrd_file */
144
145 static int hsv_to_rgb (double *hsv, double *rgb) /* {{{ */
146 {
147   double c = hsv[2] * hsv[1];
148   double h = hsv[0] / 60.0;
149   double x = c * (1.0 - fabs (fmod (h, 2.0) - 1));
150   double m = hsv[2] - c;
151
152   rgb[0] = 0.0;
153   rgb[1] = 0.0;
154   rgb[2] = 0.0;
155
156        if ((0.0 <= h) && (h < 1.0)) { rgb[0] = 1.0; rgb[1] = x; rgb[2] = 0.0; }
157   else if ((1.0 <= h) && (h < 2.0)) { rgb[0] = x; rgb[1] = 1.0; rgb[2] = 0.0; }
158   else if ((2.0 <= h) && (h < 3.0)) { rgb[0] = 0.0; rgb[1] = 1.0; rgb[2] = x; }
159   else if ((3.0 <= h) && (h < 4.0)) { rgb[0] = 0.0; rgb[1] = x; rgb[2] = 1.0; }
160   else if ((4.0 <= h) && (h < 5.0)) { rgb[0] = x; rgb[1] = 0.0; rgb[2] = 1.0; }
161   else if ((5.0 <= h) && (h < 6.0)) { rgb[0] = 1.0; rgb[1] = 0.0; rgb[2] = x; }
162
163   rgb[0] += m;
164   rgb[1] += m;
165   rgb[2] += m;
166
167   return (0);
168 } /* }}} int hsv_to_rgb */
169
170 static uint32_t rgb_to_uint32 (double *rgb) /* {{{ */
171 {
172   uint8_t r;
173   uint8_t g;
174   uint8_t b;
175
176   r = (uint8_t) (255.0 * rgb[0]);
177   g = (uint8_t) (255.0 * rgb[1]);
178   b = (uint8_t) (255.0 * rgb[2]);
179
180   return ((((uint32_t) r) << 16)
181       | (((uint32_t) g) << 8)
182       | ((uint32_t) b));
183 } /* }}} uint32_t rgb_to_uint32 */
184
185 static int uint32_to_rgb (uint32_t color, double *rgb)
186 {
187   uint8_t r;
188   uint8_t g;
189   uint8_t b;
190
191   r = (uint8_t) ((color >> 16) & 0x00ff);
192   g = (uint8_t) ((color >>  8) & 0x00ff);
193   b = (uint8_t) ((color >>  0) & 0x00ff);
194
195   rgb[0] = ((double) r) / 255.0;
196   rgb[1] = ((double) g) / 255.0;
197   rgb[2] = ((double) b) / 255.0;
198
199   return (0);
200 } /* }}} int uint32_to_rgb */
201
202 uint32_t get_random_color (void) /* {{{ */
203 {
204   double hsv[3] = { 0.0, 1.0, 1.0 };
205   double rgb[3] = { 0.0, 0.0, 0.0 };
206
207   hsv[0] = 360.0 * ((double) rand ()) / (((double) RAND_MAX) + 1.0);
208
209   hsv_to_rgb (hsv, rgb);
210
211   return (rgb_to_uint32 (rgb));
212 } /* }}} uint32_t get_random_color */
213
214 uint32_t fade_color (uint32_t color) /* {{{ */
215 {
216   double rgb[3];
217
218   uint32_to_rgb (color, rgb);
219   rgb[0] = 1.0 - ((1.0 - rgb[0]) * 0.1);
220   rgb[1] = 1.0 - ((1.0 - rgb[1]) * 0.1);
221   rgb[2] = 1.0 - ((1.0 - rgb[2]) * 0.1);
222
223   return (rgb_to_uint32 (rgb));
224 } /* }}} uint32_t fade_color */
225
226 int print_debug (const char *format, ...) /* {{{ */
227 {
228   static _Bool have_header = 0;
229
230   va_list ap;
231   int status;
232
233   if (!have_header)
234   {
235     printf ("Content-Type: text/plain\n\n");
236     have_header = 1;
237   }
238
239   va_start (ap, format);
240   status = vprintf (format, ap);
241   va_end (ap);
242
243   return (status);
244 } /* }}} int print_debug */
245
246 char *strtolower (char *str) /* {{{ */
247 {
248   unsigned int i;
249
250   if (str == NULL)
251     return (NULL);
252
253   for (i = 0; str[i] != 0; i++)
254     str[i] = (char) tolower ((int) str[i]);
255
256   return (str);
257 } /* }}} char *strtolower */
258
259 char *strtolower_copy (const char *str)
260 {
261   if (str == NULL)
262     return (NULL);
263
264   return (strtolower (strdup (str)));
265 }
266
267 /* vim: set sw=2 sts=2 et fdm=marker : */