X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fcommon.c;h=1138f96ff92e688063990c1bdd084eca816fbb47;hb=4053192182658147f98bddddcec55eb1ff1dd67c;hp=365b74f30091599c8d4d703da184c899cd20e26a;hpb=3e4bbefce5ef9b121c4282fbfd326b6d5e52375d;p=collectd.git diff --git a/src/common.c b/src/common.c index 365b74f3..1138f96f 100644 --- a/src/common.c +++ b/src/common.c @@ -20,11 +20,19 @@ * Niki W. Waibel **/ +#if HAVE_CONFIG_H +# include "config.h" +#endif + #include "common.h" -#include "utils_debug.h" +#include "plugin.h" + +#if HAVE_PTHREAD_H +# include +#endif #ifdef HAVE_MATH_H -# include +# include #endif /* for ntohl and htonl */ @@ -36,6 +44,14 @@ extern kstat_ctl_t *kc; #endif +#if !HAVE_GETPWNAM_R +static pthread_mutex_t getpwnam_r_lock = PTHREAD_MUTEX_INITIALIZER; +#endif + +#if !HAVE_STRERROR_R +static pthread_mutex_t strerror_r_lock = PTHREAD_MUTEX_INITIALIZER; +#endif + void sstrncpy (char *d, const char *s, int len) { strncpy (d, s, len); @@ -51,20 +67,68 @@ char *sstrdup (const char *s) if((r = strdup (s)) == NULL) { - DBG ("Not enough memory."); + DEBUG ("Not enough memory."); exit(3); } return (r); } +/* Even though Posix requires "strerror_r" to return an "int", + * some systems (e.g. the GNU libc) return a "char *" _and_ + * ignore the second argument ... -tokkee */ +char *sstrerror (int errnum, char *buf, size_t buflen) +{ + buf[0] = '\0'; + +#if !HAVE_STRERROR_R + { + char *temp; + + pthread_mutex_lock (&strerror_r_lock); + + temp = strerror (errnum); + strncpy (buf, temp, buflen); + + pthread_mutex_unlock (&strerror_r_lock); + } +/* #endif !HAVE_STRERROR_R */ + +#elif STRERROR_R_CHAR_P + { + char *temp; + temp = strerror_r (errnum, buf, buflen); + if (buf[0] == '\0') + { + if ((temp != NULL) && (temp != buf) && (temp[0] != '\0')) + strncpy (buf, temp, buflen); + else + strncpy (buf, "strerror_r did not return " + "an error message", buflen); + } + } +/* #endif STRERROR_R_CHAR_P */ + +#else + if (strerror_r (errnum, buf, buflen) != 0) + { + snprintf (buf, buflen, "Error #%i; " + "Additionally, strerror_r failed.", + errnum); + } +#endif /* STRERROR_R_CHAR_P */ + + buf[buflen - 1] = '\0'; + return (buf); +} /* char *sstrerror */ + void *smalloc (size_t size) { void *r; if ((r = malloc (size)) == NULL) { - DBG("Not enough memory."); + DEBUG("Not enough memory."); exit(3); } @@ -105,7 +169,7 @@ ssize_t sread (int fd, void *buf, size_t count) if (status == 0) { - DBG ("Received EOF from fd %i. " + DEBUG ("Received EOF from fd %i. " "Closing fd and returning error.", fd); close (fd); @@ -152,10 +216,12 @@ int strsplit (char *string, char **fields, size_t size) { size_t i; char *ptr; + char *saveptr; i = 0; ptr = string; - while ((fields[i] = strtok (ptr, " \t")) != NULL) + saveptr = NULL; + while ((fields[i] = strtok_r (ptr, " \t", &saveptr)) != NULL) { ptr = NULL; i++; @@ -226,7 +292,7 @@ int strsubstitute (char *str, char c_from, char c_to) } return (ret); -} +} /* int strsubstitute */ int escape_slashes (char *buf, int buf_len) { @@ -241,8 +307,12 @@ int escape_slashes (char *buf, int buf_len) return (0); } + if (buf_len <= 1) + return (0); + /* Move one to the left */ - memmove (buf, buf + 1, buf_len - 1); + if (buf[0] == '/') + memmove (buf, buf + 1, buf_len - 1); for (i = 0; i < buf_len - 1; i++) { @@ -254,7 +324,7 @@ int escape_slashes (char *buf, int buf_len) buf[i] = '\0'; return (0); -} +} /* int escape_slashes */ int timeval_sub_timespec (struct timeval *tv0, struct timeval *tv1, struct timespec *ret) { @@ -289,7 +359,9 @@ int check_create_dir (const char *file_orig) char *fields[16]; int fields_num; char *ptr; + char *saveptr; int last_is_file = 1; + int path_is_absolute = 0; int len; int i; @@ -310,9 +382,11 @@ int check_create_dir (const char *file_orig) */ if (file_orig[len - 1] == '/') last_is_file = 0; + if (file_orig[0] == '/') + path_is_absolute = 1; /* - * Create a copy for `strtok' to destroy + * Create a copy for `strtok_r' to destroy */ strncpy (file_copy, file_orig, 512); file_copy[511] = '\0'; @@ -322,8 +396,9 @@ int check_create_dir (const char *file_orig) * remove leading and trailing slashes.. */ ptr = file_copy; + saveptr = NULL; fields_num = 0; - while ((fields[fields_num] = strtok (ptr, "/")) != NULL) + while ((fields[fields_num] = strtok_r (ptr, "/", &saveptr)) != NULL) { ptr = NULL; fields_num++; @@ -344,16 +419,18 @@ int check_create_dir (const char *file_orig) */ if (fields[i][0] == '.') { - syslog (LOG_ERR, "Cowardly refusing to create a directory that begins with a `.' (dot): `%s'", file_orig); + ERROR ("Cowardly refusing to create a directory that begins with a `.' (dot): `%s'", file_orig); return (-2); } /* * Join the components together again */ - if (strjoin (dir, dir_len, fields, i + 1, "/") < 0) + dir[0] = '/'; + if (strjoin (dir + path_is_absolute, dir_len - path_is_absolute, + fields, i + 1, "/") < 0) { - syslog (LOG_ERR, "strjoin failed: `%s', component #%i", file_orig, i); + ERROR ("strjoin failed: `%s', component #%i", file_orig, i); return (-1); } @@ -363,25 +440,31 @@ int check_create_dir (const char *file_orig) { if (mkdir (dir, 0755) == -1) { - syslog (LOG_ERR, "mkdir (%s): %s", dir, strerror (errno)); + char errbuf[1024]; + ERROR ("check_create_dir: mkdir (%s): %s", dir, + sstrerror (errno, + errbuf, sizeof (errbuf))); return (-1); } } else { - syslog (LOG_ERR, "stat (%s): %s", dir, strerror (errno)); + char errbuf[1024]; + ERROR ("stat (%s): %s", dir, + sstrerror (errno, errbuf, + sizeof (errbuf))); return (-1); } } else if (!S_ISDIR (statbuf.st_mode)) { - syslog (LOG_ERR, "stat (%s): Not a directory!", dir); + ERROR ("stat (%s): Not a directory!", dir); return (-1); } } return (0); -} +} /* check_create_dir */ #ifdef HAVE_LIBKSTAT int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name) @@ -398,13 +481,13 @@ int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name) { if ((*ksp_ptr = kstat_lookup (kc, module, instance, name)) == NULL) { - syslog (LOG_ERR, "Cound not find kstat %s", ident); + ERROR ("Cound not find kstat %s", ident); return (-1); } if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED) { - syslog (LOG_WARNING, "kstat %s has wrong type", ident); + WARNING ("kstat %s has wrong type", ident); *ksp_ptr = NULL; return (-1); } @@ -417,13 +500,13 @@ int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name) if (kstat_read (kc, *ksp_ptr, NULL) == -1) { - syslog (LOG_WARNING, "kstat %s could not be read", ident); + WARNING ("kstat %s could not be read", ident); return (-1); } if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED) { - syslog (LOG_WARNING, "kstat %s has wrong type", ident); + WARNING ("kstat %s has wrong type", ident); return (-1); } @@ -463,7 +546,7 @@ long long get_kstat_value (kstat_t *ksp, char *name) else if (kn->data_type == KSTAT_DATA_UINT64) retval = (long long) kn->value.ui64; /* XXX: Might overflow! */ else - syslog (LOG_WARNING, "get_kstat_value: Not a numeric value: %s", name); + WARNING ("get_kstat_value: Not a numeric value: %s", name); return (retval); } @@ -476,7 +559,7 @@ unsigned long long ntohll (unsigned long long n) #else return (((unsigned long long) ntohl (n)) << 32) + ntohl (n >> 32); #endif -} +} /* unsigned long long ntohll */ unsigned long long htonll (unsigned long long n) { @@ -485,4 +568,182 @@ unsigned long long htonll (unsigned long long n) #else return (((unsigned long long) htonl (n)) << 32) + htonl (n >> 32); #endif -} +} /* unsigned long long htonll */ + +int format_name (char *ret, int ret_len, + const char *hostname, + const char *plugin, const char *plugin_instance, + const char *type, const char *type_instance) +{ + int status; + + assert (plugin != NULL); + assert (type != NULL); + + if ((plugin_instance == NULL) || (strlen (plugin_instance) == 0)) + { + if ((type_instance == NULL) || (strlen (type_instance) == 0)) + status = snprintf (ret, ret_len, "%s/%s/%s", + hostname, plugin, type); + else + status = snprintf (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", + hostname, plugin, plugin_instance, + type); + else + status = snprintf (ret, ret_len, "%s/%s-%s/%s-%s", + hostname, plugin, plugin_instance, + type, type_instance); + } + + if ((status < 1) || (status >= ret_len)) + return (-1); + return (0); +} /* int format_name */ + +int parse_identifier (char *str, char **ret_host, + char **ret_plugin, char **ret_plugin_instance, + char **ret_type, char **ret_type_instance) +{ + char *hostname = NULL; + char *plugin = NULL; + char *plugin_instance = NULL; + char *type = NULL; + char *type_instance = NULL; + + hostname = str; + if (hostname == NULL) + return (-1); + + plugin = strchr (hostname, '/'); + if (plugin == NULL) + return (-1); + *plugin = '\0'; plugin++; + + type = strchr (plugin, '/'); + if (type == NULL) + return (-1); + *type = '\0'; type++; + + plugin_instance = strchr (plugin, '-'); + if (plugin_instance != NULL) + { + *plugin_instance = '\0'; + plugin_instance++; + } + + type_instance = strchr (type, '-'); + if (type_instance != NULL) + { + *type_instance = '\0'; + type_instance++; + } + + *ret_host = hostname; + *ret_plugin = plugin; + *ret_plugin_instance = plugin_instance; + *ret_type = type; + *ret_type_instance = type_instance; + return (0); +} /* int parse_identifier */ + +int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds) +{ + int i; + char *dummy; + char *ptr; + char *saveptr; + + i = -1; + dummy = buffer; + saveptr = NULL; + while ((ptr = strtok_r (dummy, ":", &saveptr)) != NULL) + { + dummy = NULL; + + if (i >= vl->values_len) + break; + + if (i == -1) + { + if (strcmp ("N", ptr) == 0) + vl->time = time (NULL); + else + vl->time = (time_t) atoi (ptr); + } + else + { + if (strcmp ("U", ptr) == 0) + vl->values[i].gauge = NAN; + else if (ds->ds[i].type == DS_TYPE_COUNTER) + vl->values[i].counter = atoll (ptr); + else if (ds->ds[i].type == DS_TYPE_GAUGE) + vl->values[i].gauge = atof (ptr); + } + + i++; + } /* while (strtok_r) */ + + if ((ptr != NULL) || (i != vl->values_len)) + return (-1); + return (0); +} /* int parse_values */ + +#if !HAVE_GETPWNAM_R +int getpwnam_r (const char *name, struct passwd *pwbuf, char *buf, + size_t buflen, struct passwd **pwbufp) +{ + int status = 0; + struct passwd *pw; + + memset (pwbuf, '\0', sizeof (struct passwd)); + + pthread_mutex_lock (&getpwnam_r_lock); + + do + { + pw = getpwnam (name); + if (pw == NULL) + { + status = (errno != 0) ? errno : ENOENT; + break; + } + +#define GETPWNAM_COPY_MEMBER(member) \ + if (pw->member != NULL) \ + { \ + int len = strlen (pw->member); \ + if (len >= buflen) \ + { \ + status = ENOMEM; \ + break; \ + } \ + sstrncpy (buf, pw->member, buflen); \ + pwbuf->member = buf; \ + buf += (len + 1); \ + buflen -= (len + 1); \ + } + GETPWNAM_COPY_MEMBER(pw_name); + GETPWNAM_COPY_MEMBER(pw_passwd); + GETPWNAM_COPY_MEMBER(pw_gecos); + GETPWNAM_COPY_MEMBER(pw_dir); + GETPWNAM_COPY_MEMBER(pw_shell); + + pwbuf->pw_uid = pw->pw_uid; + pwbuf->pw_gid = pw->pw_gid; + + if (pwbufp != NULL) + *pwbufp = pwbuf; + } while (0); + + pthread_mutex_unlock (&getpwnam_r_lock); + + return (status); +} /* int getpwnam_r */ +#endif