email plugin: Prevent a segfault in read_line ().
[collectd.git] / src / email.c
index b799597..c1e139e 100644 (file)
 #      include <sys/un.h>
 #endif /* HAVE_LINUX_UN_H | HAVE_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)
+#endif /* UNIX_PATH_MAX */
+
 #if HAVE_GRP_H
 #      include <grp.h>
 #endif /* HAVE_GRP_H */
 /* 256 bytes ought to be enough for anybody ;-) */
 #define BUFSIZE 256
 
-#define SOCK_PATH "/tmp/.collectd-email"
+#ifndef COLLECTD_SOCKET_PREFIX
+# define COLLECTD_SOCKET_PREFIX "/tmp/.collectd-"
+#endif /* COLLECTD_SOCKET_PREFIX */
+
+#define SOCK_PATH COLLECTD_SOCKET_PREFIX"email"
 #define MAX_CONNS 5
 #define MAX_CONNS_LIMIT 16384
 
@@ -135,6 +144,7 @@ static int disabled = 0;
 
 /* thread managing "client" connections */
 static pthread_t connector;
+static int connector_socket;
 
 /* tell the connector thread that a collector is available */
 static pthread_cond_t collector_available = PTHREAD_COND_INITIALIZER;
@@ -201,7 +211,7 @@ static int email_config (char *key, char *value)
        }
        else if (0 == strcasecmp (key, "SocketPerms")) {
                /* the user is responsible for providing reasonable values */
-               sock_perms = (int)strtol (value, NULL, 0);
+               sock_perms = (int)strtol (value, NULL, 8);
        }
        else if (0 == strcasecmp (key, "MaxConns")) {
                long int tmp = strtol (value, NULL, 0);
@@ -322,7 +332,7 @@ char *read_line (collector_t *src)
                        break;
        }
 
-       if ('\n' != src->buffer[i]) {
+       if (i == src->idx) {
                fd_set fdset;
        
                ssize_t len = 0;
@@ -359,7 +369,7 @@ char *read_line (collector_t *src)
                                break;
                }
 
-               if ('\n' != src->buffer[i]) {
+               if (i == src->idx) {
                        ret = (char *)smalloc (1);
 
                        ret[0] = '\0';
@@ -524,13 +534,11 @@ static void *collect (void *arg)
 
 static void *open_connection (void *arg)
 {
-       int local = 0;
-
        struct sockaddr_un addr;
 
        /* create UNIX socket */
        errno = 0;
-       if (-1 == (local = socket (PF_UNIX, SOCK_STREAM, 0))) {
+       if (-1 == (connector_socket = socket (PF_UNIX, SOCK_STREAM, 0))) {
                disabled = 1;
                syslog (LOG_ERR, "socket() failed: %s", strerror (errno));
                pthread_exit ((void *)1);
@@ -543,7 +551,7 @@ static void *open_connection (void *arg)
        unlink (addr.sun_path);
 
        errno = 0;
-       if (-1 == bind (local, (struct sockaddr *)&addr,
+       if (-1 == bind (connector_socket, (struct sockaddr *)&addr,
                                offsetof (struct sockaddr_un, sun_path)
                                        + strlen(addr.sun_path))) {
                disabled = 1;
@@ -552,7 +560,7 @@ static void *open_connection (void *arg)
        }
 
        errno = 0;
-       if (-1 == listen (local, 5)) {
+       if (-1 == listen (connector_socket, 5)) {
                disabled = 1;
                syslog (LOG_ERR, "listen() failed: %s", strerror (errno));
                pthread_exit ((void *)1);
@@ -619,7 +627,7 @@ static void *open_connection (void *arg)
 
                do {
                        errno = 0;
-                       if (-1 == (remote = accept (local, NULL, NULL))) {
+                       if (-1 == (remote = accept (connector_socket, NULL, NULL))) {
                                if (EINTR != errno) {
                                        disabled = 1;
                                        syslog (LOG_ERR, "accept() failed: %s", strerror (errno));
@@ -704,6 +712,31 @@ static void email_init (void)
        return;
 } /* static void email_init (void) */
 
+#if EMAIL_HAVE_READ
+static void email_shutdown (void)
+{
+       collector_t *ptr;
+
+       if (disabled)
+               return;
+
+       close (connector_socket);
+       pthread_kill (connector, SIGTERM);
+
+       pthread_mutex_lock (&active_mutex);
+
+       for (ptr = active.head; NULL != ptr; ptr = ptr->next) {
+               close (ptr->socket);
+               pthread_kill (ptr->thread, SIGTERM);
+       }
+
+       pthread_mutex_unlock (&active_mutex);
+
+       unlink (SOCK_PATH);
+       return;
+} /* static void email_shutdown (void) */
+#endif /* EMAIL_HAVE_READ */
+
 static void count_write (char *host, char *inst, char *val)
 {
        char file[BUFSIZE] = "";
@@ -837,6 +870,7 @@ void module_register (void)
        plugin_register ("email_spam_score", NULL, NULL, score_write);
        plugin_register ("email_spam_check", NULL, NULL, check_write);
 #if EMAIL_HAVE_READ
+       plugin_register_shutdown (MODULE_NAME, email_shutdown);
        cf_register (MODULE_NAME, email_config, config_keys, config_keys_num);
 #endif /* EMAIL_HAVE_READ */
        return;