From 72e7f011b29998d8a3e15eb5b381ef962af5fe5b Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Fri, 5 Apr 2019 10:30:58 +0300 Subject: Upgrade to 8.0.15 --- mysql/mysys_ssl/my_default.cpp | 1523 ---------------------------------------- 1 file changed, 1523 deletions(-) delete mode 100644 mysql/mysys_ssl/my_default.cpp (limited to 'mysql/mysys_ssl/my_default.cpp') diff --git a/mysql/mysys_ssl/my_default.cpp b/mysql/mysys_ssl/my_default.cpp deleted file mode 100644 index 5a45200..0000000 --- a/mysql/mysys_ssl/my_default.cpp +++ /dev/null @@ -1,1523 +0,0 @@ -/* Copyright (c) 2000, 2016, 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 - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ - -/**************************************************************************** - Add all options from files named "group".cnf from the default_directories - before the command line arguments. - On Windows defaults will also search in the Windows directory for a file - called 'group'.ini - As long as the program uses the last argument for conflicting - options one only have to add a call to "load_defaults" to enable - use of default values. - pre- and end 'blank space' are removed from options and values. The - following escape sequences are recognized in values: \b \t \n \r \\ - - The following arguments are handled automatically; If used, they must be - first argument on the command line! - --no-defaults ; no options are read, except for the ones provided in the - login file. - --defaults-file=full-path-to-default-file ; Only this file will be read. - --defaults-extra-file=full-path-to-default-file ; Read this file before ~/ - --defaults-group-suffix ; Also read groups with concat(group, suffix) - --print-defaults ; Print the modified command line and exit - --login-path=login-path-name ; Read options under login-path-name from - the login file. -****************************************************************************/ - -#include "../mysys/mysys_priv.h" -#include "my_default.h" -#include "my_default_priv.h" -#include "m_string.h" -#include "m_ctype.h" -#include -#include -#include "mysql/psi/mysql_file.h" -#ifdef _WIN32 -#include -#endif - -#include "prealloced_array.h" - -C_MODE_START -#ifdef HAVE_PSI_INTERFACE -extern PSI_file_key key_file_cnf; -#endif -PSI_memory_key key_memory_defaults; -C_MODE_END - -/** - 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; -} - -/* - This flag indicates that the argument separator string - (args_separator) should be added to the list of arguments, - in order to separate arguments received from config file - and command line. -*/ -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; -const char *my_defaults_extra_file=0; - -static const char *my_login_path= 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 6 -#define DEFAULT_DIRS_SIZE (MAX_DEFAULT_DIRS + 1) /* Terminate with NULL */ -static const char **default_directories = NULL; - -#ifdef _WIN32 -static const char *f_extensions[]= { ".ini", ".cnf", 0 }; -#define NEWLINE "\r\n" -#else -static const char *f_extensions[]= { ".cnf", 0 }; -#define NEWLINE "\n" -#endif - -extern "C" { -static int handle_default_option(void *in_ctx, const char *group_name, - const char *option); -} - -/* - This structure defines the context that we pass to callback - function 'handle_default_option' used in search_default_file - to process each option. This context is used if search_default_file - was called from load_defaults. -*/ - -typedef Prealloced_array My_args; -struct handle_option_ctx -{ - MEM_ROOT *alloc; - My_args *m_args; - TYPELIB *group; -}; - -static int search_default_file(Process_option_func func, void *func_ctx, - const char *dir, const char *config_file, - my_bool is_login_file); -static int search_default_file_with_ext(Process_option_func func, - void *func_ctx, - const char *dir, const char *ext, - const char *config_file, - int recursion_level, - my_bool is_login_file); -static my_bool mysql_file_getline(char *str, int size, MYSQL_FILE *file, - my_bool is_login_file); - -/** - Create the list of default directories. - - @param alloc MEM_ROOT where the list of directories is stored - - @details - The directories searched, in order, are: - - Windows: GetSystemWindowsDirectory() - - Windows: GetWindowsDirectory() - - Windows: C:/ - - Windows: Directory above where the executable is located - - Unix: /etc/ - - Unix: /etc/mysql/ - - Unix: --sysconfdir= (compile-time option) - - ALL: getenv("MYSQL_HOME") - - ALL: --defaults-extra-file= (run-time option) - - Unix: ~/ - - On all systems, if a directory is already in the list, it will be moved - to the end of the list. This avoids reading defaults files multiple times, - while ensuring the correct precedence. - - @retval NULL Failure (out of memory, probably) - @retval other Pointer to NULL-terminated array of default directories -*/ - -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 too 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 - my_search_option_files() - conf_file Basename for configuration file to search for. - 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. - default_directories List of default directories. - found_no_defaults TRUE, if --no-defaults is specified. - - DESCRIPTION - Process the default options from argc & argv - Read through each found config file looks and calls 'func' to process - each option. This function also reads options from login file. - - NOTES - --defaults-group-suffix is only processed if we are called from - load_defaults(). - - - RETURN - 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 -*/ - -int my_search_option_files(const char *conf_file, int *argc, char ***argv, - uint *args_used, Process_option_func func, - void *func_ctx, const char **default_directories, - my_bool is_login_file, my_bool found_no_defaults) -{ - const char **dirs, *forced_default_file, *forced_extra_defaults; - int error= 0; - DBUG_ENTER("my_search_option_files"); - - /* Skip for login file. */ - if (! is_login_file) - { - /* 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, - (char **) &my_login_path, found_no_defaults); - - if (! my_defaults_group_suffix) - my_defaults_group_suffix= getenv(STRINGIFY_ARG(DEFAULT_GROUP_SUFFIX_ENV)); - - 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 - load_defaults() as otherwise we can't know the type of 'func_ctx' - */ - - if (my_defaults_group_suffix && func == handle_default_option) - { - /* Handle --defaults-group-suffix= */ - uint i; - const char **extra_groups; - const size_t instance_len= strlen(my_defaults_group_suffix); - struct handle_option_ctx *ctx= (struct handle_option_ctx*) func_ctx; - char *ptr; - TYPELIB *group= ctx->group; - - if (!(extra_groups= - (const char**)alloc_root(ctx->alloc, - (2*group->count+1)*sizeof(char*)))) - DBUG_RETURN(2); - - for (i= 0; i < group->count; i++) - { - size_t len; - extra_groups[i]= group->type_names[i]; /** copy group */ - - len= strlen(extra_groups[i]); - if (!(ptr= (char *) alloc_root(ctx->alloc, - (uint) (len + instance_len + 1)))) - DBUG_RETURN(2); - - extra_groups[i+group->count]= ptr; - - /** Construct new group */ - memcpy(ptr, extra_groups[i], len); - memcpy(ptr+len, my_defaults_group_suffix, instance_len+1); - } - - group->count*= 2; - group->type_names= extra_groups; - group->type_names[group->count]= 0; - } - } - else if (my_login_path && func == handle_default_option) - { - /* Handle --login_path= */ - uint i; - size_t len; - const char **extra_groups; - size_t instance_len= 0; - struct handle_option_ctx *ctx= (struct handle_option_ctx*) func_ctx; - char *ptr; - TYPELIB *group= ctx->group; - - if (!(extra_groups= (const char**)alloc_root(ctx->alloc, - (group->count + 3) - * sizeof(char *)))) - DBUG_RETURN(2); - - for (i= 0; i < group->count; i++) - { - extra_groups[i]= group->type_names[i]; /** copy group */ - } - - extra_groups[i]= my_login_path; - - if (my_defaults_group_suffix && func == handle_default_option) - { - instance_len= strlen(my_defaults_group_suffix); - len= strlen(extra_groups[i]); - - if (!(ptr= (char *) alloc_root(ctx->alloc, - (uint) (len + instance_len + 1)))) - DBUG_RETURN(2); - - extra_groups[i + 1]= ptr; - - /** Construct new group */ - memcpy(ptr, extra_groups[i], len); - memcpy(ptr+len, my_defaults_group_suffix, instance_len + 1); - group->count += 1; - } - - group->count += 1; - group->type_names= extra_groups; - group->type_names[group->count]= 0; - } - - // If conf_file is an absolute path, we only read it - if (dirname_length(conf_file)) - { - if ((error= search_default_file(func, func_ctx, NullS, conf_file, - is_login_file)) < 0) - goto err; - } - // If my defaults file is set (from a previous run), we read it - else if (my_defaults_file) - { - if ((error= search_default_file_with_ext(func, func_ctx, "", "", - my_defaults_file, 0, - is_login_file)) < 0) - goto err; - if (error > 0) - { - my_message_local(ERROR_LEVEL, - "Could not open required defaults file: %s", - my_defaults_file); - goto err; - } - } - else if (! found_no_defaults) - { - for (dirs= default_directories ; *dirs; dirs++) - { - if (**dirs) - { - if (search_default_file(func, func_ctx, *dirs, conf_file, - is_login_file) < 0) - goto err; - } - else if (my_defaults_extra_file) - { - if ((error= search_default_file_with_ext(func, func_ctx, "", "", - my_defaults_extra_file, 0, - is_login_file)) < 0) - goto err; /* Fatal error */ - if (error > 0) - { - my_message_local(ERROR_LEVEL, - "Could not open required defaults file: %s", - my_defaults_extra_file); - goto err; - } - } - } - } - - DBUG_RETURN(0); - -err: - my_message_local(ERROR_LEVEL, - "Fatal error in defaults handling. Program aborted!"); - DBUG_RETURN(1); -} - - -/* - The option handler for load_defaults. - - SYNOPSIS - handle_deault_option() - in_ctx Handler context. In this case it is a - handle_option_ctx structure. - group_name The name of the group the option belongs to. - option The very option to be processed. It is already - prepared to be used in argv (has -- prefix). If it - is NULL, we are handling a new group (section). - - DESCRIPTION - This handler checks whether a group is one of the listed and adds an option - to the array if yes. Some other handler can record, for instance, all - groups and their options, not knowing in advance the names and amount of - groups. - - RETURN - 0 - ok - 1 - error occured -*/ - -static int handle_default_option(void *in_ctx, const char *group_name, - const char *option) -{ - char *tmp; - struct handle_option_ctx *ctx= (struct handle_option_ctx *) in_ctx; - - if (!option) - return 0; - - if (find_type((char *)group_name, ctx->group, FIND_TYPE_NO_PREFIX)) - { - if (!(tmp= (char *) alloc_root(ctx->alloc, strlen(option) + 1))) - return 1; - if (ctx->m_args->push_back(tmp)) - return 1; - my_stpcpy(tmp, option); - } - - return 0; -} - - -/* - Gets options from the command line, however if --no-defaults - option is used, --defaults-file & --defaults-extra-file options - would be ignored. - - 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 - group_suffix --defaults-group-suffix option - login_path --login-path option - - 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, - char **login_path, - my_bool found_no_defaults) -{ - int org_argc= argc, prev_argc= 0, default_option_count= 0; - *defaults= *extra_defaults= *group_suffix= *login_path= 0; - - while (argc >= 2 && argc != prev_argc) - { - /* Skip program name or previously handled argument */ - argv++; - prev_argc= argc; /* To check if we found */ - /* --no-defaults is always the first option. */ - if (is_prefix(*argv,"--no-defaults") && ! default_option_count) - { - argc--; - default_option_count ++; - continue; - } - if (!*defaults && is_prefix(*argv, "--defaults-file=") && ! found_no_defaults) - { - *defaults= *argv + sizeof("--defaults-file=")-1; - argc--; - default_option_count ++; - continue; - } - if (!*extra_defaults && is_prefix(*argv, "--defaults-extra-file=") - && ! found_no_defaults) - { - *extra_defaults= *argv + sizeof("--defaults-extra-file=")-1; - argc--; - default_option_count ++; - continue; - } - if (!*group_suffix && is_prefix(*argv, "--defaults-group-suffix=")) - { - *group_suffix= *argv + sizeof("--defaults-group-suffix=")-1; - argc--; - default_option_count ++; - continue; - } - if (!*login_path && is_prefix(*argv, "--login-path=")) - { - *login_path= *argv + sizeof("--login-path=")-1; - argc--; - default_option_count ++; - continue; - } - } - return org_argc - argc; -} - -/* - Wrapper around my_load_defaults() for interface compatibility. - - SYNOPSIS - load_defaults() - conf_file Basename for configuration file to search for. - If this is a path, then only this file is read. - groups Which [group] entrys to read. - Points to an null terminated array of pointers - argc Pointer to argc of original program - argv Pointer to argv of original program - - NOTES - - This function is NOT thread-safe as it uses a global pointer internally. - See also notes for my_load_defaults(). - - RETURN - 0 ok - 1 The given conf_file didn't exists -*/ -int load_defaults(const char *conf_file, const char **groups, - int *argc, char ***argv) -{ - return my_load_defaults(conf_file, groups, argc, argv, &default_directories); -} - -/** A global to turn off or on reading the mylogin file. On by default */ -my_bool my_defaults_read_login_file= TRUE; -/* - Read options from configurations files - - SYNOPSIS - my_load_defaults() - conf_file Basename for configuration file to search for. - If this is a path, then only this file is read. - groups Which [group] entrys to read. - Points to an null terminated array of pointers - argc Pointer to argc of original program - argv Pointer to argv of original program - default_directories Pointer to a location where a pointer to the list - of default directories will be stored - - IMPLEMENTATION - - Read options from configuration files and put them BEFORE the arguments - that are already in argc and argv. This way the calling program can - easily command line options override options in configuration files - - NOTES - In case of fatal error, the function will print a warning and do - exit(1) - - To free used memory one should call free_defaults() with the argument - that was put in *argv - - RETURN - - If successful, 0 is returned. If 'default_directories' is not NULL, - a pointer to the array of default directory paths is stored to a location - it points to. That stored value must be passed to my_search_option_files() - later. - - - 1 is returned if the given conf_file didn't exist. In this case, the - value pointed to by default_directories is undefined. -*/ - - -int my_load_defaults(const char *conf_file, const char **groups, - int *argc, char ***argv, const char ***default_directories) -{ - My_args my_args(key_memory_defaults); - TYPELIB group; - my_bool found_print_defaults= 0; - uint args_used= 0; - int error= 0; - MEM_ROOT alloc; - char *ptr,**res; - struct handle_option_ctx ctx; - const char **dirs; - char my_login_file[FN_REFLEN]; - my_bool found_no_defaults= false; - uint args_sep= my_getopt_use_args_separator ? 1 : 0; - DBUG_ENTER("load_defaults"); - - init_alloc_root(key_memory_defaults, &alloc,512,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")) - found_no_defaults= TRUE; - - group.count=0; - group.name= "defaults"; - group.type_names= groups; - - for (; *groups ; groups++) - group.count++; - - ctx.alloc= &alloc; - ctx.m_args= &my_args; - ctx.group= &group; - - if ((error= my_search_option_files(conf_file, argc, argv, - &args_used, handle_default_option, - (void *) &ctx, dirs, false, found_no_defaults))) - { - free_root(&alloc,MYF(0)); - DBUG_RETURN(error); - } - - if (my_defaults_read_login_file) - { - /* Read options from login group. */ - if (my_default_get_login_file(my_login_file, sizeof(my_login_file)) && - (error= my_search_option_files(my_login_file, argc, argv, &args_used, - handle_default_option, (void *) &ctx, - dirs, true, found_no_defaults))) - { - 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)+ - (my_args.size() + *argc + 1 + args_sep) *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 */ - if (!my_args.empty()) - memcpy((res+1), &my_args[0], my_args.size() * sizeof(char*)); - /* Skip --defaults-xxx options */ - (*argc)-= args_used; - (*argv)+= args_used; - - /* - Check if we wan't 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 */ - } - - if (my_getopt_use_args_separator) - { - /* set arguments separator for arguments from config file and - command line */ - set_args_separator(&res[my_args.size() + 1]); - } - - if (*argc) - memcpy((uchar*) (res + 1 + my_args.size() + args_sep), - (char*) ((*argv)+1), - (*argc-1)*sizeof(char*)); - res[my_args.size() + *argc + args_sep]= 0; /* last null */ - - (*argc)+= my_args.size() + args_sep; - *argv= res; - *(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */ - - if (default_directories) - *default_directories= dirs; - - if (found_no_defaults) - DBUG_RETURN(0); - - if (found_print_defaults) - { - int i; - printf("%s would have been started with the following arguments:\n", - **argv); - for (i=1 ; i < *argc ; i++) - if (!my_getopt_is_args_separator((*argv)[i])) /* skip arguments separator */ - { - if(strncmp((*argv)[i], "--password", 10) == 0) - printf("%s ", "--password=*****"); - else - printf("%s ", (*argv)[i]); - } - puts(""); - exit(0); - } - - DBUG_RETURN(0); - - err: - my_message_local(ERROR_LEVEL, - "Fatal error in defaults handling. Program aborted!"); - exit(1); - return 0; /* Keep compiler happy */ -} - - -void free_defaults(char **argv) -{ - MEM_ROOT ptr; - memcpy(&ptr, ((char *) argv) - sizeof(ptr), sizeof(ptr)); - free_root(&ptr,MYF(0)); -} - - -static int search_default_file(Process_option_func opt_handler, - void *handler_ctx, - const char *dir, - const char *config_file, - my_bool is_login_file) -{ - char **ext; - const char *empty_list[]= { "", 0 }; - my_bool have_ext= fn_ext(config_file)[0] != 0; - const char **exts_to_use= have_ext ? empty_list : f_extensions; - - for (ext= (char**) exts_to_use; *ext; ext++) - { - int error; - if ((error= search_default_file_with_ext(opt_handler, handler_ctx, - dir, *ext, - config_file, 0, is_login_file)) < 0) - return error; - } - return 0; -} - - -/* - Skip over keyword and get argument after keyword - - SYNOPSIS - get_argument() - keyword Include directive keyword - kwlen Length of keyword - ptr Pointer to the keword in the line under process - line line number - - RETURN - 0 error - # Returns pointer to the argument after the keyword. -*/ - -static char *get_argument(const char *keyword, size_t kwlen, - char *ptr, char *name, uint line) -{ - char *end; - - /* Skip over "include / includedir keyword" and following whitespace */ - - for (ptr+= kwlen - 1; - my_isspace(&my_charset_latin1, ptr[0]); - ptr++) - {} - - /* - Trim trailing whitespace from directory name - The -1 below is for the newline added by fgets() - Note that my_isspace() is true for \r and \n - */ - for (end= ptr + strlen(ptr) - 1; - my_isspace(&my_charset_latin1, *(end - 1)); - end--) - {} - end[0]= 0; /* Cut off end space */ - - /* Print error msg if there is nothing after !include* directive */ - if (end <= ptr) - { - my_message_local(ERROR_LEVEL, - "Wrong '!%s' directive in config file %s at line %d!", - keyword, name, line); - return 0; - } - return ptr; -} - - -/* - Open a configuration file (if exists) and read given options from it - - SYNOPSIS - search_default_file_with_ext() - opt_handler Option handler function. It is used to process - every separate option. - handler_ctx Pointer to the structure to store actual - parameters of the function. - dir directory to read - ext Extension for configuration file - config_file Name of configuration file - group groups to read - recursion_level the level of recursion, got while processing - "!include" or "!includedir" - is_login_file TRUE, when login file is being processed. - - RETURN - 0 Success - -1 Fatal error, abort - 1 File not found (Warning) -*/ - -static int search_default_file_with_ext(Process_option_func opt_handler, - void *handler_ctx, - const char *dir, - const char *ext, - const char *config_file, - int recursion_level, - my_bool is_login_file) -{ - char name[FN_REFLEN + 10], buff[4096], curr_gr[4096], *ptr, *end, **tmp_ext; - char *value, option[4096+2], tmp[FN_REFLEN]; - static const char includedir_keyword[]= "includedir"; - static const char include_keyword[]= "include"; - const int max_recursion_level= 10; - MYSQL_FILE *fp; - uint line=0; - my_bool found_group=0; - uint i, rc; - MY_DIR *search_dir; - FILEINFO *search_file; - - if ((dir ? strlen(dir) : 0 )+strlen(config_file) >= FN_REFLEN-3) - return 0; /* Ignore wrong paths */ - if (dir) - { - end=convert_dirname(name, dir, NullS); - if (dir[0] == FN_HOMELIB) /* Add . to filenames in home */ - *end++='.'; - strxmov(end,config_file,ext,NullS); - } - else - { - my_stpcpy(name,config_file); - } - fn_format(name,name,"","",4); - - if ((rc= check_file_permissions(name, is_login_file)) < 2) - return (int) rc; - - if (is_login_file) - { - if ( !(fp = mysql_file_fopen(key_file_cnf, name, (O_RDONLY | O_BINARY), - MYF(0)))) - return 1; /* Ignore wrong files. */ - } - else - { - if ( !(fp = mysql_file_fopen(key_file_cnf, name, O_RDONLY, MYF(0)))) - return 1; /* Ignore wrong files */ - } - - while (mysql_file_getline(buff, sizeof(buff) - 1, fp, is_login_file)) - { - line++; - /* Ignore comment and empty lines */ - for (ptr= buff; my_isspace(&my_charset_latin1, *ptr); ptr++) - {} - - if (*ptr == '#' || *ptr == ';' || !*ptr) - continue; - - /* Configuration File Directives */ - if (*ptr == '!') - { - if (recursion_level >= max_recursion_level) - { - for (end= ptr + strlen(ptr) - 1; - my_isspace(&my_charset_latin1, *(end - 1)); - end--) - {} - end[0]= 0; - my_message_local(WARNING_LEVEL, - "skipping '%s' directive as maximum include" - "recursion level was reached in file %s at line %d!", - ptr, name, line); - continue; - } - - /* skip over `!' and following whitespace */ - for (++ptr; my_isspace(&my_charset_latin1, ptr[0]); ptr++) - {} - - if ((!strncmp(ptr, includedir_keyword, - sizeof(includedir_keyword) - 1)) && - my_isspace(&my_charset_latin1, ptr[sizeof(includedir_keyword) - 1])) - { - if (!(ptr= get_argument(includedir_keyword, - sizeof(includedir_keyword), - ptr, name, line))) - goto err; - - if (!(search_dir= my_dir(ptr, MYF(MY_WME)))) - goto err; - - for (i= 0; i < search_dir->number_off_files; i++) - { - search_file= search_dir->dir_entry + i; - ext= fn_ext(search_file->name); - - /* check extension */ - for (tmp_ext= (char**) f_extensions; *tmp_ext; tmp_ext++) - { - if (!strcmp(ext, *tmp_ext)) - break; - } - - if (*tmp_ext) - { - fn_format(tmp, search_file->name, ptr, "", - MY_UNPACK_FILENAME | MY_SAFE_PATH); - - search_default_file_with_ext(opt_handler, handler_ctx, "", "", tmp, - recursion_level + 1, is_login_file); - } - } - - my_dirend(search_dir); - } - else if ((!strncmp(ptr, include_keyword, sizeof(include_keyword) - 1)) && - my_isspace(&my_charset_latin1, ptr[sizeof(include_keyword)-1])) - { - if (!(ptr= get_argument(include_keyword, - sizeof(include_keyword), ptr, - name, line))) - goto err; - - search_default_file_with_ext(opt_handler, handler_ctx, "", "", ptr, - recursion_level + 1, is_login_file); - } - - continue; - } - - if (*ptr == '[') /* Group name */ - { - found_group=1; - if (!(end= strchr(++ptr,']'))) - { - my_message_local(ERROR_LEVEL, - "Wrong group definition in config file %s at line %d!", - name,line); - goto err; - } - /* Remove end space */ - for ( ; my_isspace(&my_charset_latin1, end[-1]); end --) - {} - - end[0]=0; - - strmake(curr_gr, ptr, MY_MIN((size_t) (end-ptr)+1, sizeof(curr_gr)-1)); - - /* signal that a new group is found */ - opt_handler(handler_ctx, curr_gr, NULL); - - continue; - } - if (!found_group) - { - my_message_local(ERROR_LEVEL, - "Found option without preceding group in config file" - " %s at line %d!", name,line); - goto err; - } - - - end= remove_end_comment(ptr); - if ((value= strchr(ptr, '='))) - end= value; /* Option without argument */ - for ( ; my_isspace(&my_charset_latin1, end[-1]) ; end--) - {} - - if (!value) - { - strmake(my_stpcpy(option,"--"),ptr, (size_t) (end-ptr)); - if (opt_handler(handler_ctx, curr_gr, option)) - goto err; - } - else - { - /* Remove pre- and end space */ - char *value_end; - for (value++ ; my_isspace(&my_charset_latin1, *value); value ++) - {} - - value_end=strend(value); - /* - We don't have to test for value_end >= value as we know there is - an '=' before - */ - for ( ; my_isspace(&my_charset_latin1, value_end[-1]); value_end --) - {} - - if (value_end < value) /* Empty string */ - value_end=value; - - /* remove quotes around argument */ - if ((*value == '\"' || *value == '\'') && /* First char is quote */ - (value + 1 < value_end ) && /* String is longer than 1 */ - *value == value_end[-1] ) /* First char is equal to last char */ - { - value++; - value_end--; - } - ptr=my_stpnmov(my_stpcpy(option,"--"),ptr,(size_t) (end-ptr)); - *ptr++= '='; - - for ( ; value != value_end; value++) - { - if (*value == '\\' && value != value_end-1) - { - switch(*++value) { - case 'n': - *ptr++='\n'; - break; - case 't': - *ptr++= '\t'; - break; - case 'r': - *ptr++ = '\r'; - break; - case 'b': - *ptr++ = '\b'; - break; - case 's': - *ptr++= ' '; /* space */ - break; - case '\"': - *ptr++= '\"'; - break; - case '\'': - *ptr++= '\''; - break; - case '\\': - *ptr++= '\\'; - break; - default: /* Unknown; Keep '\' */ - *ptr++= '\\'; - *ptr++= *value; - break; - } - } - else - *ptr++= *value; - } - *ptr=0; - if (opt_handler(handler_ctx, curr_gr, option)) - goto err; - } - } - mysql_file_fclose(fp, MYF(0)); - return(0); - - err: - mysql_file_fclose(fp, MYF(0)); - return -1; /* Fatal error */ -} - - -static char *remove_end_comment(char *ptr) -{ - char quote= 0; /* we are inside quote marks */ - char escape= 0; /* symbol is protected by escape chagacter */ - - for (; *ptr; ptr++) - { - if ((*ptr == '\'' || *ptr == '\"') && !escape) - { - if (!quote) - quote= *ptr; - else if (quote == *ptr) - quote= 0; - } - /* We are not inside a string */ - if (!quote && *ptr == '#') - { - *ptr= 0; - return ptr; - } - escape= (quote && *ptr == '\\' && !escape); - } - return ptr; -} - - -/** - Read one line from the specified file. In case - of scrambled login file, the line read is first - decrypted and then returned. - - @param str [out] Buffer to store the read text. - @param size [in] At max, size-1 bytes to be read. - @param file [in] Source file. - @param is_login_file [in] TRUE, when login file is being processed. - - @return 1 Success - 0 Error -*/ - -static my_bool mysql_file_getline(char *str, int size, MYSQL_FILE *file, - my_bool is_login_file) -{ - uchar cipher[4096], len_buf[MAX_CIPHER_STORE_LEN]; - static unsigned char my_key[LOGIN_KEY_LEN]; - int length= 0, cipher_len= 0; - - if (is_login_file) - { - if (mysql_file_ftell(file, MYF(MY_WME)) == 0) - { - /* Move past unused bytes. */ - mysql_file_fseek(file, 4, SEEK_SET, MYF(MY_WME)); - if (mysql_file_fread(file, my_key, LOGIN_KEY_LEN, - MYF(MY_WME)) != LOGIN_KEY_LEN) - return 0; - } - - if (mysql_file_fread(file, len_buf, MAX_CIPHER_STORE_LEN, - MYF(MY_WME)) == MAX_CIPHER_STORE_LEN) - { - cipher_len= sint4korr(len_buf); - if (cipher_len > size) - return 0; - } - else - return 0; - - mysql_file_fread(file, cipher, cipher_len, MYF(MY_WME)); - if ((length= my_aes_decrypt(cipher, cipher_len, (unsigned char *) str, - my_key, LOGIN_KEY_LEN, my_aes_128_ecb, NULL)) < 0) - { - /* Attempt to decrypt failed. */ - return 0; - } - str[length]= 0; - return 1; - } - else - { - if (mysql_file_fgets(str, size, file)) - return 1; - else - return 0; - } -} - - -void my_print_default_files(const char *conf_file) -{ - const char *empty_list[]= { "", 0 }; - my_bool have_ext= fn_ext(conf_file)[0] != 0; - const char **exts_to_use= have_ext ? empty_list : f_extensions; - char name[FN_REFLEN], **ext; - - puts("\nDefault options are read from the following files in the given order:"); - - if (dirname_length(conf_file)) - fputs(conf_file,stdout); - else - { - const char **dirs; - MEM_ROOT alloc; - init_alloc_root(key_memory_defaults, &alloc, 512, 0); - - if ((dirs= init_default_directories(&alloc)) == NULL) - { - fputs("Internal error initializing default directories list", stdout); - } - else - { - for ( ; *dirs; dirs++) - { - for (ext= (char**) exts_to_use; *ext; ext++) - { - const char *pos; - char *end; - if (**dirs) - pos= *dirs; - else if (my_defaults_extra_file) - pos= my_defaults_extra_file; - else - continue; - end= convert_dirname(name, pos, NullS); - if (name[0] == FN_HOMELIB) /* Add . to filenames in home */ - *end++= '.'; - - if (my_defaults_extra_file == pos) - end[(strlen(end)-1)] = ' '; - else - strxmov(end, conf_file, *ext , " ", NullS); - fputs(name, stdout); - } - } - } - - free_root(&alloc, MYF(0)); - } - puts(""); -} - -void print_defaults(const char *conf_file, const char **groups) -{ - const char **groups_save= groups; - my_print_default_files(conf_file); - - fputs("The following groups are read:",stdout); - for ( ; *groups ; groups++) - { - fputc(' ',stdout); - fputs(*groups,stdout); - } - - if (my_defaults_group_suffix) - { - groups= groups_save; - for ( ; *groups ; groups++) - { - fputc(' ',stdout); - fputs(*groups,stdout); - fputs(my_defaults_group_suffix,stdout); - } - } - puts("\nThe following options may be given as the first argument:\n\ ---print-defaults Print the program argument list and exit.\n\ ---no-defaults Don't read default options from any option file,\n\ - except for login file.\n\ ---defaults-file=# Only read default options from the given file #.\n\ ---defaults-extra-file=# Read this file after the global files are read.\n\ ---defaults-group-suffix=#\n\ - Also read groups with concat(group, suffix)\n\ ---login-path=# Read this path from the login file."); -} - - -static int add_directory(MEM_ROOT *alloc, const char *dir, const char **dirs) -{ - char buf[FN_REFLEN]; - size_t len; - char *p; - my_bool err MY_ATTRIBUTE((unused)); - - len= normalize_dirname(buf, dir); - if (!(p= strmake_root(alloc, buf, len))) - return 1; /* Failure */ - /* Should never fail if DEFAULT_DIRS_SIZE is correct size */ - err= array_append_string_unique(p, dirs, DEFAULT_DIRS_SIZE); - DBUG_ASSERT(err == FALSE); - - return 0; -} - - -#ifdef _WIN32 -/* - This wrapper for GetSystemWindowsDirectory() will dynamically bind to the - function if it is available, emulate it on NT4 Terminal Server by stripping - the \SYSTEM32 from the end of the results of GetSystemDirectory(), or just - return GetSystemDirectory(). - */ - -typedef UINT (WINAPI *GET_SYSTEM_WINDOWS_DIRECTORY)(LPSTR, UINT); - -static size_t my_get_system_windows_directory(char *buffer, size_t size) -{ - size_t count; - GET_SYSTEM_WINDOWS_DIRECTORY - func_ptr= (GET_SYSTEM_WINDOWS_DIRECTORY) - GetProcAddress(GetModuleHandle("kernel32.dll"), - "GetSystemWindowsDirectoryA"); - - if (func_ptr) - return func_ptr(buffer, (uint) size); - - /* - Windows NT 4.0 Terminal Server Edition: - To retrieve the shared Windows directory, call GetSystemDirectory and - trim the "System32" element from the end of the returned path. - */ - count= GetSystemDirectory(buffer, (uint) size); - if (count > 8 && stricmp(buffer+(count-8), "\\System32") == 0) - { - count-= 8; - buffer[count] = '\0'; - } - return count; -} - - -static const char *my_get_module_parent(char *buf, size_t size) -{ - char *last= NULL; - char *end; - if (!GetModuleFileName(NULL, buf, (DWORD) size)) - return NULL; - end= strend(buf); - - /* - Look for the second-to-last \ in the filename, but hang on - to a pointer after the last \ in case we're in the root of - a drive. - */ - for ( ; end > buf; end--) - { - if (*end == FN_LIBCHAR) - { - if (last) - { - /* Keep the last '\' as this works both with D:\ and a directory */ - end[1]= 0; - break; - } - last= end; - } - } - - return buf; -} -#endif /* _WIN32 */ - - -static const char **init_default_directories(MEM_ROOT *alloc) -{ - const char **dirs; - char *env; - int errors= 0; - - dirs= (const char **)alloc_root(alloc, DEFAULT_DIRS_SIZE * sizeof(char *)); - if (dirs == NULL) - return NULL; - memset(dirs, 0, DEFAULT_DIRS_SIZE * sizeof(char *)); - -#ifdef _WIN32 - - { - char fname_buffer[FN_REFLEN]; - if (my_get_system_windows_directory(fname_buffer, sizeof(fname_buffer))) - errors += add_directory(alloc, fname_buffer, dirs); - - if (GetWindowsDirectory(fname_buffer, sizeof(fname_buffer))) - errors += add_directory(alloc, fname_buffer, dirs); - - errors += add_directory(alloc, "C:/", dirs); - - if (my_get_module_parent(fname_buffer, sizeof(fname_buffer)) != NULL) - errors += add_directory(alloc, fname_buffer, dirs); - } - -#else - - errors += add_directory(alloc, "/etc/", dirs); - errors += add_directory(alloc, "/etc/mysql/", dirs); - -#if defined(DEFAULT_SYSCONFDIR) - if (DEFAULT_SYSCONFDIR[0]) - errors += add_directory(alloc, DEFAULT_SYSCONFDIR, dirs); -#endif /* DEFAULT_SYSCONFDIR */ - -#endif - - if ((env= getenv("MYSQL_HOME"))) - errors += add_directory(alloc, env, dirs); - - /* Placeholder for --defaults-extra-file= */ - errors += add_directory(alloc, "", dirs); - -#if !defined(_WIN32) - errors += add_directory(alloc, "~/", dirs); -#endif - - return (errors > 0 ? NULL : dirs); -} - -/** - Place the login file name in the specified buffer. - - @param file_name [out] Buffer to hold login file name - @param file_name_size [in] Length of the buffer - - @return 1 - Success - 0 - Failure -*/ - -int my_default_get_login_file(char *file_name, size_t file_name_size) -{ - size_t rc; - - if (getenv("MYSQL_TEST_LOGIN_FILE")) - rc= my_snprintf(file_name, file_name_size, "%s", - getenv("MYSQL_TEST_LOGIN_FILE")); -#ifdef _WIN32 - else if (getenv("APPDATA")) - rc= my_snprintf(file_name, file_name_size, "%s\\MySQL\\.mylogin.cnf", - getenv("APPDATA")); -#else - else if (getenv("HOME")) - rc= my_snprintf(file_name, file_name_size, "%s/.mylogin.cnf", - getenv("HOME")); -#endif - else - { - memset(file_name, 0, file_name_size); - return 0; - } - /* Anything <= 0 will be treated as error. */ - if (rc <= 0) - return 0; - - return 1; -} - -/** - Check file permissions of the option file. - - @param file_name [in] Name of the option file. - @param is_login_file [in] TRUE, when login file is being processed. - - @return 0 - Non-allowable file permissions. - 1 - Failed to stat. - 2 - Success. -*/ -int check_file_permissions(const char *file_name, my_bool is_login_file) -{ -#if !defined(_WIN32) - MY_STAT stat_info; - - if (!my_stat(file_name,&stat_info,MYF(0))) - return 1; - /* - Ignore .mylogin.cnf file if not exclusively readable/writable - by current user. - */ - if (is_login_file && (stat_info.st_mode & (S_IXUSR | S_IRWXG | S_IRWXO)) - && (stat_info.st_mode & S_IFMT) == S_IFREG) - { - my_message_local(WARNING_LEVEL, "%s should be readable/writable only by " - "current user.", file_name); - return 0; - } - /* - Ignore world-writable regular files. - This is mainly done to protect us to not read a file created by - the mysqld server, but the check is still valid in most context. - */ - else if ((stat_info.st_mode & S_IWOTH) && - (stat_info.st_mode & S_IFMT) == S_IFREG) - - { - my_message_local(WARNING_LEVEL, - "World-writable config file '%s' is ignored.", file_name); - return 0; - } -#endif - return 2; /* Success */ -} - -- cgit v1.1