#include #include #include #include #include #include #include #include #include #include #include #include #include // Debug verbosity #define DEBUG_BASE 1 #define DEBUG_ALL 2 typedef struct { char* hostname; // address of host pid_t helper_pid; // pid of helper('pinger') child process int fail_count; // how many times in a row host was unreachable } host_decl; cfg_t *cfg; // pointer to configuration structure host_decl* hosts=NULL; // structure with hosts' definitions int hosts_count=0; // count of hosts int debug_flag=0; GSM_StateMachine *state_machine=NULL; // structure to interact with mobile phones void log_debug(const char *message,int verbosity) { if (debug_flag>=verbosity) syslog(LOG_INFO,"%s",message); } void log_event(const char *message) { syslog(LOG_INFO,"%s",message); } void* allocate_memory(int bytes) { void* result=malloc(bytes); if (result==NULL) { log_event("Error: malloc failed"); exit(EXIT_FAILURE); } } void check_gammu_error(GSM_Error err) { if (err == ERR_NONE) { return; } char tmp[150]; sprintf(tmp,"gammu failure: %s\n", GSM_ErrorString(err)); log_event(tmp); exit(EXIT_FAILURE); } void init() { // Initialize config parsing library cfg_opt_t opts[] = { CFG_STR_LIST("hosts", "{}", CFGF_NONE), CFG_SIMPLE_INT("debug", &debug_flag), CFG_END() }; cfg = cfg_init(opts, CFGF_NONE); // check if config file is valid and parse it if (cfg_parse(cfg, "/etc/yasnd.conf") == CFG_PARSE_ERROR) { log_event("Error parsing config file"); exit(EXIT_FAILURE); } // hosts' array must not be empty hosts_count=cfg_size(cfg,"hosts"); if (hosts_count==0) { log_event("Error: no hosts to check defined in config file"); exit(EXIT_FAILURE); } // allocate memory for hosts array... hosts=allocate_memory(hosts_count*sizeof(host_decl)); // ...and fill it with config file content for (int i=0;ihostname); log_debug(tmp,DEBUG_BASE); execl("/bin/ping","/bin/ping","-c 4","-n",host->hostname,(char*) 0); // STUB: check result of exec call exit(EXIT_SUCCESS); } // Save child's pid host->helper_pid=pid; } void loop_function() { for (int i=0;i 0) { if (WIFEXITED(pid_status)) { char tmp[50]; sprintf(tmp, "Finished child %d with result %d", result, WEXITSTATUS(pid_status)); log_debug(tmp,DEBUG_ALL); // if host is alive - reset failure counter // otherwise - increment it if (WEXITSTATUS(pid_status) == 0) hosts[i].fail_count=0; else hosts[i].fail_count++; } } } } void termination_handler(int signum) { log_event("SIGTERM captured, daemon stopping"); closelog(); // free config structure cfg_free(cfg); // free gammu structure GSM_FreeStateMachine(state_machine); // free hosts structures memory if (hosts!=NULL) free(hosts); exit(EXIT_SUCCESS); } int main(void) { /* Our process ID and Session ID */ pid_t pid, sid; /* Fork off the parent process */ pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); } /* If we got a good PID, then we can exit the parent process. */ if (pid > 0) { exit(EXIT_SUCCESS); } /* Change the file mode mask */ umask(0); /* Open any logs here */ openlog("yasnd", LOG_PID|LOG_CONS, LOG_USER); /* Create a new SID for the child process */ sid = setsid(); if (sid < 0) { /* Log the failure */ exit(EXIT_FAILURE); } /* Change the current working directory */ if ((chdir("/")) < 0) { /* Log the failure */ exit(EXIT_FAILURE); } /* Close out the standard file descriptors */ close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); // Set signal handler for SIGTERM signal(SIGTERM, termination_handler); // Init apropriate structures init(); /* The Big Loop */ while (1) { loop_function(); // sleep(60); /* wait 60 seconds */ exit(EXIT_SUCCESS); } exit(EXIT_SUCCESS); }