summaryrefslogtreecommitdiff
path: root/mysys/default.c
diff options
context:
space:
mode:
Diffstat (limited to 'mysys/default.c')
-rw-r--r--mysys/default.c192
1 files changed, 146 insertions, 46 deletions
diff --git a/mysys/default.c b/mysys/default.c
index 63f9445dbdc..c7ac0d89462 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2003 MySQL AB
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -41,9 +41,51 @@
#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.
+
+ The args seprator will only be added when
+ my_getopt_use_args_seprator is set to TRUE before calling
+ load_defaults();
+
+ 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;
+}
+my_bool my_getopt_use_args_separator= FALSE;
+my_bool my_getopt_is_args_separator(const char* arg)
+{
+ return (arg == args_separator);
+}
const char *my_defaults_file=0;
const char *my_defaults_group_suffix=0;
-char *my_defaults_extra_file=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) */
@@ -95,11 +137,10 @@ static int search_default_file_with_ext(Process_option_func func,
- Windows: GetWindowsDirectory()
- Windows: C:/
- Windows: Directory above where the executable is located
- - Netware: sys:/etc/
- Unix: /etc/
- Unix: /etc/mysql/
- Unix: --sysconfdir=<path> (compile-time option)
- - ALL: getenv(DEFAULT_HOME_ENV)
+ - ALL: getenv("MYSQL_HOME")
- ALL: --defaults-extra-file=<path> (run-time option)
- Unix: ~/
@@ -118,6 +159,33 @@ 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: 0x%lx",
+ filename, (unsigned long) 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.
SYNOPSIS
@@ -145,6 +213,7 @@ static char *remove_end_comment(char *ptr);
0 ok
1 given cinf_file doesn't exist
2 out of memory
+ 3 Can't get current working directory
The global variable 'my_defaults_group_suffix' is updated with value for
--defaults_group_suffix
@@ -167,11 +236,23 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv,
if (! my_defaults_group_suffix)
my_defaults_group_suffix= getenv(STRINGIFY_ARG(DEFAULT_GROUP_SUFFIX_ENV));
- if (forced_extra_defaults)
- my_defaults_extra_file= (char *) forced_extra_defaults;
-
- if (forced_default_file)
- my_defaults_file= forced_default_file;
+ 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;
/*
We can only handle 'defaults-group-suffix' if we are called from
@@ -214,15 +295,15 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv,
group->type_names[group->count]= 0;
}
- if (forced_default_file)
+ if (my_defaults_file)
{
if ((error= search_default_file_with_ext(func, func_ctx, "", "",
- forced_default_file, 0)) < 0)
+ my_defaults_file, 0)) < 0)
goto err;
if (error > 0)
{
fprintf(stderr, "Could not open required defaults file: %s\n",
- forced_default_file);
+ my_defaults_file);
goto err;
}
}
@@ -295,7 +376,7 @@ static int handle_default_option(void *in_ctx, const char *group_name,
if (!option)
return 0;
- if (find_type((char *)group_name, ctx->group, 3))
+ if (find_type((char *)group_name, ctx->group, FIND_TYPE_NO_PREFIX))
{
if (!(tmp= alloc_root(ctx->alloc, strlen(option) + 1)))
return 1;
@@ -436,6 +517,7 @@ int my_load_defaults(const char *conf_file, const char **groups,
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");
init_alloc_root(&alloc,512,0);
@@ -448,16 +530,28 @@ int my_load_defaults(const char *conf_file, const char **groups,
if (*argc >= 2 && !strcmp(argv[0][1],"--no-defaults"))
{
/* remove the --no-defaults argument and return only the other arguments */
- uint i;
+ uint i, j;
if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
(*argc + 1)*sizeof(char*))))
goto err;
res= (char**) (ptr+sizeof(alloc));
res[0]= **argv; /* Copy program name */
- for (i=2 ; i < (uint) *argc ; i++)
- res[i-1]=argv[0][i];
- res[i-1]=0; /* End pointer */
- (*argc)--;
+ j= 1; /* Start from 1 for the reset result args */
+ if (my_getopt_use_args_separator)
+ {
+ /* 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)
@@ -479,15 +573,19 @@ int my_load_defaults(const char *conf_file, const char **groups,
ctx.args= &args;
ctx.group= &group;
- error= my_search_option_files(conf_file, argc, argv, &args_used,
- handle_default_option, (void *) &ctx,
- dirs);
+ if ((error= my_search_option_files(conf_file, argc, argv, &args_used,
+ handle_default_option, (void *) &ctx,
+ dirs)))
+ {
+ 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) *sizeof(char*))))
+ (args.elements + *argc + 1 + args_sep) *sizeof(char*))))
goto err;
res= (char**) (ptr+sizeof(alloc));
@@ -508,12 +606,19 @@ int my_load_defaults(const char *conf_file, const char **groups,
--*argc; ++*argv; /* skip argument */
}
+ if (my_getopt_use_args_separator)
+ {
+ /* set arguments separator for arguments from config file and
+ command line */
+ set_args_separator(&res[args.elements+1]);
+ }
+
if (*argc)
- memcpy((uchar*) (res+1+args.elements), (char*) ((*argv)+1),
+ memcpy((uchar*) (res+1+args.elements+args_sep), (char*) ((*argv)+1),
(*argc-1)*sizeof(char*));
- res[args.elements+ *argc]=0; /* last null */
+ res[args.elements+ *argc+args_sep]=0; /* last null */
- (*argc)+=args.elements;
+ (*argc)+=args.elements+args_sep;
*argv= (char**) res;
*(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */
delete_dynamic(&args);
@@ -523,15 +628,16 @@ 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 (!my_getopt_is_args_separator((*argv)[i])) /* skip arguments separator */
+ printf("%s ", (*argv)[i]);
puts("");
exit(0);
}
- if (error == 0 && default_directories)
+ if (default_directories)
*default_directories= dirs;
- DBUG_RETURN(error);
+ DBUG_RETURN(0);
err:
fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
@@ -543,7 +649,7 @@ int my_load_defaults(const char *conf_file, const char **groups,
void free_defaults(char **argv)
{
MEM_ROOT ptr;
- memcpy_fixed((char*) &ptr,(char *) argv - sizeof(ptr), sizeof(ptr));
+ memcpy(&ptr, ((char *) argv) - sizeof(ptr), sizeof(ptr));
free_root(&ptr,MYF(0));
}
@@ -654,7 +760,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
static const char includedir_keyword[]= "includedir";
static const char include_keyword[]= "include";
const int max_recursion_level= 10;
- FILE *fp;
+ MYSQL_FILE *fp;
uint line=0;
my_bool found_group=0;
uint i;
@@ -675,7 +781,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
strmov(name,config_file);
}
fn_format(name,name,"","",4);
-#if !defined(__WIN__) && !defined(__NETWARE__)
+#if !defined(__WIN__)
{
MY_STAT stat_info;
if (!my_stat(name,&stat_info,MYF(0)))
@@ -694,10 +800,10 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
}
}
#endif
- if (!(fp= my_fopen(name, O_RDONLY, MYF(0))))
+ if (!(fp= mysql_file_fopen(key_file_cnf, name, O_RDONLY, MYF(0))))
return 1; /* Ignore wrong files */
- while (fgets(buff, sizeof(buff) - 1, fp))
+ while (mysql_file_fgets(buff, sizeof(buff) - 1, fp))
{
line++;
/* Ignore comment and empty lines */
@@ -887,11 +993,11 @@ static int search_default_file_with_ext(Process_option_func opt_handler,
goto err;
}
}
- my_fclose(fp,MYF(0));
+ mysql_file_fclose(fp, MYF(0));
return(0);
err:
- my_fclose(fp,MYF(0));
+ mysql_file_fclose(fp, MYF(0));
return -1; /* Fatal error */
}
@@ -921,7 +1027,6 @@ static char *remove_end_comment(char *ptr)
return ptr;
}
-#include <help_start.h>
void my_print_default_files(const char *conf_file)
{
@@ -1001,8 +1106,6 @@ void print_defaults(const char *conf_file, const char **groups)
--defaults-extra-file=# Read this file after the global files are read.");
}
-#include <help_end.h>
-
static int add_directory(MEM_ROOT *alloc, const char *dir, const char **dirs)
{
@@ -1095,10 +1198,11 @@ static const char **init_default_directories(MEM_ROOT *alloc)
const char **dirs;
char *env;
int errors= 0;
+ DBUG_ENTER("init_default_directories");
dirs= (const char **)alloc_root(alloc, DEFAULT_DIRS_SIZE * sizeof(char *));
if (dirs == NULL)
- return NULL;
+ DBUG_RETURN(NULL);
bzero((char *) dirs, DEFAULT_DIRS_SIZE * sizeof(char *));
#ifdef __WIN__
@@ -1117,10 +1221,6 @@ static const char **init_default_directories(MEM_ROOT *alloc)
errors += add_directory(alloc, fname_buffer, dirs);
}
-#elif defined(__NETWARE__)
-
- errors += add_directory(alloc, "sys:/etc/", dirs);
-
#else
errors += add_directory(alloc, "/etc/", dirs);
@@ -1133,15 +1233,15 @@ static const char **init_default_directories(MEM_ROOT *alloc)
#endif
- if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV))))
+ if ((env= getenv("MYSQL_HOME")))
errors += add_directory(alloc, env, dirs);
/* Placeholder for --defaults-extra-file=<path> */
errors += add_directory(alloc, "", dirs);
-#if !defined(__WIN__) && !defined(__NETWARE__)
+#if !defined(__WIN__)
errors += add_directory(alloc, "~/", dirs);
#endif
- return (errors > 0 ? NULL : dirs);
+ DBUG_RETURN(errors > 0 ? NULL : dirs);
}