Пример #1
0
bool read_config(FILE *file, bool is_active) {
	struct sway_config *temp_config = malloc(sizeof(struct sway_config));
	config_defaults(temp_config);
	if (is_active) {
		sway_log(L_DEBUG, "Performing configuration file reload");
		temp_config->reloading = true;
		temp_config->active = true;
	}

	bool success = true;

	int temp_depth = 0; // Temporary: skip all config sections with depth

	while (!feof(file)) {
		int _;
		char *line = read_line(file);
		line = strip_whitespace(line, &_);
		line = strip_comments(line);
		if (!line[0]) {
			goto _continue;
		}
		if (temp_depth && line[0] == '}') {
			temp_depth--;
			goto _continue;
		}

		// Any command which would require wlc to be initialized
		// should be queued for later execution
		list_t *args = split_string(line, " ");
		if (!is_active && (
			strcmp("exec", args->items[0]) == 0 ||
			strcmp("exec_always", args->items[0]) == 0 )) {
			sway_log(L_DEBUG, "Deferring command %s", line);

			char *cmd = malloc(strlen(line) + 1);
			strcpy(cmd, line);
			list_add(temp_config->cmd_queue, cmd);
		} else if (!temp_depth && !handle_command(temp_config, line)) {
			sway_log(L_DEBUG, "Config load failed for line %s", line);
			success = false;
			temp_config->failed = true;
		}
		list_free(args);

_continue:
		if (line && line[strlen(line) - 1] == '{') {
			temp_depth++;
		}
		free(line);
	}

	if (is_active) {
		temp_config->reloading = false;
		container_map(&root_container, reset_gaps, NULL);
		arrange_windows(&root_container, -1, -1);
	}
	config = temp_config;

	return success;
}
Пример #2
0
//load configuration file
int config_load()
{
	int fd;

	//set defaults
	config_defaults();

	//try to open config file
	if((fd = file_open(path_config,"rt")) == -1) {
		log_warning("cannot open config file '%s'\n",path_config);
		return(1);
	}
	while(file_eof(fd) == 0) {
		char line[512],*p,*oldp;
		char name[256],data[256];
		int i;

		file_gets(fd,line,512);
//		log_message("read line: '%s'\n",line);
		//eat whitespace from beginning of var name
		for(p = line;*p == ' ' || *p == '\t';p++);
		//comments
		if(*p == ';' || *p == '#' || *p == 0)
			continue;
		if((oldp = p = strchr(p,'=')) == 0) {
			log_warning("malformed configuration line, skipping\n");
			continue;
		}
		//eat whitespace end of var name
		for(*p--=0;*p == ' ' || *p == '\t';)
			*p-- = 0;
		//eat whitespace from var data
		for(oldp++;*oldp == ' ' || *oldp == '\t';oldp++);
		strcpy(name,line);
		strcpy(data,oldp);
		for(i=0;configvars[i].type != 0;i++) {
			//variable match
			if(strcmp(name,configvars[i].name) == 0) {
				if(configvars[i].type == CFG_U32)
					*((u32*)configvars[i].data) = atoi(data);
				else
					strcpy(((char*)configvars[i].data),data);
//				log_message("config var '%s' set to '%s'\n",name,data);
			}
		}
	}
	file_close(fd);
#ifndef PS2
	log_message("creating directories\n");
	mkdir(config.path_state);
	mkdir(config.path_cheat);
	mkdir(config.path_shots);
#endif
	return(0);
}
Пример #3
0
void config_load()
{
    memset(&AQCONFIG,0,sizeof(AQCONFIG));
    config_read();
    if ((AQCONFIG.magic!=MAGIC) || (AQCONFIG.version!=VERSION))
    {
        config_defaults();
        config_save();
    }
    
}
Пример #4
0
bool load_main_config(const char *file, bool is_active) {
	input_init();

	char *path;
	if (file != NULL) {
		path = strdup(file);
	} else {
		path = get_config_path();
	}

	struct sway_config *old_config = config;
	config = calloc(1, sizeof(struct sway_config));

	config_defaults(config);
	if (is_active) {
		sway_log(L_DEBUG, "Performing configuration file reload");
		config->reloading = true;
		config->active = true;
	}

	config->current_config = path;
	list_add(config->config_chain, path);

	config->reading = true;
	bool success = load_config(path, config);

	if (is_active) {
		config->reloading = false;
	}

	if (old_config) {
		free_config(old_config);
	}
	config->reading = false;

	if (success) {
		update_active_bar_modifiers();
	}

	return success;
}
Пример #5
0
static int config_init(
    struct idmap_config *config)
{
    int status;

    /* load default values */
    status = config_defaults(config);
    if (status) {
        eprintf("config_defaults() failed with %d\n", status);
        goto out;
    }

    /* load configuration from file */
    status = config_load(config, CONFIG_FILENAME);
    if (status) {
        eprintf("config_load('%s') failed with %d\n", CONFIG_FILENAME, status);
        goto out;
    }
out:
    return status;
}
Пример #6
0
int read_config(const char* file, struct hub_config* config, int allow_missing)
{
	int ret;

	memset(config, 0, sizeof(struct hub_config));
	config_defaults(config);

	ret = file_read_lines(file, config, &config_parse_line);
	if (ret < 0)
	{
		if (allow_missing && ret == -2)
		{
			LOG_DUMP("Using default configuration.");
		}
		else
		{
			return -1;
		}
	}

	return 0;
}
Пример #7
0
struct sway_config *read_config(FILE *file) {
	struct sway_config *config = malloc(sizeof(struct sway_config));
	config_defaults(config);

	bool success = true;

	int temp_depth = 0; // Temporary: skip all config sections with depth

	while (!feof(file)) {
		int _;
		char *line = read_line(file);
		line = strip_whitespace(line, &_);
		line = strip_comments(line);
		if (!line[0]) {
			goto _continue;
		}
		if (temp_depth && line[0] == '}') {
			temp_depth--;
			goto _continue;
		}

		if (!temp_depth && handle_command(config, line) != 0) {
			success = false;
		}
		
_continue:
		if (line && line[strlen(line) - 1] == '{') {
			temp_depth++;
		}
		free(line);
	}

	if (!success) {
		exit(1);
	}

	return config;
}
Пример #8
0
bool load_main_config(const char *file, bool is_active) {
	input_init();

	char *path;
	if (file != NULL) {
		path = strdup(file);
	} else {
		path = get_config_path();
	}

	struct sway_config *old_config = config;
	config = calloc(1, sizeof(struct sway_config));
	if (!config) {
		sway_abort("Unable to allocate config");
	}

	config_defaults(config);
	if (is_active) {
		sway_log(L_DEBUG, "Performing configuration file reload");
		config->reloading = true;
		config->active = true;
	}

	config->current_config = path;
	list_add(config->config_chain, path);

	config->reading = true;
	
	// Read security configs
	bool success = true;
	DIR *dir = opendir(SYSCONFDIR "/sway/security.d");
	if (!dir) {
		sway_log(L_ERROR, "%s does not exist, sway will have no security configuration"
				" and will probably be broken", SYSCONFDIR "/sway/security.d");
	} else {
		list_t *secconfigs = create_list();
		char *base = SYSCONFDIR "/sway/security.d/";
		struct dirent *ent = readdir(dir);
		struct stat s;
		while (ent != NULL) {
			char *_path = malloc(strlen(ent->d_name) + strlen(base) + 1);
			strcpy(_path, base);
			strcat(_path, ent->d_name);
			lstat(_path, &s);
			if (S_ISREG(s.st_mode)) {
				list_add(secconfigs, _path);
			}
			ent = readdir(dir);
		}
		closedir(dir);

		list_qsort(secconfigs, qstrcmp);
		for (int i = 0; i < secconfigs->length; ++i) {
			char *_path = secconfigs->items[i];
			if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 || (((s.st_mode & 0777) != 0644) && (s.st_mode & 0777) != 0444)) {
				sway_log(L_ERROR, "Refusing to load %s - it must be owned by root and mode 644 or 444", _path);
				success = false;
			} else {
				success = success && load_config(_path, config);
			}
		}

		free_flat_list(secconfigs);
	}

	success = success && load_config(path, config);

	if (is_active) {
		config->reloading = false;
	}

	if (old_config) {
		free_config(old_config);
	}
	config->reading = false;

	if (success) {
		update_active_bar_modifiers();
	}

	return success;
}
Пример #9
0
bool read_config(FILE *file, bool is_active) {
	struct sway_config *old_config = config;
	config = calloc(1, sizeof(struct sway_config));

	config_defaults(config);
	config->reading = true;
	if (is_active) {
		sway_log(L_DEBUG, "Performing configuration file reload");
		config->reloading = true;
		config->active = true;
	}
	bool success = true;
	enum cmd_status block = CMD_BLOCK_END;

	int line_number = 0;
	char *line;
	while (!feof(file)) {
		line = read_line(file);
		line_number++;
		line = strip_whitespace(line);
		if (line[0] == '#') {
			continue;
		}
		struct cmd_results *res = config_command(line, block);
		switch(res->status) {
		case CMD_FAILURE:
		case CMD_INVALID:
			sway_log(L_ERROR, "Error on line %i '%s': %s", line_number, line,
				res->error);
			success = false;
			break;

		case CMD_DEFER:
			sway_log(L_DEBUG, "Defferring command `%s'", line);
			list_add(config->cmd_queue, strdup(line));
			break;

		case CMD_BLOCK_MODE:
			if (block == CMD_BLOCK_END) {
				block = CMD_BLOCK_MODE;
			} else {
				sway_log(L_ERROR, "Invalid block '%s'", line);
			}
			break;

		case CMD_BLOCK_END:
			switch(block) {
			case CMD_BLOCK_MODE:
				sway_log(L_DEBUG, "End of mode block");
				config->current_mode = config->modes->items[0];
				break;

			case CMD_BLOCK_END:
				sway_log(L_ERROR, "Unmatched }");
				break;

			default:;
			}
		default:;
		}
		free(line);
		free(res);
	}

	if (is_active) {
		config->reloading = false;
		arrange_windows(&root_container, -1, -1);
	}
	if (old_config) {
		free_config(old_config);
	}

	config->reading = false;
	return success;
}
Пример #10
0
/* Main rated */
int main(int argc, char *argv[]) {
    crew_t crew;
    pthread_t sig_thread;
    sigset_t signal_set;
    struct timeval begin_time, end_time;
    unsigned long sleep_time;
    unsigned long poll_time;
    unsigned long long polls;
    unsigned long long last_poll;
    double rate;
    char *conf_file = NULL;
    char *table;
    char errstr[BUFSIZE];
    int ch, i, freed;
    struct timespec ts;

    dfp = stderr;

    /* Check argument count */
    if (argc < 3)
	usage(argv[0]);

    /* Set default environment */
    config_defaults(set);

    /* Parse the command-line. */
    while ((ch = getopt(argc, argv, "c:p:dhmDt:vz")) != EOF)
	switch ((char) ch) {
	case 'c':
	    conf_file = optarg;
	    break;
	case 'd':
	    set->dbon = FALSE;
	    break;
	case 'D':
	    set->daemon = FALSE;
	    break;
	case 'h':
	    usage(argv[0]);
	    break;
	case 'm':
	    set->multiple++;
	    break;
	case 'p':
	    pid_file = optarg;
	    break;
	case 't':
	    target_file = optarg;
	    break;
	case 'v':
	    set->verbose++;
	    break;
	case 'z':
	    set->withzeros = TRUE;
	    break;
	}

    debug(LOW, "rated version %s starting.\n", VERSION);

    if (set->daemon) {
        if (daemon_init() < 0)
            fatal("Could not fork daemon!\n");
        debug(LOW, "Daemon detached\n");
    }

    pthread_mutex_init(&stats.mutex, NULL);

    /* Initialize signal handler */
    sigemptyset(&signal_set);
    sigaddset(&signal_set, SIGHUP);
    sigaddset(&signal_set, SIGUSR1);
    sigaddset(&signal_set, SIGUSR2);
    sigaddset(&signal_set, SIGTERM);
    sigaddset(&signal_set, SIGINT);
    sigaddset(&signal_set, SIGQUIT);
    if (!set->multiple) 
        checkPID(pid_file, set);

    if (pthread_sigmask(SIG_BLOCK, &signal_set, NULL) != 0)
        fatal("pthread_sigmask error\n");

    /* start a thread to catch signals */
    if (pthread_create(&sig_thread, NULL, sig_handler, (void *) &(signal_set)) != 0)
	fatal("pthread_create error\n");

    /* Read configuration file to establish local environment */
    if (conf_file) {
        if ((read_rated_config(conf_file, set)) < 0) 
            fatal("Could not read config file: %s\n", conf_file);
    } else {
        conf_file = malloc(BUFSIZE);
        if (!conf_file) 
            fatal("Fatal malloc error!\n");
        for(i=0;i<CONFIG_PATHS;i++) {
            snprintf(conf_file, BUFSIZE, "%s%s", config_paths[i], DEFAULT_CONF_FILE); 
            if (read_rated_config(conf_file, set) >= 0)
                break;
            if (i == CONFIG_PATHS-1) {
                snprintf(conf_file, BUFSIZE, "%s%s", config_paths[0], DEFAULT_CONF_FILE); 
                if ((write_rated_config(conf_file, set)) < 0) 
                    fatal("Couldn't write config file.\n");
            }
        }
    }

    /* these probably aren't thread safe*/
    init_snmp("rated");
    /* TODO only do this if we're debugging or not daemonised? */
    snmp_enable_stderrlog();
    /* output oids numerically - this is equivalent to -On in the snmp tools */
    netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_OID_OUTPUT_FORMAT, NETSNMP_OID_OUTPUT_NUMERIC);

    if (set->dbon) {
        /* load the database driver */
        /* we need a db connection before we parse the targets file so we can check and create tables */
        if (!(db_init(set) && db_connect(set)))
            fatal("** Database error - check configuration.\n");

        /* create our own internal tables */
        table = db_check_and_create_data_table(RATED);
        if (table == NULL)
            fatal("** Database error - couldn't create rated table.\n");
        else
            free(table);
        if (!db_check_and_create_oids_table(OIDS))
            fatal("** Database error - couldn't create oids table.\n");
    }

    /* build list of hosts to be polled */
    head = hash_target_file(target_file);
    if (head == NULL)
        fatal("Error updating target list.");

    if (hosts < set->threads) {
        debug(LOW, "Number of hosts is less than configured number of threads, defaulting to %i.\n", hosts);
        set->threads = hosts;
    }

    debug(LOW, "Initializing threads (%d).\n", set->threads);
    pthread_mutex_init(&(crew.mutex), NULL);
    pthread_cond_init(&(crew.done), NULL);
    pthread_cond_init(&(crew.go), NULL);
    crew.current = NULL;

    debug(HIGH, "Starting threads...");
    crew.running = set->threads;
    for (i = 0; i < set->threads; i++) {
        crew.member[i].index = i;
        crew.member[i].crew = &crew;
        if (pthread_create(&(crew.member[i].thread), NULL, poller, (void *) &(crew.member[i])) != 0)
	    fatal("pthread_create error\n");
	debug(HIGH, " %i", i);
	}
    debug(HIGH, " done\n");

    /* spin waiting for all threads to start up */
    debug(HIGH, "Waiting for thread startup.\n");
    ts.tv_sec = 0;
    ts.tv_nsec = 10000000; /* 10 ms */
    gettimeofday(&begin_time, NULL);
    while (crew.running > 0 ) {
	nanosleep(&ts, NULL);
    }
    gettimeofday(&end_time, NULL);
    debug(HIGH, "Waited %lu milliseconds for thread startup.\n", timediff(end_time, begin_time));

    debug(LOW, "rated ready.\n");

    /* Loop Forever Polling Target List */
    while (1) {
	/* check if we've been signalled */
	if (quitting) {
            debug(LOW, "Quitting: received signal %i.\n", quit_signal);
            if (set->dbon)
                db_disconnect();
            /* one final stat output */
            print_stats(stats, set);
            unlink(pid_file);
            exit(1);
	} else if (waiting) {
            debug(HIGH, "Processing pending SIGHUP.\n");
            /* this just rebuilds the target list
             * so all of the targets will reset to a first poll */
            /* none of the threads should be running at this point so we shouldn't need a lock */
            freed = free_host_list(head);
            debug(HIGH, "Freed %i hosts\n", freed);
            head = hash_target_file(target_file);
            waiting = FALSE;
	}

        last_poll = stats.polls;

	gettimeofday(&begin_time, NULL);

	PT_MUTEX_LOCK(&(crew.mutex));
        crew.current = head;

	debug(LOW, "Queue ready, broadcasting thread go condition.\n");

	PT_COND_BROAD(&(crew.go));
	PT_MUTEX_UNLOCK(&(crew.mutex));

        /*
         * wait for signals from threads finishing
         * we have to use a do loop because when this starts up the running count will be zero
         * so wait at least once until we get a signal that some thread is done before checking for zero
         */
	PT_MUTEX_LOCK(&(crew.mutex));
        do {
            PT_COND_WAIT(&(crew.done), &(crew.mutex));
        } while (crew.running > 0);
	PT_MUTEX_UNLOCK(&(crew.mutex));

        if (quitting_now)
            continue;

	gettimeofday(&end_time, NULL);
	poll_time = timediff(end_time, begin_time);
        polls = stats.polls - last_poll;
        rate = ((double) polls / poll_time) * 1000;
        /* don't underflow */
        if (poll_time < set->interval) {
	    sleep_time = set->interval - poll_time;
        } else {
            sleep_time = 0;
            stats.slow++;
        }

        /* have to call this before we increment the round counter */
        calc_stats(&stats, poll_time);

        stats.round++;
	debug(LOW, "Poll round %d completed %llu getnexts in %lu ms (%.0f/s).\n", stats.round, polls, poll_time, rate);
        /* insert the internal poll data for this round into the rated table */
        if (set->dbon)
            db_insert(RATED, 0, end_time, stats.polls - last_poll, rate);

	if (set->verbose >= LOW) {
            print_stats(stats, set);
        }

        if (sleep_time > 0) {
            sleepy(sleep_time, set);
        } else {
            debug(LOW, "Slow poll, not sleeping\n");
        }
    } /* while(1) */
    exit(0);
}
Пример #11
0
int main(int argc, char *argv[]) {
	struct timeval now;
	char *conf_file = NULL;
	double begin_time, end_time;
	int num_rows;
	int device_counter = 0;
	int last_active_threads = 0;
	long int THREAD_SLEEP = 100000;
	time_t nowbin;
	const struct tm *nowstruct;

	pthread_t* threads = NULL;
	pthread_attr_t attr;
	pthread_mutexattr_t mutexattr;

	int* ids = NULL;
	MYSQL mysql;
	MYSQL_RES *result = NULL;
	MYSQL_ROW mysql_row;
	int canexit = 0;
	int host_id;
	int i;
	int mutex_status = 0;
	int thread_status = 0;
	char result_string[BUFSIZE] = "";
	char logmessage[LOGSIZE];

	/* set start time for cacti */
	gettimeofday(&now, NULL);
	begin_time = (double) now.tv_usec / 1000000 + now.tv_sec;

	/* get time for poller_output table */
	if (time(&nowbin) == (time_t) - 1)
		printf("ERROR: Could not get time of day from time()\n");

	nowstruct = localtime(&nowbin);

	if (strftime(start_datetime, sizeof(start_datetime), "%Y-%m-%d %H:%M:%S", nowstruct) == (size_t) 0)
		printf("ERROR: Could not get string from strftime()\n");

	set.verbose = POLLER_VERBOSITY_HIGH;

	/* get static defaults for system */
	config_defaults(&set);

	/* scan arguments for errors */
	if ((argc != 1) && (argc != 3)) {
		printf("ERROR: Cactid requires either 0 or 2 input parameters\n");
		printf("USAGE: <cactidpath>/cactid [start_id end_id]\n");
		exit(-1);
	}

	/* return error if the first arg is greater than the second */
	if (argc == 3) {
		if (atol(argv[1]) > atol(argv[2])) {
			printf("ERROR: Invalid row specifications.  First row must be less than the second row\n");
			exit(-2);
		}
	}

	/* read configuration file to establish local environment */
	if (conf_file) {
		if ((read_cactid_config(conf_file, &set)) < 0) {
			printf("ERROR: Could not read config file: %s\n", conf_file);
			exit(-3);
		}
	}else{
		conf_file = malloc(BUFSIZE);

		if (!conf_file) {
			printf("ERROR: Fatal malloc error!\n");
			exit(-1);
		}

		for(i=0;i<CONFIG_PATHS;i++) {
			snprintf(conf_file, BUFSIZE, "%s%s", config_paths[i], DEFAULT_CONF_FILE);

			if (read_cactid_config(conf_file, &set) >= 0) {
				break;
			}

			if (i == CONFIG_PATHS-1) {
				snprintf(conf_file, BUFSIZE, "%s%s", config_paths[0], DEFAULT_CONF_FILE);
			}
		}
	}

	/* read settings table from the database to further establish environment */
	read_config_options(&set);

	/* set the poller ID, stub for next version */
	set.poller_id = 0;

	if (set.verbose == POLLER_VERBOSITY_DEBUG) {
		snprintf(logmessage, LOGSIZE, "CACTID: Version %s starting\n", VERSION);
		cacti_log(logmessage);
	} else {
		printf("CACTID: Version %s starting\n", VERSION);
	}

	/* connect to database */
	db_connect(set.dbdb, &mysql);

	/* initialize SNMP */
	init_snmp("cactid");

	/* initialize PHP */
	php_init();

	/* get the id's to poll */
	switch (argc) {
		case 1:
			result = db_query(&mysql, "SELECT id FROM host WHERE disabled='' ORDER BY id");

			break;
		case 3:
			snprintf(result_string, sizeof(result_string), "SELECT id FROM host WHERE (disabled='' and (id >= %s and id <= %s)) ORDER BY id\0", argv[1], argv[2]);
			result = db_query(&mysql, result_string);

			break;
		default:
			break;
	}

	num_rows = mysql_num_rows(result);
	threads = (pthread_t *)malloc(num_rows * sizeof(pthread_t));
	ids = (int *)malloc(num_rows * sizeof(int));

	/* initialize threads and mutexes */
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

	init_mutexes();

	if (set.verbose == POLLER_VERBOSITY_DEBUG) {
		snprintf(logmessage, LOGSIZE, "DEBUG: Initial Value of Active Threads is %i\n", active_threads);
		cacti_log(logmessage);
	}

	/* loop through devices until done */
	while (device_counter < num_rows) {
		mutex_status = thread_mutex_trylock(LOCK_THREAD);

		switch (mutex_status) {
		case 0:
			if (last_active_threads != active_threads) {
				last_active_threads = active_threads;
			}

			while ((active_threads < set.threads) && (device_counter < num_rows)) {
				mysql_row = mysql_fetch_row(result);
				host_id = atoi(mysql_row[0]);
				ids[device_counter] = host_id;

				/* create child process */
				thread_status = pthread_create(&threads[device_counter], &attr, child, &ids[device_counter]);

				switch (thread_status) {
					case 0:
						if (set.verbose == POLLER_VERBOSITY_DEBUG) {
							snprintf(logmessage, LOGSIZE, "DEBUG: Valid Thread to be Created\n");
							cacti_log(logmessage);
						}

						device_counter++;
						active_threads++;

						if (set.verbose == POLLER_VERBOSITY_DEBUG) {
							snprintf(logmessage, LOGSIZE, "DEBUG: The Value of Active Threads is %i\n", active_threads);
							cacti_log(logmessage);
						}

						break;
					case EAGAIN:
						snprintf(logmessage, LOGSIZE, "ERROR: The System Lacked the Resources to Create a Thread\n");
						cacti_log(logmessage);
						break;
					case EFAULT:
						snprintf(logmessage, LOGSIZE, "ERROR: The Thread or Attribute Was Invalid\n");
						cacti_log(logmessage);
						break;
					case EINVAL:
						snprintf(logmessage, LOGSIZE, "ERROR: The Thread Attribute is Not Initialized\n");
						cacti_log(logmessage);
						break;
					default:
						snprintf(logmessage, LOGSIZE, "ERROR: Unknown Thread Creation Error\n");
						cacti_log(logmessage);
						break;
				}
				usleep(THREAD_SLEEP);
			}

			thread_mutex_unlock(LOCK_THREAD);

			break;
		case EBUSY:
			snprintf(logmessage, LOGSIZE, "ERROR: Deadlock Occured\n");
			cacti_log(logmessage);
			break;
		case EINVAL:
			snprintf(logmessage, LOGSIZE, "ERROR: Attempt to Unlock an Uninitialized Mutex\n");
			cacti_log(logmessage);
			break;
		case EFAULT:
			snprintf(logmessage, LOGSIZE, "ERROR: Attempt to Unlock an Invalid Mutex\n");
			cacti_log(logmessage);
			break;
		default:
			snprintf(logmessage, LOGSIZE, "ERROR: Unknown Mutex Lock Error Code Returned\n");
			cacti_log(logmessage);
			break;
		}

		usleep(THREAD_SLEEP);
	}

	/* wait for all threads to complete */
	while (canexit == 0) {
		if (thread_mutex_trylock(LOCK_THREAD) != EBUSY) {
			if (last_active_threads != active_threads) {
				last_active_threads = active_threads;
			}

			if (active_threads == 0) {
				canexit = 1;
			}

			thread_mutex_unlock(LOCK_THREAD);
		}

		usleep(THREAD_SLEEP);
	}

	/* print out stats */
	gettimeofday(&now, NULL);

	/* update the db for |data_time| on graphs */
	db_insert(&mysql, "replace into settings (name,value) values ('date',NOW())");
	db_insert(&mysql, "insert into poller_time (poller_id, start_time, end_time) values (0, NOW(), NOW())");

	/* cleanup and exit program */
	pthread_attr_destroy(&attr);
	pthread_mutexattr_destroy(&mutexattr);

	if (set.verbose == POLLER_VERBOSITY_DEBUG) {
		cacti_log("DEBUG: Thread Cleanup Complete\n");
	}

	/* close the php script server */
	php_close();

	if (set.verbose == POLLER_VERBOSITY_DEBUG) {
		cacti_log("DEBUG: PHP Script Server Pipes Closed\n");
	}

	/* free malloc'd variables */
	free(threads);
	free(ids);
	free(conf_file);

	if (set.verbose == POLLER_VERBOSITY_DEBUG) {
		cacti_log("DEBUG: Allocated Variable Memory Freed\n");
	}

	/* close mysql */
	mysql_free_result(result);
	mysql_close(&mysql);

	if (set.verbose == POLLER_VERBOSITY_DEBUG) {
		cacti_log("DEBUG: MYSQL Free & Close Completed\n");
	}

	/* finally add some statistics to the log and exit */
	end_time = (double) now.tv_usec / 1000000 + now.tv_sec;

	if ((set.verbose >= POLLER_VERBOSITY_MEDIUM) && (argc != 1)) {
		snprintf(logmessage, LOGSIZE, "Time: %.4f s, Threads: %i, Hosts: %i\n", (end_time - begin_time), set.threads, num_rows);
		cacti_log(logmessage);
	} else {
		printf("CACTID: Execution Time: %.4f s, Threads: %i, Hosts: %i\n", (end_time - begin_time), set.threads, num_rows);
	}

	exit(0);
}
Пример #12
0
static char *get_config_path() {
	char *home = getenv("HOME");
	if (home) {
		home = strdup(getenv("HOME"));
	}
	char *config = getenv("XDG_CONFIG_HOME");
	if (config) {
		config = strdup(getenv("XDG_CONFIG_HOME"));
	} else if (home) {
		const char *def = "/.config";
		config = malloc(strlen(home) + strlen(def) + 1);
		strcpy(config, home);
		strcat(config, def);
	} else {
		home = strdup("");
		config = strdup("");
	}

	// Set up a temporary config for holding set variables
	struct sway_config *temp_config = malloc(sizeof(struct sway_config));
	config_defaults(temp_config);
	const char *set_home = "set $home ";
	char *_home = malloc(strlen(home) + strlen(set_home) + 1);
	strcpy(_home, set_home);
	strcat(_home, home);
	handle_command(temp_config, _home);
	free(_home);
	const char *set_config = "set $config ";
	char *_config = malloc(strlen(config) + strlen(set_config) + 1);
	strcpy(_config, set_config);
	strcat(_config, config);
	handle_command(temp_config, _config);
	free(_config);

	char *test = NULL;
	int i;
	for (i = 0; i < (int)(sizeof(search_paths) / sizeof(char *)); ++i) {
		test = strdup(search_paths[i]);
		test = do_var_replacement(temp_config, test);
		sway_log(L_DEBUG, "Checking for config at %s", test);
		if (exists(test)) {
			goto _continue;
		}
		free(test);
		test = NULL;
	}

	sway_log(L_DEBUG, "Trying to find config in XDG_CONFIG_DIRS");
	char *xdg_config_dirs = getenv("XDG_CONFIG_DIRS");
	if (xdg_config_dirs != NULL) {
		list_t *paths = split_string(xdg_config_dirs, ":");
		char *name = "/sway/config";
		int i;
		for (i = 0; i < paths->length; i++ ) {
			test = malloc(strlen(paths->items[i]) + strlen(name) + 1);
			strcpy(test, paths->items[i]);
			strcat(test, name);
			if (exists(test)) {
				free_flat_list(paths);
				return test;
			}
			free(test);
			test = NULL;
		}
		free_flat_list(paths);
	}

_continue:
	free_config(temp_config);
	free(home);
	free(config);
	return test;
}
Пример #13
0
config_t* config_parse(TCHAR* path)
{
	FILE* file = fopen(path, "r");
	TCHAR buffer[TEXTLEN], param[CONFIG_STR_MAXSIZE];
	size_t len, count;
	mask_t* msk;
	config_t* conf = malloc(sizeof(config_t));
	config_defaults(conf);
	if (file)
	{
		while (fgets(buffer, TEXTLEN, file))
		{
			len = sizeof(CONFIG_STR_COMMENTS) - 1;
			strncpy(param, buffer, len);
			param[len] = '\0';
			if (!stricmp(CONFIG_STR_COMMENTS, param))
			{
				strtok(buffer, " =-\n");
				conf->comments = atoi(strtok(NULL, " =-\n"));
				continue;
			}
			len = sizeof(CONFIG_STR_LABELS) - 1;
			strncpy(param, buffer, len);
			param[len] = '\0';
			if (!stricmp(CONFIG_STR_LABELS, param))
			{
				strtok(buffer, " =-\n");
				conf->labels = atoi(strtok(NULL, " =-\n"));
				continue;
			}
			len = sizeof(CONFIG_STR_COLLISIONS) - 1;
			strncpy(param, buffer, len);
			param[len] = '\0';
			if (!stricmp(CONFIG_STR_COLLISIONS, param))
			{
				strtok(buffer, " =-\n");
				conf->collisionchecks = atoi(strtok(NULL, " =-\n"));
				continue;
			}
			len = sizeof(CONFIG_STR_APPLYTO) - 1;
			strncpy(param, buffer, len);
			param[len] = '\0';
			if (!stricmp(CONFIG_STR_APPLYTO, param))
			{
				strtok(buffer, " =-\n");
				conf->applytodebuggee = atoi(strtok(NULL, " =-\n"));
				continue;
			}
			len = sizeof(CONFIG_STR_AUTOIMPORT) - 1;
			strncpy(param, buffer, len);
			param[len] = '\0';
			if (!stricmp(CONFIG_STR_AUTOIMPORT, param))
			{
				strtok(buffer, " =-\n");
				conf->aimport = atoi(strtok(NULL, " =-\n"));
				continue;
			}
			len = sizeof(CONFIG_STR_DEMANGLE) - 1;
			strncpy(param, buffer, len);
			param[len] = '\0';
			if (!stricmp(CONFIG_STR_DEMANGLE, param))
			{
				strtok(buffer, " =-\n");
				conf->demangle = atoi(strtok(NULL, " =-\n"));
				continue;
			}
			len = sizeof(CONFIG_STR_USEMASKS) - 1;
			strncpy(param, buffer, len);
			param[len] = '\0';
			if (!stricmp(CONFIG_STR_USEMASKS, param))
			{
				strtok(buffer, " =-\n");
				conf->usemasks = atoi(strtok(NULL, " =-\n"));
				continue;
			}
			len = sizeof(CONFIG_STR_MASKS) - 1;
			strncpy(param, buffer, len);
			param[len] = '\0';
			if (!stricmp(CONFIG_STR_MASKS, param))
			{
				strtok(buffer, " =-\n");
				conf->masks = list_create();
				count = atoi(strtok(NULL, " =-\n"));
				while (conf->masks->count < count && fgets(buffer, TEXTLEN, file))
				{
					msk = list_addmask(conf->masks, strtok(buffer, "\n"));
					if (msk->errcode)
					{
						free(msk);
					}
				}
			}
		}
		fclose(file);
	}
	return conf;
}
Пример #14
0
/* Main rtgpoll */
int main(int argc, char *argv[]) {
    crew_t crew;
    pthread_t sig_thread;
    sigset_t signal_set;
    struct timeval now;
    double begin_time, end_time, sleep_time;
    char *conf_file = NULL;
    char errstr[BUFSIZE];
    int ch, i;

	dfp = stderr;

    /* Check argument count */
    if (argc < 3)
	usage(argv[0]);

	/* Set default environment */
    config_defaults(set);

    /* Parse the command-line. */
    while ((ch = getopt(argc, argv, "c:p:dhmDt:vz")) != EOF)
	switch ((char) ch) {
	case 'c':
	    conf_file = optarg;
	    break;
	case 'd':
	    set->dboff = TRUE;
	    break;
	case 'D':
	    set->daemon = FALSE;
	    break;
	case 'h':
	    usage(argv[0]);
	    break;
	case 'm':
	    set->multiple++;
	    break;
	case 'p':
	    pid_file = optarg;
	    break;
	case 't':
	    target_file = optarg;
	    break;
	case 'v':
	    set->verbose++;
	    break;
	case 'z':
	    set->withzeros = TRUE;
	    break;
	}

	debug(LOW, "RTG version %s starting.\n", VERSION);

	if (set->daemon) {
		if (daemon_init() < 0)
			fatal("Could not fork daemon!\n");
		debug(LOW, "Daemon detached\n");
	}


    /* Initialize signal handler */
    sigemptyset(&signal_set);
    sigaddset(&signal_set, SIGHUP);
    sigaddset(&signal_set, SIGUSR1);
    sigaddset(&signal_set, SIGUSR2);
    sigaddset(&signal_set, SIGTERM);
    sigaddset(&signal_set, SIGINT);
    sigaddset(&signal_set, SIGQUIT);
	if (!set->multiple) 
		checkPID(pid_file, set);

    if (pthread_sigmask(SIG_BLOCK, &signal_set, NULL) != 0)
		printf("pthread_sigmask error\n");

    /* Read configuration file to establish local environment */
    if (conf_file) {
      if ((read_rtg_config(conf_file, set)) < 0) 
		fatal("Could not read config file: %s\n", conf_file);
    } else {
      conf_file = malloc(BUFSIZE);
      if (!conf_file) 
         fatal("Fatal malloc error!\n");
      for(i=0;i<CONFIG_PATHS;i++) {
        snprintf(conf_file, BUFSIZE, "%s%s", config_paths[i], DEFAULT_CONF_FILE); 
        if (read_rtg_config(conf_file, set) >= 0)
           break;
        if (i == CONFIG_PATHS-1) {
			snprintf(conf_file, BUFSIZE, "%s%s", config_paths[0], DEFAULT_CONF_FILE); 
			if ((write_rtg_config(conf_file, set)) < 0) 
				fatal("Couldn't write config file.\n");
        }
      }
    }


    /* hash list of targets to be polled */
    init_hash();
	entries = hash_target_file(target_file);
    if (entries <= 0) 
		fatal("Error updating target list.");

	debug(LOW, "Initializing threads (%d).\n", set->threads);
    pthread_mutex_init(&(crew.mutex), NULL);
    pthread_cond_init(&(crew.done), NULL);
    pthread_cond_init(&(crew.go), NULL);
    crew.work_count = 0;

    /* Initialize the SNMP session */
	debug(LOW, "Initializing SNMP (port %d).\n", set->snmp_port);
    init_snmp("RTG");

    /* Attempt to connect to the MySQL Database */
#ifndef FEATURES
 #if HAVE_MYSQL
    if (!(set->dboff)) {
		if (mysql_dbconnect(set->dbdb, &mysql) < 0) 
			fatal("** Database error - check configuration.\n");
		if (!mysql_ping(&mysql))
			debug(LOW, "connected.\n");
		else
			fatal("server not responding.\n");
    }
 #endif
#else
 #if HAVE_MYSQL
	my_init();
 #endif
#endif


	debug(HIGH, "\nStarting threads.\n");
    for (i = 0; i < set->threads; i++) {
		crew.member[i].index = i;
		crew.member[i].crew = &crew;
		if (pthread_create(&(crew.member[i].thread), NULL, poller, (void *) &(crew.member[i])) != 0)
			printf("pthread_create error\n");
	}
    if (pthread_create(&sig_thread, NULL, sig_handler, (void *) &(signal_set)) != 0)
		printf("pthread_create error\n");

    /* give threads time to start up */
    sleep(1);

	debug(LOW, "RTG Ready.\n");

    /* Loop Forever Polling Target List */
    while (1) {
	lock = TRUE;
	gettimeofday(&now, NULL);
	begin_time = (double) now.tv_usec / 1000000 + now.tv_sec;

	PT_MUTEX_LOCK(&(crew.mutex));
	init_hash_walk();
	current = getNext();
	crew.work_count = entries;
	PT_MUTEX_UNLOCK(&(crew.mutex));
	    
	if (set->verbose >= LOW) {
		if (set->daemon)
			sysloginfo("Queue ready, broadcasting thread go condition.");
		else
        	timestamp("Queue ready, broadcasting thread go condition.");
	}
	PT_COND_BROAD(&(crew.go));
	PT_MUTEX_LOCK(&(crew.mutex));
	    
	while (crew.work_count > 0) {
		PT_COND_WAIT(&(crew.done), &(crew.mutex));
	}
	PT_MUTEX_UNLOCK(&(crew.mutex));

	gettimeofday(&now, NULL);
	lock = FALSE;
	end_time = (double) now.tv_usec / 1000000 + now.tv_sec;
	stats.poll_time = end_time - begin_time;
        stats.round++;
	sleep_time = set->interval - stats.poll_time;

	if (waiting) {
		debug(HIGH, "Processing pending SIGHUP.\n");
	    entries = hash_target_file(target_file);
	    waiting = FALSE;
	}

	if (set->verbose >= LOW) {
        snprintf(errstr, sizeof(errstr), "Poll round %d complete.", stats.round);
		if (set->daemon)
			sysloginfo(errstr);
		else
			timestamp(errstr);
	    print_stats(stats, set);
    }

	if (sleep_time <= 0)
	    stats.slow++;
	else
	    sleepy(sleep_time, set);
    } /* while */

#ifndef FEATURES
  #if HAVE_MYSQL
    /* Disconnect from the MySQL Database, exit. */
    if (!(set->dboff))
	mysql_dbdisconnect(&mysql);
  #endif
#endif
    exit(0);
}
Пример #15
0
/*! \fn main(int argc, char *argv[])
 *  \brief The Cactid program entry point
 *  \param argc The number of arguments passed to the function plus one (+1)
 *  \param argv An array of the command line arguments
 *
 *  The Cactid entry point.  This function performs the following tasks.
 *  1) Processes command line input parameters
 *  2) Processes the Cactid configuration file to obtain database access information
 *  3) Process runtime parameters from the settings table
 *  4) Initialize the runtime threads and mutexes for the threaded environment
 *  5) Initialize Net-SNMP, MySQL, and the PHP Script Server (if required)
 *  6) Spawns X threads in order to process hosts
 *  7) Loop until either all hosts have been processed or until the poller runtime
 *     has been exceeded
 *  8) Close database and free variables
 *  9) Log poller process statistics if required
 *  10) Exit
 *
 *  Note: Command line runtime parameters override any database settings.
 *
 *  \return 0 if SUCCESS, or -1 if FAILED
 *
 */
int main(int argc, char *argv[]) {
	struct timeval now;
	char *conf_file = NULL;
	double begin_time, end_time, current_time;
	int poller_interval;
	int num_rows;
	int device_counter = 0;
	int poller_counter = 0;
	int last_active_threads = 0;
	long int EXTERNAL_THREAD_SLEEP = 100000;
	long int internal_thread_sleep;
	time_t nowbin;
	struct tm now_time;
	struct tm *now_ptr;

	pthread_t* threads = NULL;
	pthread_attr_t attr;

	int* ids = NULL;
	MYSQL mysql;
	MYSQL_RES *result = NULL;
	MYSQL_ROW mysql_row;
	int canexit = 0;
	int host_id;
	int i;
	int mutex_status = 0;
	int thread_status = 0;

	UNUSED_PARAMETER(argc);		/* we operate strictly with argv */

	/* establish php processes and initialize space */
	php_processes = (php_t*) calloc(MAX_PHP_SERVERS, sizeof(php_t));
	for (i = 0; i < MAX_PHP_SERVERS; i++) {
		php_processes[i].php_state = PHP_BUSY;
	}

	/* set start time for cacti */
	begin_time = get_time_as_double();

	/* get time for poller_output table */
	if (time(&nowbin) == (time_t) - 1) {
		die("ERROR: Could not get time of day from time()\n");
	}
	localtime_r(&nowbin,&now_time);
	now_ptr = &now_time;

	if (strftime(start_datetime, sizeof(start_datetime), "%Y-%m-%d %H:%M:%S", now_ptr) == (size_t) 0) {
		die("ERROR: Could not get string from strftime()\n");
	}

	/* set default verbosity */
	set.log_level = POLLER_VERBOSITY_LOW;

	/* get static defaults for system */
	config_defaults();

	/*! ----------------------------------------------------------------
	 * PROCESS COMMAND LINE
	 *
	 * Run through the list of ARGV words looking for parameters we
	 * know about. Most have two flavors (-C + --conf), and many
	 * themselves take a parameter.
	 *
	 * These parameters can be structured in two ways:
	 *
	 *	--conf=FILE		both parts in one argv[] string
	 *	--conf FILE		two separate argv[] strings
	 *
	 * We set "arg" to point to "--conf", and "opt" to point to FILE.
	 * The helper routine
	 *
	 * In each loop we set "arg" to next argv[] string, then look
	 * to see if it has an equal sign. If so, we split it in half
	 * and point to the option separately.
	 *
	 * NOTE: most direction to the program is given with dash-type
	 * parameters, but we also allow standalone numeric device IDs
	 * in "first last" format: this is how poller.php calls this
	 * program.
	 */

	/* initialize some global variables */
	set.start_host_id = -1;
	set.end_host_id   = -1;
	set.php_initialized = FALSE;
	set.logfile_processed = FALSE;
	set.parent_fork = CACTID_PARENT;

	for (argv++; *argv; argv++) {
		char	*arg = *argv;
		char	*opt = strchr(arg, '=');	/* pick off the =VALUE part */

		if (opt) *opt++ = '\0';

		if (STRIMATCH(arg, "-f") ||
			STRIMATCH(arg, "--first")) {
			if (HOSTID_DEFINED(set.start_host_id)) {
				die("ERROR: %s can only be used once", arg);
			}

			set.start_host_id = atoi(opt = getarg(opt, &argv));

			if (!HOSTID_DEFINED(set.start_host_id)) {
				die("ERROR: '%s=%s' is invalid first-host ID", arg, opt);
			}
		}

		else if (STRIMATCH(arg, "-l") ||
				 STRIMATCH(arg, "--last")) {
			if (HOSTID_DEFINED(set.end_host_id)) {
				die("ERROR: %s can only be used once", arg);
			}

			set.end_host_id = atoi(opt = getarg(opt, &argv));

			if (!HOSTID_DEFINED(set.end_host_id)) {
				die("ERROR: '%s=%s' is invalid last-host ID", arg, opt);
			}
		}

		else if (STRIMATCH(arg, "-p") ||
				 STRIMATCH(arg, "--poller")) {
			set.poller_id = atoi(getarg(opt, &argv));
		}

		else if (STRIMATCH(arg, "-h") ||
				 STRIMATCH(arg, "-v") ||
				 STRIMATCH(arg, "--help") ||
				 STRIMATCH(arg, "--version")) {
			display_help();

			exit(EXIT_SUCCESS);
		}

		else if (STRIMATCH(arg, "-O") ||
				 STRIMATCH(arg, "--option")) {
			char	*setting = getarg(opt, &argv);
			char	*value   = strchr(setting, ':');

			if (*value) {
				*value++ = '\0';
			}else{
				die("ERROR: -O requires setting:value");
			}

			set_option(setting, value);
		}

		else if (STRIMATCH(arg, "-R") ||
				 STRIMATCH(arg, "--readonly") ||
				 STRIMATCH(arg, "--read-only")) {
			set.SQL_readonly = TRUE;
		}

		else if (STRIMATCH(arg, "-C") ||
				 STRIMATCH(arg, "--conf")) {
			conf_file = strdup(getarg(opt, &argv));
		}

		else if (STRIMATCH(arg, "-S") ||
				 STRIMATCH(arg, "--stdout")) {
			set_option("log_destination", "STDOUT");
		}

		else if (STRIMATCH(arg, "-L") ||
				 STRIMATCH(arg, "--log")) {
			set_option("log_destination", getarg(opt, &argv));
		}

		else if (STRIMATCH(arg, "-V") ||
				 STRIMATCH(arg, "--verbosity")) {
			set_option("log_verbosity", getarg(opt, &argv));
		}

		else if (STRIMATCH(arg, "--snmponly") ||
				 STRIMATCH(arg, "--snmp-only")) {
			set.snmponly = TRUE;
		}

		else if (!HOSTID_DEFINED(set.start_host_id) && all_digits(arg)) {
			set.start_host_id = atoi(arg);
		}

		else if (!HOSTID_DEFINED(set.end_host_id) && all_digits(arg)) {
			set.end_host_id = atoi(arg);
		}

		else {
			die("ERROR: %s is an unknown command-line parameter", arg);
		}
	}

	/* we require either both the first and last hosts, or niether host */
	if (HOSTID_DEFINED(set.start_host_id) != HOSTID_DEFINED(set.end_host_id)) {
		die("ERROR: must provide both -f/-l, or neither");
	}

	if (set.start_host_id > set.end_host_id) {
		die("ERROR: Invalid row spec; first host_id must be less than the second");
	}

	/* read configuration file to establish local environment */
	if (conf_file) {
		if ((read_cactid_config(conf_file)) < 0) {
			die("ERROR: Could not read config file: %s\n", conf_file);
		}
	}else{
		if (!(conf_file = calloc(1, BUFSIZE))) {
			die("ERROR: Fatal malloc error: cactid.c conf_file!\n");
		}

		for (i=0; i<CONFIG_PATHS; i++) {
			snprintf(conf_file, BUFSIZE-1, "%s%s", config_paths[i], DEFAULT_CONF_FILE);

			if (read_cactid_config(conf_file) >= 0) {
				break;
			}

			if (i == CONFIG_PATHS-1) {
				snprintf(conf_file, BUFSIZE-1, "%s%s", config_paths[0], DEFAULT_CONF_FILE);
			}
		}
	}

	/* read settings table from the database to further establish environment */
	read_config_options();

	/* set the poller interval for those who use less than 5 minute intervals */
	if (set.poller_interval == 0) {
		poller_interval = 300;
	}else {
		poller_interval = set.poller_interval;
	}

	/* calculate the external_tread_sleep value */
	internal_thread_sleep = EXTERNAL_THREAD_SLEEP * set.num_parent_processes / 2;

	if (set.log_level == POLLER_VERBOSITY_DEBUG) {
		CACTID_LOG_DEBUG(("CACTID: Version %s starting\n", VERSION));
	}else{
		printf("CACTID: Version %s starting\n", VERSION);
	}

	/* connect to database */
	db_connect(set.dbdb, &mysql);

	/* initialize SNMP */
	CACTID_LOG_DEBUG(("CACTID: Initializing Net-SNMP API\n"));
	snmp_cactid_init();

	/* initialize PHP if required */
	CACTID_LOG_DEBUG(("CACTID: Initializing PHP Script Server\n"));

	/* tell cactid that it is parent, and set the poller id */
	set.parent_fork = CACTID_PARENT;
	set.poller_id = 0;

	/* initialize the script server */
	if (set.php_required) {
		php_init(PHP_INIT);
		set.php_initialized = TRUE;
		set.php_current_server = 0;
	}

	/* obtain the list of hosts to poll */
	{
	char querybuf[256], *qp = querybuf;

	qp += sprintf(qp, "SELECT id FROM host");
	qp += sprintf(qp, " WHERE disabled=''");
	qp += append_hostrange(qp, "id");	/* AND id BETWEEN a AND b */
	qp += sprintf(qp, " ORDER BY id");

	result = db_query(&mysql, querybuf);
	}

	num_rows = mysql_num_rows(result) + 1; /* add 1 for host = 0 */

	if (!(threads = (pthread_t *)malloc(num_rows * sizeof(pthread_t)))) {
		die("ERROR: Fatal malloc error: cactid.c threads!\n");
	}

	if (!(ids = (int *)malloc(num_rows * sizeof(int)))) {
		die("ERROR: Fatal malloc error: cactid.c host id's!\n");
	}

	/* initialize threads and mutexes */
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

	init_mutexes();

	CACTID_LOG_DEBUG(("DEBUG: Initial Value of Active Threads is %i\n", active_threads));

	/* tell fork processes that they are now active */
	set.parent_fork = CACTID_FORK;

	/* loop through devices until done */
	while ((device_counter < num_rows) && (canexit == 0)) {
		mutex_status = thread_mutex_trylock(LOCK_THREAD);

		switch (mutex_status) {
		case 0:
			if (last_active_threads != active_threads) {
				last_active_threads = active_threads;
			}

			while ((active_threads < set.threads) && (device_counter < num_rows)) {
				if (device_counter > 0) {
					mysql_row = mysql_fetch_row(result);
					host_id = atoi(mysql_row[0]);
					ids[device_counter] = host_id;
				}else{
					ids[device_counter] = 0;
				}

				/* create child process */
				thread_status = pthread_create(&threads[device_counter], &attr, child, &ids[device_counter]);

				switch (thread_status) {
					case 0:
						CACTID_LOG_DEBUG(("DEBUG: Valid Thread to be Created\n"));

						device_counter++;
						active_threads++;

						CACTID_LOG_DEBUG(("DEBUG: The Value of Active Threads is %i\n", active_threads));

						break;
					case EAGAIN:
						CACTID_LOG(("ERROR: The System Lacked the Resources to Create a Thread\n"));
						break;
					case EFAULT:
						CACTID_LOG(("ERROR: The Thread or Attribute Was Invalid\n"));
						break;
					case EINVAL:
						CACTID_LOG(("ERROR: The Thread Attribute is Not Initialized\n"));
						break;
					default:
						CACTID_LOG(("ERROR: Unknown Thread Creation Error\n"));
						break;
				}
				usleep(internal_thread_sleep);

				/* get current time and exit program if time limit exceeded */
				if (poller_counter >= 20) {
					current_time = get_time_as_double();

					if ((current_time - begin_time + 6) > poller_interval) {
						CACTID_LOG(("ERROR: Cactid Timed Out While Processing Hosts Internal\n"));
						canexit = 1;
						break;
					}

					poller_counter = 0;
				}else{
					poller_counter++;
				}
			}

			thread_mutex_unlock(LOCK_THREAD);

			break;
		case EDEADLK:
			CACTID_LOG(("ERROR: Deadlock Occured\n"));
			break;
		case EBUSY:
			break;
		case EINVAL:
			CACTID_LOG(("ERROR: Attempt to Unlock an Uninitialized Mutex\n"));
			break;
		case EFAULT:
			CACTID_LOG(("ERROR: Attempt to Unlock an Invalid Mutex\n"));
			break;
		default:
			CACTID_LOG(("ERROR: Unknown Mutex Lock Error Code Returned\n"));
			break;
		}

		usleep(internal_thread_sleep);

		/* get current time and exit program if time limit exceeded */
		if (poller_counter >= 20) {
			current_time = get_time_as_double();

			if ((current_time - begin_time + 6) > poller_interval) {
				CACTID_LOG(("ERROR: Cactid Timed Out While Processing Hosts Internal\n"));
				canexit = 1;
				break;
			}

			poller_counter = 0;
		}else{
			poller_counter++;
		}
	}

	/* wait for all threads to complete */
	while (canexit == 0) {
		if (thread_mutex_trylock(LOCK_THREAD) == 0) {
			if (last_active_threads != active_threads) {
				last_active_threads = active_threads;
			}

			if (active_threads == 0) {
				canexit = 1;
			}

			thread_mutex_unlock(LOCK_THREAD);
		}

		usleep(EXTERNAL_THREAD_SLEEP);

		/* get current time and exit program if time limit exceeded */
		if (poller_counter >= 20) {
			current_time = get_time_as_double();

			if ((current_time - begin_time + 6) > poller_interval) {
				CACTID_LOG(("ERROR: Cactid Timed Out While Processing Hosts Internal\n"));
				canexit = 1;
				break;
			}

			poller_counter = 0;
		}else{
			poller_counter++;
		}
	}

	/* tell Cactid that it is now parent */
	set.parent_fork = CACTID_PARENT;

	/* print out stats */
	gettimeofday(&now, NULL);

	/* update the db for |data_time| on graphs */
	db_insert(&mysql, "replace into settings (name,value) values ('date',NOW())");
	db_insert(&mysql, "insert into poller_time (poller_id, start_time, end_time) values (0, NOW(), NOW())");

	/* cleanup and exit program */
	pthread_attr_destroy(&attr);

	CACTID_LOG_DEBUG(("DEBUG: Thread Cleanup Complete\n"));

	/* close the php script server */
	if (set.php_required) {
		php_close(PHP_INIT);
	}

	CACTID_LOG_DEBUG(("DEBUG: PHP Script Server Pipes Closed\n"));

	/* free malloc'd variables */
	free(threads);
	free(ids);
	free(conf_file);

	CACTID_LOG_DEBUG(("DEBUG: Allocated Variable Memory Freed\n"));

	/* shutdown SNMP */
	snmp_cactid_close();

	CACTID_LOG_DEBUG(("CACTID: Net-SNMP API Shutdown Completed\n"));

	/* close mysql */
	mysql_free_result(result);
	mysql_close(&mysql);

	CACTID_LOG_DEBUG(("DEBUG: MYSQL Free & Close Completed\n"));

	/* finally add some statistics to the log and exit */
	end_time = TIMEVAL_TO_DOUBLE(now);

	CACTID_LOG_MEDIUM(("Time: %.4f s, Threads: %i, Hosts: %i\n", (end_time - begin_time), set.threads, num_rows));

	exit(EXIT_SUCCESS);
}