*/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
-#include "configfile.h"
-
#include <stddef.h>
-#if HAVE_LIBPTHREAD
-# include <pthread.h>
-#endif
-
-#include <sys/un.h>
#include <sys/select.h>
+#include <sys/un.h>
/* some systems (e.g. Darwin) seem to not define UNIX_PATH_MAX at all */
#ifndef UNIX_PATH_MAX
-# define UNIX_PATH_MAX sizeof (((struct sockaddr_un *)0)->sun_path)
+#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *)0)->sun_path)
#endif /* UNIX_PATH_MAX */
#if HAVE_GRP_H
-# include <grp.h>
+#include <grp.h>
#endif /* HAVE_GRP_H */
-#define SOCK_PATH LOCALSTATEDIR"/run/"PACKAGE_NAME"-email"
+#define SOCK_PATH LOCALSTATEDIR "/run/" PACKAGE_NAME "-email"
#define MAX_CONNS 5
#define MAX_CONNS_LIMIT 16384
-#define log_debug(...) DEBUG ("email: "__VA_ARGS__)
-#define log_err(...) ERROR ("email: "__VA_ARGS__)
-#define log_warn(...) WARNING ("email: "__VA_ARGS__)
+#define log_debug(...) DEBUG("email: "__VA_ARGS__)
+#define log_err(...) ERROR("email: "__VA_ARGS__)
+#define log_warn(...) WARNING("email: "__VA_ARGS__)
/*
* Private data structures
*/
/* linked list of email and check types */
typedef struct type {
- char *name;
- int value;
- struct type *next;
+ char *name;
+ int value;
+ struct type *next;
} type_t;
typedef struct {
- type_t *head;
- type_t *tail;
+ type_t *head;
+ type_t *tail;
} type_list_t;
/* collector thread control information */
typedef struct collector {
- pthread_t thread;
+ pthread_t thread;
- /* socket descriptor of the current/last connection */
- FILE *socket;
+ /* socket descriptor of the current/last connection */
+ FILE *socket;
} collector_t;
/* linked list of pending connections */
typedef struct conn {
- /* socket to read data from */
- FILE *socket;
+ /* socket to read data from */
+ FILE *socket;
- /* linked list of connections */
- struct conn *next;
+ /* linked list of connections */
+ struct conn *next;
} conn_t;
typedef struct {
- conn_t *head;
- conn_t *tail;
+ conn_t *head;
+ conn_t *tail;
} conn_list_t;
/*
* Private variables
*/
/* valid configuration file keys */
-static const char *config_keys[] =
-{
- "SocketFile",
- "SocketGroup",
- "SocketPerms",
- "MaxConns"
-};
-static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+static const char *config_keys[] = {"SocketFile", "SocketGroup", "SocketPerms",
+ "MaxConns"};
+static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
/* socket configuration */
-static char *sock_file = NULL;
+static char *sock_file = NULL;
static char *sock_group = NULL;
-static int sock_perms = S_IRWXU | S_IRWXG;
-static int max_conns = MAX_CONNS;
+static int sock_perms = S_IRWXU | S_IRWXG;
+static int max_conns = MAX_CONNS;
/* state of the plugin */
static int disabled = 0;
/* thread managing "client" connections */
-static pthread_t connector = (pthread_t) 0;
+static pthread_t connector = (pthread_t)0;
static int connector_socket = -1;
/* tell the collector threads that a new connection is available */
/*
* Private functions
*/
-static int email_config (const char *key, const char *value)
-{
- if (0 == strcasecmp (key, "SocketFile")) {
- if (NULL != sock_file)
- free (sock_file);
- sock_file = sstrdup (value);
- }
- else if (0 == strcasecmp (key, "SocketGroup")) {
- if (NULL != sock_group)
- free (sock_group);
- sock_group = sstrdup (value);
- }
- else if (0 == strcasecmp (key, "SocketPerms")) {
- /* the user is responsible for providing reasonable values */
- sock_perms = (int)strtol (value, NULL, 8);
- }
- else if (0 == strcasecmp (key, "MaxConns")) {
- long int tmp = strtol (value, NULL, 0);
-
- if (tmp < 1) {
- fprintf (stderr, "email plugin: `MaxConns' was set to invalid "
- "value %li, will use default %i.\n",
- tmp, MAX_CONNS);
- ERROR ("email plugin: `MaxConns' was set to invalid "
- "value %li, will use default %i.\n",
- tmp, MAX_CONNS);
- max_conns = MAX_CONNS;
- }
- else if (tmp > MAX_CONNS_LIMIT) {
- fprintf (stderr, "email plugin: `MaxConns' was set to invalid "
- "value %li, will use hardcoded limit %i.\n",
- tmp, MAX_CONNS_LIMIT);
- ERROR ("email plugin: `MaxConns' was set to invalid "
- "value %li, will use hardcoded limit %i.\n",
- tmp, MAX_CONNS_LIMIT);
- max_conns = MAX_CONNS_LIMIT;
- }
- else {
- max_conns = (int)tmp;
- }
- }
- else {
- return -1;
- }
- return 0;
+static int email_config(const char *key, const char *value) {
+ if (0 == strcasecmp(key, "SocketFile")) {
+ if (NULL != sock_file)
+ free(sock_file);
+ sock_file = sstrdup(value);
+ } else if (0 == strcasecmp(key, "SocketGroup")) {
+ if (NULL != sock_group)
+ free(sock_group);
+ sock_group = sstrdup(value);
+ } else if (0 == strcasecmp(key, "SocketPerms")) {
+ /* the user is responsible for providing reasonable values */
+ sock_perms = (int)strtol(value, NULL, 8);
+ } else if (0 == strcasecmp(key, "MaxConns")) {
+ long int tmp = strtol(value, NULL, 0);
+
+ if (tmp < 1) {
+ fprintf(stderr, "email plugin: `MaxConns' was set to invalid "
+ "value %li, will use default %i.\n",
+ tmp, MAX_CONNS);
+ ERROR("email plugin: `MaxConns' was set to invalid "
+ "value %li, will use default %i.\n",
+ tmp, MAX_CONNS);
+ max_conns = MAX_CONNS;
+ } else if (tmp > MAX_CONNS_LIMIT) {
+ fprintf(stderr, "email plugin: `MaxConns' was set to invalid "
+ "value %li, will use hardcoded limit %i.\n",
+ tmp, MAX_CONNS_LIMIT);
+ ERROR("email plugin: `MaxConns' was set to invalid "
+ "value %li, will use hardcoded limit %i.\n",
+ tmp, MAX_CONNS_LIMIT);
+ max_conns = MAX_CONNS_LIMIT;
+ } else {
+ max_conns = (int)tmp;
+ }
+ } else {
+ return -1;
+ }
+ return 0;
} /* static int email_config (char *, char *) */
/* Increment the value of the given name in the given list by incr. */
-static void type_list_incr (type_list_t *list, char *name, int incr)
-{
- if (NULL == list->head) {
- list->head = smalloc (sizeof (*list->head));
-
- list->head->name = sstrdup (name);
- list->head->value = incr;
- list->head->next = NULL;
-
- list->tail = list->head;
- }
- else {
- type_t *ptr;
-
- for (ptr = list->head; NULL != ptr; ptr = ptr->next) {
- if (0 == strcmp (name, ptr->name))
- break;
- }
-
- if (NULL == ptr) {
- list->tail->next = smalloc (sizeof (*list->tail->next));
- list->tail = list->tail->next;
-
- list->tail->name = sstrdup (name);
- list->tail->value = incr;
- list->tail->next = NULL;
- }
- else {
- ptr->value += incr;
- }
- }
- return;
+static void type_list_incr(type_list_t *list, char *name, int incr) {
+ if (NULL == list->head) {
+ list->head = smalloc(sizeof(*list->head));
+
+ list->head->name = sstrdup(name);
+ list->head->value = incr;
+ list->head->next = NULL;
+
+ list->tail = list->head;
+ } else {
+ type_t *ptr;
+
+ for (ptr = list->head; NULL != ptr; ptr = ptr->next) {
+ if (0 == strcmp(name, ptr->name))
+ break;
+ }
+
+ if (NULL == ptr) {
+ list->tail->next = smalloc(sizeof(*list->tail->next));
+ list->tail = list->tail->next;
+
+ list->tail->name = sstrdup(name);
+ list->tail->value = incr;
+ list->tail->next = NULL;
+ } else {
+ ptr->value += incr;
+ }
+ }
+ return;
} /* static void type_list_incr (type_list_t *, char *) */
-static void *collect (void *arg)
-{
- collector_t *this = (collector_t *)arg;
-
- while (1) {
- conn_t *connection;
-
- pthread_mutex_lock (&conns_mutex);
-
- while (NULL == conns.head) {
- pthread_cond_wait (&conn_available, &conns_mutex);
- }
-
- connection = conns.head;
- conns.head = conns.head->next;
-
- if (NULL == conns.head) {
- conns.tail = NULL;
- }
-
- pthread_mutex_unlock (&conns_mutex);
-
- /* make the socket available to the global
- * thread and connection management */
- this->socket = connection->socket;
-
- log_debug ("collect: handling connection on fd #%i",
- fileno (this->socket));
-
- while (42) {
- /* 256 bytes ought to be enough for anybody ;-) */
- char line[256 + 1]; /* line + '\0' */
- int len = 0;
-
- errno = 0;
- if (NULL == fgets (line, sizeof (line), this->socket)) {
- if (0 != errno) {
- char errbuf[1024];
- log_err ("collect: reading from socket (fd #%i) "
- "failed: %s", fileno (this->socket),
- sstrerror (errno, errbuf, sizeof (errbuf)));
- }
- break;
- }
-
- len = strlen (line);
- if (('\n' != line[len - 1]) && ('\r' != line[len - 1])) {
- log_warn ("collect: line too long (> %zu characters): "
- "'%s' (truncated)", sizeof (line) - 1, line);
-
- while (NULL != fgets (line, sizeof (line), this->socket))
- if (('\n' == line[len - 1]) || ('\r' == line[len - 1]))
- break;
- continue;
- }
- if (len < 3) { /* [a-z] ':' '\n' */
- continue;
- }
-
- line[len - 1] = 0;
-
- log_debug ("collect: line = '%s'", line);
-
- if (':' != line[1]) {
- log_err ("collect: syntax error in line '%s'", line);
- continue;
- }
-
- if ('e' == line[0]) { /* e:<type>:<bytes> */
- char *ptr = NULL;
- char *type = strtok_r (line + 2, ":", &ptr);
- char *tmp = strtok_r (NULL, ":", &ptr);
- int bytes = 0;
-
- if (NULL == tmp) {
- log_err ("collect: syntax error in line '%s'", line);
- continue;
- }
-
- bytes = atoi (tmp);
-
- pthread_mutex_lock (&count_mutex);
- type_list_incr (&list_count, type, /* increment = */ 1);
- pthread_mutex_unlock (&count_mutex);
-
- if (bytes > 0) {
- pthread_mutex_lock (&size_mutex);
- type_list_incr (&list_size, type, /* increment = */ bytes);
- pthread_mutex_unlock (&size_mutex);
- }
- }
- else if ('s' == line[0]) { /* s:<value> */
- pthread_mutex_lock (&score_mutex);
- score = (score * (double)score_count + atof (line + 2))
- / (double)(score_count + 1);
- ++score_count;
- pthread_mutex_unlock (&score_mutex);
- }
- else if ('c' == line[0]) { /* c:<type1>[,<type2>,...] */
- char *dummy = line + 2;
- char *endptr = NULL;
- char *type;
-
- pthread_mutex_lock (&check_mutex);
- while ((type = strtok_r (dummy, ",", &endptr)) != NULL)
- {
- dummy = NULL;
- type_list_incr (&list_check, type, /* increment = */ 1);
- }
- pthread_mutex_unlock (&check_mutex);
- }
- else {
- log_err ("collect: unknown type '%c'", line[0]);
- }
- } /* while (42) */
-
- log_debug ("Shutting down connection on fd #%i",
- fileno (this->socket));
-
- fclose (connection->socket);
- free (connection);
-
- this->socket = NULL;
-
- pthread_mutex_lock (&available_mutex);
- ++available_collectors;
- pthread_mutex_unlock (&available_mutex);
-
- pthread_cond_signal (&collector_available);
- } /* while (1) */
-
- pthread_exit ((void *)0);
- return ((void *) 0);
+static void *collect(void *arg) {
+ collector_t *this = (collector_t *)arg;
+
+ while (1) {
+ conn_t *connection;
+
+ pthread_mutex_lock(&conns_mutex);
+
+ while (NULL == conns.head) {
+ pthread_cond_wait(&conn_available, &conns_mutex);
+ }
+
+ connection = conns.head;
+ conns.head = conns.head->next;
+
+ if (NULL == conns.head) {
+ conns.tail = NULL;
+ }
+
+ pthread_mutex_unlock(&conns_mutex);
+
+ /* make the socket available to the global
+ * thread and connection management */
+ this->socket = connection->socket;
+
+ log_debug("collect: handling connection on fd #%i", fileno(this->socket));
+
+ while (42) {
+ /* 256 bytes ought to be enough for anybody ;-) */
+ char line[256 + 1]; /* line + '\0' */
+ int len = 0;
+
+ errno = 0;
+ if (NULL == fgets(line, sizeof(line), this->socket)) {
+ if (0 != errno) {
+ char errbuf[1024];
+ log_err("collect: reading from socket (fd #%i) "
+ "failed: %s",
+ fileno(this->socket),
+ sstrerror(errno, errbuf, sizeof(errbuf)));
+ }
+ break;
+ }
+
+ len = strlen(line);
+ if (('\n' != line[len - 1]) && ('\r' != line[len - 1])) {
+ log_warn("collect: line too long (> %zu characters): "
+ "'%s' (truncated)",
+ sizeof(line) - 1, line);
+
+ while (NULL != fgets(line, sizeof(line), this->socket))
+ if (('\n' == line[len - 1]) || ('\r' == line[len - 1]))
+ break;
+ continue;
+ }
+ if (len < 3) { /* [a-z] ':' '\n' */
+ continue;
+ }
+
+ line[len - 1] = 0;
+
+ log_debug("collect: line = '%s'", line);
+
+ if (':' != line[1]) {
+ log_err("collect: syntax error in line '%s'", line);
+ continue;
+ }
+
+ if ('e' == line[0]) { /* e:<type>:<bytes> */
+ char *ptr = NULL;
+ char *type = strtok_r(line + 2, ":", &ptr);
+ char *tmp = strtok_r(NULL, ":", &ptr);
+ int bytes = 0;
+
+ if (NULL == tmp) {
+ log_err("collect: syntax error in line '%s'", line);
+ continue;
+ }
+
+ bytes = atoi(tmp);
+
+ pthread_mutex_lock(&count_mutex);
+ type_list_incr(&list_count, type, /* increment = */ 1);
+ pthread_mutex_unlock(&count_mutex);
+
+ if (bytes > 0) {
+ pthread_mutex_lock(&size_mutex);
+ type_list_incr(&list_size, type, /* increment = */ bytes);
+ pthread_mutex_unlock(&size_mutex);
+ }
+ } else if ('s' == line[0]) { /* s:<value> */
+ pthread_mutex_lock(&score_mutex);
+ score = (score * (double)score_count + atof(line + 2)) /
+ (double)(score_count + 1);
+ ++score_count;
+ pthread_mutex_unlock(&score_mutex);
+ } else if ('c' == line[0]) { /* c:<type1>[,<type2>,...] */
+ char *dummy = line + 2;
+ char *endptr = NULL;
+ char *type;
+
+ pthread_mutex_lock(&check_mutex);
+ while ((type = strtok_r(dummy, ",", &endptr)) != NULL) {
+ dummy = NULL;
+ type_list_incr(&list_check, type, /* increment = */ 1);
+ }
+ pthread_mutex_unlock(&check_mutex);
+ } else {
+ log_err("collect: unknown type '%c'", line[0]);
+ }
+ } /* while (42) */
+
+ log_debug("Shutting down connection on fd #%i", fileno(this->socket));
+
+ fclose(connection->socket);
+ free(connection);
+
+ this->socket = NULL;
+
+ pthread_mutex_lock(&available_mutex);
+ ++available_collectors;
+ pthread_mutex_unlock(&available_mutex);
+
+ pthread_cond_signal(&collector_available);
+ } /* while (1) */
+
+ pthread_exit((void *)0);
+ return ((void *)0);
} /* static void *collect (void *) */
-static void *open_connection (void __attribute__((unused)) *arg)
-{
- struct sockaddr_un addr;
-
- const char *path = (NULL == sock_file) ? SOCK_PATH : sock_file;
- const char *group = (NULL == sock_group) ? COLLECTD_GRP_NAME : sock_group;
-
- /* create UNIX socket */
- errno = 0;
- if (-1 == (connector_socket = socket (PF_UNIX, SOCK_STREAM, 0))) {
- char errbuf[1024];
- disabled = 1;
- log_err ("socket() failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- pthread_exit ((void *)1);
- }
-
- addr.sun_family = AF_UNIX;
- sstrncpy (addr.sun_path, path, (size_t)(UNIX_PATH_MAX - 1));
-
- errno = 0;
- if (-1 == bind (connector_socket, (struct sockaddr *)&addr,
- offsetof (struct sockaddr_un, sun_path)
- + strlen(addr.sun_path))) {
- char errbuf[1024];
- disabled = 1;
- close (connector_socket);
- connector_socket = -1;
- log_err ("bind() failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- pthread_exit ((void *)1);
- }
-
- errno = 0;
- if (-1 == listen (connector_socket, 5)) {
- char errbuf[1024];
- disabled = 1;
- close (connector_socket);
- connector_socket = -1;
- log_err ("listen() failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- pthread_exit ((void *)1);
- }
-
- {
- struct group sg;
- struct group *grp;
- char grbuf[2048];
- int status;
-
- grp = NULL;
- status = getgrnam_r (group, &sg, grbuf, sizeof (grbuf), &grp);
- if (status != 0)
- {
- char errbuf[1024];
- log_warn ("getgrnam_r (%s) failed: %s", group,
- sstrerror (errno, errbuf, sizeof (errbuf)));
- }
- else if (grp == NULL)
- {
- log_warn ("No such group: `%s'", group);
- }
- else
- {
- status = chown (path, (uid_t) -1, grp->gr_gid);
- if (status != 0)
- {
- char errbuf[1024];
- log_warn ("chown (%s, -1, %i) failed: %s",
- path, (int) grp->gr_gid,
- sstrerror (errno, errbuf, sizeof (errbuf)));
- }
- }
- }
-
- errno = 0;
- if (0 != chmod (path, sock_perms)) {
- char errbuf[1024];
- log_warn ("chmod() failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- }
-
- { /* initialize collector threads */
- int i = 0;
- int err = 0;
-
- pthread_attr_t ptattr;
-
- conns.head = NULL;
- conns.tail = NULL;
-
- pthread_attr_init (&ptattr);
- pthread_attr_setdetachstate (&ptattr, PTHREAD_CREATE_DETACHED);
-
- available_collectors = max_conns;
-
- collectors =
- smalloc (max_conns * sizeof (*collectors));
-
- for (i = 0; i < max_conns; ++i) {
- collectors[i] = smalloc (sizeof (*collectors[i]));
- collectors[i]->socket = NULL;
-
- if (0 != (err = plugin_thread_create (&collectors[i]->thread,
- &ptattr, collect, collectors[i]))) {
- char errbuf[1024];
- log_err ("pthread_create() failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- collectors[i]->thread = (pthread_t) 0;
- }
- }
-
- pthread_attr_destroy (&ptattr);
- }
-
- while (1) {
- int remote = 0;
-
- conn_t *connection;
-
- pthread_mutex_lock (&available_mutex);
-
- while (0 == available_collectors) {
- pthread_cond_wait (&collector_available, &available_mutex);
- }
-
- --available_collectors;
-
- pthread_mutex_unlock (&available_mutex);
-
- while (42) {
- errno = 0;
-
- remote = accept (connector_socket, NULL, NULL);
- if (remote == -1) {
- char errbuf[1024];
-
- if (errno == EINTR)
- continue;
-
- disabled = 1;
- close (connector_socket);
- connector_socket = -1;
- log_err ("accept() failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- pthread_exit ((void *)1);
- }
-
- /* access() succeeded. */
- break;
- }
-
- connection = malloc (sizeof (*connection));
- if (connection == NULL)
- {
- close (remote);
- continue;
- }
- memset (connection, 0, sizeof (*connection));
-
- connection->socket = fdopen (remote, "r");
- connection->next = NULL;
-
- if (NULL == connection->socket) {
- close (remote);
- sfree (connection);
- continue;
- }
-
- pthread_mutex_lock (&conns_mutex);
+static void *open_connection(void __attribute__((unused)) * arg) {
+ const char *path = (NULL == sock_file) ? SOCK_PATH : sock_file;
+ const char *group = (NULL == sock_group) ? COLLECTD_GRP_NAME : sock_group;
+
+ /* create UNIX socket */
+ errno = 0;
+ if (-1 == (connector_socket = socket(PF_UNIX, SOCK_STREAM, 0))) {
+ char errbuf[1024];
+ disabled = 1;
+ log_err("socket() failed: %s", sstrerror(errno, errbuf, sizeof(errbuf)));
+ pthread_exit((void *)1);
+ }
+
+ struct sockaddr_un addr = {
+ .sun_family = AF_UNIX
+ };
+ sstrncpy(addr.sun_path, path, (size_t)(UNIX_PATH_MAX - 1));
+
+ errno = 0;
+ if (-1 ==
+ bind(connector_socket, (struct sockaddr *)&addr,
+ offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path))) {
+ char errbuf[1024];
+ disabled = 1;
+ close(connector_socket);
+ connector_socket = -1;
+ log_err("bind() failed: %s", sstrerror(errno, errbuf, sizeof(errbuf)));
+ pthread_exit((void *)1);
+ }
+
+ errno = 0;
+ if (-1 == listen(connector_socket, 5)) {
+ char errbuf[1024];
+ disabled = 1;
+ close(connector_socket);
+ connector_socket = -1;
+ log_err("listen() failed: %s", sstrerror(errno, errbuf, sizeof(errbuf)));
+ pthread_exit((void *)1);
+ }
+
+ {
+ struct group sg;
+ struct group *grp;
+ int status;
+
+ long int grbuf_size = sysconf(_SC_GETGR_R_SIZE_MAX);
+ if (grbuf_size <= 0)
+ grbuf_size = sysconf(_SC_PAGESIZE);
+ if (grbuf_size <= 0)
+ grbuf_size = 4096;
+ char grbuf[grbuf_size];
+
+ grp = NULL;
+ status = getgrnam_r(group, &sg, grbuf, sizeof(grbuf), &grp);
+ if (status != 0) {
+ char errbuf[1024];
+ log_warn("getgrnam_r (%s) failed: %s", group,
+ sstrerror(status, errbuf, sizeof(errbuf)));
+ } else if (grp == NULL) {
+ log_warn("No such group: `%s'", group);
+ } else {
+ status = chown(path, (uid_t)-1, grp->gr_gid);
+ if (status != 0) {
+ char errbuf[1024];
+ log_warn("chown (%s, -1, %i) failed: %s", path, (int)grp->gr_gid,
+ sstrerror(errno, errbuf, sizeof(errbuf)));
+ }
+ }
+ }
+
+ errno = 0;
+ if (0 != chmod(path, sock_perms)) {
+ char errbuf[1024];
+ log_warn("chmod() failed: %s", sstrerror(errno, errbuf, sizeof(errbuf)));
+ }
+
+ { /* initialize collector threads */
+ pthread_attr_t ptattr;
+
+ conns.head = NULL;
+ conns.tail = NULL;
+
+ pthread_attr_init(&ptattr);
+ pthread_attr_setdetachstate(&ptattr, PTHREAD_CREATE_DETACHED);
+
+ available_collectors = max_conns;
+
+ collectors = smalloc(max_conns * sizeof(*collectors));
+
+ for (int i = 0; i < max_conns; ++i) {
+ collectors[i] = smalloc(sizeof(*collectors[i]));
+ collectors[i]->socket = NULL;
+
+ if (plugin_thread_create(&collectors[i]->thread, &ptattr, collect,
+ collectors[i], "email collector") != 0) {
+ char errbuf[1024];
+ log_err("plugin_thread_create() failed: %s",
+ sstrerror(errno, errbuf, sizeof(errbuf)));
+ collectors[i]->thread = (pthread_t)0;
+ }
+ }
+
+ pthread_attr_destroy(&ptattr);
+ }
+
+ while (1) {
+ int remote = 0;
+
+ conn_t *connection;
+
+ pthread_mutex_lock(&available_mutex);
+
+ while (0 == available_collectors) {
+ pthread_cond_wait(&collector_available, &available_mutex);
+ }
+
+ --available_collectors;
+
+ pthread_mutex_unlock(&available_mutex);
+
+ while (42) {
+ errno = 0;
+
+ remote = accept(connector_socket, NULL, NULL);
+ if (remote == -1) {
+ char errbuf[1024];
+
+ if (errno == EINTR)
+ continue;
+
+ disabled = 1;
+ close(connector_socket);
+ connector_socket = -1;
+ log_err("accept() failed: %s",
+ sstrerror(errno, errbuf, sizeof(errbuf)));
+ pthread_exit((void *)1);
+ }
+
+ /* access() succeeded. */
+ break;
+ }
+
+ connection = calloc(1, sizeof(*connection));
+ if (connection == NULL) {
+ close(remote);
+ continue;
+ }
+
+ connection->socket = fdopen(remote, "r");
+ connection->next = NULL;
+
+ if (NULL == connection->socket) {
+ close(remote);
+ sfree(connection);
+ continue;
+ }
+
+ pthread_mutex_lock(&conns_mutex);
+
+ if (NULL == conns.head) {
+ conns.head = connection;
+ conns.tail = connection;
+ } else {
+ conns.tail->next = connection;
+ conns.tail = conns.tail->next;
+ }
- if (NULL == conns.head) {
- conns.head = connection;
- conns.tail = connection;
- }
- else {
- conns.tail->next = connection;
- conns.tail = conns.tail->next;
- }
+ pthread_mutex_unlock(&conns_mutex);
- pthread_mutex_unlock (&conns_mutex);
+ pthread_cond_signal(&conn_available);
+ }
- pthread_cond_signal (&conn_available);
- }
-
- pthread_exit ((void *) 0);
- return ((void *) 0);
+ pthread_exit((void *)0);
+ return ((void *)0);
} /* static void *open_connection (void *) */
-static int email_init (void)
-{
- int err = 0;
-
- if (0 != (err = plugin_thread_create (&connector, NULL,
- open_connection, NULL))) {
- char errbuf[1024];
- disabled = 1;
- log_err ("pthread_create() failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- return (-1);
- }
-
- return (0);
+static int email_init(void) {
+ if (plugin_thread_create(&connector, NULL, open_connection, NULL,
+ "email listener") != 0) {
+ char errbuf[1024];
+ disabled = 1;
+ log_err("plugin_thread_create() failed: %s",
+ sstrerror(errno, errbuf, sizeof(errbuf)));
+ return (-1);
+ }
+
+ return (0);
} /* int email_init */
-static void type_list_free (type_list_t *t)
-{
- type_t *this;
+static void type_list_free(type_list_t *t) {
+ type_t *this;
- this = t->head;
- while (this != NULL)
- {
- type_t *next = this->next;
+ this = t->head;
+ while (this != NULL) {
+ type_t *next = this->next;
- sfree (this->name);
- sfree (this);
+ sfree(this->name);
+ sfree(this);
- this = next;
- }
+ this = next;
+ }
- t->head = NULL;
- t->tail = NULL;
+ t->head = NULL;
+ t->tail = NULL;
}
-static int email_shutdown (void)
-{
- int i = 0;
+static int email_shutdown(void) {
+ if (connector != ((pthread_t)0)) {
+ pthread_kill(connector, SIGTERM);
+ connector = (pthread_t)0;
+ }
- if (connector != ((pthread_t) 0)) {
- pthread_kill (connector, SIGTERM);
- connector = (pthread_t) 0;
- }
+ if (connector_socket >= 0) {
+ close(connector_socket);
+ connector_socket = -1;
+ }
- if (connector_socket >= 0) {
- close (connector_socket);
- connector_socket = -1;
- }
+ /* don't allow any more connections to be processed */
+ pthread_mutex_lock(&conns_mutex);
- /* don't allow any more connections to be processed */
- pthread_mutex_lock (&conns_mutex);
+ available_collectors = 0;
- available_collectors = 0;
+ if (collectors != NULL) {
+ for (int i = 0; i < max_conns; ++i) {
+ if (collectors[i] == NULL)
+ continue;
- if (collectors != NULL) {
- for (i = 0; i < max_conns; ++i) {
- if (collectors[i] == NULL)
- continue;
+ if (collectors[i]->thread != ((pthread_t)0)) {
+ pthread_kill(collectors[i]->thread, SIGTERM);
+ collectors[i]->thread = (pthread_t)0;
+ }
- if (collectors[i]->thread != ((pthread_t) 0)) {
- pthread_kill (collectors[i]->thread, SIGTERM);
- collectors[i]->thread = (pthread_t) 0;
- }
+ if (collectors[i]->socket != NULL) {
+ fclose(collectors[i]->socket);
+ collectors[i]->socket = NULL;
+ }
- if (collectors[i]->socket != NULL) {
- fclose (collectors[i]->socket);
- collectors[i]->socket = NULL;
- }
+ sfree(collectors[i]);
+ }
+ sfree(collectors);
+ } /* if (collectors != NULL) */
- sfree (collectors[i]);
- }
- sfree (collectors);
- } /* if (collectors != NULL) */
+ pthread_mutex_unlock(&conns_mutex);
- pthread_mutex_unlock (&conns_mutex);
+ type_list_free(&list_count);
+ type_list_free(&list_count_copy);
+ type_list_free(&list_size);
+ type_list_free(&list_size_copy);
+ type_list_free(&list_check);
+ type_list_free(&list_check_copy);
- type_list_free (&list_count);
- type_list_free (&list_count_copy);
- type_list_free (&list_size);
- type_list_free (&list_size_copy);
- type_list_free (&list_check);
- type_list_free (&list_check_copy);
+ unlink((NULL == sock_file) ? SOCK_PATH : sock_file);
- unlink ((NULL == sock_file) ? SOCK_PATH : sock_file);
-
- sfree (sock_file);
- sfree (sock_group);
- return (0);
+ sfree(sock_file);
+ sfree(sock_group);
+ return (0);
} /* static void email_shutdown (void) */
-static void email_submit (const char *type, const char *type_instance, gauge_t value)
-{
- value_t values[1];
- value_list_t vl = VALUE_LIST_INIT;
-
- values[0].gauge = value;
+static void email_submit(const char *type, const char *type_instance,
+ gauge_t value) {
+ value_list_t vl = VALUE_LIST_INIT;
- vl.values = values;
- vl.values_len = 1;
- sstrncpy (vl.host, hostname_g, sizeof (vl.host));
- sstrncpy (vl.plugin, "email", sizeof (vl.plugin));
- sstrncpy (vl.type, type, sizeof (vl.type));
- sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+ vl.values = &(value_t){.gauge = value};
+ vl.values_len = 1;
+ sstrncpy(vl.plugin, "email", sizeof(vl.plugin));
+ sstrncpy(vl.type, type, sizeof(vl.type));
+ sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
- plugin_dispatch_values (&vl);
+ plugin_dispatch_values(&vl);
} /* void email_submit */
/* Copy list l1 to list l2. l2 may partly exist already, but it is assumed
* that neither the order nor the name of any element of either list is
* changed and no elements are deleted. The values of l1 are reset to zero
* after they have been copied to l2. */
-static void copy_type_list (type_list_t *l1, type_list_t *l2)
-{
- type_t *ptr1;
- type_t *ptr2;
-
- type_t *last = NULL;
-
- for (ptr1 = l1->head, ptr2 = l2->head; NULL != ptr1;
- ptr1 = ptr1->next, last = ptr2, ptr2 = ptr2->next) {
- if (NULL == ptr2) {
- ptr2 = smalloc (sizeof (*ptr2));
- ptr2->name = NULL;
- ptr2->next = NULL;
-
- if (NULL == last) {
- l2->head = ptr2;
- }
- else {
- last->next = ptr2;
- }
-
- l2->tail = ptr2;
- }
-
- if (NULL == ptr2->name) {
- ptr2->name = sstrdup (ptr1->name);
- }
-
- ptr2->value = ptr1->value;
- ptr1->value = 0;
- }
- return;
+static void copy_type_list(type_list_t *l1, type_list_t *l2) {
+ type_t *last = NULL;
+
+ for (type_t *ptr1 = l1->head, *ptr2 = l2->head; NULL != ptr1;
+ ptr1 = ptr1->next, last = ptr2, ptr2 = ptr2->next) {
+ if (NULL == ptr2) {
+ ptr2 = smalloc(sizeof(*ptr2));
+ ptr2->name = NULL;
+ ptr2->next = NULL;
+
+ if (NULL == last) {
+ l2->head = ptr2;
+ } else {
+ last->next = ptr2;
+ }
+
+ l2->tail = ptr2;
+ }
+
+ if (NULL == ptr2->name) {
+ ptr2->name = sstrdup(ptr1->name);
+ }
+
+ ptr2->value = ptr1->value;
+ ptr1->value = 0;
+ }
+ return;
}
-static int email_read (void)
-{
- type_t *ptr;
-
- double score_old;
- int score_count_old;
+static int email_read(void) {
+ double score_old;
+ int score_count_old;
- if (disabled)
- return (-1);
+ if (disabled)
+ return (-1);
- /* email count */
- pthread_mutex_lock (&count_mutex);
+ /* email count */
+ pthread_mutex_lock(&count_mutex);
- copy_type_list (&list_count, &list_count_copy);
+ copy_type_list(&list_count, &list_count_copy);
- pthread_mutex_unlock (&count_mutex);
+ pthread_mutex_unlock(&count_mutex);
- for (ptr = list_count_copy.head; NULL != ptr; ptr = ptr->next) {
- email_submit ("email_count", ptr->name, ptr->value);
- }
+ for (type_t *ptr = list_count_copy.head; NULL != ptr; ptr = ptr->next) {
+ email_submit("email_count", ptr->name, ptr->value);
+ }
- /* email size */
- pthread_mutex_lock (&size_mutex);
+ /* email size */
+ pthread_mutex_lock(&size_mutex);
- copy_type_list (&list_size, &list_size_copy);
+ copy_type_list(&list_size, &list_size_copy);
- pthread_mutex_unlock (&size_mutex);
+ pthread_mutex_unlock(&size_mutex);
- for (ptr = list_size_copy.head; NULL != ptr; ptr = ptr->next) {
- email_submit ("email_size", ptr->name, ptr->value);
- }
+ for (type_t *ptr = list_size_copy.head; NULL != ptr; ptr = ptr->next) {
+ email_submit("email_size", ptr->name, ptr->value);
+ }
- /* spam score */
- pthread_mutex_lock (&score_mutex);
+ /* spam score */
+ pthread_mutex_lock(&score_mutex);
- score_old = score;
- score_count_old = score_count;
- score = 0.0;
- score_count = 0;
+ score_old = score;
+ score_count_old = score_count;
+ score = 0.0;
+ score_count = 0;
- pthread_mutex_unlock (&score_mutex);
+ pthread_mutex_unlock(&score_mutex);
- if (score_count_old > 0)
- email_submit ("spam_score", "", score_old);
+ if (score_count_old > 0)
+ email_submit("spam_score", "", score_old);
- /* spam checks */
- pthread_mutex_lock (&check_mutex);
+ /* spam checks */
+ pthread_mutex_lock(&check_mutex);
- copy_type_list (&list_check, &list_check_copy);
+ copy_type_list(&list_check, &list_check_copy);
- pthread_mutex_unlock (&check_mutex);
+ pthread_mutex_unlock(&check_mutex);
- for (ptr = list_check_copy.head; NULL != ptr; ptr = ptr->next)
- email_submit ("spam_check", ptr->name, ptr->value);
+ for (type_t *ptr = list_check_copy.head; NULL != ptr; ptr = ptr->next)
+ email_submit("spam_check", ptr->name, ptr->value);
- return (0);
+ return (0);
} /* int email_read */
-void module_register (void)
-{
- plugin_register_config ("email", email_config, config_keys, config_keys_num);
- plugin_register_init ("email", email_init);
- plugin_register_read ("email", email_read);
- plugin_register_shutdown ("email", email_shutdown);
+void module_register(void) {
+ plugin_register_config("email", email_config, config_keys, config_keys_num);
+ plugin_register_init("email", email_init);
+ plugin_register_read("email", email_read);
+ plugin_register_shutdown("email", email_shutdown);
} /* void module_register */
/* vim: set sw=4 ts=4 tw=78 noexpandtab : */