📄 apphbd.c
字号:
extern pid_t getsid(pid_t);static void init_config(const char* cfgfile){ /* Set default configure */ set_debug_level(DEFAULT_DEBUG_LEVEL); set_watchdog_device(DEFAULT_WDT_DEV); set_watchdog_interval(DEFAULT_WDT_INTERVAL_MS); set_realtime(DEFAULT_REALTIME); /* Read configure file */ if (cfgfile) { if (!parse_config(cfgfile)) { exit(LSB_EXIT_NOTCONFIGED); } }else{ exit(LSB_EXIT_NOTCONFIGED); }}/* Adapted from parse_config in config.c */static gbooleanparse_config(const char* cfgfile){ FILE* f; char buf[MAXLINE]; char* bp; char* cp; char directive[MAXLINE]; int dirlength; int optionlength; char option[MAXLINE]; int dir_index; gboolean ret = TRUE; if ((f = fopen(cfgfile, "r")) == NULL){ cl_log(LOG_ERR, "Cannot open config file:[%s]", cfgfile); return(FALSE); } while(fgets(buf, MAXLINE, f) != NULL){ bp = buf; /* Skip over white space*/ bp += strspn(bp, " \t\n\r\f"); /* comments */ if ((cp = strchr(bp, '#')) != NULL){ *cp = EOS; } if (*bp == EOS){ continue; } dirlength = strcspn(bp, " \t\n\f\r"); strncpy(directive, bp, dirlength); directive[dirlength] = EOS; if ((dir_index = get_dir_index(directive)) == -1){ cl_log(LOG_ERR, "Illegal directive [%s] in %s" , directive, cfgfile); ret = FALSE; continue; } bp += dirlength; /* skip delimiters */ bp += strspn(bp, " ,\t\n\f\r"); /* Set option */ optionlength = strcspn(bp, " ,\t\n\f\r"); strncpy(option, bp, optionlength); option[optionlength] = EOS; if (!(*Directives[dir_index].add_func)(option)) { ret = FALSE; } }/*while*/ fclose(f); return ret;}static int get_dir_index(const char* directive){ int j; for(j=0; j < DIMOF(Directives); j++){ if (strcmp(directive, Directives[j].name) == 0){ return j; } } return -1;}static int set_debug_level(const char* option){ char * ep; long lval; if (!option) { return FALSE; } errno = 0; lval = strtol(option, &ep, 10); if (errno == 0 && option[0] != EOS && *ep == EOS){ apphbd_config.debug_level = (int) lval; return TRUE; }else{ cl_log(LOG_ERR, "invalid debug_level [%s] specified" , option); return FALSE; }}static intset_watchdog_device(const char* option){ if (!option) { apphbd_config.wdt_dev[0] = EOS; return FALSE; } strncpy(apphbd_config.wdt_dev, option, MAXLINE); return TRUE;}static int set_watchdog_interval(const char* option){ char * ep; long lval; if (!option) { return FALSE; } errno = 0; lval = strtol(option, &ep, 10); if (errno == 0 && option[0] != EOS && *ep == EOS && lval >= 10) { apphbd_config.wdt_interval_ms = (int) lval; return TRUE; }else{ cl_log(LOG_ERR, "invalid watchdog_interval_ms [%s] specified" , option); return FALSE; }}static intset_realtime(const char* option){ if (!option) { return FALSE; } if (strcmp(option, "yes") == 0){ apphbd_config.realtime = 1; return TRUE; }else if (strcmp(option, "no") == 0){ apphbd_config.realtime = 0; return TRUE; } return FALSE;}static intset_notify_plugin(const char* option){ if (option && load_notification_plugin(option)) { cl_log(LOG_INFO, "Plugin [%s] loaded", option); return TRUE; } return FALSE;}static intset_debugfile(const char* option){ if (!option){ apphbd_config.debugfile[0] = EOS; return FALSE; } strncpy(apphbd_config.debugfile, option, MAXLINE); return TRUE;}static intset_logfile(const char* option){ if (!option){ apphbd_config.logfile[0] = EOS; return FALSE; } strncpy(apphbd_config.logfile, option, MAXLINE); return TRUE;}/* * Main program for monitoring application heartbeats... */GMainLoop* mainloop = NULL;voidusage(const char* cmd, int exit_status){ FILE* stream; stream = exit_status ? stderr : stdout; fprintf(stream, "usage: %s [-srkh]" "[-c configure file]\n", cmd); fprintf(stream, "\t-d\tsets debug level\n"); fprintf(stream, "\t-s\tgets daemon status\n"); fprintf(stream, "\t-r\trestarts daemon\n"); fprintf(stream, "\t-k\tstops daemon\n"); fprintf(stream, "\t-h\thelp message\n"); fflush(stream); exit(exit_status);}#define OPTARGS "srdkhc:"intmain(int argc, char ** argv){ int flag; int req_restart = FALSE; int req_status = FALSE; int req_stop = FALSE; int argerr = 0; const char* cfgfile = CONFIG_FILE; cl_malloc_forced_for_glib(); /* Must be first */ cl_cdtocoredir(); cl_enable_coredumps(TRUE); cl_log_set_entity(cmdname); cl_log_enable_stderr(TRUE); cl_log_set_facility(LOG_USER); while ((flag = getopt(argc, argv, OPTARGS)) != EOF) { switch(flag) { case 's': /* Status */ req_status = TRUE; break; case 'k': /* Stop (kill) */ req_stop = TRUE; break; case 'r': /* Restart */ req_restart = TRUE; break; case 'h': /* Help message */ usage(cmdname, LSB_EXIT_OK); break; case 'c': /* Configure file */ cfgfile = optarg; break; case 'd': ++apphbd_config.debug_level; break; default: ++argerr; break; } } if (optind > argc) { ++argerr; } if (argerr) { usage(cmdname, LSB_EXIT_GENERIC); } if (req_status){ return init_status(); } if (req_stop){ return init_stop(); } if (req_restart) { init_stop(); } init_config(cfgfile); return init_start();}static voidshutdown(int nsig){ static int shuttingdown = 0; CL_SIGNAL(nsig, shutdown); if (!shuttingdown) { /* Let the watchdog get us if we can't shut down */ tickle_watchdog(); shuttingdown = 1; } if (mainloop != NULL && g_main_is_running(mainloop)) { g_main_quit(mainloop); }else{ exit(LSB_EXIT_OK); }}static gbooleancpu_limit_timer(gpointer unused){ (void)unused; cl_cpu_limit_update(); return TRUE;}static intinit_start(){ char path[] = IPC_PATH_ATTR; char commpath[] = APPHBSOCKPATH; long pid; struct IPC_WAIT_CONNECTION* wconn; GHashTable* wconnattrs; if ((pid = get_running_pid(NULL)) > 0) { cl_log(LOG_CRIT, "already running: [pid %ld]." , pid); exit(LSB_EXIT_OK); } if (apphbd_config.debug_level) { if (apphbd_config.logfile[0] != EOS) { cl_log_set_logfile(apphbd_config.logfile); } if (apphbd_config.debugfile[0] != EOS) { cl_log_set_debugfile(apphbd_config.debugfile); } } if (apphbd_config.realtime == 1){ cl_enable_realtime(); }else if (apphbd_config.realtime == 0){ cl_disable_realtime(); } if (!usenormalpoll) { g_main_set_poll_func(cl_glibpoll); ipc_set_pollfunc(cl_poll); } make_daemon(); /* Create a "waiting for connection" object */ wconnattrs = g_hash_table_new(g_str_hash, g_str_equal); g_hash_table_insert(wconnattrs, path, commpath); wconn = ipc_wait_conn_constructor(IPC_ANYTYPE, wconnattrs); if (wconn == NULL) { cl_log(LOG_CRIT, "Unable to create wcon of type %s", IPC_ANYTYPE); cl_log(LOG_CRIT, "UhOh! Failed to create wconn!"); exit(LSB_EXIT_GENERIC); } /* Create a source to handle new connection requests */ G_main_add_IPC_WaitConnection(G_PRIORITY_HIGH, wconn , NULL, FALSE, apphb_new_dispatch, wconn, NULL); if (apphbd_config.debug_level >= DBGMIN) { int ms_interval; cl_cpu_limit_setpercent(20); ms_interval = cl_cpu_limit_ms_interval(); Gmain_timeout_add(ms_interval, cpu_limit_timer, NULL); } /* Create the mainloop and run it... */ mainloop = g_main_new(FALSE); cl_log(LOG_INFO, "Starting %s", cmdname); cl_make_realtime(SCHED_RR, 5, 64, 64); if (apphbd_config.wdt_dev[0] != EOS) { open_watchdog(apphbd_config.wdt_dev); } if (watchdogfd >= 0) { Gmain_timeout_add(apphbd_config.wdt_interval_ms , tickle_watchdog_timer, NULL); } drop_privs(0, 0); /* Become nobody */ g_main_run(mainloop); return_to_orig_privs(); cl_log(LOG_DEBUG, "testing write to syslog when i am a nobody"); close_watchdog(); wconn->ops->destroy(wconn); if (unlink(PIDFILE) == 0) { cl_log(LOG_INFO, "[%s] stopped", cmdname); } return 0;}static voidmake_daemon(void){ int j; long pid; FILE * lockfd;#ifndef NOFORK pid = fork(); if (pid < 0) { cl_log(LOG_CRIT, "cannot start daemon.\n"); exit(LSB_EXIT_GENERIC); }else if (pid > 0) { exit(LSB_EXIT_OK); }#endif lockfd = fopen(PIDFILE, "w"); if (lockfd == NULL) { cl_log(LOG_CRIT, "cannot create pid file" PIDFILE); exit(LSB_EXIT_GENERIC); }else{ pid = getpid(); fprintf(lockfd, "%ld\n", pid); fclose(lockfd); } umask(022); getsid(0); if (!apphbd_config.debug_level) { cl_log_enable_stderr(FALSE); } for (j=0; j < 3; ++j) { close(j); (void)open("/dev/null", j == 0 ? O_RDONLY : O_RDONLY); } CL_IGNORE_SIG(SIGINT); CL_IGNORE_SIG(SIGHUP); CL_SIGNAL(SIGTERM, shutdown);}static longget_running_pid(gboolean* anypidfile){ long pid; FILE * lockfd; lockfd = fopen(PIDFILE, "r"); if (anypidfile) { *anypidfile = (lockfd != NULL); } if (lockfd != NULL && fscanf(lockfd, "%ld", &pid) == 1 && pid > 0) { if (CL_PID_EXISTS((pid_t)pid)) { fclose(lockfd); return(pid); } } if (lockfd != NULL) { fclose(lockfd); } return(-1L);}static intinit_stop(void){ long pid; int rc = LSB_EXIT_OK; pid = get_running_pid(NULL); if (pid > 0) { if (CL_KILL((pid_t)pid, SIGTERM) < 0) { rc = (errno == EPERM ? LSB_EXIT_EPERM : LSB_EXIT_GENERIC); fprintf(stderr, "Cannot kill pid %ld\n", pid); }else{ while (CL_PID_EXISTS(pid)) { sleep(1); } } } return rc;}static intinit_status(void){ gboolean anypidfile; long pid = get_running_pid(&anypidfile); if (pid > 0) { fprintf(stderr, "%s is running [pid: %ld]\n" , cmdname, pid); return LSB_STATUS_OK; } if (anypidfile) { fprintf(stderr, "%s is stopped [pidfile exists]\n" , cmdname); return LSB_STATUS_VAR_PID; } fprintf(stderr, "%s is stopped.\n", cmdname); return LSB_STATUS_STOPPED;}/* * Notification plugin imported functions: * authenticate_client(void * handle, uidlist, gidlist) * This returns TRUE if the app at apphandle * properly authenticates according to the gidlist * and the uidlist. */static gbooleanauthenticate_client(void * clienthandle, uid_t * uidlist, gid_t* gidlist, int nuid, int ngid){ struct apphb_client* client = clienthandle; struct IPC_AUTH* auth; struct IPC_CHANNEL* ch; gboolean rc = FALSE; if ((auth = ipc_set_auth(uidlist, gidlist, nuid, ngid)) == NULL) { return FALSE; } if (client != NULL && (ch = client->ch) != NULL) { rc = ch->ops->verify_auth(ch, auth) == IPC_OK; } ipc_destroy_auth(auth); return rc;}static gbooleanopen_watchdog(const char * dev){ if (watchdogfd >= 0) { cl_log(LOG_WARNING, "Watchdog device already open."); return FALSE; } if (!dev) { cl_log(LOG_WARNING, "Bad watchdog device name."); return FALSE; } watchdogfd = open(dev, O_WRONLY); if (watchdogfd >= 0) { if (fcntl(watchdogfd, F_SETFD, FD_CLOEXEC)) { cl_log(LOG_WARNING, "Error setting the " "close-on-exec flag for watchdog"); } cl_log(LOG_NOTICE, "Using watchdog device: %s" , dev); tickle_watchdog(); return TRUE; }else{ cl_log(LOG_ERR, "Cannot open watchdog device: %s" , dev); } return FALSE;}static voidclose_watchdog(void){ if (watchdogfd >= 0) { if (write(watchdogfd, "V", 1) != 1) { cl_log(LOG_CRIT , "Watchdog write magic character failure:" " closing watchdog!\n"); } close(watchdogfd); watchdogfd=-1; }}static voidtickle_watchdog(void){ if (watchdogfd >= 0) { if (write(watchdogfd, "", 1) != 1) { cl_log(LOG_CRIT , "Watchdog write failure: closing watchdog!\n"); close_watchdog(); watchdogfd=-1; } }}static gbooleantickle_watchdog_timer(gpointer data){ tickle_watchdog(); return TRUE;}static PILPluginUniv* pisys = NULL;static GHashTable* Notifications = NULL;AppHBNotifyImports piimports = { authenticate_client};static PILGenericIfMgmtRqst RegistrationRqsts [] ={ {"AppHBNotification", &Notifications, &piimports, NULL, NULL}, {NULL, NULL, NULL, NULL, NULL}};static gboolean load_notification_plugin(const char * pluginname){ PIL_rc rc; void* exports; if (pisys == NULL) { pisys = NewPILPluginUniv("/usr/lib/heartbeat/plugins"); if (pisys == NULL) { return FALSE; } if ((rc = PILLoadPlugin(pisys, "InterfaceMgr", "generic" , &RegistrationRqsts)) != PIL_OK) { cl_log(LOG_ERR , "cannot load generic interface manager" " [%s/%s]: %s" , "InterfaceMgr", "generic" , PIL_strerror(rc)); return FALSE; } } rc = PILLoadPlugin(pisys, "AppHBNotification" , pluginname, NULL); if (rc != PIL_OK) { cl_log(LOG_ERR, "cannot load plugin %s", pluginname); return FALSE; } if ((exports = g_hash_table_lookup(Notifications, pluginname)) == NULL) { cl_log(LOG_ERR, "cannot find plugin %s", pluginname); return FALSE; } NotificationPlugins[n_Notification_Plugins] = exports; n_Notification_Plugins ++; return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -