summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--extra/my_print_defaults.c3
-rw-r--r--include/my_sys.h1
-rw-r--r--mysys/default.c45
-rw-r--r--mysys/my_getopt.c33
-rw-r--r--sql-common/client.c2
-rw-r--r--storage/ndb/test/run-test/setup.cpp8
6 files changed, 81 insertions, 11 deletions
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 <winbase.h>
#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 */
}
+ /* set arguments separator for arguments from config file and
+ command line */
+ res[args.elements+1]= args_separator;
+
if (*argc)
- memcpy((uchar*) (res+1+args.elements), (char*) ((*argv)+1),
+ memcpy((uchar*) (res+1+args.elements+1), (char*) ((*argv)+1),
(*argc-1)*sizeof(char*));
- res[args.elements+ *argc]=0; /* last null */
+ res[args.elements+ *argc+1]=0; /* last null */
- (*argc)+=args.elements;
+ (*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;