/** * This is the "real" main which is called both on Windows and UNIX platforms. * For the Windows service case, this will also handle the notifications and set * up the logging support appropriately. */ int main_cmdline(int argc, char **argv) { chassis *srv = NULL; #ifdef HAVE_SIGACTION static struct sigaction sigsegv_sa; #endif /* read the command-line options */ GOptionContext *option_ctx = NULL; GOptionEntry *main_entries = NULL; chassis_frontend_t *frontend = NULL; chassis_options_t *opts = NULL; GError *gerr = NULL; chassis_log_t *log = NULL; /* a little helper macro to set the src-location that we stepped out at to exit */ #define GOTO_EXIT(status) \ exit_code = status; \ exit_location = G_STRLOC; \ goto exit_nicely; int exit_code = EXIT_SUCCESS; const gchar *exit_location = G_STRLOC; if (chassis_frontend_init_glib()) { /* init the thread, module, ... system */ GOTO_EXIT(EXIT_FAILURE); } log = chassis_log_new(); chassis_log_set_default(log, NULL, G_LOG_LEVEL_CRITICAL); /* default to stderr for everything that is critical */ g_log_set_default_handler(chassis_log_func, log); #ifdef _WIN32 if (chassis_frontend_init_win32()) { /* setup winsock */ GOTO_EXIT(EXIT_FAILURE); } #endif /* may fail on library mismatch */ if (NULL == (srv = chassis_new())) { GOTO_EXIT(EXIT_FAILURE); } srv->log = log; /* we need the log structure for the log-rotation */ frontend = chassis_frontend_new(); option_ctx = g_option_context_new("- MySQL Proxy"); /** * parse once to get the basic options like --defaults-file and --version * * leave the unknown options in the list */ if (chassis_frontend_init_base_options(option_ctx, &argc, &argv, &(frontend->print_version), &(frontend->default_file), &gerr)) { g_critical("%s: %s", G_STRLOC, gerr->message); g_clear_error(&gerr); GOTO_EXIT(EXIT_FAILURE); } if (frontend->default_file) { if (!(frontend->keyfile = chassis_frontend_open_config_file(frontend->default_file, &gerr))) { g_critical("%s: loading config from '%s' failed: %s", G_STRLOC, frontend->default_file, gerr->message); g_clear_error(&gerr); GOTO_EXIT(EXIT_FAILURE); } } /* print the main version number here, but don't exit * we check for print_version again, after loading the plugins (if any) * and print their version numbers, too. then we exit cleanly. */ if (frontend->print_version) { #ifndef CHASSIS_BUILD_TAG #define CHASSIS_BUILD_TAG PACKAGE_STRING #endif g_print("%s" CHASSIS_NEWLINE, CHASSIS_BUILD_TAG); chassis_frontend_print_version(); } /* add the other options which can also appear in the configfile */ opts = chassis_options_new(); chassis_frontend_set_chassis_options(frontend, opts); main_entries = chassis_options_to_g_option_entries(opts); g_option_context_add_main_entries(option_ctx, main_entries, NULL); /** * parse once to get the basic options * * leave the unknown options in the list */ if (FALSE == g_option_context_parse(option_ctx, &argc, &argv, &gerr)) { g_critical("%s", gerr->message); GOTO_EXIT(EXIT_FAILURE); } if (frontend->keyfile) { if (chassis_keyfile_to_options(frontend->keyfile, "mysql-proxy", main_entries)) { GOTO_EXIT(EXIT_FAILURE); } } if (chassis_frontend_init_basedir(argv[0], &(frontend->base_dir))) { GOTO_EXIT(EXIT_FAILURE); } /* basic setup is done, base-dir is known, ... */ frontend->lua_subdirs = g_new(char *, 2); frontend->lua_subdirs[0] = g_strdup("mysql-proxy"); frontend->lua_subdirs[1] = NULL; if (chassis_frontend_init_lua_path(frontend->lua_path, frontend->base_dir, frontend->lua_subdirs)) { GOTO_EXIT(EXIT_FAILURE); } if (chassis_frontend_init_lua_cpath(frontend->lua_cpath, frontend->base_dir, frontend->lua_subdirs)) { GOTO_EXIT(EXIT_FAILURE); } /* assign the mysqld part to the */ network_mysqld_init(srv); /* starts the also the lua-scope, LUA_PATH and LUA_CPATH have to be set before this being called */ #ifdef HAVE_SIGACTION /* register the sigsegv interceptor */ memset(&sigsegv_sa, 0, sizeof(sigsegv_sa)); sigsegv_sa.sa_handler = sigsegv_handler; sigemptyset(&sigsegv_sa.sa_mask); if (frontend->invoke_dbg_on_crash && !(RUNNING_ON_VALGRIND)) { sigaction(SIGSEGV, &sigsegv_sa, NULL); } #endif /* * some plugins cannot see the chassis struct from the point * where they open files, hence we must make it available */ srv->base_dir = g_strdup(frontend->base_dir); chassis_frontend_init_plugin_dir(&frontend->plugin_dir, srv->base_dir); /* * these are used before we gathered all the options * from the plugins, thus we need to fix them up before * dealing with all the rest. */ chassis_resolve_path(srv->base_dir, &frontend->log_config_filename); chassis_resolve_path(srv->base_dir, &frontend->log_filename); chassis_resolve_path(srv->base_dir, &frontend->pid_file); chassis_resolve_path(srv->base_dir, &frontend->plugin_dir); /* * start the logging * * If we have a log config file, it takes precendence before the simple other log-* options. */ if (frontend->log_filename && frontend->use_syslog) { g_critical("%s: log-file and log-use-syslog were given, but only one is allowed", G_STRLOC); GOTO_EXIT(EXIT_FAILURE); } if (frontend->log_config_filename) { if (FALSE == chassis_log_load_config(log, frontend->log_config_filename, &gerr)) { g_critical("%s: reading log-config from %s failed: %s", G_STRLOC, frontend->log_config_filename, gerr->message); g_clear_error(&gerr); GOTO_EXIT(EXIT_FAILURE); } /* the system should now be set up, let's try to log something */ g_message("this should go to the root logger on level message"); } else { /* set a default config */ chassis_log_backend_t *backend; chassis_log_domain_t *domain; GLogLevelFlags log_lvl = G_LOG_LEVEL_CRITICAL; /* handle log-level after the config-file is read, just in case it is specified in the file */ if (frontend->log_level) { log_lvl = chassis_log_level_string_to_level(frontend->log_level); if (0 == log_lvl) { g_critical("--log-level=... failed, level '%s' is unknown ", frontend->log_level); GOTO_EXIT(EXIT_FAILURE); } } if (frontend->log_filename) { backend = chassis_log_backend_file_new(frontend->log_filename); } else if (frontend->use_syslog) { backend = chassis_log_backend_syslog_new(); #ifdef _WIN32 } else if (chassis_win32_is_service()) { backend = chassis_log_backend_eventlog_new(); #endif } else { backend = chassis_log_backend_stderr_new(); } chassis_log_register_backend(log, backend); domain = chassis_log_domain_new(CHASSIS_LOG_DEFAULT_DOMAIN, log_lvl, backend); chassis_log_register_domain(log, domain); } /* * the MySQL Proxy should load 'admin' and 'proxy' plugins */ if (!frontend->plugin_names) { frontend->plugin_names = g_new(char *, 3); frontend->plugin_names[0] = g_strdup("admin"); frontend->plugin_names[1] = g_strdup("proxy"); frontend->plugin_names[2] = NULL; }
/** * This is the "real" main which is called both on Windows and UNIX platforms. * For the Windows service case, this will also handle the notifications and set * up the logging support appropriately. */ int main_cmdline(int argc, char **argv) { chassis *srv = NULL; #ifdef HAVE_SIGACTION static struct sigaction sigsegv_sa; #endif /* read the command-line options */ GOptionContext *option_ctx = NULL; GOptionEntry *main_entries = NULL; chassis_frontend_t *frontend = NULL; chassis_options_t *opts = NULL; GError *gerr = NULL; chassis_log *log = NULL; /* a little helper macro to set the src-location that we stepped out at to exit */ #define GOTO_EXIT(status) \ exit_code = status; \ exit_location = G_STRLOC; \ goto exit_nicely; int exit_code = EXIT_SUCCESS; const gchar *exit_location = G_STRLOC; if (chassis_frontend_init_glib()) { /* init the thread, module, ... system */ GOTO_EXIT(EXIT_FAILURE); } /* start the logging ... to stderr */ log = chassis_log_new(); log->min_lvl = G_LOG_LEVEL_MESSAGE; /* display messages while parsing or loading plugins */ g_log_set_default_handler(chassis_log_func, log); #ifdef _WIN32 if (chassis_win32_is_service() && chassis_log_set_event_log(log, g_get_prgname())) { GOTO_EXIT(EXIT_FAILURE); } if (chassis_frontend_init_win32()) { /* setup winsock */ GOTO_EXIT(EXIT_FAILURE); } #endif /* may fail on library mismatch */ if (NULL == (srv = chassis_new())) { GOTO_EXIT(EXIT_FAILURE); } srv->log = log; /* we need the log structure for the log-rotation */ frontend = chassis_frontend_new(); option_ctx = g_option_context_new("- MySQL Proxy"); /** * parse once to get the basic options like --defaults-file and --version * * leave the unknown options in the list */ if (chassis_frontend_init_base_options(option_ctx, &argc, &argv, &(frontend->print_version), &(frontend->default_file), &gerr)) { g_critical("%s: %s", G_STRLOC, gerr->message); g_clear_error(&gerr); GOTO_EXIT(EXIT_FAILURE); } #ifndef _WIN32 signal(SIGPIPE, SIG_IGN); srv->daemon_mode = frontend->daemon_mode; /* add by vinchen/CFR */ srv->auto_restart = frontend->auto_restart; if (frontend->daemon_mode) { chassis_unix_daemonize(); } if (frontend->auto_restart) { int child_exit_status = EXIT_SUCCESS; /* forward the exit-status of the child */ int ret = chassis_unix_proc_keepalive(&child_exit_status); if (ret > 0) { /* the agent stopped */ exit_code = child_exit_status; goto exit_nicely; } else if (ret < 0) { GOTO_EXIT(EXIT_FAILURE); } else { /* we are the child, go on */ } } #endif if (frontend->default_file) { srv->default_file = g_strdup(frontend->default_file); //add by vinchen/CFR if (!(frontend->keyfile = chassis_frontend_open_config_file(frontend->default_file, &gerr))) { g_critical("%s: loading config from '%s' failed: %s", G_STRLOC, frontend->default_file, gerr->message); g_clear_error(&gerr); GOTO_EXIT(EXIT_FAILURE); } } /* print the main version number here, but don't exit * we check for print_version again, after loading the plugins (if any) * and print their version numbers, too. then we exit cleanly. */ if (frontend->print_version) { #ifndef CHASSIS_BUILD_TAG #define CHASSIS_BUILD_TAG PACKAGE_STRING #endif g_print("%s" CHASSIS_NEWLINE, CHASSIS_BUILD_TAG); chassis_frontend_print_version(); } /* add the other options which can also appear in the configfile */ opts = chassis_options_new(); chassis_frontend_set_chassis_options(frontend, opts); main_entries = chassis_options_to_g_option_entries(opts); g_option_context_add_main_entries(option_ctx, main_entries, NULL); /** * parse once to get the basic options * * leave the unknown options in the list */ if (FALSE == g_option_context_parse(option_ctx, &argc, &argv, &gerr)) { g_critical("%s", gerr->message); GOTO_EXIT(EXIT_FAILURE); } if (frontend->keyfile) { if (chassis_keyfile_to_options(frontend->keyfile, "mysql-proxy", main_entries)) { GOTO_EXIT(EXIT_FAILURE); } } //add by vinchen/CFR if (frontend->base_dir != NULL) srv->base_dir_org = g_strdup(frontend->base_dir); if (chassis_frontend_init_basedir(argv[0], &(frontend->base_dir))) { GOTO_EXIT(EXIT_FAILURE); } /* basic setup is done, base-dir is known, ... */ frontend->lua_subdirs = g_new(char *, 2); frontend->lua_subdirs[0] = g_strdup("mysql-proxy"); frontend->lua_subdirs[1] = NULL; if (chassis_frontend_init_lua_path(frontend->lua_path, frontend->base_dir, frontend->lua_subdirs)) { GOTO_EXIT(EXIT_FAILURE); } if (chassis_frontend_init_lua_cpath(frontend->lua_cpath, frontend->base_dir, frontend->lua_subdirs)) { GOTO_EXIT(EXIT_FAILURE); } /* assign the mysqld part to the */ network_mysqld_init(srv); /* starts the also the lua-scope, LUA_PATH and LUA_CPATH have to be set before this being called */ #ifdef HAVE_SIGACTION /* register the sigsegv interceptor */ memset(&sigsegv_sa, 0, sizeof(sigsegv_sa)); sigsegv_sa.sa_handler = sigsegv_handler; sigemptyset(&sigsegv_sa.sa_mask); srv->invoke_dbg_on_crash = frontend->invoke_dbg_on_crash; //add by vinchen/CFR if (frontend->invoke_dbg_on_crash && !(RUNNING_ON_VALGRIND)) { sigaction(SIGSEGV, &sigsegv_sa, NULL); } #endif /* * some plugins cannot see the chassis struct from the point * where they open files, hence we must make it available */ srv->base_dir = g_strdup(frontend->base_dir); if (frontend->plugin_dir) //vinchen/CFR srv->plugin_dir_org = g_strdup(frontend->plugin_dir); if (frontend->pid_file) srv->pid_file_org = g_strdup(frontend->pid_file); if (frontend->log_filename) srv->log_file_name_org = g_strdup(frontend->log_filename); if (frontend->lua_path) srv->lua_path_org = g_strdup(frontend->lua_path); if (frontend->lua_cpath) srv->lua_cpath_org = g_strdup(frontend->lua_cpath); srv->max_files_number = frontend->max_files_number; srv->conn_log = frontend->conn_log; //add by huibohuang srv->query_response_time_stats = frontend->query_response_time_stats; srv->ignore_user = g_strdupv(frontend->ignore_user); chassis_frontend_init_plugin_dir(&frontend->plugin_dir, srv->base_dir); /* * these are used before we gathered all the options * from the plugins, thus we need to fix them up before * dealing with all the rest. */ chassis_resolve_path(srv->base_dir, &frontend->log_filename); chassis_resolve_path(srv->base_dir, &frontend->pid_file); chassis_resolve_path(srv->base_dir, &frontend->plugin_dir); /* * start the logging */ if (frontend->log_filename) { log->log_filename = g_strdup(frontend->log_filename); } log->use_syslog = frontend->use_syslog; if (log->log_filename && log->use_syslog) { g_critical("%s: log-file and log-use-syslog were given, but only one is allowed", G_STRLOC); GOTO_EXIT(EXIT_FAILURE); } if (log->log_filename && FALSE == chassis_log_open(log)) { g_critical("can't open log-file '%s': %s", log->log_filename, g_strerror(errno)); GOTO_EXIT(EXIT_FAILURE); } /* handle log-level after the config-file is read, just in case it is specified in the file */ if (frontend->log_level) { if (0 != chassis_log_set_level(log, frontend->log_level)) { g_critical("--log-level=... failed, level '%s' is unknown ", frontend->log_level); GOTO_EXIT(EXIT_FAILURE); } } else { /* if it is not set, use "critical" as default */ log->min_lvl = G_LOG_LEVEL_CRITICAL; } /* * the MySQL Proxy should load 'admin' and 'proxy' plugins */ if (!frontend->plugin_names) { frontend->plugin_names = g_new(char *, 2); frontend->plugin_names[0] = g_strdup("proxy"); frontend->plugin_names[1] = NULL; }
/** * This is the "real" main which is called both on Windows and UNIX platforms. * For the Windows service case, this will also handle the notifications and set * up the logging support appropriately. */ int main_cmdline(int argc, char **argv) { chassis *srv = NULL; #ifdef HAVE_SIGACTION static struct sigaction sigsegv_sa; #endif /* read the command-line options */ GOptionContext *option_ctx = NULL; GOptionEntry *main_entries = NULL; chassis_frontend_t *frontend = NULL; chassis_options_t *opts = NULL; GError *gerr = NULL; chassis_log *log = NULL; /* a little helper macro to set the src-location that we stepped out at to exit */ #define GOTO_EXIT(status) \ exit_code = status; \ exit_location = G_STRLOC; \ goto exit_nicely; int exit_code = EXIT_SUCCESS; const gchar *exit_location = G_STRLOC; if (chassis_frontend_init_glib()) { /* init the thread, module, ... system */ GOTO_EXIT(EXIT_FAILURE); } /* start the logging ... to stderr */ log = chassis_log_new(); log->min_lvl = G_LOG_LEVEL_MESSAGE; /* display messages while parsing or loading plugins */ g_log_set_default_handler(chassis_log_func, log); #ifdef _WIN32 if (chassis_win32_is_service() && chassis_log_set_event_log(log, g_get_prgname())) { GOTO_EXIT(EXIT_FAILURE); } if (chassis_frontend_init_win32()) { /* setup winsock */ GOTO_EXIT(EXIT_FAILURE); } #endif /* may fail on library mismatch */ if (NULL == (srv = chassis_new())) { GOTO_EXIT(EXIT_FAILURE); } srv->log = log; /* we need the log structure for the log-rotation */ frontend = chassis_frontend_new(); option_ctx = g_option_context_new("- MySQL Proxy"); /** * parse once to get the basic options like --defaults-file and --version * * leave the unknown options in the list */ if (chassis_frontend_init_base_options(option_ctx, &argc, &argv, &(frontend->print_version), &(frontend->default_file), &gerr)) { g_log_dbproxy(g_critical, "%s", gerr->message); g_clear_error(&gerr); GOTO_EXIT(EXIT_FAILURE); } if (frontend->default_file) { if (!(frontend->keyfile = chassis_frontend_open_config_file(frontend->default_file, &gerr))) { g_log_dbproxy(g_critical, "loading config from '%s' failed: %s", frontend->default_file, gerr->message); g_clear_error(&gerr); GOTO_EXIT(EXIT_FAILURE); } } /* print the main version number here, but don't exit * we check for print_version again, after loading the plugins (if any) * and print their version numbers, too. then we exit cleanly. */ if (frontend->print_version) { g_print("%s" CHASSIS_NEWLINE, CHASSIS_BUILD_TAG); g_print(" glib2: %d.%d.%d" CHASSIS_NEWLINE, GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); g_print(" libevent: %s" CHASSIS_NEWLINE, event_get_version()); GOTO_EXIT(EXIT_SUCCESS); } /* add the other options which can also appear in the configfile */ opts = chassis_options_new(); chassis_frontend_set_chassis_options(frontend, opts); main_entries = chassis_options_to_g_option_entries(opts); g_option_context_add_main_entries(option_ctx, main_entries, NULL); srv->opts = opts; /** * parse once to get the basic options * * leave the unknown options in the list */ g_option_context_set_help_enabled(option_ctx, TRUE); if (FALSE == g_option_context_parse(option_ctx, &argc, &argv, &gerr)) { g_log_dbproxy(g_critical, "%s", gerr->message); GOTO_EXIT(EXIT_FAILURE); } if (frontend->keyfile) { if (chassis_keyfile_to_options(frontend->keyfile, "mysql-proxy", main_entries)) { GOTO_EXIT(EXIT_FAILURE); } } if (chassis_frontend_init_basedir(argv[0], &(frontend->base_dir))) { GOTO_EXIT(EXIT_FAILURE); } /* basic setup is done, base-dir is known, ... */ frontend->lua_subdirs = g_new(char *, 2); frontend->lua_subdirs[0] = g_strdup("mysql-proxy"); frontend->lua_subdirs[1] = NULL; if (chassis_frontend_init_lua_path(frontend->lua_path, frontend->base_dir, frontend->lua_subdirs)) { GOTO_EXIT(EXIT_FAILURE); } if (chassis_frontend_init_lua_cpath(frontend->lua_cpath, frontend->base_dir, frontend->lua_subdirs)) { GOTO_EXIT(EXIT_FAILURE); } /* make sure that he max-thread-count isn't negative */ if (frontend->event_thread_count < 1) { g_log_dbproxy(g_critical, "--event-threads has to be >= 1, is %d", frontend->event_thread_count); GOTO_EXIT(EXIT_FAILURE); } srv->event_thread_count = frontend->event_thread_count; if (frontend->wait_timeout < 0) { g_log_dbproxy(g_critical, "--wait-timeout has to be >= 0, is %d", frontend->wait_timeout); GOTO_EXIT(EXIT_FAILURE); } srv->wait_timeout = frontend->wait_timeout; if (frontend->shutdown_timeout < 1) { g_log_dbproxy(g_critical, "--shutdown-timeout has to be >= 1, is %d", frontend->shutdown_timeout); GOTO_EXIT(EXIT_FAILURE); } srv->shutdown_timeout = frontend->shutdown_timeout; if (frontend->db_connection_idle_timeout < 0) { g_log_dbproxy(g_critical, "--db-connection-idle-timeout has to be >= 0, is %d", frontend->db_connection_idle_timeout); GOTO_EXIT(EXIT_FAILURE); } srv->db_connection_idle_timeout = frontend->db_connection_idle_timeout; if (frontend->db_connection_max_age < 0) { g_log_dbproxy(g_critical, "--db-connection-max-age has to be >= 0, is %d", frontend->db_connection_max_age); GOTO_EXIT(EXIT_FAILURE); } srv->db_connection_max_age = frontend->db_connection_max_age; if (frontend->mysql_version == NULL || strcmp(frontend->mysql_version, "5.5") == 0) { srv->my_version = MYSQL_55; } else if (frontend->mysql_version == NULL || strcmp(frontend->mysql_version, "5.6") == 0) { srv->my_version = MYSQL_56; } else { g_log_dbproxy(g_critical, "--mysql-version has to be 5.6 or 5.5, is %s", frontend->mysql_version); GOTO_EXIT(EXIT_FAILURE); } if (frontend->max_connections < 0) { g_log_dbproxy(g_critical, "--max-connections has to be >= 0, is %d", frontend->max_connections); GOTO_EXIT(EXIT_FAILURE); } srv->proxy_max_connections = frontend->max_connections; if (frontend->long_wait_time < 0) { g_log_dbproxy(g_critical, "--long-wait-time has to be >= 0, is %d", frontend->long_wait_time); GOTO_EXIT(EXIT_FAILURE); } srv->long_wait_time = frontend->long_wait_time; if (frontend->long_query_time < 0) { g_log_dbproxy(g_critical, "--long-query-time has to be >= 0, is %d", frontend->long_query_time); GOTO_EXIT(EXIT_FAILURE); } srv->long_query_time = frontend->long_query_time; if (frontend->query_response_time_stats < 0) { g_log_dbproxy(g_critical, "--query-response-time-stats has to be >= 0, is %d", frontend->query_response_time_stats); GOTO_EXIT(EXIT_FAILURE); } srv->query_response_time_stats = frontend->query_response_time_stats; if (frontend->query_response_time_stats > 1 && frontend->query_response_time_range_base < 2) { g_log_dbproxy(g_critical, "--query-response-time-range-base has to be >= 2, is %d", frontend->query_response_time_range_base); GOTO_EXIT(EXIT_FAILURE); } srv->query_response_time_range_base = frontend->query_response_time_range_base; if (frontend->lastest_query_num < 0) { g_log_dbproxy(g_critical, "--lastest-query-num has to be >= 0, is %d", frontend->lastest_query_num); GOTO_EXIT(EXIT_FAILURE); } srv->proxy_reserved->lastest_query_num = frontend->lastest_query_num; if (frontend->query_filter_time_threshold < -1) { g_log_dbproxy(g_critical, "--query-filter-time-threshold has to be >= -1, is %d", frontend->query_filter_time_threshold); GOTO_EXIT(EXIT_FAILURE); } srv->proxy_reserved->query_filter_time_threshold = frontend->query_filter_time_threshold; if (frontend->query_filter_frequent_threshold < 0) { g_log_dbproxy(g_critical, "--query-filter-frequent-threshold has to be >= 0, is %f", frontend->query_filter_frequent_threshold); GOTO_EXIT(EXIT_FAILURE); } srv->proxy_reserved->query_filter_frequent_threshold = frontend->query_filter_frequent_threshold; if (frontend->access_num_per_time_window < 1) { g_log_dbproxy(g_critical, "--freq-access-num-threshold has to be >= 1, is %d", frontend->access_num_per_time_window); GOTO_EXIT(EXIT_FAILURE); } srv->proxy_reserved->access_num_per_time_window = frontend->access_num_per_time_window; int flag = 0; if (frontend->auto_filter_flag == NULL || strcasecmp(frontend->auto_filter_flag, "OFF") == 0) flag = 0; else if (strcasecmp(frontend->auto_filter_flag, "ON") == 0) flag = 1; else { g_log_dbproxy(g_critical, "--auto-filter-flag has to be on or off, is %s", frontend->auto_filter_flag); GOTO_EXIT(EXIT_FAILURE); } srv->proxy_filter->auto_filter_flag = flag; if (frontend->manual_filter_flag == NULL || strcasecmp(frontend->manual_filter_flag, "OFF") == 0) flag = 0; else if (strcasecmp(frontend->manual_filter_flag, "ON") == 0) flag = 1; else { g_log_dbproxy(g_critical, "--manual-filter-flag has to be on or off, is %s", frontend->manual_filter_flag); GOTO_EXIT(EXIT_FAILURE); } srv->proxy_filter->manual_filter_flag = flag; if (frontend->max_backend_tr < 0) { g_log_dbproxy(g_critical, "--backend-max-thread-running has to be >= 0, is %d", frontend->max_backend_tr); GOTO_EXIT(EXIT_FAILURE); } srv->max_backend_tr = frontend->max_backend_tr; if (frontend->thread_running_sleep_delay < 1) { g_log_dbproxy(g_critical, "--thread-running-sleep-delay has to be >= 1, is %d", frontend->thread_running_sleep_delay); GOTO_EXIT(EXIT_FAILURE); } srv->thread_running_sleep_delay = frontend->thread_running_sleep_delay; if (frontend->remove_backend_timeout < 0) { g_log_dbproxy(g_critical, "--remove-backend-timeout has to be >= 0, is %d", frontend->remove_backend_timeout); GOTO_EXIT(EXIT_FAILURE); } /* assign the mysqld part to the */ network_mysqld_init(srv, frontend->default_file, frontend->remove_backend_timeout); /* starts the also the lua-scope, LUA_PATH and LUA_CPATH have to be set before this being called */ #ifdef HAVE_SIGACTION /* register the sigsegv interceptor */ memset(&sigsegv_sa, 0, sizeof(sigsegv_sa)); sigsegv_sa.sa_handler = sigsegv_handler; sigemptyset(&sigsegv_sa.sa_mask); sigaction(SIGSEGV, &sigsegv_sa, NULL); #ifdef SIGBUS sigaction(SIGBUS, &sigsegv_sa, NULL); #endif sigaction(SIGILL, &sigsegv_sa, NULL); sigaction(SIGFPE, &sigsegv_sa, NULL); /*if (frontend->invoke_dbg_on_crash && !(RUNNING_ON_VALGRIND)) { sigaction(SIGSEGV, &sigsegv_sa, NULL); }*/ #endif /* * some plugins cannot see the chassis struct from the point * where they open files, hence we must make it available */ srv->base_dir = g_strdup(frontend->base_dir); chassis_frontend_init_plugin_dir(&frontend->plugin_dir, srv->base_dir); /* * these are used before we gathered all the options * from the plugins, thus we need to fix them up before * dealing with all the rest. */ if (chassis_frontend_init_logdir(frontend->log_path)) { GOTO_EXIT(EXIT_FAILURE); } chassis_resolve_path(srv->base_dir, &frontend->log_path); chassis_resolve_path(srv->base_dir, &frontend->plugin_dir); /* * start the logging and pid */ if (frontend->log_path) { if (frontend->instance_name == NULL) { gchar *default_file = frontend->default_file; gchar *slash = strrchr(default_file, '/'); if (slash != NULL) ++slash; else slash = default_file; gchar *dot = strrchr(default_file, '.'); if (dot != NULL && dot >= slash) frontend->instance_name = g_strndup(slash, dot-slash); else frontend->instance_name = g_strdup(slash); } log->log_filename = g_strdup_printf("%s/%s.log", frontend->log_path, frontend->instance_name); frontend->pid_file = g_strdup_printf("%s/%s.pid", frontend->log_path, frontend->instance_name); srv->log_path = g_strdup(frontend->log_path); } log->use_syslog = frontend->use_syslog; if (log->log_filename && log->use_syslog) { g_log_dbproxy(g_critical, "log-file and log-use-syslog were given, but only one is allowed"); GOTO_EXIT(EXIT_FAILURE); } /* * we have to drop root privileges in chassis_mainloop() after * the plugins opened the ports, so we need the user there */ if (frontend->user) { srv->user = g_strdup(frontend->user); } /** * create the path of sql and its parents path if it is necessary */ gchar *sql_path = g_strdup_printf("%s/%s", srv->log_path, SQL_LOG_DIR); if(g_mkdir_with_parents(sql_path, S_IRWXU|S_IRWXG|S_IRWXO) != 0) { g_log_dbproxy(g_critical, "g_mkdir_with_parents(%s) failed: %s", sql_path, g_strerror(errno)); g_free(sql_path); GOTO_EXIT(EXIT_FAILURE); } g_free(sql_path); /* * check whether we should drop root privileges */ #ifndef _win32 if (srv->user) { struct passwd *user_info; uid_t user_id= geteuid(); /* Don't bother if we aren't superuser */ if (user_id) { g_log_dbproxy(g_warning, "current user is not root, --user is ignored"); } else { if (NULL == (user_info = getpwnam(srv->user))) { g_log_dbproxy(g_critical, "unknown user: %s", srv->user); return -1; } /* chown log-path */ if (-1 == chown_recursion(srv->log_path, user_info->pw_uid, user_info->pw_gid)) { g_log_dbproxy(g_critical, "chown_recursion(%s) failed: %s", srv->log_path, g_strerror(errno)); GOTO_EXIT(EXIT_FAILURE); } setgid(user_info->pw_gid); setuid(user_info->pw_uid); g_log_dbproxy(g_debug, "running as user: %s (%d/%d)", srv->user, user_info->pw_uid, user_info->pw_gid); /*check the config file can read or write, and the config file dir can execute*/ gchar *config_file = frontend->default_file; /*if the config_file is relative get the real path */ char resolved_path[PATH_MAX]; if (g_path_is_absolute(config_file) == FALSE) { realpath(config_file, resolved_path); config_file = resolved_path; } gchar *config_dir = g_path_get_dirname(config_file); if (-1 == faccessat(0, config_file, R_OK | W_OK, AT_EACCESS) || -1 == faccessat(0, config_dir, X_OK | W_OK, AT_EACCESS)) { g_free(config_dir); g_log_dbproxy(g_critical, "%s don't have correct privilege for the user %s set in the config file, config file should have read write privileges and the config file dir should have execute and write privilege.", config_file, srv->user); GOTO_EXIT(EXIT_FAILURE); } g_free(config_dir); g_log_dbproxy(g_message, "running as user: %s (%d/%d)", srv->user, user_info->pw_uid, user_info->pw_gid); } } #endif if (log->log_filename && FALSE == chassis_log_open(log)) { g_log_dbproxy(g_critical, "can't open log-file '%s': %s", log->log_filename, g_strerror(errno)); GOTO_EXIT(EXIT_FAILURE); } /* handle log-level after the config-file is read, just in case it is specified in the file */ if (frontend->log_level) { if (0 != chassis_log_set_level(log, frontend->log_level)) { g_log_dbproxy(g_critical, "--log-level=... failed, level '%s' is unknown ", frontend->log_level); GOTO_EXIT(EXIT_FAILURE); } } else { /* if it is not set, use "critical" as default */ log->min_lvl = G_LOG_LEVEL_CRITICAL; } if (frontend->log_trace_modules < 0) { g_log_dbproxy(g_critical, "log-trace-modules has to be >= 0, is %d", frontend->log_trace_modules); GOTO_EXIT(EXIT_FAILURE); } srv->log->log_trace_modules = frontend->log_trace_modules; if(frontend->db_connect_timeout < 0) { g_log_dbproxy(g_critical, "db_connect_timeout has to be >= 0.0, is %lf", frontend->db_connect_timeout); GOTO_EXIT(EXIT_FAILURE); } srv->db_connect_timeout = frontend->db_connect_timeout; /* * the MySQL Proxy should load 'admin' and 'proxy' plugins */ if (!frontend->plugin_names) { frontend->plugin_names = g_new(char *, 3); frontend->plugin_names[0] = g_strdup("admin"); frontend->plugin_names[1] = g_strdup("proxy"); frontend->plugin_names[2] = NULL; }