MYSQL_RES *db_query(MYSQL *mysql, char *query) { MYSQL_RES *mysql_res; int return_code; int retries; int error; thread_mutex_lock(LOCK_MYSQL); retries = 0; error = FALSE; while (retries < 3) { return_code = mysql_query(mysql, query); if (return_code) { cacti_log("MYSQL: ERROR encountered while attempting to retrieve records from query\n"); error = TRUE; } else { mysql_res = mysql_store_result(mysql); error = FALSE; break; } usleep(1000); retries++; } thread_mutex_unlock(LOCK_MYSQL); if (error) { cacti_log("MYSQL: ERROR could not obtain results from database, exiting\n"); exit_cactid(); } return mysql_res; }
void *child(void * arg) { extern int active_threads; int host_id = *(int *) arg; char logmessage[LOGSIZE]; if (set.verbose == POLLER_VERBOSITY_DEBUG) { snprintf(logmessage, LOGSIZE, "DEBUG: In Poller, About to Start Polling of Host\n"); cacti_log(logmessage); } if (active_threads == 1) { if (set.verbose == POLLER_VERBOSITY_DEBUG) { snprintf(logmessage, LOGSIZE, "DEBUG: This is where popen DEADLOCKs errors occur\n"); } } poll_host(host_id); thread_mutex_lock(LOCK_THREAD); active_threads = active_threads - 1; thread_mutex_unlock(LOCK_THREAD); if (set.verbose == POLLER_VERBOSITY_DEBUG) { snprintf(logmessage, LOGSIZE, "DEBUG: The Value of Active Threads is %i\n" ,active_threads); cacti_log(logmessage); } pthread_exit(0); }
int db_connect(char *database, MYSQL *mysql) { char logmessage[LOGSIZE]; int tries; int result; char *hostname; char *socket; if ((hostname = strdup(set.dbhost)) == NULL) { snprintf(logmessage, LOGSIZE-1, "ERROR: malloc(): strdup() failed\n"); cacti_log(logmessage); return (FALSE); } if ((socket = strstr(hostname,":"))) *socket++ = 0x0; /* initialalize my variables */ tries = 10; result = 0; if (set.verbose == POLLER_VERBOSITY_DEBUG) { snprintf(logmessage, LOGSIZE-1, "MYSQL: Connecting to MySQL database '%s' on '%s'...\n", database, set.dbhost); cacti_log(logmessage); } thread_mutex_lock(LOCK_MYSQL); mysql_init(mysql); while (tries > 0){ tries--; if (!mysql_real_connect(mysql, hostname, set.dbuser, set.dbpass, database, set.dbport, socket, 0)) { if (set.verbose == POLLER_VERBOSITY_DEBUG) { snprintf(logmessage, LOGSIZE-1, "MYSQL: Connection Failed: %s\n", mysql_error(mysql)); cacti_log(logmessage); } result = 1; }else{ tries = 0; result = 0; if (set.verbose == POLLER_VERBOSITY_DEBUG) { snprintf(logmessage, LOGSIZE-1, "MYSQL: Connected to MySQL database '%s' on '%s'...\n", database, set.dbhost); cacti_log(logmessage); } } } free(hostname); if (result == 1){ snprintf(logmessage, LOGSIZE-1, "MYSQL: Connection Failed: %s\n", mysql_error(mysql)); cacti_log(logmessage); thread_mutex_unlock(LOCK_MYSQL); exit_cactid(); }else{ thread_mutex_unlock(LOCK_MYSQL); return (0); } }
int db_insert(MYSQL *mysql, char *query) { char logmessage[LOGSIZE]; if (set.verbose == POLLER_VERBOSITY_DEBUG) { snprintf(logmessage, LOGSIZE-1, "DEBUG: SQLCMD: %s\n", query); cacti_log(logmessage); } thread_mutex_lock(LOCK_MYSQL); if (mysql_query(mysql, query)) { snprintf(logmessage, LOGSIZE-1, "ERROR: Problem with MySQL: %s\n", mysql_error(mysql)); cacti_log(logmessage); thread_mutex_unlock(LOCK_MYSQL); return (FALSE); }else{ thread_mutex_unlock(LOCK_MYSQL); return (TRUE); } }
MYSQL_RES *db_query(MYSQL *mysql, char *query) { MYSQL_RES *mysql_res; int return_code; thread_mutex_lock(LOCK_MYSQL); return_code = mysql_query(mysql, query); if (return_code) { cacti_log("MYSQL: ERROR encountered while attempting to retrieve records from query\n"); thread_mutex_unlock(LOCK_MYSQL); exit_cactid(); }else{ mysql_res = mysql_store_result(mysql); thread_mutex_unlock(LOCK_MYSQL); } return mysql_res; }
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); }
void poll_host(int host_id) { char query1[BUFSIZE]; char query2[BUFSIZE]; char *query3; char query4[BUFSIZE]; char errstr[512]; int num_rows; int host_status; int assert_fail = 0; char *poll_result = NULL; char logmessage[LOGSIZE]; char update_sql[BUFSIZE]; reindex_t *reindex; target_t *entry; host_t *host; ping_t *ping; MYSQL mysql; MYSQL_RES *result; MYSQL_ROW row; /* allocate host and ping structures with appropriate values */ host = (host_t *) malloc(sizeof(host_t)); ping = (ping_t *) malloc(sizeof(ping_t)); #ifndef OLD_MYSQL mysql_thread_init(); #endif snprintf(query1, sizeof(query1), "select action,hostname,snmp_community,snmp_version,snmp_username,snmp_password,rrd_name,rrd_path,arg1,arg2,arg3,local_data_id,rrd_num,snmp_port,snmp_timeout from poller_item where host_id=%i order by rrd_path,rrd_name", host_id); snprintf(query2, sizeof(query2), "select id, hostname,snmp_community,snmp_version,snmp_port,snmp_timeout,status,status_event_count,status_fail_date,status_rec_date,status_last_error,min_time,max_time,cur_time,avg_time,total_polls,failed_polls,availability from host where id=%i", host_id); snprintf(query4, sizeof(query4), "select data_query_id,action,op,assert_value,arg1 from poller_reindex where host_id=%i", host_id); db_connect(set.dbdb, &mysql); /* get data about this host */ result = db_query(&mysql, query2); num_rows = (int)mysql_num_rows(result); if (num_rows != 1) { snprintf(logmessage, LOGSIZE, "Host[%i] ERROR: Unknown Host ID", host_id); cacti_log(logmessage); return; } row = mysql_fetch_row(result); /* populate host structure */ host->id = atoi(row[0]); if (row[1] != NULL) snprintf(host->hostname, sizeof(host->hostname), "%s", row[1]); if (row[2] != NULL) snprintf(host->snmp_community, sizeof(host->snmp_community), "%s", row[2]); host->snmp_version = atoi(row[3]); host->snmp_port = atoi(row[4]); host->snmp_timeout = atoi(row[5]); if (row[6] != NULL) host->status = atoi(row[6]); host->status_event_count = atoi(row[7]); snprintf(host->status_fail_date, sizeof(host->status_fail_date), "%s", row[8]); snprintf(host->status_rec_date, sizeof(host->status_rec_date), "%s", row[9]); snprintf(host->status_last_error, sizeof(host->status_last_error), "%s", row[10]); host->min_time = atof(row[11]); host->max_time = atof(row[12]); host->cur_time = atof(row[13]); host->avg_time = atof(row[14]); host->total_polls = atoi(row[15]); host->failed_polls = atoi(row[16]); host->availability = atof(row[17]); host->ignore_host = 0; /* initialize SNMP */ snmp_host_init(host); /* perform a check to see if the host is alive by polling it's SysDesc * if the host down from an snmp perspective, don't poll it. * function sets the ignore_host bit */ if ((set.availability_method == AVAIL_SNMP) && (host->snmp_community == "")) { update_host_status(HOST_UP, host, ping, set.availability_method); if (set.verbose >= POLLER_VERBOSITY_MEDIUM) { snprintf(logmessage, LOGSIZE, "Host[%s] No host availability check possible for '%s'\n", host->id, host->hostname); cacti_log(logmessage); } } else { if (ping_host(host, ping) == HOST_UP) { update_host_status(HOST_UP, host, ping, set.availability_method); } else { host->ignore_host = 1; update_host_status(HOST_DOWN, host, ping, set.availability_method); } } /* update host table */ snprintf(update_sql, sizeof(update_sql), "update host set status='%i',status_event_count='%i', status_fail_date='%s',status_rec_date='%s',status_last_error='%s',min_time='%f',max_time='%f',cur_time='%f',avg_time='%f',total_polls='%i',failed_polls='%i',availability='%.4f' where id='%i'\n", host->status, host->status_event_count, host->status_fail_date, host->status_rec_date, host->status_last_error, host->min_time, host->max_time, host->cur_time, host->avg_time, host->total_polls, host->failed_polls, host->availability, host->id); db_insert(&mysql, update_sql); /* do the reindex check for this host */ if (!host->ignore_host) { reindex = (reindex_t *) malloc(sizeof(reindex_t)); result = db_query(&mysql, query4); num_rows = (int)mysql_num_rows(result); if (num_rows > 0) { if (set.verbose == POLLER_VERBOSITY_DEBUG) { snprintf(logmessage, LOGSIZE, "Host[%i] RECACHE: Processing %i items in the auto reindex cache for '%s'\n", host->id, num_rows, host->hostname); cacti_log(logmessage); } while ((row = mysql_fetch_row(result))) { assert_fail = 0; reindex->data_query_id = atoi(row[0]); reindex->action = atoi(row[1]); if (row[2] != NULL) snprintf(reindex->op, sizeof(reindex->op), "%s", row[2]); if (row[3] != NULL) snprintf(reindex->assert_value, sizeof(reindex->assert_value), "%s", row[3]); if (row[4] != NULL) snprintf(reindex->arg1, sizeof(reindex->arg1), "%s", row[4]); switch(reindex->action) { case POLLER_ACTION_SNMP: /* snmp */ poll_result = snmp_get(host, reindex->arg1); break; case POLLER_ACTION_SCRIPT: /* script (popen) */ poll_result = exec_poll(host, reindex->arg1); break; } /* assume ok if host is up and result wasn't obtained */ if (!strcmp(poll_result,"U")) { assert_fail = 0; } else if ((!strcmp(reindex->op, "=")) && (strcmp(reindex->assert_value,poll_result) != 0)) { snprintf(logmessage, LOGSIZE, "ASSERT: '%s=%s' failed. Recaching host '%s', data query #%i\n", reindex->assert_value, poll_result, host->hostname, reindex->data_query_id); cacti_log(logmessage); query3 = (char *)malloc(128); snprintf(query3, 128, "insert into poller_command (poller_id,time,action,command) values (0,NOW(),%i,'%i:%i')", POLLER_COMMAND_REINDEX, host_id, reindex->data_query_id); db_insert(&mysql, query3); free(query3); assert_fail = 1; } else if ((!strcmp(reindex->op, ">")) && (strtoll(reindex->assert_value, (char **)NULL, 10) <= strtoll(poll_result, (char **)NULL, 10))) { snprintf(logmessage, LOGSIZE, "ASSERT: '%s>%s' failed. Recaching host '%s', data query #%i\n", reindex->assert_value, poll_result, host->hostname, reindex->data_query_id); cacti_log(logmessage); query3 = (char *)malloc(128); snprintf(query3, 128, "insert into poller_command (poller_id,time,action,command) values (0,NOW(),%i,'%i:%i')", POLLER_COMMAND_REINDEX, host_id, reindex->data_query_id); db_insert(&mysql, query3); free(query3); assert_fail = 1; } else if ((!strcmp(reindex->op, "<")) && (strtoll(reindex->assert_value, (char **)NULL, 10) >= strtoll(poll_result, (char **)NULL, 10))) { snprintf(logmessage, LOGSIZE, "ASSERT: '%s<%s' failed. Recaching host '%s', data query #%i\n", reindex->assert_value, poll_result, host->hostname, reindex->data_query_id); cacti_log(logmessage); query3 = (char *)malloc(128); snprintf(query3, 128, "insert into poller_command (poller_id,time,action,command) values (0,NOW(),%i,'%i:%i')", POLLER_COMMAND_REINDEX, host_id, reindex->data_query_id); db_insert(&mysql, query3); free(query3); assert_fail = 1; } /* update 'poller_reindex' with the correct information if: * 1) the assert fails * 2) the OP code is > or < meaning the current value could have changed without causing * the assert to fail */ if ((assert_fail == 1) || (!strcmp(reindex->op, ">")) || (!strcmp(reindex->op, ">"))) { query3 = (char *)malloc(255); snprintf(query3, 255, "update poller_reindex set assert_value='%s' where host_id='%i' and data_query_id='%i' and arg1='%s'", poll_result, host_id, reindex->data_query_id, reindex->arg1); db_insert(&mysql, query3); free(query3); } free(poll_result); } } } /* retreive each hosts polling items from poller cache */ entry = (target_t *) malloc(sizeof(target_t)); result = db_query(&mysql, query1); num_rows = (int)mysql_num_rows(result); while ((row = mysql_fetch_row(result)) && (!host->ignore_host)) { /* initialize monitored object */ entry->target_id = 0; entry->action = atoi(row[0]); if (row[1] != NULL) snprintf(entry->hostname, sizeof(entry->hostname), "%s", row[1]); if (row[2] != NULL) { snprintf(entry->snmp_community, sizeof(entry->snmp_community), "%s", row[2]); } else { snprintf(entry->snmp_community, sizeof(entry->snmp_community), "%s", ""); } entry->snmp_version = atoi(row[3]); if (row[4] != NULL) snprintf(entry->snmp_username, sizeof(entry->snmp_username), "%s", row[4]); if (row[5] != NULL) snprintf(entry->snmp_password, sizeof(entry->snmp_password), "%s", row[5]); if (row[6] != NULL) snprintf(entry->rrd_name, sizeof(entry->rrd_name), "%s", row[6]); if (row[7] != NULL) snprintf(entry->rrd_path, sizeof(entry->rrd_path), "%s", row[7]); if (row[8] != NULL) snprintf(entry->arg1, sizeof(entry->arg1), "%s", row[8]); if (row[9] != NULL) snprintf(entry->arg2, sizeof(entry->arg2), "%s", row[9]); if (row[10] != NULL) snprintf(entry->arg3, sizeof(entry->arg3), "%s", row[10]); entry->local_data_id = atoi(row[11]); entry->rrd_num = atoi(row[12]); entry->snmp_port = atoi(row[13]); entry->snmp_timeout = atoi(row[14]); snprintf(entry->result, sizeof(entry->result), "%s", "U"); if (!host->ignore_host) { switch(entry->action) { case POLLER_ACTION_SNMP: /* raw SNMP poll */ poll_result = snmp_get(host, entry->arg1); snprintf(entry->result, sizeof(entry->result), "%s", poll_result); free(poll_result); if (host->ignore_host) { snprintf(logmessage, LOGSIZE, "Host[%i] ERROR: SNMP timeout detected [%i milliseconds], ignoring host '%s'\n", host_id, host->snmp_timeout, host->hostname); cacti_log(logmessage); snprintf(entry->result, sizeof(entry->result), "%s", "U"); } else { /* remove double or single quotes from string */ strncpy(entry->result, strip_quotes(entry->result), sizeof(entry->result)); /* detect erroneous non-numeric result */ if (!is_numeric(entry->result)) { strncpy(errstr, entry->result,sizeof(errstr)); snprintf(logmessage, LOGSIZE, "Host[%i] WARNING: Result from SNMP not valid. Partial Result: %.20s...\n", host_id, errstr); cacti_log(logmessage); strncpy(entry->result, "U", sizeof(entry->result)); } } if (set.verbose >= POLLER_VERBOSITY_MEDIUM) { snprintf(logmessage, LOGSIZE, "Host[%i] SNMP: v%i: %s, dsname: %s, oid: %s, value: %s\n", host_id, host->snmp_version, host->hostname, entry->rrd_name, entry->arg1, entry->result); cacti_log(logmessage); } break; case POLLER_ACTION_SCRIPT: /* execute script file */ poll_result = exec_poll(host, entry->arg1); snprintf(entry->result, sizeof(entry->result), "%s", poll_result); free(poll_result); /* remove double or single quotes from string */ strncpy(entry->result, strip_quotes(entry->result), sizeof(entry->result)); /* detect erroneous result. can be non-numeric */ if (!validate_result(entry->result)) { strncpy(errstr, (char *) strip_string_crlf(entry->result),sizeof(errstr)); snprintf(logmessage, LOGSIZE, "Host[%i] WARNING: Result from SCRIPT not valid. Partial Result: %.20s...\n", host_id, errstr); cacti_log(logmessage); strncpy(entry->result, "U", sizeof(entry->result)); } if (set.verbose >= POLLER_VERBOSITY_MEDIUM) { snprintf(logmessage, LOGSIZE, "Host[%i] SCRIPT: %s, output: %s\n", host_id, entry->arg1, entry->result); cacti_log(logmessage); } break; case POLLER_ACTION_PHP_SCRIPT_SERVER: /* execute script server */ poll_result = php_cmd(entry->arg1); snprintf(entry->result, sizeof(entry->result), "%s", poll_result); free(poll_result); /* remove double or single quotes from string */ strncpy(entry->result, strip_quotes(entry->result), sizeof(entry->result)); /* detect erroneous result. can be non-numeric */ if (!validate_result(entry->result)) { strncpy(errstr, entry->result, sizeof(errstr)); snprintf(logmessage, LOGSIZE, "Host[%i] WARNING: Result from SERVER not valid. Partial Result: %.20s...\n", host_id, errstr); cacti_log(logmessage); strncpy(entry->result, "U", sizeof(entry->result)); } if (set.verbose >= POLLER_VERBOSITY_MEDIUM) { snprintf(logmessage, LOGSIZE, "Host[%i] SERVER: %s, output: %s\n", host_id, entry->arg1, entry->result); cacti_log(logmessage); } break; default: /* unknown action, generate error */ snprintf(logmessage, LOGSIZE, "Host[%i] ERROR: Unknown Poller Action: %s\n", host_id, entry->arg1); cacti_log(logmessage); break; } } if (entry->result != NULL) { /* format database insert string */ query3 = (char *)malloc(sizeof(entry->result) + sizeof(entry->local_data_id) + 128); snprintf(query3, (sizeof(entry->result) + sizeof(entry->local_data_id) + 128), "insert into poller_output (local_data_id,rrd_name,time,output) values (%i,'%s','%s','%s')", entry->local_data_id, entry->rrd_name, start_datetime, entry->result); db_insert(&mysql, query3); free(query3); } } /* cleanup memory and prepare for function exit */ snmp_host_cleanup(host); free(entry); free(host); free(ping); mysql_free_result(result); #ifndef OLD_MYSQL mysql_thread_end(); #endif mysql_close(&mysql); if (set.verbose == POLLER_VERBOSITY_DEBUG) { snprintf(logmessage, LOGSIZE, "Host[%i] DEBUG: HOST COMPLETE: About to Exit Host Polling Thread Function\n", host_id); cacti_log(logmessage); } }
char *exec_poll(host_t *current_host, char *command) { extern int errno; FILE *cmd_stdout; int cmd_fd; int return_value; int bytes_read; char logmessage[LOGSIZE]; fd_set fds; int rescode, numfds; struct timeval timeout; char *result_string = (char *) malloc(BUFSIZE); /* establish timeout of 5 seconds for pipe response */ timeout.tv_sec = 5; timeout.tv_usec = 0; cmd_fd = nft_popen((char *)clean_string(command), "r"); if (set.verbose == POLLER_VERBOSITY_DEBUG) { snprintf(logmessage, LOGSIZE, "Host[%i] DEBUG: The POPEN returned the following File Descriptor %i\n", current_host->id, cmd_fd); cacti_log(logmessage); } if (cmd_fd >= 0) { /* Initialize File Descriptors to Review for Input/Output */ FD_ZERO(&fds); FD_SET(cmd_fd,&fds); numfds = cmd_fd + 1; /* wait 5 seonds for pipe response */ switch (select(numfds, &fds, NULL, NULL, &timeout)) { case -1: switch (errno) { case EBADF: snprintf(logmessage, LOGSIZE, "Host[%i] ERROR: One or more of the file descriptor sets specified a file descriptor that is not a valid open file descriptor.\n", current_host->id); cacti_log(logmessage); snprintf(result_string, 2, "%s", "U"); break; case EINTR: snprintf(logmessage, LOGSIZE, "Host[%i] ERROR: The function was interrupted before any of the selected events occurred and before the timeout interval expired.\n", current_host->id); cacti_log(logmessage); snprintf(result_string, 2, "%s", "U"); break; case EINVAL: snprintf(logmessage, LOGSIZE, "Host[%i] ERROR: Possible invalid timeout specified in select() statement.\n", current_host->id); cacti_log(logmessage); snprintf(result_string, 2, "%s", "U"); break; default: snprintf(logmessage, LOGSIZE, "Host[%i] ERROR: The script/command select() failed\n", current_host->id); cacti_log(logmessage); snprintf(result_string, 2, "%s", "U"); break; } case 0: snprintf(logmessage, LOGSIZE, "Host[%i] ERROR: The POPEN timed out\n", current_host->id); cacti_log(logmessage); snprintf(result_string, 2, "%s", "U"); break; default: /* get only one line of output, we will ignore the rest */ bytes_read = read(cmd_fd, result_string, BUFSIZE-1); if (bytes_read > 0) { result_string[bytes_read] = '\0'; strip_string_crlf(result_string); } else { snprintf(logmessage, LOGSIZE, "Host[%i] ERROR: Empty result [%s]: '%s'\n", current_host->id, current_host->hostname, command); cacti_log(logmessage); snprintf(result_string, BUFSIZE, "%s", "U"); } } /* close pipe */ nft_pclose(cmd_fd); } else { snprintf(logmessage, LOGSIZE, "Host[%i] ERROR: Problem executing POPEN [%s]: '%s'\n", current_host->id, current_host->hostname, command); cacti_log(logmessage); snprintf(result_string, BUFSIZE, "%s", "U"); } return result_string; }