Esempio n. 1
0
static int
process_global_set(struct archive_read *a,
    struct mtree_option **global, const char *line)
{
	const char *next, *eq;
	size_t len;
	int r;

	line += 4;
	for (;;) {
		next = line + strspn(line, " \t\r\n");
		if (*next == '\0')
			return (ARCHIVE_OK);
		line = next;
		next = line + strcspn(line, " \t\r\n");
		eq = strchr(line, '=');
		if (eq > next)
			len = next - line;
		else
			len = eq - line;

		remove_option(global, line, len);
		r = add_option(a, global, line, next - line);
		if (r != ARCHIVE_OK)
			return (r);
		line = next;
	}
}
Esempio n. 2
0
static int
process_global_unset(struct archive_read *a,
    struct mtree_option **global, const char *line)
{
	const char *next;
	size_t len;

	line += 6;
	if (strchr(line, '=') != NULL) {
		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
		    "/unset shall not contain `='");
		return ARCHIVE_FATAL;
	}

	for (;;) {
		next = line + strspn(line, " \t\r\n");
		if (*next == '\0')
			return (ARCHIVE_OK);
		line = next;
		len = strcspn(line, " \t\r\n");

		if (len == 3 && strncmp(line, "all", 3) == 0) {
			free_options(*global);
			*global = NULL;
		} else {
			remove_option(global, line, len);
		}

		line += len;
	}
}
Esempio n. 3
0
File: pppoe.c Progetto: OPSF/uClinux
//int (*old_setdevname_hook)(char* cp) = NULL;
int setdevname_pppoe(char *cp)
{
    int ret;
    char dev[IFNAMSIZ+1];
    int addr[ETH_ALEN];
    int sid;

    char **a;
    ret =sscanf(cp, FMTSTRING(IFNAMSIZ),addr, addr+1, addr+2,
		addr+3, addr+4, addr+5,&sid,dev);
    if( ret != 8 ){

	ret = get_sockaddr_ll(cp,NULL,0);
        if (ret < 0)
	    fatal("PPPoE: Cannot create PF_PACKET socket for PPPoE discovery\n");
	/* not a device name */
	if (ret == 0)
	    return 0;
	if (ret == 1)
	    strncpy(devnam, cp, sizeof(devnam));
    }else{
	/* long form parsed */
	ret = get_sockaddr_ll(dev,NULL,0);
        if (ret < 0)
	    fatal("PPPoE: Cannot create PF_PACKET socket for PPPoE discovery\n");

	strncpy(devnam, cp, sizeof(devnam));
	ret = 1;
    }



    for (a = bad_options; *a != NULL; a++)
		remove_option(*a);
    deprecate_options(deprecated_options);
	modem = 0;

	lcp_allowoptions[0].neg_accompression = 0;
	lcp_wantoptions[0].neg_accompression = 0;

	lcp_allowoptions[0].neg_asyncmap = 0;
	lcp_wantoptions[0].neg_asyncmap = 0;

	lcp_allowoptions[0].neg_pcompression = 0;
	lcp_wantoptions[0].neg_pcompression = 0;

	ccp_allowoptions[0].deflate = 0 ;
	ccp_wantoptions[0].deflate = 0 ;

	ipcp_allowoptions[0].neg_vj=0;
	ipcp_wantoptions[0].neg_vj=0;

	ccp_allowoptions[0].bsd_compress = 0;
	ccp_wantoptions[0].bsd_compress = 0;

	init_device_pppoe();

    return ret;
}
//
//
//
/// @brief The @c std::string key found before the given @c option in the config
///        file. Otherwise, return the given @c default_preference. The search
///        pattern @c "option = key".
//
/// @return A string pattern.
//
std::string settings::scan_config_file(const std::string &option,
									   const std::string &default_key)
{
//
/// @note This member function reads the entire config file looking for the pattern
///       @c "option = key". It ignores the existence of blank space by removing
///       them. In the other hand, it is case sensitive (since it is also used to
///       read paths).
//
/// @bug Since this is an overloaded function, the compiler needs to know the proper version
///      of the function to call (through the second input argument). The type promotion did
///      also by the compiler may or may not induce it to call the wrong one. The only known
///      case so far is for the @c std::string type: When the @c std::string @c default_key
///      argument is given in terms of quote symbols, @c " ", i.e. @c const @c char*, the
///      compiler can convert it to @c int type (@c char, @c size_t, and @c bool may bahave
///      as @c int). Due to that, the function called will be the @c int type one. To avoid
///      this problem, when the second input argument is given by means of quote symbols, it
///      is highly recomended to specify its type. The layout call should looks like @c
///      "scan_config_file(option, (std::string) my_default_input_key)";.
//
	std::ifstream file(config_file.std::string::c_str(), std::ios::in);
	switch(file.std::ifstream::is_open() and file.std::ifstream::good())
	{
		case false:
		{
			return default_key;
		}
		break;
		case true:
		{
			std::string line = "";
			while(getline(file, line))
			{
				switch(tools::comment_line(line))
				{
					case false:
					tools::remove_blank_spaces(line);
					switch(tools::is_equal(option, line))
					{
						case true:
						remove_option(line, option);
						return line;
						break;
					}
					break;
				}
			}
			file.std::ifstream::close();
			return default_key;
		}
		break;
	}
}
Esempio n. 5
0
int setdevname_pppoatm(const char *cp)
{
	struct sockaddr_atmpvc addr;
	extern struct stat devstat;
	
	memset(&addr, 0, sizeof addr);
	if (text2atm(cp, (struct sockaddr *) &addr, sizeof(addr),
	    T2A_PVC | T2A_NAME) < 0)
		return 0;

	memcpy(&glb.pvcaddr, &addr, sizeof glb.pvcaddr);
	strlcpy(devnam, cp, sizeof devnam);
	
	info("PPPoATM setdevname_pppoatm - SUCCESS");
	if(the_channel != &pppoatm_channel) {
		the_channel = &pppoatm_channel;	
		
		{
			char **a;
			for (a = bad_options; *a != NULL; a++)
				remove_option(*a);
		}
#ifndef _DISABLE_SERIAL_
		modem = 0;
#endif

		lcp_allowoptions[0].neg_accompression = 0;
		lcp_wantoptions[0].neg_accompression = 0;

		lcp_allowoptions[0].neg_asyncmap = 0;
		lcp_wantoptions[0].neg_asyncmap = 0;

		lcp_allowoptions[0].neg_pcompression = 0;
		lcp_wantoptions[0].neg_pcompression = 0;

		ccp_allowoptions[0].deflate = 0 ;
		ccp_wantoptions[0].deflate = 0 ;

		ipcp_allowoptions[0].neg_vj=0;
		ipcp_wantoptions[0].neg_vj=0;

		ccp_allowoptions[0].bsd_compress = 0;
		ccp_wantoptions[0].bsd_compress = 0;
	}
	return 1;
}
//
//
//
/// @brief The @c double key found before the given @c option in the config file.
///        Otherwise, return the given @c default_preference. The search pattern
///        @c "option = key".
//
/// @return A real number.
//
double settings::scan_config_file(const std::string &option,
								  const double &default_key)
{
//
/// @note This member function reads the entire config file looking for the pattern
///       @c "option = key". It ignores the existence of blank space by removing
///       them. In the other hand, it is case sensitive (since it is also used to
///       read paths).
//
	std::ifstream file(config_file.std::string::c_str(), std::ios::in);
	switch(file.std::ifstream::is_open() and file.std::ifstream::good())
	{
		case false:
		{
			return default_key;
		}
		break;
		case true:
		{
			std::string line = "";
			while(getline(file, line))
			{
				switch(tools::comment_line(line))
				{
					case false:
					tools::remove_blank_spaces(line);
					switch(tools::is_equal(option, line))
					{
						case true:
						remove_option(line, option);
						return tools::convert<double>(line);
						break;
					}
					break;
				}
			}
			file.std::ifstream::close();
			return default_key;
		}
		break;
	}
}
Esempio n. 7
0
int main(int argc, char **argv)
{
	int i;
	int config_loaded = 0;
	int dont_fork = 0;
	size_t wanted_stacksize = 0, stacksize = 0;
	pthread_attr_t attr;

	// global initialization
	get_HZ();

	// set the name for logging
	program_name = "netdata";

	// parse command line.

	// parse depercated options
	// TODO: Remove this block with the next major release.
	{
		i = 1;
		while(i < argc) {
			if(strcmp(argv[i], "-pidfile") == 0 && (i+1) < argc) {
				strncpyz(pidfile, argv[i+1], FILENAME_MAX);
				fprintf(stderr, "%s: deprecated option -- %s -- please use -P instead.\n", argv[0], argv[i]);
				remove_option(i, &argc, argv);
			}
			else if(strcmp(argv[i], "-nodaemon") == 0 || strcmp(argv[i], "-nd") == 0) {
				dont_fork = 1;
				fprintf(stderr, "%s: deprecated option -- %s -- please use -D instead.\n ", argv[0], argv[i]);
				remove_option(i, &argc, argv);
			}
			else if(strcmp(argv[i], "-ch") == 0 && (i+1) < argc) {
				config_set("global", "host access prefix", argv[i+1]);
				fprintf(stderr, "%s: deprecated option -- %s -- please use -s instead.\n", argv[0], argv[i]);
				remove_option(i, &argc, argv);
			}
			else if(strcmp(argv[i], "-l") == 0 && (i+1) < argc) {
				config_set("global", "history", argv[i+1]);
				fprintf(stderr, "%s: deprecated option -- %s -- This option will be removed with V2.*.\n", argv[0], argv[i]);
				remove_option(i, &argc, argv);
			}
			else i++;
		}
	}

	// parse options
	{
		int num_opts = sizeof(options) / 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;
			string_i++;
			if(options[i].arg_name) {
				optstring[string_i] = ':';
				string_i++;
			}
		}

		int opt;
		while( (opt = getopt(argc, argv, optstring)) != -1 ) {
			switch(opt) {
				case 'c':
					if(load_config(optarg, 1) != 1) {
						error("Cannot load configuration file %s.", optarg);
						exit(1);
					}
					else {
						debug(D_OPTIONS, "Configuration loaded from %s.", optarg);
						config_loaded = 1;
					}
					break;
				case 'D':
					dont_fork = 1;
					break;
				case 'h':
					help(0);
					break;
				case 'i':
					config_set("global", "bind to", optarg);
					break;
				case 'P':
					strncpy(pidfile, optarg, FILENAME_MAX);
					pidfile[FILENAME_MAX] = '\0';
					break;
				case 'p':
					config_set("global", "default port", optarg);
					break;
				case 's':
					config_set("global", "host access prefix", optarg);
					break;
				case 't':
					config_set("global", "update every", optarg);
					break;
				case 'u':
					config_set("global", "run as user", optarg);
					break;
				case 'v':
					// TODO: Outsource version to makefile which can compute version from git.
					printf("netdata 1.2.1_master\n");
					return 0;
					break;
				case 'W':
					{
						char* stacksize = "stacksize=";
						char* debug_flags_string = "debug_flags=";
						if(strcmp(optarg, "unittest") == 0) {
							rrd_update_every = 1;
							if(run_all_mockup_tests()) exit(1);
							if(unit_test_storage()) exit(1);
							fprintf(stderr, "\n\nALL TESTS PASSED\n\n");
							exit(0);
						} else if(strncmp(optarg, stacksize, strlen(stacksize)) == 0) {
							optarg += strlen(stacksize);
							config_set("global", "pthread stack size", optarg);
						} else if(strncmp(optarg, debug_flags_string, strlen(debug_flags_string)) == 0) {
							optarg += strlen(debug_flags_string);
							config_set("global", "debug flags",  optarg);
							debug_flags = strtoull(optarg, NULL, 0);
						}
					}
					break;
				default: /* ? */
					help(1);
					break;
			}
		}
	}

	if(!config_loaded) load_config(NULL, 0);

	// prepare configuration environment variables for the plugins
	setenv("NETDATA_CONFIG_DIR" , config_get("global", "config directory"   , CONFIG_DIR) , 1);
	setenv("NETDATA_PLUGINS_DIR", config_get("global", "plugins directory"  , PLUGINS_DIR), 1);
	setenv("NETDATA_WEB_DIR"    , config_get("global", "web files directory", WEB_DIR)    , 1);
	setenv("NETDATA_CACHE_DIR"  , config_get("global", "cache directory"    , CACHE_DIR)  , 1);
	setenv("NETDATA_LIB_DIR"    , config_get("global", "lib directory"      , VARLIB_DIR) , 1);
	setenv("NETDATA_LOG_DIR"    , config_get("global", "log directory"      , LOG_DIR)    , 1);
	setenv("NETDATA_HOST_PREFIX", config_get("global", "host access prefix" , "")         , 1);
	setenv("HOME"               , config_get("global", "home directory"     , CACHE_DIR)  , 1);

	// disable buffering for python plugins
	setenv("PYTHONUNBUFFERED", "1", 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
	setenv("TZ", ":/etc/localtime", 0);

	{
		char path[1024 + 1], *p = getenv("PATH");
		if(!p) p = "/bin:/usr/bin";
		snprintfz(path, 1024, "%s:%s", p, "/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin");
		setenv("PATH", config_get("plugins", "PATH environment variable", path), 1);
	}

	// cd to /tmp to avoid any plugins writing files at random places
	if(chdir("/tmp")) error("netdata: ERROR: Cannot cd to /tmp");

	char *input_log_file = NULL;
	char *output_log_file = NULL;
	char *error_log_file = NULL;
	char *access_log_file = NULL;
	char *user = NULL;
	{
		char *flags = config_get("global", "debug flags",  "0x00000000");
		setenv("NETDATA_DEBUG_FLAGS", flags, 1);

		debug_flags = strtoull(flags, NULL, 0);
		debug(D_OPTIONS, "Debug flags set to '0x%8llx'.", debug_flags);

		if(debug_flags != 0) {
			struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
			if(setrlimit(RLIMIT_CORE, &rl) != 0)
				info("Cannot request unlimited core dumps for debugging... Proceeding anyway...");
			prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
		}

		// --------------------------------------------------------------------

#ifdef MADV_MERGEABLE
		enable_ksm = config_get_boolean("global", "memory deduplication (ksm)", enable_ksm);
#else
#warning "Kernel memory deduplication (KSM) is not available"
#endif

		// --------------------------------------------------------------------


		global_host_prefix = config_get("global", "host access prefix", "");
		setenv("NETDATA_HOST_PREFIX", global_host_prefix, 1);

		// --------------------------------------------------------------------

		output_log_file = config_get("global", "debug log", LOG_DIR "/debug.log");
		if(strcmp(output_log_file, "syslog") == 0) {
			output_log_syslog = 1;
			output_log_file = NULL;
		}
		else if(strcmp(output_log_file, "none") == 0) {
			output_log_syslog = 0;
			output_log_file = NULL;
		}
		else output_log_syslog = 0;

		// --------------------------------------------------------------------

		error_log_file = config_get("global", "error log", LOG_DIR "/error.log");
		if(strcmp(error_log_file, "syslog") == 0) {
			error_log_syslog = 1;
			error_log_file = NULL;
		}
		else if(strcmp(error_log_file, "none") == 0) {
			error_log_syslog = 0;
			error_log_file = NULL;
			// optimization - do not even generate debug log entries
		}
		else error_log_syslog = 0;

		error_log_throttle_period = config_get_number("global", "errors flood protection period", error_log_throttle_period);
		setenv("NETDATA_ERRORS_THROTTLE_PERIOD", config_get("global", "errors flood protection period"    , ""), 1);

		error_log_errors_per_period = (unsigned long)config_get_number("global", "errors to trigger flood protection", error_log_errors_per_period);
		setenv("NETDATA_ERRORS_PER_PERIOD"     , config_get("global", "errors to trigger flood protection", ""), 1);

		// --------------------------------------------------------------------

		access_log_file = config_get("global", "access log", LOG_DIR "/access.log");
		if(strcmp(access_log_file, "syslog") == 0) {
			access_log_syslog = 1;
			access_log_file = NULL;
		}
		else if(strcmp(access_log_file, "none") == 0) {
			access_log_syslog = 0;
			access_log_file = NULL;
		}
		else access_log_syslog = 0;

		// --------------------------------------------------------------------

		rrd_memory_mode = rrd_memory_mode_id(config_get("global", "memory mode", rrd_memory_mode_name(rrd_memory_mode)));

		// --------------------------------------------------------------------

		{
			char hostnamebuf[HOSTNAME_MAX + 1];
			if(gethostname(hostnamebuf, HOSTNAME_MAX) == -1)
				error("WARNING: Cannot get machine hostname.");
			hostname = config_get("global", "hostname", hostnamebuf);
			debug(D_OPTIONS, "hostname set to '%s'", hostname);
		}

		// --------------------------------------------------------------------

		rrd_default_history_entries = (int) config_get_number("global", "history", RRD_DEFAULT_HISTORY_ENTRIES);
		if(rrd_default_history_entries < 5 || rrd_default_history_entries > RRD_HISTORY_ENTRIES_MAX) {
			info("Invalid save lines %d given. Defaulting to %d.", rrd_default_history_entries, RRD_DEFAULT_HISTORY_ENTRIES);
			rrd_default_history_entries = RRD_DEFAULT_HISTORY_ENTRIES;
		}
		else {
			debug(D_OPTIONS, "save lines set to %d.", rrd_default_history_entries);
		}

		// --------------------------------------------------------------------

		rrd_update_every = (int) config_get_number("global", "update every", UPDATE_EVERY);
		if(rrd_update_every < 1 || rrd_update_every > 600) {
			info("Invalid update timer %d given. Defaulting to %d.", rrd_update_every, UPDATE_EVERY_MAX);
			rrd_update_every = UPDATE_EVERY;
		}
		else debug(D_OPTIONS, "update timer set to %d.", rrd_update_every);

		// let the plugins know the min update_every
		{
			char buf[16];
			snprintfz(buf, 15, "%d", rrd_update_every);
			setenv("NETDATA_UPDATE_EVERY", buf, 1);
		}

		// --------------------------------------------------------------------

		// block signals while initializing threads.
		// this causes the threads to block signals.
		sigset_t sigset;
		sigfillset(&sigset);

		if(pthread_sigmask(SIG_BLOCK, &sigset, NULL) == -1) {
			error("Could not block signals for threads");
		}

		// Catch signals which we want to use to quit savely
		struct sigaction sa;
		sigemptyset(&sa.sa_mask);
		sigaddset(&sa.sa_mask, SIGHUP);
		sigaddset(&sa.sa_mask, SIGINT);
		sigaddset(&sa.sa_mask, SIGTERM);
		sa.sa_handler = sig_handler_exit;
		sa.sa_flags = 0;
		if(sigaction(SIGHUP, &sa, NULL) == -1) {
			error("Failed to change signal handler for SIGHUP");
		}
		if(sigaction(SIGINT, &sa, NULL) == -1) {
			error("Failed to change signal handler for SIGINT");
		}
		if(sigaction(SIGTERM, &sa, NULL) == -1) {
			error("Failed to change signal handler for SIGTERM");
		}

		// save database on SIGUSR1
		sa.sa_handler = sig_handler_save;
		if(sigaction(SIGUSR1, &sa, NULL) == -1) {
			error("Failed to change signal handler for SIGUSR1");
		}

		// Ignore SIGPIPE completely.
		// INFO: If we add signals here we have to unblock them
		// at popen.c when running a external plugin.
		sa.sa_handler = SIG_IGN;
		if(sigaction(SIGPIPE, &sa, NULL) == -1) {
			error("Failed to change signal handler for SIGPIPE");
		}

		// --------------------------------------------------------------------

		i = pthread_attr_init(&attr);
		if(i != 0)
			fatal("pthread_attr_init() failed with code %d.", i);

		i = pthread_attr_getstacksize(&attr, &stacksize);
		if(i != 0)
			fatal("pthread_attr_getstacksize() failed with code %d.", i);
		else
			debug(D_OPTIONS, "initial pthread stack size is %zu bytes", stacksize);

		wanted_stacksize = config_get_number("global", "pthread stack size", stacksize);

		// --------------------------------------------------------------------

		for (i = 0; static_threads[i].name != NULL ; i++) {
			struct netdata_static_thread *st = &static_threads[i];

			if(st->config_name) st->enabled = config_get_boolean(st->config_section, st->config_name, st->enabled);
			if(st->enabled && st->init_routine) st->init_routine();
		}

		// --------------------------------------------------------------------

		// get the user we should run
		// IMPORTANT: this is required before web_files_uid()
		user = config_get("global", "run as user"    , (getuid() == 0)?NETDATA_USER:"");

		// IMPORTANT: these have to run once, while single threaded
		web_files_uid(); // IMPORTANT: web_files_uid() before web_files_gid()
		web_files_gid();

		// --------------------------------------------------------------------

		create_listen_sockets();
	}

	// never become a problem
	if(nice(20) == -1) error("Cannot lower my CPU priority.");

	if(become_daemon(dont_fork, 0, user, input_log_file, output_log_file, error_log_file, access_log_file, &access_fd, &stdaccess) == -1)
		fatal("Cannot demonize myself.");

#ifdef NETDATA_INTERNAL_CHECKS
	if(debug_flags != 0) {
		struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
		if(setrlimit(RLIMIT_CORE, &rl) != 0)
			info("Cannot request unlimited core dumps for debugging... Proceeding anyway...");
		prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
	}
#endif /* NETDATA_INTERNAL_CHECKS */

	if(output_log_syslog || error_log_syslog || access_log_syslog)
		openlog("netdata", LOG_PID, LOG_DAEMON);

	info("NetData started on pid %d", getpid());


	// ------------------------------------------------------------------------
	// get default pthread stack size

	if(stacksize < wanted_stacksize) {
		i = pthread_attr_setstacksize(&attr, wanted_stacksize);
		if(i != 0)
			fatal("pthread_attr_setstacksize() to %zu bytes, failed with code %d.", wanted_stacksize, i);
		else
			info("Successfully set pthread stacksize to %zu bytes", wanted_stacksize);
	}

	// --------------------------------------------------------------------
	// initialize the registry

	registry_init();

	// ------------------------------------------------------------------------
	// spawn the threads

	web_server_threading_selection();

	for (i = 0; static_threads[i].name != NULL ; i++) {
		struct netdata_static_thread *st = &static_threads[i];

		if(st->enabled) {
			st->thread = malloc(sizeof(pthread_t));
			if(!st->thread)
				fatal("Cannot allocate pthread_t memory");

			info("Starting thread %s.", st->name);

			if(pthread_create(st->thread, &attr, st->start_routine, NULL))
				error("failed to create new thread for %s.", st->name);

			else if(pthread_detach(*st->thread))
				error("Cannot request detach of newly created %s thread.", st->name);
		}
		else info("Not starting thread %s.", st->name);
	}

	// ------------------------------------------------------------------------
	// block signals while initializing threads.
	sigset_t sigset;
	sigfillset(&sigset);

	if(pthread_sigmask(SIG_UNBLOCK, &sigset, NULL) == -1) {
		error("Could not unblock signals for threads");
	}

	// Handle flags set in the signal handler.
	while(1) {
		pause();
		if(netdata_exit) {
			info("Exit main loop of netdata.");
			netdata_cleanup_and_exit(0);
			exit(0);
		}
	}
}
Esempio n. 8
0
int main(int argc, char **argv) {
    int i;
    int config_loaded = 0;
    int dont_fork = 0;
    size_t default_stacksize;

    // set the name for logging
    program_name = "netdata";

    // parse depercated options
    // TODO: Remove this block with the next major release.
    {
        i = 1;
        while(i < argc) {
            if(strcmp(argv[i], "-pidfile") == 0 && (i+1) < argc) {
                strncpyz(pidfile, argv[i+1], FILENAME_MAX);
                fprintf(stderr, "%s: deprecated option -- %s -- please use -P instead.\n", argv[0], argv[i]);
                remove_option(i, &argc, argv);
            }
            else if(strcmp(argv[i], "-nodaemon") == 0 || strcmp(argv[i], "-nd") == 0) {
                dont_fork = 1;
                fprintf(stderr, "%s: deprecated option -- %s -- please use -D instead.\n ", argv[0], argv[i]);
                remove_option(i, &argc, argv);
            }
            else if(strcmp(argv[i], "-ch") == 0 && (i+1) < argc) {
                config_set(CONFIG_SECTION_GLOBAL, "host access prefix", argv[i+1]);
                fprintf(stderr, "%s: deprecated option -- %s -- please use -s instead.\n", argv[0], argv[i]);
                remove_option(i, &argc, argv);
            }
            else if(strcmp(argv[i], "-l") == 0 && (i+1) < argc) {
                config_set(CONFIG_SECTION_GLOBAL, "history", argv[i+1]);
                fprintf(stderr, "%s: deprecated option -- %s -- This option will be removed with V2.*.\n", argv[0], argv[i]);
                remove_option(i, &argc, argv);
            }
            else i++;
        }
    }

    // parse options
    {
        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] = option_definitions[i].val;
            string_i++;
            if(option_definitions[i].arg_name) {
                optstring[string_i] = ':';
                string_i++;
            }
        }
        // terminate optstring
        optstring[string_i] ='\0';
        optstring[(num_opts *2)] ='\0';

        int opt;
        while( (opt = getopt(argc, argv, optstring)) != -1 ) {
            switch(opt) {
                case 'c':
                    if(config_load(optarg, 1) != 1) {
                        error("Cannot load configuration file %s.", optarg);
                        return 1;
                    }
                    else {
                        debug(D_OPTIONS, "Configuration loaded from %s.", optarg);
                        config_loaded = 1;
                    }
                    break;
                case 'D':
                    dont_fork = 1;
                    break;
                case 'h':
                    return help(0);
                case 'i':
                    config_set(CONFIG_SECTION_WEB, "bind to", optarg);
                    break;
                case 'P':
                    strncpy(pidfile, optarg, FILENAME_MAX);
                    pidfile[FILENAME_MAX] = '\0';
                    break;
                case 'p':
                    config_set(CONFIG_SECTION_GLOBAL, "default port", optarg);
                    break;
                case 's':
                    config_set(CONFIG_SECTION_GLOBAL, "host access prefix", optarg);
                    break;
                case 't':
                    config_set(CONFIG_SECTION_GLOBAL, "update every", optarg);
                    break;
                case 'u':
                    config_set(CONFIG_SECTION_GLOBAL, "run as user", optarg);
                    break;
                case 'v':
                case 'V':
                    printf("%s %s\n", program_name, program_version);
                    return 0;
                case 'W':
                    {
                        char* stacksize_string = "stacksize=";
                        char* debug_flags_string = "debug_flags=";

                        if(strcmp(optarg, "unittest") == 0) {
                            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);
                            get_netdata_configured_variables();
                            default_rrd_update_every = 1;
                            default_rrd_memory_mode = RRD_MEMORY_MODE_RAM;
                            default_health_enabled = 0;
                            rrd_init("unittest");
                            default_rrdpush_enabled = 0;
                            if(run_all_mockup_tests()) return 1;
                            if(unit_test_storage()) return 1;
                            fprintf(stderr, "\n\nALL TESTS PASSED\n\n");
                            return 0;
                        }
                        else if(strcmp(optarg, "simple-pattern") == 0) {
                            if(optind + 2 > argc) {
                                fprintf(stderr, "%s", "\nUSAGE: -W simple-pattern 'pattern' 'string'\n\n"
                                        " Checks if 'pattern' matches the given 'string'.\n"
                                        " - 'pattern' can be one or more space separated words.\n"
                                        " - each 'word' can contain one or more asterisks.\n"
                                        " - words starting with '!' give negative matches.\n"
                                        " - words are processed left to right\n"
                                        "\n"
                                        "Examples:\n"
                                        "\n"
                                        " > match all veth interfaces, except veth0:\n"
                                        "\n"
                                        "   -W simple-pattern '!veth0 veth*' 'veth12'\n"
                                        "\n"
                                        "\n"
                                        " > match all *.ext files directly in /path/:\n"
                                        "   (this will not match *.ext files in a subdir of /path/)\n"
                                        "\n"
                                        "   -W simple-pattern '!/path/*/*.ext /path/*.ext' '/path/test.ext'\n"
                                        "\n"
                                );
                                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, NULL, 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', wildcarded '%s'\n", heystack, needle, wildcarded);
                                return 0;
                            }
                            else {
                                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) {
                            optarg += strlen(stacksize_string);
                            config_set(CONFIG_SECTION_GLOBAL, "pthread stack size", optarg);
                        }
                        else if(strncmp(optarg, debug_flags_string, strlen(debug_flags_string)) == 0) {
                            optarg += strlen(debug_flags_string);
                            config_set(CONFIG_SECTION_GLOBAL, "debug flags",  optarg);
                            debug_flags = strtoull(optarg, NULL, 0);
                        }
                        else if(strcmp(optarg, "set") == 0) {
                            if(optind + 3 > argc) {
                                fprintf(stderr, "%s", "\nUSAGE: -W set 'section' 'key' 'value'\n\n"
                                        " Overwrites settings of netdata.conf.\n"
                                        "\n"
                                        " These options interact with: -c netdata.conf\n"
                                        " If -c netdata.conf is given on the command line,\n"
                                        " before -W set... the user may overwrite command\n"
                                        " line parameters at netdata.conf\n"
                                        " If -c netdata.conf is given after (or missing)\n"
                                        " -W set... the user cannot overwrite the command line\n"
                                        " parameters."
                                        "\n"
                                );
                                return 1;
                            }
                            const char *section = argv[optind];
                            const char *key = argv[optind + 1];
                            const char *value = argv[optind + 2];
                            optind += 3;

                            // set this one as the default
                            // only if it is not already set in the config file
                            // so the caller can use -c netdata.conf before or
                            // after this parameter to prevent or allow overwriting
                            // variables at netdata.conf
                            config_set_default(section, key,  value);

                            // fprintf(stderr, "SET section '%s', key '%s', value '%s'\n", section, key, value);
                        }
                        else if(strcmp(optarg, "get") == 0) {
                            if(optind + 3 > argc) {
                                fprintf(stderr, "%s", "\nUSAGE: -W get 'section' 'key' 'value'\n\n"
                                        " Prints settings of netdata.conf.\n"
                                        "\n"
                                        " These options interact with: -c netdata.conf\n"
                                        " -c netdata.conf has to be given before -W get.\n"
                                        "\n"
                                );
                                return 1;
                            }

                            if(!config_loaded) {
                                fprintf(stderr, "warning: no configuration file has been loaded. Use -c CONFIG_FILE, before -W get. Using default config.\n");
                                config_load(NULL, 0);
                            }

                            backwards_compatible_config();
                            get_netdata_configured_variables();

                            const char *section = argv[optind];
                            const char *key = argv[optind + 1];
                            const char *def = argv[optind + 2];
                            const char *value = config_get(section, key, def);
                            printf("%s\n", value);
                            return 0;
                        }
                        else {
                            fprintf(stderr, "Unknown -W parameter '%s'\n", optarg);
                            return help(1);
                        }
                    }
                    break;

                default: /* ? */
                    fprintf(stderr, "Unknown parameter '%c'\n", opt);
                    return help(1);
            }
        }
    }

#ifdef _SC_OPEN_MAX
    // close all open file descriptors, except the standard ones
    // the caller may have left open files (lxc-attach has this issue)
    {
        int fd;
        for(fd = (int) (sysconf(_SC_OPEN_MAX) - 1); fd > 2; fd--)
            if(fd_is_valid(fd)) close(fd);
    }
#endif

    if(!config_loaded)
        config_load(NULL, 0);

    // ------------------------------------------------------------------------
    // initialize netdata
    {
        char *pmax = config_get(CONFIG_SECTION_GLOBAL, "glibc malloc arena max for plugins", "1");
        if(pmax && *pmax)
            setenv("MALLOC_ARENA_MAX", pmax, 1);

#if defined(HAVE_C_MALLOPT)
        i = (int)config_get_number(CONFIG_SECTION_GLOBAL, "glibc malloc arena max for netdata", 1);
        if(i > 0)
            mallopt(M_ARENA_MAX, 1);
#endif

        // prepare configuration environment variables for the plugins

        get_netdata_configured_variables();
        set_global_environment();

        // work while we are cd into config_dir
        // to allow the plugins refer to their config
        // files using relative filenames
        if(chdir(netdata_configured_config_dir) == -1)
            fatal("Cannot cd to '%s'", netdata_configured_config_dir);
    }

    char *user = NULL;

    {
        // --------------------------------------------------------------------
        // get the debugging flags from the configuration file

        char *flags = config_get(CONFIG_SECTION_GLOBAL, "debug flags",  "0x0000000000000000");
        setenv("NETDATA_DEBUG_FLAGS", flags, 1);

        debug_flags = strtoull(flags, NULL, 0);
        debug(D_OPTIONS, "Debug flags set to '0x%" PRIX64 "'.", debug_flags);

        if(debug_flags != 0) {
            struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
            if(setrlimit(RLIMIT_CORE, &rl) != 0)
                error("Cannot request unlimited core dumps for debugging... Proceeding anyway...");

#ifdef HAVE_SYS_PRCTL_H
            prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
#endif
        }


        // --------------------------------------------------------------------
        // get log filenames and settings

        log_init();
        error_log_limit_unlimited();


        // --------------------------------------------------------------------
        // load stream.conf
        {
            char filename[FILENAME_MAX + 1];
            snprintfz(filename, FILENAME_MAX, "%s/stream.conf", netdata_configured_config_dir);
            appconfig_load(&stream_config, filename, 0);
        }


        // --------------------------------------------------------------------
        // setup process signals

        // block signals while initializing threads.
        // this causes the threads to block signals.
        signals_block();

        // setup the signals we want to use
        signals_init();

        // setup threads configs
        default_stacksize = netdata_threads_init();


        // --------------------------------------------------------------------
        // check which threads are enabled and initialize them

        for (i = 0; static_threads[i].name != NULL ; i++) {
            struct netdata_static_thread *st = &static_threads[i];

            if(st->config_name)
                st->enabled = config_get_boolean(st->config_section, st->config_name, st->enabled);

            if(st->enabled && st->init_routine)
                st->init_routine();
        }


        // --------------------------------------------------------------------
        // get the user we should run

        // IMPORTANT: this is required before web_files_uid()
        if(getuid() == 0) {
            user = config_get(CONFIG_SECTION_GLOBAL, "run as user", NETDATA_USER);
        }
        else {
            struct passwd *passwd = getpwuid(getuid());
            user = config_get(CONFIG_SECTION_GLOBAL, "run as user", (passwd && passwd->pw_name)?passwd->pw_name:"");
        }

        // --------------------------------------------------------------------
        // create the listening sockets

        web_client_api_v1_init();
        web_server_threading_selection();

        if(web_server_mode != WEB_SERVER_MODE_NONE)
            api_listen_sockets_setup();
    }

    // initialize the log files
    open_all_log_files();

#ifdef NETDATA_INTERNAL_CHECKS
    if(debug_flags != 0) {
        struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
        if(setrlimit(RLIMIT_CORE, &rl) != 0)
            error("Cannot request unlimited core dumps for debugging... Proceeding anyway...");
#ifdef HAVE_SYS_PRCTL_H
        prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
#endif
    }
#endif /* NETDATA_INTERNAL_CHECKS */

    // get the max file limit
    if(getrlimit(RLIMIT_NOFILE, &rlimit_nofile) != 0)
        error("getrlimit(RLIMIT_NOFILE) failed");
    else
        info("resources control: allowed file descriptors: soft = %zu, max = %zu", rlimit_nofile.rlim_cur, rlimit_nofile.rlim_max);

    // fork, switch user, create pid file, set process priority
    if(become_daemon(dont_fork, user) == -1)
        fatal("Cannot daemonize myself.");

    info("netdata started on pid %d.", getpid());

    // IMPORTANT: these have to run once, while single threaded
    // but after we have switched user
    web_files_uid();
    web_files_gid();

    netdata_threads_init_after_fork((size_t)config_get_number(CONFIG_SECTION_GLOBAL, "pthread stack size", (long)default_stacksize));

    // ------------------------------------------------------------------------
    // initialize rrd, registry, health, rrdpush, etc.

    rrd_init(netdata_configured_hostname);


    // ------------------------------------------------------------------------
    // enable log flood protection

    error_log_limit_reset();


    // ------------------------------------------------------------------------
    // spawn the threads

    web_server_config_options();

    for (i = 0; static_threads[i].name != NULL ; i++) {
        struct netdata_static_thread *st = &static_threads[i];

        if(st->enabled) {
            st->thread = mallocz(sizeof(netdata_thread_t));
            debug(D_SYSTEM, "Starting thread %s.", st->name);
            netdata_thread_create(st->thread, st->name, NETDATA_THREAD_OPTION_DEFAULT, st->start_routine, st);
        }
        else debug(D_SYSTEM, "Not starting thread %s.", st->name);
    }

    info("netdata initialization completed. Enjoy real-time performance monitoring!");


    // ------------------------------------------------------------------------
    // unblock signals

    signals_unblock();

    // ------------------------------------------------------------------------
    // Handle signals

    signals_handle();

    // should never reach this point
    // but we need it for rpmlint #2752
    return 1;
}
Esempio n. 9
0
static int
process_add_entry(struct archive_read *a, struct mtree *mtree,
    struct mtree_option **global, const char *line, ssize_t line_len,
    struct mtree_entry **last_entry, int is_form_d)
{
	struct mtree_entry *entry;
	struct mtree_option *iter;
	const char *next, *eq, *name, *end;
	size_t len;
	int r;

	if ((entry = malloc(sizeof(*entry))) == NULL) {
		archive_set_error(&a->archive, errno, "Can't allocate memory");
		return (ARCHIVE_FATAL);
	}
	entry->next = NULL;
	entry->options = NULL;
	entry->name = NULL;
	entry->used = 0;
	entry->full = 0;

	/* Add this entry to list. */
	if (*last_entry == NULL)
		mtree->entries = entry;
	else
		(*last_entry)->next = entry;
	*last_entry = entry;

	if (is_form_d) {
		/*
		 * This form places the file name as last parameter.
		 */
		name = line + line_len -1;
		while (line_len > 0) {
			if (*name != '\r' && *name != '\n' &&
			    *name != '\t' && *name != ' ')
				break;
			name--;
			line_len--;
		}
		len = 0;
		while (line_len > 0) {
			if (*name == '\r' || *name == '\n' ||
			    *name == '\t' || *name == ' ') {
				name++;
				break;
			}
			name--;
			line_len--;
			len++;
		}
		end = name;
	} else {
		len = strcspn(line, " \t\r\n");
		name = line;
		line += len;
		end = line + line_len;
	}

	if ((entry->name = malloc(len + 1)) == NULL) {
		archive_set_error(&a->archive, errno, "Can't allocate memory");
		return (ARCHIVE_FATAL);
	}

	memcpy(entry->name, name, len);
	entry->name[len] = '\0';
	parse_escapes(entry->name, entry);

	for (iter = *global; iter != NULL; iter = iter->next) {
		r = add_option(a, &entry->options, iter->value,
		    strlen(iter->value));
		if (r != ARCHIVE_OK)
			return (r);
	}

	for (;;) {
		next = line + strspn(line, " \t\r\n");
		if (*next == '\0')
			return (ARCHIVE_OK);
		if (next >= end)
			return (ARCHIVE_OK);
		line = next;
		next = line + strcspn(line, " \t\r\n");
		eq = strchr(line, '=');
		if (eq == NULL || eq > next)
			len = next - line;
		else
			len = eq - line;

		remove_option(&entry->options, line, len);
		r = add_option(a, &entry->options, line, next - line);
		if (r != ARCHIVE_OK)
			return (r);
		line = next;
	}
}
static int
process_add_entry(struct archive_read *a, struct mtree *mtree,
    struct mtree_option **global, const char *line,
    struct mtree_entry **last_entry)
{
	struct mtree_entry *entry;
	struct mtree_option *iter;
	const char *next, *eq;
	size_t len;
	int r;

	if ((entry = malloc(sizeof(*entry))) == NULL) {
		archive_set_error(&a->archive, errno, "Can't allocate memory");
		return (ARCHIVE_FATAL);
	}
	entry->next = NULL;
	entry->options = NULL;
	entry->name = NULL;
	entry->used = 0;
	entry->full = 0;

	/* Add this entry to list. */
	if (*last_entry == NULL)
		mtree->entries = entry;
	else
		(*last_entry)->next = entry;
	*last_entry = entry;

	len = strcspn(line, " \t\r\n");
	if ((entry->name = malloc(len + 1)) == NULL) {
		archive_set_error(&a->archive, errno, "Can't allocate memory");
		return (ARCHIVE_FATAL);
	}

	memcpy(entry->name, line, len);
	entry->name[len] = '\0';
	parse_escapes(entry->name, entry);

	line += len;
	for (iter = *global; iter != NULL; iter = iter->next) {
		r = add_option(a, &entry->options, iter->value,
		    strlen(iter->value));
		if (r != ARCHIVE_OK)
			return (r);
	}

	for (;;) {
		next = line + strspn(line, " \t\r\n");
		if (*next == '\0')
			return (ARCHIVE_OK);
		line = next;
		next = line + strcspn(line, " \t\r\n");
		eq = strchr(line, '=');
		if (eq == NULL || eq > next)
			len = next - line;
		else
			len = eq - line;

		remove_option(&entry->options, line, len);
		r = add_option(a, &entry->options, line, next - line);
		if (r != ARCHIVE_OK)
			return (r);
		line = next;
	}
}
Esempio n. 11
0
int setdevname_pppoe(const char *cp)
{
    int ret;
    char dev[IFNAMSIZ+1];
    int addr[ETH_ALEN];
    int sid;

//    char **a;
    ret =sscanf(cp, FMTSTRING(IFNAMSIZ),addr, addr+1, addr+2,
		addr+3, addr+4, addr+5,&sid,dev);
    if( ret != 8 ){

	ret = get_sockaddr_ll(cp,NULL);
        if (ret < 0)
	    fatal("PPPoE: Cannot create PF_PACKET socket for PPPoE discovery\n");
	if (ret == 1)
	    strncpy(devnam, cp, sizeof(devnam));
    }else{
	/* long form parsed */
	ret = get_sockaddr_ll(dev,NULL);
        if (ret < 0)
	    fatal("PPPoE: Cannot create PF_PACKET socket for PPPoE discovery\n");

	strncpy(devnam, cp, sizeof(devnam));
	ret = 1;
    }


    if( ret == 1 && the_channel != &pppoe_channel ){

	the_channel = &pppoe_channel;

	{
	    char **a;
	    for (a = bad_options; *a != NULL; a++)
		remove_option(*a);
	}

// cwu
	ipcp_allowoptions[0].default_route = 0 ;
	ipcp_wantoptions[0].default_route = 0 ;

// cwu
#if 0
	modem = 0;
#endif

	lcp_allowoptions[0].neg_accompression = 0;
	lcp_wantoptions[0].neg_accompression = 0;

	lcp_allowoptions[0].neg_asyncmap = 0;
	lcp_wantoptions[0].neg_asyncmap = 0;

	lcp_allowoptions[0].neg_pcompression = 0;
	lcp_wantoptions[0].neg_pcompression = 0;
// cwu
#if 0
	ccp_allowoptions[0].deflate = 0 ;
	ccp_wantoptions[0].deflate = 0 ;
#endif

	ipcp_allowoptions[0].neg_vj=0;
	ipcp_wantoptions[0].neg_vj=0;
// cwu
#if 0
	ccp_allowoptions[0].bsd_compress = 0;
	ccp_wantoptions[0].bsd_compress = 0;
#endif

	init_device_pppoe();
    }
    return ret;
}
static int
process_add_entry(struct archive_read *a, struct mtree *mtree,
    struct mtree_option **global, const char *line, ssize_t line_len,
    struct mtree_entry **last_entry, int is_form_d)
{
	struct mtree_entry *entry;
	struct mtree_option *iter;
	const char *next, *eq, *name, *end;
	size_t name_len, len;
	int r, i;

	if ((entry = malloc(sizeof(*entry))) == NULL) {
		archive_set_error(&a->archive, errno, "Can't allocate memory");
		return (ARCHIVE_FATAL);
	}
	entry->next = NULL;
	entry->options = NULL;
	entry->name = NULL;
	entry->used = 0;
	entry->full = 0;

	/* Add this entry to list. */
	if (*last_entry == NULL)
		mtree->entries = entry;
	else
		(*last_entry)->next = entry;
	*last_entry = entry;

	if (is_form_d) {
		/* Filename is last item on line. */
		/* Adjust line_len to trim trailing whitespace */
		while (line_len > 0) {
			char last_character = line[line_len - 1];
			if (last_character == '\r'
			    || last_character == '\n'
			    || last_character == '\t'
			    || last_character == ' ') {
				line_len--;
			} else {
				break;
			}
		}
		/* Name starts after the last whitespace separator */
		name = line;
		for (i = 0; i < line_len; i++) {
			if (line[i] == '\r'
			    || line[i] == '\n'
			    || line[i] == '\t'
			    || line[i] == ' ') {
				name = line + i + 1;
			}
		}
		name_len = line + line_len - name;
		end = name;
	} else {
		/* Filename is first item on line */
		name_len = strcspn(line, " \t\r\n");
		name = line;
		line += name_len;
		end = line + line_len;
	}
	/* name/name_len is the name within the line. */
	/* line..end brackets the entire line except the name */

	if ((entry->name = malloc(name_len + 1)) == NULL) {
		archive_set_error(&a->archive, errno, "Can't allocate memory");
		return (ARCHIVE_FATAL);
	}

	memcpy(entry->name, name, name_len);
	entry->name[name_len] = '\0';
	parse_escapes(entry->name, entry);

	for (iter = *global; iter != NULL; iter = iter->next) {
		r = add_option(a, &entry->options, iter->value,
		    strlen(iter->value));
		if (r != ARCHIVE_OK)
			return (r);
	}

	for (;;) {
		next = line + strspn(line, " \t\r\n");
		if (*next == '\0')
			return (ARCHIVE_OK);
		if (next >= end)
			return (ARCHIVE_OK);
		line = next;
		next = line + strcspn(line, " \t\r\n");
		eq = strchr(line, '=');
		if (eq == NULL || eq > next)
			len = next - line;
		else
			len = eq - line;

		remove_option(&entry->options, line, len);
		r = add_option(a, &entry->options, line, next - line);
		if (r != ARCHIVE_OK)
			return (r);
		line = next;
	}
}