diff --git a/Makefile b/Makefile index 992bc98..8a3f7be 100644 --- a/Makefile +++ b/Makefile @@ -17,9 +17,9 @@ WWW_OWNER = www-data # ############################ -SRC := configfile.c event.c helper.c logging.c network.c pidfile.c plugins.c probe.c -SRC += sammler.c signals.c sockaddr.c -CFLAGS := -O2 -Wall -MMD -fno-stack-protector -I. +SRC := configfile.c event.c helper.c linebuffer.c logging.c network.c pidfile.c +SRC += plugins.c probe.c sammler.c signals.c sockaddr.c +CFLAGS := -O2 -Wall -Wno-unused-result -MMD -fno-stack-protector -I. LDFLAGS := -ldl -rdynamic # ############################ diff --git a/configfile.c b/configfile.c index 8219f21..04e71b7 100644 --- a/configfile.c +++ b/configfile.c @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 07/2007 by Olaf Rempel * + * Copyright (C) 03/2010 by Olaf Rempel * * razzor@kopf-tisch.de * * * * This program is free software; you can redistribute it and/or modify * @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -126,10 +127,10 @@ int config_parse(const char *config) return -1; } - char *tok = strtok(line, " \n"); + char *tmp, *tok = strtok_r(line, " \t\n", &tmp); if (tok != NULL) { char *tok2; - while ((tok2 = strtok(NULL, " \n"))) { + while ((tok2 = strtok_r(NULL, " \n", &tmp))) { if (config_add_tupel(section, tok, tok2) != 0) log_print(LOG_WARN, "config_parse(): invalid row %d", linenum); } @@ -186,15 +187,29 @@ const char * config_get_string(const char *section_str, const char *option, cons return def; } -int config_get_int(const char *section, const char *option, int def) +int config_get_int(const char *section, const char *option, int *value, int def) { const char *ret = config_get_string(section, option, NULL); if (ret == NULL) { log_print(LOG_WARN, "config [%s:%s] not found, using default: '%d'", section, option, def); - return def; + + *value = def; + return -1; } - return atoi(ret); + + char *tmp; + *value = strtol(ret, &tmp, 0); + + if (*tmp != '\0' && !isspace(*tmp)) { + log_print(LOG_WARN, "config [%s:%s] not an integer: '%s', using default '%d'", + section, option, ret, def); + + *value = def; + return -1; + } + + return 0; } int config_get_strings(const char *section_str, const char *option, @@ -214,3 +229,65 @@ int config_get_strings(const char *section_str, const char *option, } return cnt; } + +struct strtoken * strtokenize(const char *input, const char *delim, int maxfields) +{ + struct strtoken *tokens = malloc(sizeof(struct strtoken) + + maxfields * sizeof(char *) + + strlen(input)); + if (tokens == NULL) + return NULL; + + char *ptr = (char *)&tokens->field[maxfields]; + strcpy(ptr, input); + + int i; + char *tmp; + + tokens->count = 0; + for (i = 0; i < maxfields; i++) { + tokens->field[i] = strtok_r(ptr, delim, &tmp); + ptr = NULL; + + if (tokens->field[i] != NULL) + tokens->count++; + } + + return tokens; +} + +struct strtoken * config_get_strtoken(const char *section, const char *option, const char *delim, int maxfields) +{ + const char *ret = config_get_string(section, option, NULL); + if (ret == NULL) { + log_print(LOG_WARN, "config [%s:%s] not found", section, option); + + return NULL; + } + + return strtokenize(ret, delim, maxfields); +} + +int config_get_strtokens(const char *section_str, const char *option, const char *delim, int maxfields, + int (*callback)(struct strtoken *data, void *privdata), + void *privdata) +{ + struct conf_section *section = config_get_section(section_str); + if (section == NULL) + return -1; + + int cnt = 0; + struct conf_tupel *tupel; + list_for_each_entry(tupel, §ion->tupel_list, list) { + if (!strcmp(tupel->option, option)) { + struct strtoken *tokens = strtokenize(tupel->parameter, delim, maxfields); + if (tokens != NULL) { + if (callback(tokens, privdata) == 0) + cnt++; + + free(tokens); + } + } + } + return cnt; +} diff --git a/configfile.h b/configfile.h index 9a2b669..63c2edb 100644 --- a/configfile.h +++ b/configfile.h @@ -6,10 +6,23 @@ void config_free(void); const char * config_get_string(const char *section_str, const char *option, const char *def); -int config_get_int(const char *section, const char *option, int def); +int config_get_int(const char *section, const char *option, int *value, int def); int config_get_strings(const char *section_str, const char *option, int (*callback)(const char *value, void *privdata), void *privdata); +struct strtoken { + int count; + char *field[0]; +}; + +struct strtoken * strtokenize(const char *input, const char *delim, int maxfields); + +struct strtoken * config_get_strtoken(const char *section_str, const char *option, const char *delim, int maxfields); + +int config_get_strtokens(const char *section_str, const char *option, const char *delim, int maxfields, + int (*callback)(struct strtoken *tokens, void *privdata), + void *privdata); + #endif /* _CONFIG_H_ */ diff --git a/event.c b/event.c index 935a331..4e52c31 100644 --- a/event.c +++ b/event.c @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 07/2007 by Olaf Rempel * + * Copyright (C) 03/2010 by Olaf Rempel * * razzor@kopf-tisch.de * * * * This program is free software; you can redistribute it and/or modify * @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -30,7 +31,6 @@ static LIST_HEAD(event_fd_list); static LIST_HEAD(event_timeout_list); -static int leave_loop; struct event_fd { struct list_head list; @@ -199,12 +199,7 @@ void event_remove_timeout(struct event_timeout *entry) entry->flags |= EVENT_DELETE; } -void event_loop_break(void) -{ - leave_loop = 1; -} - -int event_loop(void) +int event_loop(int (*callback)(void *privdata), void *privdata) { fd_set *fdsets = malloc(sizeof(fd_set) * 2); if (fdsets == NULL) { @@ -212,8 +207,7 @@ int event_loop(void) return -1; } - leave_loop = 0; - while (!leave_loop) { + while (1) { struct timeval timeout, *timeout_p = NULL; if (!list_empty(&event_timeout_list)) { struct timeval now; @@ -284,13 +278,20 @@ int event_loop(void) maxfd = (entry->fd > maxfd) ? entry->fd : maxfd; } + /* exit loop if callback returns true */ + if (callback != NULL && callback(privdata) != 0) + break; + int i = select(maxfd +1, readfds, writefds, NULL, timeout_p); - if (i <= 0) { - /* On error, -1 is returned, and errno is set - * appropriately; the sets and timeout become - * undefined, so do not rely on their contents - * after an error. - */ + if (i < 0 && errno == EINTR) { + errno = 0; + continue; + + } else if (i < 0) { + log_print(LOG_ERROR, "event_loop(): select():"); + continue; + + } else if (i == 0) { continue; } diff --git a/event.h b/event.h index 0413b86..cb8b0d4 100644 --- a/event.h +++ b/event.h @@ -37,7 +37,6 @@ struct event_timeout * event_add_timeout( void event_remove_timeout(struct event_timeout *entry); -void event_loop_break(void); -int event_loop(void); +int event_loop(int (*callback)(void *privdata), void *privdata); #endif /* _EVENT_H_ */ diff --git a/linebuffer.c b/linebuffer.c new file mode 100644 index 0000000..b6b210b --- /dev/null +++ b/linebuffer.c @@ -0,0 +1,239 @@ +/*************************************************************************** + * Copyright (C) 03/2010 by Olaf Rempel * + * razzor@kopf-tisch.de * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; version 2 of the License * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include +#include + +#include "linebuffer.h" + +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) + +struct lbuf { + size_t size; + size_t pos; + + char *token; + char data[0]; +}; + +/* + * creates linebuffer with given size + */ +struct lbuf * lbuf_create(size_t size) +{ + struct lbuf *buf = malloc(sizeof(struct lbuf) + size); + if (buf == NULL) + return NULL; + + buf->size = size; + buf->pos = 0; + return buf; +} + +/* + * frees the linebuffer and all data in it + */ +void lbuf_free(struct lbuf *buf) +{ + free(buf); +} + +/* + * clears the linebuffer + * - returns the datasize it was holding + */ +int lbuf_clear(struct lbuf *buf) +{ + int oldpos = buf->pos; + buf->pos = 0; + return oldpos; +} + +/* + * get pointer to internal data + * - returns pointer to datasize + */ +char * lbuf_getdata(struct lbuf *buf, size_t *len) +{ + if (len != NULL) + *len = buf->pos; + + return buf->data; +} + +/* + * appends data to the buffer + * - returns the number of bytes copied + */ +int lbuf_append(struct lbuf *buf, const char *src, size_t size) +{ + int len = MIN(buf->size - buf->pos, size); + memcpy(buf->data + buf->pos, src, len); + buf->pos += len; + return len; +} + +/* + * reads as much data as it can get from a FD + * - returns the number of bytes read, or -1 on error + */ +int lbuf_readfd(struct lbuf *buf, int fd) +{ + int len = read(fd, buf->data + buf->pos, buf->size - buf->pos); + if (len <= 0) + return -1; + + buf->pos += len; + return len; +} + +/* + * parses as much data as it can get from a FD + * parses means: backspaces remove one byte from the end of the buffer + * - returns 0 on success, or -1 on error + */ +int lbuf_parsefd(struct lbuf *buf, int fd) +{ + char tmp[32]; + int len = read(fd, tmp, sizeof(tmp)); + if (len <= 0) + return -1; + + int i; + for (i = 0; i < len; i++) { + /* "understand" backspace */ + if (tmp[i] == 0x08 && buf->pos > 0) { + buf->pos--; + + /* copy */ + } else if (tmp[i] >= ' ' || tmp[i] == '\n') { + *(buf->data + buf->pos++) = tmp[i]; + } + + if (buf->pos > buf->size) + return -1; + } + /* TODO: return bytes appended to buffer? */ + return 0; +} + +/* + * writes as much data as it can to a FD + * - returns the number of bytes written, or -1 on error + */ +int lbuf_writefd(struct lbuf *buf, int fd) +{ + int len = write(fd, buf->data, buf->pos); + if (len <= 0) + return -1; + + /* handle partial writes */ + if (len != buf->pos) + memmove(buf->data, buf->data + len, buf->pos - len); + + buf->pos -= len; + return len; +} + +/* + * append va_list to buffer + * - returns number ob bytes appended, or -1 on error + */ +int lbuf_vprintf(struct lbuf *buf, const char *fmt, va_list az) +{ + int len = vsnprintf(buf->data + buf->pos, buf->size - buf->pos, fmt, az); + if (len < 0 || len >= (buf->size - buf->pos)) + return -1; + + buf->pos += len; + return len; +} + +/* + * printf into buffer + * - returns number of bytes appended, or -1 on error + */ +int lbuf_printf(struct lbuf *buf, const char *fmt, ...) +{ + va_list az; + + va_start(az, fmt); + int ret = lbuf_vprintf(buf, fmt, az); + va_end(az); + + return ret; +} + +/* + * get next non-empty token + * - returns pointer to next token + * - returns NULL if no delimter is found in buffer + */ +char * lbuf_gettok(struct lbuf *buf, const char *delim) +{ + char *start = buf->data; + char *end = buf->data + buf->pos; + int dlen = strlen(delim); + + while (1) { + buf->token = NULL; + + /* find first delimiter in buffer */ + int i; + for (i = 0; i < dlen; i++) { + char *tok = memchr(start, delim[i], end - start); + if (tok != NULL && (tok < buf->token || buf->token == NULL)) + buf->token = tok; + } + + /* nothing found */ + if (buf->token == NULL) + return NULL; + + /* delimter found on start pos -> skip empty token */ + if (buf->token == start) { + start++; + if (start >= end) + return NULL; + } else { + /* non-empty token found, exit */ + break; + } + } + + /* overwrite token, return start ptr */ + *(buf->token) = '\0'; + return start; +} + +/* + * release previous fetched line + * - returns number of remaining bytes in buffer + */ +int lbuf_freetok(struct lbuf *buf) +{ + if (buf->token != NULL) { + buf->pos -= (buf->token - buf->data) +1; + memmove(buf->data, buf->token +1, buf->pos); + buf->token = NULL; + } + return buf->pos; +} diff --git a/linebuffer.h b/linebuffer.h new file mode 100644 index 0000000..12d6d03 --- /dev/null +++ b/linebuffer.h @@ -0,0 +1,27 @@ +#ifndef _LINEBUFFER_H_ +#define _LINEBUFFER_H_ + +#include + +/* hide details */ +struct lbuf; + +struct lbuf * lbuf_create(size_t size); +void lbuf_free(struct lbuf *buf); + +int lbuf_clear(struct lbuf *buf); + +int lbuf_readfd(struct lbuf *buf, int fd); +int lbuf_parsefd(struct lbuf *buf, int fd); +int lbuf_writefd(struct lbuf *buf, int fd); + +char * lbuf_getdata(struct lbuf *buf, size_t *len); + +int lbuf_append(struct lbuf *buf, const char *src, size_t size); +int lbuf_vprintf(struct lbuf *buf, const char *fmt, va_list ap); +int lbuf_printf(struct lbuf *buf, const char *fmt, ...); + +char * lbuf_gettok(struct lbuf *buf, const char *delim); +int lbuf_freetok(struct lbuf *buf); + +#endif /* _LINEBUFFER_H_ */ diff --git a/pidfile.c b/pidfile.c index 9de2d3d..f5dd0be 100644 --- a/pidfile.c +++ b/pidfile.c @@ -44,6 +44,8 @@ pid_t pidfile_check(const char *filename, int remove_stale) int len = read(fd, buf, sizeof(buf) -1); buf[len] = '\0'; + close(fd); + char *tmp; pid_t pid = strtol(buf, &tmp, 10); if (len == 0 || tmp == buf) diff --git a/plugins/apache.c b/plugins/apache.c index a460586..c174348 100644 --- a/plugins/apache.c +++ b/plugins/apache.c @@ -26,6 +26,7 @@ #include "configfile.h" #include "helper.h" +#include "linebuffer.h" #include "list.h" #include "logging.h" #include "plugins.h" @@ -57,8 +58,7 @@ struct stats { uint64_t idle_workers; }; -static char *rx_buf; -static int rx_pos; +static struct lbuf * rxbuf; static const char * get_ds(int ds_id) { @@ -69,13 +69,8 @@ static size_t curl_callback(void *buffer, size_t size, size_t nmemb, void *userp { size_t realsize = size * nmemb; - // discard data - if (rx_pos + realsize >= BUFSIZE) - return realsize; + lbuf_append(rxbuf, buffer, realsize); - memcpy(rx_buf + rx_pos, buffer, realsize); - - rx_pos += realsize; return realsize; } @@ -83,14 +78,19 @@ static int probe(void) { struct server_entry *entry; list_for_each_entry(entry, &server_list, list) { - rx_pos = 0; - curl_easy_perform(entry->handle); + lbuf_clear(rxbuf); + + int ret = curl_easy_perform(entry->handle); + if (ret != 0) { + log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret)); + continue; + } struct stats stats; memset(&stats, 0, sizeof(stats)); - char *line, *tmp = rx_buf, *tmp2; - while ((line = strtok_r(tmp, "\r\n", &tmp2))) { + char *line; + while ((line = lbuf_gettok(rxbuf, "\r\n")) != NULL) { char *part[2]; strsplit(line, ":", part, 2); @@ -106,7 +106,7 @@ static int probe(void) else if (!strcmp(part[0], "IdleWorkers") || !strcmp(part[0], "IdleServers")) stats.idle_workers = atoll(part[1]); - tmp = NULL; + lbuf_freetok(rxbuf); } char filename[32]; @@ -121,12 +121,10 @@ static int probe(void) return 0; } -static int init_cb(const char *parameter, void *privdata) +static int init_cb(struct strtoken *tokens, void *privdata) { - char *part[4]; - int ret = strsplit(parameter, ",", part, 4); - if (ret < 2) { - log_print(LOG_ERROR, "p_apache: parse error (1)"); + if (tokens->count < 2) { + log_print(LOG_ERROR, "p_apache: parse error"); return -1; } @@ -136,8 +134,7 @@ static int init_cb(const char *parameter, void *privdata) return -1; } - // reference config mem - entry->name = part[0]; + entry->name = strdup(tokens->field[0]); entry->handle = curl_easy_init(); if (entry->handle == NULL) { @@ -145,7 +142,8 @@ static int init_cb(const char *parameter, void *privdata) return -1; } - ret = curl_easy_setopt(entry->handle, CURLOPT_URL, part[1]); + /* set URL */ + int ret = curl_easy_setopt(entry->handle, CURLOPT_URL, tokens->field[1]); if (ret != 0) { log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret)); curl_easy_cleanup(entry->handle); @@ -153,12 +151,13 @@ static int init_cb(const char *parameter, void *privdata) return -1; } - if (part[2] != NULL && part[3] != NULL) { - *(part[3] -1) = ':'; + if (tokens->field[2] != NULL && tokens->field[3] != NULL) { + *(tokens->field[3] -1) = ':'; - log_print(LOG_INFO, "p_apache: auth: '%s'", part[2]); + log_print(LOG_INFO, "p_apache: auth: '%s'", tokens->field[2]); - ret = curl_easy_setopt(entry->handle, CURLOPT_USERPWD, part[2]); + /* set username:password */ + ret = curl_easy_setopt(entry->handle, CURLOPT_USERPWD, tokens->field[2]); if (ret != 0) { log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret)); curl_easy_cleanup(entry->handle); @@ -191,13 +190,13 @@ static int init_cb(const char *parameter, void *privdata) static int init(void) { - rx_buf = malloc(BUFSIZE); - if (rx_buf == NULL) { + rxbuf = lbuf_create(BUFSIZE); + if (rxbuf == NULL) { log_print(LOG_ERROR, "p_apache: out of memory"); return -1; } - config_get_strings("p_apache", "server", init_cb, NULL); + config_get_strtokens("p_apache", "server", ",", 4, init_cb, NULL); return 0; } @@ -206,10 +205,11 @@ static int fini(void) struct server_entry *entry, *tmp; list_for_each_entry_safe(entry, tmp, &server_list, list) { curl_easy_cleanup(entry->handle); + free(entry->name); free(entry); } - free(rx_buf); + lbuf_free(rxbuf); return 0; } diff --git a/plugins/hwmon.c b/plugins/hwmon.c index c64fe80..0e2d455 100644 --- a/plugins/hwmon.c +++ b/plugins/hwmon.c @@ -75,11 +75,9 @@ static int probe(void) return 0; } -static int init_cb(const char *parameter, void *privdata) +static int init_cb(struct strtoken *tokens, void *privdata) { - char *part[2]; - int ret = strsplit(parameter, ",", part, 2); - if (ret != 2) { + if (tokens->count != 2) { log_print(LOG_ERROR, "p_hwmon: parse error"); return -1; } @@ -90,8 +88,8 @@ static int init_cb(const char *parameter, void *privdata) return -1; } - entry->name = part[0]; - entry->path = part[1]; + entry->name = strdup(tokens->field[0]); + entry->path = strdup(tokens->field[1]); log_print(LOG_DEBUG, "p_hwmon: added sensor '%s' (%s)", entry->name, entry->path); list_add_tail(&entry->list, &hwmon_list); @@ -101,15 +99,18 @@ static int init_cb(const char *parameter, void *privdata) static int init(void) { - config_get_strings("p_hwmon", "temp", init_cb, NULL); + config_get_strtokens("p_hwmon", "temp", ",", 2, init_cb, NULL); return 0; } static int fini(void) { struct hwmon_entry *entry, *tmp; - list_for_each_entry_safe(entry, tmp, &hwmon_list, list) + list_for_each_entry_safe(entry, tmp, &hwmon_list, list) { + free(entry->name); + free(entry->path); free(entry); + } return 0; } diff --git a/plugins/mysql.c b/plugins/mysql.c index 42c7ae5..05ffa36 100644 --- a/plugins/mysql.c +++ b/plugins/mysql.c @@ -150,18 +150,17 @@ static int probe(void) return 0; } -static int init_cb(const char *parameter, void *privdata) +static int init_cb(struct strtoken *tokens, void *privdata) { - char *part[4]; - int ret = strsplit(parameter, ",", part, 4); - if (ret != 4) { + if (tokens->count != 4) { log_print(LOG_ERROR, "p_mysql: parse error"); return -1; } - void *mysql = init_connection(part[1], part[2], part[3]); - if (mysql == NULL) + void *mysql = init_connection(tokens->field[1], tokens->field[2], tokens->field[3]); + if (mysql == NULL) { return -1; + } struct server_entry *entry = malloc(sizeof(struct server_entry)); if (entry == NULL) { @@ -170,7 +169,7 @@ static int init_cb(const char *parameter, void *privdata) return -1; } - entry->name = part[0]; + entry->name = strdup(tokens->field[0]); entry->mysql = mysql; log_print(LOG_DEBUG, "p_mysql: added server '%s'", entry->name); @@ -180,7 +179,7 @@ static int init_cb(const char *parameter, void *privdata) static int init(void) { - config_get_strings("p_mysql", "server", init_cb, NULL); + config_get_strtokens("p_mysql", "server", ",", 4, init_cb, NULL); return 0; } @@ -189,6 +188,7 @@ static int fini(void) struct server_entry *entry, *tmp; list_for_each_entry_safe(entry, tmp, &server_list, list) { close_connection(entry->mysql); + free(entry->name); free(entry); } return 0; diff --git a/plugins/ts2.c b/plugins/ts2.c index a8f95da..3513ea4 100644 --- a/plugins/ts2.c +++ b/plugins/ts2.c @@ -151,11 +151,9 @@ static int probe(void) return 0; } -static int init_cb(const char *parameter, void *privdata) +static int init_cb(struct strtoken *tokens, void *privdata) { - char *part[2]; - int ret = strsplit((char *)parameter, ",", part, 2); - if (ret < 2) { + if (tokens->count != 2) { log_print(LOG_ERROR, "p_ts2: parse error"); return -1; } @@ -166,11 +164,11 @@ static int init_cb(const char *parameter, void *privdata) return -1; } - entry->name = strdup(part[0]); + entry->name = strdup(tokens->field[0]); entry->errors = 0; - if (parse_sockaddr((char *)part[1], &entry->sa) < 0) { - log_print(LOG_ERROR, "p_ts2: invalid address: <%s>", part[1]); + if (parse_sockaddr(tokens->field[1], &entry->sa) < 0) { + log_print(LOG_ERROR, "p_ts2: invalid address: <%s>", tokens->field[1]); free(entry->name); free(entry); return -1; @@ -189,7 +187,7 @@ static int init(void) return -1; } - config_get_strings("p_ts2", "server", init_cb, NULL); + config_get_strtokens("p_ts2", "server", ",", 2, init_cb, NULL); return 0; } diff --git a/rrdtool.c b/rrdtool.c index ce27eb5..9293f42 100644 --- a/rrdtool.c +++ b/rrdtool.c @@ -28,6 +28,7 @@ #include "configfile.h" #include "helper.h" +#include "linebuffer.h" #include "list.h" #include "logging.h" #include "plugins.h" @@ -38,12 +39,6 @@ #define ARGVSIZE 1024 #define BUFSIZE 1024 -struct rra_cb_data { - char *buffer; - int size; - int *pos; -}; - static const char *rrd_dir; int sammler_rrd_init(void) @@ -54,20 +49,19 @@ int sammler_rrd_init(void) static int append_rra_config(const char *parameter, void *privdata) { - struct rra_cb_data *data = (struct rra_cb_data *)privdata; + struct lbuf *buffer = (struct lbuf *)privdata; - int len = snprintf(data->buffer + *(data->pos), data->size - *(data->pos), "%s ", parameter); - if (len < 0 || len >= data->size - *(data->pos)) { - log_print(LOG_ERROR, "append_rra_config_cb: arguments too long"); - return -1; - } - - *(data->pos) += len; + lbuf_printf(buffer, "%s ", parameter); return 0; } -static int do_rrd(int (*rrd_func)(int, char **), char *cmd) +static int do_rrd(int (*rrd_func)(int, char **), struct lbuf *buffer) { + size_t len; + char *cmd = lbuf_getdata(buffer, &len); + if (len < ARGVSIZE -1) + cmd[len] = '\0'; + char *argv[ARGCMAX]; int argc = strsplit(cmd, " \t\n", argv, ARGCMAX -1); argv[argc] = NULL; @@ -81,7 +75,6 @@ static int do_rrd(int (*rrd_func)(int, char **), char *cmd) log_print(LOG_ERROR, "rrd_func failed: %s: %s", argv[1], rrd_get_error()); } - free(cmd); return retval; } @@ -99,51 +92,48 @@ static int rrd_create_file(const char *filename, const char *pluginname, int ds_ return -1; } - char *buffer = malloc(ARGVSIZE); + struct lbuf *buffer = lbuf_create(ARGVSIZE); if (buffer == NULL) { log_print(LOG_ERROR, "rrd_create_file: out of memory"); return -1; } - int step = plugin->interval; - int pos = snprintf(buffer, ARGVSIZE, "create %s -s %d %s ", filename, step, ds_def); - if (pos < 0 || pos >= ARGVSIZE) { + int ret = lbuf_printf(buffer, "create %s -s %d %s ", filename, plugin->interval, ds_def); + if (ret == -1) { log_print(LOG_ERROR, "rrd_create_file: arguments too long"); - free(buffer); + lbuf_free(buffer); return -1; } - struct rra_cb_data data = { - .buffer = buffer, - .size = ARGVSIZE, - .pos = &pos, - }; - - int cnt = config_get_strings("global", "rra", append_rra_config, &data); - if (cnt <= 0) { - free(buffer); + ret = config_get_strings("global", "rra", append_rra_config, buffer); + if (ret <= 0) { + lbuf_free(buffer); return -1; } - return do_rrd(&rrd_create, buffer); + ret = do_rrd(&rrd_create, buffer); + lbuf_free(buffer); + return ret; } static int rrd_update_file(const char *filename, const char *values) { - char *buffer = malloc(ARGVSIZE); + struct lbuf *buffer = lbuf_create(ARGVSIZE); if (buffer == NULL) { log_print(LOG_ERROR, "append_ds_config: out of memory"); return -1; } - int pos = snprintf(buffer, ARGVSIZE, "update %s N:%s", filename, values); - if (pos < 0 || pos >= ARGVSIZE) { + int ret = lbuf_printf(buffer, "update %s N:%s", filename, values); + if (ret == -1) { log_print(LOG_ERROR, "rrd_update_file: arguments too long"); - free(buffer); + lbuf_free(buffer); return -1; } - return do_rrd(&rrd_update, buffer); + ret = do_rrd(&rrd_update, buffer); + lbuf_free(buffer); + return ret; } static int check_create_dir(const char *dir) diff --git a/sammler.c b/sammler.c index c84477d..0462684 100644 --- a/sammler.c +++ b/sammler.c @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 06/2006 by Olaf Rempel * + * Copyright (C) 03/2010 by Olaf Rempel * * razzor@kopf-tisch.de * * * * This program is free software; you can redistribute it and/or modify * @@ -48,6 +48,25 @@ static struct option opts[] = { {0, 0, 0, 0} }; +static int restart_var; + +static void trigger_restart(void *privdata) +{ + int *restart = (int *)privdata; + *restart = 1; +} + +static int check_restart(void *privdata) +{ + int *restart = (int *)privdata; + if (*restart == 1) { + *restart = 0; + return 1; + } + + return 0; +} + int main(int argc, char *argv[]) { char *config = DEFAULT_CONFIG; @@ -102,7 +121,10 @@ int main(int argc, char *argv[]) exit(1); /* zum daemon mutieren */ - daemon(-1, 0); + if (daemon(-1, 0) < 0) { + log_print(LOG_ERROR, "failed to daemonize"); + exit(1); + } /* create pidfile */ if (pidfile_create(pidfile) < 0) { @@ -112,7 +134,7 @@ int main(int argc, char *argv[]) } signal_init(); - signal_set_callback(SIGHUP, event_loop_break); + signal_add_callback(SIGHUP, trigger_restart, (void *)&restart_var); log_print(LOG_EVERYTIME, "sammler started (pid:%d)", getpid()); @@ -130,7 +152,7 @@ int main(int argc, char *argv[]) break; /* exited on restart / SIGUSR1 */ - event_loop(); + event_loop(check_restart, (void *)&restart_var); plugin_close(); diff --git a/signals.c b/signals.c index f640a3b..4ae7176 100644 --- a/signals.c +++ b/signals.c @@ -32,7 +32,8 @@ struct signal_entry { int signum; int deleted; - void (*callback)(void); + void (*callback)(void *privdata); + void *privdata; }; static LIST_HEAD(callback_list); @@ -76,7 +77,7 @@ int signal_remove_callback(int signum, int type) return 0; } -int signal_set_callback(int signum, void (*callback)(void)) +int signal_add_callback(int signum, void (*callback)(void *privdata), void *privdata) { struct signal_entry *entry = malloc(sizeof(struct signal_entry)); if (entry == NULL) { @@ -87,6 +88,7 @@ int signal_set_callback(int signum, void (*callback)(void)) entry->signum = signum; entry->deleted = 0; entry->callback = callback; + entry->privdata = privdata; list_add_tail(&entry->list, &callback_list); struct sigaction sig_action = { @@ -121,7 +123,7 @@ static int sig_event(int fd, void *privdata) } if (search->signum == signum) - search->callback(); + search->callback(search->privdata); } return 0; diff --git a/signals.h b/signals.h index f2c8a06..3a9cc16 100644 --- a/signals.h +++ b/signals.h @@ -5,7 +5,7 @@ #define SIG_IGNORE 0x01 int signal_remove_callback(int signum, int type); -int signal_set_callback(int signum, void (*callback)(void)); +int signal_add_callback(int signum, void (*callback)(void *privdata), void *privdata); int signal_init(void);