00001 /* Copyright (C) 2003 MySQL AB & MySQL Finland AB & TCX DataKonsult AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 #if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION) 00018 #pragma implementation 00019 #endif 00020 00021 #include "options.h" 00022 00023 #include <my_global.h> 00024 #include <my_sys.h> 00025 #include <my_getopt.h> 00026 #include <mysql_com.h> 00027 00028 #include "exit_codes.h" 00029 #include "log.h" 00030 #include "portability.h" 00031 #include "priv.h" 00032 #include "user_management_commands.h" 00033 00034 #define QUOTE2(x) #x 00035 #define QUOTE(x) QUOTE2(x) 00036 00037 #ifdef __WIN__ 00038 00039 /* Define holders for default values. */ 00040 00041 static char win_dflt_config_file_name[FN_REFLEN]; 00042 static char win_dflt_password_file_name[FN_REFLEN]; 00043 static char win_dflt_pid_file_name[FN_REFLEN]; 00044 static char win_dflt_socket_file_name[FN_REFLEN]; 00045 00046 static char win_dflt_mysqld_path[FN_REFLEN]; 00047 00048 /* Define and initialize Windows-specific options. */ 00049 00050 my_bool Options::Service::install_as_service; 00051 my_bool Options::Service::remove_service; 00052 my_bool Options::Service::stand_alone; 00053 00054 const char *Options::Main::config_file= win_dflt_config_file_name; 00055 const char *Options::Main::password_file_name= win_dflt_password_file_name; 00056 const char *Options::Main::pid_file_name= win_dflt_pid_file_name; 00057 const char *Options::Main::socket_file_name= win_dflt_socket_file_name; 00058 00059 const char *Options::Main::default_mysqld_path= win_dflt_mysqld_path; 00060 00061 static int setup_windows_defaults(); 00062 00063 #else /* UNIX */ 00064 00065 /* Define and initialize UNIX-specific options. */ 00066 00067 my_bool Options::Daemon::run_as_service= FALSE; 00068 const char *Options::Daemon::log_file_name= QUOTE(DEFAULT_LOG_FILE_NAME); 00069 const char *Options::Daemon::user= NULL; /* No default value */ 00070 const char *Options::Daemon::angel_pid_file_name= NULL; 00071 00072 const char *Options::Main::config_file= QUOTE(DEFAULT_CONFIG_FILE); 00073 const char * 00074 Options::Main::password_file_name= QUOTE(DEFAULT_PASSWORD_FILE_NAME); 00075 const char *Options::Main::pid_file_name= QUOTE(DEFAULT_PID_FILE_NAME); 00076 const char *Options::Main::socket_file_name= QUOTE(DEFAULT_SOCKET_FILE_NAME); 00077 00078 const char *Options::Main::default_mysqld_path= QUOTE(DEFAULT_MYSQLD_PATH); 00079 00080 #endif 00081 00082 /* Remember if the config file was forced. */ 00083 00084 bool Options::Main::is_forced_default_file= FALSE; 00085 00086 /* Define and initialize common options. */ 00087 00088 const char *Options::Main::bind_address= NULL; /* No default value */ 00089 uint Options::Main::monitoring_interval= DEFAULT_MONITORING_INTERVAL; 00090 uint Options::Main::port_number= DEFAULT_PORT; 00091 my_bool Options::Main::mysqld_safe_compatible= FALSE; 00092 00093 /* Options::User_management */ 00094 00095 char *Options::User_management::user_name= NULL; 00096 char *Options::User_management::password= NULL; 00097 00098 User_management_cmd *Options::User_management::cmd= NULL; 00099 00100 /* Private members. */ 00101 00102 char **Options::saved_argv= NULL; 00103 00104 #ifndef DBUG_OFF 00105 const char *Options::Debug::config_str= "d:t:i:O,im.trace"; 00106 #endif 00107 00108 static const char * const ANGEL_PID_FILE_SUFFIX= ".angel.pid"; 00109 static const int ANGEL_PID_FILE_SUFFIX_LEN= strlen(ANGEL_PID_FILE_SUFFIX); 00110 00111 /* 00112 List of options, accepted by the instance manager. 00113 List must be closed with empty option. 00114 */ 00115 00116 enum options { 00117 OPT_USERNAME= 'u', 00118 OPT_PASSWORD= 'p', 00119 OPT_LOG= 256, 00120 OPT_PID_FILE, 00121 OPT_SOCKET, 00122 OPT_PASSWORD_FILE, 00123 OPT_MYSQLD_PATH, 00124 #ifdef __WIN__ 00125 OPT_INSTALL_SERVICE, 00126 OPT_REMOVE_SERVICE, 00127 OPT_STAND_ALONE, 00128 #else 00129 OPT_RUN_AS_SERVICE, 00130 OPT_USER, 00131 OPT_ANGEL_PID_FILE, 00132 #endif 00133 OPT_MONITORING_INTERVAL, 00134 OPT_PORT, 00135 OPT_WAIT_TIMEOUT, 00136 OPT_BIND_ADDRESS, 00137 OPT_PRINT_PASSWORD_LINE, 00138 OPT_ADD_USER, 00139 OPT_DROP_USER, 00140 OPT_EDIT_USER, 00141 OPT_CLEAN_PASSWORD_FILE, 00142 OPT_CHECK_PASSWORD_FILE, 00143 OPT_LIST_USERS, 00144 OPT_MYSQLD_SAFE_COMPATIBLE 00145 }; 00146 00147 static struct my_option my_long_options[] = 00148 { 00149 { "help", '?', "Display this help and exit.", 00150 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, 00151 00152 { "add-user", OPT_ADD_USER, 00153 "Add a user to the password file", 00154 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, 00155 00156 #ifndef __WIN__ 00157 { "angel-pid-file", OPT_ANGEL_PID_FILE, "Pid file for angel process.", 00158 (gptr *) &Options::Daemon::angel_pid_file_name, 00159 (gptr *) &Options::Daemon::angel_pid_file_name, 00160 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, 00161 #endif 00162 00163 { "bind-address", OPT_BIND_ADDRESS, "Bind address to use for connection.", 00164 (gptr *) &Options::Main::bind_address, 00165 (gptr *) &Options::Main::bind_address, 00166 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, 00167 00168 { "check-password-file", OPT_CHECK_PASSWORD_FILE, 00169 "Check the password file for consistency", 00170 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, 00171 00172 { "clean-password-file", OPT_CLEAN_PASSWORD_FILE, 00173 "Clean the password file", 00174 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, 00175 00176 #ifndef DBUG_OFF 00177 {"debug", '#', "Debug log.", 00178 (gptr *) &Options::Debug::config_str, 00179 (gptr *) &Options::Debug::config_str, 00180 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, 00181 #endif 00182 00183 { "default-mysqld-path", OPT_MYSQLD_PATH, "Where to look for MySQL" 00184 " Server binary.", 00185 (gptr *) &Options::Main::default_mysqld_path, 00186 (gptr *) &Options::Main::default_mysqld_path, 00187 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 }, 00188 00189 { "drop-user", OPT_DROP_USER, 00190 "Drop existing user from the password file", 00191 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, 00192 00193 { "edit-user", OPT_EDIT_USER, 00194 "Edit existing user in the password file", 00195 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, 00196 00197 #ifdef __WIN__ 00198 { "install", OPT_INSTALL_SERVICE, "Install as system service.", 00199 (gptr *) &Options::Service::install_as_service, 00200 (gptr *) &Options::Service::install_as_service, 00201 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 }, 00202 #endif 00203 00204 { "list-users", OPT_LIST_USERS, 00205 "Print out a list of registered users", 00206 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, 00207 00208 #ifndef __WIN__ 00209 { "log", OPT_LOG, "Path to log file. Used only with --run-as-service.", 00210 (gptr *) &Options::Daemon::log_file_name, 00211 (gptr *) &Options::Daemon::log_file_name, 00212 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, 00213 #endif 00214 00215 { "monitoring-interval", OPT_MONITORING_INTERVAL, "Interval to monitor" 00216 " instances in seconds.", 00217 (gptr *) &Options::Main::monitoring_interval, 00218 (gptr *) &Options::Main::monitoring_interval, 00219 0, GET_UINT, REQUIRED_ARG, DEFAULT_MONITORING_INTERVAL, 00220 0, 0, 0, 0, 0 }, 00221 00222 { "mysqld-safe-compatible", OPT_MYSQLD_SAFE_COMPATIBLE, 00223 "Start Instance Manager in mysqld_safe compatible manner", 00224 (gptr *) &Options::Main::mysqld_safe_compatible, 00225 (gptr *) &Options::Main::mysqld_safe_compatible, 00226 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 }, 00227 00228 { "print-password-line", OPT_PRINT_PASSWORD_LINE, 00229 "Print out a user entry as a line for the password file and exit.", 00230 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, 00231 00232 { "password", OPT_PASSWORD, "Password to update the password file", 00233 (gptr *) &Options::User_management::password, 00234 (gptr *) &Options::User_management::password, 00235 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, 00236 00237 { "password-file", OPT_PASSWORD_FILE, 00238 "Look for Instance Manager users and passwords here.", 00239 (gptr *) &Options::Main::password_file_name, 00240 (gptr *) &Options::Main::password_file_name, 00241 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, 00242 00243 { "pid-file", OPT_PID_FILE, "Pid file to use.", 00244 (gptr *) &Options::Main::pid_file_name, 00245 (gptr *) &Options::Main::pid_file_name, 00246 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, 00247 00248 { "port", OPT_PORT, "Port number to use for connections", 00249 (gptr *) &Options::Main::port_number, 00250 (gptr *) &Options::Main::port_number, 00251 0, GET_UINT, REQUIRED_ARG, DEFAULT_PORT, 0, 0, 0, 0, 0 }, 00252 00253 #ifdef __WIN__ 00254 { "remove", OPT_REMOVE_SERVICE, "Remove system service.", 00255 (gptr *) &Options::Service::remove_service, 00256 (gptr *) &Options::Service::remove_service, 00257 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0}, 00258 #else 00259 { "run-as-service", OPT_RUN_AS_SERVICE, 00260 "Daemonize and start angel process.", 00261 (gptr *) &Options::Daemon::run_as_service, 00262 0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 }, 00263 #endif 00264 00265 { "socket", OPT_SOCKET, "Socket file to use for connection.", 00266 (gptr *) &Options::Main::socket_file_name, 00267 (gptr *) &Options::Main::socket_file_name, 00268 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, 00269 00270 #ifdef __WIN__ 00271 { "standalone", OPT_STAND_ALONE, "Run the application in stand alone mode.", 00272 (gptr *) &Options::Service::stand_alone, 00273 (gptr *) &Options::Service::stand_alone, 00274 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0}, 00275 #else 00276 { "user", OPT_USER, "Username to start mysqlmanager", 00277 (gptr *) &Options::Daemon::user, 00278 (gptr *) &Options::Daemon::user, 00279 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, 00280 #endif 00281 00282 { "username", OPT_USERNAME, 00283 "Username to update the password file", 00284 (gptr *) &Options::User_management::user_name, 00285 (gptr *) &Options::User_management::user_name, 00286 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, 00287 00288 { "version", 'V', "Output version information and exit.", 0, 0, 0, 00289 GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, 00290 00291 { "wait-timeout", OPT_WAIT_TIMEOUT, "The number of seconds IM waits " 00292 "for activity on a connection before closing it.", 00293 (gptr *) &net_read_timeout, 00294 (gptr *) &net_read_timeout, 00295 0, GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0 }, 00296 00297 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 } 00298 }; 00299 00300 static void version() 00301 { 00302 printf("%s Ver %s for %s on %s\n", my_progname, 00303 (const char *) mysqlmanager_version.str, 00304 SYSTEM_TYPE, MACHINE_TYPE); 00305 } 00306 00307 00308 static const char *default_groups[]= { "manager", 0 }; 00309 00310 00311 static void usage() 00312 { 00313 version(); 00314 00315 printf("Copyright (C) 2003, 2004 MySQL AB\n" 00316 "This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n" 00317 "and you are welcome to modify and redistribute it under the GPL license\n"); 00318 printf("Usage: %s [OPTIONS] \n", my_progname); 00319 00320 my_print_help(my_long_options); 00321 printf("\nThe following options may be given as the first argument:\n" 00322 "--print-defaults Print the program argument list and exit\n" 00323 "--defaults-file=# Only read manager configuration and instance\n" 00324 " setings from the given file #. The same file\n" 00325 " will be used to modify configuration of instances\n" 00326 " with SET commands.\n"); 00327 my_print_variables(my_long_options); 00328 } 00329 00330 00331 C_MODE_START 00332 00333 static my_bool 00334 get_one_option(int optid, 00335 const struct my_option *opt __attribute__((unused)), 00336 char *argument) 00337 { 00338 switch(optid) { 00339 case 'V': 00340 version(); 00341 exit(0); 00342 case OPT_PRINT_PASSWORD_LINE: 00343 case OPT_ADD_USER: 00344 case OPT_DROP_USER: 00345 case OPT_EDIT_USER: 00346 case OPT_CLEAN_PASSWORD_FILE: 00347 case OPT_CHECK_PASSWORD_FILE: 00348 case OPT_LIST_USERS: 00349 if (Options::User_management::cmd) 00350 { 00351 fprintf(stderr, "Error: only one password-management command " 00352 "can be specified at a time.\n"); 00353 exit(ERR_INVALID_USAGE); 00354 } 00355 00356 switch (optid) { 00357 case OPT_PRINT_PASSWORD_LINE: 00358 Options::User_management::cmd= new Print_password_line_cmd(); 00359 break; 00360 case OPT_ADD_USER: 00361 Options::User_management::cmd= new Add_user_cmd(); 00362 break; 00363 case OPT_DROP_USER: 00364 Options::User_management::cmd= new Drop_user_cmd(); 00365 break; 00366 case OPT_EDIT_USER: 00367 Options::User_management::cmd= new Edit_user_cmd(); 00368 break; 00369 case OPT_CLEAN_PASSWORD_FILE: 00370 Options::User_management::cmd= new Clean_db_cmd(); 00371 break; 00372 case OPT_CHECK_PASSWORD_FILE: 00373 Options::User_management::cmd= new Check_db_cmd(); 00374 break; 00375 case OPT_LIST_USERS: 00376 Options::User_management::cmd= new List_users_cmd(); 00377 break; 00378 } 00379 00380 break; 00381 case '?': 00382 usage(); 00383 exit(0); 00384 case '#': 00385 #ifndef DBUG_OFF 00386 DBUG_SET(argument ? argument : Options::Debug::config_str); 00387 DBUG_SET_INITIAL(argument ? argument : Options::Debug::config_str); 00388 #endif 00389 break; 00390 } 00391 return 0; 00392 } 00393 00394 C_MODE_END 00395 00396 00397 /* 00398 - Process argv of original program: get tid of --defaults-extra-file 00399 and print a message if met there. 00400 - call load_defaults to load configuration file section and save the pointer 00401 for free_defaults. 00402 - call handle_options to assign defaults and command-line arguments 00403 to the class members. 00404 if either of these function fail, return the error code. 00405 */ 00406 00407 int Options::load(int argc, char **argv) 00408 { 00409 if (argc >= 2) 00410 { 00411 if (is_prefix(argv[1], "--defaults-file=")) 00412 { 00413 Main::config_file= strchr(argv[1], '=') + 1; 00414 Main::is_forced_default_file= TRUE; 00415 } 00416 if (is_prefix(argv[1], "--defaults-extra-file=") || 00417 is_prefix(argv[1], "--no-defaults")) 00418 { 00419 /* the log is not enabled yet */ 00420 fprintf(stderr, "The --defaults-extra-file and --no-defaults options" 00421 " are not supported by\n" 00422 "Instance Manager. Program aborted.\n"); 00423 return ERR_INVALID_USAGE; 00424 } 00425 } 00426 00427 #ifdef __WIN__ 00428 if (setup_windows_defaults()) 00429 { 00430 fprintf(stderr, "Internal error: could not setup default values.\n"); 00431 return ERR_OUT_OF_MEMORY; 00432 } 00433 #endif 00434 00435 /* load_defaults will reset saved_argv with a new allocated list */ 00436 saved_argv= argv; 00437 00438 /* config-file options are prepended to command-line ones */ 00439 00440 log_info("Loading config file '%s'...", 00441 (const char *) Main::config_file); 00442 00443 load_defaults(Main::config_file, default_groups, &argc, &saved_argv); 00444 00445 if ((handle_options(&argc, &saved_argv, my_long_options, get_one_option))) 00446 return ERR_INVALID_USAGE; 00447 00448 if (!User_management::cmd && 00449 (User_management::user_name || User_management::password)) 00450 { 00451 fprintf(stderr, 00452 "--username and/or --password options have been specified, " 00453 "but no password-management command has been given.\n"); 00454 return ERR_INVALID_USAGE; 00455 } 00456 00457 #ifndef __WIN__ 00458 if (Options::Daemon::run_as_service) 00459 { 00460 if (Options::Daemon::angel_pid_file_name == NULL) 00461 { 00462 /* 00463 Calculate angel pid file on the IM pid file basis: replace the 00464 extension (everything after the last dot) of the pid file basename to 00465 '.angel.pid'. 00466 */ 00467 00468 char *angel_pid_file_name; 00469 char *base_name_ptr; 00470 char *ext_ptr; 00471 00472 angel_pid_file_name= 00473 (char *) malloc(strlen(Options::Main::pid_file_name) + 00474 ANGEL_PID_FILE_SUFFIX_LEN); 00475 00476 strcpy(angel_pid_file_name, Options::Main::pid_file_name); 00477 00478 base_name_ptr= strrchr(angel_pid_file_name, '/'); 00479 00480 if (!base_name_ptr) 00481 base_name_ptr= angel_pid_file_name + 1; 00482 00483 ext_ptr= strrchr(base_name_ptr, '.'); 00484 if (ext_ptr) 00485 *ext_ptr= 0; 00486 00487 strcat(angel_pid_file_name, ANGEL_PID_FILE_SUFFIX); 00488 00489 Options::Daemon::angel_pid_file_name= angel_pid_file_name; 00490 } 00491 else 00492 { 00493 Options::Daemon::angel_pid_file_name= 00494 strdup(Options::Daemon::angel_pid_file_name); 00495 } 00496 } 00497 #endif 00498 00499 return 0; 00500 } 00501 00502 void Options::cleanup() 00503 { 00504 if (saved_argv) 00505 free_defaults(saved_argv); 00506 00507 delete User_management::cmd; 00508 00509 #ifndef __WIN__ 00510 if (Options::Daemon::run_as_service) 00511 free((void *) Options::Daemon::angel_pid_file_name); 00512 #endif 00513 } 00514 00515 #ifdef __WIN__ 00516 00517 static int setup_windows_defaults() 00518 { 00519 char module_full_name[FN_REFLEN]; 00520 char dir_name[FN_REFLEN]; 00521 char base_name[FN_REFLEN]; 00522 char im_name[FN_REFLEN]; 00523 char *base_name_ptr; 00524 char *ptr; 00525 00526 /* Determine dirname and basename. */ 00527 00528 if (!GetModuleFileName(NULL, module_full_name, sizeof (module_full_name)) || 00529 !GetFullPathName(module_full_name, sizeof (dir_name), dir_name, 00530 &base_name_ptr)) 00531 { 00532 return 1; 00533 } 00534 00535 strmake(base_name, base_name_ptr, FN_REFLEN); 00536 *base_name_ptr= 0; 00537 00538 strmake(im_name, base_name, FN_REFLEN); 00539 ptr= strrchr(im_name, '.'); 00540 00541 if (!ptr) 00542 return 1; 00543 00544 *ptr= 0; 00545 00546 /* Initialize the defaults. */ 00547 00548 strxmov(win_dflt_config_file_name, dir_name, DFLT_CONFIG_FILE_NAME, NullS); 00549 strxmov(win_dflt_mysqld_path, dir_name, DFLT_MYSQLD_PATH, NullS); 00550 strxmov(win_dflt_password_file_name, dir_name, im_name, DFLT_PASSWD_FILE_EXT, 00551 NullS); 00552 strxmov(win_dflt_pid_file_name, dir_name, im_name, DFLT_PID_FILE_EXT, NullS); 00553 strxmov(win_dflt_socket_file_name, dir_name, im_name, DFLT_SOCKET_FILE_EXT, 00554 NullS); 00555 00556 return 0; 00557 } 00558 00559 #endif
1.4.7

