/*! \fn void snmp_spine_init() * \brief wrapper function for init_snmp * * Initializes snmp for the given application ID * */ void snmp_spine_init(void) { #ifdef USE_NET_SNMP /* Only do numeric output */ #ifdef NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_NUMERIC_ENUM, 1); #endif /* Prevent update of the snmpapp.conf file */ #ifdef NETSNMP_DS_LIB_DONT_PERSIST_STATE netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PERSIST_STATE, 1); #endif /* Prevent update of the snmpapp.conf file */ #ifdef NETSNMP_DS_LIB_DISABLE_PERSISTENT_LOAD netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DISABLE_PERSISTENT_LOAD, 1); #endif #ifdef NETSNMP_DS_LIB_DONT_PRINT_UNITS netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_PRINT_UNITS, 1); #endif netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICK_PRINT, 1); netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_QUICKE_PRINT, 1); netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_PRINT_BARE_VALUE, 1); netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_NUMERIC_TIMETICKS, 1); #ifdef PACKAGE_VERSION /* check that the headers we compiled with match the library we linked with - apparently not defined in UCD-SNMP... */ SPINE_LOG_DEBUG(("DEBUG: SNMP Header Version is %s\n", PACKAGE_VERSION)); SPINE_LOG_DEBUG(("DEBUG: SNMP Library Version is %s\n", netsnmp_get_version())); if(STRMATCH(PACKAGE_VERSION,netsnmp_get_version())) { init_snmp("spine"); }else{ /* report the error and quit spine */ die("ERROR: SNMP Library Version Mismatch (%s vs %s)",PACKAGE_VERSION,netsnmp_get_version()); } #else SPINE_LOG_DEBUG(("DEBUG: Issues with SNMP Header Version information, assuming old version of Net-SNMP.\n")); init_snmp("spine"); #endif #else ds_set_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT, 1); ds_set_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_BARE_VALUE, 1); ds_set_boolean(DS_LIBRARY_ID, DS_LIB_NUMERIC_TIMETICKS, 1); init_snmp("spine"); #endif }
/*! \fn void php_close(int php_process) * \brief close the php script server process * \param php_process the process to close or PHP_INIT * * This function will take an input parameter of either a specially coded * PHP_INIT parameter or an integer stating the process number. With that * information is will close and/or terminate the child PHP Script Server * process and then return to the calling function. * * TODO: Make ending of the child process not be reliant on SIG_TERM in cases * where the child process is hung for one reason or another. * */ void php_close(int php_process) { int i; int num_processes; ssize_t bytes; if (php_process == PHP_INIT) { num_processes = set.php_servers; } else { num_processes = 1; } for(i = 0; i < num_processes; i++) { php_t *phpp; SPINE_LOG_DEBUG(("DEBUG: SS[%i] Script Server Shutdown Started", i)); /* tell the script server to close */ if (php_process == PHP_INIT) { phpp = &php_processes[i]; } else { phpp = &php_processes[php_process]; } /* If we still have a valid write pipe, tell PHP to close down * by sending a "quit" message, then closing the input channel * so it gets an EOF. * * Then we wait a moment before actually killing it to allow for * a clean shutdown. */ if (phpp->php_write_fd >= 0) { static const char quit[] = "quit\r\n"; bytes = write(phpp->php_write_fd, quit, strlen(quit)); close(phpp->php_write_fd); phpp->php_write_fd = -1; /* wait before killing php */ #ifndef SOLAR_THREAD usleep(50000); /* 50 msec */ #endif } /* only try to kill the process if the PID looks valid. * Trying to kill a negative number is bad news (it's * a process group leader), and PID 1 is "init". */ if (phpp->php_pid > 1) { /* end the php script server process */ kill(phpp->php_pid, SIGTERM); /* reset this PID variable? */ } /* close file descriptors */ close(phpp->php_read_fd); phpp->php_read_fd = -1; } }
/*! \fn MYSQL_RES *db_query(MYSQL *mysql, const char *query) * \brief executes a query and returns a pointer to the result set. * \param mysql the database connection object * \param query the database query to execute * * This function will execute the SQL statement specified in the query variable. * * \return MYSQL_RES a MySQL result structure * */ MYSQL_RES *db_query(MYSQL *mysql, const char *query) { MYSQL_RES *mysql_res = 0; int error = 0; int error_count = 0; char query_frag[BUFSIZE]; /* save a fragment just in case */ snprintf(query_frag, BUFSIZE, "%s", query); /* show the sql query */ SPINE_LOG_DEBUG(("DEBUG: SQL:'%s'", query_frag)); while (1) { if (mysql_query(mysql, query)) { error = mysql_errno(mysql); if ((error == 1213) || (error == 1205)) { #ifndef SOLAR_THREAD usleep(50000); #endif error_count++; if (error_count > 30) { die("FATAL: Too many Lock/Deadlock errors occurred!, SQL Fragment:'%s'\n", query_frag); } continue; }else{ die("FATAL: MySQL Error:'%i', Message:'%s'", error, mysql_error(mysql)); } }else{ mysql_res = mysql_store_result(mysql); break; } } return mysql_res; }
/*! \fn int db_insert(MYSQL *mysql, const char *query) * \brief inserts a row or rows in a database table. * \param mysql the database connection object * \param query the database query to execute * * Unless the SQL_readonly boolean is set to TRUE, the function will execute * the SQL statement specified in the query variable. * * \return TRUE if successful, or FALSE if not. * */ int db_insert(MYSQL *mysql, const char *query) { int error; int error_count = 0; char query_frag[BUFSIZE]; /* save a fragment just in case */ snprintf(query_frag, BUFSIZE, "%s", query); /* show the sql query */ if (set.log_level == 5) { SPINE_LOG_DEBUG(("DEBUG: SQL:'%s'", query_frag)); } while(1) { if (set.SQL_readonly == FALSE) { if (mysql_query(mysql, query)) { error = mysql_errno(mysql); if ((error == 1213) || (error == 1205)) { usleep(50000); error_count++; if (error_count > 30) { SPINE_LOG(("ERROR: Too many Lock/Deadlock errors occurred!, SQL Fragment:'%s'\n", query_frag)); return FALSE; } continue; }else{ SPINE_LOG(("ERROR: SQL Failed! Error:'%i', Message:'%s', SQL Fragment:'%s'\n", error, mysql_error(mysql), query_frag)); return FALSE; } }else{ return TRUE; } }else{ return TRUE; } } }
int hasCaps() { #ifdef HAVE_LCAP cap_t caps; cap_value_t capval; cap_flag_value_t capflag; caps = cap_from_text("cap_net_raw=eip"); if (caps == NULL) { SPINE_LOG_DEBUG(("WARNING: cap_from_text failed.")); return FALSE; } for (capval=0; ;capval++) { if (cap_get_flag(caps, capval, CAP_EFFECTIVE, &capflag)) break; if (capflag != CAP_SET) return FALSE; } return TRUE; #else return FALSE; #endif }
/*! \fn void read_config_options(void) * \brief Reads the default Spine runtime parameters from the database and set's the global array * * load default values from the database for poller processing * */ void read_config_options() { MYSQL mysql; MYSQL_RES *result; int num_rows; char web_root[BUFSIZE]; char sqlbuf[SMALL_BUFSIZE], *sqlp = sqlbuf; const char *res; db_connect(set.dbdb, &mysql); /* get the mysql server version */ set.dbversion = 0; if ((res = getglobalvariable(&mysql, "version")) != 0 ) { set.dbversion = atoi(res); } /* get logging level from database - overrides spine.conf */ if ((res = getsetting(&mysql, "log_verbosity")) != 0 ) { const int n = atoi(res); if (n != 0) set.log_level = n; } /* determine script server path operation and default log file processing */ if ((res = getsetting(&mysql, "path_webroot")) != 0 ) { snprintf(set.path_php_server, SMALL_BUFSIZE, "%s/script_server.php", res); snprintf(web_root, BUFSIZE, "%s", res); } /* determine logfile path */ if ((res = getsetting(&mysql, "path_cactilog")) != 0 ) { if (strlen(res) != 0) { snprintf(set.path_logfile, SMALL_BUFSIZE, "%s", res); }else{ if (strlen(web_root) != 0) { snprintf(set.path_logfile, SMALL_BUFSIZE, "%s/log/cacti.log", web_root); }else{ set.path_logfile[0] ='\0'; } } }else{ snprintf(set.path_logfile, SMALL_BUFSIZE, "%s/log/cacti.log", web_root); } /* log the path_webroot variable */ SPINE_LOG_DEBUG(("DEBUG: The path_php_server variable is %s", set.path_php_server)); /* log the path_cactilog variable */ SPINE_LOG_DEBUG(("DEBUG: The path_cactilog variable is %s", set.path_logfile)); /* determine log file, syslog or both, default is 1 or log file only */ if ((res = getsetting(&mysql, "log_destination")) != 0 ) { set.log_destination = parse_logdest(res, LOGDEST_FILE); }else{ set.log_destination = LOGDEST_FILE; } /* log the log_destination variable */ SPINE_LOG_DEBUG(("DEBUG: The log_destination variable is %i (%s)", set.log_destination, printable_logdest(set.log_destination))); set.logfile_processed = TRUE; /* get PHP Path Information for Scripting */ if ((res = getsetting(&mysql, "path_php_binary")) != 0 ) { STRNCOPY(set.path_php, res); } /* log the path_php variable */ SPINE_LOG_DEBUG(("DEBUG: The path_php variable is %s", set.path_php)); /* set availability_method */ if ((res = getsetting(&mysql, "availability_method")) != 0 ) { set.availability_method = atoi(res); } /* log the availability_method variable */ SPINE_LOG_DEBUG(("DEBUG: The availability_method variable is %i", set.availability_method)); /* set ping_recovery_count */ if ((res = getsetting(&mysql, "ping_recovery_count")) != 0 ) { set.ping_recovery_count = atoi(res); } /* log the ping_recovery_count variable */ SPINE_LOG_DEBUG(("DEBUG: The ping_recovery_count variable is %i", set.ping_recovery_count)); /* set ping_failure_count */ if ((res = getsetting(&mysql, "ping_failure_count")) != 0) { set.ping_failure_count = atoi(res); } /* log the ping_failure_count variable */ SPINE_LOG_DEBUG(("DEBUG: The ping_failure_count variable is %i", set.ping_failure_count)); /* set ping_method */ if ((res = getsetting(&mysql, "ping_method")) != 0 ) { set.ping_method = atoi(res); } /* log the ping_method variable */ SPINE_LOG_DEBUG(("DEBUG: The ping_method variable is %i", set.ping_method)); /* set ping_retries */ if ((res = getsetting(&mysql, "ping_retries")) != 0 ) { set.ping_retries = atoi(res); } /* log the ping_retries variable */ SPINE_LOG_DEBUG(("DEBUG: The ping_retries variable is %i", set.ping_retries)); /* set ping_timeout */ if ( (res = getsetting(&mysql, "ping_timeout")) != 0 ) { set.ping_timeout = atoi(res); } /* log the ping_timeout variable */ SPINE_LOG_DEBUG(("DEBUG: The ping_timeout variable is %i", set.ping_timeout)); /* set snmp_retries */ if ( (res = getsetting(&mysql, "snmp_retries")) != 0 ) { set.snmp_retries = atoi(res); } /* log the snmp_retries variable */ SPINE_LOG_DEBUG(("DEBUG: The snmp_retries variable is %i", set.snmp_retries)); /* set logging option for errors */ set.log_perror = getboolsetting(&mysql, "log_perror", FALSE); /* log the log_perror variable */ SPINE_LOG_DEBUG(("DEBUG: The log_perror variable is %i", set.log_perror)); /* set logging option for errors */ set.log_pwarn = getboolsetting(&mysql, "log_pwarn", FALSE); /* log the log_pwarn variable */ SPINE_LOG_DEBUG(("DEBUG: The log_pwarn variable is %i", set.log_pwarn)); /* set logging option for errors */ set.boost_redirect = getboolsetting(&mysql, "boost_redirect", FALSE); /* log the log_pwarn variable */ SPINE_LOG_DEBUG(("DEBUG: The boost_redirect variable is %i", set.boost_redirect)); /* set logging option for statistics */ set.log_pstats = getboolsetting(&mysql, "log_pstats", FALSE); /* log the log_pstats variable */ SPINE_LOG_DEBUG(("DEBUG: The log_pstats variable is %i", set.log_pstats)); /* get Cacti defined max threads override spine.conf */ if ((res = getsetting(&mysql, "max_threads")) != 0 ) { set.threads = atoi(res); if (set.threads > MAX_THREADS) { set.threads = MAX_THREADS; } } /* log the threads variable */ SPINE_LOG_DEBUG(("DEBUG: The threads variable is %i", set.threads)); /* get the poller_interval for those who have elected to go with a 1 minute polling interval */ if ((res = getsetting(&mysql, "poller_interval")) != 0 ) { set.poller_interval = atoi(res); }else{ set.poller_interval = 0; } /* log the poller_interval variable */ if (set.poller_interval == 0) { SPINE_LOG_DEBUG(("DEBUG: The polling interval is the system default")); }else{ SPINE_LOG_DEBUG(("DEBUG: The polling interval is %i seconds", set.poller_interval)); } /* get the concurrent_processes variable to determine thread sleep values */ if ((res = getsetting(&mysql, "concurrent_processes")) != 0 ) { set.num_parent_processes = atoi(res); }else{ set.num_parent_processes = 1; } /* log the concurrent processes variable */ SPINE_LOG_DEBUG(("DEBUG: The number of concurrent processes is %i", set.num_parent_processes)); /* get the script timeout to establish timeouts */ if ((res = getsetting(&mysql, "script_timeout")) != 0 ) { set.script_timeout = atoi(res); if (set.script_timeout < 5) { set.script_timeout = 5; } }else{ set.script_timeout = 25; } /* log the script timeout value */ SPINE_LOG_DEBUG(("DEBUG: The script timeout is %i", set.script_timeout)); /* get the number of script server processes to run */ if ((res = getsetting(&mysql, "php_servers")) != 0 ) { set.php_servers = atoi(res); if (set.php_servers > MAX_PHP_SERVERS) { set.php_servers = MAX_PHP_SERVERS; } if (set.php_servers <= 0) { set.php_servers = 1; } }else{ set.php_servers = 2; } /* log the script timeout value */ SPINE_LOG_DEBUG(("DEBUG: The number of php script servers to run is %i", set.php_servers)); /*---------------------------------------------------------------- * determine if the php script server is required by searching for * all the host records for an action of POLLER_ACTION_PHP_SCRIPT_SERVER. * If we get even one, it means we have to deal with the PHP script * server. * */ set.php_required = FALSE; /* assume no */ /* log the requirement for the script server */ if (!strlen(set.host_id_list)) { sqlp = sqlbuf; sqlp += sprintf(sqlp, "SELECT action FROM poller_item"); sqlp += sprintf(sqlp, " WHERE action=%d", POLLER_ACTION_PHP_SCRIPT_SERVER); sqlp += append_hostrange(sqlp, "host_id"); if (set.poller_id_exists) { sqlp += sprintf(sqlp, " AND poller_id=%i", set.poller_id); } sqlp += sprintf(sqlp, " LIMIT 1"); result = db_query(&mysql, sqlbuf); num_rows = mysql_num_rows(result); if (num_rows > 0) set.php_required = TRUE; SPINE_LOG_DEBUG(("DEBUG: StartHost='%i', EndHost='%i', TotalPHPScripts='%i'", set.start_host_id, set.end_host_id, num_rows)); }else{ sqlp = sqlbuf; sqlp += sprintf(sqlp, "SELECT action FROM poller_item"); sqlp += sprintf(sqlp, " WHERE action=%d", POLLER_ACTION_PHP_SCRIPT_SERVER); sqlp += sprintf(sqlp, " AND host_id IN(%s)", set.host_id_list); if (set.poller_id_exists) { sqlp += sprintf(sqlp, " AND poller_id=%i", set.poller_id); } sqlp += sprintf(sqlp, " LIMIT 1"); result = db_query(&mysql, sqlbuf); num_rows = mysql_num_rows(result); if (num_rows > 0) set.php_required = TRUE; SPINE_LOG_DEBUG(("DEBUG: Host List to be polled='%s', TotalPHPScripts='%i'", set.host_id_list, num_rows)); } SPINE_LOG_DEBUG(("DEBUG: The PHP Script Server is %sRequired", set.php_required ? "" : "Not ")); /* determine the maximum oid's to obtain in a single get request */ if ((res = getsetting(&mysql, "max_get_size")) != 0 ) { set.snmp_max_get_size = atoi(res); if (set.snmp_max_get_size > 128) { set.snmp_max_get_size = 128; } }else{ set.snmp_max_get_size = 25; } /* log the snmp_max_get_size variable */ SPINE_LOG_DEBUG(("DEBUG: The Maximum SNMP OID Get Size is %i", set.snmp_max_get_size)); mysql_free_result(result); db_disconnect(&mysql); }
void checkAsRoot() { #ifndef __CYGWIN__ #ifdef SOLAR_PRIV priv_set_t *privset; char *p; /* Get the basic set */ privset = priv_str_to_set("basic", ",", NULL); if (privset == NULL) { die("ERROR: Could not get basic privset from priv_str_to_set()."); } else { p = priv_set_to_str(privset, ',', 0); SPINE_LOG_DEBUG(("DEBUG: Basic privset is: '%s'.", p != NULL ? p : "Unknown")); } /* Add priviledge to send/receive ICMP packets */ if (priv_addset(privset, PRIV_NET_ICMPACCESS) < 0 ) { SPINE_LOG_DEBUG(("Warning: Addition of PRIV_NET_ICMPACCESS to privset failed: '%s'.", strerror(errno))); } /* Compute the set of privileges that are never needed */ priv_inverse(privset); /* Remove the set of unneeded privs from Permitted (and by * implication from Effective) */ if (setppriv(PRIV_OFF, PRIV_PERMITTED, privset) < 0) { SPINE_LOG_DEBUG(("Warning: Dropping privileges from PRIV_PERMITTED failed: '%s'.", strerror(errno))); } /* Remove unneeded priv set from Limit to be safe */ if (setppriv(PRIV_OFF, PRIV_LIMIT, privset) < 0) { SPINE_LOG_DEBUG(("Warning: Dropping privileges from PRIV_LIMIT failed: '%s'.", strerror(errno))); } boolean_t pe = priv_ineffect(PRIV_NET_ICMPACCESS); SPINE_LOG_DEBUG(("DEBUG: Privilege PRIV_NET_ICMPACCESS is: '%s'.", pe != 0 ? "Enabled" : "Disabled")); set.icmp_avail = pe; /* Free the privset */ priv_freeset(privset); free(p); #else if (hasCaps() != TRUE) { seteuid(0); if (geteuid() != 0) { SPINE_LOG_DEBUG(("WARNING: Spine NOT running asroot. This is required if using ICMP. Please run \"chmod +s;chown root:root spine\" to resolve.")); set.icmp_avail = FALSE; }else{ SPINE_LOG_DEBUG(("DEBUG: Spine is running asroot.")); set.icmp_avail = TRUE; seteuid(getuid()); } } else { SPINE_LOG_DEBUG(("DEBUG: Spine has cap_net_raw capability.")); set.icmp_avail = TRUE; } #endif #endif }
/*! \fn int php_init(int php_process) * \brief initialize either a specific PHP Script Server or all of them. * \param php_process the process number to start or PHP_INIT * * This function will either start an individual PHP Script Server process * or all of them if the input parameter is the PHP_INIT constant. The function * will check the status of the process to verify that it is ready to process * scripts as well. * * \return TRUE if the PHP Script Server is know running or FALSE otherwise */ int php_init(int php_process) { int cacti2php_pdes[2]; int php2cacti_pdes[2]; pid_t pid; char poller_id[TINY_BUFSIZE]; char *argv[6]; int cancel_state; char *result_string = 0; int num_processes; int i; int retry_count = 0; /* special code to start all PHP Servers */ if (php_process == PHP_INIT) { num_processes = set.php_servers; }else{ num_processes = 1; } for (i=0; i < num_processes; i++) { SPINE_LOG_DEBUG(("DEBUG: SS[%i] PHP Script Server Routine Starting\n", i)); /* create the output pipes from Spine to php*/ if (pipe(cacti2php_pdes) < 0) { SPINE_LOG(("ERROR: SS[%i] Could not allocate php server pipes\n", i)); return FALSE; } /* create the input pipes from php to Spine */ if (pipe(php2cacti_pdes) < 0) { SPINE_LOG(("ERROR: SS[%i] Could not allocate php server pipes\n", i)); return FALSE; } /* disable thread cancellation from this point forward. */ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_state); /* establish arguments for script server execution */ argv[0] = set.path_php; argv[1] = "-q"; argv[2] = set.path_php_server; argv[3] = "spine"; snprintf(poller_id, TINY_BUFSIZE, "%d", set.poller_id); argv[4] = poller_id; argv[5] = NULL; /* fork a child process */ SPINE_LOG_DEBUG(("DEBUG: SS[%i] PHP Script Server About to FORK Child Process\n", i)); retry: pid = vfork(); /* check the pid status and process as required */ switch (pid) { case -1: /* ERROR: Could not fork() */ switch (errno) { case EAGAIN: if (retry_count < 3) { retry_count++; #ifndef SOLAR_THREAD /* take a moment */ usleep(50000); #endif goto retry; }else{ SPINE_LOG(("ERROR: SS[%i] Cound not fork PHP Script Server Out of Resources\n", i)); } case ENOMEM: if (retry_count < 3) { retry_count++; #ifndef SOLAR_THREAD /* take a moment */ usleep(50000); #endif goto retry; }else{ SPINE_LOG(("ERROR: SS[%i] Cound not fork PHP Script Server Out of Memory\n", i)); } default: SPINE_LOG(("ERROR: SS[%i] Cound not fork PHP Script Server Unknown Reason\n", i)); } close(php2cacti_pdes[0]); close(php2cacti_pdes[1]); close(cacti2php_pdes[0]); close(cacti2php_pdes[1]); SPINE_LOG(("ERROR: SS[%i] Cound not fork PHP Script Server\n", i)); pthread_setcancelstate(cancel_state, NULL); return FALSE; /* NOTREACHED */ case 0: /* SUCCESS: I am now the child */ /* set the standard input/output channels of the new process. */ dup2(cacti2php_pdes[0], STDIN_FILENO); dup2(php2cacti_pdes[1], STDOUT_FILENO); /* close unneeded Pipes */ (void)close(php2cacti_pdes[0]); (void)close(php2cacti_pdes[1]); (void)close(cacti2php_pdes[0]); (void)close(cacti2php_pdes[1]); /* start the php script server process */ execv(argv[0], argv); _exit(127); /* NOTREACHED */ default: /* I am the parent process */ SPINE_LOG_DEBUG(("DEBUG: SS[%i] PHP Script Server Child FORK Success\n", i)); } /* Parent */ /* close unneeded pipes */ close(cacti2php_pdes[0]); close(php2cacti_pdes[1]); if (php_process == PHP_INIT) { php_processes[i].php_pid = pid; php_processes[i].php_write_fd = cacti2php_pdes[1]; php_processes[i].php_read_fd = php2cacti_pdes[0]; }else{ php_processes[php_process].php_pid = pid; php_processes[php_process].php_write_fd = cacti2php_pdes[1]; php_processes[php_process].php_read_fd = php2cacti_pdes[0]; } /* restore caller's cancellation state. */ pthread_setcancelstate(cancel_state, NULL); /* check pipe to insure startup took place */ if (php_process == PHP_INIT) { result_string = php_readpipe(i); }else{ result_string = php_readpipe(php_process); } if (strstr(result_string, "Started")) { if (php_process == PHP_INIT) { SPINE_LOG_DEBUG(("DEBUG: SS[%i] Confirmed PHP Script Server running\n", i)); php_processes[i].php_state = PHP_READY; }else{ SPINE_LOG_DEBUG(("DEBUG: SS[%i] Confirmed PHP Script Server running\n", php_process)); php_processes[php_process].php_state = PHP_READY; } }else{ SPINE_LOG(("ERROR: SS[%i] Script Server did not start properly return message was: '%s'\n", php_process, result_string)); if (php_process == PHP_INIT) { php_processes[i].php_state = PHP_BUSY; }else{ php_processes[php_process].php_state = PHP_BUSY; } } } free(result_string); return TRUE; }