Merge branch 'collectd-4.4'
authorFlorian Forster <octo@leeloo.lan.home.verplant.org>
Sun, 6 Jul 2008 14:17:27 +0000 (16:17 +0200)
committerFlorian Forster <octo@leeloo.lan.home.verplant.org>
Sun, 6 Jul 2008 14:17:27 +0000 (16:17 +0200)
Conflicts:

src/apache.c
src/apcups.c
src/apple_sensors.c
src/battery.c
src/cpu.c
src/cpufreq.c
src/df.c
src/disk.c
src/dns.c
src/email.c
src/entropy.c
src/hddtemp.c
src/interface.c
src/ipvs.c
src/irq.c
src/load.c
src/mbmon.c
src/memcached.c
src/memory.c
src/multimeter.c
src/mysql.c
src/netlink.c
src/network.c
src/nfs.c
src/nginx.c
src/ntpd.c
src/nut.c
src/ping.c
src/processes.c
src/rrdtool.c
src/serial.c
src/snmp.c
src/swap.c
src/tape.c
src/tcpconns.c
src/users.c
src/utils_cmd_putval.c
src/vserver.c
src/wireless.c
src/xmms.c

51 files changed:
1  2 
src/apache.c
src/apcups.c
src/apple_sensors.c
src/ascent.c
src/battery.c
src/collectd.conf.in
src/collectd.h
src/common.c
src/cpu.c
src/cpufreq.c
src/df.c
src/disk.c
src/dns.c
src/email.c
src/entropy.c
src/hddtemp.c
src/interface.c
src/iptables.c
src/ipvs.c
src/irq.c
src/libvirt.c
src/load.c
src/mbmon.c
src/memcached.c
src/memory.c
src/multimeter.c
src/mysql.c
src/netlink.c
src/network.c
src/nfs.c
src/nginx.c
src/ntpd.c
src/nut.c
src/perl.c
src/ping.c
src/plugin.c
src/powerdns.c
src/processes.c
src/rrdtool.c
src/serial.c
src/snmp.c
src/swap.c
src/tape.c
src/tcpconns.c
src/users.c
src/utils_cmd_putval.c
src/utils_dns.c
src/vmem.c
src/vserver.c
src/wireless.c
src/xmms.c

diff --combined src/apache.c
@@@ -146,7 -146,7 +146,7 @@@ static int init (void
        {
                int status;
  
 -              status = snprintf (credentials, sizeof (credentials), "%s:%s",
 +              status = ssnprintf (credentials, sizeof (credentials), "%s:%s",
                                user, (pass == NULL) ? "" : pass);
                if (status >= sizeof (credentials))
                {
                                        "truncated.");
                        return (-1);
                }
 -              credentials[sizeof (credentials) - 1] = '\0';
  
                curl_easy_setopt (curl, CURLOPT_USERPWD, credentials);
        }
@@@ -198,16 -199,18 +198,16 @@@ static void submit_counter (const char 
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "apache");
-       strcpy (vl.plugin_instance, "");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "apache", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
  
        if (type_instance != NULL)
 -      {
 -              strncpy (vl.type_instance, type_instance,
 +              sstrncpy (vl.type_instance, type_instance,
                                sizeof (vl.type_instance));
 -              vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
 -      }
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  } /* void submit_counter */
  
  static void submit_gauge (const char *type, const char *type_instance,
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "apache");
-       strcpy (vl.plugin_instance, "");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "apache", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
  
        if (type_instance != NULL)
 -      {
 -              strncpy (vl.type_instance, type_instance,
 +              sstrncpy (vl.type_instance, type_instance,
                                sizeof (vl.type_instance));
 -              vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
 -      }
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  } /* void submit_counter */
  
  static void submit_scoreboard (char *buf)
diff --combined src/apcups.c
@@@ -124,7 -124,8 +124,7 @@@ static int net_open (char *host, int po
        assert ((port > 0x00000000) && (port <= 0x0000FFFF));
  
        /* Convert the port to a string */
 -      snprintf (port_str, 8, "%i", port);
 -      port_str[7] = '\0';
 +      ssnprintf (port_str, sizeof (port_str), "%i", port);
  
        /* Resolve name */
        memset ((void *) &ai_hints, '\0', sizeof (ai_hints));
@@@ -372,13 -373,12 +372,13 @@@ static void apc_submit_generic (char *t
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "apcups");
-       strcpy (vl.plugin_instance, "");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "apcups", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
 -      strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
 +      sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  }
  
  static void apc_submit (struct apc_detail_s *apcups_detail)
diff --combined src/apple_sensors.c
@@@ -88,13 -88,12 +88,13 @@@ static void as_submit (const char *type
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "apple_sensors");
-       strcpy (vl.plugin_instance, "");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "apple_sensors", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
 +      sstrncpy (vl.type, type, sizeof (vl.type))
        sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  }
  
  static int as_read (void)
                if (CFGetTypeID (property) != CFStringGetTypeID ())
                        continue;
                if (!CFStringGetCString (property,
 -                                      type, 128,
 +                                      type, sizeof (type),
                                        kCFStringEncodingASCII))
                        continue;
 -              type[127] = '\0';
 +              type[sizeof (type) - 1] = '\0';
  
                /* Copy the sensor location. This will be used as `instance'. */
                property = NULL;
                if (CFGetTypeID (property) != CFStringGetTypeID ())
                        continue;
                if (!CFStringGetCString (property,
 -                                      inst, 128,
 +                                      inst, sizeof (inst),
                                        kCFStringEncodingASCII))
                        continue;
 -              inst[127] = '\0';
 +              inst[sizeof (inst) - 1] = '\0';
                for (i = 0; i < 128; i++)
                {
                        if (inst[i] == '\0')
                if (strcmp (type, "temperature") == 0)
                {
                        value_double = ((double) value_int) / 65536.0;
-                       strcpy (type, "temperature");
+                       sstrncpy (type, "temperature", sizeof (type));
                }
                else if (strcmp (type, "temp") == 0)
                {
                        value_double = ((double) value_int) / 10.0;
-                       strcpy (type, "temperature");
+                       sstrncpy (type, "temperature", sizeof (type));
                }
                else if (strcmp (type, "fanspeed") == 0)
                {
                        value_double = ((double) value_int) / 65536.0;
-                       strcpy (type, "fanspeed");
+                       sstrncpy (type, "fanspeed", sizeof (type));
                }
                else if (strcmp (type, "voltage") == 0)
                {
                else if (strcmp (type, "adc") == 0)
                {
                        value_double = ((double) value_int) / 10.0;
-                       strcpy (type, "fanspeed");
+                       sstrncpy (type, "fanspeed", sizeof (type));
                }
                else
                {
diff --combined src/ascent.c
@@@ -91,12 -91,10 +91,12 @@@ struct player_info_
  typedef struct player_info_s player_info_t;
  #define PLAYER_INFO_STATIC_INIT { -1, -1, -1, -1, -1 }
  
 -static char *url    = NULL;
 -static char *user   = NULL;
 -static char *pass   = NULL;
 -static char *cacert = NULL;
 +static char *url         = NULL;
 +static char *user        = NULL;
 +static char *pass        = NULL;
 +static char *verify_peer = NULL;
 +static char *verify_host = NULL;
 +static char *cacert      = NULL;
  
  static CURL *curl = NULL;
  
@@@ -110,8 -108,6 +110,8 @@@ static const char *config_keys[] 
    "URL",
    "User",
    "Password",
 +  "VerifyPeer",
 +  "VerifyHost",
    "CACert"
  };
  static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
@@@ -127,19 -123,17 +127,19 @@@ static int ascent_submit_gauge (const c
    vl.values = values;
    vl.values_len = 1;
    vl.time = time (NULL);
-   strcpy (vl.host, hostname_g);
-   strcpy (vl.plugin, "ascent");
+   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+   sstrncpy (vl.plugin, "ascent", sizeof (vl.plugin));
  
    if (plugin_instance != NULL)
      sstrncpy (vl.plugin_instance, plugin_instance,
          sizeof (vl.plugin_instance));
  
 +  sstrncpy (vl.type, type, sizeof (vl.type));
 +
    if (type_instance != NULL)
      sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
  
 -  plugin_dispatch_values (type, &vl);
 +  plugin_dispatch_values (&vl);
    return (0);
  } /* }}} int ascent_submit_gauge */
  
@@@ -504,10 -498,6 +504,10 @@@ static int ascent_config (const char *k
      return (config_set (&user, value));
    else if (strcasecmp (key, "Password") == 0)
      return (config_set (&pass, value));
 +  else if (strcasecmp (key, "VerifyPeer") == 0)
 +    return (config_set (&verify_peer, value));
 +  else if (strcasecmp (key, "VerifyHost") == 0)
 +    return (config_set (&verify_host, value));
    else if (strcasecmp (key, "CACert") == 0)
      return (config_set (&cacert, value));
    else
@@@ -544,7 -534,7 +544,7 @@@ static int ascent_init (void) /* {{{ *
    {
      int status;
  
 -    status = snprintf (credentials, sizeof (credentials), "%s:%s",
 +    status = ssnprintf (credentials, sizeof (credentials), "%s:%s",
          user, (pass == NULL) ? "" : pass);
      if (status >= sizeof (credentials))
      {
            "credentials have been truncated.");
        return (-1);
      }
 -    credentials[sizeof (credentials) - 1] = '\0';
  
      curl_easy_setopt (curl, CURLOPT_USERPWD, credentials);
    }
  
    curl_easy_setopt (curl, CURLOPT_URL, url);
  
 +  if ((verify_peer == NULL) || (strcmp (verify_peer, "true") == 0))
 +    curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 1);
 +  else
 +    curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0);
 +
 +  if ((verify_host == NULL) || (strcmp (verify_host, "true") == 0))
 +    curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 2);
 +  else
 +    curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0);
 +
    if (cacert != NULL)
      curl_easy_setopt (curl, CURLOPT_CAINFO, cacert);
  
diff --combined src/battery.c
@@@ -61,7 -61,6 +61,7 @@@
  #elif KERNEL_LINUX
  static int   battery_pmu_num = 0;
  static char *battery_pmu_file = "/proc/pmu/battery_%i";
 +static const char *battery_acpi_dir = "/proc/acpi/battery";
  #endif /* KERNEL_LINUX */
  
  static int battery_init (void)
@@@ -76,7 -75,7 +76,7 @@@
  
        for (battery_pmu_num = 0; ; battery_pmu_num++)
        {
 -              len = snprintf (filename, sizeof (filename), battery_pmu_file, battery_pmu_num);
 +              len = ssnprintf (filename, sizeof (filename), battery_pmu_file, battery_pmu_num);
  
                if ((len < 0) || ((unsigned int)len >= sizeof (filename)))
                        break;
@@@ -99,12 -98,11 +99,12 @@@ static void battery_submit (const char 
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "battery");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "battery", sizeof (vl.plugin));
        sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  } /* void battery_submit */
  
  #if HAVE_IOKIT_PS_IOPOWERSOURCES_H || HAVE_IOKIT_IOKITLIB_H
@@@ -314,99 -312,6 +314,99 @@@ static void get_via_generic_iokit (doub
  }
  #endif /* HAVE_IOKIT_IOKITLIB_H */
  
 +#if KERNEL_LINUX
 +static int battery_read_acpi (const char *name)
 +{
 +      double  current = INVALID_VALUE;
 +      double  voltage = INVALID_VALUE;
 +      double  charge  = INVALID_VALUE;
 +      double *valptr = NULL;
 +      int charging = 0;
 +
 +      char filename[256];
 +      FILE *fh;
 +
 +      char buffer[1024];
 +      char *fields[8];
 +      int numfields;
 +      char *endptr;
 +      int len;
 +
 +      len = ssnprintf (filename, sizeof (filename), "%s/%s/state", battery_acpi_dir, name);
 +
 +      if ((len < 0) || ((unsigned int)len >= sizeof (filename)))
 +              return -1;
 +
 +      if ((fh = fopen (filename, "r")) == NULL) {
 +              char errbuf[1024];
 +              ERROR ("Cannot open `%s': %s", filename,
 +                      sstrerror (errno, errbuf, sizeof (errbuf)));
 +              return -1;
 +      }
 +
 +      /*
 +       * [11:00] <@tokkee> $ cat /proc/acpi/battery/BAT1/state
 +       * [11:00] <@tokkee> present:                 yes
 +       * [11:00] <@tokkee> capacity state:          ok
 +       * [11:00] <@tokkee> charging state:          charging
 +       * [11:00] <@tokkee> present rate:            1724 mA
 +       * [11:00] <@tokkee> remaining capacity:      4136 mAh
 +       * [11:00] <@tokkee> present voltage:         12428 mV
 +       */
 +      while (fgets (buffer, sizeof (buffer), fh) != NULL)
 +      {
 +              numfields = strsplit (buffer, fields, 8);
 +
 +              if (numfields < 3)
 +                      continue;
 +
 +              if ((strcmp (fields[0], "charging") == 0)
 +                              && (strcmp (fields[1], "state:") == 0))
 +              {
 +                      if (strcmp (fields[2], "charging") == 0)
 +                              charging = 1;
 +                      else
 +                              charging = 0;
 +                      continue;
 +              }
 +
 +              if ((strcmp (fields[0], "present") == 0)
 +                              && (strcmp (fields[1], "rate:") == 0))
 +                      valptr = &current;
 +              else if ((strcmp (fields[0], "remaining") == 0)
 +                              && (strcmp (fields[1], "capacity:") == 0))
 +                      valptr = &charge;
 +              else if ((strcmp (fields[0], "present") == 0)
 +                              && (strcmp (fields[1], "voltage:") == 0))
 +                      valptr = &voltage;
 +              else
 +                      continue;
 +
 +              endptr = NULL;
 +              errno  = 0;
 +              *valptr = strtod (fields[2], &endptr) / 1000.0;
 +
 +              if ((fields[2] == endptr) || (errno != 0))
 +                      *valptr = INVALID_VALUE;
 +      } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */
 +
 +      fclose (fh);
 +
 +      if ((current != INVALID_VALUE) && (charging == 0))
 +                      current *= -1;
 +
 +      if (charge != INVALID_VALUE)
 +              battery_submit ("0", "charge", charge);
 +      if (current != INVALID_VALUE)
 +              battery_submit ("0", "current", current);
 +      if (voltage != INVALID_VALUE)
 +              battery_submit ("0", "voltage", voltage);
 +
 +      return 0;
 +}
 +#endif /* KERNEL_LINUX */
 +
 +
  static int battery_read (void)
  {
  #if HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H
                double  charge  = INVALID_VALUE;
                double *valptr = NULL;
  
 -              len = snprintf (filename, sizeof (filename), battery_pmu_file, i);
 +              len = ssnprintf (filename, sizeof (filename), battery_pmu_file, i);
                if ((len < 0) || ((unsigned int)len >= sizeof (filename)))
                        continue;
  
 -              len = snprintf (batnum_str, sizeof (batnum_str), "%i", i);
 +              len = ssnprintf (batnum_str, sizeof (batnum_str), "%i", i);
                if ((len < 0) || ((unsigned int)len >= sizeof (batnum_str)))
                        continue;
  
                        battery_submit ("0", "voltage", voltage);
        }
  
 -      if (access ("/proc/acpi/battery", R_OK | X_OK) == 0)
 -      {
 -              double  current = INVALID_VALUE;
 -              double  voltage = INVALID_VALUE;
 -              double  charge  = INVALID_VALUE;
 -              double *valptr = NULL;
 -              int charging = 0;
 -
 -              struct dirent *ent;
 -              DIR *dh;
 +      walk_directory (battery_acpi_dir, battery_read_acpi);
  
 -              if ((dh = opendir ("/proc/acpi/battery")) == NULL)
 -              {
 -                      char errbuf[1024];
 -                      ERROR ("Cannot open `/proc/acpi/battery': %s",
 -                                      sstrerror (errno, errbuf, sizeof (errbuf)));
 -                      return (-1);
 -              }
 -
 -              while ((ent = readdir (dh)) != NULL)
 -              {
 -                      if (ent->d_name[0] == '.')
 -                              continue;
 -
 -                      len = snprintf (filename, sizeof (filename),
 -                                      "/proc/acpi/battery/%s/state",
 -                                      ent->d_name);
 -                      if ((len < 0) || ((unsigned int)len >= sizeof (filename)))
 -                              continue;
 -
 -                      if ((fh = fopen (filename, "r")) == NULL)
 -                      {
 -                              char errbuf[1024];
 -                              ERROR ("Cannot open `%s': %s", filename,
 -                                              sstrerror (errno, errbuf,
 -                                                      sizeof (errbuf)));
 -                              continue;
 -                      }
 -
 -                      /*
 -                       * [11:00] <@tokkee> $ cat /proc/acpi/battery/BAT1/state
 -                       * [11:00] <@tokkee> present:                 yes
 -                       * [11:00] <@tokkee> capacity state:          ok
 -                       * [11:00] <@tokkee> charging state:          charging
 -                       * [11:00] <@tokkee> present rate:            1724 mA
 -                       * [11:00] <@tokkee> remaining capacity:      4136 mAh
 -                       * [11:00] <@tokkee> present voltage:         12428 mV
 -                       */
 -                      while (fgets (buffer, sizeof (buffer), fh) != NULL)
 -                      {
 -                              numfields = strsplit (buffer, fields, 8);
 -
 -                              if (numfields < 3)
 -                                      continue;
 -
 -                              if ((strcmp (fields[0], "present") == 0)
 -                                              && (strcmp (fields[1], "rate:") == 0))
 -                                      valptr = &current;
 -                              else if ((strcmp (fields[0], "remaining") == 0)
 -                                              && (strcmp (fields[1], "capacity:") == 0))
 -                                      valptr = &charge;
 -                              else if ((strcmp (fields[0], "present") == 0)
 -                                              && (strcmp (fields[1], "voltage:") == 0))
 -                                      valptr = &voltage;
 -                              else
 -                                      valptr = NULL;
 -
 -                              if ((strcmp (fields[0], "charging") == 0)
 -                                              && (strcmp (fields[1], "state:") == 0))
 -                              {
 -                                      if (strcmp (fields[2], "charging") == 0)
 -                                              charging = 1;
 -                                      else
 -                                              charging = 0;
 -                              }
 -
 -                              if (valptr != NULL)
 -                              {
 -                                      char *endptr;
 -
 -                                      endptr = NULL;
 -                                      errno  = 0;
 -
 -                                      *valptr = strtod (fields[2], &endptr) / 1000.0;
 -
 -                                      if ((fields[2] == endptr) || (errno != 0))
 -                                              *valptr = INVALID_VALUE;
 -                              }
 -                      } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */
 -
 -                      fclose (fh);
 -
 -                      if ((current != INVALID_VALUE) && (charging == 0))
 -                                      current *= -1;
 -
 -                      if (charge != INVALID_VALUE)
 -                              battery_submit ("0", "charge", charge);
 -                      if (current != INVALID_VALUE)
 -                              battery_submit ("0", "current", current);
 -                      if (voltage != INVALID_VALUE)
 -                              battery_submit ("0", "voltage", voltage);
 -              }
 -
 -              closedir (dh);
 -      }
  #endif /* KERNEL_LINUX */
  
        return (0);
diff --combined src/collectd.conf.in
@@@ -45,13 -45,10 +45,13 @@@ FQDNLookup   tru
  @BUILD_PLUGIN_NETWORK_TRUE@LoadPlugin network
  @BUILD_PLUGIN_NFS_TRUE@LoadPlugin nfs
  @BUILD_PLUGIN_NGINX_TRUE@LoadPlugin nginx
 +@BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE@LoadPlugin notify_desktop
 +@BUILD_PLUGIN_NOTIFY_EMAIL_TRUE@LoadPlugin notify_email
  @BUILD_PLUGIN_NTPD_TRUE@LoadPlugin ntpd
  @BUILD_PLUGIN_NUT_TRUE@LoadPlugin nut
  @BUILD_PLUGIN_PERL_TRUE@LoadPlugin perl
  @BUILD_PLUGIN_PING_TRUE@LoadPlugin ping
 +@BUILD_PLUGIN_POSTGRESQL_TRUE@LoadPlugin postgresql
  @BUILD_PLUGIN_POWERDNS_TRUE@LoadPlugin powerdns
  @BUILD_PLUGIN_PROCESSES_TRUE@LoadPlugin processes
  @BUILD_PLUGIN_RRDTOOL_TRUE@LoadPlugin rrdtool
@@@ -64,7 -61,6 +64,7 @@@
  @BUILD_PLUGIN_TAPE_TRUE@LoadPlugin tape
  @BUILD_PLUGIN_TCPCONNS_TRUE@LoadPlugin tcpconns
  @BUILD_PLUGIN_TEAMSPEAK2_TRUE@LoadPlugin teamspeak2
 +@BUILD_PLUGIN_THERMAL_TRUE@LoadPlugin thermal
  @BUILD_PLUGIN_UNIXSOCK_TRUE@LoadPlugin unixsock
  @BUILD_PLUGIN_USERS_TRUE@LoadPlugin users
  @BUILD_PLUGIN_UUID_TRUE@LoadPlugin uuid
  
  #<Plugin exec>
  #     Exec "user:group" "/path/to/exec"
- #     NotificationExec "/path/to/exec"
+ #     NotificationExec "user:group" "/path/to/exec"
  #</Plugin>
  
  @BUILD_PLUGIN_HDDTEMP_TRUE@<Plugin hddtemp>
  #     CACert "/etc/ssl/ca.crt"
  #</Plugin>
  
 +#<Plugin notify_desktop>
 +#     OkayTimeout 1000
 +#     WarningTimeout 5000
 +#     FailureTimeout 0
 +#</Plugin>
 +
 +#<Plugin notify_email>
 +#       SMTPServer "localhost"
 +#     SMTPPort 25
 +#     SMTPUser "my-username"
 +#     SMTPPassword "my-password"
 +#     From "collectd@main0server.com"
 +#     # <WARNING/FAILURE/OK> on <hostname>. beware! do not use not more than two %s in this string!!!
 +#     Subject "Aaaaaa!! %s on %s!!!!!"
 +#     Recipient "email1@domain1.net"
 +#     Recipient "email2@domain2.com"
 +#</Plugin>
 +
  #<Plugin ntpd>
  #     Host "localhost"
  #     Port 123
  #     TTL 255
  #</Plugin>
  
 +#<Plugin postgresql>
 +#     <Database foo>
 +#             Host "hostname"
 +#             Port 5432
 +#             User "username"
 +#             Password "secret"
 +#
 +#             SSLMode "prefer"
 +#             KRBSrvName "kerberos_service_name"
 +#     </Database>
 +#
 +#     <Database bar>
 +#             Service "service_name"
 +#     </Database>
 +#</Plugin>
 +
  #<Plugin powerdns>
  #  <Server "server_name">
  #    Collect "latency"
  #     Server "8767"
  #</Plugin>
  
 +#<Plugin thermal>
 +#     ForceUseProcfs false
 +#     Device "THRM"
 +#     IgnoreSelected false
 +#</Plugin>
 +
  #<Plugin unixsock>
  #     SocketFile "@prefix@/var/run/@PACKAGE_NAME@-unixsock"
  #     SocketGroup "collectd"
diff --combined src/collectd.h
@@@ -56,9 -56,6 +56,9 @@@
  #if HAVE_STDINT_H
  # include <stdint.h>
  #endif
 +#if HAVE_STDBOOL_H
 +# include <stdbool.h>
 +#endif
  #if HAVE_UNISTD_H
  # include <unistd.h>
  #endif
  # define __attribute__(x) /**/
  #endif
  
+ #if __GNUC__
+ # pragma GCC poison strcpy strcat sprintf strtok
+ #endif
  extern char hostname_g[];
  extern int  interval_g;
  
diff --combined src/common.c
@@@ -61,19 -61,6 +61,19 @@@ char *sstrncpy (char *dest, const char 
        return (dest);
  } /* char *sstrncpy */
  
 +int ssnprintf (char *dest, size_t n, const char *format, ...)
 +{
 +      int ret = 0;
 +      va_list ap;
 +
 +      va_start (ap, format);
 +      ret = vsnprintf (dest, n, format, ap);
 +      dest[n - 1] = '\0';
 +      va_end (ap);
 +
 +      return (ret);
 +} /* int ssnprintf */
 +
  char *sstrdup (const char *s)
  {
        char *r;
  
        if((r = strdup (s)) == NULL)
        {
-               DEBUG ("Not enough memory.");
-               exit(3);
+               ERROR ("Not enough memory.");
+               exit (3);
        }
  
        return (r);
- }
+ } /* char *sstrdup */
  
  /* Even though Posix requires "strerror_r" to return an "int",
   * some systems (e.g. the GNU libc) return a "char *" _and_
@@@ -104,7 -91,7 +104,7 @@@ char *sstrerror (int errnum, char *buf
                pthread_mutex_lock (&strerror_r_lock);
  
                temp = strerror (errnum);
 -              strncpy (buf, temp, buflen);
 +              sstrncpy (buf, temp, buflen);
  
                pthread_mutex_unlock (&strerror_r_lock);
        }
                if (buf[0] == '\0')
                {
                        if ((temp != NULL) && (temp != buf) && (temp[0] != '\0'))
 -                              strncpy (buf, temp, buflen);
 +                              sstrncpy (buf, temp, buflen);
                        else
 -                              strncpy (buf, "strerror_r did not return "
 +                              sstrncpy (buf, "strerror_r did not return "
                                                "an error message", buflen);
                }
        }
  #else
        if (strerror_r (errnum, buf, buflen) != 0)
        {
 -              snprintf (buf, buflen, "Error #%i; "
 +              ssnprintf (buf, buflen, "Error #%i; "
                                "Additionally, strerror_r failed.",
                                errnum);
        }
  #endif /* STRERROR_R_CHAR_P */
  
 -      buf[buflen - 1] = '\0';
        return (buf);
  } /* char *sstrerror */
  
@@@ -143,12 -131,12 +143,12 @@@ void *smalloc (size_t size
  
        if ((r = malloc (size)) == NULL)
        {
-               DEBUG("Not enough memory.");
-               exit(3);
+               ERROR ("Not enough memory.");
+               exit (3);
        }
  
-       return r;
- }
+       return (r);
+ } /* void *smalloc */
  
  #if 0
  void sfree (void **ptr)
@@@ -236,7 -224,7 +236,7 @@@ int strsplit (char *string, char **fiel
        i = 0;
        ptr = string;
        saveptr = NULL;
-       while ((fields[i] = strtok_r (ptr, " \t", &saveptr)) != NULL)
+       while ((fields[i] = strtok_r (ptr, " \t\r\n", &saveptr)) != NULL)
        {
                ptr = NULL;
                i++;
@@@ -388,7 -376,7 +388,7 @@@ int check_create_dir (const char *file_
  
        if ((len = strlen (file_orig)) < 1)
                return (-1);
 -      else if (len >= 512)
 +      else if (len >= sizeof (file_copy))
                return (-1);
  
        /*
        /*
         * Create a copy for `strtok_r' to destroy
         */
 -      strncpy (file_copy, file_orig, 512);
 -      file_copy[511] = '\0';
 +      sstrncpy (file_copy, file_orig, sizeof (file_copy));
  
        /*
         * Break into components. This will eat up several slashes in a row and
@@@ -488,7 -477,8 +488,7 @@@ int get_kstat (kstat_t **ksp_ptr, char 
        if (kc == NULL)
                return (-1);
  
 -      snprintf (ident, 128, "%s,%i,%s", module, instance, name);
 -      ident[127] = '\0';
 +      ssnprintf (ident, sizeof (ident), "%s,%i,%s", module, instance, name);
  
        if (*ksp_ptr == NULL)
        {
@@@ -673,21 -663,21 +673,21 @@@ int format_name (char *ret, int ret_len
        if ((plugin_instance == NULL) || (strlen (plugin_instance) == 0))
        {
                if ((type_instance == NULL) || (strlen (type_instance) == 0))
 -                      status = snprintf (ret, ret_len, "%s/%s/%s",
 +                      status = ssnprintf (ret, ret_len, "%s/%s/%s",
                                        hostname, plugin, type);
                else
 -                      status = snprintf (ret, ret_len, "%s/%s/%s-%s",
 +                      status = ssnprintf (ret, ret_len, "%s/%s/%s-%s",
                                        hostname, plugin, type,
                                        type_instance);
        }
        else
        {
                if ((type_instance == NULL) || (strlen (type_instance) == 0))
 -                      status = snprintf (ret, ret_len, "%s/%s-%s/%s",
 +                      status = ssnprintf (ret, ret_len, "%s/%s-%s/%s",
                                        hostname, plugin, plugin_instance,
                                        type);
                else
 -                      status = snprintf (ret, ret_len, "%s/%s-%s/%s-%s",
 +                      status = ssnprintf (ret, ret_len, "%s/%s-%s/%s-%s",
                                        hostname, plugin, plugin_instance,
                                        type, type_instance);
        }
@@@ -848,63 -838,26 +848,63 @@@ int notification_init (notification_t *
        n->severity = severity;
  
        if (message != NULL)
 -              strncpy (n->message, message, sizeof (n->message));
 +              sstrncpy (n->message, message, sizeof (n->message));
        if (host != NULL)
 -              strncpy (n->host, host, sizeof (n->host));
 +              sstrncpy (n->host, host, sizeof (n->host));
        if (plugin != NULL)
 -              strncpy (n->plugin, plugin, sizeof (n->plugin));
 +              sstrncpy (n->plugin, plugin, sizeof (n->plugin));
        if (plugin_instance != NULL)
 -              strncpy (n->plugin_instance, plugin_instance,
 +              sstrncpy (n->plugin_instance, plugin_instance,
                                sizeof (n->plugin_instance));
        if (type != NULL)
 -              strncpy (n->type, type, sizeof (n->type));
 +              sstrncpy (n->type, type, sizeof (n->type));
        if (type_instance != NULL)
 -              strncpy (n->type_instance, type_instance,
 +              sstrncpy (n->type_instance, type_instance,
                                sizeof (n->type_instance));
  
 -      n->message[sizeof (n->message) - 1] = '\0';
 -      n->host[sizeof (n->host) - 1] = '\0';
 -      n->plugin[sizeof (n->plugin) - 1] = '\0';
 -      n->plugin_instance[sizeof (n->plugin_instance) - 1] = '\0';
 -      n->type[sizeof (n->type) - 1] = '\0';
 -      n->type_instance[sizeof (n->type_instance) - 1] = '\0';
 -
        return (0);
  } /* int notification_init */
 +
 +int walk_directory (const char *dir, dirwalk_callback_f callback)
 +{
 +      struct dirent *ent;
 +      DIR *dh;
 +      int ok = 0;
 +
 +      if ((dh = opendir (dir)) == NULL)
 +      {
 +              char errbuf[1024];
 +              ERROR ("Cannot open '%s': %s", dir,
 +                              sstrerror (errno, errbuf, sizeof (errbuf)));
 +              return -1;
 +      }
 +
 +      while ((ent = readdir (dh)) != NULL)
 +      {
 +              if (ent->d_name[0] == '.')
 +                      continue;
 +
 +              if (!callback(ent->d_name))
 +                      ++ok;
 +      }
 +
 +      closedir (dh);
 +
 +      return ok ? 0 : -1;
 +}
 +
 +int read_file_contents (const char *filename, char *buf, int bufsize)
 +{
 +      FILE *fh;
 +      int n;
 +
 +      if ((fh = fopen (filename, "r")) == NULL)
 +              return -1;
 +
 +      n = fread(buf, 1, bufsize, fh);
 +      fclose(fh);
 +
 +      return n;
 +}
 +
 +
diff --combined src/cpu.c
+++ b/src/cpu.c
@@@ -180,14 -180,14 +180,14 @@@ static void submit (int cpu_num, const 
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "cpu");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "cpu", sizeof (vl.plugin));
 -      snprintf (vl.plugin_instance, sizeof (vl.type_instance),
 +      ssnprintf (vl.plugin_instance, sizeof (vl.type_instance),
                        "%i", cpu_num);
-       strcpy (vl.type, "cpu");
 -      vl.plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
++      sstrncpy (vl.type, "cpu", sizeof (vl.type));
        sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values ("cpu", &vl);
 +      plugin_dispatch_values (&vl);
  }
  
  static int cpu_read (void)
diff --combined src/cpufreq.c
@@@ -37,7 -37,7 +37,7 @@@ static int cpufreq_init (void
  
        while (1)
        {
 -              status = snprintf (filename, sizeof (filename),
 +              status = ssnprintf (filename, sizeof (filename),
                                "/sys/devices/system/cpu/cpu%d/cpufreq/"
                                "scaling_cur_freq", num_cpu);
                if ((status < 1) || ((unsigned int)status >= sizeof (filename)))
@@@ -68,13 -68,12 +68,13 @@@ static void cpufreq_submit (int cpu_num
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "cpufreq");
-       strcpy (vl.type, "cpufreq");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "cpufreq", sizeof (vl.plugin));
 -      snprintf (vl.type_instance, sizeof (vl.type_instance),
++      sstrncpy (vl.type, "cpufreq", sizeof (vl.type));
 +      ssnprintf (vl.type_instance, sizeof (vl.type_instance),
                        "%i", cpu_num);
  
 -      plugin_dispatch_values ("cpufreq", &vl);
 +      plugin_dispatch_values (&vl);
  }
  
  static int cpufreq_read (void)
@@@ -88,7 -87,7 +88,7 @@@
  
        for (i = 0; i < num_cpu; i++)
        {
 -              status = snprintf (filename, sizeof (filename),
 +              status = ssnprintf (filename, sizeof (filename),
                                "/sys/devices/system/cpu/cpu%d/cpufreq/"
                                "scaling_cur_freq", i);
                if ((status < 1) || ((unsigned int)status >= sizeof (filename)))
diff --combined src/df.c
+++ b/src/df.c
@@@ -125,13 -125,12 +125,13 @@@ static void df_submit (char *df_name
        vl.values = values;
        vl.values_len = 2;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "df");
-       strcpy (vl.plugin_instance, "");
-       strcpy (vl.type, "df");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "df", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
 -      strncpy (vl.type_instance, df_name, sizeof (vl.type_instance));
++      sstrncpy (vl.type, "df", sizeof (vl.host));
 +      sstrncpy (vl.type_instance, df_name, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values ("df", &vl);
 +      plugin_dispatch_values (&vl);
  } /* void df_submit */
  
  static int df_read (void)
  
                if (strcmp (mnt_ptr->dir, "/") == 0)
                {
 -                      strncpy (mnt_name, "root", sizeof (mnt_name));
 +                      sstrncpy (mnt_name, "root", sizeof (mnt_name));
                }
                else
                {
                        int i, len;
  
 -                      strncpy (mnt_name, mnt_ptr->dir + 1, sizeof (mnt_name));
 +                      sstrncpy (mnt_name, mnt_ptr->dir + 1, sizeof (mnt_name));
                        len = strlen (mnt_name);
  
                        for (i = 0; i < len; i++)
diff --combined src/disk.c
@@@ -213,13 -213,12 +213,13 @@@ static void disk_submit (const char *pl
        vl.values = values;
        vl.values_len = 2;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "disk");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "disk", sizeof (vl.plugin));
 -      strncpy (vl.plugin_instance, plugin_instance,
 +      sstrncpy (vl.plugin_instance, plugin_instance,
                        sizeof (vl.plugin_instance));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  } /* void disk_submit */
  
  #if HAVE_IOKIT_IOKITLIB_H
@@@ -376,8 -375,7 +376,8 @@@ static int disk_read (void
                write_tme = dict_get_value (stats_dict,
                                kIOBlockStorageDriverStatisticsTotalWriteTimeKey);
  
 -              if (snprintf (disk_name, 64, "%i-%i", disk_major, disk_minor) >= 64)
 +              if (ssnprintf (disk_name, sizeof (disk_name),
 +                              "%i-%i", disk_major, disk_minor) >= sizeof (disk_name))
                {
                        DEBUG ("snprintf (major, minor) failed.");
                        CFRelease (child_dict);
diff --combined src/dns.c
+++ b/src/dns.c
@@@ -299,12 -299,11 +299,12 @@@ static void submit_counter (const char 
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "dns");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "dns", sizeof (vl.plugin));
 -      strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
 +      sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  } /* void submit_counter */
  
  static void submit_octets (counter_t queries, counter_t responses)
        vl.values = values;
        vl.values_len = 2;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "dns");
-       strcpy (vl.type, "dns_octets");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "dns", sizeof (vl.plugin));
++      sstrncpy (vl.type, "dns_octets", sizeof (vl.type));
  
 -      plugin_dispatch_values ("dns_octets", &vl);
 +      plugin_dispatch_values (&vl);
  } /* void submit_counter */
  
  static int dns_read (void)
diff --combined src/email.c
@@@ -243,7 -243,6 +243,6 @@@ static void type_list_incr (type_list_
  static void *collect (void *arg)
  {
        collector_t *this = (collector_t *)arg;
-       pthread_t    self = pthread_self ();
  
        while (1) {
                int loop = 1;
                 * thread and connection management */
                this->socket = connection->socket;
  
-               log_debug ("[thread #%5lu] handling connection on fd #%i",
-                               self, fileno (this->socket));
+               log_debug ("collect: handling connection on fd #%i",
+                               fileno (this->socket));
  
                while (loop) {
                        /* 256 bytes ought to be enough for anybody ;-) */
  
                                if (0 != errno) {
                                        char errbuf[1024];
-                                       log_err ("[thread #%5lu] reading from socket (fd #%i) "
-                                                       "failed: %s", self, fileno (this->socket),
+                                       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 ("[thread #%5lu] line too long (> %zu characters): "
-                                               "'%s' (truncated)",
-                                               (unsigned long) self, sizeof (line) - 1, line);
+                               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]))
  
                        line[len - 1] = '\0';
  
-                       log_debug ("[thread #%5lu] line = '%s'", self, line);
+                       log_debug ("collect: line = '%s'", line);
  
                        if (':' != line[1]) {
-                               log_err ("[thread #%5lu] syntax error in line '%s'",
-                                               self, line);
+                               log_err ("collect: syntax error in line '%s'", line);
                                continue;
                        }
  
                                int  bytes = 0;
  
                                if (NULL == tmp) {
-                                       log_err ("[thread #%5lu] syntax error in line '%s'",
-                                                       self, line);
+                                       log_err ("collect: syntax error in line '%s'", line);
                                        continue;
                                }
  
                                } while (NULL != (type = strtok_r (NULL, ",", &ptr)));
                        }
                        else {
-                               log_err ("[thread #%5lu] unknown type '%c'", self, line[0]);
+                               log_err ("collect: unknown type '%c'", line[0]);
                        }
                } /* while (loop) */
  
@@@ -394,9 -390,9 +390,7 @@@ static void *open_connection (void *arg
        }
  
        addr.sun_family = AF_UNIX;
--
 -      strncpy (addr.sun_path, path, (size_t)(UNIX_PATH_MAX - 1));
 -      addr.sun_path[UNIX_PATH_MAX - 1] = '\0';
 +      sstrncpy (addr.sun_path, path, (size_t)(UNIX_PATH_MAX - 1));
-       unlink (addr.sun_path);
  
        errno = 0;
        if (-1 == bind (connector_socket, (struct sockaddr *)&addr,
@@@ -657,12 -653,11 +651,12 @@@ static void email_submit (const char *t
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "email");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "email", sizeof (vl.plugin));
 -      strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
 +      sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  } /* void email_submit */
  
  /* Copy list l1 to list l2. l2 may partly exist already, but it is assumed
diff --combined src/entropy.c
@@@ -39,13 -39,12 +39,11 @@@ static void entropy_submit (double entr
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "entropy");
-       strcpy (vl.plugin_instance, "");
-       strcpy (vl.type, "entropy");
-       strcpy (vl.type_instance, "");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "entropy", sizeof (vl.plugin));
 -      sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
 -      sstrncpy (vl.type_instance, "", sizeof (vl.type_instance));
++      sstrncpy (vl.type, "entropy", sizeof (vl.type));
  
 -      plugin_dispatch_values ("entropy", &vl);
 +      plugin_dispatch_values (&vl);
  }
  
  static int entropy_read (void)
diff --combined src/hddtemp.c
@@@ -223,10 -223,11 +223,10 @@@ static int hddtemp_config (const char *
        {
                int port = (int) (atof (value));
                if ((port > 0) && (port <= 65535))
 -                      snprintf (hddtemp_port, sizeof (hddtemp_port),
 +                      ssnprintf (hddtemp_port, sizeof (hddtemp_port),
                                        "%i", port);
                else
 -                      strncpy (hddtemp_port, value, sizeof (hddtemp_port));
 -              hddtemp_port[sizeof (hddtemp_port) - 1] = '\0';
 +                      sstrncpy (hddtemp_port, value, sizeof (hddtemp_port));
        }
        else if (strcasecmp (key, "TranslateDevicename") == 0)
        {
@@@ -429,7 -430,7 +429,7 @@@ static char *hddtemp_get_major_minor (c
        if ((ret = (char *) malloc (128 * sizeof (char))) == NULL)
                return (NULL);
  
 -      if (snprintf (ret, 128, "%i-%i", list->major, list->minor) >= 128)
 +      if (ssnprintf (ret, 128, "%i-%i", list->major, list->minor) >= 128)
        {
                free (ret);
                return (NULL);
@@@ -448,12 -449,11 +448,12 @@@ static void hddtemp_submit (char *type_
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "hddtemp");
-       strcpy (vl.type, "temperature");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "hddtemp", sizeof (vl.plugin));
 -      strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
++      sstrncpy (vl.type, "temperature", sizeof (vl.type));
 +      sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values ("temperature", &vl);
 +      plugin_dispatch_values (&vl);
  }
  
  static int hddtemp_read (void)
diff --combined src/interface.c
@@@ -197,12 -197,11 +197,12 @@@ static void if_submit (const char *dev
        vl.values = values;
        vl.values_len = 2;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "interface");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "interface", sizeof (vl.plugin));
 -      strncpy (vl.type_instance, dev, sizeof (vl.type_instance));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
 +      sstrncpy (vl.type_instance, dev, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  } /* void if_submit */
  
  static int interface_read (void)
diff --combined src/iptables.c
@@@ -114,7 -114,8 +114,7 @@@ static int iptables_config (const char 
                        free (value_copy);
                        return (1);
                }
 -              strncpy (temp.table, table, table_len);
 -              temp.table[table_len] = '\0';
 +              sstrncpy (temp.table, table, table_len);
  
                chain_len = strlen (chain);
                if ((unsigned int)chain_len >= sizeof(temp.chain))
                        free (value_copy);
                        return (1);
                }
 -              strncpy (temp.chain, chain, chain_len);
 -              temp.chain[chain_len] = '\0'; 
 +              sstrncpy (temp.chain, chain, chain_len);
  
                if (fields_num >= 3)
                {
                }
  
                if (fields_num >= 4)
 -                  strncpy (temp.name, fields[3], sizeof (temp.name) - 1);
 +                  sstrncpy (temp.name, fields[3], sizeof (temp.name));
  
                free (value_copy);
                value_copy = NULL;
@@@ -219,35 -221,34 +219,35 @@@ static int submit_match (const struct i
      vl.values = values;
      vl.values_len = 1;
      vl.time = time (NULL);
-     strcpy (vl.host, hostname_g);
-     strcpy (vl.plugin, "iptables");
+     sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+     sstrncpy (vl.plugin, "iptables", sizeof (vl.plugin));
  
 -    status = snprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
 +    status = ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
            "%s-%s", chain->table, chain->chain);
      if ((status < 1) || ((unsigned int)status >= sizeof (vl.plugin_instance)))
        return (0);
  
      if (chain->name[0] != '\0')
      {
 -      strncpy (vl.type_instance, chain->name, sizeof (vl.type_instance));
 +      sstrncpy (vl.type_instance, chain->name, sizeof (vl.type_instance));
      }
      else
      {
        if (chain->rule_type == RTYPE_NUM)
 -          snprintf (vl.type_instance, sizeof (vl.type_instance),
 +          ssnprintf (vl.type_instance, sizeof (vl.type_instance),
                    "%i", chain->rule.num);
        else
 -          strncpy (vl.type_instance, (char *) match->data,
 +          sstrncpy (vl.type_instance, (char *) match->data,
                    sizeof (vl.type_instance));
      }
 -    vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
  
-     strcpy (vl.type, "ipt_bytes");
++    sstrncpy (vl.type, "ipt_bytes", sizeof (vl.type));
      values[0].counter = (counter_t) entry->counters.bcnt;
 -    plugin_dispatch_values ("ipt_bytes", &vl);
 +    plugin_dispatch_values (&vl);
  
-     strcpy (vl.type, "ipt_packets");
++    sstrncpy (vl.type, "ipt_packets", sizeof (vl.type));
      values[0].counter = (counter_t) entry->counters.pcnt;
 -    plugin_dispatch_values ("ipt_packets", &vl);
 +    plugin_dispatch_values (&vl);
  
      return (0);
  } /* void submit_match */
diff --combined src/ipvs.c
@@@ -191,7 -191,7 +191,7 @@@ static int get_pi (struct ip_vs_service
  
        /* inet_ntoa() returns a pointer to a statically allocated buffer
         * I hope non-glibc systems behave the same */
 -      len = snprintf (pi, size, "%s_%s%u", inet_ntoa (addr),
 +      len = ssnprintf (pi, size, "%s_%s%u", inet_ntoa (addr),
                        (se->protocol == IPPROTO_TCP) ? "TCP" : "UDP",
                        ntohs (se->port));
  
@@@ -215,7 -215,7 +215,7 @@@ static int get_ti (struct ip_vs_dest_en
  
        /* inet_ntoa() returns a pointer to a statically allocated buffer
         * I hope non-glibc systems behave the same */
 -      len = snprintf (ti, size, "%s_%u", inet_ntoa (addr),
 +      len = ssnprintf (ti, size, "%s_%u", inet_ntoa (addr),
                        ntohs (de->port));
  
        if ((0 > len) || (size <= len)) {
@@@ -238,14 -238,12 +238,14 @@@ static void cipvs_submit_connections (c
        vl.time     = time (NULL);
        vl.interval = interval_g;
  
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "ipvs");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "ipvs", sizeof (vl.plugin));
        sstrncpy (vl.plugin_instance, pi, sizeof (vl.plugin_instance));
-       strcpy (vl.type, "connections");
 -      sstrncpy (vl.type_instance, (NULL != ti) ? ti : "total", sizeof (vl.type_instance));
++      sstrncpy (vl.type, "connections", sizeof (vl.type));
 +      sstrncpy (vl.type_instance, (NULL != ti) ? ti : "total",
 +              sizeof (vl.type_instance));
  
 -      plugin_dispatch_values ("connections", &vl);
 +      plugin_dispatch_values (&vl);
        return;
  } /* cipvs_submit_connections */
  
@@@ -264,14 -262,12 +264,14 @@@ static void cipvs_submit_if (char *pi, 
        vl.time     = time (NULL);
        vl.interval = interval_g;
  
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "ipvs");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "ipvs", sizeof (vl.plugin));
        sstrncpy (vl.plugin_instance, pi, sizeof (vl.plugin_instance));
 -      sstrncpy (vl.type_instance, (NULL != ti) ? ti : "total", sizeof (vl.type_instance));
 +      sstrncpy (vl.type, t, sizeof (vl.type));
 +      sstrncpy (vl.type_instance, (NULL != ti) ? ti : "total",
 +              sizeof (vl.type_instance));
  
 -      plugin_dispatch_values (t, &vl);
 +      plugin_dispatch_values (&vl);
        return;
  } /* cipvs_submit_if */
  
diff --combined src/irq.c
+++ b/src/irq.c
@@@ -132,16 -132,15 +132,16 @@@ static void irq_submit (unsigned int ir
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "irq");
-       strcpy (vl.type, "irq");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "irq", sizeof (vl.plugin));
++      sstrncpy (vl.type, "irq", sizeof (vl.type));
  
 -      status = snprintf (vl.type_instance, sizeof (vl.type_instance),
 +      status = ssnprintf (vl.type_instance, sizeof (vl.type_instance),
                        "%u", irq);
        if ((status < 1) || ((unsigned int)status >= sizeof (vl.type_instance)))
                return;
  
 -      plugin_dispatch_values ("irq", &vl);
 +      plugin_dispatch_values (&vl);
  } /* void irq_submit */
  
  static int irq_read (void)
diff --combined src/libvirt.c
@@@ -634,7 -634,7 +634,7 @@@ ignore_device_match (ignorelist_t *il, 
          ERROR ("libvirt plugin: malloc failed.");
          return 0;
      }
 -    snprintf (name, n, "%s:%s", domname, devpath);
 +    ssnprintf (name, n, "%s:%s", domname, devpath);
      r = ignorelist_match (il, name);
      free (name);
      return r;
@@@ -652,7 -652,8 +652,7 @@@ init_value_list (value_list_t *vl, time
      vl->time = t;
      vl->interval = interval_g;
  
 -    strncpy (vl->plugin, "libvirt", sizeof (vl->plugin));
 -    vl->plugin[sizeof (vl->plugin) - 1] = '\0';
 +    sstrncpy (vl->plugin, "libvirt", sizeof (vl->plugin));
  
      vl->host[0] = '\0';
      host_ptr = vl->host;
          n = DATA_MAX_NAME_LEN - strlen (vl->host) - 2;
  
          if (i > 0 && n >= 1) {
-             strcat (vl->host, ":");
+             strncat (vl->host, ":", 1);
              n--;
          }
  
@@@ -705,9 -706,7 +705,9 @@@ cpu_submit (unsigned long long cpu_time
      vl.values = values;
      vl.values_len = 1;
  
 -    plugin_dispatch_values (type, &vl);
 +    sstrncpy (vl.type, type, sizeof (vl.type));
 +
 +    plugin_dispatch_values (&vl);
  }
  
  static void
@@@ -724,10 -723,10 +724,10 @@@ vcpu_submit (counter_t cpu_time
      vl.values = values;
      vl.values_len = 1;
  
 -    snprintf (vl.type_instance, sizeof (vl.type_instance), "%d", vcpu_nr);
 -    vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
 +    sstrncpy (vl.type, type, sizeof (vl.type));
 +    ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%d", vcpu_nr);
  
 -    plugin_dispatch_values (type, &vl);
 +    plugin_dispatch_values (&vl);
  }
  
  static void
@@@ -745,10 -744,10 +745,10 @@@ submit_counter2 (const char *type, coun
      vl.values = values;
      vl.values_len = 2;
  
 -    strncpy (vl.type_instance, devname, sizeof (vl.type_instance));
 -    vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
 +    sstrncpy (vl.type, type, sizeof (vl.type));
 +    sstrncpy (vl.type_instance, devname, sizeof (vl.type_instance));
  
 -    plugin_dispatch_values (type, &vl);
 +    plugin_dispatch_values (&vl);
  } /* void submit_counter2 */
  
  static int
diff --combined src/load.c
@@@ -51,11 -51,10 +51,11 @@@ static void load_submit (gauge_t snum, 
        vl.values = values;
        vl.values_len = STATIC_ARRAY_SIZE (values);
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "load");
-       strcpy (vl.type, "load");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "load", sizeof (vl.plugin));
++      sstrncpy (vl.type, "load", sizeof (vl.type));
  
 -      plugin_dispatch_values ("load", &vl);
 +      plugin_dispatch_values (&vl);
  }
  
  static int load_read (void)
diff --combined src/mbmon.c
@@@ -228,12 -228,11 +228,12 @@@ static void mbmon_submit (const char *t
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "mbmon");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "mbmon", sizeof (vl.plugin));
 -      strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
 +      sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  } /* void mbmon_submit */
  
  /* Trim trailing whitespace from a string. */
diff --combined src/memcached.c
@@@ -200,10 -200,11 +200,10 @@@ static int memcached_config (const cha
        } else if (strcasecmp (key, "Port") == 0) {
                int port = (int) (atof (value));
                if ((port > 0) && (port <= 65535)) {
 -                      snprintf (memcached_port, sizeof (memcached_port), "%i", port);
 +                      ssnprintf (memcached_port, sizeof (memcached_port), "%i", port);
                } else {
 -                      strncpy (memcached_port, value, sizeof (memcached_port));
 +                      sstrncpy (memcached_port, value, sizeof (memcached_port));
                }
 -              memcached_port[sizeof (memcached_port) - 1] = '\0';
        } else {
                return -1;
        }
@@@ -223,13 -224,15 +223,13 @@@ static void submit_counter (const char 
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "memcached");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
        if (type_inst != NULL)
 -      {
 -              strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
 -              vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
 -      }
 +              sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  } /* void memcached_submit_cmd */
  /* }}} */
  
@@@ -245,13 -248,15 +245,13 @@@ static void submit_counter2 (const cha
        vl.values = values;
        vl.values_len = 2;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "memcached");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
        if (type_inst != NULL)
 -      {
 -              strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
 -              vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
 -      }
 +              sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  } /* void memcached_submit_cmd */
  /* }}} */
  
@@@ -266,13 -271,15 +266,13 @@@ static void submit_gauge (const char *t
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "memcached");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
        if (type_inst != NULL)
 -      {
 -              strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
 -              vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
 -      }
 +              sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  }
  /* }}} */
  
@@@ -288,13 -295,15 +288,13 @@@ static void submit_gauge2 (const char *
        vl.values = values;
        vl.values_len = 2;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "memcached");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "memcached", sizeof (vl.plugin));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
        if (type_inst != NULL)
 -      {
 -              strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
 -              vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
 -      }
 +              sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  }
  /* }}} */
  
diff --combined src/memory.c
@@@ -109,12 -109,12 +109,12 @@@ static void memory_submit (const char *
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "memory");
-       strcpy (vl.type, "memory");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "memory", sizeof (vl.plugin));
 -      strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 -      vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
++      sstrncpy (vl.type, "memory", sizeof (vl.type));
 +      sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values ("memory", &vl);
 +      plugin_dispatch_values (&vl);
  }
  
  static int memory_read (void)
diff --combined src/multimeter.c
@@@ -216,11 -216,10 +216,11 @@@ static void multimeter_submit (double v
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "multimeter");
-       strcpy (vl.type, "multimeter");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "multimeter", sizeof (vl.plugin));
++      sstrncpy (vl.type, "multimeter", sizeof (vl.type));
  
 -      plugin_dispatch_values ("multimeter", &vl);
 +      plugin_dispatch_values (&vl);
  }
  
  static int multimeter_read (void)
diff --combined src/mysql.c
@@@ -126,12 -126,11 +126,12 @@@ static void counter_submit (const char 
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "mysql");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "mysql", sizeof (vl.plugin));
 -      strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
 +      sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  } /* void counter_submit */
  
  static void qcache_submit (counter_t hits, counter_t inserts,
        vl.values = values;
        vl.values_len = 5;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "mysql");
-       strcpy (vl.type, "mysql_qcache");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "mysql", sizeof (vl.plugin));
++      sstrncpy (vl.type, "mysql_qcache", sizeof (vl.type));
  
 -      plugin_dispatch_values ("mysql_qcache", &vl);
 +      plugin_dispatch_values (&vl);
  } /* void qcache_submit */
  
  static void threads_submit (gauge_t running, gauge_t connected, gauge_t cached,
        vl.values = values;
        vl.values_len = 4;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "mysql");
-       strcpy (vl.type, "mysql_threads");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "mysql", sizeof (vl.plugin));
++      sstrncpy (vl.type, "mysql_threads", sizeof (vl.type));
  
 -      plugin_dispatch_values ("mysql_threads", &vl);
 +      plugin_dispatch_values (&vl);
  } /* void threads_submit */
  
  static void traffic_submit (counter_t rx, counter_t tx)
        vl.values = values;
        vl.values_len = 2;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "mysql");
-       strcpy (vl.type, "mysql_octets");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "mysql", sizeof (vl.plugin));
++      sstrncpy (vl.type, "mysql_octets", sizeof (vl.type));
  
 -      plugin_dispatch_values ("mysql_octets", &vl);
 +      plugin_dispatch_values (&vl);
  } /* void traffic_submit */
  
  static int mysql_read (void)
diff --combined src/netlink.c
@@@ -171,15 -171,14 +171,15 @@@ static void submit_one (const char *dev
    vl.values = values;
    vl.values_len = 1;
    vl.time = time (NULL);
-   strcpy (vl.host, hostname_g);
-   strcpy (vl.plugin, "netlink");
+   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+   sstrncpy (vl.plugin, "netlink", sizeof (vl.plugin));
 -  strncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
 +  sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
 +  sstrncpy (vl.type, type, sizeof (vl.type));
  
    if (type_instance != NULL)
 -    strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 +    sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
  
 -  plugin_dispatch_values (type, &vl);
 +  plugin_dispatch_values (&vl);
  } /* void submit_one */
  
  static void submit_two (const char *dev, const char *type,
    vl.values = values;
    vl.values_len = 2;
    vl.time = time (NULL);
-   strcpy (vl.host, hostname_g);
-   strcpy (vl.plugin, "netlink");
+   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+   sstrncpy (vl.plugin, "netlink", sizeof (vl.plugin));
 -  strncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
 +  sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
 +  sstrncpy (vl.type, type, sizeof (vl.type));
  
    if (type_instance != NULL)
 -    strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 +    sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
  
 -  plugin_dispatch_values (type, &vl);
 +  plugin_dispatch_values (&vl);
  } /* void submit_two */
  
  static int link_filter (const struct sockaddr_nl *sa,
 -    const struct nlmsghdr *nmh, void *args)
 +    struct nlmsghdr *nmh, void *args)
  {
    struct ifinfomsg *msg;
    int msg_len;
  } /* int link_filter */
  
  static int qos_filter (const struct sockaddr_nl *sa,
 -    const struct nlmsghdr *nmh, void *args)
 +    struct nlmsghdr *nmh, void *args)
  {
    struct tcmsg *msg;
    int msg_len;
      if (strcmp (tc_type, "filter") == 0)
        numberic_id = msg->tcm_parent;
  
 -    snprintf (tc_inst, sizeof (tc_inst), "%s-%x:%x",
 +    ssnprintf (tc_inst, sizeof (tc_inst), "%s-%x:%x",
        (const char *) RTA_DATA (attrs[TCA_KIND]),
        numberic_id >> 16,
        numberic_id & 0x0000FFFF);
 -    tc_inst[sizeof (tc_inst) - 1] = '\0';
    }
  
    DEBUG ("netlink plugin: qos_filter: got %s for %s (%i).",
        struct gnet_stats_basic bs;
        char type_instance[DATA_MAX_NAME_LEN];
  
 -      snprintf (type_instance, sizeof (type_instance), "%s-%s",
 +      ssnprintf (type_instance, sizeof (type_instance), "%s-%s",
          tc_type, tc_inst);
 -      type_instance[sizeof (type_instance) - 1] = '\0';
  
        memset (&bs, '\0', sizeof (bs));
        memcpy (&bs, RTA_DATA (attrs_stats[TCA_STATS_BASIC]),
      struct tc_stats ts;
      char type_instance[DATA_MAX_NAME_LEN];
  
 -    snprintf (type_instance, sizeof (type_instance), "%s-%s",
 +    ssnprintf (type_instance, sizeof (type_instance), "%s-%s",
        tc_type, tc_inst);
 -    type_instance[sizeof (type_instance) - 1] = '\0';
  
      memset(&ts, '\0', sizeof (ts));
      memcpy(&ts, RTA_DATA (attrs[TCA_STATS]),
diff --combined src/network.c
@@@ -246,7 -246,7 +246,7 @@@ static int cache_flush (void
        return (0);
  } /* int cache_flush */
  
 -static int cache_check (const char *type, const value_list_t *vl)
 +static int cache_check (const value_list_t *vl)
  {
        char key[1024];
        time_t *value = NULL;
                return (-1);
  
        if (format_name (key, sizeof (key), vl->host, vl->plugin,
 -                              vl->plugin_instance, type, vl->type_instance))
 +                              vl->plugin_instance, vl->type, vl->type_instance))
                return (-1);
  
        pthread_mutex_lock (&cache_lock);
@@@ -678,12 -678,14 +678,12 @@@ static int parse_packet (void *buffer, 
        int status;
  
        value_list_t vl = VALUE_LIST_INIT;
 -      char type[DATA_MAX_NAME_LEN];
        notification_t n;
  
        DEBUG ("network plugin: parse_packet: buffer = %p; buffer_len = %i;",
                        buffer, buffer_len);
  
        memset (&vl, '\0', sizeof (vl));
 -      memset (&type, '\0', sizeof (type));
        memset (&n, '\0', sizeof (n));
        status = 0;
  
                        if ((vl.time > 0)
                                        && (strlen (vl.host) > 0)
                                        && (strlen (vl.plugin) > 0)
 -                                      && (strlen (type) > 0)
 -                                      && (cache_check (type, &vl) == 0))
 +                                      && (strlen (vl.type) > 0)
 +                                      && (cache_check (&vl) == 0))
                        {
 -                              plugin_dispatch_values (type, &vl);
 +                              plugin_dispatch_values (&vl);
                        }
                        else
                        {
                else if (pkg_type == TYPE_TYPE)
                {
                        status = parse_part_string (&buffer, &buffer_len,
 -                                      type, sizeof (type));
 +                                      vl.type, sizeof (vl.type));
                        if (status == 0)
 -                              sstrncpy (n.type, type, sizeof (n.type));
 +                              sstrncpy (n.type, vl.type, sizeof (n.type));
                }
                else if (pkg_type == TYPE_TYPE_INSTANCE)
                {
@@@ -1403,7 -1405,7 +1403,7 @@@ static int add_to_buffer (char *buffer
                if (write_part_string (&buffer, &buffer_size, TYPE_HOST,
                                        vl->host, strlen (vl->host)) != 0)
                        return (-1);
-               strcpy (vl_def->host, vl->host);
+               sstrncpy (vl_def->host, vl->host, sizeof (vl_def->host));
        }
  
        if (vl_def->time != vl->time)
                if (write_part_string (&buffer, &buffer_size, TYPE_PLUGIN,
                                        vl->plugin, strlen (vl->plugin)) != 0)
                        return (-1);
-               strcpy (vl_def->plugin, vl->plugin);
+               sstrncpy (vl_def->plugin, vl->plugin, sizeof (vl_def->plugin));
        }
  
        if (strcmp (vl_def->plugin_instance, vl->plugin_instance) != 0)
                                        vl->plugin_instance,
                                        strlen (vl->plugin_instance)) != 0)
                        return (-1);
-               strcpy (vl_def->plugin_instance, vl->plugin_instance);
+               sstrncpy (vl_def->plugin_instance, vl->plugin_instance, sizeof (vl_def->plugin_instance));
        }
  
 -      if (strcmp (type_def, ds->type) != 0)
 +      if (strcmp (type_def, vl->type) != 0)
        {
                if (write_part_string (&buffer, &buffer_size, TYPE_TYPE,
 -                                      ds->type, strlen (ds->type)) != 0)
 +                                      vl->type, strlen (vl->type)) != 0)
                        return (-1);
-               strcpy (type_def, vl->type);
 -              sstrncpy (type_def, ds->type, sizeof (type_def));
++              sstrncpy (type_def, vl->type, sizeof (type_def));
        }
  
        if (strcmp (vl_def->type_instance, vl->type_instance) != 0)
                                        vl->type_instance,
                                        strlen (vl->type_instance)) != 0)
                        return (-1);
-               strcpy (vl_def->type_instance, vl->type_instance);
+               sstrncpy (vl_def->type_instance, vl->type_instance, sizeof (vl_def->type_instance));
        }
        
        if (write_part_values (&buffer, &buffer_size, ds, vl) != 0)
@@@ -1481,7 -1483,7 +1481,7 @@@ static int network_write (const data_se
        /* If the value is already in the cache, we have received it via the
         * network. We write it again if forwarding is activated. It's then in
         * the cache and should we receive it again we will ignore it. */
 -      status = cache_check (ds->type, vl);
 +      status = cache_check (vl);
        if ((network_config_forward == 0)
                        && (status != 0))
                return (0);
@@@ -1765,14 -1767,7 +1765,14 @@@ static int network_init (void
        return (0);
  } /* int network_init */
  
 -static int network_flush (int timeout)
 +/* 
 + * The flush option of the network plugin cannot flush individual identifiers.
 + * All the values are added to a buffer and sent when the buffer is full, the
 + * requested value may or may not be in there, it's not worth finding out. We
 + * just send the buffer if `flush'  is called - if the requested value was in
 + * there, good. If not, well, then there is nothing to flush.. -octo
 + */
 +static int network_flush (int timeout, const char *identifier)
  {
        pthread_mutex_lock (&send_buffer_lock);
  
diff --combined src/nfs.c
+++ b/src/nfs.c
@@@ -188,21 -188,20 +188,21 @@@ static void nfs_procedures_submit (cons
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "nfs");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "nfs", sizeof (vl.plugin));
 -      strncpy (vl.plugin_instance, plugin_instance,
 +      sstrncpy (vl.plugin_instance, plugin_instance,
                        sizeof (vl.plugin_instance));
-       strcpy (vl.type, "nfs_procedure");
++      sstrncpy (vl.type, "nfs_procedure", sizeof (vl.type));
  
        for (i = 0; i < len; i++)
        {
                values[0].counter = val[i];
 -              strncpy (vl.type_instance, names[i],
 +              sstrncpy (vl.type_instance, names[i],
                                sizeof (vl.type_instance));
                DEBUG ("%s-%s/nfs_procedure-%s = %llu",
                                vl.plugin, vl.plugin_instance,
                                vl.type_instance, val[i]);
 -              plugin_dispatch_values ("nfs_procedure", &vl);
 +              plugin_dispatch_values (&vl);
        }
  } /* void nfs_procedures_submit */
  
@@@ -241,8 -240,9 +241,8 @@@ static void nfs_read_stats_file (FILE *
                                continue;
                        }
  
 -                      snprintf (plugin_instance, sizeof (plugin_instance),
 +                      ssnprintf (plugin_instance, sizeof (plugin_instance),
                                        "v2%s", inst);
 -                      plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
  
                        values = (unsigned long long *) malloc (nfs2_procedures_names_num * sizeof (unsigned long long));
                        if (values == NULL)
                                continue;
                        }
  
 -                      snprintf (plugin_instance, sizeof (plugin_instance),
 +                      ssnprintf (plugin_instance, sizeof (plugin_instance),
                                        "v3%s", inst);
 -                      plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
  
                        values = (unsigned long long *) malloc (nfs3_procedures_names_num * sizeof (unsigned long long));
                        if (values == NULL)
diff --combined src/nginx.c
@@@ -122,8 -122,7 +122,8 @@@ static int init (void
  
    if (user != NULL)
    {
 -    if (snprintf (credentials, 1024, "%s:%s", user, pass == NULL ? "" : pass) >= 1024)
 +    if (ssnprintf (credentials, sizeof (credentials),
 +        "%s:%s", user, pass == NULL ? "" : pass) >= sizeof (credentials))
      {
        ERROR ("nginx plugin: Credentials would have been truncated.");
        return (-1);
@@@ -178,15 -177,17 +178,15 @@@ static void submit (char *type, char *i
    vl.values = values;
    vl.values_len = 1;
    vl.time = time (NULL);
-   strcpy (vl.host, hostname_g);
-   strcpy (vl.plugin, "nginx");
-   strcpy (vl.plugin_instance, "");
+   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+   sstrncpy (vl.plugin, "nginx", sizeof (vl.plugin));
+   sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
 +  sstrncpy (vl.type, type, sizeof (vl.type));
  
    if (inst != NULL)
 -  {
 -    strncpy (vl.type_instance, inst, sizeof (vl.type_instance));
 -    vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
 -  }
 +    sstrncpy (vl.type_instance, inst, sizeof (vl.type_instance));
  
 -  plugin_dispatch_values (type, &vl);
 +  plugin_dispatch_values (&vl);
  } /* void submit */
  
  static int nginx_read (void)
    char *ptr;
    char *lines[16];
    int   lines_num = 0;
+   char *saveptr;
  
    char *fields[16];
    int   fields_num;
    }
  
    ptr = nginx_buffer;
-   while ((lines[lines_num] = strtok (ptr, "\n\r")) != NULL)
+   saveptr = NULL;
+   while ((lines[lines_num] = strtok_r (ptr, "\n\r", &saveptr)) != NULL)
    {
      ptr = NULL;
      lines_num++;
diff --combined src/ntpd.c
@@@ -269,10 -269,11 +269,10 @@@ static int ntpd_config (const char *key
        {
                int port = (int) (atof (value));
                if ((port > 0) && (port <= 65535))
 -                      snprintf (ntpd_port, sizeof (ntpd_port),
 +                      ssnprintf (ntpd_port, sizeof (ntpd_port),
                                        "%i", port);
                else
 -                      strncpy (ntpd_port, value, sizeof (ntpd_port));
 -              ntpd_port[sizeof (ntpd_port) - 1] = '\0';
 +                      sstrncpy (ntpd_port, value, sizeof (ntpd_port));
        }
        else if (strcasecmp (key, "ReverseLookups") == 0)
        {
@@@ -301,13 -302,12 +301,13 @@@ static void ntpd_submit (char *type, ch
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "ntpd");
-       strcpy (vl.plugin_instance, "");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "ntpd", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
 -      strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
 +      sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  }
  
  /* returns `tv0 - tv1' in milliseconds or 0 if `tv1 > tv0' */
@@@ -874,7 -874,7 +874,7 @@@ static int ntpd_read (void
  
                        if (refclock_id < refclock_names_num)
                        {
 -                              strncpy (peername, refclock_names[refclock_id],
 +                              sstrncpy (peername, refclock_names[refclock_id],
                                                sizeof (peername));
                        }
                        else
                                addr_obj.s_addr = ptr->srcadr;
                                addr_str = inet_ntoa (addr_obj);
  
 -                              strncpy (peername, addr_str, sizeof (peername));
 +                              sstrncpy (peername, addr_str, sizeof (peername));
                        }
                }
                else /* Normal network host. */
diff --combined src/nut.c
+++ b/src/nut.c
@@@ -124,17 -124,20 +124,17 @@@ static void nut_submit (nut_ups_t *ups
    vl.values = values;
    vl.values_len = STATIC_ARRAY_SIZE (values);
    vl.time = time (NULL);
 -  strncpy (vl.host,
 +  sstrncpy (vl.host,
        (strcasecmp (ups->hostname, "localhost") == 0)
        ? hostname_g
        : ups->hostname,
        sizeof (vl.host));
-   strcpy (vl.plugin, "nut");
+   sstrncpy (vl.plugin, "nut", sizeof (vl.plugin));
 -  strncpy (vl.plugin_instance, ups->upsname, sizeof (vl.plugin_instance));
 -  strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 +  sstrncpy (vl.plugin_instance, ups->upsname, sizeof (vl.plugin_instance));
 +  sstrncpy (vl.type, type, sizeof (vl.type));
 +  sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
  
 -  vl.host[sizeof (vl.host) - 1] = '\0';
 -  vl.plugin_instance[sizeof (vl.plugin_instance) - 1] = '\0';
 -  vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
 -
 -  plugin_dispatch_values (type, &vl);
 +  plugin_dispatch_values (&vl);
  } /* void nut_submit */
  
  static int nut_read_one (nut_ups_t *ups)
diff --combined src/perl.c
@@@ -210,7 -210,8 +210,7 @@@ static int hv2data_source (pTHX_ HV *ha
                return -1;
  
        if (NULL != (tmp = hv_fetch (hash, "name", 4, 0))) {
 -              strncpy (ds->name, SvPV_nolen (*tmp), DATA_MAX_NAME_LEN);
 -              ds->name[DATA_MAX_NAME_LEN - 1] = '\0';
 +              sstrncpy (ds->name, SvPV_nolen (*tmp), sizeof (ds->name));
        }
        else {
                log_err ("hv2data_source: No DS name given.");
@@@ -372,10 -373,6 +372,10 @@@ static int value_list2hv (pTHX_ value_l
                                newSVpv (vl->plugin_instance, 0), 0))
                        return -1;
  
 +      if ('\0' != vl->type[0])
 +              if (NULL == hv_store (hash, "type", 4, newSVpv (vl->type, 0), 0))
 +                      return -1;
 +
        if ('\0' != vl->type_instance[0])
                if (NULL == hv_store (hash, "type_instance", 13,
                                newSVpv (vl->type_instance, 0), 0))
@@@ -427,11 -424,12 +427,11 @@@ static int notification2hv (pTHX_ notif
  static char *get_module_name (char *buf, size_t buf_len, const char *module) {
        int status = 0;
        if (base_name[0] == '\0')
 -              status = snprintf (buf, buf_len, "%s", module);
 +              status = ssnprintf (buf, buf_len, "%s", module);
        else
 -              status = snprintf (buf, buf_len, "%s::%s", base_name, module);
 +              status = ssnprintf (buf, buf_len, "%s::%s", base_name, module);
        if ((status < 0) || ((unsigned int)status >= buf_len))
                return (NULL);
 -      buf[buf_len - 1] = '\0';
        return (buf);
  } /* char *get_module_name */
  
@@@ -477,7 -475,8 +477,7 @@@ static int pplugin_register_data_set (p
                                ds[i].name, ds[i].type, ds[i].min, ds[i].max);
        }
  
 -      strncpy (set->type, name, DATA_MAX_NAME_LEN);
 -      set->type[DATA_MAX_NAME_LEN - 1] = '\0';
 +      sstrncpy (set->type, name, sizeof (set->type));
  
        set->ds_num = len + 1;
        set->ds = ds;
@@@ -512,7 -511,7 +512,7 @@@ static int pplugin_unregister_data_set 
   *   type_instance   => $tinstance,
   * }
   */
 -static int pplugin_dispatch_values (pTHX_ char *name, HV *values)
 +static int pplugin_dispatch_values (pTHX_ HV *values)
  {
        value_list_t list = VALUE_LIST_INIT;
        value_t      *val = NULL;
  
        int ret = 0;
  
 -      if ((NULL == name) || (NULL == values))
 +      if (NULL == values)
 +              return -1;
 +
 +      if (NULL == (tmp = hv_fetch (values, "type", 4, 0))) {
 +              log_err ("pplugin_dispatch_values: No type given.");
                return -1;
 +      }
 +
 +      sstrncpy (list.type, SvPV_nolen (*tmp), sizeof (list.type));
  
        if ((NULL == (tmp = hv_fetch (values, "values", 6, 0)))
                        || (! (SvROK (*tmp) && (SVt_PVAV == SvTYPE (SvRV (*tmp)))))) {
  
                val = (value_t *)smalloc (len * sizeof (value_t));
  
 -              list.values_len = av2value (aTHX_ name, (AV *)SvRV (*tmp), val, len);
 +              list.values_len = av2value (aTHX_ list.type, (AV *)SvRV (*tmp),
 +                              val, len);
                list.values = val;
  
                if (-1 == list.values_len) {
        }
  
        if (NULL != (tmp = hv_fetch (values, "host", 4, 0))) {
 -              strncpy (list.host, SvPV_nolen (*tmp), DATA_MAX_NAME_LEN);
 -              list.host[DATA_MAX_NAME_LEN - 1] = '\0';
 +              sstrncpy (list.host, SvPV_nolen (*tmp), sizeof (list.host));
        }
        else {
-               strcpy (list.host, hostname_g);
+               sstrncpy (list.host, hostname_g, sizeof (list.host));
        }
  
 -      if (NULL != (tmp = hv_fetch (values, "plugin", 6, 0))) {
 -              strncpy (list.plugin, SvPV_nolen (*tmp), DATA_MAX_NAME_LEN);
 -              list.plugin[DATA_MAX_NAME_LEN - 1] = '\0';
 -      }
 +      if (NULL != (tmp = hv_fetch (values, "plugin", 6, 0)))
 +              sstrncpy (list.plugin, SvPV_nolen (*tmp), sizeof (list.plugin));
  
 -      if (NULL != (tmp = hv_fetch (values, "plugin_instance", 15, 0))) {
 -              strncpy (list.plugin_instance, SvPV_nolen (*tmp), DATA_MAX_NAME_LEN);
 -              list.plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
 -      }
 +      if (NULL != (tmp = hv_fetch (values, "plugin_instance", 15, 0)))
 +              sstrncpy (list.plugin_instance, SvPV_nolen (*tmp),
 +                              sizeof (list.plugin_instance));
  
 -      if (NULL != (tmp = hv_fetch (values, "type_instance", 13, 0))) {
 -              strncpy (list.type_instance, SvPV_nolen (*tmp), DATA_MAX_NAME_LEN);
 -              list.type_instance[DATA_MAX_NAME_LEN - 1] = '\0';
 -      }
 +      if (NULL != (tmp = hv_fetch (values, "type_instance", 13, 0)))
 +              sstrncpy (list.type_instance, SvPV_nolen (*tmp),
 +                              sizeof (list.type_instance));
  
 -      ret = plugin_dispatch_values (name, &list);
 +      ret = plugin_dispatch_values (&list);
  
        sfree (val);
        return ret;
@@@ -624,25 -620,31 +624,25 @@@ static int pplugin_dispatch_notificatio
                n.time = time (NULL);
  
        if (NULL != (tmp = hv_fetch (notif, "message", 7, 0)))
 -              strncpy (n.message, SvPV_nolen (*tmp), sizeof (n.message));
 -      n.message[sizeof (n.message) - 1] = '\0';
 +              sstrncpy (n.message, SvPV_nolen (*tmp), sizeof (n.message));
  
        if (NULL != (tmp = hv_fetch (notif, "host", 4, 0)))
 -              strncpy (n.host, SvPV_nolen (*tmp), sizeof (n.host));
 +              sstrncpy (n.host, SvPV_nolen (*tmp), sizeof (n.host));
        else
 -              strncpy (n.host, hostname_g, sizeof (n.host));
 -      n.host[sizeof (n.host) - 1] = '\0';
 +              sstrncpy (n.host, hostname_g, sizeof (n.host));
  
        if (NULL != (tmp = hv_fetch (notif, "plugin", 6, 0)))
 -              strncpy (n.plugin, SvPV_nolen (*tmp), sizeof (n.plugin));
 -      n.plugin[sizeof (n.plugin) - 1] = '\0';
 +              sstrncpy (n.plugin, SvPV_nolen (*tmp), sizeof (n.plugin));
  
        if (NULL != (tmp = hv_fetch (notif, "plugin_instance", 15, 0)))
 -              strncpy (n.plugin_instance, SvPV_nolen (*tmp),
 +              sstrncpy (n.plugin_instance, SvPV_nolen (*tmp),
                                sizeof (n.plugin_instance));
 -      n.plugin_instance[sizeof (n.plugin_instance) - 1] = '\0';
  
        if (NULL != (tmp = hv_fetch (notif, "type", 4, 0)))
 -              strncpy (n.type, SvPV_nolen (*tmp), sizeof (n.type));
 -      n.type[sizeof (n.type) - 1] = '\0';
 +              sstrncpy (n.type, SvPV_nolen (*tmp), sizeof (n.type));
  
        if (NULL != (tmp = hv_fetch (notif, "type_instance", 13, 0)))
 -              strncpy (n.type_instance, SvPV_nolen (*tmp), sizeof (n.type_instance));
 -      n.type_instance[sizeof (n.type_instance) - 1] = '\0';
 +              sstrncpy (n.type_instance, SvPV_nolen (*tmp), sizeof (n.type_instance));
        return plugin_dispatch_notification (&n);
  } /* static int pplugin_dispatch_notification (HV *) */
  
@@@ -691,7 -693,6 +691,7 @@@ static int pplugin_call_all (pTHX_ int 
                 *   time   => $time,
                 *   host   => $hostname,
                 *   plugin => $plugin,
 +               *   type   => $type,
                 *   plugin_instance => $instance,
                 *   type_instance   => $type_instance
                 * };
@@@ -867,43 -868,33 +867,43 @@@ static XS (Collectd_plugin_unregister_d
   */
  static XS (Collectd_plugin_dispatch_values)
  {
 -      SV *values = NULL;
 +      SV *values     = NULL;
 +      int values_idx = 0;
  
        int ret = 0;
  
        dXSARGS;
  
 -      if (2 != items) {
 -              log_err ("Usage: Collectd::plugin_dispatch_values(name, values)");
 +      if (2 == items) {
 +              log_warn ("Collectd::plugin_dispatch_values with two arguments "
 +                              "is deprecated - pass the type through values->{type}.");
 +              values_idx = 1;
 +      }
 +      else if (1 != items) {
 +              log_err ("Usage: Collectd::plugin_dispatch_values(values)");
                XSRETURN_EMPTY;
        }
  
 -      log_debug ("Collectd::plugin_dispatch_values: "
 -                      "name = \"%s\", values=\"%s\"",
 -                      SvPV_nolen (ST (0)), SvPV_nolen (ST (1)));
 +      log_debug ("Collectd::plugin_dispatch_values: values=\"%s\"",
 +                      SvPV_nolen (ST (values_idx)));
  
 -      values = ST (1);
 +      values = ST (values_idx);
  
        if (! (SvROK (values) && (SVt_PVHV == SvTYPE (SvRV (values))))) {
                log_err ("Collectd::plugin_dispatch_values: Invalid values.");
                XSRETURN_EMPTY;
        }
  
 -      if ((NULL == ST (0)) || (NULL == values))
 +      if (((2 == items) && (NULL == ST (0))) || (NULL == values))
                XSRETURN_EMPTY;
  
 -      ret = pplugin_dispatch_values (aTHX_ SvPV_nolen (ST (0)),
 -                      (HV *)SvRV (values));
 +      if ((2 == items) && (NULL == hv_store ((HV *)SvRV (values), "type", 4,
 +                      newSVsv (ST (0)), 0))) {
 +              log_err ("Collectd::plugin_dispatch_values: Could not store type.");
 +              XSRETURN_EMPTY;
 +      }
 +
 +      ret = pplugin_dispatch_values (aTHX_ (HV *)SvRV (values));
  
        if (0 == ret)
                XSRETURN_YES;
@@@ -1264,8 -1255,7 +1264,8 @@@ static int perl_notify (const notificat
        return pplugin_call_all (aTHX_ PLUGIN_NOTIF, notif);
  } /* static int perl_notify (const notification_t *) */
  
 -static int perl_flush (const int timeout)
 +/* TODO: Implement flushing of single identifiers. */
 +static int perl_flush (int timeout, const char *identifier)
  {
        dTHX;
  
@@@ -1362,7 -1352,8 +1362,7 @@@ static int g_pv_get (pTHX_ SV *var, MAG
  static int g_pv_set (pTHX_ SV *var, MAGIC *mg)
  {
        char *pv = mg->mg_ptr;
 -      strncpy (pv, SvPV_nolen (var), DATA_MAX_NAME_LEN);
 -      pv[DATA_MAX_NAME_LEN - 1] = '\0';
 +      sstrncpy (pv, SvPV_nolen (var), DATA_MAX_NAME_LEN);
        return 0;
  } /* static int g_pv_set (pTHX_ SV *, MAGIC *) */
  
@@@ -1563,7 -1554,8 +1563,7 @@@ static int perl_config_basename (pTHX_ 
        value = ci->values[0].value.string;
  
        log_debug ("perl_config: Setting plugin basename to \"%s\"", value);
 -      strncpy (base_name, value, sizeof (base_name));
 -      base_name[sizeof (base_name) - 1] = '\0';
 +      sstrncpy (base_name, value, sizeof (base_name));
        return 0;
  } /* static int perl_config_basename (oconfig_item_it *) */
  
diff --combined src/ping.c
@@@ -186,13 -186,12 +186,13 @@@ static void ping_submit (char *host, do
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "ping");
-       strcpy (vl.plugin_instance, "");
-       strcpy (vl.type, "ping");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "ping", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
 -      strncpy (vl.type_instance, host, sizeof (vl.type_instance));
 +      sstrncpy (vl.type_instance, host, sizeof (vl.type_instance));
++      sstrncpy (vl.type, "ping", sizeof (vl.type));
  
 -      plugin_dispatch_values ("ping", &vl);
 +      plugin_dispatch_values (&vl);
  }
  
  static int ping_read (void)
diff --combined src/plugin.c
@@@ -21,7 -21,6 +21,7 @@@
   **/
  
  #include "collectd.h"
 +#include "utils_complain.h"
  
  #include <ltdl.h>
  
@@@ -329,8 -328,7 +329,8 @@@ int plugin_load (const char *type
  
        /* `cpu' should not match `cpufreq'. To solve this we add `.so' to the
         * type when matching the filename */
 -      if (snprintf (typename, BUFSIZE, "%s.so", type) >= BUFSIZE)
 +      if (ssnprintf (typename, sizeof (typename),
 +                      "%s.so", type) >= sizeof (typename))
        {
                WARNING ("snprintf: truncated: `%s.so'", type);
                return (-1);
                if (strncasecmp (de->d_name, typename, typename_len))
                        continue;
  
 -              if (snprintf (filename, BUFSIZE, "%s/%s", dir, de->d_name) >= BUFSIZE)
 +              if (ssnprintf (filename, sizeof (filename),
 +                              "%s/%s", dir, de->d_name) >= sizeof (filename))
                {
                        WARNING ("snprintf: truncated: `%s/%s'", dir, de->d_name);
                        continue;
@@@ -442,8 -439,7 +442,8 @@@ int plugin_register_write (const char *
        return (register_callback (&list_write, name, (void *) callback));
  } /* int plugin_register_write */
  
 -int plugin_register_flush (const char *name, int (*callback) (const int))
 +int plugin_register_flush (const char *name,
 +              int (*callback) (const int timeout, const char *identifier))
  {
        return (register_callback (&list_flush, name, (void *) callback));
  } /* int plugin_register_flush */
@@@ -584,22 -580,15 +584,15 @@@ void plugin_init_all (void
        llentry_t *le;
        int status;
  
-       /* Start read-threads */
-       if (list_read != NULL)
-       {
-               const char *rt;
-               int num;
-               rt = global_option_get ("ReadThreads");
-               num = atoi (rt);
-               start_threads ((num > 0) ? num : 5);
-       }
        /* Init the value cache */
        uc_init ();
  
-       if (list_init == NULL)
+       if ((list_init == NULL) && (list_read == NULL))
                return;
  
+       /* Calling all init callbacks before checking if read callbacks
+        * are available allows the init callbacks to register the read
+        * callback. */
        le = llist_head (list_init);
        while (le != NULL)
        {
                                        "failed with status %i. "
                                        "Plugin will be unloaded.",
                                        le->key, status);
+                       /* Plugins that register read callbacks from the init
+                        * callback should take care of appropriate error
+                        * handling themselves. */
                        /* FIXME: Unload _all_ functions */
                        plugin_unregister_read (le->key);
                }
  
                le = le->next;
        }
+       /* Start read-threads */
+       if (list_read != NULL)
+       {
+               const char *rt;
+               int num;
+               rt = global_option_get ("ReadThreads");
+               num = atoi (rt);
+               start_threads ((num > 0) ? num : 5);
+       }
  } /* void plugin_init_all */
  
  void plugin_read_all (void)
@@@ -696,29 -698,6 +702,29 @@@ void plugin_flush_all (int timeout
        }
  } /* void plugin_flush_all */
  
 +int plugin_flush (const char *plugin, int timeout, const char *identifier)
 +{
 +  int (*callback) (int timeout, const char *identifier);
 +  llentry_t *le;
 +
 +  if (list_flush == NULL)
 +    return (0);
 +
 +  le = llist_head (list_flush);
 +  while (le != NULL)
 +  {
 +    if ((plugin != NULL)
 +      && (strcmp (plugin, le->key) != 0))
 +      continue;
 +
 +    callback = (int (*) (int, const char *)) le->value;
 +    le = le->next;
 +
 +    (*callback) (timeout, identifier);
 +  }
 +  return (0);
 +} /* int plugin_flush */
 +
  void plugin_shutdown_all (void)
  {
        int (*callback) (void);
        }
  } /* void plugin_shutdown_all */
  
 -int plugin_dispatch_values (const char *name, value_list_t *vl)
 +int plugin_dispatch_values (value_list_t *vl)
  {
 +      static c_complain_t no_write_complaint = C_COMPLAIN_INIT;
 +
        int (*callback) (const data_set_t *, const value_list_t *);
        data_set_t *ds;
        llentry_t *le;
  
 -      if (list_write == NULL)
 -      {
 -              ERROR ("plugin_dispatch_values: No write callback has been "
 -                              "registered. Please load at least one plugin "
 -                              "that provides a write function.");
 +      if ((vl == NULL) || (*vl->type == '\0')) {
 +              ERROR ("plugin_dispatch_values: Invalid value list.");
                return (-1);
        }
  
 +      if (list_write == NULL)
 +              c_complain_once (LOG_WARNING, &no_write_complaint,
 +                              "plugin_dispatch_values: No write callback has been "
 +                              "registered. Please load at least one output plugin, "
 +                              "if you want the collected data to be stored.");
 +
        if (data_sets == NULL)
        {
                ERROR ("plugin_dispatch_values: No data sets registered. "
                return (-1);
        }
  
 -      if (c_avl_get (data_sets, name, (void *) &ds) != 0)
 +      if (c_avl_get (data_sets, vl->type, (void *) &ds) != 0)
        {
 -              INFO ("plugin_dispatch_values: Dataset not found: %s", name);
 +              INFO ("plugin_dispatch_values: Dataset not found: %s", vl->type);
                return (-1);
        }
  
                        (unsigned int) vl->time, vl->interval,
                        vl->host,
                        vl->plugin, vl->plugin_instance,
 -                      ds->type, vl->type_instance);
 +                      vl->type, vl->type_instance);
 +
 +#if COLLECT_DEBUG
 +      assert (0 == strcmp (ds->type, vl->type));
 +#else
 +      if (0 != strcmp (ds->type, vl->type))
 +              WARNING ("plugin_dispatch_values: (ds->type = %s) != (vl->type = %s)",
 +                              ds->type, vl->type);
 +#endif
  
  #if COLLECT_DEBUG
        assert (ds->ds_num == vl->values_len);
        escape_slashes (vl->host, sizeof (vl->host));
        escape_slashes (vl->plugin, sizeof (vl->plugin));
        escape_slashes (vl->plugin_instance, sizeof (vl->plugin_instance));
 +      escape_slashes (vl->type, sizeof (vl->type));
        escape_slashes (vl->type_instance, sizeof (vl->type_instance));
  
        /* Update the value cache */
@@@ -899,179 -864,3 +905,179 @@@ const data_set_t *plugin_get_ds (const 
  
        return (ds);
  } /* data_set_t *plugin_get_ds */
 +
 +static int plugin_notification_meta_add (notification_t *n,
 +              const char *name,
 +              enum notification_meta_type_e type,
 +              const void *value)
 +{
 +  notification_meta_t *meta;
 +  notification_meta_t *tail;
 +
 +  if ((n == NULL) || (name == NULL) || (value == NULL))
 +  {
 +    ERROR ("plugin_notification_meta_add: A pointer is NULL!");
 +    return (-1);
 +  }
 +
 +  meta = (notification_meta_t *) malloc (sizeof (notification_meta_t));
 +  if (meta == NULL)
 +  {
 +    ERROR ("plugin_notification_meta_add: malloc failed.");
 +    return (-1);
 +  }
 +  memset (meta, 0, sizeof (notification_meta_t));
 +
 +  sstrncpy (meta->name, name, sizeof (meta->name));
 +  meta->type = type;
 +
 +  switch (type)
 +  {
 +    case NM_TYPE_STRING:
 +    {
 +      meta->value_string = strdup ((const char *) value);
 +      if (meta->value_string == NULL)
 +      {
 +        ERROR ("plugin_notification_meta_add: strdup failed.");
 +        sfree (meta);
 +        return (-1);
 +      }
 +      break;
 +    }
 +    case NM_TYPE_SIGNED_INT:
 +    {
 +      meta->value_signed_int = *((int64_t *) value);
 +      break;
 +    }
 +    case NM_TYPE_UNSIGNED_INT:
 +    {
 +      meta->value_unsigned_int = *((uint64_t *) value);
 +      break;
 +    }
 +    case NM_TYPE_DOUBLE:
 +    {
 +      meta->value_double = *((double *) value);
 +      break;
 +    }
 +    case NM_TYPE_BOOLEAN:
 +    {
 +      meta->value_boolean = *((bool *) value);
 +      break;
 +    }
 +    default:
 +    {
 +      ERROR ("plugin_notification_meta_add: Unknown type: %i", type);
 +      sfree (meta);
 +      return (-1);
 +    }
 +  } /* switch (type) */
 +
 +  meta->next = NULL;
 +  tail = n->meta;
 +  while ((tail != NULL) && (tail->next != NULL))
 +    tail = tail->next;
 +
 +  if (tail == NULL)
 +    n->meta = meta;
 +  else
 +    tail->next = meta;
 +
 +  return (0);
 +} /* int plugin_notification_meta_add */
 +
 +int plugin_notification_meta_add_string (notification_t *n,
 +    const char *name,
 +    const char *value)
 +{
 +  return (plugin_notification_meta_add (n, name, NM_TYPE_STRING, value));
 +}
 +
 +int plugin_notification_meta_add_signed_int (notification_t *n,
 +    const char *name,
 +    int64_t value)
 +{
 +  return (plugin_notification_meta_add (n, name, NM_TYPE_SIGNED_INT, &value));
 +}
 +
 +int plugin_notification_meta_add_unsigned_int (notification_t *n,
 +    const char *name,
 +    uint64_t value)
 +{
 +  return (plugin_notification_meta_add (n, name, NM_TYPE_UNSIGNED_INT, &value));
 +}
 +
 +int plugin_notification_meta_add_double (notification_t *n,
 +    const char *name,
 +    double value)
 +{
 +  return (plugin_notification_meta_add (n, name, NM_TYPE_DOUBLE, &value));
 +}
 +
 +int plugin_notification_meta_add_boolean (notification_t *n,
 +    const char *name,
 +    bool value)
 +{
 +  return (plugin_notification_meta_add (n, name, NM_TYPE_BOOLEAN, &value));
 +}
 +
 +int plugin_notification_meta_copy (notification_t *dst,
 +    const notification_t *src)
 +{
 +  notification_meta_t *meta;
 +
 +  assert (dst != NULL);
 +  assert (src != NULL);
 +  assert (dst != src);
 +  assert ((src->meta == NULL) || (src->meta != dst->meta));
 +
 +  for (meta = src->meta; meta != NULL; meta = meta->next)
 +  {
 +    if (meta->type == NM_TYPE_STRING)
 +      plugin_notification_meta_add_string (dst, meta->name,
 +        meta->value_string);
 +    else if (meta->type == NM_TYPE_SIGNED_INT)
 +      plugin_notification_meta_add_signed_int (dst, meta->name,
 +        meta->value_signed_int);
 +    else if (meta->type == NM_TYPE_UNSIGNED_INT)
 +      plugin_notification_meta_add_unsigned_int (dst, meta->name,
 +        meta->value_unsigned_int);
 +    else if (meta->type == NM_TYPE_DOUBLE)
 +      plugin_notification_meta_add_double (dst, meta->name,
 +        meta->value_double);
 +    else if (meta->type == NM_TYPE_BOOLEAN)
 +      plugin_notification_meta_add_boolean (dst, meta->name,
 +        meta->value_boolean);
 +  }
 +
 +  return (0);
 +} /* int plugin_notification_meta_copy */
 +
 +int plugin_notification_meta_free (notification_t *n)
 +{
 +  notification_meta_t *this;
 +  notification_meta_t *next;
 +
 +  if (n == NULL)
 +  {
 +    ERROR ("plugin_notification_meta_free: n == NULL!");
 +    return (-1);
 +  }
 +
 +  this = n->meta;
 +  n->meta = NULL;
 +  while (this != NULL)
 +  {
 +    next = this->next;
 +
 +    if (this->type == NM_TYPE_STRING)
 +    {
 +      free ((char *)this->value_string);
 +      this->value_string = NULL;
 +    }
 +    sfree (this);
 +
 +    this = next;
 +  }
 +
 +  return (0);
 +} /* int plugin_notification_meta_free */
diff --combined src/powerdns.c
@@@ -320,12 -320,11 +320,12 @@@ static void submit (const char *plugin_
    vl.time = time (NULL);
    sstrncpy (vl.host, hostname_g, sizeof (vl.host));
    sstrncpy (vl.plugin, "powerdns", sizeof (vl.plugin));
 +  sstrncpy (vl.type, type, sizeof (vl.type));
    if (type_instance != NULL)
      sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
    sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
  
 -  plugin_dispatch_values (type, &vl);
 +  plugin_dispatch_values (&vl);
  } /* }}} static void submit */
  
  static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */
  
    memset (&sa_unix, 0, sizeof (sa_unix));
    sa_unix.sun_family = AF_UNIX;
 -  strncpy (sa_unix.sun_path,
 +  sstrncpy (sa_unix.sun_path,
        (local_sockpath != NULL) ? local_sockpath : PDNS_LOCAL_SOCKPATH,
        sizeof (sa_unix.sun_path));
 -  sa_unix.sun_path[sizeof (sa_unix.sun_path) - 1] = 0;
  
    status = unlink (sa_unix.sun_path);
    if ((status != 0) && (errno != ENOENT))
@@@ -619,7 -619,7 +619,7 @@@ static int powerdns_update_recursor_com
    }
    else
    {
-     strcpy (buffer, "get ");
+     sstrncpy (buffer, "get ", sizeof (buffer));
      status = strjoin (&buffer[4], sizeof (buffer) - strlen ("get "),
        li->fields, li->fields_num,
        /* seperator = */ " ");
@@@ -860,8 -860,7 +860,8 @@@ static int powerdns_config_add_server (
      }
  
      item->sockaddr.sun_family = AF_UNIX;
 -    sstrncpy (item->sockaddr.sun_path, socket_temp, UNIX_PATH_MAX);
 +    sstrncpy (item->sockaddr.sun_path, socket_temp,
 +      sizeof (item->sockaddr.sun_path));
  
      e = llentry_create (item->instance, item);
      if (e == NULL)
diff --combined src/processes.c
@@@ -1,8 -1,7 +1,8 @@@
  /**
   * collectd - src/processes.c
   * Copyright (C) 2005  Lyonel Vincent
 - * Copyright (C) 2006-2007  Florian Forster (Mach code)
 + * Copyright (C) 2006-2008  Florian Forster (Mach code)
 + * Copyright (C) 2008  Oleg King
   *
   * 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
@@@ -21,7 -20,6 +21,7 @@@
   * Authors:
   *   Lyonel Vincent <lyonel at ezix.org>
   *   Florian octo Forster <octo at verplant.org>
 + *   Oleg King <king2 at kaluga.ru>
   **/
  
  #include "collectd.h"
  #  endif
  /* #endif KERNEL_LINUX */
  
 +#elif HAVE_KVM_H
 +#  include <kvm.h>
 +#  include <sys/user.h>
 +#  include <sys/proc.h>
 +#  if HAVE_SYS_SYSCTL_H
 +#    include <sys/sysctl.h>
 +#  endif
 +/* #endif HAVE_KVM_H */
 +
  #else
  # error "No applicable input method."
  #endif
  
 +#if HAVE_REGEX_H
 +# include <regex.h>
 +#endif
 +
  #define BUFSIZE 256
  
  static const char *config_keys[] =
  {
        "Process",
 +      "ProcessMatch",
        NULL
  };
 -static int config_keys_num = 1;
 +static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
  
  typedef struct procstat_entry_s
  {
  typedef struct procstat
  {
        char          name[PROCSTAT_NAME_LEN];
 +#if HAVE_REGEX_H
 +      regex_t *re;
 +#endif
  
        unsigned long num_proc;
        unsigned long num_lwp;
@@@ -169,71 -150,20 +169,71 @@@ static mach_msg_type_number_t     pset_
  static long pagesize_g;
  #endif /* KERNEL_LINUX */
  
 -static void ps_list_register (const char *name)
 +/* put name of process from config to list_head_g tree
 +   list_head_g is a list of 'procstat_t' structs with
 +   processes names we want to watch */
 +static void ps_list_register (const char *name, const char *regexp)
  {
        procstat_t *new;
        procstat_t *ptr;
 +      int status;
  
 -      if ((new = (procstat_t *) malloc (sizeof (procstat_t))) == NULL)
 +      new = (procstat_t *) malloc (sizeof (procstat_t));
 +      if (new == NULL)
 +      {
 +              ERROR ("processes plugin: ps_list_register: malloc failed.");
                return;
 +      }
        memset (new, 0, sizeof (procstat_t));
 -      strncpy (new->name, name, PROCSTAT_NAME_LEN);
 +      sstrncpy (new->name, name, sizeof (new->name));
  
 +#if HAVE_REGEX_H
 +      if (regexp != NULL)
 +      {
 +              DEBUG ("ProcessMatch: adding \"%s\" as criteria to process %s.", regexp, name);
 +              new->re = (regex_t *) malloc (sizeof (regex_t));
 +              if (new->re == NULL)
 +              {
 +                      ERROR ("processes plugin: ps_list_register: malloc failed.");
 +                      sfree (new);
 +                      return;
 +              }
 +
 +              status = regcomp (new->re, regexp, REG_EXTENDED | REG_NOSUB);
 +              if (status != 0)
 +              {
 +                      DEBUG ("ProcessMatch: compiling the regular expression \"%s\" failed.", regexp);
 +                      sfree(new->re);
 +                      return;
 +              }
 +      }
 +#else
 +      if (regexp != NULL)
 +      {
 +              ERROR ("processes plugin: ps_list_register: "
 +                              "Regular expression \"%s\" found in config "
 +                              "file, but support for regular expressions "
 +                              "has been dispabled at compile time.",
 +                              regexp);
 +              sfree (new);
 +              return;
 +      }
 +#endif
 +      
        for (ptr = list_head_g; ptr != NULL; ptr = ptr->next)
        {
                if (strcmp (ptr->name, name) == 0)
 +              {
 +                      WARNING ("processes plugin: You have configured more "
 +                                      "than one `Process' or "
 +                                      "`ProcessMatch' with the same name. "
 +                                      "All but the first setting will be "
 +                                      "ignored.");
 +                      sfree (new->re);
 +                      sfree (new);
                        return;
 +              }
 +
                if (ptr->next == NULL)
                        break;
        }
                list_head_g = new;
        else
                ptr->next = new;
 -}
 +} /* void ps_list_register */
  
 -static procstat_t *ps_list_search (const char *name)
 +/* try to match name against entry, returns 1 if success */
 +static int ps_list_match (const char *name, const char *cmdline, procstat_t *ps)
  {
 -      procstat_t *ptr;
 +#if HAVE_REGEX_H
 +      if (ps->re != NULL)
 +      {
 +              int status;
 +              const char *str;
  
 -      for (ptr = list_head_g; ptr != NULL; ptr = ptr->next)
 -              if (strcmp (ptr->name, name) == 0)
 -                      break;
 +              str = cmdline;
 +              if ((str == NULL) || (str[0] == 0))
 +                      str = name;
  
 -      return (ptr);
 -}
 +              assert (str != NULL);
 +
 +              status = regexec (ps->re, str,
 +                              /* nmatch = */ 0,
 +                              /* pmatch = */ NULL,
 +                              /* eflags = */ 0);
 +              if (status == 0)
 +                      return (1);
 +      }
 +      else
 +#endif
 +      if (strcmp (ps->name, name) == 0)
 +              return (1);
  
 -static void ps_list_add (const char *name, procstat_entry_t *entry)
 +      return (0);
 +} /* int ps_list_match */
 +
 +/* add process entry to 'instances' of process 'name' (or refresh it) */
 +static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t *entry)
  {
        procstat_t *ps;
        procstat_entry_t *pse;
        if (entry->id == 0)
                return;
  
 -      if ((ps = ps_list_search (name)) == NULL)
 -              return;
 -
 -      for (pse = ps->instances; pse != NULL; pse = pse->next)
 -              if ((pse->id == entry->id) || (pse->next == NULL))
 -                      break;
 -
 -      if ((pse == NULL) || (pse->id != entry->id))
 +      for (ps = list_head_g; ps != NULL; ps = ps->next)
        {
 -              procstat_entry_t *new;
 -
 -              new = (procstat_entry_t *) malloc (sizeof (procstat_entry_t));
 -              if (new == NULL)
 -                      return;
 -              memset (new, 0, sizeof (procstat_entry_t));
 -              new->id = entry->id;
 +              if ((ps_list_match (name, cmdline, ps)) == 0)
 +                      continue;
  
 -              if (pse == NULL)
 -                      ps->instances = new;
 -              else
 -                      pse->next = new;
 +              for (pse = ps->instances; pse != NULL; pse = pse->next)
 +                      if ((pse->id == entry->id) || (pse->next == NULL))
 +                              break;
  
 -              pse = new;
 -      }
 +              if ((pse == NULL) || (pse->id != entry->id))
 +              {
 +                      procstat_entry_t *new;
 +                      
 +                      new = (procstat_entry_t *) malloc (sizeof (procstat_entry_t));
 +                      if (new == NULL)
 +                              return;
 +                      memset (new, 0, sizeof (procstat_entry_t));
 +                      new->id = entry->id;
 +                      
 +                      if (pse == NULL)
 +                              ps->instances = new;
 +                      else
 +                              pse->next = new;
  
 -      pse->age = 0;
 -      pse->num_proc = entry->num_proc;
 -      pse->num_lwp  = entry->num_lwp;
 -      pse->vmem_rss = entry->vmem_rss;
 +                      pse = new;
 +              }
  
 -      ps->num_proc += pse->num_proc;
 -      ps->num_lwp  += pse->num_lwp;
 -      ps->vmem_rss += pse->vmem_rss;
 +              pse->age = 0;
 +              pse->num_proc = entry->num_proc;
 +              pse->num_lwp  = entry->num_lwp;
 +              pse->vmem_rss = entry->vmem_rss;
  
 -      if ((entry->vmem_minflt_counter == 0)
 -                      && (entry->vmem_majflt_counter == 0))
 -      {
 -              pse->vmem_minflt_counter += entry->vmem_minflt;
 -              pse->vmem_minflt = entry->vmem_minflt;
 +              ps->num_proc += pse->num_proc;
 +              ps->num_lwp  += pse->num_lwp;
 +              ps->vmem_rss += pse->vmem_rss;
  
 -              pse->vmem_majflt_counter += entry->vmem_majflt;
 -              pse->vmem_majflt = entry->vmem_majflt;
 -      }
 -      else
 -      {
 -              if (entry->vmem_minflt_counter < pse->vmem_minflt_counter)
 +              if ((entry->vmem_minflt_counter == 0)
 +                              && (entry->vmem_majflt_counter == 0))
                {
 -                      pse->vmem_minflt = entry->vmem_minflt_counter
 -                              + (ULONG_MAX - pse->vmem_minflt_counter);
 -              }
 -              else
 -              {
 -                      pse->vmem_minflt = entry->vmem_minflt_counter - pse->vmem_minflt_counter;
 -              }
 -              pse->vmem_minflt_counter = entry->vmem_minflt_counter;
 +                      pse->vmem_minflt_counter += entry->vmem_minflt;
 +                      pse->vmem_minflt = entry->vmem_minflt;
  
 -              if (entry->vmem_majflt_counter < pse->vmem_majflt_counter)
 -              {
 -                      pse->vmem_majflt = entry->vmem_majflt_counter
 -                              + (ULONG_MAX - pse->vmem_majflt_counter);
 +                      pse->vmem_majflt_counter += entry->vmem_majflt;
 +                      pse->vmem_majflt = entry->vmem_majflt;
                }
                else
                {
 -                      pse->vmem_majflt = entry->vmem_majflt_counter - pse->vmem_majflt_counter;
 +                      if (entry->vmem_minflt_counter < pse->vmem_minflt_counter)
 +                      {
 +                              pse->vmem_minflt = entry->vmem_minflt_counter
 +                                      + (ULONG_MAX - pse->vmem_minflt_counter);
 +                      }
 +                      else
 +                      {
 +                              pse->vmem_minflt = entry->vmem_minflt_counter - pse->vmem_minflt_counter;
 +                      }
 +                      pse->vmem_minflt_counter = entry->vmem_minflt_counter;
 +                      
 +                      if (entry->vmem_majflt_counter < pse->vmem_majflt_counter)
 +                      {
 +                              pse->vmem_majflt = entry->vmem_majflt_counter
 +                                      + (ULONG_MAX - pse->vmem_majflt_counter);
 +                      }
 +                      else
 +                      {
 +                              pse->vmem_majflt = entry->vmem_majflt_counter - pse->vmem_majflt_counter;
 +                      }
 +                      pse->vmem_majflt_counter = entry->vmem_majflt_counter;
                }
 -              pse->vmem_majflt_counter = entry->vmem_majflt_counter;
 -      }
 -
 -      ps->vmem_minflt_counter += pse->vmem_minflt;
 -      ps->vmem_majflt_counter += pse->vmem_majflt;
  
 -      if ((entry->cpu_user_counter == 0)
 -                      && (entry->cpu_system_counter == 0))
 -      {
 -              pse->cpu_user_counter += entry->cpu_user;
 -              pse->cpu_user = entry->cpu_user;
 +              ps->vmem_minflt_counter += pse->vmem_minflt;
 +              ps->vmem_majflt_counter += pse->vmem_majflt;
  
 -              pse->cpu_system_counter += entry->cpu_system;
 -              pse->cpu_system = entry->cpu_system;
 -      }
 -      else
 -      {
 -              if (entry->cpu_user_counter < pse->cpu_user_counter)
 +              if ((entry->cpu_user_counter == 0)
 +                              && (entry->cpu_system_counter == 0))
                {
 -                      pse->cpu_user = entry->cpu_user_counter
 -                              + (ULONG_MAX - pse->cpu_user_counter);
 -              }
 -              else
 -              {
 -                      pse->cpu_user = entry->cpu_user_counter - pse->cpu_user_counter;
 -              }
 -              pse->cpu_user_counter = entry->cpu_user_counter;
 +                      pse->cpu_user_counter += entry->cpu_user;
 +                      pse->cpu_user = entry->cpu_user;
  
 -              if (entry->cpu_system_counter < pse->cpu_system_counter)
 -              {
 -                      pse->cpu_system = entry->cpu_system_counter
 -                              + (ULONG_MAX - pse->cpu_system_counter);
 +                      pse->cpu_system_counter += entry->cpu_system;
 +                      pse->cpu_system = entry->cpu_system;
                }
                else
                {
 -                      pse->cpu_system = entry->cpu_system_counter - pse->cpu_system_counter;
 +                      if (entry->cpu_user_counter < pse->cpu_user_counter)
 +                      {
 +                              pse->cpu_user = entry->cpu_user_counter
 +                                      + (ULONG_MAX - pse->cpu_user_counter);
 +                      }
 +                      else
 +                      {
 +                              pse->cpu_user = entry->cpu_user_counter - pse->cpu_user_counter;
 +                      }
 +                      pse->cpu_user_counter = entry->cpu_user_counter;
 +                      
 +                      if (entry->cpu_system_counter < pse->cpu_system_counter)
 +                      {
 +                              pse->cpu_system = entry->cpu_system_counter
 +                                      + (ULONG_MAX - pse->cpu_system_counter);
 +                      }
 +                      else
 +                      {
 +                              pse->cpu_system = entry->cpu_system_counter - pse->cpu_system_counter;
 +                      }
 +                      pse->cpu_system_counter = entry->cpu_system_counter;
                }
 -              pse->cpu_system_counter = entry->cpu_system_counter;
 -      }
  
 -      ps->cpu_user_counter   += pse->cpu_user;
 -      ps->cpu_system_counter += pse->cpu_system;
 +              ps->cpu_user_counter   += pse->cpu_user;
 +              ps->cpu_system_counter += pse->cpu_system;
 +      }
  }
  
 +/* remove old entries from instances of processes in list_head_g */
  static void ps_list_reset (void)
  {
        procstat_t *ps;
        } /* for (ps = list_head_g; ps != NULL; ps = ps->next) */
  }
  
 +/* put all pre-defined 'Process' names from config to list_head_g tree */
  static int ps_config (const char *key, const char *value)
  {
        if (strcasecmp (key, "Process") == 0)
        {
 -              ps_list_register (value);
 +              ps_list_register (value, NULL);
 +      }
 +      else if (strcasecmp (key, "ProcessMatch") == 0)
 +      {
 +              char *new_val;
 +              char *fields[3];
 +              int fields_num;
 +
 +              new_val = strdup (value);
 +              if (new_val == NULL)
 +                      return (1);
 +              fields_num = strsplit (new_val, fields,
 +                              STATIC_ARRAY_SIZE (fields));
 +              if (fields_num != 2)
 +              {
 +                      sfree (new_val);
 +                      return (1);
 +              }
 +              ps_list_register (fields[0], fields[1]);
 +              sfree (new_val);
        }
        else
        {
@@@ -513,7 -399,6 +513,7 @@@ static int ps_init (void
        return (0);
  } /* int ps_init */
  
 +/* submit global state (e.g.: qty of zombies, running, etc..) */
  static void ps_submit_state (const char *state, double value)
  {
        value_t values[1];
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "processes");
-       strcpy (vl.plugin_instance, "");
-       strcpy (vl.type, "ps_state");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "processes", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
 -      strncpy (vl.type_instance, state, sizeof (vl.type_instance));
++      sstrncpy (vl.type, "ps_state", sizeof (vl.type));
 +      sstrncpy (vl.type_instance, state, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values ("ps_state", &vl);
 +      plugin_dispatch_values (&vl);
  }
  
 +/* submit info about specific process (e.g.: memory taken, cpu usage, etc..) */
  static void ps_submit_proc_list (procstat_t *ps)
  {
        value_t values[2];
        vl.values = values;
        vl.values_len = 2;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "processes");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "processes", sizeof (vl.plugin));
 -      strncpy (vl.plugin_instance, ps->name, sizeof (vl.plugin_instance));
 +      sstrncpy (vl.plugin_instance, ps->name, sizeof (vl.plugin_instance));
  
-       strcpy (vl.type, "ps_rss");
++      sstrncpy (vl.type, "ps_rss", sizeof (vl.type));
        vl.values[0].gauge = ps->vmem_rss;
        vl.values_len = 1;
 -      plugin_dispatch_values ("ps_rss", &vl);
 +      plugin_dispatch_values (&vl);
  
-       strcpy (vl.type, "ps_cputime");
++      sstrncpy (vl.type, "ps_cputime", sizeof (vl.type));
        vl.values[0].counter = ps->cpu_user_counter;
        vl.values[1].counter = ps->cpu_system_counter;
        vl.values_len = 2;
 -      plugin_dispatch_values ("ps_cputime", &vl);
 +      plugin_dispatch_values (&vl);
  
-       strcpy (vl.type, "ps_count");
++      sstrncpy (vl.type, "ps_count", sizeof (vl.type));
        vl.values[0].gauge = ps->num_proc;
        vl.values[1].gauge = ps->num_lwp;
        vl.values_len = 2;
 -      plugin_dispatch_values ("ps_count", &vl);
 +      plugin_dispatch_values (&vl);
  
-       strcpy (vl.type, "ps_pagefaults");
++      sstrncpy (vl.type, "ps_pagefaults", sizeof (vl.type));
        vl.values[0].counter = ps->vmem_minflt_counter;
        vl.values[1].counter = ps->vmem_majflt_counter;
        vl.values_len = 2;
 -      plugin_dispatch_values ("ps_pagefaults", &vl);
 +      plugin_dispatch_values (&vl);
  
        DEBUG ("name = %s; num_proc = %lu; num_lwp = %lu; vmem_rss = %lu; "
                        "vmem_minflt_counter = %lu; vmem_majflt_counter = %lu; "
                        ps->cpu_user_counter, ps->cpu_system_counter);
  } /* void ps_submit_proc_list */
  
 +/* ------- additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */
  #if KERNEL_LINUX
  static int *ps_read_tasks (int pid)
  {
        DIR           *dh;
        struct dirent *ent;
  
 -      snprintf (dirname, 64, "/proc/%i/task", pid);
 -      dirname[63] = '\0';
 +      ssnprintf (dirname, sizeof (dirname), "/proc/%i/task", pid);
  
        if ((dh = opendir (dirname)) == NULL)
        {
@@@ -644,6 -523,7 +644,6 @@@ int ps_read_process (int pid, procstat_
  {
        char  filename[64];
        char  buffer[1024];
 -      FILE *fh;
  
        char *fields[64];
        char  fields_len;
  
        memset (ps, 0, sizeof (procstat_t));
  
 -      snprintf (filename, 64, "/proc/%i/stat", pid);
 -      filename[63] = '\0';
 +      ssnprintf (filename, sizeof (filename), "/proc/%i/stat", pid);
  
 -      if ((fh = fopen (filename, "r")) == NULL)
 +      i = read_file_contents (filename, buffer, sizeof(buffer) - 1);
 +      if (i <= 0)
                return (-1);
 -
 -      if (fgets (buffer, 1024, fh) == NULL)
 -      {
 -              fclose (fh);
 -              return (-1);
 -      }
 -
 -      fclose (fh);
 +      buffer[i] = 0;
  
        fields_len = strsplit (buffer, fields, 64);
        if (fields_len < 24)
@@@ -776,9 -663,7 +776,9 @@@ static int mach_get_task_name (task_t t
        return (0);
  }
  #endif /* HAVE_THREAD_INFO */
 +/* ------- end of additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */
  
 +/* do actual readings from kernel */
  static int ps_read (void)
  {
  #if HAVE_THREAD_INFO
                        if (mach_get_task_name (task_list[task],
                                                &task_pid,
                                                task_name, PROCSTAT_NAME_LEN) == 0)
 -                              ps = ps_list_search (task_name);
 +                      {
 +                              /* search for at least one match */
 +                              for (ps = list_head_g; ps != NULL; ps = ps->next)
 +                                      /* FIXME: cmdline should be here instead of NULL */
 +                                      if (ps_list_match (task_name, NULL, ps) == 1)
 +                                              break;
 +                      }
  
                        /* Collect more detailed statistics for this process */
                        if (ps != NULL)
                        }
  
                        if (ps != NULL)
 -                              ps_list_add (task_name, &pse);
 +                              /* FIXME: cmdline should be here instead of NULL */
 +                              ps_list_add (task_name, NULL, &pse);
                } /* for (task_list) */
  
                if ((status = vm_deallocate (port_task_self,
                        case 'W': paging++;   break;
                }
  
 -              ps_list_add (ps.name, &pse);
 +              /* FIXME: cmdline should be here instead of NULL */
 +              ps_list_add (ps.name, NULL, &pse);
        }
  
        closedir (proc);
  
        for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
                ps_submit_proc_list (ps_ptr);
 -#endif /* KERNEL_LINUX */
 +/* #endif KERNEL_LINUX */
 +
 +#elif HAVE_LIBKVM
 +      int running  = 0;
 +      int sleeping = 0;
 +      int zombies  = 0;
 +      int stopped  = 0;
 +      int blocked  = 0;
 +      int idle     = 0;
 +      int wait     = 0;
 +
 +      kvm_t *kd;
 +      char errbuf[1024];
 +      char cmdline[ARG_MAX];
 +      char *cmdline_ptr;
 +      struct kinfo_proc *procs;          /* array of processes */
 +      char **argv;
 +      int count;                         /* returns number of processes */
 +      int i;
 +
 +      procstat_t *ps_ptr;
 +      procstat_entry_t pse;
 +
 +      ps_list_reset ();
 +
 +      /* Open the kvm interface, get a descriptor */
 +      kd = kvm_open (NULL, NULL, NULL, 0, errbuf);
 +      if (kd == NULL)
 +      {
 +              ERROR ("processes plugin: Cannot open kvm interface: %s",
 +                              errbuf);
 +              return (0);
 +      }
 +
 +      /* Get the list of processes. */
 +      procs = kvm_getprocs(kd, KERN_PROC_ALL, 0, &count);
 +      if (procs == NULL)
 +      {
 +              kvm_close (kd);
 +              ERROR ("processes plugin: Cannot get kvm processes list: %s",
 +                              kvm_geterr(kd));
 +              return (0);
 +      }
 +
 +      /* Iterate through the processes in kinfo_proc */
 +      for (i = 0; i < count; i++)
 +      {
 +              /* retrieve the arguments */
 +              cmdline[0] = 0;
 +              cmdline_ptr = NULL;
 +
 +              argv = kvm_getargv (kd, (const struct kinfo_proc *) &(procs[i]), 0);
 +              if (argv != NULL)
 +              {
 +                      int status;
 +                      int argc;
 +
 +                      argc = 0;
 +                      while (argv[argc] != NULL)
 +                              argc++;
 +
 +                      status = strjoin (cmdline, sizeof (cmdline),
 +                                      argv, argc, " ");
 +
 +                      if (status < 0)
 +                      {
 +                              WARNING ("processes plugin: Command line did "
 +                                              "not fit into buffer.");
 +                      }
 +                      else
 +                      {
 +                              cmdline_ptr = &cmdline[0];
 +                      }
 +              }
 +
 +              pse.id       = procs[i].ki_pid;
 +              pse.age      = 0;
 +
 +              pse.num_proc = 1;
 +              pse.num_lwp  = procs[i].ki_numthreads;
 +
 +              pse.vmem_rss = procs[i].ki_rssize * getpagesize();
 +              pse.vmem_minflt = 0;
 +              pse.vmem_minflt_counter = procs[i].ki_rusage.ru_minflt;
 +              pse.vmem_majflt = 0;
 +              pse.vmem_majflt_counter = procs[i].ki_rusage.ru_majflt;
 +
 +              pse.cpu_user = 0;
 +              pse.cpu_user_counter = procs[i].ki_rusage.ru_utime.tv_sec
 +                      * 1000
 +                      + procs[i].ki_rusage.ru_utime.tv_usec;
 +              pse.cpu_system = 0;
 +              pse.cpu_system_counter = procs[i].ki_rusage.ru_stime.tv_sec
 +                      * 1000
 +                      + procs[i].ki_rusage.ru_stime.tv_usec;
 +
 +              switch (procs[i].ki_stat)
 +              {
 +                      case SSTOP:     stopped++;      break;
 +                      case SSLEEP:    sleeping++;     break;
 +                      case SRUN:      running++;      break;
 +                      case SIDL:      idle++;         break;
 +                      case SWAIT:     wait++;         break;
 +                      case SLOCK:     blocked++;      break;
 +                      case SZOMB:     zombies++;      break;
 +              }
 +
 +              ps_list_add (procs[i].ki_comm, cmdline_ptr, &pse);
 +      }
 +
 +      kvm_close(kd);
 +
 +      ps_submit_state ("running",  running);
 +      ps_submit_state ("sleeping", sleeping);
 +      ps_submit_state ("zombies",  zombies);
 +      ps_submit_state ("stopped",  stopped);
 +      ps_submit_state ("blocked",  blocked);
 +      ps_submit_state ("idle",     idle);
 +      ps_submit_state ("wait",     wait);
 +
 +      for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
 +              ps_submit_proc_list (ps_ptr);
 +#endif /* HAVE_LIBKVM */
  
        return (0);
  } /* int ps_read */
diff --combined src/rrdtool.c
@@@ -1,6 -1,6 +1,6 @@@
  /**
   * collectd - src/rrdtool.c
 - * Copyright (C) 2006,2007  Florian octo Forster
 + * Copyright (C) 2006-2008  Florian octo Forster
   *
   * 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
@@@ -47,13 -47,6 +47,13 @@@ struct rrd_cache_
  };
  typedef struct rrd_cache_s rrd_cache_t;
  
 +enum rrd_queue_dir_e
 +{
 +  QUEUE_INSERT_FRONT,
 +  QUEUE_INSERT_BACK
 +};
 +typedef enum rrd_queue_dir_e rrd_queue_dir_t;
 +
  struct rrd_queue_s
  {
        char *filename;
@@@ -218,7 -211,7 +218,7 @@@ static int rra_get (char ***ret, const 
                        if (rra_num >= rra_max)
                                break;
  
 -                      if (snprintf (buffer, sizeof (buffer), "RRA:%s:%3.1f:%u:%u",
 +                      if (ssnprintf (buffer, sizeof (buffer), "RRA:%s:%3.1f:%u:%u",
                                                rra_types[j], xff,
                                                cdp_len, cdp_num) >= sizeof (buffer))
                        {
@@@ -291,16 -284,26 +291,20 @@@ static int ds_get (char ***ret, const d
                }
  
                if (isnan (d->min))
-                       strcpy (min, "U");
+               {
+                       sstrncpy (min, "U", sizeof (min));
+               }
                else
 -              {
 -                      snprintf (min, sizeof (min), "%lf", d->min);
 -                      min[sizeof (min) - 1] = '\0';
 -              }
 +                      ssnprintf (min, sizeof (min), "%lf", d->min);
  
                if (isnan (d->max))
-                       strcpy (max, "U");
+               {
+                       sstrncpy (max, "U", sizeof (max));
+               }
                else
 -              {
 -                      snprintf (max, sizeof (max), "%lf", d->max);
 -                      max[sizeof (max) - 1] = '\0';
 -              }
 +                      ssnprintf (max, sizeof (max), "%lf", d->max);
  
 -              status = snprintf (buffer, sizeof (buffer),
 +              status = ssnprintf (buffer, sizeof (buffer),
                                "DS:%s:%s:%i:%s:%s",
                                d->name, type,
                                (heartbeat > 0) ? heartbeat : (2 * vl->interval),
  
  #if HAVE_THREADSAFE_LIBRRD
  static int srrd_create (char *filename, unsigned long pdp_step, time_t last_up,
 -              int argc, char **argv)
 +              int argc, const char **argv)
  {
        int status;
  
        optind = 0; /* bug in librrd? */
        rrd_clear_error ();
  
-       status = rrd_create_r (filename, pdp_step, last_up, argc, argv);
+       status = rrd_create_r (filename, pdp_step, last_up, argc, (void *) argv);
  
        if (status != 0)
        {
        return (status);
  } /* int srrd_create */
  
 -static int srrd_update (char *filename, char *template, int argc, char **argv)
 +static int srrd_update (char *filename, char *template,
 +              int argc, const char **argv)
  {
        int status;
  
        optind = 0; /* bug in librrd? */
        rrd_clear_error ();
  
-       status = rrd_update_r (filename, template, argc, argv);
+       status = rrd_update_r (filename, template, argc, (void *) argv);
  
        if (status != 0)
        {
  
  #else /* !HAVE_THREADSAFE_LIBRRD */
  static int srrd_create (char *filename, unsigned long pdp_step, time_t last_up,
 -              int argc, char **argv)
 +              int argc, const char **argv)
  {
        int status;
  
        if (last_up == 0)
                last_up = time (NULL) - 10;
  
 -      snprintf (pdp_step_str, sizeof (pdp_step_str), "%lu", pdp_step);
 -      pdp_step_str[sizeof (pdp_step_str) - 1] = '\0';
 -      snprintf (last_up_str, sizeof (last_up_str), "%u", (unsigned int) last_up);
 -      last_up_str[sizeof (last_up_str) - 1] = '\0';
 +      ssnprintf (pdp_step_str, sizeof (pdp_step_str), "%lu", pdp_step);
 +      ssnprintf (last_up_str, sizeof (last_up_str), "%u", (unsigned int) last_up);
  
        new_argv[0] = "create";
        new_argv[1] = filename;
        return (status);
  } /* int srrd_create */
  
 -static int srrd_update (char *filename, char *template, int argc, char **argv)
 +static int srrd_update (char *filename, char *template,
 +              int argc, const char **argv)
  {
        int status;
  
@@@ -510,7 -513,7 +514,7 @@@ static int rrd_create_file (char *filen
        status = srrd_create (filename,
                        (stepsize > 0) ? stepsize : vl->interval,
                        vl->time - 10,
 -                      argc, argv);
 +                      argc, (const char **)argv);
  
        free (argv);
        ds_free (ds_num, ds_def);
@@@ -528,7 -531,7 +532,7 @@@ static int value_list_to_string (char *
  
        memset (buffer, '\0', buffer_len);
  
 -      status = snprintf (buffer, buffer_len, "%u", (unsigned int) vl->time);
 +      status = ssnprintf (buffer, buffer_len, "%u", (unsigned int) vl->time);
        if ((status < 1) || (status >= buffer_len))
                return (-1);
        offset = status;
                        return (-1);
  
                if (ds->ds[i].type == DS_TYPE_COUNTER)
 -                      status = snprintf (buffer + offset, buffer_len - offset,
 +                      status = ssnprintf (buffer + offset, buffer_len - offset,
                                        ":%llu", vl->values[i].counter);
                else
 -                      status = snprintf (buffer + offset, buffer_len - offset,
 +                      status = ssnprintf (buffer + offset, buffer_len - offset,
                                        ":%lf", vl->values[i].gauge);
  
                if ((status < 1) || (status >= (buffer_len - offset)))
@@@ -563,35 -566,35 +567,35 @@@ static int value_list_to_filename (cha
  
        if (datadir != NULL)
        {
 -              status = snprintf (buffer + offset, buffer_len - offset,
 +              status = ssnprintf (buffer + offset, buffer_len - offset,
                                "%s/", datadir);
                if ((status < 1) || (status >= buffer_len - offset))
                        return (-1);
                offset += status;
        }
  
 -      status = snprintf (buffer + offset, buffer_len - offset,
 +      status = ssnprintf (buffer + offset, buffer_len - offset,
                        "%s/", vl->host);
        if ((status < 1) || (status >= buffer_len - offset))
                return (-1);
        offset += status;
  
        if (strlen (vl->plugin_instance) > 0)
 -              status = snprintf (buffer + offset, buffer_len - offset,
 +              status = ssnprintf (buffer + offset, buffer_len - offset,
                                "%s-%s/", vl->plugin, vl->plugin_instance);
        else
 -              status = snprintf (buffer + offset, buffer_len - offset,
 +              status = ssnprintf (buffer + offset, buffer_len - offset,
                                "%s/", vl->plugin);
        if ((status < 1) || (status >= buffer_len - offset))
                return (-1);
        offset += status;
  
        if (strlen (vl->type_instance) > 0)
 -              status = snprintf (buffer + offset, buffer_len - offset,
 -                              "%s-%s.rrd", ds->type, vl->type_instance);
 +              status = ssnprintf (buffer + offset, buffer_len - offset,
 +                              "%s-%s.rrd", vl->type, vl->type_instance);
        else
 -              status = snprintf (buffer + offset, buffer_len - offset,
 -                              "%s.rrd", ds->type);
 +              status = ssnprintf (buffer + offset, buffer_len - offset,
 +                              "%s.rrd", vl->type);
        if ((status < 1) || (status >= buffer_len - offset))
                return (-1);
        offset += status;
@@@ -650,8 -653,7 +654,8 @@@ static void *rrd_queue_thread (void *da
                pthread_mutex_unlock (&cache_lock);
  
                /* Write the values to the RRD-file */
 -              srrd_update (queue_entry->filename, NULL, values_num, values);
 +              srrd_update (queue_entry->filename, NULL,
 +                              values_num, (const char **)values);
                DEBUG ("rrdtool plugin: queue thread: Wrote %i values to %s",
                                values_num, queue_entry->filename);
  
        return ((void *) 0);
  } /* void *rrd_queue_thread */
  
 -static int rrd_queue_cache_entry (const char *filename)
 +static int rrd_queue_cache_entry (const char *filename, rrd_queue_dir_t dir)
  {
 -      rrd_queue_t *queue_entry;
 -
 -      queue_entry = (rrd_queue_t *) malloc (sizeof (rrd_queue_t));
 -      if (queue_entry == NULL)
 -              return (-1);
 -
 -      queue_entry->filename = strdup (filename);
 -      if (queue_entry->filename == NULL)
 -      {
 -              free (queue_entry);
 -              return (-1);
 -      }
 -
 -      queue_entry->next = NULL;
 -
 -      pthread_mutex_lock (&queue_lock);
 -      if (queue_tail == NULL)
 -              queue_head = queue_entry;
 -      else
 -              queue_tail->next = queue_entry;
 -      queue_tail = queue_entry;
 -      pthread_cond_signal (&queue_cond);
 -      pthread_mutex_unlock (&queue_lock);
 -
 -      DEBUG ("rrdtool plugin: Put `%s' into the update queue", filename);
 -
 -      return (0);
 +  rrd_queue_t *queue_entry;
 +
 +  queue_entry = (rrd_queue_t *) malloc (sizeof (rrd_queue_t));
 +  if (queue_entry == NULL)
 +    return (-1);
 +
 +  queue_entry->filename = strdup (filename);
 +  if (queue_entry->filename == NULL)
 +  {
 +    free (queue_entry);
 +    return (-1);
 +  }
 +
 +  queue_entry->next = NULL;
 +
 +  pthread_mutex_lock (&queue_lock);
 +  if (dir == QUEUE_INSERT_FRONT)
 +  {
 +    queue_entry->next = queue_head;
 +    queue_head = queue_entry;
 +    if (queue_tail == NULL)
 +      queue_tail = queue_head;
 +  }
 +  else /* (dir == QUEUE_INSERT_BACK) */
 +  {
 +    if (queue_tail == NULL)
 +      queue_head = queue_entry;
 +    else
 +      queue_tail->next = queue_entry;
 +    queue_tail = queue_entry;
 +  }
 +  pthread_cond_signal (&queue_cond);
 +  pthread_mutex_unlock (&queue_lock);
 +
 +  DEBUG ("rrdtool plugin: Put `%s' into the update queue", filename);
 +
 +  return (0);
  } /* int rrd_queue_cache_entry */
  
 +static int rrd_queue_move_to_front (const char *filename)
 +{
 +  rrd_queue_t *this;
 +  rrd_queue_t *prev;
 +
 +  this = NULL;
 +  prev = NULL;
 +  pthread_mutex_lock (&queue_lock);
 +  for (this = queue_head; this != NULL; this = this->next)
 +  {
 +    if (strcmp (this->filename, filename) == 0)
 +      break;
 +    prev = this;
 +  }
 +
 +  /* Check if we found the entry and if it is NOT the first entry. */
 +  if ((this != NULL) && (prev != NULL))
 +  {
 +    prev->next = this->next;
 +    this->next = queue_head;
 +    queue_head = this;
 +  }
 +  pthread_mutex_unlock (&queue_lock);
 +
 +  return (0);
 +} /* int rrd_queue_move_to_front */
 +
  static void rrd_cache_flush (int timeout)
  {
        rrd_cache_t *rc;
                        continue;
                else if (rc->values_num > 0)
                {
 -                      if (rrd_queue_cache_entry (key) == 0)
 +                      if (rrd_queue_cache_entry (key, QUEUE_INSERT_BACK) == 0)
                                rc->flags = FLAG_QUEUED;
                }
                else /* ancient and no values -> waste of memory */
        cache_flush_last = now;
  } /* void rrd_cache_flush */
  
 +static int rrd_cache_flush_identifier (int timeout, const char *identifier)
 +{
 +  rrd_cache_t *rc;
 +  time_t now;
 +  int status;
 +  char key[2048];
 +
 +  if (identifier == NULL)
 +  {
 +    rrd_cache_flush (timeout);
 +    return (0);
 +  }
 +
 +  now = time (NULL);
 +
 +  if (datadir == NULL)
 +        snprintf (key, sizeof (key), "%s.rrd",
 +                        identifier);
 +  else
 +        snprintf (key, sizeof (key), "%s/%s.rrd",
 +                        datadir, identifier);
 +  key[sizeof (key) - 1] = 0;
 +
 +  status = c_avl_get (cache, key, (void *) &rc);
 +  if (status != 0)
 +  {
 +    WARNING ("rrdtool plugin: rrd_cache_flush_identifier: "
 +      "c_avl_get (%s) failed. Does that file really exist?",
 +      key);
 +    return (status);
 +  }
 +
 +  if (rc->flags == FLAG_QUEUED)
 +    status = rrd_queue_move_to_front (key);
 +  else if ((now - rc->first_value) < timeout)
 +    status = 0;
 +  else if (rc->values_num > 0)
 +  {
 +    status = rrd_queue_cache_entry (key, QUEUE_INSERT_FRONT);
 +    if (status == 0)
 +      rc->flags = FLAG_QUEUED;
 +  }
 +
 +  return (status);
 +} /* int rrd_cache_flush_identifier */
 +
  static int rrd_cache_insert (const char *filename,
                const char *value, time_t value_time)
  {
        }
  
        DEBUG ("rrdtool plugin: rrd_cache_insert: file = %s; "
 -                      "values_num = %i; age = %u;",
 +                      "values_num = %i; age = %lu;",
                        filename, rc->values_num,
 -                      rc->last_value - rc->first_value);
 +                      (unsigned long)(rc->last_value - rc->first_value));
  
        if ((rc->last_value - rc->first_value) >= cache_timeout)
        {
                 * the same time, ALWAYS lock `cache_lock' first! */
                if (rc->flags != FLAG_QUEUED)
                {
 -                      if (rrd_queue_cache_entry (filename) == 0)
 +                      if (rrd_queue_cache_entry (filename, QUEUE_INSERT_BACK) == 0)
                                rc->flags = FLAG_QUEUED;
                }
                else
@@@ -994,11 -913,6 +998,11 @@@ static int rrd_write (const data_set_t 
        char         values[512];
        int          status;
  
 +      if (0 != strcmp (ds->type, vl->type)) {
 +              ERROR ("rrdtool plugin: DS type does not match value list type");
 +              return -1;
 +      }
 +
        if (value_list_to_filename (filename, sizeof (filename), ds, vl) != 0)
                return (-1);
  
        return (status);
  } /* int rrd_write */
  
 -static int rrd_flush (const int timeout)
 +static int rrd_flush (int timeout, const char *identifier)
  {
        pthread_mutex_lock (&cache_lock);
  
                return (0);
        }
  
 -      rrd_cache_flush (timeout);
 +      rrd_cache_flush_identifier (timeout, identifier);
 +
        pthread_mutex_unlock (&cache_lock);
        return (0);
  } /* int rrd_flush */
diff --combined src/serial.c
@@@ -41,13 -41,12 +41,13 @@@ static void serial_submit (const char *
        vl.values = values;
        vl.values_len = 2;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "serial");
-       strcpy (vl.type, "serial_octets");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "serial", sizeof (vl.plugin));
 -      strncpy (vl.type_instance, type_instance,
++      sstrncpy (vl.type, "serial_octets", sizeof (vl.type));
 +      sstrncpy (vl.type_instance, type_instance,
                        sizeof (vl.type_instance));
  
 -      plugin_dispatch_values ("serial_octets", &vl);
 +      plugin_dispatch_values (&vl);
  }
  
  static int serial_read (void)
diff --combined src/snmp.c
@@@ -198,8 -198,7 +198,8 @@@ static int csnmp_config_add_data_instan
    else
    {
      /* Instance is a simple string */
 -    strncpy (dd->instance.string, ci->values[0].value.string, DATA_MAX_NAME_LEN - 1);
 +    sstrncpy (dd->instance.string, ci->values[0].value.string,
 +      sizeof (dd->instance.string));
    }
  
    return (0);
@@@ -780,7 -779,7 +780,7 @@@ static int csnmp_check_res_left_subtre
      if (vb == NULL)
      {
        ERROR ("snmp plugin: host %s: Expected one more variable for "
 -        "the instance..");
 +        "the instance..", host->name);
        return (-1);
      }
  
@@@ -834,10 -833,11 +834,10 @@@ static int csnmp_instance_list_add (csn
      if (instance_len > vb->val_len)
        instance_len = vb->val_len;
  
 -    strncpy (il->instance, (char *) ((vb->type == ASN_OCTET_STR)
 +    sstrncpy (il->instance, (char *) ((vb->type == ASN_OCTET_STR)
          ? vb->val.string
          : vb->val.bitstring),
        instance_len);
 -    il->instance[instance_len] = '\0';
  
      for (ptr = il->instance; *ptr != '\0'; ptr++)
      {
    else
    {
      value_t val = csnmp_value_list_to_value (vb, DS_TYPE_COUNTER, 1.0, 0.0);
 -    snprintf (il->instance, sizeof (il->instance),
 +    ssnprintf (il->instance, sizeof (il->instance),
        "%llu", val.counter);
    }
 -  il->instance[sizeof (il->instance) - 1] = '\0';
  
    /* TODO: Debugging output */
  
@@@ -906,8 -907,9 +906,8 @@@ static int csnmp_dispatch_table (host_d
      return (-1);
    }
  
 -  strncpy (vl.host, host->name, sizeof (vl.host));
 -  vl.host[sizeof (vl.host) - 1] = '\0';
 +  sstrncpy (vl.host, host->name, sizeof (vl.host));
-   strcpy (vl.plugin, "snmp");
+   sstrncpy (vl.plugin, "snmp", sizeof (vl.plugin));
  
    vl.interval = host->interval;
    vl.time = time (NULL);
        || (instance_list_ptr->subid == value_table_ptr[0]->subid));
  #endif
  
 +    sstrncpy (vl.type, data->type, sizeof (vl.type));
 +
      {
        char temp[DATA_MAX_NAME_LEN];
  
        if (instance_list_ptr == NULL)
 -      snprintf (temp, sizeof (temp), "%u",
 -          (uint32_t) subid);
 +      ssnprintf (temp, sizeof (temp), "%u", (uint32_t) subid);
        else
 -      strncpy (temp, instance_list_ptr->instance,
 -          sizeof (temp));
 -      temp[sizeof (temp) - 1] = '\0';
 +      sstrncpy (temp, instance_list_ptr->instance, sizeof (temp));
  
        if (data->instance_prefix == NULL)
 -      strncpy (vl.type_instance, temp, sizeof (vl.type_instance));
 +      sstrncpy (vl.type_instance, temp, sizeof (vl.type_instance));
        else
 -      snprintf (vl.type_instance, sizeof (vl.type_instance), "%s%s",
 +      ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s%s",
            data->instance_prefix, temp);
 -      vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
      }
  
      for (i = 0; i < data->values_len; i++)
        vl.values[i] = value_table_ptr[i]->value;
  
      /* If we get here `vl.type_instance' and all `vl.values' have been set */
 -    plugin_dispatch_values (data->type, &vl);
 +    plugin_dispatch_values (&vl);
  
      subid++;
    } /* while (have_more != 0) */
@@@ -1295,10 -1299,11 +1295,10 @@@ static int csnmp_read_value (host_defin
        vl.values[i].gauge = NAN;
    }
  
 -  strncpy (vl.host, host->name, sizeof (vl.host));
 -  vl.host[sizeof (vl.host) - 1] = '\0';
 +  sstrncpy (vl.host, host->name, sizeof (vl.host));
-   strcpy (vl.plugin, "snmp");
+   sstrncpy (vl.plugin, "snmp", sizeof (vl.plugin));
 -  strncpy (vl.type_instance, data->instance.string, sizeof (vl.type_instance));
 -  vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
 +  sstrncpy (vl.type, data->type, sizeof (vl.type));
 +  sstrncpy (vl.type_instance, data->instance.string, sizeof (vl.type_instance));
  
    vl.interval = host->interval;
  
      snmp_free_pdu (res);
    res = NULL;
  
 -  DEBUG ("snmp plugin: -> plugin_dispatch_values (%s, &vl);", data->type);
 -  plugin_dispatch_values (data->type, &vl);
 +  DEBUG ("snmp plugin: -> plugin_dispatch_values (&vl);");
 +  plugin_dispatch_values (&vl);
    sfree (vl.values);
  
    return (0);
@@@ -1395,8 -1400,8 +1395,8 @@@ static int csnmp_read_host (host_defini
    if ((time_end - time_start) > host->interval)
    {
      WARNING ("snmp plugin: Host `%s' should be queried every %i seconds, "
 -      "but reading all values takes %i seconds.",
 -      host->name, host->interval, time_end - time_start);
 +      "but reading all values takes %lu seconds.",
 +      host->name, host->interval, (unsigned long)(time_end - time_start));
    }
  
    return (0);
diff --combined src/swap.c
@@@ -124,12 -124,11 +124,12 @@@ static void swap_submit (const char *ty
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "swap");
-       strcpy (vl.type, "swap");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "swap", sizeof (vl.plugin));
 -      strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
++      sstrncpy (vl.type, "swap", sizeof (vl.type));
 +      sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values ("swap", &vl);
 +      plugin_dispatch_values (&vl);
  } /* void swap_submit */
  
  static int swap_read (void)
diff --combined src/tape.c
@@@ -69,13 -69,12 +69,13 @@@ static void tape_submit (const char *pl
        vl.values = values;
        vl.values_len = 2;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "tape");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "tape", sizeof (vl.plugin));
 -      strncpy (vl.plugin_instance, plugin_instance,
 +      sstrncpy (vl.plugin_instance, plugin_instance,
                        sizeof (vl.plugin_instance));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  } /* void tape_submit */
  
  static int tape_read (void)
diff --combined src/tcpconns.c
@@@ -135,38 -135,41 +135,38 @@@ static void conn_submit_port_entry (por
    vl.values = values;
    vl.values_len = 1;
    vl.time = time (NULL);
-   strcpy (vl.host, hostname_g);
-   strcpy (vl.plugin, "tcpconns");
-   strcpy (vl.type, "tcp_connections");
+   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+   sstrncpy (vl.plugin, "tcpconns", sizeof (vl.plugin));
++  sstrncpy (vl.type, "tcp_connections", sizeof (vl.type));
  
    if (((port_collect_listening != 0) && (pe->flags & PORT_IS_LISTENING))
        || (pe->flags & PORT_COLLECT_LOCAL))
    {
 -    snprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
 +    ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
        "%hu-local", pe->port);
 -    vl.plugin_instance[sizeof (vl.plugin_instance) - 1] = '\0';
  
      for (i = 1; i <= TCP_STATE_MAX; i++)
      {
        vl.values[0].gauge = pe->count_local[i];
  
 -      strncpy (vl.type_instance, tcp_state[i], sizeof (vl.type_instance));
 -      vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
 +      sstrncpy (vl.type_instance, tcp_state[i], sizeof (vl.type_instance));
  
 -      plugin_dispatch_values ("tcp_connections", &vl);
 +      plugin_dispatch_values (&vl);
      }
    }
  
    if (pe->flags & PORT_COLLECT_REMOTE)
    {
 -    snprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
 +    ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
        "%hu-remote", pe->port);
 -    vl.plugin_instance[sizeof (vl.plugin_instance) - 1] = '\0';
  
      for (i = 1; i <= TCP_STATE_MAX; i++)
      {
        vl.values[0].gauge = pe->count_remote[i];
  
 -      strncpy (vl.type_instance, tcp_state[i], sizeof (vl.type_instance));
 -      vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
 +      sstrncpy (vl.type_instance, tcp_state[i], sizeof (vl.type_instance));
  
 -      plugin_dispatch_values ("tcp_connections", &vl);
 +      plugin_dispatch_values (&vl);
      }
    }
  } /* void conn_submit */
diff --combined src/users.c
@@@ -49,11 -49,10 +49,11 @@@ static void users_submit (gauge_t value
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "users");
-       strcpy (vl.type, "users");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "users", sizeof (vl.plugin));
++      sstrncpy (vl.type, "users", sizeof (vl.plugin));
  
 -      plugin_dispatch_values ("users", &vl);
 +      plugin_dispatch_values (&vl);
  } /* void users_submit */
  
  static int users_read (void)
diff --combined src/utils_cmd_putval.c
@@@ -32,6 -32,7 +32,6 @@@
        }
  
  static int parse_value (const data_set_t *ds, value_list_t *vl,
 -              const char *type,
                FILE *fh, char *buffer)
  {
        char *dummy;
@@@ -89,7 -90,7 +89,7 @@@
                return (-1);
        }
  
 -      plugin_dispatch_values (type, vl);
 +      plugin_dispatch_values (vl);
        return (0);
  } /* int parse_value */
  
@@@ -170,13 -171,12 +170,13 @@@ int handle_putval (FILE *fh, char **fie
                return (-1);
        }
  
-       strcpy (vl.host, hostname);
-       strcpy (vl.plugin, plugin);
+       sstrncpy (vl.host, hostname, sizeof (vl.host));
+       sstrncpy (vl.plugin, plugin, sizeof (vl.plugin));
++      sstrncpy (vl.type, type, sizeof (vl.type));
        if (plugin_instance != NULL)
-               strcpy (vl.plugin_instance, plugin_instance);
-       strcpy (vl.type, type);
+               sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
        if (type_instance != NULL)
-               strcpy (vl.type_instance, type_instance);
+               sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
  
        ds = plugin_get_ds (type);
        if (ds == NULL) {
                        /* It's parse_value's job to write an error to `fh'.
                         * This is not the case with `parse_option below.
                         * Neither will write an success message. */
 -                      if (parse_value (ds, &vl, type, fh, fields[i]) != 0)
 +                      if (parse_value (ds, &vl, fh, fields[i]) != 0)
                                break;
                }
                else if (strchr (fields[i], '=') != NULL)
diff --combined src/utils_dns.c
@@@ -34,7 -34,6 +34,7 @@@
   */
  
  #include "collectd.h"
 +#include "common.h"
  
  #if HAVE_NETINET_IN_SYSTM_H
  # include <netinet/in_systm.h>
@@@ -385,7 -384,7 +385,7 @@@ handle_dns(const char *buf, int len
      if (0 != x)
        return 0;
      if ('\0' == qh.qname[0])
-       strcpy(qh.qname, ".");
 -      strncpy (qh.qname, ".", sizeof (qh.qname));
++      sstrncpy (qh.qname, ".", sizeof (qh.qname));
      while ((t = strchr(qh.qname, '\n')))
        *t = ' ';
      while ((t = strchr(qh.qname, '\r')))
@@@ -705,7 -704,7 +705,7 @@@ const char *qtype_str(int t
  {
      static char buf[32];
      switch (t) {
- #if (defined (__NAMESER)) && (__NAMESER >= 19991006)
+ #if (defined (__NAMESER)) && (__NAMESER >= 19991001)
            case ns_t_a:        return ("A");
            case ns_t_ns:       return ("NS");
            case ns_t_md:       return ("MD");
            case ns_t_dname:    return ("DNAME");
            case ns_t_sink:     return ("SINK");
            case ns_t_opt:      return ("OPT");
+ # if __NAMESER >= 19991006
            case ns_t_tsig:     return ("TSIG");
+ # endif
            case ns_t_ixfr:     return ("IXFR");
            case ns_t_axfr:     return ("AXFR");
            case ns_t_mailb:    return ("MAILB");
            case T_ANY:         return ("ANY"); /* ... 255 */
  #endif /* __BIND >= 19950621 */
            default:
 -                  snprintf (buf, 32, "#%i", t);
 -                  buf[31] = '\0';
 +                  ssnprintf (buf, sizeof (buf), "#%i", t);
                    return (buf);
      }; /* switch (t) */
      /* NOTREACHED */
@@@ -841,7 -843,7 +843,7 @@@ const char *opcode_str (int o
        return "Update";
        break;
      default:
 -      snprintf(buf, 30, "Opcode%d", o);
 +      ssnprintf(buf, sizeof (buf), "Opcode%d", o);
        return buf;
      }
      /* NOTREACHED */
@@@ -885,7 -887,8 +887,7 @@@ const char *rcode_str (int rcode
  #endif  /* RFC2136 rcodes */
  #endif /* __BIND >= 19950621 */
                default:
 -                      snprintf (buf, 32, "RCode%i", rcode);
 -                      buf[31] = '\0';
 +                      ssnprintf (buf, sizeof (buf), "RCode%i", rcode);
                        return (buf);
        }
        /* Never reached */
diff --combined src/vmem.c
@@@ -46,15 -46,14 +46,15 @@@ static void submit (const char *plugin_
    vl.values_len = values_len;
  
    vl.time = time (NULL);
-   strcpy (vl.host, hostname_g);
-   strcpy (vl.plugin, "vmem");
+   sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+   sstrncpy (vl.plugin, "vmem", sizeof (vl.plugin));
    if (plugin_instance != NULL)
      sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
 +  sstrncpy (vl.type, type, sizeof (vl.type));
    if (type_instance != NULL)
      sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
  
 -  plugin_dispatch_values (type, &vl);
 +  plugin_dispatch_values (&vl);
  } /* void vmem_submit */
  
  static void submit_two (const char *plugin_instance, const char *type,
diff --combined src/vserver.c
@@@ -57,13 -57,12 +57,13 @@@ static void traffic_submit (const char 
        vl.values = values;
        vl.values_len = STATIC_ARRAY_SIZE (values);
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "vserver");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "vserver", sizeof (vl.plugin));
 -      strncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
 -      strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 +      sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
-       strcpy (vl.type, "if_octets");
++      sstrncpy (vl.type, "if_octets", sizeof (vl.type));
 +      sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values ("if_octets", &vl);
 +      plugin_dispatch_values (&vl);
  } /* void traffic_submit */
  
  static void load_submit (const char *plugin_instance,
        vl.values = values;
        vl.values_len = STATIC_ARRAY_SIZE (values);
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "vserver");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "vserver", sizeof (vl.plugin));
 -      strncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
 +      sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
-       strcpy (vl.type, "load");
++      sstrncpy (vl.type, "load", sizeof (vl.type));
  
 -      plugin_dispatch_values ("load", &vl);
 +      plugin_dispatch_values (&vl);
  }
  
  static void submit_gauge (const char *plugin_instance, const char *type,
        vl.values = values;
        vl.values_len = STATIC_ARRAY_SIZE (values);
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "vserver");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "vserver", sizeof (vl.plugin));
 -      strncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
 -      strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
 +      sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
 +      sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  } /* void submit_gauge */
  
  static inline long long __get_sock_bytes(const char *s)
@@@ -150,9 -147,8 +150,9 @@@ static int vserver_read (void
                        continue;
  
                /* socket message accounting */
 -              len = snprintf (file, BUFSIZE, PROCDIR "/%s/cacct", dent->d_name);
 -              if ((len < 0) || (len >= BUFSIZE))
 +              len = ssnprintf (file, sizeof (file),
 +                              PROCDIR "/%s/cacct", dent->d_name);
 +              if ((len < 0) || (len >= sizeof (file)))
                        continue;
  
                if (NULL == (fh = fopen (file, "r")))
                }
  
                /* thread information and load */
 -              len = snprintf (file, BUFSIZE, PROCDIR "/%s/cvirt", dent->d_name);
 -              if ((len < 0) || (len >= BUFSIZE))
 +              len = ssnprintf (file, sizeof (file),
 +                              PROCDIR "/%s/cvirt", dent->d_name);
 +              if ((len < 0) || (len >= sizeof (file)))
                        continue;
  
                if (NULL == (fh = fopen (file, "r")))
                }
  
                /* processes and memory usage */
 -              len = snprintf (file, BUFSIZE, PROCDIR "/%s/limit", dent->d_name);
 -              if ((len < 0) || (len >= BUFSIZE))
 +              len = ssnprintf (file, sizeof (file),
 +                              PROCDIR "/%s/limit", dent->d_name);
 +              if ((len < 0) || (len >= sizeof (file)))
                        continue;
  
                if (NULL == (fh = fopen (file, "r")))
diff --combined src/wireless.c
@@@ -56,13 -56,12 +56,13 @@@ static void wireless_submit (const cha
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "wireless");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "wireless", sizeof (vl.plugin));
 -      strncpy (vl.plugin_instance, plugin_instance,
 +      sstrncpy (vl.plugin_instance, plugin_instance,
                        sizeof (vl.plugin_instance));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  } /* void wireless_submit */
  
  #define POWER_MIN -90.0
diff --combined src/xmms.c
@@@ -37,11 -37,10 +37,11 @@@ static void cxmms_submit (const char *t
        vl.values = values;
        vl.values_len = 1;
        vl.time = time (NULL);
-       strcpy (vl.host, hostname_g);
-       strcpy (vl.plugin, "xmms");
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "xmms", sizeof (vl.plugin));
 +      sstrncpy (vl.type, type, sizeof (vl.type));
  
 -      plugin_dispatch_values (type, &vl);
 +      plugin_dispatch_values (&vl);
  } /* void cxmms_submit */
  
  int cxmms_read (void)