diff --git a/extra/my_print_defaults.c b/extra/my_print_defaults.c index 06f7e51c380..42a5cbd6877 100644 --- a/extra/my_print_defaults.c +++ b/extra/my_print_defaults.c @@ -192,7 +192,8 @@ int main(int argc, char **argv) } for (argument= arguments+1 ; *argument ; argument++) - puts(*argument); + if (*argument != args_separator) /* skip arguments separator */ + puts(*argument); my_free((char*) load_default_groups,MYF(0)); free_defaults(arguments); diff --git a/include/my_sys.h b/include/my_sys.h index 222564e0b44..4e85525e4b0 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -843,6 +843,7 @@ extern void *memdup_root(MEM_ROOT *root,const void *str, size_t len); extern int get_defaults_options(int argc, char **argv, char **defaults, char **extra_defaults, char **group_suffix); +extern const char *args_separator; extern int my_load_defaults(const char *conf_file, const char **groups, int *argc, char ***argv, const char ***); extern int load_defaults(const char *conf_file, const char **groups, diff --git a/mysys/default.c b/mysys/default.c index 1c021b4584f..c610b57c6d1 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -41,6 +41,29 @@ #include #endif +/** + arguments separator + + load_defaults() loads arguments from config file and put them + before the arguments from command line, this separator is used to + separate the arguments loaded from config file and arguments user + provided on command line. + + Options with value loaded from config file are always in the form + '--option=value', while for command line options, the value can be + given as the next argument. Thus we used a separator so that + handle_options() can distinguish them. + + Note: any other places that does not need to distinguish them + should skip the separator. + + The content of arguments separator does not matter, one should only + check the pointer, use "----args-separator----" here to ease debug + if someone misused it. + + See BUG#25192 +*/ +const char *args_separator= "----args-separator----"; const char *my_defaults_file=0; const char *my_defaults_group_suffix=0; char *my_defaults_extra_file=0; @@ -454,10 +477,11 @@ int my_load_defaults(const char *conf_file, const char **groups, goto err; res= (char**) (ptr+sizeof(alloc)); res[0]= **argv; /* Copy program name */ + /* set arguments separator */ + res[1]= args_separator; for (i=2 ; i < (uint) *argc ; i++) - res[i-1]=argv[0][i]; - res[i-1]=0; /* End pointer */ - (*argc)--; + res[i]=argv[0][i]; + res[i]=0; /* End pointer */ *argv=res; *(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */ if (default_directories) @@ -487,7 +511,7 @@ int my_load_defaults(const char *conf_file, const char **groups, or a forced default file */ if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+ - (args.elements + *argc +1) *sizeof(char*)))) + (args.elements + *argc + 1 + 1) *sizeof(char*)))) goto err; res= (char**) (ptr+sizeof(alloc)); @@ -508,12 +532,16 @@ int my_load_defaults(const char *conf_file, const char **groups, --*argc; ++*argv; /* skip argument */ } - if (*argc) - memcpy((uchar*) (res+1+args.elements), (char*) ((*argv)+1), - (*argc-1)*sizeof(char*)); - res[args.elements+ *argc]=0; /* last null */ + /* set arguments separator for arguments from config file and + command line */ + res[args.elements+1]= args_separator; - (*argc)+=args.elements; + if (*argc) + memcpy((uchar*) (res+1+args.elements+1), (char*) ((*argv)+1), + (*argc-1)*sizeof(char*)); + res[args.elements+ *argc+1]=0; /* last null */ + + (*argc)+=args.elements+1; *argv= (char**) res; *(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */ delete_dynamic(&args); @@ -523,7 +551,8 @@ int my_load_defaults(const char *conf_file, const char **groups, printf("%s would have been started with the following arguments:\n", **argv); for (i=1 ; i < *argc ; i++) - printf("%s ", (*argv)[i]); + if ((*argv)[i] != args_separator) /* skip arguments separator */ + printf("%s ", (*argv)[i]); puts(""); exit(0); } diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index b6eb6dac54f..22b1216f99c 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -121,6 +121,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *optp; uchar* *value; int error, i; + my_bool is_cmdline_arg= 1; LINT_INIT(opt_found); /* handle_options() assumes arg0 (program name) always exists */ @@ -130,10 +131,34 @@ int handle_options(int *argc, char ***argv, (*argv)++; /* --- || ---- */ init_variables(longopts, init_one_value); + /* + Search for args_separator, if found, then the first part of the + arguments are loaded from configs + */ + for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++) + { + if (*pos == args_separator) + { + is_cmdline_arg= 0; + break; + } + } + for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++) { char **first= pos; char *cur_arg= *pos; + if (!is_cmdline_arg && (cur_arg == args_separator)) + { + is_cmdline_arg= 1; + + /* save the separator too if skip unkown options */ + if (my_getopt_skip_unknown) + (*argv)[argvpos++]= cur_arg; + else + (*argc)--; + continue; + } if (cur_arg[0] == '-' && cur_arg[1] && !end_of_options) /* must be opt */ { char *argument= 0; @@ -426,8 +451,12 @@ invalid value '%s'", } else if (optp->arg_type == REQUIRED_ARG && !optend) { - /* Check if there are more arguments after this one */ - if (!*++pos) + /* Check if there are more arguments after this one, + + Note: options loaded from config file that requires value + should always be in the form '--option=value'. + */ + if (!is_cmdline_arg || !*++pos) { if (my_getopt_print_errors) my_getopt_error_reporter(ERROR_LEVEL, diff --git a/sql-common/client.c b/sql-common/client.c index 84029b449af..cbed3a5e2a8 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1053,6 +1053,8 @@ void mysql_read_default_options(struct st_mysql_options *options, char **option=argv; while (*++option) { + if (option[0] == args_separator) /* skip arguments separator */ + continue; /* DBUG_PRINT("info",("option: %s",option[0])); */ if (option[0][0] == '-' && option[0][1] == '-') { diff --git a/storage/ndb/test/run-test/setup.cpp b/storage/ndb/test/run-test/setup.cpp index cbb7a34f171..60f8285888c 100644 --- a/storage/ndb/test/run-test/setup.cpp +++ b/storage/ndb/test/run-test/setup.cpp @@ -105,6 +105,8 @@ setup_config(atrt_config& config) */ for (j = 0; j<(size_t)argc; j++) { + if (tmp[j] == args_separator) /* skip arguments separator */ + continue; for (k = 0; proc_args[k].name; k++) { if (!strncmp(tmp[j], proc_args[k].name, strlen(proc_args[k].name))) @@ -369,6 +371,12 @@ load_options(int argc, char** argv, int type, atrt_options& opts) { for (size_t i = 0; i<(size_t)argc; i++) { + /** + * Skip the separator for arguments from config file and command + * line + */ + if (argv[i] == args_separator) + continue; for (size_t j = 0; f_options[j].name; j++) { const char * name = f_options[j].name;