summaryrefslogtreecommitdiffstats
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c225
1 files changed, 162 insertions, 63 deletions
diff --git a/src/main.c b/src/main.c
index 89ca828a1..b14ebc0c1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -32,24 +32,34 @@ void netdata_cleanup_and_exit(int ret) {
}
struct netdata_static_thread static_threads[] = {
+
#ifdef INTERNAL_PLUGIN_NFACCT
-// nfacct requires root access
+ // nfacct requires root access
// so, we build it as an external plugin with setuid to root
{"nfacct", CONFIG_SECTION_PLUGINS, "nfacct", 1, NULL, NULL, nfacct_main},
#endif
- {"tc", CONFIG_SECTION_PLUGINS, "tc", 1, NULL, NULL, tc_main},
- {"idlejitter", CONFIG_SECTION_PLUGINS, "idlejitter", 1, NULL, NULL, cpuidlejitter_main},
+#ifdef NETDATA_INTERNAL_CHECKS
+ // debugging plugin
+ {"check", CONFIG_SECTION_PLUGINS, "checks", 0, NULL, NULL, checks_main},
+#endif
+
#if defined(__FreeBSD__)
+ // FreeBSD internal plugins
{"freebsd", CONFIG_SECTION_PLUGINS, "freebsd", 1, NULL, NULL, freebsd_main},
#elif defined(__APPLE__)
+ // macOS internal plugins
{"macos", CONFIG_SECTION_PLUGINS, "macos", 1, NULL, NULL, macos_main},
#else
+ // linux internal plugins
{"proc", CONFIG_SECTION_PLUGINS, "proc", 1, NULL, NULL, proc_main},
{"diskspace", CONFIG_SECTION_PLUGINS, "diskspace", 1, NULL, NULL, proc_diskspace_main},
{"cgroups", CONFIG_SECTION_PLUGINS, "cgroups", 1, NULL, NULL, cgroups_main},
+ {"tc", CONFIG_SECTION_PLUGINS, "tc", 1, NULL, NULL, tc_main},
#endif /* __FreeBSD__, __APPLE__*/
- {"check", CONFIG_SECTION_PLUGINS, "checks", 0, NULL, NULL, checks_main},
+
+ // common plugins for all systems
+ {"idlejitter", CONFIG_SECTION_PLUGINS, "idlejitter", 1, NULL, NULL, cpuidlejitter_main},
{"backends", NULL, NULL, 1, NULL, NULL, backends_main},
{"health", NULL, NULL, 1, NULL, NULL, health_main},
{"plugins.d", NULL, NULL, 1, NULL, NULL, pluginsd_main},
@@ -57,6 +67,7 @@ struct netdata_static_thread static_threads[] = {
{"web-single-threaded", NULL, NULL, 0, NULL, NULL, socket_listen_main_single_threaded},
{"push-metrics", NULL, NULL, 0, NULL, NULL, rrdpush_sender_thread},
{"statsd", NULL, NULL, 1, NULL, NULL, statsd_main},
+
{NULL, NULL, NULL, 0, NULL, NULL, NULL}
};
@@ -83,6 +94,13 @@ void web_server_config_options(void) {
web_x_frame_options = config_get(CONFIG_SECTION_WEB, "x-frame-options response header", "");
if(!*web_x_frame_options) web_x_frame_options = NULL;
+ web_allow_connections_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow connections from", "localhost *"), SIMPLE_PATTERN_EXACT);
+ web_allow_dashboard_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow dashboard from", "localhost *"), SIMPLE_PATTERN_EXACT);
+ web_allow_badges_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow badges from", "*"), SIMPLE_PATTERN_EXACT);
+ web_allow_registry_from = simple_pattern_create(config_get(CONFIG_SECTION_REGISTRY, "allow from", "*"), SIMPLE_PATTERN_EXACT);
+ web_allow_streaming_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow streaming from", "*"), SIMPLE_PATTERN_EXACT);
+ web_allow_netdataconf_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow netdata.conf from", "localhost fd* 10.* 192.168.* 172.16.* 172.17.* 172.18.* 172.19.* 172.20.* 172.21.* 172.22.* 172.23.* 172.24.* 172.25.* 172.26.* 172.27.* 172.28.* 172.29.* 172.30.* 172.31.*"), SIMPLE_PATTERN_EXACT);
+
#ifdef NETDATA_WITH_ZLIB
web_enable_gzip = config_get_boolean(CONFIG_SECTION_WEB, "enable gzip compression", web_enable_gzip);
@@ -195,23 +213,8 @@ void kill_childs()
tc_child_pid = 0;
}
- struct plugind *cd;
- for(cd = pluginsd_root ; cd ; cd = cd->next) {
- if(cd->enabled && !cd->obsolete) {
- info("Stopping %s plugin thread", cd->id);
- pthread_cancel(cd->thread);
-
- if(cd->pid) {
- info("killing %s plugin child process pid %d", cd->id, cd->pid);
- if(killpid(cd->pid, SIGTERM) != -1)
- waitid(P_PID, (id_t) cd->pid, &info, WEXITED);
-
- cd->pid = 0;
- }
-
- cd->obsolete = 1;
- }
- }
+ // stop all running plugins
+ pluginsd_stop_all_external_plugins();
// if, for any reason there is any child exited
// catch it here
@@ -221,7 +224,7 @@ void kill_childs()
info("All threads/childs stopped.");
}
-struct option_def options[] = {
+struct option_def option_definitions[] = {
// opt description arg name default value
{ 'c', "Configuration file to load.", "filename", CONFIG_DIR "/" CONFIG_FILENAME},
{ 'D', "Do not fork. Run in the foreground.", NULL, "run in the background"},
@@ -237,21 +240,21 @@ struct option_def options[] = {
{ 'W', "See Advanced options below.", "options", NULL},
};
-void help(int exitcode) {
+int help(int exitcode) {
FILE *stream;
if(exitcode == 0)
stream = stdout;
else
stream = stderr;
- int num_opts = sizeof(options) / sizeof(struct option_def);
+ int num_opts = sizeof(option_definitions) / sizeof(struct option_def);
int i;
int max_len_arg = 0;
// Compute maximum argument length
for( i = 0; i < num_opts; i++ ) {
- if(options[i].arg_name) {
- int len_arg = (int)strlen(options[i].arg_name);
+ if(option_definitions[i].arg_name) {
+ int len_arg = (int)strlen(option_definitions[i].arg_name);
if(len_arg > max_len_arg) max_len_arg = len_arg;
}
}
@@ -289,9 +292,9 @@ void help(int exitcode) {
// Output options description.
for( i = 0; i < num_opts; i++ ) {
- fprintf(stream, " -%c %-*s %s", options[i].val, max_len_arg, options[i].arg_name ? options[i].arg_name : "", options[i].description);
- if(options[i].default_value) {
- fprintf(stream, "\n %c %-*s Default: %s\n", ' ', max_len_arg, "", options[i].default_value);
+ fprintf(stream, " -%c %-*s %s", option_definitions[i].val, max_len_arg, option_definitions[i].arg_name ? option_definitions[i].arg_name : "", option_definitions[i].description);
+ if(option_definitions[i].default_value) {
+ fprintf(stream, "\n %c %-*s Default: %s\n", ' ', max_len_arg, "", option_definitions[i].default_value);
} else {
fprintf(stream, "\n");
}
@@ -316,7 +319,7 @@ void help(int exitcode) {
);
fflush(stream);
- exit(exitcode);
+ return exitcode;
}
// TODO: Remove this function with the nix major release.
@@ -454,17 +457,23 @@ static void get_netdata_configured_variables() {
}
// ------------------------------------------------------------------------
- // let the plugins know the min update_every
-
// get system paths
+
netdata_configured_config_dir = config_get(CONFIG_SECTION_GLOBAL, "config directory", CONFIG_DIR);
netdata_configured_log_dir = config_get(CONFIG_SECTION_GLOBAL, "log directory", LOG_DIR);
- netdata_configured_plugins_dir = config_get(CONFIG_SECTION_GLOBAL, "plugins directory", PLUGINS_DIR);
netdata_configured_web_dir = config_get(CONFIG_SECTION_GLOBAL, "web files directory", WEB_DIR);
netdata_configured_cache_dir = config_get(CONFIG_SECTION_GLOBAL, "cache directory", CACHE_DIR);
netdata_configured_varlib_dir = config_get(CONFIG_SECTION_GLOBAL, "lib directory", VARLIB_DIR);
netdata_configured_home_dir = config_get(CONFIG_SECTION_GLOBAL, "home directory", CACHE_DIR);
+ {
+ char plugins_dirs[(FILENAME_MAX * 2) + 1];
+ snprintfz(plugins_dirs, FILENAME_MAX * 2, "\"%s\" \"%s/custom-plugins.d\"", PLUGINS_DIR, CONFIG_DIR);
+ netdata_configured_plugins_dir_base = strdupz(config_get(CONFIG_SECTION_GLOBAL, "plugins directory", plugins_dirs));
+ quoted_strings_splitter(netdata_configured_plugins_dir_base, plugin_directories, PLUGINSD_MAX_DIRECTORIES, config_isspace);
+ netdata_configured_plugins_dir = plugin_directories[0];
+ }
+
// ------------------------------------------------------------------------
// get default memory mode for the database
@@ -489,6 +498,95 @@ static void get_netdata_configured_variables() {
get_system_pid_max();
}
+static void get_system_timezone(void) {
+ // avoid flood calls to stat(/etc/localtime)
+ // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux
+ const char *tz = getenv("TZ");
+ if(!tz || !*tz)
+ setenv("TZ", config_get(CONFIG_SECTION_GLOBAL, "TZ environment variable", ":/etc/localtime"), 0);
+
+ char buffer[FILENAME_MAX + 1] = "";
+ const char *timezone = NULL;
+ ssize_t ret;
+
+ // use the TZ variable
+ if(tz && *tz && *tz != ':') {
+ timezone = tz;
+ // info("TIMEZONE: using TZ variable '%s'", timezone);
+ }
+
+ // use the contents of /etc/timezone
+ if(!timezone && !read_file("/etc/timezone", buffer, FILENAME_MAX)) {
+ timezone = buffer;
+ // info("TIMEZONE: using the contents of /etc/timezone: '%s'", timezone);
+ }
+
+ // read the link /etc/localtime
+ if(!timezone) {
+ ret = readlink("/etc/localtime", buffer, FILENAME_MAX);
+
+ if(ret > 0) {
+ buffer[ret] = '\0';
+
+ char *cmp = "/usr/share/zoneinfo/";
+ size_t cmp_len = strlen(cmp);
+
+ char *s = strstr(buffer, cmp);
+ if (s && s[cmp_len]) {
+ timezone = &s[cmp_len];
+ // info("TIMEZONE: using the link of /etc/localtime: '%s'", timezone);
+ }
+ }
+ else
+ buffer[0] = '\0';
+ }
+
+ // find the timezone from strftime()
+ if(!timezone) {
+ time_t t;
+ struct tm *tmp, tmbuf;
+
+ t = now_realtime_sec();
+ tmp = localtime_r(&t, &tmbuf);
+
+ if (tmp != NULL) {
+ if(strftime(buffer, FILENAME_MAX, "%Z", tmp) == 0)
+ buffer[0] = '\0';
+ else {
+ buffer[FILENAME_MAX] = '\0';
+ timezone = buffer;
+ // info("TIMEZONE: using strftime(): '%s'", timezone);
+ }
+ }
+ }
+
+ if(timezone && *timezone) {
+ // make sure it does not have illegal characters
+ // info("TIMEZONE: fixing '%s'", timezone);
+
+ size_t len = strlen(timezone);
+ char tmp[len + 1];
+ char *d = tmp;
+ *d = '\0';
+
+ while(*timezone) {
+ if(isalnum(*timezone) || *timezone == '_' || *timezone == '/')
+ *d++ = *timezone++;
+ else
+ timezone++;
+ }
+ *d = '\0';
+ strncpyz(buffer, tmp, len);
+ timezone = buffer;
+ // info("TIMEZONE: fixed as '%s'", timezone);
+ }
+
+ if(!timezone || !*timezone)
+ timezone = "unknown";
+
+ netdata_configured_timezone = config_get(CONFIG_SECTION_GLOBAL, "timezone", timezone);
+}
+
void set_global_environment() {
{
char b[16];
@@ -506,11 +604,7 @@ void set_global_environment() {
setenv("HOME" , verify_required_directory(netdata_configured_home_dir), 1);
setenv("NETDATA_HOST_PREFIX", netdata_configured_host_prefix, 1);
- // avoid flood calls to stat(/etc/localtime)
- // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux
- const char *tz = getenv("TZ");
- if(!tz || !*tz)
- setenv("TZ", config_get(CONFIG_SECTION_GLOBAL, "TZ environment variable", ":/etc/localtime"), 0);
+ get_system_timezone();
// set the path we need
char path[1024 + 1], *p = getenv("PATH");
@@ -571,14 +665,14 @@ int main(int argc, char **argv) {
// parse options
{
- int num_opts = sizeof(options) / sizeof(struct option_def);
+ int num_opts = sizeof(option_definitions) / sizeof(struct option_def);
char optstring[(num_opts * 2) + 1];
int string_i = 0;
for( i = 0; i < num_opts; i++ ) {
- optstring[string_i] = options[i].val;
+ optstring[string_i] = option_definitions[i].val;
string_i++;
- if(options[i].arg_name) {
+ if(option_definitions[i].arg_name) {
optstring[string_i] = ':';
string_i++;
}
@@ -593,7 +687,7 @@ int main(int argc, char **argv) {
case 'c':
if(config_load(optarg, 1) != 1) {
error("Cannot load configuration file %s.", optarg);
- exit(1);
+ return 1;
}
else {
debug(D_OPTIONS, "Configuration loaded from %s.", optarg);
@@ -604,8 +698,7 @@ int main(int argc, char **argv) {
dont_fork = 1;
break;
case 'h':
- help(0);
- break;
+ return help(0);
case 'i':
config_set(CONFIG_SECTION_WEB, "bind to", optarg);
break;
@@ -635,8 +728,8 @@ int main(int argc, char **argv) {
char* debug_flags_string = "debug_flags=";
if(strcmp(optarg, "unittest") == 0) {
- if(unit_test_buffer()) exit(1);
- if(unit_test_str2ld()) exit(1);
+ if(unit_test_buffer()) return 1;
+ if(unit_test_str2ld()) return 1;
//default_rrd_update_every = 1;
//default_rrd_memory_mode = RRD_MEMORY_MODE_RAM;
//if(!config_loaded) config_load(NULL, 0);
@@ -646,10 +739,10 @@ int main(int argc, char **argv) {
default_health_enabled = 0;
rrd_init("unittest");
default_rrdpush_enabled = 0;
- if(run_all_mockup_tests()) exit(1);
- if(unit_test_storage()) exit(1);
+ if(run_all_mockup_tests()) return 1;
+ if(unit_test_storage()) return 1;
fprintf(stderr, "\n\nALL TESTS PASSED\n\n");
- exit(0);
+ return 0;
}
else if(strcmp(optarg, "simple-pattern") == 0) {
if(optind + 2 > argc) {
@@ -673,24 +766,25 @@ int main(int argc, char **argv) {
" -W simple-pattern '!/path/*/*.ext /path/*.ext' '/path/test.ext'\n"
"\n"
);
- exit(1);
+ return 1;
}
const char *heystack = argv[optind];
const char *needle = argv[optind + 1];
+ size_t len = strlen(needle) + 1;
+ char wildcarded[len];
- SIMPLE_PATTERN *p = simple_pattern_create(heystack
- , SIMPLE_PATTERN_EXACT);
- int ret = simple_pattern_matches(p, needle);
+ SIMPLE_PATTERN *p = simple_pattern_create(heystack, SIMPLE_PATTERN_EXACT);
+ int ret = simple_pattern_matches_extract(p, needle, wildcarded, len);
simple_pattern_free(p);
if(ret) {
- fprintf(stdout, "RESULT: MATCHED - pattern '%s' matches '%s'\n", heystack, needle);
- exit(0);
+ fprintf(stdout, "RESULT: MATCHED - pattern '%s' matches '%s', wildcarded '%s'\n", heystack, needle, wildcarded);
+ return 0;
}
else {
- fprintf(stdout, "RESULT: NOT MATCHED - pattern '%s' does not match '%s'\n", heystack, needle);
- exit(1);
+ fprintf(stdout, "RESULT: NOT MATCHED - pattern '%s' does not match '%s', wildcarded '%s'\n", heystack, needle, wildcarded);
+ return 1;
}
}
else if(strncmp(optarg, stacksize_string, strlen(stacksize_string)) == 0) {
@@ -716,7 +810,7 @@ int main(int argc, char **argv) {
" parameters."
"\n"
);
- exit(1);
+ return 1;
}
const char *section = argv[optind];
const char *key = argv[optind + 1];
@@ -741,7 +835,7 @@ int main(int argc, char **argv) {
" -c netdata.conf has to be given before -W get.\n"
"\n"
);
- exit(1);
+ return 1;
}
if(!config_loaded) {
@@ -757,18 +851,18 @@ int main(int argc, char **argv) {
const char *def = argv[optind + 2];
const char *value = config_get(section, key, def);
printf("%s\n", value);
- exit(0);
+ return 0;
}
else {
fprintf(stderr, "Unknown -W parameter '%s'\n", optarg);
- help(1);
+ return help(1);
}
}
break;
+
default: /* ? */
fprintf(stderr, "Unknown parameter '%c'\n", opt);
- help(1);
- break;
+ return help(1);
}
}
}
@@ -906,6 +1000,7 @@ int main(int argc, char **argv) {
// --------------------------------------------------------------------
// create the listening sockets
+ web_client_api_v1_init();
web_server_threading_selection();
if(web_server_mode != WEB_SERVER_MODE_NONE)
@@ -997,4 +1092,8 @@ int main(int argc, char **argv) {
// Handle signals
signals_handle();
+
+ // should never reach this point
+ // but we need it for rpmlint #2752
+ return 1;
}