X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Fdaemon%2Fcollectd.c;h=9ec09347267f474c846d4807ceb065f9800ce493;hp=f3df795d8246c8acdce67e0a4db685e1b7c4253d;hb=1159cb5d383c55a80a0db100b8f7aadcf44740a5;hpb=3fb6fe5776c14f41879249f4147c0b8924b39cc1 diff --git a/src/daemon/collectd.c b/src/daemon/collectd.c index f3df795d..9ec09347 100644 --- a/src/daemon/collectd.c +++ b/src/daemon/collectd.c @@ -47,16 +47,6 @@ #define COLLECTD_LOCALE "C" #endif -/* - * Global variables - */ -char hostname_g[DATA_MAX_NAME_LEN]; -cdtime_t interval_g; -int timeout_g; -#if HAVE_LIBKSTAT -kstat_ctl_t *kc; -#endif /* HAVE_LIBKSTAT */ - static int loop = 0; static void *do_flush(void __attribute__((unused)) * arg) { @@ -86,38 +76,42 @@ static void sig_usr1_handler(int __attribute__((unused)) signal) { } static int init_hostname(void) { - const char *str; - - struct addrinfo *ai_list; - int status; - - str = global_option_get("Hostname"); + const char *str = global_option_get("Hostname"); if ((str != NULL) && (str[0] != 0)) { - sstrncpy(hostname_g, str, sizeof(hostname_g)); - return (0); + hostname_set(str); + return 0; + } + + long hostname_len = sysconf(_SC_HOST_NAME_MAX); + if (hostname_len == -1) { + hostname_len = NI_MAXHOST; } + char hostname[hostname_len]; - if (gethostname(hostname_g, sizeof(hostname_g)) != 0) { + if (gethostname(hostname, hostname_len) != 0) { fprintf(stderr, "`gethostname' failed and no " "hostname was configured.\n"); - return (-1); + return -1; } + hostname_set(hostname); + str = global_option_get("FQDNLookup"); if (IS_FALSE(str)) - return (0); + return 0; + struct addrinfo *ai_list; struct addrinfo ai_hints = {.ai_flags = AI_CANONNAME}; - status = getaddrinfo(hostname_g, NULL, &ai_hints, &ai_list); + int status = getaddrinfo(hostname, NULL, &ai_hints, &ai_list); if (status != 0) { ERROR("Looking up \"%s\" failed. You have set the " "\"FQDNLookup\" option, but I cannot resolve " "my hostname to a fully qualified domain " "name. Please fix the network " "configuration.", - hostname_g); - return (-1); + hostname); + return -1; } for (struct addrinfo *ai_ptr = ai_list; ai_ptr != NULL; @@ -125,12 +119,12 @@ static int init_hostname(void) { if (ai_ptr->ai_canonname == NULL) continue; - sstrncpy(hostname_g, ai_ptr->ai_canonname, sizeof(hostname_g)); + hostname_set(ai_ptr->ai_canonname); break; } freeaddrinfo(ai_list); - return (0); + return 0; } /* int init_hostname */ static int init_global_variables(void) { @@ -147,18 +141,18 @@ static int init_global_variables(void) { if (timeout_g <= 1) { fprintf(stderr, "Cannot set the timeout to a correct value.\n" "Please check your settings.\n"); - return (-1); + return -1; } DEBUG("timeout_g = %i;", timeout_g); if (init_hostname() != 0) - return (-1); + return -1; DEBUG("hostname_g = %s;", hostname_g); - return (0); + return 0; } /* int init_global_variables */ -static int change_basedir(const char *orig_dir) { +static int change_basedir(const char *orig_dir, _Bool create) { char *dir; size_t dirlen; int status; @@ -167,7 +161,7 @@ static int change_basedir(const char *orig_dir) { if (dir == NULL) { char errbuf[1024]; ERROR("strdup failed: %s", sstrerror(errno, errbuf, sizeof(errbuf))); - return (-1); + return -1; } dirlen = strlen(dir); @@ -176,19 +170,19 @@ static int change_basedir(const char *orig_dir) { if (dirlen == 0) { free(dir); - return (-1); + return -1; } status = chdir(dir); if (status == 0) { free(dir); - return (0); - } else if (errno != ENOENT) { + return 0; + } else if (!create || (errno != ENOENT)) { char errbuf[1024]; ERROR("change_basedir: chdir (%s): %s", dir, sstrerror(errno, errbuf, sizeof(errbuf))); free(dir); - return (-1); + return -1; } status = mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO); @@ -197,7 +191,7 @@ static int change_basedir(const char *orig_dir) { ERROR("change_basedir: mkdir (%s): %s", dir, sstrerror(errno, errbuf, sizeof(errbuf))); free(dir); - return (-1); + return -1; } status = chdir(dir); @@ -206,11 +200,11 @@ static int change_basedir(const char *orig_dir) { ERROR("change_basedir: chdir (%s): %s", dir, sstrerror(errno, errbuf, sizeof(errbuf))); free(dir); - return (-1); + return -1; } free(dir); - return (0); + return 0; } /* static int change_basedir (char *dir) */ #if HAVE_LIBKSTAT @@ -250,6 +244,7 @@ __attribute__((noreturn)) static void exit_usage(int status) { #if COLLECT_DAEMON " -f Don't fork to the background.\n" #endif + " -B Don't create the BaseDir\n" " -h Display help (this message)\n" "\nBuiltin defaults:\n" " Config file " CONFIGFILE "\n" @@ -285,12 +280,12 @@ static int do_init(void) { #endif )) { ERROR("sg_init: %s", sg_str_error(sg_get_error())); - return (-1); + return -1; } if (sg_drop_privileges()) { ERROR("sg_drop_privileges: %s", sg_str_error(sg_get_error())); - return (-1); + return -1; } #endif @@ -329,12 +324,12 @@ static int do_loop(void) { if (errno != EINTR) { char errbuf[1024]; ERROR("nanosleep failed: %s", sstrerror(errno, errbuf, sizeof(errbuf))); - return (-1); + return -1; } } } /* while (loop == 0) */ - return (0); + return 0; } /* int do_loop */ static int do_shutdown(void) { @@ -349,13 +344,13 @@ static int pidfile_create(void) { if ((fh = fopen(file, "w")) == NULL) { char errbuf[1024]; ERROR("fopen (%s): %s", file, sstrerror(errno, errbuf, sizeof(errbuf))); - return (1); + return 1; } fprintf(fh, "%i\n", (int)getpid()); fclose(fh); - return (0); + return 0; } /* static int pidfile_create (const char *file) */ static int pidfile_remove(void) { @@ -363,7 +358,7 @@ static int pidfile_remove(void) { if (file == NULL) return 0; - return (unlink(file)); + return unlink(file); } /* static int pidfile_remove (const char *file) */ #endif /* COLLECT_DAEMON */ @@ -454,21 +449,18 @@ static int notify_systemd(void) { } #endif /* KERNEL_LINUX */ -int main(int argc, char **argv) { - const char *configfile = CONFIGFILE; - int test_config = 0; - int test_readall = 0; - const char *basedir; -#if COLLECT_DAEMON - pid_t pid; - int daemonize = 1; -#endif - int exit_status = 0; +struct cmdline_config { + _Bool test_config; + _Bool test_readall; + _Bool create_basedir; + const char *configfile; + _Bool daemonize; +}; +void read_cmdline(int argc, char **argv, struct cmdline_config *config) { /* read options */ while (1) { int c; - c = getopt(argc, argv, "htTC:" #if COLLECT_DAEMON "fP:" @@ -479,17 +471,20 @@ int main(int argc, char **argv) { break; switch (c) { + case 'B': + config->create_basedir = 0; + break; case 'C': - configfile = optarg; + config->configfile = optarg; break; case 't': - test_config = 1; + config->test_config = 1; break; case 'T': - test_readall = 1; + config->test_readall = 1; global_option_set("ReadThreads", "-1", 1); #if COLLECT_DAEMON - daemonize = 0; + config->daemonize = 0; #endif /* COLLECT_DAEMON */ break; #if COLLECT_DAEMON @@ -497,7 +492,7 @@ int main(int argc, char **argv) { global_option_set("PIDFile", optarg, 1); break; case 'f': - daemonize = 0; + config->daemonize = 0; break; #endif /* COLLECT_DAEMON */ case 'h': @@ -507,22 +502,20 @@ int main(int argc, char **argv) { exit_usage(1); } /* switch (c) */ } /* while (1) */ +} - if (optind < argc) - exit_usage(1); - - plugin_init_ctx(); - +int configure_collectd(struct cmdline_config *config) { + const char *basedir; /* * Read options from the config file, the environment and the command * line (in that order, with later options overwriting previous ones in * general). * Also, this will automatically load modules. */ - if (cf_read(configfile)) { + if (cf_read(config->configfile)) { fprintf(stderr, "Error: Reading the config file failed!\n" - "Read the syslog for details.\n"); - return (1); + "Read the logs for details.\n"); + return 1; } /* @@ -532,23 +525,47 @@ int main(int argc, char **argv) { if ((basedir = global_option_get("BaseDir")) == NULL) { fprintf(stderr, "Don't have a basedir to use. This should not happen. Ever."); - return (1); - } else if (change_basedir(basedir)) { + return 1; + } else if (change_basedir(basedir, config->create_basedir)) { fprintf(stderr, "Error: Unable to change to directory `%s'.\n", basedir); - return (1); + return 1; } /* - * Set global variables or, if that failes, exit. We cannot run with + * Set global variables or, if that fails, exit. We cannot run with * them being uninitialized. If nothing is configured, then defaults * are being used. So this means that the user has actually done * something wrong. */ if (init_global_variables() != 0) - exit(EXIT_FAILURE); + return 1; - if (test_config) - return (0); + return 0; +} + +int main(int argc, char **argv) { +#if COLLECT_DAEMON + pid_t pid; +#endif + int exit_status = 0; + + struct cmdline_config config = { + .daemonize = 1, .create_basedir = 1, .configfile = CONFIGFILE, + }; + + read_cmdline(argc, argv, &config); + + if (config.test_config) + return 0; + + if (optind < argc) + exit_usage(1); + + plugin_init_ctx(); + + int status; + if ((status = configure_collectd(&config)) != 0) + exit(EXIT_FAILURE); #if COLLECT_DAEMON /* @@ -562,7 +579,7 @@ int main(int argc, char **argv) { * Only daemonize if we're not being supervised * by upstart or systemd (when using Linux). */ - if (daemonize + if (config.daemonize #ifdef KERNEL_LINUX && notify_upstart() == 0 && notify_systemd() == 0 #endif @@ -573,11 +590,11 @@ int main(int argc, char **argv) { /* error */ char errbuf[1024]; fprintf(stderr, "fork: %s", sstrerror(errno, errbuf, sizeof(errbuf))); - return (1); + return 1; } else if (pid != 0) { /* parent */ /* printf ("Running (PID %i)\n", pid); */ - return (0); + return 0; } /* Detach from session */ @@ -596,23 +613,23 @@ int main(int argc, char **argv) { if (status != 0) { ERROR("Error: Could not connect `STDIN' to `/dev/null' (status %d)", status); - return (1); + return 1; } status = dup(0); if (status != 1) { ERROR("Error: Could not connect `STDOUT' to `/dev/null' (status %d)", status); - return (1); + return 1; } status = dup(0); if (status != 2) { ERROR("Error: Could not connect `STDERR' to `/dev/null', (status %d)", status); - return (1); + return 1; } - } /* if (daemonize) */ + } /* if (config.daemonize) */ #endif /* COLLECT_DAEMON */ struct sigaction sig_pipe_action = {.sa_handler = SIG_IGN}; @@ -628,7 +645,7 @@ int main(int argc, char **argv) { char errbuf[1024]; ERROR("Error: Failed to install a signal handler for signal INT: %s", sstrerror(errno, errbuf, sizeof(errbuf))); - return (1); + return 1; } struct sigaction sig_term_action = {.sa_handler = sig_term_handler}; @@ -637,7 +654,7 @@ int main(int argc, char **argv) { char errbuf[1024]; ERROR("Error: Failed to install a signal handler for signal TERM: %s", sstrerror(errno, errbuf, sizeof(errbuf))); - return (1); + return 1; } struct sigaction sig_usr1_action = {.sa_handler = sig_usr1_handler}; @@ -646,7 +663,7 @@ int main(int argc, char **argv) { char errbuf[1024]; ERROR("Error: Failed to install a signal handler for signal USR1: %s", sstrerror(errno, errbuf, sizeof(errbuf))); - return (1); + return 1; } /* @@ -657,7 +674,7 @@ int main(int argc, char **argv) { exit_status = 1; } - if (test_readall) { + if (config.test_readall) { if (plugin_read_all_once() != 0) { ERROR("Error: one or more plugin read callbacks failed."); exit_status = 1; @@ -676,9 +693,9 @@ int main(int argc, char **argv) { } #if COLLECT_DAEMON - if (daemonize) + if (config.daemonize) pidfile_remove(); #endif /* COLLECT_DAEMON */ - return (exit_status); + return exit_status; } /* int main */