1
/* Copyright (C) 2003-2006 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
#if defined(__GNUC__) && defined(USE_PRAGMA_IMPLEMENTATION)
17
#pragma implementation
22
#include <my_global.h>
24
#include <my_getopt.h>
25
#include <mysql_com.h>
27
#include "exit_codes.h"
29
#include "portability.h"
31
#include "user_management_commands.h"
34
#define QUOTE(x) QUOTE2(x)
38
/* Define holders for default values. */
40
static char win_dflt_config_file_name[FN_REFLEN];
41
static char win_dflt_password_file_name[FN_REFLEN];
42
static char win_dflt_pid_file_name[FN_REFLEN];
44
static char win_dflt_mysqld_path[FN_REFLEN];
46
/* Define and initialize Windows-specific options. */
48
my_bool Options::Service::install_as_service;
49
my_bool Options::Service::remove_service;
50
my_bool Options::Service::stand_alone;
52
const char *Options::Main::config_file= win_dflt_config_file_name;
53
const char *Options::Main::password_file_name= win_dflt_password_file_name;
54
const char *Options::Main::pid_file_name= win_dflt_pid_file_name;
56
const char *Options::Main::default_mysqld_path= win_dflt_mysqld_path;
58
static int setup_windows_defaults();
62
/* Define and initialize UNIX-specific options. */
64
my_bool Options::Daemon::run_as_service= FALSE;
65
const char *Options::Daemon::log_file_name= QUOTE(DEFAULT_LOG_FILE_NAME);
66
const char *Options::Daemon::user= NULL; /* No default value */
67
const char *Options::Daemon::angel_pid_file_name= NULL;
69
const char *Options::Main::config_file= QUOTE(DEFAULT_CONFIG_FILE);
71
Options::Main::password_file_name= QUOTE(DEFAULT_PASSWORD_FILE_NAME);
72
const char *Options::Main::pid_file_name= QUOTE(DEFAULT_PID_FILE_NAME);
73
const char *Options::Main::socket_file_name= QUOTE(DEFAULT_SOCKET_FILE_NAME);
75
const char *Options::Main::default_mysqld_path= QUOTE(DEFAULT_MYSQLD_PATH);
79
/* Remember if the config file was forced. */
81
bool Options::Main::is_forced_default_file= FALSE;
83
/* Define and initialize common options. */
85
const char *Options::Main::bind_address= NULL; /* No default value */
86
uint Options::Main::monitoring_interval= DEFAULT_MONITORING_INTERVAL;
87
uint Options::Main::port_number= DEFAULT_PORT;
88
my_bool Options::Main::mysqld_safe_compatible= FALSE;
89
const char **Options::default_directories= NULL;
91
/* Options::User_management */
93
char *Options::User_management::user_name= NULL;
94
char *Options::User_management::password= NULL;
96
User_management_cmd *Options::User_management::cmd= NULL;
98
/* Private members. */
100
char **Options::saved_argv= NULL;
103
const char *Options::Debug::config_str= "d:t:i:O,im.trace";
106
static const char * const ANGEL_PID_FILE_SUFFIX= ".angel.pid";
107
static const int ANGEL_PID_FILE_SUFFIX_LEN= (uint) strlen(ANGEL_PID_FILE_SUFFIX);
110
List of options, accepted by the instance manager.
111
List must be closed with empty option.
131
OPT_MONITORING_INTERVAL,
135
OPT_PRINT_PASSWORD_LINE,
139
OPT_CLEAN_PASSWORD_FILE,
140
OPT_CHECK_PASSWORD_FILE,
142
OPT_MYSQLD_SAFE_COMPATIBLE
145
static struct my_option my_long_options[] =
147
{ "help", '?', "Display this help and exit.",
148
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
150
{ "add-user", OPT_ADD_USER,
151
"Add a user to the password file.",
152
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
155
{ "angel-pid-file", OPT_ANGEL_PID_FILE, "Pid file for angel process.",
156
(uchar* *) &Options::Daemon::angel_pid_file_name,
157
(uchar* *) &Options::Daemon::angel_pid_file_name,
158
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
161
{ "bind-address", OPT_BIND_ADDRESS, "Bind address to use for connection.",
162
(uchar* *) &Options::Main::bind_address,
163
(uchar* *) &Options::Main::bind_address,
164
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
166
{ "check-password-file", OPT_CHECK_PASSWORD_FILE,
167
"Check the password file for consistency.",
168
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
170
{ "clean-password-file", OPT_CLEAN_PASSWORD_FILE,
171
"Clean the password file.",
172
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
175
{"debug", '#', "Debug log.",
176
(uchar* *) &Options::Debug::config_str,
177
(uchar* *) &Options::Debug::config_str,
178
0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
181
{ "default-mysqld-path", OPT_MYSQLD_PATH, "Where to look for MySQL"
183
(uchar* *) &Options::Main::default_mysqld_path,
184
(uchar* *) &Options::Main::default_mysqld_path,
185
0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 },
187
{ "drop-user", OPT_DROP_USER,
188
"Drop existing user from the password file.",
189
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
191
{ "edit-user", OPT_EDIT_USER,
192
"Edit existing user in the password file.",
193
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
196
{ "install", OPT_INSTALL_SERVICE, "Install as system service.",
197
(uchar* *) &Options::Service::install_as_service,
198
(uchar* *) &Options::Service::install_as_service,
199
0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
202
{ "list-users", OPT_LIST_USERS,
203
"Print out a list of registered users.",
204
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
207
{ "log", OPT_LOG, "Path to log file. Used only with --run-as-service.",
208
(uchar* *) &Options::Daemon::log_file_name,
209
(uchar* *) &Options::Daemon::log_file_name,
210
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
213
{ "monitoring-interval", OPT_MONITORING_INTERVAL, "Interval to monitor"
214
" instances in seconds.",
215
(uchar* *) &Options::Main::monitoring_interval,
216
(uchar* *) &Options::Main::monitoring_interval,
217
0, GET_UINT, REQUIRED_ARG, DEFAULT_MONITORING_INTERVAL,
220
{ "mysqld-safe-compatible", OPT_MYSQLD_SAFE_COMPATIBLE,
221
"Start Instance Manager in mysqld_safe-compatible manner.",
222
(uchar* *) &Options::Main::mysqld_safe_compatible,
223
(uchar* *) &Options::Main::mysqld_safe_compatible,
224
0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
226
{ "print-password-line", OPT_PRINT_PASSWORD_LINE,
227
"Print out a user entry as a line for the password file and exit.",
228
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
230
{ "password", OPT_PASSWORD, "Password to update the password file.",
231
(uchar* *) &Options::User_management::password,
232
(uchar* *) &Options::User_management::password,
233
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
235
{ "password-file", OPT_PASSWORD_FILE,
236
"Look for Instance Manager users and passwords here.",
237
(uchar* *) &Options::Main::password_file_name,
238
(uchar* *) &Options::Main::password_file_name,
239
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
241
{ "pid-file", OPT_PID_FILE, "Pid file to use.",
242
(uchar* *) &Options::Main::pid_file_name,
243
(uchar* *) &Options::Main::pid_file_name,
244
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
246
{ "port", OPT_PORT, "Port number to use for connections.",
247
(uchar* *) &Options::Main::port_number,
248
(uchar* *) &Options::Main::port_number,
249
0, GET_UINT, REQUIRED_ARG, DEFAULT_PORT, 0, 0, 0, 0, 0 },
252
{ "remove", OPT_REMOVE_SERVICE, "Remove system service.",
253
(uchar* *) &Options::Service::remove_service,
254
(uchar* *) &Options::Service::remove_service,
255
0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0},
257
{ "run-as-service", OPT_RUN_AS_SERVICE,
258
"Daemonize and start angel process.",
259
(uchar* *) &Options::Daemon::run_as_service,
260
0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 },
264
{ "socket", OPT_SOCKET, "Socket file to use for connection.",
265
(uchar* *) &Options::Main::socket_file_name,
266
(uchar* *) &Options::Main::socket_file_name,
267
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
271
{ "standalone", OPT_STAND_ALONE, "Run the application in stand alone mode.",
272
(uchar* *) &Options::Service::stand_alone,
273
(uchar* *) &Options::Service::stand_alone,
274
0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0},
276
{ "user", OPT_USER, "Username to start mysqlmanager.",
277
(uchar* *) &Options::Daemon::user,
278
(uchar* *) &Options::Daemon::user,
279
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
282
{ "username", OPT_USERNAME,
283
"Username to update the password file.",
284
(uchar* *) &Options::User_management::user_name,
285
(uchar* *) &Options::User_management::user_name,
286
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
288
{ "version", 'V', "Output version information and exit.", 0, 0, 0,
289
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
291
{ "wait-timeout", OPT_WAIT_TIMEOUT, "The number of seconds IM waits "
292
"for activity on a connection before closing it.",
293
(uchar* *) &net_read_timeout,
294
(uchar* *) &net_read_timeout,
295
0, GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0 },
297
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }
300
static void version()
302
printf("%s Ver %s for %s on %s\n", my_progname,
303
(const char *) mysqlmanager_version.str,
304
SYSTEM_TYPE, MACHINE_TYPE);
308
static const char *default_groups[]= { "manager", 0 };
315
printf("Copyright (C) 2003, 2004 MySQL AB.\n"
316
"This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
317
"and you are welcome to modify and redistribute it under the GPL license.\n");
318
printf("Usage: %s [OPTIONS] \n", my_progname);
320
my_print_help(my_long_options);
321
printf("\nThe following options may be given as the first argument:\n"
322
"--print-defaults Print the program argument list and exit.\n"
323
"--defaults-file=# Only read manager configuration and instance\n"
324
" settings from the given file #. The same file\n"
325
" will be used to modify configuration of instances\n"
326
" with SET commands.\n");
327
my_print_variables(my_long_options);
334
get_one_option(int optid,
335
const struct my_option *opt __attribute__((unused)),
342
case OPT_PRINT_PASSWORD_LINE:
346
case OPT_CLEAN_PASSWORD_FILE:
347
case OPT_CHECK_PASSWORD_FILE:
349
if (Options::User_management::cmd)
351
fprintf(stderr, "Error: only one password-management command "
352
"can be specified at a time.\n");
353
exit(ERR_INVALID_USAGE);
357
case OPT_PRINT_PASSWORD_LINE:
358
Options::User_management::cmd= new Print_password_line_cmd();
361
Options::User_management::cmd= new Add_user_cmd();
364
Options::User_management::cmd= new Drop_user_cmd();
367
Options::User_management::cmd= new Edit_user_cmd();
369
case OPT_CLEAN_PASSWORD_FILE:
370
Options::User_management::cmd= new Clean_db_cmd();
372
case OPT_CHECK_PASSWORD_FILE:
373
Options::User_management::cmd= new Check_db_cmd();
376
Options::User_management::cmd= new List_users_cmd();
386
DBUG_SET(argument ? argument : Options::Debug::config_str);
387
DBUG_SET_INITIAL(argument ? argument : Options::Debug::config_str);
398
- Process argv of original program: get tid of --defaults-extra-file
399
and print a message if met there.
400
- call load_defaults to load configuration file section and save the pointer
402
- call handle_options to assign defaults and command-line arguments
403
to the class members.
404
if either of these function fail, return the error code.
407
int Options::load(int argc, char **argv)
411
if (is_prefix(argv[1], "--defaults-file="))
413
Main::config_file= strchr(argv[1], '=') + 1;
414
Main::is_forced_default_file= TRUE;
416
if (is_prefix(argv[1], "--defaults-extra-file=") ||
417
is_prefix(argv[1], "--no-defaults"))
419
/* the log is not enabled yet */
420
fprintf(stderr, "The --defaults-extra-file and --no-defaults options"
421
" are not supported by\n"
422
"Instance Manager. Program aborted.\n");
423
return ERR_INVALID_USAGE;
428
if (setup_windows_defaults())
430
fprintf(stderr, "Internal error: could not setup default values.\n");
431
return ERR_OUT_OF_MEMORY;
435
/* load_defaults will reset saved_argv with a new allocated list */
438
/* config-file options are prepended to command-line ones */
440
log_info("Loading config file '%s'...",
441
(const char *) Main::config_file);
443
my_load_defaults(Main::config_file, default_groups, &argc,
444
&saved_argv, &default_directories);
446
if ((handle_options(&argc, &saved_argv, my_long_options, get_one_option)))
447
return ERR_INVALID_USAGE;
449
if (!User_management::cmd &&
450
(User_management::user_name || User_management::password))
453
"--username and/or --password options have been specified, "
454
"but no password-management command has been given.\n");
455
return ERR_INVALID_USAGE;
459
if (Options::Daemon::run_as_service)
461
if (Options::Daemon::angel_pid_file_name == NULL)
464
Calculate angel pid file on the IM pid file basis: replace the
465
extension (everything after the last dot) of the pid file basename to
469
char *local_angel_pid_file_name;
473
local_angel_pid_file_name=
474
(char *) malloc(strlen(Options::Main::pid_file_name) +
475
ANGEL_PID_FILE_SUFFIX_LEN);
477
strcpy(local_angel_pid_file_name, Options::Main::pid_file_name);
479
base_name_ptr= strrchr(local_angel_pid_file_name, '/');
482
base_name_ptr= local_angel_pid_file_name + 1;
484
ext_ptr= strrchr(base_name_ptr, '.');
488
strcat(local_angel_pid_file_name, ANGEL_PID_FILE_SUFFIX);
490
Options::Daemon::angel_pid_file_name= local_angel_pid_file_name;
494
Options::Daemon::angel_pid_file_name=
495
strdup(Options::Daemon::angel_pid_file_name);
503
void Options::cleanup()
506
free_defaults(saved_argv);
508
delete User_management::cmd;
511
if (Options::Daemon::run_as_service)
512
free((void *) Options::Daemon::angel_pid_file_name);
518
static int setup_windows_defaults()
520
char module_full_name[FN_REFLEN];
521
char dir_name[FN_REFLEN];
522
char base_name[FN_REFLEN];
523
char im_name[FN_REFLEN];
527
/* Determine dirname and basename. */
529
if (!GetModuleFileName(NULL, module_full_name, sizeof (module_full_name)) ||
530
!GetFullPathName(module_full_name, sizeof (dir_name), dir_name,
536
strmake(base_name, base_name_ptr, FN_REFLEN - 1);
539
strmake(im_name, base_name, FN_REFLEN - 1);
540
ptr= strrchr(im_name, '.');
547
/* Initialize the defaults. */
549
strxmov(win_dflt_config_file_name, dir_name, DFLT_CONFIG_FILE_NAME, NullS);
550
strxmov(win_dflt_mysqld_path, dir_name, DFLT_MYSQLD_PATH, NullS);
551
strxmov(win_dflt_password_file_name, dir_name, im_name, DFLT_PASSWD_FILE_EXT,
553
strxmov(win_dflt_pid_file_name, dir_name, im_name, DFLT_PID_FILE_EXT, NullS);