Merge branch 'collectd-5.7'
authorFlorian Forster <octo@collectd.org>
Fri, 29 Sep 2017 11:08:25 +0000 (13:08 +0200)
committerFlorian Forster <octo@collectd.org>
Fri, 29 Sep 2017 11:08:25 +0000 (13:08 +0200)
1  2 
src/dbi.c
src/email.c
src/exec.c
src/snmp.c
src/unixsock.c

diff --combined src/dbi.c
+++ b/src/dbi.c
@@@ -62,7 -62,6 +62,7 @@@ struct cdbi_database_s /* {{{ *
  {
    char *name;
    char *select_db;
 +  char *plugin_name;
  
    cdtime_t interval;
  
@@@ -102,18 -101,18 +102,18 @@@ static const char *cdbi_strerror(dbi_co
  
    if (conn == NULL) {
      sstrncpy(buffer, "connection is NULL", buffer_size);
 -    return (buffer);
 +    return buffer;
    }
  
    msg = NULL;
    status = dbi_conn_error(conn, &msg);
    if ((status >= 0) && (msg != NULL))
 -    ssnprintf(buffer, buffer_size, "%s (status %i)", msg, status);
 +    snprintf(buffer, buffer_size, "%s (status %i)", msg, status);
    else
 -    ssnprintf(buffer, buffer_size, "dbi_conn_error failed with status %i",
 -              status);
 +    snprintf(buffer, buffer_size, "dbi_conn_error failed with status %i",
 +             status);
  
 -  return (buffer);
 +  return buffer;
  } /* }}} const char *cdbi_conn_error */
  
  static int cdbi_result_get_field(dbi_result res, /* {{{ */
    if (src_type == DBI_TYPE_ERROR) {
      ERROR("dbi plugin: cdbi_result_get: "
            "dbi_result_get_field_type_idx failed.");
 -    return (-1);
 +    return -1;
    }
  
    if (src_type == DBI_TYPE_INTEGER) {
      long long value;
  
      value = dbi_result_get_longlong_idx(res, index);
 -    ssnprintf(buffer, buffer_size, "%lli", value);
 +    snprintf(buffer, buffer_size, "%lli", value);
    } else if (src_type == DBI_TYPE_DECIMAL) {
      double value;
  
      value = dbi_result_get_double_idx(res, index);
 -    ssnprintf(buffer, buffer_size, "%63.15g", value);
 +    snprintf(buffer, buffer_size, "%63.15g", value);
    } else if (src_type == DBI_TYPE_STRING) {
      const char *value;
  
      if (value == NULL)
        sstrncpy(buffer, "", buffer_size);
      else if (strcmp("ERROR", value) == 0)
 -      return (-1);
 +      return -1;
      else
        sstrncpy(buffer, value, buffer_size);
    }
      ERROR("dbi plugin: Column `%s': Don't know how to handle "
            "source type %hu.",
            field_name, src_type);
 -    return (-1);
 +    return -1;
    }
  
 -  return (0);
 +  return 0;
  } /* }}} int cdbi_result_get_field */
  
  static void cdbi_database_free(cdbi_database_t *db) /* {{{ */
  
    sfree(db->name);
    sfree(db->select_db);
 +  sfree(db->plugin_name);
    sfree(db->driver);
    sfree(db->host);
  
    if (db->q_prep_areas)
      for (size_t i = 0; i < db->queries_num; ++i)
        udb_query_delete_preparation_area(db->q_prep_areas[i]);
-   free(db->q_prep_areas);
+   sfree(db->q_prep_areas);
+   /* N.B.: db->queries references objects "owned" by the global queries
+    * variable. Free the array here, but not the content. */
+   sfree(db->queries);
  
    sfree(db);
  } /* }}} void cdbi_database_free */
@@@ -225,14 -226,14 +228,14 @@@ static int cdbi_config_add_database_dri
         (ci->values[1].type != OCONFIG_TYPE_NUMBER))) {
      WARNING("dbi plugin: The `DriverOption' config option "
              "needs exactly two arguments.");
 -    return (-1);
 +    return -1;
    }
  
    option = realloc(db->driver_options,
                     sizeof(*option) * (db->driver_options_num + 1));
    if (option == NULL) {
      ERROR("dbi plugin: realloc failed");
 -    return (-1);
 +    return -1;
    }
  
    db->driver_options = option;
    option->key = strdup(ci->values[0].value.string);
    if (option->key == NULL) {
      ERROR("dbi plugin: strdup failed.");
 -    return (-1);
 +    return -1;
    }
  
    if (ci->values[1].type == OCONFIG_TYPE_STRING) {
      if (option->value.string == NULL) {
        ERROR("dbi plugin: strdup failed.");
        sfree(option->key);
 -      return (-1);
 +      return -1;
      }
    } else {
      assert(ci->values[1].type == OCONFIG_TYPE_NUMBER);
    }
  
    db->driver_options_num++;
 -  return (0);
 +  return 0;
  } /* }}} int cdbi_config_add_database_driver_option */
  
  static int cdbi_config_add_database(oconfig_item_t *ci) /* {{{ */
    if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
      WARNING("dbi plugin: The `Database' block "
              "needs exactly one string argument.");
 -    return (-1);
 +    return -1;
    }
  
    db = calloc(1, sizeof(*db));
    if (db == NULL) {
      ERROR("dbi plugin: calloc failed.");
 -    return (-1);
 +    return -1;
    }
  
    status = cf_util_get_string(ci, &db->name);
    if (status != 0) {
      sfree(db);
 -    return (status);
 +    return status;
    }
  
    /* Fill the `cdbi_database_t' structure.. */
        status = cf_util_get_string(child, &db->host);
      else if (strcasecmp("Interval", child->key) == 0)
        status = cf_util_get_cdtime(child, &db->interval);
 +    else if (strcasecmp("Plugin", child->key) == 0)
 +      status = cf_util_get_string(child, &db->plugin_name);
      else {
        WARNING("dbi plugin: Option `%s' not allowed here.", child->key);
        status = -1;
  
    if (status != 0) {
      cdbi_database_free(db);
 -    return (-1);
 +    return -1;
    }
  
 -  return (0);
 +  return 0;
  } /* }}} int cdbi_config_add_database */
  
  static int cdbi_config(oconfig_item_t *ci) /* {{{ */
      }
    } /* for (ci->children) */
  
 -  return (0);
 +  return 0;
  } /* }}} int cdbi_config */
  
  /* }}} End of configuration handling functions */
@@@ -408,34 -407,34 +411,34 @@@ static int cdbi_init(void) /* {{{ *
    int status;
  
    if (did_init != 0)
 -    return (0);
 +    return 0;
  
    if (queries_num == 0) {
      ERROR("dbi plugin: No <Query> blocks have been found. Without them, "
            "this plugin can't do anything useful, so we will return an error.");
 -    return (-1);
 +    return -1;
    }
  
    if (databases_num == 0) {
      ERROR("dbi plugin: No <Database> blocks have been found. Without them, "
            "this plugin can't do anything useful, so we will return an error.");
 -    return (-1);
 +    return -1;
    }
  
    status = dbi_initialize_r(/* driverdir = */ NULL, &dbi_instance);
    if (status < 0) {
      ERROR("dbi plugin: cdbi_init: dbi_initialize_r failed with status %i.",
            status);
 -    return (-1);
 +    return -1;
    } else if (status == 0) {
      ERROR("dbi plugin: `dbi_initialize_r' could not load any drivers. Please "
            "install at least one `DBD' or check your installation.");
 -    return (-1);
 +    return -1;
    }
    DEBUG("dbi plugin: cdbi_init: dbi_initialize_r reports %i driver%s.", status,
          (status == 1) ? "" : "s");
  
 -  return (0);
 +  return 0;
  } /* }}} int cdbi_init */
  
  static int cdbi_read_database_query(cdbi_database_t *db, /* {{{ */
  
    udb_query_prepare_result(
        q, prep_area, (db->host ? db->host : hostname_g),
 -      /* plugin = */ "dbi", db->name, column_names, column_num,
 +      /* plugin = */ (db->plugin_name != NULL) ? db->plugin_name : "dbi",
 +      db->name, column_names, column_num,
        /* interval = */ (db->interval > 0) ? db->interval : 0);
  
    /* 0 = error; 1 = success; */
@@@ -626,7 -624,7 +629,7 @@@ static int cdbi_connect_database(cdbi_d
    if (db->connection != NULL) {
      status = dbi_conn_ping(db->connection);
      if (status != 0) /* connection is alive */
 -      return (0);
 +      return 0;
  
      dbi_conn_close(db->connection);
      db->connection = NULL;
           driver = dbi_driver_list_r(driver, dbi_instance)) {
        INFO("dbi plugin: * %s", dbi_driver_get_name(driver));
      }
 -    return (-1);
 +    return -1;
    }
  
    connection = dbi_conn_open(driver);
    if (connection == NULL) {
      ERROR("dbi plugin: cdbi_connect_database: dbi_conn_open (%s) failed.",
            db->driver);
 -    return (-1);
 +    return -1;
    }
  
    /* Set all the driver options. Because this is a very very very generic
        }
  
        dbi_conn_close(connection);
 -      return (-1);
 +      return -1;
      }
    } /* for (i = 0; i < db->driver_options_num; i++) */
  
            "dbi_conn_connect failed: %s",
            db->name, cdbi_strerror(connection, errbuf, sizeof(errbuf)));
      dbi_conn_close(connection);
 -    return (-1);
 +    return -1;
    }
  
    if (db->select_db != NULL) {
            db->name, db->select_db,
            cdbi_strerror(connection, errbuf, sizeof(errbuf)));
        dbi_conn_close(connection);
 -      return (-1);
 +      return -1;
      }
    }
  
    db->connection = connection;
 -  return (0);
 +  return 0;
  } /* }}} int cdbi_connect_database */
  
  static int cdbi_read_database(user_data_t *ud) /* {{{ */
  
    status = cdbi_connect_database(db);
    if (status != 0)
 -    return (status);
 +    return status;
    assert(db->connection != NULL);
  
    db_version = dbi_conn_get_engine_version(db->connection);
  
    if (success == 0) {
      ERROR("dbi plugin: All queries failed for database `%s'.", db->name);
 -    return (-1);
 +    return -1;
    }
  
 -  return (0);
 +  return 0;
  } /* }}} int cdbi_read_database */
  
  static int cdbi_shutdown(void) /* {{{ */
    queries = NULL;
    queries_num = 0;
  
 -  return (0);
 +  return 0;
  } /* }}} int cdbi_shutdown */
  
  void module_register(void) /* {{{ */
    plugin_register_init("dbi", cdbi_init);
    plugin_register_shutdown("dbi", cdbi_shutdown);
  } /* }}} void module_register */
 -
 -/*
 - * vim: shiftwidth=2 softtabstop=2 et fdm=marker
 - */
diff --combined src/email.c
@@@ -159,18 -159,18 +159,18 @@@ static type_list_t list_check_copy
   * Private functions
   */
  static int email_config(const char *key, const char *value) {
 -  if (0 == strcasecmp(key, "SocketFile")) {
 -    if (NULL != sock_file)
 +  if (strcasecmp(key, "SocketFile") == 0) {
 +    if (sock_file != NULL)
        free(sock_file);
      sock_file = sstrdup(value);
 -  } else if (0 == strcasecmp(key, "SocketGroup")) {
 -    if (NULL != sock_group)
 +  } else if (strcasecmp(key, "SocketGroup") == 0) {
 +    if (sock_group != NULL)
        free(sock_group);
      sock_group = sstrdup(value);
 -  } else if (0 == strcasecmp(key, "SocketPerms")) {
 +  } else if (strcasecmp(key, "SocketPerms") == 0) {
      /* the user is responsible for providing reasonable values */
      sock_perms = (int)strtol(value, NULL, 8);
 -  } else if (0 == strcasecmp(key, "MaxConns")) {
 +  } else if (strcasecmp(key, "MaxConns") == 0) {
      long int tmp = strtol(value, NULL, 0);
  
      if (tmp < 1) {
  
  /* 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) {
 +  if (list->head == NULL) {
      list->head = smalloc(sizeof(*list->head));
  
      list->head->name = sstrdup(name);
      type_t *ptr;
  
      for (ptr = list->head; NULL != ptr; ptr = ptr->next) {
 -      if (0 == strcmp(name, ptr->name))
 +      if (strcmp(name, ptr->name) == 0)
          break;
      }
  
 -    if (NULL == ptr) {
 +    if (ptr == NULL) {
        list->tail->next = smalloc(sizeof(*list->tail->next));
        list->tail = list->tail->next;
  
@@@ -238,14 -238,14 +238,14 @@@ static void *collect(void *arg) 
  
      pthread_mutex_lock(&conns_mutex);
  
 -    while (NULL == conns.head) {
 +    while (conns.head == NULL) {
        pthread_cond_wait(&conn_available, &conns_mutex);
      }
  
      connection = conns.head;
      conns.head = conns.head->next;
  
 -    if (NULL == conns.head) {
 +    if (conns.head == NULL) {
        conns.tail = NULL;
      }
  
        int len = 0;
  
        errno = 0;
 -      if (NULL == fgets(line, sizeof(line), this->socket)) {
 -        if (0 != errno) {
 +      if (fgets(line, sizeof(line), this->socket) == NULL) {
 +        if (errno != 0) {
            char errbuf[1024];
            log_err("collect: reading from socket (fd #%i) "
                    "failed: %s",
        }
  
        len = strlen(line);
 -      if (('\n' != line[len - 1]) && ('\r' != line[len - 1])) {
 +      if ((line[len - 1] != '\n') && (line[len - 1] != '\r')) {
          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]))
 +        while (fgets(line, sizeof(line), this->socket) != NULL)
 +          if ((line[len - 1] == '\n') || (line[len - 1] == '\r'))
              break;
          continue;
        }
  
        log_debug("collect: line = '%s'", line);
  
 -      if (':' != line[1]) {
 +      if (line[1] != ':') {
          log_err("collect: syntax error in line '%s'", line);
          continue;
        }
  
 -      if ('e' == line[0]) { /* e:<type>:<bytes> */
 +      if (line[0] == 'e') { /* 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) {
 +        if (tmp == NULL) {
            log_err("collect: syntax error in line '%s'", line);
            continue;
          }
            type_list_incr(&list_size, type, /* increment = */ bytes);
            pthread_mutex_unlock(&size_mutex);
          }
 -      } else if ('s' == line[0]) { /* s:<value> */
 +      } else if (line[0] == 's') { /* 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>,...] */
 +      } else if (line[0] == 'c') { /* c:<type1>[,<type2>,...] */
          char *dummy = line + 2;
          char *endptr = NULL;
          char *type;
    } /* while (1) */
  
    pthread_exit((void *)0);
 -  return ((void *)0);
 +  return (void *)0;
  } /* static void *collect (void *) */
  
  static void *open_connection(void __attribute__((unused)) * arg) {
  
    /* create UNIX socket */
    errno = 0;
 -  if (-1 == (connector_socket = socket(PF_UNIX, SOCK_STREAM, 0))) {
 +  if ((connector_socket = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
      char errbuf[1024];
      disabled = 1;
      log_err("socket() failed: %s", sstrerror(errno, errbuf, sizeof(errbuf)));
    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))) {
 +  if (bind(connector_socket, (struct sockaddr *)&addr,
 +           offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path)) == -1) {
      char errbuf[1024];
      disabled = 1;
      close(connector_socket);
    }
  
    errno = 0;
 -  if (-1 == listen(connector_socket, 5)) {
 +  if (listen(connector_socket, 5) == -1) {
      char errbuf[1024];
      disabled = 1;
      close(connector_socket);
    {
      struct group sg;
      struct group *grp;
-     char grbuf[4096];
      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) {
    }
  
    errno = 0;
 -  if (0 != chmod(path, sock_perms)) {
 +  if (chmod(path, sock_perms) != 0) {
      char errbuf[1024];
      log_warn("chmod() failed: %s", sstrerror(errno, errbuf, sizeof(errbuf)));
    }
  
      pthread_mutex_lock(&available_mutex);
  
 -    while (0 == available_collectors) {
 +    while (available_collectors == 0) {
        pthread_cond_wait(&collector_available, &available_mutex);
      }
  
      connection->socket = fdopen(remote, "r");
      connection->next = NULL;
  
 -    if (NULL == connection->socket) {
 +    if (connection->socket == NULL) {
        close(remote);
        sfree(connection);
        continue;
  
      pthread_mutex_lock(&conns_mutex);
  
 -    if (NULL == conns.head) {
 +    if (conns.head == NULL) {
        conns.head = connection;
        conns.tail = connection;
      } else {
    }
  
    pthread_exit((void *)0);
 -  return ((void *)0);
 +  return (void *)0;
  } /* static void *open_connection (void *) */
  
  static int email_init(void) {
      disabled = 1;
      log_err("plugin_thread_create() failed: %s",
              sstrerror(errno, errbuf, sizeof(errbuf)));
 -    return (-1);
 +    return -1;
    }
  
 -  return (0);
 +  return 0;
  } /* int email_init */
  
  static void type_list_free(type_list_t *t) {
@@@ -604,11 -611,11 +610,11 @@@ static int email_shutdown(void) 
    type_list_free(&list_check);
    type_list_free(&list_check_copy);
  
 -  unlink((NULL == sock_file) ? SOCK_PATH : sock_file);
 +  unlink((sock_file == NULL) ? SOCK_PATH : sock_file);
  
    sfree(sock_file);
    sfree(sock_group);
 -  return (0);
 +  return 0;
  } /* static void email_shutdown (void) */
  
  static void email_submit(const char *type, const char *type_instance,
  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;
 +  for (type_t *ptr1 = l1->head, *ptr2 = l2->head; ptr1 != NULL;
         ptr1 = ptr1->next, last = ptr2, ptr2 = ptr2->next) {
 -    if (NULL == ptr2) {
 +    if (ptr2 == NULL) {
        ptr2 = smalloc(sizeof(*ptr2));
        ptr2->name = NULL;
        ptr2->next = NULL;
  
 -      if (NULL == last) {
 +      if (last == NULL) {
          l2->head = ptr2;
        } else {
          last->next = ptr2;
        l2->tail = ptr2;
      }
  
 -    if (NULL == ptr2->name) {
 +    if (ptr2->name == NULL) {
        ptr2->name = sstrdup(ptr1->name);
      }
  
@@@ -662,7 -669,7 +668,7 @@@ static int email_read(void) 
    int score_count_old;
  
    if (disabled)
 -    return (-1);
 +    return -1;
  
    /* email count */
    pthread_mutex_lock(&count_mutex);
  
    pthread_mutex_unlock(&count_mutex);
  
 -  for (type_t *ptr = list_count_copy.head; NULL != ptr; ptr = ptr->next) {
 +  for (type_t *ptr = list_count_copy.head; ptr != NULL; ptr = ptr->next) {
      email_submit("email_count", ptr->name, ptr->value);
    }
  
  
    pthread_mutex_unlock(&size_mutex);
  
 -  for (type_t *ptr = list_size_copy.head; NULL != ptr; ptr = ptr->next) {
 +  for (type_t *ptr = list_size_copy.head; ptr != NULL; ptr = ptr->next) {
      email_submit("email_size", ptr->name, ptr->value);
    }
  
  
    pthread_mutex_unlock(&check_mutex);
  
 -  for (type_t *ptr = list_check_copy.head; NULL != ptr; ptr = ptr->next)
 +  for (type_t *ptr = list_check_copy.head; ptr != NULL; ptr = ptr->next)
      email_submit("spam_check", ptr->name, ptr->value);
  
 -  return (0);
 +  return 0;
  } /* int email_read */
  
  void module_register(void) {
    plugin_register_read("email", email_read);
    plugin_register_shutdown("email", email_shutdown);
  } /* void module_register */
 -
 -/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
diff --combined src/exec.c
@@@ -108,26 -108,26 +108,26 @@@ static int exec_config_exec(oconfig_ite
  
    if (ci->children_num != 0) {
      WARNING("exec plugin: The config option `%s' may not be a block.", ci->key);
 -    return (-1);
 +    return -1;
    }
    if (ci->values_num < 2) {
      WARNING("exec plugin: The config option `%s' needs at least two "
              "arguments.",
              ci->key);
 -    return (-1);
 +    return -1;
    }
    if ((ci->values[0].type != OCONFIG_TYPE_STRING) ||
        (ci->values[1].type != OCONFIG_TYPE_STRING)) {
      WARNING("exec plugin: The first two arguments to the `%s' option must "
              "be string arguments.",
              ci->key);
 -    return (-1);
 +    return -1;
    }
  
    pl = calloc(1, sizeof(*pl));
    if (pl == NULL) {
      ERROR("exec plugin: calloc failed.");
 -    return (-1);
 +    return -1;
    }
  
    if (strcasecmp("NotificationExec", ci->key) == 0)
    if (pl->user == NULL) {
      ERROR("exec plugin: strdup failed.");
      sfree(pl);
 -    return (-1);
 +    return -1;
    }
  
    pl->group = strchr(pl->user, ':');
      ERROR("exec plugin: strdup failed.");
      sfree(pl->user);
      sfree(pl);
 -    return (-1);
 +    return -1;
    }
  
    pl->argv = calloc(ci->values_num, sizeof(*pl->argv));
      sfree(pl->exec);
      sfree(pl->user);
      sfree(pl);
 -    return (-1);
 +    return -1;
    }
  
    {
      sfree(pl->exec);
      sfree(pl->user);
      sfree(pl);
 -    return (-1);
 +    return -1;
    }
  
    for (i = 1; i < (ci->values_num - 1); i++) {
        pl->argv[i] = strdup(ci->values[i + 1].value.string);
      } else {
        if (ci->values[i + 1].type == OCONFIG_TYPE_NUMBER) {
 -        ssnprintf(buffer, sizeof(buffer), "%lf",
 -                  ci->values[i + 1].value.number);
 +        snprintf(buffer, sizeof(buffer), "%lf", ci->values[i + 1].value.number);
        } else {
          if (ci->values[i + 1].value.boolean)
            sstrncpy(buffer, "true", sizeof(buffer));
      sfree(pl->exec);
      sfree(pl->user);
      sfree(pl);
 -    return (-1);
 +    return -1;
    }
  
    for (i = 0; pl->argv[i] != NULL; i++) {
    pl->next = pl_head;
    pl_head = pl;
  
 -  return (0);
 +  return 0;
  } /* int exec_config_exec }}} */
  
  static int exec_config(oconfig_item_t *ci) /* {{{ */
      }
    } /* for (i) */
  
 -  return (0);
 +  return 0;
  } /* int exec_config }}} */
  
  static void set_environment(void) /* {{{ */
    char buffer[1024];
  
  #ifdef HAVE_SETENV
 -  ssnprintf(buffer, sizeof(buffer), "%.3f",
 -            CDTIME_T_TO_DOUBLE(plugin_get_interval()));
 +  snprintf(buffer, sizeof(buffer), "%.3f",
 +           CDTIME_T_TO_DOUBLE(plugin_get_interval()));
    setenv("COLLECTD_INTERVAL", buffer, /* overwrite = */ 1);
  
    sstrncpy(buffer, hostname_g, sizeof(buffer));
    setenv("COLLECTD_HOSTNAME", buffer, /* overwrite = */ 1);
  #else
 -  ssnprintf(buffer, sizeof(buffer), "COLLECTD_INTERVAL=%.3f",
 -            CDTIME_T_TO_DOUBLE(plugin_get_interval()));
 +  snprintf(buffer, sizeof(buffer), "COLLECTD_INTERVAL=%.3f",
 +           CDTIME_T_TO_DOUBLE(plugin_get_interval()));
    putenv(buffer);
  
 -  ssnprintf(buffer, sizeof(buffer), "COLLECTD_HOSTNAME=%s", hostname_g);
 +  snprintf(buffer, sizeof(buffer), "COLLECTD_HOSTNAME=%s", hostname_g);
    putenv(buffer);
  #endif
  } /* }}} void set_environment */
@@@ -331,7 -332,7 +331,7 @@@ static int create_pipe(int fd_pipe[2]) 
    if (status != 0) {
      ERROR("exec plugin: pipe failed: %s",
            sstrerror(errno, errbuf, sizeof(errbuf)));
 -    return (-1);
 +    return -1;
    }
  
    return 0;
@@@ -368,11 -369,17 +368,17 @@@ static int fork_child(program_list_t *p
  
    struct passwd *sp_ptr;
    struct passwd sp;
-   char nambuf[4096];
  
    if (pl->pid != 0)
 -    return (-1);
 +    return -1;
  
+   long int nambuf_size = sysconf(_SC_GETPW_R_SIZE_MAX);
+   if (nambuf_size <= 0)
+     nambuf_size = sysconf(_SC_PAGESIZE);
+   if (nambuf_size <= 0)
+     nambuf_size = 4096;
+   char nambuf[nambuf_size];
    if ((create_pipe(fd_pipe_in) == -1) || (create_pipe(fd_pipe_out) == -1) ||
        (create_pipe(fd_pipe_err) == -1))
      goto failed;
    /* The group configured in the configfile is set as effective group, because
     * this way the forked process can (re-)gain the user's primary group. */
    egid = -1;
 -  if (NULL != pl->group) {
 -    if ('\0' != *pl->group) {
 +  if (pl->group != NULL) {
 +    if (*pl->group != '\0') {
        struct group *gr_ptr = NULL;
        struct group gr;
  
-       status = getgrnam_r(pl->group, &gr, nambuf, sizeof(nambuf), &gr_ptr);
+       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];
+       status = getgrnam_r(pl->group, &gr, grbuf, sizeof(grbuf), &gr_ptr);
 -      if (0 != status) {
 +      if (status != 0) {
          ERROR("exec plugin: Failed to get group information "
                "for group ``%s'': %s",
                pl->group, sstrerror(status, errbuf, sizeof(errbuf)));
          goto failed;
        }
 -      if (NULL == gr_ptr) {
 +      if (gr_ptr == NULL) {
          ERROR("exec plugin: No such group: `%s'", pl->group);
          goto failed;
        }
    else
      close(fd_pipe_err[0]);
  
 -  return (pid);
 +  return pid;
  
  failed:
    close_pipe(fd_pipe_in);
    close_pipe(fd_pipe_out);
    close_pipe(fd_pipe_err);
  
 -  return (-1);
 +  return -1;
  } /* int fork_child }}} */
  
  static int parse_line(char *buffer) /* {{{ */
  {
    if (strncasecmp("PUTVAL", buffer, strlen("PUTVAL")) == 0)
 -    return (cmd_handle_putval(stdout, buffer));
 +    return cmd_handle_putval(stdout, buffer);
    else if (strncasecmp("PUTNOTIF", buffer, strlen("PUTNOTIF")) == 0)
 -    return (handle_putnotif(stdout, buffer));
 +    return handle_putnotif(stdout, buffer);
    else {
      ERROR("exec plugin: Unable to parse command, ignoring line: \"%s\"",
            buffer);
 -    return (-1);
 +    return -1;
    }
  } /* int parse_line }}} */
  
@@@ -654,7 -668,7 +667,7 @@@ static void *exec_read_one(void *arg) /
      close(fd_err);
  
    pthread_exit((void *)0);
 -  return (NULL);
 +  return NULL;
  } /* void *exec_read_one }}} */
  
  static void *exec_notification_one(void *arg) /* {{{ */
    n->meta = NULL;
    sfree(arg);
    pthread_exit((void *)0);
 -  return (NULL);
 +  return NULL;
  } /* void *exec_notification_one }}} */
  
  static int exec_init(void) /* {{{ */
    }
  #endif
  
 -  return (0);
 +  return 0;
  } /* int exec_init }}} */
  
  static int exec_read(void) /* {{{ */
      pthread_attr_destroy(&attr);
    } /* for (pl) */
  
 -  return (0);
 +  return 0;
  } /* int exec_read }}} */
  
  static int exec_notification(const notification_t *n, /* {{{ */
      pthread_attr_destroy(&attr);
    } /* for (pl) */
  
 -  return (0);
 +  return 0;
  } /* }}} int exec_notification */
  
  static int exec_shutdown(void) /* {{{ */
    } /* while (pl) */
    pl_head = NULL;
  
 -  return (0);
 +  return 0;
  } /* int exec_shutdown }}} */
  
  void module_register(void) {
                                 /* user_data = */ NULL);
    plugin_register_shutdown("exec", exec_shutdown);
  } /* void module_register */
 -
 -/*
 - * vim:shiftwidth=2:softtabstop=2:tabstop=8:fdm=marker
 - */
diff --combined src/snmp.c
@@@ -130,22 -130,23 +130,22 @@@ static void csnmp_oid_init(oid_t *dst, 
  }
  
  static int csnmp_oid_compare(oid_t const *left, oid_t const *right) {
 -  return (
 -      snmp_oid_compare(left->oid, left->oid_len, right->oid, right->oid_len));
 +  return snmp_oid_compare(left->oid, left->oid_len, right->oid, right->oid_len);
  }
  
  static int csnmp_oid_suffix(oid_t *dst, oid_t const *src, oid_t const *root) {
    /* Make sure "src" is in "root"s subtree. */
    if (src->oid_len <= root->oid_len)
 -    return (EINVAL);
 +    return EINVAL;
    if (snmp_oid_ncompare(root->oid, root->oid_len, src->oid, src->oid_len,
                          /* n = */ root->oid_len) != 0)
 -    return (EINVAL);
 +    return EINVAL;
  
    memset(dst, 0, sizeof(*dst));
    dst->oid_len = src->oid_len - root->oid_len;
    memcpy(dst->oid, &src->oid[root->oid_len],
           dst->oid_len * sizeof(dst->oid[0]));
 -  return (0);
 +  return 0;
  }
  
  static int csnmp_oid_to_string(char *buffer, size_t buffer_size,
    char *oid_str_ptr[MAX_OID_LEN];
  
    for (size_t i = 0; i < o->oid_len; i++) {
 -    ssnprintf(oid_str[i], sizeof(oid_str[i]), "%lu", (unsigned long)o->oid[i]);
 +    snprintf(oid_str[i], sizeof(oid_str[i]), "%lu", (unsigned long)o->oid[i]);
      oid_str_ptr[i] = oid_str[i];
    }
  
 -  return (strjoin(buffer, buffer_size, oid_str_ptr, o->oid_len,
 -                  /* separator = */ "."));
 +  return strjoin(buffer, buffer_size, oid_str_ptr, o->oid_len, ".");
  }
  
  static void csnmp_host_close_session(host_definition_t *host) /* {{{ */
@@@ -239,14 -241,14 +239,14 @@@ static int csnmp_config_add_data_instan
  
      if (!read_objid(buffer, dd->instance.oid.oid, &dd->instance.oid.oid_len)) {
        ERROR("snmp plugin: read_objid (%s) failed.", buffer);
 -      return (-1);
 +      return -1;
      }
    } else {
      /* Instance is a simple string */
      sstrncpy(dd->instance.string, buffer, sizeof(dd->instance.string));
    }
  
 -  return (0);
 +  return 0;
  } /* int csnmp_config_add_data_instance */
  
  static int csnmp_config_add_data_instance_prefix(data_definition_t *dd,
      WARNING("snmp plugin: data %s: InstancePrefix is ignored when `Table' "
              "is set to `false'.",
              dd->name);
 -    return (-1);
 +    return -1;
    }
  
    status = cf_util_get_string(ci, &dd->instance_prefix);
@@@ -268,20 -270,20 +268,20 @@@ static int csnmp_config_add_data_values
                                          oconfig_item_t *ci) {
    if (ci->values_num < 1) {
      WARNING("snmp plugin: `Values' needs at least one argument.");
 -    return (-1);
 +    return -1;
    }
  
    for (int i = 0; i < ci->values_num; i++)
      if (ci->values[i].type != OCONFIG_TYPE_STRING) {
        WARNING("snmp plugin: `Values' needs only string argument.");
 -      return (-1);
 +      return -1;
      }
  
    sfree(dd->values);
    dd->values_len = 0;
    dd->values = malloc(sizeof(*dd->values) * ci->values_num);
    if (dd->values == NULL)
 -    return (-1);
 +    return -1;
    dd->values_len = (size_t)ci->values_num;
  
    for (int i = 0; i < ci->values_num; i++) {
        free(dd->values);
        dd->values = NULL;
        dd->values_len = 0;
 -      return (-1);
 +      return -1;
      }
    }
  
 -  return (0);
 +  return 0;
  } /* int csnmp_config_add_data_instance */
  
  static int csnmp_config_add_data_blacklist(data_definition_t *dd,
                                             oconfig_item_t *ci) {
    if (ci->values_num < 1)
 -    return (0);
 +    return 0;
  
    for (int i = 0; i < ci->values_num; i++) {
      if (ci->values[i].type != OCONFIG_TYPE_STRING) {
        WARNING("snmp plugin: `Ignore' needs only string argument.");
 -      return (-1);
 +      return -1;
      }
    }
  
                       ci->values[i].value.string) != 0) {
        ERROR("snmp plugin: Can't allocate memory");
        strarray_free(dd->ignores, dd->ignores_len);
 -      return (ENOMEM);
 +      return ENOMEM;
      }
    }
    return 0;
@@@ -331,12 -333,12 +331,12 @@@ static int csnmp_config_add_data_blackl
                                                            oconfig_item_t *ci) {
    if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN)) {
      WARNING("snmp plugin: `InvertMatch' needs exactly one boolean argument.");
 -    return (-1);
 +    return -1;
    }
  
    dd->invert_match = ci->values[0].value.boolean ? 1 : 0;
  
 -  return (0);
 +  return 0;
  } /* int csnmp_config_add_data_blacklist_match_inverted */
  
  static int csnmp_config_add_data(oconfig_item_t *ci) {
  
    dd = calloc(1, sizeof(*dd));
    if (dd == NULL)
 -    return (-1);
 +    return -1;
  
    status = cf_util_get_string(ci, &dd->name);
    if (status != 0) {
      free(dd);
 -    return (-1);
 +    return -1;
    }
  
    dd->scale = 1.0;
      sfree(dd->values);
      sfree(dd->ignores);
      sfree(dd);
 -    return (-1);
 +    return -1;
    }
  
    DEBUG("snmp plugin: dd = { name = %s, type = %s, is_table = %s, values_len = "
      last->next = dd;
    }
  
 -  return (0);
 +  return 0;
  } /* int csnmp_config_add_data */
  
  static int csnmp_config_add_host_version(host_definition_t *hd,
    if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) {
      WARNING("snmp plugin: The `Version' config option needs exactly one number "
              "argument.");
 -    return (-1);
 +    return -1;
    }
  
    version = (int)ci->values[0].value.number;
    if ((version < 1) || (version > 3)) {
      WARNING("snmp plugin: `Version' must either be `1', `2', or `3'.");
 -    return (-1);
 +    return -1;
    }
  
    hd->version = version;
  
 -  return (0);
 +  return 0;
  } /* int csnmp_config_add_host_address */
  
  static int csnmp_config_add_host_collect(host_definition_t *host,
  
    if (ci->values_num < 1) {
      WARNING("snmp plugin: `Collect' needs at least one argument.");
 -    return (-1);
 +    return -1;
    }
  
    for (int i = 0; i < ci->values_num; i++)
      if (ci->values[i].type != OCONFIG_TYPE_STRING) {
        WARNING("snmp plugin: All arguments to `Collect' must be strings.");
 -      return (-1);
 +      return -1;
      }
  
    data_list_len = host->data_list_len + ci->values_num;
    data_list =
        realloc(host->data_list, sizeof(data_definition_t *) * data_list_len);
    if (data_list == NULL)
 -    return (-1);
 +    return -1;
    host->data_list = data_list;
  
    for (int i = 0; i < ci->values_num; i++) {
      host->data_list_len++;
    } /* for (values_num) */
  
 -  return (0);
 +  return 0;
  } /* int csnmp_config_add_host_collect */
  
  static int csnmp_config_add_host_auth_protocol(host_definition_t *hd,
    } else {
      WARNING("snmp plugin: The `AuthProtocol' config option must be `MD5' or "
              "`SHA'.");
 -    return (-1);
 +    return -1;
    }
  
    DEBUG("snmp plugin: host = %s; host->auth_protocol = %s;", hd->name,
          hd->auth_protocol == usmHMACMD5AuthProtocol ? "MD5" : "SHA");
  
 -  return (0);
 +  return 0;
  } /* int csnmp_config_add_host_auth_protocol */
  
  static int csnmp_config_add_host_priv_protocol(host_definition_t *hd,
    } else {
      WARNING("snmp plugin: The `PrivProtocol' config option must be `AES' or "
              "`DES'.");
 -    return (-1);
 +    return -1;
    }
  
    DEBUG("snmp plugin: host = %s; host->priv_protocol = %s;", hd->name,
          hd->priv_protocol == usmAESPrivProtocol ? "AES" : "DES");
  
 -  return (0);
 +  return 0;
  } /* int csnmp_config_add_host_priv_protocol */
  
  static int csnmp_config_add_host_security_level(host_definition_t *hd,
    else {
      WARNING("snmp plugin: The `SecurityLevel' config option must be "
              "`noAuthNoPriv', `authNoPriv', or `authPriv'.");
 -    return (-1);
 +    return -1;
    }
  
    DEBUG("snmp plugin: host = %s; host->security_level = %d;", hd->name,
          hd->security_level);
  
 -  return (0);
 +  return 0;
  } /* int csnmp_config_add_host_security_level */
  
  static int csnmp_config_add_host(oconfig_item_t *ci) {
  
    hd = calloc(1, sizeof(*hd));
    if (hd == NULL)
 -    return (-1);
 +    return -1;
    hd->version = 2;
    C_COMPLAIN_INIT(&hd->complaint);
  
  
    if (status != 0) {
      csnmp_host_definition_destroy(hd);
 -    return (-1);
 +    return -1;
    }
  
    DEBUG("snmp plugin: hd = { name = %s, address = %s, community = %s, version "
          "= %i }",
          hd->name, hd->address, hd->community, hd->version);
  
 -  ssnprintf(cb_name, sizeof(cb_name), "snmp-%s", hd->name);
 +  snprintf(cb_name, sizeof(cb_name), "snmp-%s", hd->name);
  
    status = plugin_register_complex_read(
        /* group = */ NULL, cb_name, csnmp_read_host, hd->interval,
        });
    if (status != 0) {
      ERROR("snmp plugin: Registering complex read function failed.");
 -    csnmp_host_definition_destroy(hd);
 -    return (-1);
 +    return -1;
    }
  
 -  return (0);
 +  return 0;
  } /* int csnmp_config_add_host */
  
  static int csnmp_config(oconfig_item_t *ci) {
      }
    } /* for (ci->children) */
  
 -  return (0);
 +  return 0;
  } /* int csnmp_config */
  
  /* }}} End of the config stuff. Now the interesting part begins */
@@@ -941,7 -944,7 +941,7 @@@ static value_t csnmp_value_list_to_valu
      ret.gauge = NAN;
    }
  
 -  return (ret);
 +  return ret;
  } /* value_t csnmp_value_list_to_value */
  
  /* csnmp_strvbcopy_hexstring converts the bit string contained in "vb" to a hex
@@@ -995,13 -998,13 +995,13 @@@ static int csnmp_strvbcopy(char *dst, /
    else if (vb->type == ASN_BIT_STR)
      src = (char *)vb->val.bitstring;
    else if (vb->type == ASN_IPADDRESS) {
 -    return ssnprintf(dst, dst_size,
 -                     "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 "",
 -                     (uint8_t)vb->val.string[0], (uint8_t)vb->val.string[1],
 -                     (uint8_t)vb->val.string[2], (uint8_t)vb->val.string[3]);
 +    return snprintf(dst, dst_size,
 +                    "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 "",
 +                    (uint8_t)vb->val.string[0], (uint8_t)vb->val.string[1],
 +                    (uint8_t)vb->val.string[2], (uint8_t)vb->val.string[3]);
    } else {
      dst[0] = 0;
 -    return (EINVAL);
 +    return EINVAL;
    }
  
    num_chars = dst_size - 1;
    for (size_t i = 0; i < num_chars; i++) {
      /* Check for control characters. */
      if ((unsigned char)src[i] < 32)
 -      return (csnmp_strvbcopy_hexstring(dst, vb, dst_size));
 +      return csnmp_strvbcopy_hexstring(dst, vb, dst_size);
      dst[i] = src[i];
    }
    dst[num_chars] = 0;
@@@ -1039,21 -1042,21 +1039,21 @@@ static int csnmp_instance_list_add(csnm
         vb = vb->next_variable)
      /* do nothing */;
    if (vb == NULL)
 -    return (-1);
 +    return -1;
  
    csnmp_oid_init(&vb_name, vb->name, vb->name_length);
  
    il = calloc(1, sizeof(*il));
    if (il == NULL) {
      ERROR("snmp plugin: calloc failed.");
 -    return (-1);
 +    return -1;
    }
    il->next = NULL;
  
    status = csnmp_oid_suffix(&il->suffix, &vb_name, &dd->instance.oid);
    if (status != 0) {
      sfree(il);
 -    return (status);
 +    return status;
    }
  
    /* Get instance name */
      value_t val = csnmp_value_list_to_value(
          vb, DS_TYPE_COUNTER,
          /* scale = */ 1.0, /* shift = */ 0.0, hd->name, dd->name);
 -    ssnprintf(il->instance, sizeof(il->instance), "%llu", val.counter);
 +    snprintf(il->instance, sizeof(il->instance), "%llu", val.counter);
    }
  
    /* TODO: Debugging output */
      (*tail)->next = il;
    *tail = il;
  
 -  return (0);
 +  return 0;
  } /* int csnmp_instance_list_add */
  
  static int csnmp_dispatch_table(host_definition_t *host,
    value_list_t vl = VALUE_LIST_INIT;
  
    csnmp_list_instances_t *instance_list_ptr;
 -  csnmp_table_values_t **value_table_ptr;
 +  csnmp_table_values_t *value_table_ptr[data->values_len];
  
    size_t i;
    _Bool have_more;
    ds = plugin_get_ds(data->type);
    if (!ds) {
      ERROR("snmp plugin: DataSet `%s' not defined.", data->type);
 -    return (-1);
 +    return -1;
    }
    assert(ds->ds_num == data->values_len);
    assert(data->values_len > 0);
  
    instance_list_ptr = instance_list;
  
 -  value_table_ptr = calloc(data->values_len, sizeof(*value_table_ptr));
 -  if (value_table_ptr == NULL)
 -    return (-1);
    for (i = 0; i < data->values_len; i++)
      value_table_ptr[i] = value_table[i];
  
 -  vl.values_len = data->values_len;
 -  vl.values = malloc(sizeof(*vl.values) * vl.values_len);
 -  if (vl.values == NULL) {
 -    ERROR("snmp plugin: malloc failed.");
 -    sfree(value_table_ptr);
 -    return (-1);
 -  }
 -
    sstrncpy(vl.host, host->name, sizeof(vl.host));
    sstrncpy(vl.plugin, "snmp", sizeof(vl.plugin));
  
  
        memcpy(&current_suffix, &instance_list_ptr->suffix,
               sizeof(current_suffix));
 -    } else /* no instance configured */
 -    {
 +    } else {
 +      /* no instance configured */
        csnmp_table_values_t *ptr = value_table_ptr[0];
        if (ptr == NULL) {
          have_more = 0;
        if (data->instance_prefix == NULL)
          sstrncpy(vl.type_instance, temp, sizeof(vl.type_instance));
        else
 -        ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s%s",
 -                  data->instance_prefix, temp);
 +        snprintf(vl.type_instance, sizeof(vl.type_instance), "%s%s",
 +                 data->instance_prefix, temp);
      }
  
 +    vl.values_len = data->values_len;
 +    value_t values[vl.values_len];
 +    vl.values = values;
 +
      for (i = 0; i < data->values_len; i++)
        vl.values[i] = value_table_ptr[i]->value;
  
      if (vl.type_instance[0] != '\0')
        plugin_dispatch_values(&vl);
  
 +    /* prevent leakage of pointer to local variable. */
 +    vl.values_len = 0;
 +    vl.values = NULL;
 +
      if (instance_list != NULL)
        instance_list_ptr = instance_list_ptr->next;
      else
        value_table_ptr[0] = value_table_ptr[0]->next;
    } /* while (have_more) */
  
 -  sfree(vl.values);
 -  sfree(value_table_ptr);
 -
    return (0);
  } /* int csnmp_dispatch_table */
  
@@@ -1283,20 -1292,20 +1283,20 @@@ static int csnmp_read_table(host_defini
  
    if (host->sess_handle == NULL) {
      DEBUG("snmp plugin: csnmp_read_table: host->sess_handle == NULL");
 -    return (-1);
 +    return -1;
    }
  
    ds = plugin_get_ds(data->type);
    if (!ds) {
      ERROR("snmp plugin: DataSet `%s' not defined.", data->type);
 -    return (-1);
 +    return -1;
    }
  
    if (ds->ds_num != data->values_len) {
      ERROR("snmp plugin: DataSet `%s' requires %zu values, but config talks "
            "about %zu",
            data->type, ds->ds_num, data->values_len);
 -    return (-1);
 +    return -1;
    }
    assert(data->values_len > 0);
  
      ERROR("snmp plugin: csnmp_read_table: calloc failed.");
      sfree(value_list_head);
      sfree(value_list_tail);
 -    return (-1);
 +    return -1;
    }
  
    instance_list_head = NULL;
  
    status = 0;
    while (status == 0) {
 -    int oid_list_todo_num;
 -
      req = snmp_pdu_create(SNMP_MSG_GETNEXT);
      if (req == NULL) {
        ERROR("snmp plugin: snmp_pdu_create failed.");
        break;
      }
  
 -    oid_list_todo_num = 0;
 +    size_t oid_list_todo_num = 0;
 +    size_t var_idx[oid_list_len];
 +    memset(var_idx, 0, sizeof(var_idx));
 +
      for (i = 0; i < oid_list_len; i++) {
        /* Do not rerequest already finished OIDs */
        if (!oid_list_todo[i])
          continue;
 -      oid_list_todo_num++;
        snmp_add_null_var(req, oid_list[i].oid, oid_list[i].oid_len);
 +      var_idx[oid_list_todo_num] = i;
 +      oid_list_todo_num++;
      }
  
      if (oid_list_todo_num == 0) {
        /* The request is still empty - so we are finished */
        DEBUG("snmp plugin: all variables have left their subtree");
+       snmp_free_pdu(req);
        status = 0;
        break;
      }
  
      res = NULL;
      status = snmp_sess_synch_response(host->sess_handle, req, &res);
+     /* snmp_sess_synch_response always frees our req PDU */
+     req = NULL;
      if ((status != STAT_SUCCESS) || (res == NULL)) {
        char *errstr = NULL;
  
          snmp_free_pdu(res);
        res = NULL;
  
-       /* snmp_synch_response already freed our PDU */
-       req = NULL;
        sfree(errstr);
        csnmp_host_close_session(host);
  
        break;
      }
  
 +    if (res->errstat != SNMP_ERR_NOERROR) {
 +      if (res->errindex != 0) {
 +        /* Find the OID which caused error */
 +        for (i = 1, vb = res->variables; vb != NULL && i != res->errindex;
 +             vb = vb->next_variable, i++)
 +          /* do nothing */;
 +      }
 +
 +      if ((res->errindex == 0) || (vb == NULL)) {
 +        ERROR("snmp plugin: host %s; data %s: response error: %s (%li) ",
 +              host->name, data->name, snmp_errstring(res->errstat),
 +              res->errstat);
 +        status = -1;
 +        break;
 +      }
 +
 +      char oid_buffer[1024] = {0};
 +      snprint_objid(oid_buffer, sizeof(oid_buffer) - 1, vb->name,
 +                    vb->name_length);
 +      NOTICE("snmp plugin: host %s; data %s: OID `%s` failed: %s", host->name,
 +             data->name, oid_buffer, snmp_errstring(res->errstat));
 +
 +      /* Get value index from todo list and skip OID found */
 +      assert(res->errindex <= oid_list_todo_num);
 +      i = var_idx[res->errindex - 1];
 +      assert(i < oid_list_len);
 +      oid_list_todo[i] = 0;
 +
 +      snmp_free_pdu(res);
 +      res = NULL;
 +      continue;
 +    }
 +
      for (vb = res->variables, i = 0; (vb != NULL);
           vb = vb->next_variable, i++) {
        /* Calculate value index from todo list */
      snmp_free_pdu(res);
    res = NULL;
  
-   if (req != NULL)
-     snmp_free_pdu(req);
-   req = NULL;
  
    if (status == 0)
      csnmp_dispatch_table(host, data, instance_list_head, value_list_head);
    sfree(value_list_head);
    sfree(value_list_tail);
  
 -  return (0);
 +  return 0;
  } /* int csnmp_read_table */
  
  static int csnmp_read_value(host_definition_t *host, data_definition_t *data) {
  
    if (host->sess_handle == NULL) {
      DEBUG("snmp plugin: csnmp_read_value: host->sess_handle == NULL");
 -    return (-1);
 +    return -1;
    }
  
    ds = plugin_get_ds(data->type);
    if (!ds) {
      ERROR("snmp plugin: DataSet `%s' not defined.", data->type);
 -    return (-1);
 +    return -1;
    }
  
    if (ds->ds_num != data->values_len) {
      ERROR("snmp plugin: DataSet `%s' requires %zu values, but config talks "
            "about %zu",
            data->type, ds->ds_num, data->values_len);
 -    return (-1);
 +    return -1;
    }
  
    vl.values_len = ds->ds_num;
    vl.values = malloc(sizeof(*vl.values) * vl.values_len);
    if (vl.values == NULL)
 -    return (-1);
 +    return -1;
    for (i = 0; i < vl.values_len; i++) {
      if (ds->ds[i].type == DS_TYPE_COUNTER)
        vl.values[i].counter = 0;
    if (req == NULL) {
      ERROR("snmp plugin: snmp_pdu_create failed.");
      sfree(vl.values);
 -    return (-1);
 +    return -1;
    }
  
    for (i = 0; i < data->values_len; i++)
      sfree(vl.values);
      csnmp_host_close_session(host);
  
 -    return (-1);
 +    return -1;
    }
  
    for (vb = res->variables; vb != NULL; vb = vb->next_variable) {
    plugin_dispatch_values(&vl);
    sfree(vl.values);
  
 -  return (0);
 +  return 0;
  } /* int csnmp_read_value */
  
  static int csnmp_read_host(user_data_t *ud) {
      csnmp_host_open_session(host);
  
    if (host->sess_handle == NULL)
 -    return (-1);
 +    return -1;
  
    success = 0;
    for (i = 0; i < host->data_list_len; i++) {
    }
  
    if (success == 0)
 -    return (-1);
 +    return -1;
  
 -  return (0);
 +  return 0;
  } /* int csnmp_read_host */
  
  static int csnmp_init(void) {
    call_snmp_init_once();
  
 -  return (0);
 +  return 0;
  } /* int csnmp_init */
  
  static int csnmp_shutdown(void) {
      data_this = data_next;
    }
  
 -  return (0);
 +  return 0;
  } /* int csnmp_shutdown */
  
  void module_register(void) {
    plugin_register_init("snmp", csnmp_init);
    plugin_register_shutdown("snmp", csnmp_shutdown);
  } /* void module_register */
 -
 -/*
 - * vim: shiftwidth=2 softtabstop=2 tabstop=8 fdm=marker
 - */
diff --combined src/unixsock.c
@@@ -78,7 -78,7 +78,7 @@@ static int us_open_socket(void) 
      char errbuf[1024];
      ERROR("unixsock plugin: socket failed: %s",
            sstrerror(errno, errbuf, sizeof(errbuf)));
 -    return (-1);
 +    return -1;
    }
  
    sa.sun_family = AF_UNIX;
      ERROR("unixsock plugin: bind failed: %s", errbuf);
      close(sock_fd);
      sock_fd = -1;
 -    return (-1);
 +    return -1;
    }
  
    status = chmod(sa.sun_path, sock_perms);
            sstrerror(errno, errbuf, sizeof(errbuf)));
      close(sock_fd);
      sock_fd = -1;
 -    return (-1);
 +    return -1;
    }
  
    status = listen(sock_fd, 8);
            sstrerror(errno, errbuf, sizeof(errbuf)));
      close(sock_fd);
      sock_fd = -1;
 -    return (-1);
 +    return -1;
    }
  
    do {
      const char *grpname;
      struct group *g;
      struct group sg;
-     char grbuf[4096];
+     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];
  
      grpname = (sock_group != NULL) ? sock_group : COLLECTD_GRP_NAME;
      g = NULL;
      }
    } while (0);
  
 -  return (0);
 +  return 0;
  } /* int us_open_socket */
  
  static void *us_handle_client(void *arg) {
      close(fdin);
      close(fdout);
      pthread_exit((void *)1);
 -    return ((void *)1);
 +    return (void *)1;
    }
  
    fhout = fdopen(fdout, "w");
      fclose(fhin); /* this closes fdin as well */
      close(fdout);
      pthread_exit((void *)1);
 -    return ((void *)1);
 +    return (void *)1;
    }
  
    /* change output buffer to line buffered mode */
      fclose(fhin);
      fclose(fhout);
      pthread_exit((void *)1);
 -    return ((void *)0);
 +    return (void *)0;
    }
  
    while (42) {
        fclose(fhin);
        fclose(fhout);
        pthread_exit((void *)1);
 -      return ((void *)1);
 +      return (void *)1;
      }
  
      if (strcasecmp(fields[0], "getval") == 0) {
    fclose(fhout);
  
    pthread_exit((void *)0);
 -  return ((void *)0);
 +  return (void *)0;
  } /* void *us_handle_client */
  
  static void *us_server_thread(void __attribute__((unused)) * arg) {
             sstrerror(errno, errbuf, sizeof(errbuf)));
    }
  
 -  return ((void *)0);
 +  return (void *)0;
  } /* void *us_server_thread */
  
  static int us_config(const char *key, const char *val) {
    if (strcasecmp(key, "SocketFile") == 0) {
      char *new_sock_file = strdup(val);
      if (new_sock_file == NULL)
 -      return (1);
 +      return 1;
  
      sfree(sock_file);
      sock_file = new_sock_file;
    } else if (strcasecmp(key, "SocketGroup") == 0) {
      char *new_sock_group = strdup(val);
      if (new_sock_group == NULL)
 -      return (1);
 +      return 1;
  
      sfree(sock_group);
      sock_group = new_sock_group;
      else
        delete_socket = 0;
    } else {
 -    return (-1);
 +    return -1;
    }
  
 -  return (0);
 +  return 0;
  } /* int us_config */
  
  static int us_init(void) {
  
    /* Initialize only once. */
    if (have_init != 0)
 -    return (0);
 +    return 0;
    have_init = 1;
  
    loop = 1;
      char errbuf[1024];
      ERROR("unixsock plugin: pthread_create failed: %s",
            sstrerror(errno, errbuf, sizeof(errbuf)));
 -    return (-1);
 +    return -1;
    }
  
 -  return (0);
 +  return 0;
  } /* int us_init */
  
  static int us_shutdown(void) {
    plugin_unregister_init("unixsock");
    plugin_unregister_shutdown("unixsock");
  
 -  return (0);
 +  return 0;
  } /* int us_shutdown */
  
  void module_register(void) {
    plugin_register_init("unixsock", us_init);
    plugin_register_shutdown("unixsock", us_shutdown);
  } /* void module_register (void) */
 -
 -/* vim: set sw=4 ts=4 sts=4 tw=78 : */