diff options
Diffstat (limited to 'server-tools/instance-manager/options.cc')
-rw-r--r-- | server-tools/instance-manager/options.cc | 416 |
1 files changed, 283 insertions, 133 deletions
diff --git a/server-tools/instance-manager/options.cc b/server-tools/instance-manager/options.cc index 8de592f59b6..c8870a1ac39 100644 --- a/server-tools/instance-manager/options.cc +++ b/server-tools/instance-manager/options.cc @@ -20,46 +20,89 @@ #include "options.h" -#include "priv.h" -#include "portability.h" +#include <my_global.h> #include <my_sys.h> #include <my_getopt.h> -#include <m_string.h> #include <mysql_com.h> +#include "exit_codes.h" +#include "log.h" +#include "portability.h" +#include "priv.h" +#include "user_management_commands.h" + #define QUOTE2(x) #x #define QUOTE(x) QUOTE2(x) #ifdef __WIN__ -char Options::install_as_service; -char Options::remove_service; -char Options::stand_alone; -char windows_config_file[FN_REFLEN]; -char default_password_file_name[FN_REFLEN]; -char default_log_file_name[FN_REFLEN]; -const char *Options::config_file= windows_config_file; -#else -char Options::run_as_service; -const char *Options::user= 0; /* No default value */ -const char *default_password_file_name= QUOTE(DEFAULT_PASSWORD_FILE_NAME); -const char *default_log_file_name= QUOTE(DEFAULT_LOG_FILE_NAME); -const char *Options::config_file= QUOTE(DEFAULT_CONFIG_FILE); + +/* Define holders for default values. */ + +static char win_dflt_config_file_name[FN_REFLEN]; +static char win_dflt_password_file_name[FN_REFLEN]; +static char win_dflt_pid_file_name[FN_REFLEN]; +static char win_dflt_socket_file_name[FN_REFLEN]; + +static char win_dflt_mysqld_path[FN_REFLEN]; + +/* Define and initialize Windows-specific options. */ + +my_bool Options::Service::install_as_service; +my_bool Options::Service::remove_service; +my_bool Options::Service::stand_alone; + +const char *Options::Main::config_file= win_dflt_config_file_name; +const char *Options::Main::password_file_name= win_dflt_password_file_name; +const char *Options::Main::pid_file_name= win_dflt_pid_file_name; +const char *Options::Main::socket_file_name= win_dflt_socket_file_name; + +const char *Options::Main::default_mysqld_path= win_dflt_mysqld_path; + +static int setup_windows_defaults(); + +#else /* UNIX */ + +/* Define and initialize UNIX-specific options. */ + +my_bool Options::Daemon::run_as_service= FALSE; +const char *Options::Daemon::log_file_name= QUOTE(DEFAULT_LOG_FILE_NAME); +const char *Options::Daemon::user= NULL; /* No default value */ const char *Options::angel_pid_file_name= NULL; + +const char *Options::Main::config_file= QUOTE(DEFAULT_CONFIG_FILE); +const char * +Options::Main::password_file_name= QUOTE(DEFAULT_PASSWORD_FILE_NAME); +const char *Options::Main::pid_file_name= QUOTE(DEFAULT_PID_FILE_NAME); +const char *Options::Main::socket_file_name= QUOTE(DEFAULT_SOCKET_FILE_NAME); + +const char *Options::Main::default_mysqld_path= QUOTE(DEFAULT_MYSQLD_PATH); + #endif -const char *Options::log_file_name= default_log_file_name; -const char *Options::pid_file_name= QUOTE(DEFAULT_PID_FILE_NAME); -const char *Options::socket_file_name= QUOTE(DEFAULT_SOCKET_FILE_NAME); -const char *Options::password_file_name= default_password_file_name; -const char *Options::default_mysqld_path= QUOTE(DEFAULT_MYSQLD_PATH); -const char *Options::bind_address= 0; /* No default value */ -uint Options::monitoring_interval= DEFAULT_MONITORING_INTERVAL; -uint Options::port_number= DEFAULT_PORT; -/* just to declare */ + +/* Remember if the config file was forced. */ + +bool Options::Main::is_forced_default_file= FALSE; + +/* Define and initialize common options. */ + +const char *Options::Main::bind_address= NULL; /* No default value */ +uint Options::Main::monitoring_interval= DEFAULT_MONITORING_INTERVAL; +uint Options::Main::port_number= DEFAULT_PORT; +my_bool Options::Main::mysqld_safe_compatible= FALSE; + +/* Options::User_management */ + +char *Options::User_management::user_name= NULL; +char *Options::User_management::password= NULL; + +User_management_cmd *Options::User_management::cmd= NULL; + +/* Private members. */ + char **Options::saved_argv= NULL; -/* Remember if the config file was forced */ -bool Options::is_forced_default_file= 0; + #ifndef DBUG_OFF -const char *Options::default_dbug_option= "d:t:i:O,im.trace"; +const char *Options::Debug::config_str= "d:t:i:O,im.trace"; #endif static const char * const ANGEL_PID_FILE_SUFFIX= ".angel.pid"; @@ -71,24 +114,34 @@ static const int ANGEL_PID_FILE_SUFFIX_LEN= strlen(ANGEL_PID_FILE_SUFFIX); */ enum options { + OPT_PASSWD= 'P', + OPT_USERNAME= 'u', + OPT_PASSWORD= 'p', OPT_LOG= 256, OPT_PID_FILE, OPT_SOCKET, OPT_PASSWORD_FILE, OPT_MYSQLD_PATH, -#ifndef __WIN__ - OPT_RUN_AS_SERVICE, - OPT_USER, - OPT_ANGEL_PID_FILE, -#else +#ifdef __WIN__ OPT_INSTALL_SERVICE, OPT_REMOVE_SERVICE, OPT_STAND_ALONE, +#else + OPT_RUN_AS_SERVICE, + OPT_USER, + OPT_ANGEL_PID_FILE, #endif OPT_MONITORING_INTERVAL, OPT_PORT, OPT_WAIT_TIMEOUT, - OPT_BIND_ADDRESS + OPT_BIND_ADDRESS, + OPT_ADD_USER, + OPT_DROP_USER, + OPT_EDIT_USER, + OPT_CLEAN_PASSWORD_FILE, + OPT_CHECK_PASSWORD_FILE, + OPT_LIST_USERS, + OPT_MYSQLD_SAFE_COMPATIBLE }; static struct my_option my_long_options[] = @@ -96,6 +149,10 @@ static struct my_option my_long_options[] = { "help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "add-user", OPT_ADD_USER, + "Add a user to the password file", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, + #ifndef __WIN__ { "angel-pid-file", OPT_ANGEL_PID_FILE, "Pid file for angel process.", (gptr *) &Options::angel_pid_file_name, @@ -104,93 +161,146 @@ static struct my_option my_long_options[] = #endif { "bind-address", OPT_BIND_ADDRESS, "Bind address to use for connection.", - (gptr *) &Options::bind_address, (gptr *) &Options::bind_address, + (gptr *) &Options::Main::bind_address, + (gptr *) &Options::Main::bind_address, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "check-password-file", OPT_CHECK_PASSWORD_FILE, + "Check the password file for consistency", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, + + { "clean-password-file", OPT_CLEAN_PASSWORD_FILE, + "Clean the password file", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, + #ifndef DBUG_OFF {"debug", '#', "Debug log.", - (gptr*) &Options::default_dbug_option, (gptr*) &Options::default_dbug_option, + (gptr *) &Options::Debug::config_str, + (gptr *) &Options::Debug::config_str, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif { "default-mysqld-path", OPT_MYSQLD_PATH, "Where to look for MySQL" " Server binary.", - (gptr *) &Options::default_mysqld_path, - (gptr *) &Options::default_mysqld_path, + (gptr *) &Options::Main::default_mysqld_path, + (gptr *) &Options::Main::default_mysqld_path, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 }, + + { "drop-user", OPT_DROP_USER, + "Drop existing user from the password file", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, + + { "edit-user", OPT_EDIT_USER, + "Edit existing user in the password file", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, + #ifdef __WIN__ { "install", OPT_INSTALL_SERVICE, "Install as system service.", - (gptr *) &Options::install_as_service, (gptr*) &Options::install_as_service, + (gptr *) &Options::Service::install_as_service, + (gptr *) &Options::Service::install_as_service, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 }, #endif + { "list-users", OPT_LIST_USERS, + "Print out a list of registered users", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, + +#ifndef __WIN__ { "log", OPT_LOG, "Path to log file. Used only with --run-as-service.", - (gptr *) &Options::log_file_name, (gptr *) &Options::log_file_name, + (gptr *) &Options::Daemon::log_file_name, + (gptr *) &Options::Daemon::log_file_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, +#endif { "monitoring-interval", OPT_MONITORING_INTERVAL, "Interval to monitor" " instances in seconds.", - (gptr *) &Options::monitoring_interval, - (gptr *) &Options::monitoring_interval, + (gptr *) &Options::Main::monitoring_interval, + (gptr *) &Options::Main::monitoring_interval, 0, GET_UINT, REQUIRED_ARG, DEFAULT_MONITORING_INTERVAL, 0, 0, 0, 0, 0 }, - { "passwd", 'P', "Prepare entry for passwd file and exit.", 0, 0, 0, - GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, + { "mysqld-safe-compatible", OPT_MYSQLD_SAFE_COMPATIBLE, + "Start Instance Manager in mysqld_safe compatible manner", + (gptr *) &Options::Main::mysqld_safe_compatible, + (gptr *) &Options::Main::mysqld_safe_compatible, + 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 }, + + { "passwd", OPT_PASSWD, + "Prepare an entry for the password file and exit.", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, + + { "password", OPT_PASSWORD, "Password to update the password file", + (gptr *) &Options::User_management::password, + (gptr *) &Options::User_management::password, + 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, - { "password-file", OPT_PASSWORD_FILE, "Look for Instance Manager users" - " and passwords here.", - (gptr *) &Options::password_file_name, - (gptr *) &Options::password_file_name, + { "password-file", OPT_PASSWORD_FILE, + "Look for Instance Manager users and passwords here.", + (gptr *) &Options::Main::password_file_name, + (gptr *) &Options::Main::password_file_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, { "pid-file", OPT_PID_FILE, "Pid file to use.", - (gptr *) &Options::pid_file_name, (gptr *) &Options::pid_file_name, + (gptr *) &Options::Main::pid_file_name, + (gptr *) &Options::Main::pid_file_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, { "port", OPT_PORT, "Port number to use for connections", - (gptr *) &Options::port_number, (gptr *) &Options::port_number, + (gptr *) &Options::Main::port_number, + (gptr *) &Options::Main::port_number, 0, GET_UINT, REQUIRED_ARG, DEFAULT_PORT, 0, 0, 0, 0, 0 }, #ifdef __WIN__ { "remove", OPT_REMOVE_SERVICE, "Remove system service.", - (gptr *)&Options::remove_service, (gptr*) &Options::remove_service, + (gptr *) &Options::Service::remove_service, + (gptr *) &Options::Service::remove_service, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0}, #else { "run-as-service", OPT_RUN_AS_SERVICE, - "Daemonize and start angel process.", (gptr *) &Options::run_as_service, + "Daemonize and start angel process.", + (gptr *) &Options::Daemon::run_as_service, 0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 }, #endif { "socket", OPT_SOCKET, "Socket file to use for connection.", - (gptr *) &Options::socket_file_name, (gptr *) &Options::socket_file_name, + (gptr *) &Options::Main::socket_file_name, + (gptr *) &Options::Main::socket_file_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, #ifdef __WIN__ { "standalone", OPT_STAND_ALONE, "Run the application in stand alone mode.", - (gptr *)&Options::stand_alone, (gptr*) &Options::stand_alone, + (gptr *) &Options::Service::stand_alone, + (gptr *) &Options::Service::stand_alone, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0}, #else { "user", OPT_USER, "Username to start mysqlmanager", - (gptr *) &Options::user, - (gptr *) &Options::user, + (gptr *) &Options::Daemon::user, + (gptr *) &Options::Daemon::user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, #endif + { "username", OPT_USERNAME, + "Username to update the password file", + (gptr *) &Options::User_management::user_name, + (gptr *) &Options::User_management::user_name, + 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + { "version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, { "wait-timeout", OPT_WAIT_TIMEOUT, "The number of seconds IM waits " "for activity on a connection before closing it.", - (gptr *) &net_read_timeout, (gptr *) &net_read_timeout, 0, GET_ULONG, - REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0 }, + (gptr *) &net_read_timeout, + (gptr *) &net_read_timeout, + 0, GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 } }; static void version() { - printf("%s Ver %s for %s on %s\n", my_progname, mysqlmanager_version, + printf("%s Ver %s for %s on %s\n", my_progname, + (const char *) mysqlmanager_version.str, SYSTEM_TYPE, MACHINE_TYPE); } @@ -218,37 +328,6 @@ static void usage() } -static void passwd() -{ - char user[1024], *p; - const char *pw1, *pw2; - char pw1msg[]= "Enter password: "; - char pw2msg[]= "Re-type password: "; - char crypted_pw[SCRAMBLED_PASSWORD_CHAR_LENGTH + 1]; - - fprintf(stderr, "Creating record for new user.\n"); - fprintf(stderr, "Enter user name: "); - if (!fgets(user, sizeof(user), stdin)) - { - fprintf(stderr, "Unable to read user.\n"); - return; - } - if ((p= strchr(user, '\n'))) *p= 0; - - pw1= get_tty_password(pw1msg); - pw2= get_tty_password(pw2msg); - - if (strcmp(pw1, pw2)) - { - fprintf(stderr, "Sorry, passwords do not match.\n"); - return; - } - - make_scrambled_password(crypted_pw, pw1); - printf("%s:%s\n", user, crypted_pw); -} - - C_MODE_START static my_bool @@ -260,16 +339,52 @@ get_one_option(int optid, case 'V': version(); exit(0); - case 'P': - passwd(); - exit(0); + case OPT_PASSWD: + case OPT_ADD_USER: + case OPT_DROP_USER: + case OPT_EDIT_USER: + case OPT_CLEAN_PASSWORD_FILE: + case OPT_CHECK_PASSWORD_FILE: + case OPT_LIST_USERS: + if (Options::User_management::cmd) + { + fprintf(stderr, "Error: only one password-management command " + "can be specified at a time.\n"); + exit(ERR_INVALID_USAGE); + } + + switch (optid) { + case OPT_PASSWD: + Options::User_management::cmd= new Passwd_cmd(); + break; + case OPT_ADD_USER: + Options::User_management::cmd= new Add_user_cmd(); + break; + case OPT_DROP_USER: + Options::User_management::cmd= new Drop_user_cmd(); + break; + case OPT_EDIT_USER: + Options::User_management::cmd= new Edit_user_cmd(); + break; + case OPT_CLEAN_PASSWORD_FILE: + Options::User_management::cmd= new Clean_db_cmd(); + break; + case OPT_CHECK_PASSWORD_FILE: + Options::User_management::cmd= new Check_db_cmd(); + break; + case OPT_LIST_USERS: + Options::User_management::cmd= new List_users_cmd(); + break; + } + + break; case '?': usage(); exit(0); case '#': #ifndef DBUG_OFF - DBUG_SET(argument ? argument : Options::default_dbug_option); - DBUG_SET_INITIAL(argument ? argument : Options::default_dbug_option); + DBUG_SET(argument ? argument : Options::Debug::config_str); + DBUG_SET_INITIAL(argument ? argument : Options::Debug::config_str); #endif break; } @@ -295,8 +410,8 @@ int Options::load(int argc, char **argv) { if (is_prefix(argv[1], "--defaults-file=")) { - Options::config_file= strchr(argv[1], '=') + 1; - Options::is_forced_default_file= 1; + Main::config_file= strchr(argv[1], '=') + 1; + Main::is_forced_default_file= TRUE; } if (is_prefix(argv[1], "--defaults-extra-file=") || is_prefix(argv[1], "--no-defaults")) @@ -305,29 +420,44 @@ int Options::load(int argc, char **argv) fprintf(stderr, "The --defaults-extra-file and --no-defaults options" " are not supported by\n" "Instance Manager. Program aborted.\n"); - goto err; + return ERR_INVALID_USAGE; } } #ifdef __WIN__ if (setup_windows_defaults()) - goto err; + { + fprintf(stderr, "Internal error: could not setup default values.\n"); + return ERR_OUT_OF_MEMORY; + } #endif + /* load_defaults will reset saved_argv with a new allocated list */ saved_argv= argv; /* config-file options are prepended to command-line ones */ - load_defaults(config_file, default_groups, &argc, - &saved_argv); - if ((handle_options(&argc, &saved_argv, my_long_options, - get_one_option)) != 0) - goto err; + log_info("Loading config file '%s'...", + (const char *) Main::config_file); + + load_defaults(Main::config_file, default_groups, &argc, &saved_argv); + + if ((handle_options(&argc, &saved_argv, my_long_options, get_one_option))) + return ERR_INVALID_USAGE; + + if (!User_management::cmd && + (User_management::user_name || User_management::password)) + { + fprintf(stderr, + "--username and/or --password options have been specified, " + "but no password-management command has been given.\n"); + return ERR_INVALID_USAGE; + } #ifndef __WIN__ - if (Options::run_as_service) + if (Options::Daemon::run_as_service) { - if (Options::angel_pid_file_name == NULL) + if (Options::Daemon::angel_pid_file_name == NULL) { /* Calculate angel pid file on the IM pid file basis: replace the @@ -339,10 +469,11 @@ int Options::load(int argc, char **argv) char *base_name_ptr; char *ext_ptr; - angel_pid_file_name= (char *) malloc(strlen(Options::pid_file_name) + - ANGEL_PID_FILE_SUFFIX_LEN); + angel_pid_file_name= + (char *) malloc(strlen(Options::Main::pid_file_name) + + ANGEL_PID_FILE_SUFFIX_LEN); - strcpy(angel_pid_file_name, Options::pid_file_name); + strcpy(angel_pid_file_name, Options::Main::pid_file_name); base_name_ptr= strrchr(angel_pid_file_name, '/'); @@ -355,26 +486,25 @@ int Options::load(int argc, char **argv) strcat(angel_pid_file_name, ANGEL_PID_FILE_SUFFIX); - Options::angel_pid_file_name= angel_pid_file_name; + Options::Daemon::angel_pid_file_name= angel_pid_file_name; } else { - Options::angel_pid_file_name= strdup(Options::angel_pid_file_name); + Options::Daemon::angel_pid_file_name= + strdup(Options::Daemon::angel_pid_file_name); } } #endif return 0; - -err: - return 1; } void Options::cleanup() { - /* free_defaults returns nothing */ - if (Options::saved_argv != NULL) - free_defaults(Options::saved_argv); + if (saved_argv) + free_defaults(saved_argv); + + delete User_management::cmd; #ifndef __WIN__ if (Options::run_as_service) @@ -384,25 +514,45 @@ void Options::cleanup() #ifdef __WIN__ -int Options::setup_windows_defaults() +static int setup_windows_defaults() { - if (!GetModuleFileName(NULL, default_password_file_name, - sizeof(default_password_file_name))) - return 1; - char *filename= strstr(default_password_file_name, ".exe"); - strcpy(filename, ".passwd"); - - if (!GetModuleFileName(NULL, default_log_file_name, - sizeof(default_log_file_name))) + char module_full_name[FN_REFLEN]; + char dir_name[FN_REFLEN]; + char base_name[FN_REFLEN]; + char im_name[FN_REFLEN]; + char *base_name_ptr; + char *ptr; + + /* Determine dirname and basename. */ + + if (!GetModuleFileName(NULL, module_full_name, sizeof (module_full_name)) || + !GetFullPathName(module_full_name, sizeof (dir_name), dir_name, + &base_name_ptr)) + { return 1; - filename= strstr(default_log_file_name, ".exe"); - strcpy(filename, ".log"); + } + + strmake(base_name, base_name_ptr, FN_REFLEN); + *base_name_ptr= 0; + + strmake(im_name, base_name, FN_REFLEN); + ptr= strrchr(im_name, '.'); + + if (!ptr) + return 1; + + *ptr= 0; + + /* Initialize the defaults. */ + + strxmov(win_dflt_config_file_name, dir_name, DFLT_CONFIG_FILE_NAME, NullS); + strxmov(win_dflt_mysqld_path, dir_name, DFLT_MYSQLD_PATH, NullS); + strxmov(win_dflt_password_file_name, dir_name, im_name, DFLT_PASSWD_FILE_EXT, + NullS); + strxmov(win_dflt_pid_file_name, dir_name, im_name, DFLT_PID_FILE_EXT, NullS); + strxmov(win_dflt_socket_file_name, dir_name, im_name, DFLT_SOCKET_FILE_EXT, + NullS); - if (!GetModuleFileName(NULL, windows_config_file, - sizeof(windows_config_file))) - return 1; - char *slash= strrchr(windows_config_file, '\\'); - strcpy(slash, "\\my.ini"); return 0; } |