int main(int argc, char **argv) { int error; app_subsys **ss; int exit_signals[2] = {SIGTERM, SIGINT}; struct event terminators[2]; struct event dumper; bool conftest = false; int opt; int i; red_srand(); while ((opt = getopt(argc, argv, "h?vtc:p:")) != -1) { switch (opt) { case 't': conftest = true; break; case 'c': confname = optarg; break; case 'p': pidfile = optarg; break; case 'v': puts(redsocks_version); return EXIT_SUCCESS; default: printf( "Usage: %s [-?hvt] [-c config] [-p pidfile]\n" " -h, -? this message\n" " -v print version\n" " -t test config syntax\n" " -p write pid to pidfile\n", argv[0]); return (opt == '?' || opt == 'h') ? EXIT_SUCCESS : EXIT_FAILURE; } } FILE *f = fopen(confname, "r"); if (!f) { perror("Unable to open config file"); return EXIT_FAILURE; } parser_context* parser = parser_start(f, NULL); if (!parser) { perror("Not enough memory for parser"); return EXIT_FAILURE; } FOREACH(ss, subsystems) if ((*ss)->conf_section) parser_add_section(parser, (*ss)->conf_section); error = parser_run(parser); parser_stop(parser); fclose(f); if (error) return EXIT_FAILURE; if (conftest) return EXIT_SUCCESS; // Initialize global event base g_event_base = event_base_new(); if (!g_event_base) return EXIT_FAILURE; memset(&dumper, 0, sizeof(dumper)); memset(terminators, 0, sizeof(terminators)); FOREACH(ss, subsystems) { if ((*ss)->init) { error = (*ss)->init(); if (error) goto shutdown; } } if (pidfile) { f = fopen(pidfile, "w"); if (!f) { perror("Unable to open pidfile for write"); return EXIT_FAILURE; } fprintf(f, "%d\n", getpid()); fclose(f); } assert(SIZEOF_ARRAY(exit_signals) == SIZEOF_ARRAY(terminators)); for (i = 0; i < SIZEOF_ARRAY(exit_signals); i++) { evsignal_assign(&terminators[i], get_event_base(), exit_signals[i], terminate, NULL); if (evsignal_add(&terminators[i], NULL) != 0) { log_errno(LOG_ERR, "signal_add"); goto shutdown; } } evsignal_assign(&dumper, get_event_base(), SIGUSR1, dump_handler, NULL); if (evsignal_add(&dumper, NULL) != 0) { log_errno(LOG_ERR, "evsignal_add"); goto shutdown; } log_error(LOG_NOTICE, "redsocks started"); event_base_dispatch(g_event_base); log_error(LOG_NOTICE, "redsocks goes down"); shutdown: if (evsignal_initialized(&dumper)) { if (evsignal_del(&dumper) != 0) log_errno(LOG_WARNING, "signal_del"); memset(&dumper, 0, sizeof(dumper)); } for (i = 0; i < SIZEOF_ARRAY(exit_signals); i++) { if (evsignal_initialized(&terminators[i])) { if (evsignal_del(&terminators[i]) != 0) log_errno(LOG_WARNING, "signal_del"); memset(&terminators[i], 0, sizeof(terminators[i])); } } for (--ss; ss >= subsystems; ss--) if ((*ss)->fini) (*ss)->fini(); if (g_event_base) event_base_free(g_event_base); return !error ? EXIT_SUCCESS : EXIT_FAILURE; }
int main(int argc, char **argv) { int error; app_subsys **ss; int exit_signals[2] = {SIGTERM, SIGINT}; struct event terminators[2]; bool conftest = false; int opt; int i; evutil_secure_rng_init(); while ((opt = getopt(argc, argv, "h?vtc:p:")) != -1) { switch (opt) { case 't': conftest = true; break; case 'c': confname = optarg; break; case 'p': pidfile = optarg; break; case 'v': puts(redsocks_version); printf("Built with libevent-%s\n", LIBEVENT_VERSION); printf("Runs with libevent-%s\n", event_get_version()); if (LIBEVENT_VERSION_NUMBER != event_get_version_number()) { printf("Warning: libevent version number mismatch.\n" " Headers: %8x\n" " Runtime: %8x\n", LIBEVENT_VERSION_NUMBER, event_get_version_number()); } return EXIT_SUCCESS; default: printf( "Usage: %s [-?hvt] [-c config] [-p pidfile]\n" " -h, -? this message\n" " -v print version\n" " -t test config syntax\n" " -p write pid to pidfile\n", argv[0]); return (opt == '?' || opt == 'h') ? EXIT_SUCCESS : EXIT_FAILURE; } } if (event_get_struct_event_size() != sizeof(struct event)) { puts("libevent event_get_struct_event_size() != sizeof(struct event)! Check `redsocks -v` and recompile redsocks"); return EXIT_FAILURE; } FILE *f = fopen(confname, "r"); if (!f) { perror("Unable to open config file"); return EXIT_FAILURE; } parser_context* parser = parser_start(f); if (!parser) { perror("Not enough memory for parser"); return EXIT_FAILURE; } FOREACH(ss, subsystems) if ((*ss)->conf_section) parser_add_section(parser, (*ss)->conf_section); error = parser_run(parser); parser_stop(parser); fclose(f); if (error) return EXIT_FAILURE; if (conftest) return EXIT_SUCCESS; struct event_base* evbase = event_init(); memset(terminators, 0, sizeof(terminators)); FOREACH(ss, subsystems) { if ((*ss)->init) { error = (*ss)->init(evbase); if (error) goto shutdown; } } if (pidfile) { f = fopen(pidfile, "w"); if (!f) { perror("Unable to open pidfile for write"); return EXIT_FAILURE; } fprintf(f, "%d\n", getpid()); fclose(f); } assert(SIZEOF_ARRAY(exit_signals) == SIZEOF_ARRAY(terminators)); for (i = 0; i < SIZEOF_ARRAY(exit_signals); i++) { signal_set(&terminators[i], exit_signals[i], terminate, NULL); if (signal_add(&terminators[i], NULL) != 0) { log_errno(LOG_ERR, "signal_add"); goto shutdown; } } if (LIBEVENT_VERSION_NUMBER != event_get_version_number()) { log_error(LOG_WARNING, "libevent version mismatch! headers %8x, runtime %8x\n", LIBEVENT_VERSION_NUMBER, event_get_version_number()); } log_error(LOG_NOTICE, "redsocks started, conn_max=%u", redsocks_conn_max()); event_dispatch(); log_error(LOG_NOTICE, "redsocks goes down"); shutdown: for (i = 0; i < SIZEOF_ARRAY(exit_signals); i++) { if (signal_initialized(&terminators[i])) { if (signal_del(&terminators[i]) != 0) log_errno(LOG_WARNING, "signal_del"); memset(&terminators[i], 0, sizeof(terminators[i])); } } for (--ss; ss >= subsystems; ss--) if ((*ss)->fini) (*ss)->fini(); event_base_free(evbase); return !error ? EXIT_SUCCESS : EXIT_FAILURE; }