static void process_widget (GType type) { GObjectClass *oclass; if (!type || !G_TYPE_IS_CLASSED (type) || !g_type_is_a (type, GTK_TYPE_WIDGET)) { return; } oclass = g_type_class_ref (type); process_properties (type, oclass); if (g_type_is_a (type, GTK_TYPE_CONTAINER) && type != GTK_TYPE_CONTAINER) { process_child_properties (type, oclass); } process_signals (type); g_print ("\n\n%1$s = element %1$s { %1$sAttrs, %1$sSignals %2$s}\n", g_type_name (type), g_type_is_a (type, GTK_TYPE_CONTAINER) ? ", (misc | widget)*" : ", misc*"); if (type != GTK_TYPE_WIDGET) { g_print ("widget |= %s\n", g_type_name (type)); } g_print ("\n"); }
/* * General server example: accept a client connection and do something. * This program just outputs a short HTML page, but can be easily adapted * to do other things. * * This server creates a constant number of processes ("virtual processors" * or VPs) and replaces them when they die. Each virtual processor manages * its own independent set of state threads (STs), the number of which varies * with load against the server. Each state thread listens to exactly one * listening socket. The initial process becomes the watchdog, waiting for * children (VPs) to die or for a signal requesting termination or restart. * Upon receiving a restart signal (SIGHUP), all VPs close and then reopen * log files and reload configuration. All currently active connections remain * active. It is assumed that new configuration affects only request * processing and not the general server parameters such as number of VPs, * thread limits, bind addresses, etc. Those are specified as command line * arguments, so the server has to be stopped and then started again in order * to change them. * * Each state thread loops processing connections from a single listening * socket. Only one ST runs on a VP at a time, and VPs do not share memory, * so no mutual exclusion locking is necessary on any data, and the entire * server is free to use all the static variables and non-reentrant library * functions it wants, greatly simplifying programming and debugging and * increasing performance (for example, it is safe to ++ and -- all global * counters or call inet_ntoa(3) without any mutexes). The current thread on * each VP maintains equilibrium on that VP, starting a new thread or * terminating itself if the number of spare threads exceeds the lower or * upper limit. * * All I/O operations on sockets must use the State Thread library's I/O * functions because only those functions prevent blocking of the entire VP * process and perform state thread scheduling. */ int main(int argc, char *argv[]) { /* Parse command-line options */ parse_arguments(argc, argv); /* Allocate array of server pids */ if ((vp_pids = calloc(vp_count, sizeof(pid_t))) == NULL) err_sys_quit(errfd, "ERROR: calloc failed"); /* Start the daemon */ if (!interactive_mode) start_daemon(); /* Initialize the ST library */ if (st_init() < 0) err_sys_quit(errfd, "ERROR: initialization failed: st_init"); /* Set thread throttling parameters */ set_thread_throttling(); /* Create listening sockets */ create_listeners(); /* Change the user */ if (username) change_user(); /* Open log files */ open_log_files(); /* Start server processes (VPs) */ start_processes(); /* Turn time caching on */ st_timecache_set(1); /* Install signal handlers */ install_sighandlers(); /* Load configuration from config files */ load_configs(); /* Start all threads */ start_threads(); /* Become a signal processing thread */ process_signals(NULL); /* NOTREACHED */ return 1; }
int main(int argc, char *argv[]) { daemonize(); init_all(); /* Parent can now exit, we're ready to handle requests */ kill(getppid(), SIGTERM); LOG_PRINT("Starting cmirrord:"); LOG_PRINT(" Built: "__DATE__" "__TIME__"\n"); LOG_DBG(" Compiled with debugging."); while (!exit_now) { links_monitor(); links_issue_callbacks(); process_signals(); } exit(EXIT_SUCCESS); }
int user_getstr(const char *prompt, char **response) { const int MAX_INPUT_SIZE = 1000; /* TODO remove this limit */ char *input; int pos, ch, ret; /* display the prompt */ werase(ui.command); mvwprintw(ui.command, 0, 0, "%s", prompt); /* position the cursor */ curs_set(1); wmove(ui.command, 0, strlen(prompt)); wrefresh(ui.command); /* allocate input space and clear */ if ((input = calloc(MAX_INPUT_SIZE, sizeof(char))) == NULL) err(1, "user_getstr: calloc(3) failed for input string"); bzero(input, MAX_INPUT_SIZE); /* start getting input */ ret = 0; pos = 0; while ((ch = getch()) && !VSIG_QUIT) { /* * Handle any signals. Note that the use of curs_set, wmvoe, and * wrefresh here are all necessary to ensure that the cursor does * not show anywhere outside of the command window. */ curs_set(0); process_signals(); curs_set(1); wmove(ui.command, 0, strlen(prompt) + pos); wrefresh(ui.command); if (ch == ERR) continue; if (ch == '\n' || ch == 13) break; /* handle 'escape' */ if (ch == 27) { ret = 1; goto end; } /* handle 'backspace' / left-arrow, etc. */ if (ch == 127 || ch == KEY_BACKSPACE || ch == KEY_LEFT || ch == KEY_DC || ch == KEY_SDC) { if (pos == 0) { if (ch == KEY_BACKSPACE) { ret = 1; goto end; } beep(); } else { mvwaddch(ui.command, 0, strlen(prompt) + pos - 1, ' '); wmove(ui.command, 0, strlen(prompt) + pos - 1); wrefresh(ui.command); pos--; } continue; } /* got regular input. add to buffer. */ input[pos] = ch; mvwaddch(ui.command, 0, strlen(prompt) + pos, ch); wrefresh(ui.command); pos++; /* see todo above - realloc input buffer here if position reaches max */ if (pos >= MAX_INPUT_SIZE) errx(1, "user_getstr: shamefull limit reached"); } /* For lack of input, bail out */ if (pos == 0) { ret = 1; goto end; } /* NULL-terminate and trim off trailing whitespace */ input[pos--] = '\0'; for (; input[pos] == ' ' && pos >= 0; pos--) input[pos] = '\0'; /* trim the fat */ if ((*response = calloc(strlen(input) + 1, sizeof(char))) == NULL) err(1, "user_getstr: calloc(3) failed for result"); snprintf(*response, strlen(input) + 1, "%s", input); end: free(input); curs_set(0); return ret; }
static void process_options(int ac, char *av[]) { ac-=ac>0; av+=ac>0; option::Stats stats(usage, ac, av); #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wvla" option::Option options[stats.options_max], buffer[stats.buffer_max]; #pragma GCC diagnostic pop option::Parser parse(usage, ac, av, options, buffer); #else auto options = std::make_unique<option::Option[]>(stats.options_max); auto buffer = std::make_unique<option::Option[]>(stats.buffer_max); option::Parser parse(usage, ac, av, options.get(), buffer.get()); #endif if (parse.error()) std::exit(EXIT_FAILURE); if (options[OPT_HELP]) { uint16_t col{80}; const auto cols = getenv("COLUMNS"); if (cols) col = nk::str_to_u16(cols); option::printUsage(fwrite, stdout, usage, col); std::exit(EXIT_FAILURE); } if (options[OPT_VERSION]) { print_version(); std::exit(EXIT_FAILURE); } std::vector<std::string> addrlist; std::string pidfile, chroot_path; for (int i = 0; i < parse.optionsCount(); ++i) { option::Option &opt = buffer[i]; switch (opt.index()) { case OPT_BACKGROUND: gflags_detach = 1; break; case OPT_CONFIG: configfile = std::string(opt.arg); break; case OPT_LEASEFILE: leasefile = std::string(opt.arg); break; case OPT_PIDFILE: pidfile = std::string(opt.arg); break; case OPT_CHROOT: chroot_path = std::string(opt.arg); break; case OPT_USER: { if (nk_uidgidbyname(opt.arg, &nrad6_uid, &nrad6_gid)) { fmt::print(stderr, "invalid user '{}' specified\n", opt.arg); std::exit(EXIT_FAILURE); } break; } case OPT_SECCOMP: use_seccomp = true; break; case OPT_QUIET: gflags_quiet = 1; break; } } init_prng(); if (configfile.size()) parse_config(configfile); for (int i = 0; i < parse.nonOptionsCount(); ++i) parse_config(parse.nonOption(i)); if (!bound_interfaces_count()) { fmt::print(stderr, "No interfaces have been bound\n"); std::exit(EXIT_FAILURE); } if (!leasefile.size()) { leasefile = chroot_path.size() ? "/store/dynlease.txt" : "/var/lib/ndhs/store/dynlease.txt"; } nl_socket = std::make_unique<NLSocket>(io_service); init_listeners(); if (gflags_detach && daemon(0,0)) { fmt::print(stderr, "detaching fork failed\n"); std::exit(EXIT_FAILURE); } if (pidfile.size() && file_exists(pidfile.c_str(), "w")) write_pid(pidfile.c_str()); umask(077); process_signals(); if (chroot_path.size()) { nk_set_chroot(chroot_path.c_str()); } dynlease_deserialize(leasefile); if (nrad6_uid || nrad6_gid) nk_set_uidgid(nrad6_uid, nrad6_gid, NULL, 0); if (enforce_seccomp(nrad6_uid || nrad6_gid)) { fmt::print(stderr, "seccomp filter cannot be installed\n"); std::exit(EXIT_FAILURE); } }
int main(int argc, char **argv) { INIT_GLB_VARS(); SET_PROCESS_ROLE(PROCESS_ROLE_MASTER); SET_CHILD_PROCESS(PROCESS_ROLE_MASTER, getpid()); /* 此处注册清理函数, 以便主进程由于某些原因退出时, kill掉 * 启动的所有子进程. 但man atexit可知, 通过fork的子进程会 * 继承atexit的注册链, 而exec后将抛弃此注册链. * <NOTE> 此处不考虑fork子进程也执行此函数带来的影响 */ (void)atexit(kill_child_all); if (log_init() == RET_ERR) { SDNS_LOG_ERR("LOG init failed"); exit(EXIT_FAILURE); } if (zone_init() == RET_ERR) { SDNS_LOG_ERR("ZONE init failed"); exit(EXIT_FAILURE); } if (get_options(argc, argv) == RET_ERR) { SDNS_LOG_ERR("parse cmdline failed"); usage_help(); exit(EXIT_FAILURE); } if (IS_PROCESS_ROLE(PROCESS_ROLE_SIGNALLER)) { process_option_signal(); exit(EXIT_SUCCESS); } if (IS_PROCESS_ROLE(PROCESS_ROLE_HELPER)) { usage_help(); exit(EXIT_SUCCESS); } if (start_monitor() == RET_ERR) { exit(EXIT_FAILURE); } if (parse_conf() == RET_ERR) { exit(EXIT_FAILURE); } if (IS_PROCESS_ROLE(PROCESS_ROLE_TESTER)) { SDNS_LOG_DEBUG("配置文件测试OK"); print_parse_res(); exit(EXIT_SUCCESS); } if (pkt_engine_init() == RET_ERR) { SDNS_LOG_ERR("engine init failed"); exit(EXIT_FAILURE); } if (set_required_signal() == RET_ERR || block_required_signal() == RET_ERR) { SDNS_LOG_ERR("signal init failed"); exit(EXIT_FAILURE); } if (sort_init() == RET_ERR) { SDNS_LOG_ERR("sort init failed"); exit(EXIT_FAILURE); } start_worker(); if (start_pkt_engine() == RET_ERR) { SDNS_LOG_ERR("start engine failed"); exit(EXIT_FAILURE); } for(;;) { (void)wait_required_signal(); (void)process_signals(); } exit(EXIT_SUCCESS); }