|
|
|
@ -69,26 +69,19 @@
|
|
|
|
|
|
|
|
|
|
See BUG#25192
|
|
|
|
|
*/
|
|
|
|
|
static const char *args_separator= "----args-separator----";
|
|
|
|
|
inline static void set_args_separator(char** arg)
|
|
|
|
|
{
|
|
|
|
|
DBUG_ASSERT(my_getopt_use_args_separator);
|
|
|
|
|
*arg= (char*)args_separator;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *args_separator= (char*)"----args-separator----";
|
|
|
|
|
my_bool my_getopt_use_args_separator= FALSE;
|
|
|
|
|
my_bool my_getopt_is_args_separator(const char* arg)
|
|
|
|
|
{
|
|
|
|
|
return (arg == args_separator);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
my_bool my_no_defaults=FALSE, my_print_defaults= FALSE;
|
|
|
|
|
const char *my_defaults_file=0;
|
|
|
|
|
const char *my_defaults_group_suffix=0;
|
|
|
|
|
const char *my_defaults_extra_file=0;
|
|
|
|
|
|
|
|
|
|
static char my_defaults_file_buffer[FN_REFLEN];
|
|
|
|
|
static char my_defaults_extra_file_buffer[FN_REFLEN];
|
|
|
|
|
|
|
|
|
|
static my_bool defaults_already_read= FALSE;
|
|
|
|
|
|
|
|
|
|
/* Which directories are searched for options (and in which order) */
|
|
|
|
|
|
|
|
|
|
#define MAX_DEFAULT_DIRS 7
|
|
|
|
@ -110,11 +103,11 @@ struct handle_option_ctx
|
|
|
|
|
TYPELIB *group;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int search_default_file(struct handle_option_ctx *ctx,
|
|
|
|
|
const char *dir, const char *config_file);
|
|
|
|
|
static int search_default_file_with_ext(struct handle_option_ctx *ctx,
|
|
|
|
|
const char *dir, const char *ext,
|
|
|
|
|
const char *config_file, int recursion_level);
|
|
|
|
|
static int search_default_file(struct handle_option_ctx *,
|
|
|
|
|
const char *, const char *);
|
|
|
|
|
static int search_default_file_with_ext(struct handle_option_ctx *,
|
|
|
|
|
const char *, const char *,
|
|
|
|
|
const char *, int);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -148,33 +141,6 @@ static const char **init_default_directories(MEM_ROOT *alloc);
|
|
|
|
|
static char *remove_end_comment(char *ptr);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Expand a file name so that the current working directory is added if
|
|
|
|
|
the name is relative.
|
|
|
|
|
|
|
|
|
|
RETURNS
|
|
|
|
|
0 All OK
|
|
|
|
|
2 Out of memory or path to long
|
|
|
|
|
3 Not able to get working directory
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
fn_expand(const char *filename, char *result_buf)
|
|
|
|
|
{
|
|
|
|
|
char dir[FN_REFLEN];
|
|
|
|
|
const int flags= MY_UNPACK_FILENAME | MY_SAFE_PATH | MY_RELATIVE_PATH;
|
|
|
|
|
DBUG_ENTER("fn_expand");
|
|
|
|
|
DBUG_PRINT("enter", ("filename: %s, result_buf: %p",
|
|
|
|
|
filename, result_buf));
|
|
|
|
|
if (my_getwd(dir, sizeof(dir), MYF(0)))
|
|
|
|
|
DBUG_RETURN(3);
|
|
|
|
|
DBUG_PRINT("debug", ("dir: %s", dir));
|
|
|
|
|
if (fn_format(result_buf, filename, dir, "", flags) == NULL)
|
|
|
|
|
DBUG_RETURN(2);
|
|
|
|
|
DBUG_PRINT("return", ("result: %s", result_buf));
|
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Process config files in default directories.
|
|
|
|
|
|
|
|
|
@ -184,8 +150,6 @@ fn_expand(const char *filename, char *result_buf)
|
|
|
|
|
If this is a path, then only this file is read.
|
|
|
|
|
argc Pointer to argc of original program
|
|
|
|
|
argv Pointer to argv of original program
|
|
|
|
|
args_used Pointer to variable for storing the number of
|
|
|
|
|
arguments used.
|
|
|
|
|
func Pointer to the function to process options
|
|
|
|
|
func_ctx It's context. Usually it is the structure to
|
|
|
|
|
store additional options.
|
|
|
|
@ -209,42 +173,14 @@ fn_expand(const char *filename, char *result_buf)
|
|
|
|
|
--defaults_group_suffix
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static int my_search_option_files(const char *conf_file, int *argc,
|
|
|
|
|
char ***argv, uint *args_used,
|
|
|
|
|
static int my_search_option_files(const char *conf_file, int *argc, char ***argv,
|
|
|
|
|
struct handle_option_ctx *ctx,
|
|
|
|
|
const char **default_directories)
|
|
|
|
|
{
|
|
|
|
|
const char **dirs, *forced_default_file, *forced_extra_defaults;
|
|
|
|
|
const char **dirs;
|
|
|
|
|
int error= 0;
|
|
|
|
|
DBUG_ENTER("my_search_option_files");
|
|
|
|
|
|
|
|
|
|
/* Check if we want to force the use a specific default file */
|
|
|
|
|
*args_used+= get_defaults_options(*argc - *args_used, *argv + *args_used,
|
|
|
|
|
(char **) &forced_default_file,
|
|
|
|
|
(char **) &forced_extra_defaults,
|
|
|
|
|
(char **) &my_defaults_group_suffix);
|
|
|
|
|
|
|
|
|
|
if (! my_defaults_group_suffix)
|
|
|
|
|
my_defaults_group_suffix= getenv("MYSQL_GROUP_SUFFIX");
|
|
|
|
|
|
|
|
|
|
if (forced_extra_defaults && !defaults_already_read)
|
|
|
|
|
{
|
|
|
|
|
int error= fn_expand(forced_extra_defaults, my_defaults_extra_file_buffer);
|
|
|
|
|
if (error)
|
|
|
|
|
DBUG_RETURN(error);
|
|
|
|
|
my_defaults_extra_file= my_defaults_extra_file_buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (forced_default_file && !defaults_already_read)
|
|
|
|
|
{
|
|
|
|
|
int error= fn_expand(forced_default_file, my_defaults_file_buffer);
|
|
|
|
|
if (error)
|
|
|
|
|
DBUG_RETURN(error);
|
|
|
|
|
my_defaults_file= my_defaults_file_buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
defaults_already_read= TRUE;
|
|
|
|
|
|
|
|
|
|
if (my_defaults_group_suffix)
|
|
|
|
|
{
|
|
|
|
|
/* Handle --defaults-group-suffix= */
|
|
|
|
@ -355,50 +291,73 @@ static int add_option(struct handle_option_ctx *ctx, const char *option)
|
|
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
|
get_defaults_options()
|
|
|
|
|
argc Pointer to argc of original program
|
|
|
|
|
argv Pointer to argv of original program
|
|
|
|
|
defaults --defaults-file option
|
|
|
|
|
extra_defaults --defaults-extra-file option
|
|
|
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
|
Sets my_no_defaults, my_defaults_file, my_defaults_extra_file,
|
|
|
|
|
my_defaults_group_suffix, my_print_defaults
|
|
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
|
# Number of arguments used from *argv
|
|
|
|
|
defaults and extra_defaults will be set to option of the appropriate
|
|
|
|
|
items of argv array, or to NULL if there are no such options
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int get_defaults_options(int argc, char **argv,
|
|
|
|
|
char **defaults,
|
|
|
|
|
char **extra_defaults,
|
|
|
|
|
char **group_suffix)
|
|
|
|
|
int get_defaults_options(char **argv)
|
|
|
|
|
{
|
|
|
|
|
int org_argc= argc;
|
|
|
|
|
*defaults= *extra_defaults= *group_suffix= 0;
|
|
|
|
|
static char file_buffer[FN_REFLEN];
|
|
|
|
|
static char extra_file_buffer[FN_REFLEN];
|
|
|
|
|
char **orig_argv= argv;
|
|
|
|
|
|
|
|
|
|
while (argc >= 2)
|
|
|
|
|
argv++; /* Skip program name */
|
|
|
|
|
|
|
|
|
|
my_defaults_file= my_defaults_group_suffix= my_defaults_extra_file= 0;
|
|
|
|
|
my_no_defaults= my_print_defaults= FALSE;
|
|
|
|
|
|
|
|
|
|
if (*argv && !strcmp(*argv, "--no-defaults"))
|
|
|
|
|
{
|
|
|
|
|
/* Skip program name or previously handled argument */
|
|
|
|
|
my_no_defaults= 1;
|
|
|
|
|
argv++;
|
|
|
|
|
if (!*defaults && is_prefix(*argv,"--defaults-file="))
|
|
|
|
|
{
|
|
|
|
|
*defaults= *argv + sizeof("--defaults-file=")-1;
|
|
|
|
|
argc--;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (!*extra_defaults && is_prefix(*argv,"--defaults-extra-file="))
|
|
|
|
|
else
|
|
|
|
|
for(; *argv; argv++)
|
|
|
|
|
{
|
|
|
|
|
*extra_defaults= *argv + sizeof("--defaults-extra-file=")-1;
|
|
|
|
|
argc--;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (!*group_suffix && is_prefix(*argv, "--defaults-group-suffix="))
|
|
|
|
|
{
|
|
|
|
|
*group_suffix= *argv + sizeof("--defaults-group-suffix=")-1;
|
|
|
|
|
argc--;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (!my_defaults_file && is_prefix(*argv, "--defaults-file="))
|
|
|
|
|
my_defaults_file= *argv + sizeof("--defaults-file=")-1;
|
|
|
|
|
else
|
|
|
|
|
if (!my_defaults_extra_file && is_prefix(*argv, "--defaults-extra-file="))
|
|
|
|
|
my_defaults_extra_file= *argv + sizeof("--defaults-extra-file=")-1;
|
|
|
|
|
else
|
|
|
|
|
if (!my_defaults_group_suffix && is_prefix(*argv, "--defaults-group-suffix="))
|
|
|
|
|
my_defaults_group_suffix= *argv + sizeof("--defaults-group-suffix=")-1;
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return org_argc - argc;
|
|
|
|
|
|
|
|
|
|
if (*argv && !strcmp(*argv, "--print-defaults"))
|
|
|
|
|
{
|
|
|
|
|
my_print_defaults= 1;
|
|
|
|
|
argv++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! my_defaults_group_suffix)
|
|
|
|
|
my_defaults_group_suffix= getenv("MYSQL_GROUP_SUFFIX");
|
|
|
|
|
|
|
|
|
|
if (my_defaults_extra_file && my_defaults_extra_file != extra_file_buffer)
|
|
|
|
|
{
|
|
|
|
|
int error= my_realpath(extra_file_buffer, my_defaults_extra_file, MYF(0));
|
|
|
|
|
if (error)
|
|
|
|
|
return error;
|
|
|
|
|
my_defaults_extra_file= extra_file_buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (my_defaults_file && my_defaults_file != file_buffer)
|
|
|
|
|
{
|
|
|
|
|
int error= my_realpath(file_buffer, my_defaults_file, MYF(0));
|
|
|
|
|
if (error)
|
|
|
|
|
return error;
|
|
|
|
|
my_defaults_file= file_buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (int)(argv - orig_argv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -469,55 +428,31 @@ int my_load_defaults(const char *conf_file, const char **groups, int *argc,
|
|
|
|
|
char ***argv, const char ***default_directories)
|
|
|
|
|
{
|
|
|
|
|
DYNAMIC_ARRAY args;
|
|
|
|
|
TYPELIB group;
|
|
|
|
|
my_bool found_print_defaults= 0;
|
|
|
|
|
uint args_used= 0;
|
|
|
|
|
int args_used= 0;
|
|
|
|
|
int error= 0;
|
|
|
|
|
MEM_ROOT alloc;
|
|
|
|
|
char *ptr,**res;
|
|
|
|
|
struct handle_option_ctx ctx;
|
|
|
|
|
const char **dirs;
|
|
|
|
|
uint args_sep= my_getopt_use_args_separator ? 1 : 0;
|
|
|
|
|
DBUG_ENTER("load_defaults");
|
|
|
|
|
DBUG_ENTER("my_load_defaults");
|
|
|
|
|
|
|
|
|
|
init_alloc_root(&alloc, "my_load_defaults", 512, 0, MYF(0));
|
|
|
|
|
if ((dirs= init_default_directories(&alloc)) == NULL)
|
|
|
|
|
goto err;
|
|
|
|
|
/*
|
|
|
|
|
Check if the user doesn't want any default option processing
|
|
|
|
|
--no-defaults is always the first option
|
|
|
|
|
*/
|
|
|
|
|
if (*argc >= 2 && !strcmp(argv[0][1],"--no-defaults"))
|
|
|
|
|
{
|
|
|
|
|
/* remove the --no-defaults argument and return only the other arguments */
|
|
|
|
|
uint i, j;
|
|
|
|
|
if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
|
|
|
|
|
(*argc + 1)*sizeof(char*))))
|
|
|
|
|
|
|
|
|
|
args_used= get_defaults_options(*argv);
|
|
|
|
|
|
|
|
|
|
if (my_init_dynamic_array(&args, sizeof(char*), 128, 64, MYF(0)))
|
|
|
|
|
goto err;
|
|
|
|
|
res= (char**) (ptr+sizeof(alloc));
|
|
|
|
|
res[0]= **argv; /* Copy program name */
|
|
|
|
|
j= 1; /* Start from 1 for the reset result args */
|
|
|
|
|
if (my_getopt_use_args_separator)
|
|
|
|
|
|
|
|
|
|
insert_dynamic(&args, *argv);/* Name MUST be set, even by embedded library */
|
|
|
|
|
|
|
|
|
|
*argc-= args_used;
|
|
|
|
|
*argv+= args_used;
|
|
|
|
|
|
|
|
|
|
if (!my_no_defaults)
|
|
|
|
|
{
|
|
|
|
|
/* set arguments separator */
|
|
|
|
|
set_args_separator(&res[1]);
|
|
|
|
|
j++;
|
|
|
|
|
}
|
|
|
|
|
for (i=2 ; i < (uint) *argc ; i++, j++)
|
|
|
|
|
res[j]=argv[0][i];
|
|
|
|
|
res[j]=0; /* End pointer */
|
|
|
|
|
/*
|
|
|
|
|
Update the argc, if have not added args separator, then we have
|
|
|
|
|
to decrease argc because we have removed the "--no-defaults".
|
|
|
|
|
*/
|
|
|
|
|
if (!my_getopt_use_args_separator)
|
|
|
|
|
(*argc)--;
|
|
|
|
|
*argv=res;
|
|
|
|
|
*(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */
|
|
|
|
|
if (default_directories)
|
|
|
|
|
*default_directories= dirs;
|
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
|
}
|
|
|
|
|
TYPELIB group; // XXX
|
|
|
|
|
struct handle_option_ctx ctx;
|
|
|
|
|
|
|
|
|
|
group.count=0;
|
|
|
|
|
group.name= "defaults";
|
|
|
|
@ -526,63 +461,39 @@ int my_load_defaults(const char *conf_file, const char **groups, int *argc,
|
|
|
|
|
for (; *groups ; groups++)
|
|
|
|
|
group.count++;
|
|
|
|
|
|
|
|
|
|
if (my_init_dynamic_array(&args, sizeof(char*), 128, 64, MYF(0)))
|
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
|
|
ctx.alloc= &alloc;
|
|
|
|
|
ctx.args= &args;
|
|
|
|
|
ctx.group= &group;
|
|
|
|
|
|
|
|
|
|
if ((error= my_search_option_files(conf_file, argc, argv, &args_used, &ctx,
|
|
|
|
|
dirs)))
|
|
|
|
|
if ((error= my_search_option_files(conf_file, argc - args_used,
|
|
|
|
|
argv + args_used, &ctx, dirs)))
|
|
|
|
|
{
|
|
|
|
|
delete_dynamic(&args);
|
|
|
|
|
free_root(&alloc,MYF(0));
|
|
|
|
|
DBUG_RETURN(error);
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
Here error contains <> 0 only if we have a fully specified conf_file
|
|
|
|
|
or a forced default file
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(ptr=(char*) alloc_root(&alloc, sizeof(alloc) +
|
|
|
|
|
(args.elements + *argc + 1 + args_sep) *sizeof(char*))))
|
|
|
|
|
(args.elements + *argc + 3) * sizeof(char*))))
|
|
|
|
|
goto err;
|
|
|
|
|
res= (char**) (ptr+sizeof(alloc));
|
|
|
|
|
|
|
|
|
|
/* copy name + found arguments + command line arguments to new array */
|
|
|
|
|
res[0]= argv[0][0]; /* Name MUST be set, even by embedded library */
|
|
|
|
|
memcpy((uchar*) (res+1), args.buffer, args.elements*sizeof(char*));
|
|
|
|
|
/* Skip --defaults-xxx options */
|
|
|
|
|
(*argc)-= args_used;
|
|
|
|
|
(*argv)+= args_used;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Check if we want to see the new argument list
|
|
|
|
|
This options must always be the last of the default options
|
|
|
|
|
*/
|
|
|
|
|
if (*argc >= 2 && !strcmp(argv[0][1],"--print-defaults"))
|
|
|
|
|
{
|
|
|
|
|
found_print_defaults=1;
|
|
|
|
|
--*argc; ++*argv; /* skip argument */
|
|
|
|
|
}
|
|
|
|
|
/* found arguments + command line arguments to new array */
|
|
|
|
|
memcpy(res, args.buffer, args.elements * sizeof(char*));
|
|
|
|
|
|
|
|
|
|
if (my_getopt_use_args_separator)
|
|
|
|
|
{
|
|
|
|
|
/* set arguments separator for arguments from config file and
|
|
|
|
|
command line */
|
|
|
|
|
set_args_separator(&res[args.elements+1]);
|
|
|
|
|
}
|
|
|
|
|
res[args.elements++]= args_separator;
|
|
|
|
|
|
|
|
|
|
if (*argc)
|
|
|
|
|
memcpy((uchar*) (res+1+args.elements+args_sep), (char*) ((*argv)+1),
|
|
|
|
|
(*argc-1)*sizeof(char*));
|
|
|
|
|
res[args.elements+ *argc+args_sep]=0; /* last null */
|
|
|
|
|
memcpy(res + args.elements, *argv, *argc * sizeof(char*));
|
|
|
|
|
|
|
|
|
|
(*argc)+=args.elements+args_sep;
|
|
|
|
|
*argv= (char**) res;
|
|
|
|
|
(*argc)+= args.elements;
|
|
|
|
|
*argv= res;
|
|
|
|
|
(*argv)[*argc]= 0;
|
|
|
|
|
*(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */
|
|
|
|
|
delete_dynamic(&args);
|
|
|
|
|
if (found_print_defaults)
|
|
|
|
|
if (my_print_defaults)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
printf("%s would have been started with the following arguments:\n",
|
|
|
|
@ -718,7 +629,7 @@ static int search_default_file_with_ext(struct handle_option_ctx *ctx,
|
|
|
|
|
MY_DIR *search_dir;
|
|
|
|
|
FILEINFO *search_file;
|
|
|
|
|
|
|
|
|
|
if ((dir ? strlen(dir) : 0 )+strlen(config_file) >= FN_REFLEN-3)
|
|
|
|
|
if (safe_strlen(dir) + strlen(config_file) >= FN_REFLEN-3)
|
|
|
|
|
return 0; /* Ignore wrong paths */
|
|
|
|
|
if (dir)
|
|
|
|
|
{
|
|
|
|
|