int servant_cluster(const char *diskname, int mode, const void* argp) { enum cluster_type_e cluster_stack = get_cluster_type(); crm_system_name = strdup("sbd:cluster"); cl_log(LOG_INFO, "Monitoring %s cluster health", name_for_cluster_type(cluster_stack)); set_proc_title("sbd: watcher: Cluster"); sbd_membership_connect(); /* stonith_our_uname = cluster.uname; */ /* stonith_our_uuid = cluster.uuid; */ mainloop = g_main_new(FALSE); notify_timer = g_timeout_add(timeout_loop * 1000, notify_timer_cb, NULL); mainloop_add_signal(SIGTERM, cluster_shutdown); mainloop_add_signal(SIGINT, cluster_shutdown); g_main_run(mainloop); g_main_destroy(mainloop); clean_up(0); return 0; /* never reached */ }
/* Character generator */ void chargen_stream (int s, struct servtab *sep) { int len; char *rs, text[LINESIZ + 2]; set_proc_title (sep->se_service, s); if (!endring) { initring (); rs = ring; } text[LINESIZ] = '\r'; text[LINESIZ + 1] = '\n'; for (rs = ring;;) { if ((len = endring - rs) >= LINESIZ) memmove (text, rs, LINESIZ); else { memmove (text, rs, len); memmove (text + len, ring, LINESIZ - len); } if (++rs == endring) rs = ring; if (write (s, text, sizeof text) != sizeof text) break; } exit (0); }
/* ------------------------------------------------------------- ** ** Sets up the control connection to the server and initialises ** session info. ** ------------------------------------------------------------- */ void init_session(int fd, struct sockaddr_in source) { info = init_info(fd, source); write_log(INFO, "Connect from %s", sstr_buf(addr2name(info->client_control.address.sin_addr))); /*FIXME have a login function which deals with ntp and cache */ ccp_changedest(); ntp_changedest(); info->final_server_address = info->server_control.address; write_log(INFO, "... to %s(%s)", inet_ntoa(info->final_server_address.sin_addr), sstr_buf(info->server_name)); #ifdef ENABLE_CHANGEPROC set_proc_title("frox: %s <-> %s", inet_ntoa(info->client_control.address.sin_addr), inet_ntoa(info->final_server_address.sin_addr)); #endif connect_to_server(); ntp_senduser(); run_proxy(); }
pid_t play_sound(char *sound_cmd, char *soundfile) { pid_t sound_pid; char command[600]; sound_pid=0; if (strlen(sound_cmd)>3 && strlen(soundfile)>1) { if (last_sound_pid==0) { // Create a new process to run in sound_pid = fork(); if (sound_pid!=-1) { if(sound_pid==0) { // This is the child process // Go back to default signal handler instead of // calling restart() on SIGHUP (void) signal(SIGHUP,SIG_DFL); // Change the name of the new child process. So // far this only works for "ps" listings, not // for "top". This code only works on Linux. // For BSD use setproctitle(3), NetBSD can use // setprogname(2). #ifdef __linux__ init_set_proc_title(my_argc, my_argv, my_envp); set_proc_title("%s", "festival process (xastir)"); //fprintf(stderr,"DEBUG: %s\n", Argv[0]); #endif // __linux__ xastir_snprintf(command, sizeof(command), "%s %s/%s", sound_cmd, SOUND_DIR, soundfile); if (system(command) != 0) {} // We don't care whether it succeeded exit(0); // Exits only this process, not Xastir itself } else { // This is the parent process last_sound_pid=sound_pid; } } else fprintf(stderr,"Error! trying to play sound\n"); } else { sound_pid=last_sound_pid; /*fprintf(stderr,"Sound already running\n");*/ } } return(sound_pid); }
/* Echo service -- echo data back */ void echo_stream (int s, struct servtab *sep) { char buffer[BUFSIZE]; int i; set_proc_title (sep->se_service, s); while ((i = read (s, buffer, sizeof buffer)) > 0 && write (s, buffer, i) > 0) ; exit (0); }
static int pty_alloc(int *master, int *slave, struct termios *tios, struct winsize *ws) { char name[PATH_MAX]; if (openpty(master, slave, name, tios, ws) < 0) { logger(-1, errno, "Unable to open pty"); return -1; } set_proc_title(name); logger(2, 0, "Open %s", name); return 0; }
/* Discard service -- ignore data */ void discard_stream (int s, struct servtab *sep) { int ret; char buffer[BUFSIZE]; set_proc_title (sep->se_service, s); while (1) { while ((ret = read (s, buffer, sizeof buffer)) > 0) ; if (ret == 0 || errno != EINTR) break; } exit (0); }
int main(int argc, char **argv) { alexjlz_log(1, "client started:%s\n", uuid); generate_uuid(); alexjlz_log(1, "uuid generated:%s\n", uuid); getOurIP(); srand(time(NULL) ^ getpid()); init_rand(time(NULL) ^ getpid()); set_proc_title(argc, argv, PROC_TITLE); alexjlz_log(1, "set proc title success\n"); while (1) { if ( daemonize() == 0 ) break; alexjlz_log(3, "daemonize failed\n"); sleep(3); } alexjlz_log(3, "daemonize success\n"); while ( 1 ) { if( (mainCommSock=connect_tcp_server(server, port)) == -1) { alexjlz_log(3, "connect to server failed\n"); sleep(5); continue; } alexjlz_log(3, "connect to server success\n"); if ( ask_for_service( mainCommSock ) == -1 ) // return from this function means connection between client // and server are unexpectedly closed { //fprintf(stdout, "error in client\n"); } if ( check_fd(mainCommSock) ) { close(mainCommSock); } sleep(3); } return 0; }
int main(int argc, char** argv, char** envp) { int c; gboolean daemonize = FALSE; gboolean stop_logd = FALSE; gboolean ask_status= FALSE; const char* cfgfile = NULL; pid_t pid; cmdname = argv[0]; while ((c = getopt(argc, argv, "c:dksvh")) != -1){ switch(c){ case 'd': /* daemonize */ daemonize = TRUE; break; case 'k': /* stop */ stop_logd = TRUE; break; case 's': /* status */ ask_status = TRUE; break; case 'c': /* config file*/ cfgfile = optarg; break; case 'v': verbose = TRUE; break; case 'h': /*help message */ default: usage(); exit(1); } } set_ipc_time_debug_flag(FALSE); cl_log_set_uselogd(FALSE); if (!cfgfile && access(DEFAULT_CFG_FILE, F_OK) == 0) { cfgfile = DEFAULT_CFG_FILE; } /* default one set to "logd" * by setting facility, we enable syslog */ cl_log_enable_stderr(TRUE); cl_log_set_entity(logd_config.entity); cl_log_set_facility(logd_config.log_facility); if (ask_status){ long pid; if( (pid = cl_read_pidfile(LOGD_PIDFILE)) > 0 ){ printf("logging daemon is running [pid = %ld].\n", pid); exit(LSB_EXIT_OK); }else{ if (pid == - LSB_STATUS_VAR_PID) { printf("logging daemon is stopped: %s exists.\n" , LOGD_PIDFILE); }else{ printf("logging daemon is stopped.\n"); } } exit(-pid); } if (stop_logd){ logd_stop(); exit(LSB_EXIT_OK); } logd_make_daemon(daemonize); if (ipc_channel_pair(chanspair) != IPC_OK){ cl_perror("cannot create channel pair IPC"); return -1; } if (cfgfile && !parse_config(cfgfile)) { FILE* f; if ((f = fopen(cfgfile, "r")) != NULL){ fclose(f); cl_log(LOG_ERR, "Config file [%s] is incorrect." , cfgfile); exit(LSB_EXIT_NOTCONFIGED); } } if (strlen(logd_config.debugfile) > 0) { cl_log_set_debugfile(logd_config.debugfile); } if (strlen(logd_config.logfile) > 0) { cl_log_set_logfile(logd_config.logfile); } cl_log_set_syslogprefix(logd_config.syslogprefix); cl_log_set_entity(logd_config.entity); cl_log_set_facility(logd_config.log_facility); cl_log(LOG_INFO, "logd started with %s.", cfgfile ? cfgfile : "default configuration"); if (cl_enable_coredumps(TRUE) < 0){ cl_log(LOG_ERR, "enabling core dump failed"); } cl_cdtocoredir(); chanspair[WRITE_PROC_CHAN]->ops->set_recv_qlen(chanspair[WRITE_PROC_CHAN], LOGD_QUEUE_LEN); chanspair[READ_PROC_CHAN]->ops->set_send_qlen(chanspair[READ_PROC_CHAN], LOGD_QUEUE_LEN); if (init_set_proc_title(argc, argv, envp) < 0) { cl_log(LOG_ERR, "Allocation of proc title failed."); return -1; } switch(pid = fork()){ case -1: cl_perror("Can't fork child process!"); return -1; case 0: /*child*/ cl_log_use_buffered_io(1); set_proc_title("ha_logd: write process"); write_msg_process(chanspair[WRITE_PROC_CHAN]); break; default: /*parent*/ set_proc_title("ha_logd: read process"); write_process_pid = pid; /* we don't expect to log anything in the parent. */ cl_log_close_log_files(); read_msg_process(chanspair[READ_PROC_CHAN]); break; } return 0; }
int servant(const char *diskname, int mode, const void* argp) { struct sector_mbox_s *s_mbox = NULL; struct sector_node_s *s_node = NULL; struct sector_header_s *s_header = NULL; int mbox; int rc = 0; time_t t0, t1, latency; union sigval signal_value; sigset_t servant_masks; struct sbd_context *st; pid_t ppid; char uuid[37]; const struct servants_list_item *s = argp; if (!diskname) { cl_log(LOG_ERR, "Empty disk name %s.", diskname); return -1; } cl_log(LOG_INFO, "Servant starting for device %s", diskname); /* Block most of the signals */ sigfillset(&servant_masks); sigdelset(&servant_masks, SIGKILL); sigdelset(&servant_masks, SIGFPE); sigdelset(&servant_masks, SIGILL); sigdelset(&servant_masks, SIGSEGV); sigdelset(&servant_masks, SIGBUS); sigdelset(&servant_masks, SIGALRM); /* FIXME: check error */ sigprocmask(SIG_SETMASK, &servant_masks, NULL); atexit(servant_exit); servant_inform_parent = 1; st = open_device(diskname, LOG_WARNING); if (!st) { return -1; } s_header = header_get(st); if (!s_header) { cl_log(LOG_ERR, "Not a valid header on %s", diskname); return -1; } if (servant_check_timeout_inconsistent(s_header) < 0) { cl_log(LOG_ERR, "Timeouts on %s do not match first device", diskname); return -1; } if (s_header->minor_version > 0) { uuid_unparse_lower(s_header->uuid, uuid); cl_log(LOG_INFO, "Device %s uuid: %s", diskname, uuid); } mbox = slot_allocate(st, local_uname); if (mbox < 0) { cl_log(LOG_ERR, "No slot allocated, and automatic allocation failed for disk %s.", diskname); rc = -1; goto out; } s_node = sector_alloc(); if (slot_read(st, mbox, s_node) < 0) { cl_log(LOG_ERR, "Unable to read node entry on %s", diskname); exit(1); } DBGLOG(LOG_INFO, "Monitoring slot %d on disk %s", mbox, diskname); if (s_header->minor_version == 0) { set_proc_title("sbd: watcher: %s - slot: %d", diskname, mbox); } else { set_proc_title("sbd: watcher: %s - slot: %d - uuid: %s", diskname, mbox, uuid); } s_mbox = sector_alloc(); if (s->first_start) { if (mode > 0) { if (mbox_read(st, mbox, s_mbox) < 0) { cl_log(LOG_ERR, "mbox read failed during start-up in servant."); rc = -1; goto out; } if (s_mbox->cmd != SBD_MSG_EXIT && s_mbox->cmd != SBD_MSG_EMPTY) { /* Not a clean stop. Abort start-up */ cl_log(LOG_WARNING, "Found fencing message - aborting start-up. Manual intervention required!"); ppid = getppid(); sigqueue(ppid, SIG_EXITREQ, signal_value); rc = 0; goto out; } } DBGLOG(LOG_INFO, "First servant start - zeroing inbox"); memset(s_mbox, 0, sizeof(*s_mbox)); if (mbox_write(st, mbox, s_mbox) < 0) { rc = -1; goto out; } } memset(&signal_value, 0, sizeof(signal_value)); while (1) { struct sector_header_s *s_header_retry = NULL; struct sector_node_s *s_node_retry = NULL; t0 = time(NULL); sleep(timeout_loop); ppid = getppid(); if (ppid == 1) { /* Our parent died unexpectedly. Triggering * self-fence. */ do_reset(); } /* These attempts are, by definition, somewhat racy. If * the device is wiped out or corrupted between here and * us reading our mbox, there is nothing we can do about * that. But at least we tried. */ s_header_retry = header_get(st); if (!s_header_retry) { cl_log(LOG_ERR, "No longer found a valid header on %s", diskname); exit(1); } if (memcmp(s_header, s_header_retry, sizeof(*s_header)) != 0) { cl_log(LOG_ERR, "Header on %s changed since start-up!", diskname); exit(1); } free(s_header_retry); s_node_retry = sector_alloc(); if (slot_read(st, mbox, s_node_retry) < 0) { cl_log(LOG_ERR, "slot read failed in servant."); exit(1); } if (memcmp(s_node, s_node_retry, sizeof(*s_node)) != 0) { cl_log(LOG_ERR, "Node entry on %s changed since start-up!", diskname); exit(1); } free(s_node_retry); if (mbox_read(st, mbox, s_mbox) < 0) { cl_log(LOG_ERR, "mbox read failed in servant."); exit(1); } if (s_mbox->cmd > 0) { cl_log(LOG_INFO, "Received command %s from %s on disk %s", char2cmd(s_mbox->cmd), s_mbox->from, diskname); switch (s_mbox->cmd) { case SBD_MSG_TEST: memset(s_mbox, 0, sizeof(*s_mbox)); mbox_write(st, mbox, s_mbox); sigqueue(ppid, SIG_TEST, signal_value); break; case SBD_MSG_RESET: do_reset(); break; case SBD_MSG_OFF: do_off(); break; case SBD_MSG_EXIT: sigqueue(ppid, SIG_EXITREQ, signal_value); break; case SBD_MSG_CRASHDUMP: do_crashdump(); break; default: /* FIXME: An "unknown" message might result from a partial write. log it and clear the slot. */ cl_log(LOG_ERR, "Unknown message on disk %s", diskname); memset(s_mbox, 0, sizeof(*s_mbox)); mbox_write(st, mbox, s_mbox); break; } } sigqueue(ppid, SIG_LIVENESS, signal_value); t1 = time(NULL); latency = t1 - t0; if (timeout_watchdog_warn && (latency > timeout_watchdog_warn)) { cl_log(LOG_WARNING, "Latency: %d exceeded threshold %d on disk %s", (int)latency, (int)timeout_watchdog_warn, diskname); } else if (debug) { DBGLOG(LOG_INFO, "Latency: %d on disk %s", (int)latency, diskname); } } out: free(s_mbox); close_device(st); if (rc == 0) { servant_inform_parent = 0; } return rc; }
static int do_server(int type) { int rv = -1; static char log_ent[128] = DAEMON_NAME "-"; rv = setup_config(type); if (rv < 0) return rv; if (!local) { log_error("Cannot find myself in the configuration."); exit(EXIT_FAILURE); } if (daemonize) { if (daemon(0, 0) < 0) { perror("daemon error"); exit(EXIT_FAILURE); } } /* The lockfile must be written to _after_ the call to daemon(), so * that the lockfile contains the pid of the daemon, not the parent. */ lock_fd = create_lockfile(); if (lock_fd < 0) return lock_fd; atexit(server_exit); strcat(log_ent, type_to_string(local->type)); cl_log_set_entity(log_ent); cl_log_enable_stderr(enable_stderr ? TRUE : FALSE); cl_log_set_facility(HA_LOG_FACILITY); cl_inherit_logging_environment(0); log_info("BOOTH %s %s daemon is starting", type_to_string(local->type), RELEASE_STR); signal(SIGUSR1, (__sighandler_t)tickets_log_info); signal(SIGTERM, (__sighandler_t)sig_exit_handler); signal(SIGINT, (__sighandler_t)sig_exit_handler); /* we'll handle errors there and then */ signal(SIGPIPE, SIG_IGN); set_scheduler(); /* we don't want to be killed by the OOM-killer */ if (set_procfs_val("/proc/self/oom_score_adj", "-999")) (void)set_procfs_val("/proc/self/oom_adj", "-16"); set_proc_title("%s %s %s for [%s]:%d", DAEMON_NAME, cl.configfile, type_to_string(local->type), local->addr_string, booth_conf->port); rv = limit_this_process(); if (rv) return rv; #ifdef COREDUMP_NURSING if (cl_enable_coredumps(TRUE) < 0){ log_error("enabling core dump failed"); } cl_cdtocoredir(); prctl(PR_SET_DUMPABLE, (unsigned long)TRUE, 0UL, 0UL, 0UL); #else if (chdir(BOOTH_CORE_DIR) < 0) { log_error("cannot change working directory to %s", BOOTH_CORE_DIR); } #endif signal(SIGCHLD, (__sighandler_t)wait_child); rv = loop(lock_fd); return rv; }
static int do_server(int type) { int rv = -1; static char log_ent[128] = DAEMON_NAME "-"; rv = setup_config(type); if (rv < 0) return rv; if (!local) { log_error("Cannot find myself in the configuration."); exit(EXIT_FAILURE); } if (!daemonize) { if (daemon(0, 0) < 0) { perror("daemon error"); exit(EXIT_FAILURE); } } /* The lockfile must be written to _after_ the call to daemon(), so * that the lockfile contains the pid of the daemon, not the parent. */ lock_fd = create_lockfile(); if (lock_fd < 0) return lock_fd; atexit(server_exit); strcat(log_ent, type_to_string(local->type)); cl_log_set_entity(log_ent); cl_log_enable_stderr(enable_stderr ? TRUE : FALSE); cl_log_set_facility(HA_LOG_FACILITY); cl_inherit_logging_environment(0); log_info("BOOTH %s %s daemon is starting", type_to_string(local->type), RELEASE_STR); signal(SIGUSR1, (__sighandler_t)tickets_log_info); signal(SIGTERM, (__sighandler_t)sig_exit_handler); signal(SIGINT, (__sighandler_t)sig_exit_handler); set_scheduler(); set_oom_adj(-16); set_proc_title("%s %s %s for [%s]:%d", DAEMON_NAME, cl.configfile, type_to_string(local->type), local->addr_string, booth_conf->port); rv = limit_this_process(); if (rv) return rv; if (cl_enable_coredumps(TRUE) < 0){ cl_log(LOG_ERR, "enabling core dump failed"); } cl_cdtocoredir(); prctl(PR_SET_DUMPABLE, (unsigned long)TRUE, 0UL, 0UL, 0UL); rv = loop(lock_fd); return rv; }
int servant_pcmk(const char *diskname, int mode, const void* argp) { int exit_code = 0; crm_cluster_t crm_cluster; cl_log(LOG_INFO, "Monitoring Pacemaker health"); set_proc_title("sbd: watcher: Pacemaker"); setenv("PCMK_watchdog", "true", 1); if(debug == 0) { /* We don't want any noisy crm messages */ set_crm_log_level(LOG_CRIT); } #ifdef SUPPORT_PLUGIN cluster_stack = get_cluster_type(); if (cluster_stack != pcmk_cluster_classic_ais) { check_ais = 0; } else { check_ais = 1; cl_log(LOG_INFO, "Legacy plug-in detected, AIS quorum check enabled"); if(is_openais_cluster()) { crm_cluster.destroy = ais_membership_destroy; crm_cluster.cpg.cpg_deliver_fn = ais_membership_dispatch; /* crm_cluster.cpg.cpg_confchg_fn = pcmk_cpg_membership; TODO? */ crm_cluster.cpg.cpg_confchg_fn = NULL; } while (!crm_cluster_connect(&crm_cluster)) { cl_log(LOG_INFO, "Waiting to sign in with cluster ..."); sleep(reconnect_msec / 1000); } } #endif if (current_cib == NULL) { cib = cib_new(); do { exit_code = cib_connect(TRUE); if (exit_code != 0) { sleep(reconnect_msec / 1000); } } while (exit_code == -ENOTCONN); if (exit_code != 0) { clean_up(-exit_code); } } mainloop = g_main_new(FALSE); mainloop_add_signal(SIGTERM, mon_shutdown); mainloop_add_signal(SIGINT, mon_shutdown); timer_id_notify = g_timeout_add(timeout_loop * 1000, mon_timer_notify, NULL); #ifdef SUPPORT_PLUGIN if (check_ais) { timer_id_ais = g_timeout_add(timeout_loop * 1000, mon_timer_ais, NULL); } #endif g_main_run(mainloop); g_main_destroy(mainloop); clean_up(0); return 0; /* never reached */ }
int main(int argc, char *argv[], char **envp) { QueryHandle *res; time_t tt; GLOBAL *g; INSTANCE *instances; int fval = 0, i = 0, reload = 0; char *inst, *instance; FILE *pidf; openlog(PROGNAME, 0, LOG_INFO | LOG_CRIT | LOG_ERR); syslog(LOG_INFO, "LMS Daemon started."); // initialize global structure g = (GLOBAL *) realloc(NULL, sizeof(GLOBAL)); g->api_version = APIVERSION; g->db = (DB *) realloc(NULL, sizeof(DB)); g->db->conn = NULL; // initialize proces name change init_set_proc_title(argc, argv, envp); // configuration load sequence - check if LMSini is set configfile = ( getenv("LMSINI") ? getenv("LMSINI") : "/etc/lms/lms.ini" ); // read environment and command line driver = ( getenv("LMSDBTYPE") ? getenv("DBTYPE") : strdup("mysql") ); passwd = ( getenv("LMSDBPASS") ? getenv("LMSDBPASS") : "" ); dbname = ( getenv("LMSDBNAME") ? getenv("LMSDBNAME") : "lms" ); user = ( getenv("LMSDBUSER") ? getenv("LMSDBUSER") : "lms" ); port = ( getenv("LMSDBPORT") ? atoi(getenv("LMSDBPORT")) : 0 ); if( getenv("LMSDBHOST") ) strcpy(host, getenv("LMSDBHOST")); else strcpy(host, "localhost"); gethostname(dhost, 255); // date/time localization according to environement settings setlocale(LC_TIME, ""); // command line arguments parse_command_line(argc, argv); // load configuration file if exist (if not it will use default parameters - only database section) ini = config_load(configfile, g->db, dhost, "database"); // assign variables driver = config_getstring(ini, "database", "type", driver); passwd = config_getstring(ini, "database", "password", passwd); dbname = config_getstring(ini, "database", "database", dbname); user = config_getstring(ini, "database", "user", user); port = config_getint(ini, "database", "port", port); strcpy(host, config_getstring(ini, "database", "host", host)); // change process name (hide command line args) set_proc_title(PROGNAME); str_replace(&driver, "postgres", "pgsql"); // postgres in ini file is pgsql str_replace(&driver, "mysqli", "mysql"); // mysqli in ini file is mysql char dbdrv_path[strlen(LMS_LIB_DIR) + strlen(driver) + 4]; sprintf(dbdrv_path, LMS_LIB_DIR "/%s.so", driver); if( !file_exists(dbdrv_path)) { syslog(LOG_CRIT, "Database driver '%s' does not exist. Could not find '%s'.", driver, dbdrv_path); fprintf(stderr, "Database driver '%s' does not exist. Could not find '%s'.\n", driver, dbdrv_path); exit(1); } void *dbdrv; dbdrv = dlopen(dbdrv_path, RTLD_NOW); if( !dbdrv ) { char * errMsg = dlerror(); syslog(LOG_CRIT, "Unable to load database driver '%s': %s", dbdrv_path, errMsg); fprintf(stderr, "Unable to load database driver '%s': %s.\n", dbdrv_path, errMsg); exit(1); } else { syslog(LOG_INFO, "Database driver '%s' loaded.", driver); } g->db->connect = dlsym(dbdrv, "db_connect"); g->db->disconnect = dlsym(dbdrv, "db_disconnect"); g->db->query = dlsym(dbdrv, "db_query"); g->db->pquery = dlsym(dbdrv, "db_pquery"); g->db->exec = dlsym(dbdrv, "db_exec"); g->db->pexec = dlsym(dbdrv, "db_pexec"); g->db->last_insert_id = dlsym(dbdrv, "db_last_insert_id"); g->db->free = dlsym(dbdrv, "db_free"); g->db->begin = dlsym(dbdrv, "db_begin"); g->db->commit = dlsym(dbdrv, "db_commit"); g->db->abort = dlsym(dbdrv, "db_abort"); g->db->get_data = dlsym(dbdrv, "db_get_data"); g->db->nrows = dlsym(dbdrv, "db_nrows"); g->db->ncols = dlsym(dbdrv, "db_ncols"); g->db->concat = dlsym(dbdrv, "db_concat"); g->db->escape = dlsym(dbdrv, "db_escape"); g->db->colname = dlsym(dbdrv, "db_colname"); // test database connection if( !(g->db->conn = g->db->connect(dbname,user,passwd,host,port,ssl)) ) { fprintf(stderr, "CRITICAL: Could not connect to database. See logs for details.\n"); termination_handler(1); } res = g->db->pquery(g->db->conn, "SELECT count(*) FROM dbinfo"); if( ! g->db->nrows(res) ) { fprintf(stderr, "CRITICAL: Could not query database. See logs for details.\n"); termination_handler(1); } g->db->free(&res); g->db->disconnect(g->db->conn); g->str_replace = &str_replace; g->str_save = &str_save; g->str_concat = &str_concat; g->str_lwc = &str_lwc; g->str_upc = &str_upc; g->va_list_join = &va_list_join; g->config_getstring = &config_getstring; g->config_getint = &config_getint; g->config_getbool = &config_getbool; g->config_getdouble = &config_getdouble; // catch SIGCHLD to catch zombies sa.sa_handler = sig_child; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGCHLD, &sa, &orig); // daemonize if ( !quit && !dontfork ) { fval = fork(); switch(fval) { case -1: fprintf(stderr, "Fork error. Exiting."); termination_handler(1); case 0: setsid(); break; default: #ifdef DEBUG1 syslog(LOG_INFO, "DEBUG: [lmsd] Daemonize. Forked child %d.", fval); #endif if (pidfile != NULL && (pidf = fopen(pidfile, "w")) != NULL) { fprintf(pidf, "%d", fval); fclose(pidf); } exit(0); // parent exits } } // termination signals handling signal(SIGINT, termination_handler); signal(SIGTERM, termination_handler); // main loop **************************************************** for(;;) { int i_no = 0; if( quit ) { reload = 1; tt = time(0); } else // daemon mode { reload = 0; tt = cron_sync_sleep(); } // run shell command, i.e. secure connections tuneling if( command!=NULL ) { #ifdef DEBUG1 syslog(LOG_INFO, "DEBUG: [lmsd] Executing command: %s.", command); #endif system(command); } // try to connect to database if( !(g->db->conn = g->db->connect(dbname,user,passwd,host,port,ssl)) ) { if( quit ) termination_handler(1); continue; } if( !reload ) { // check reload order res = g->db->pquery(g->db->conn, "SELECT reload FROM hosts WHERE name = '?' AND reload != 0", dhost); if( g->db->nrows(res) ) { reload = 1; } g->db->free(&res); } instances = (INSTANCE *) malloc(sizeof(INSTANCE)); // get instances list even if reload == 0 // maybe we should do that once before main loop, but in // this way we can change configuration without daemon restart if( iopt ) // from command line... { inst = strdup(iopt); for( instance=strtok(inst," "); instance!=NULL; instance=strtok(NULL, " ") ) { char *name = strdup(instance); str_replace(&name, "\\s", " "); // instance name with spaces res = g->db->pquery(g->db->conn, "SELECT module, crontab FROM daemoninstances, hosts WHERE hosts.id = hostid AND disabled = 0 AND hosts.name = '?' AND daemoninstances.name = '?'", dhost, name); if( g->db->nrows(res) ) { char *crontab = g->db->get_data(res, 0, "crontab"); if( runall || (reload && !strlen(crontab)) || (!quit && crontab_match(tt, crontab)) ) { instances = (INSTANCE *) realloc(instances, sizeof(INSTANCE)*(i_no+1)); instances[i_no].name = strdup(name); instances[i_no].module = strdup(g->db->get_data(res, 0, "module")); instances[i_no].crontab = strdup(crontab); i_no++; } } else { syslog(LOG_CRIT, "Host '%s' and/or instance '%s' not found in database!", dhost, name); fprintf(stderr, "Host '%s' and/or instance '%s' not found in database!\n", dhost, name); } g->db->free(&res); free(name); } free(inst); } else // ... or from database { res = g->db->pquery(g->db->conn, "SELECT module, crontab, daemoninstances.name AS name FROM daemoninstances, hosts WHERE hosts.id = hostid AND disabled = 0 AND hosts.name = '?' ORDER BY priority", dhost); for(i=0; i<g->db->nrows(res); i++) { char *crontab = g->db->get_data(res, i, "crontab"); if( runall || (reload && !strlen(crontab)) || (!quit && crontab_match(tt, crontab)) ) { instances = (INSTANCE *) realloc(instances, sizeof(INSTANCE)*(i_no+1)); instances[i_no].name = strdup(g->db->get_data(res, i, "name")); instances[i_no].module = strdup(g->db->get_data(res, i, "module")); instances[i_no].crontab = strdup(crontab); i_no++; } } g->db->free(&res); } g->db->disconnect(g->db->conn); if( i_no ) { // forking reload - we can do a job for longer than one minute if( quit ) fval = 0; // don't fork in "quit mode" else fval = fork(); if( fval < 0 ) { syslog(LOG_CRIT, "Fork error. Can't reload."); if ( quit ) termination_handler(1); } else if( fval == 0 ) // child or "quit mode" { set_proc_title(PROGNAME": reload"); // restore old handler so we can wait for childs executed by modules if( !quit ) sigaction(SIGCHLD, &orig, NULL); #ifdef DEBUG1 syslog(LOG_INFO, "DEBUG: [lmsd] Reloading..."); #endif // try to connect to database again if( !(g->db->conn = g->db->connect(dbname,user,passwd,host,port,ssl)) ) { if( quit ) termination_handler(1); else exit(1); } // write reload timestamp and disable reload order if( reload ) g->db->pexec(g->db->conn, "UPDATE hosts SET lastreload = %NOW%, reload = 0 WHERE name = '?'", dhost); for(i=0; i<i_no; i++) { MODULE *m; MODULE *mod = (MODULE*) malloc(sizeof(MODULE)); MODULE * (*init)(GLOBAL *, MODULE *); char path[strlen(LMS_LIB_DIR) + strlen(instances[i].module) + 4]; // get instance configuration and members mod->ini = config_load(configfile, g->db, dhost, instances[i].name); mod->instance = strdup(instances[i].name); // set path to module if not specified // be sure that it has .so extension str_replace(&instances[i].module, ".so", ""); if( instances[i].module[0] == '/' ) sprintf(path, "%s.so", instances[i].module); else sprintf(path, LMS_LIB_DIR "/%s.so", instances[i].module); mod->file = strdup(path); // try to load module mod->dlh = dlopen(mod->file, RTLD_NOW); if( !mod->dlh ) { syslog(LOG_ERR, "Unable to load module '%s': %s", mod->file, dlerror()); free_module(mod); continue; } // initialize module init = dlsym(mod->dlh, "init"); if( !init ) { syslog(LOG_CRIT, "Unable to find initialization function in module '%s'. Is that file really a lmsd module?", mod->file); free_module(mod); continue; } if( !(m = init(g, mod))) { syslog(LOG_CRIT, "Unable to initialize module '%s'. Perhaps there is a version mismatch?", mod->file); free_module(mod); continue; } syslog(LOG_INFO, "Running module: %s", instances[i].module); // now run module m->reload(g, m); // cleanup free_module(m); } g->db->disconnect(g->db->conn); // exit child (reload) thread if( !quit ) { #ifdef DEBUG1 syslog(LOG_INFO, "DEBUG: [lmsd] Reload finished. Exiting child."); #endif exit(0); } } else sleep(10); // it's important to sleep parent for some time for(i=0; i<i_no; i++) { free(instances[i].name); free(instances[i].module); free(instances[i].crontab); } } if( quit ) termination_handler(0); free(instances); } // end of loop ********************************************** return 0; }