2 * RRDTool - src/rrd_client.c
3 * Copyright (C) 2008 Florian octo Forster
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; only version 2 of the License is applicable.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * Florian octo Forster <octo at verplant.org>
23 #include "rrd_client.h"
30 #include <sys/types.h>
31 #include <sys/socket.h>
35 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
41 static ssize_t sread (void *buffer_void, size_t buffer_size) /* {{{ */
48 buffer = (char *) buffer_void;
50 buffer_free = buffer_size;
52 while (buffer_free > 0)
54 status = read (sd, buffer + buffer_used, buffer_free);
55 if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR)))
72 assert ((0 > status) || (buffer_free >= (size_t) status));
74 buffer_free = buffer_free - status;
75 buffer_used = buffer_used + status;
77 if (buffer[buffer_used - 1] == '\n')
81 if (buffer[buffer_used - 1] != '\n')
87 buffer[buffer_used - 1] = 0;
89 } /* }}} ssize_t sread */
91 static ssize_t swrite (const void *buf, size_t count) /* {{{ */
97 ptr = (const char *) buf;
102 status = write (sd, (const void *) ptr, nleft);
104 if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR)))
110 nleft = nleft - status;
115 } /* }}} ssize_t swrite */
117 static int buffer_add_string (const char *str, /* {{{ */
118 char **buffer_ret, size_t *buffer_size_ret)
126 buffer = *buffer_ret;
127 buffer_size = *buffer_size_ret;
132 while (buffer_pos < buffer_size)
136 buffer[buffer_pos] = ' ';
141 else if ((str[i] == ' ') || (str[i] == '\\'))
143 if (buffer_pos >= (buffer_size - 1))
145 buffer[buffer_pos] = '\\';
147 buffer[buffer_pos] = str[i];
152 buffer[buffer_pos] = str[i];
156 } /* while (buffer_pos < buffer_size) */
161 *buffer_ret = buffer + buffer_pos;
162 *buffer_size_ret = buffer_size - buffer_pos;
165 } /* }}} int buffer_add_string */
167 static int buffer_add_value (const char *value, /* {{{ */
168 char **buffer_ret, size_t *buffer_size_ret)
172 if (strncmp (value, "N:", 2) == 0)
173 snprintf (temp, sizeof (temp), "%lu:%s",
174 (unsigned long) time (NULL), value + 2);
176 strncpy (temp, value, sizeof (temp));
177 temp[sizeof (temp) - 1] = 0;
179 return (buffer_add_string (temp, buffer_ret, buffer_size_ret));
180 } /* }}} int buffer_add_value */
182 static int rrdc_connect_unix (const char *path) /* {{{ */
184 struct sockaddr_un sa;
188 path = RRDD_SOCK_PATH;
190 pthread_mutex_lock (&lock);
194 pthread_mutex_unlock (&lock);
198 sd = socket (PF_UNIX, SOCK_STREAM, /* protocol = */ 0);
202 pthread_mutex_unlock (&lock);
206 memset (&sa, 0, sizeof (sa));
207 sa.sun_family = AF_UNIX;
208 strncpy (sa.sun_path, path, sizeof (sa.sun_path) - 1);
210 status = connect (sd, (struct sockaddr *) &sa, sizeof (sa));
214 pthread_mutex_unlock (&lock);
219 sh = fdopen (sd, "w+");
225 pthread_mutex_unlock (&lock);
230 pthread_mutex_unlock (&lock);
233 } /* }}} int rrdc_connect_unix */
235 int rrdc_connect (const char *addr) /* {{{ */
237 struct addrinfo ai_hints;
238 struct addrinfo *ai_res;
239 struct addrinfo *ai_ptr;
243 addr = RRDD_SOCK_PATH;
245 if (strncmp ("unix:", addr, strlen ("unix:")) == 0)
246 return (rrdc_connect_unix (addr + strlen ("unix:")));
247 else if (addr[0] == '/')
248 return (rrdc_connect_unix (addr));
250 pthread_mutex_lock (&lock);
254 pthread_mutex_unlock (&lock);
258 memset (&ai_hints, 0, sizeof (ai_hints));
259 ai_hints.ai_flags = 0;
261 ai_hints.ai_flags |= AI_ADDRCONFIG;
263 ai_hints.ai_family = AF_UNSPEC;
264 ai_hints.ai_socktype = SOCK_STREAM;
267 status = getaddrinfo (addr, DEFAULT_PORT, &ai_hints, &ai_res);
270 pthread_mutex_unlock (&lock);
274 for (ai_ptr = ai_res; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
276 sd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
284 status = connect (sd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
294 sh = fdopen (sd, "w+");
304 assert (status == 0);
307 pthread_mutex_unlock (&lock);
310 } /* }}} int rrdc_connect */
312 int rrdc_disconnect (void) /* {{{ */
316 pthread_mutex_lock (&lock);
320 pthread_mutex_unlock (&lock);
325 status = fclose (sh);
335 pthread_mutex_unlock (&lock);
338 } /* }}} int rrdc_disconnect */
340 int rrdc_update (const char *filename, int values_num, /* {{{ */
341 const char * const *values)
350 memset (buffer, 0, sizeof (buffer));
351 buffer_ptr = &buffer[0];
352 buffer_free = sizeof (buffer);
354 status = buffer_add_string ("update", &buffer_ptr, &buffer_free);
358 status = buffer_add_string (filename, &buffer_ptr, &buffer_free);
362 for (i = 0; i < values_num; i++)
364 status = buffer_add_value (values[i], &buffer_ptr, &buffer_free);
369 assert (buffer_free < sizeof (buffer));
370 buffer_size = sizeof (buffer) - buffer_free;
371 assert (buffer[buffer_size - 1] == ' ');
372 buffer[buffer_size - 1] = '\n';
374 pthread_mutex_lock (&lock);
378 pthread_mutex_unlock (&lock);
382 status = swrite (buffer, buffer_size);
385 pthread_mutex_unlock (&lock);
389 status = sread (buffer, sizeof (buffer));
393 pthread_mutex_unlock (&lock);
396 else if (status == 0)
398 pthread_mutex_unlock (&lock);
402 pthread_mutex_unlock (&lock);
404 status = atoi (buffer);
406 } /* }}} int rrd_update_daemon */
408 int rrdc_flush (const char *filename) /* {{{ */
416 if (filename == NULL)
419 memset (buffer, 0, sizeof (buffer));
420 buffer_ptr = &buffer[0];
421 buffer_free = sizeof (buffer);
423 status = buffer_add_string ("flush", &buffer_ptr, &buffer_free);
427 status = buffer_add_string (filename, &buffer_ptr, &buffer_free);
431 assert (buffer_free < sizeof (buffer));
432 buffer_size = sizeof (buffer) - buffer_free;
433 assert (buffer[buffer_size - 1] == ' ');
434 buffer[buffer_size - 1] = '\n';
436 pthread_mutex_lock (&lock);
440 pthread_mutex_unlock (&lock);
444 status = swrite (buffer, buffer_size);
447 pthread_mutex_unlock (&lock);
451 status = sread (buffer, sizeof (buffer));
455 pthread_mutex_unlock (&lock);
458 else if (status == 0)
460 pthread_mutex_unlock (&lock);
464 pthread_mutex_unlock (&lock);
466 status = atoi (buffer);
468 } /* }}} int rrdc_flush */
471 * vim: set sw=2 sts=2 ts=8 et fdm=marker :