2 Copyright (c) 2000-2008 MySQL AB, 2008-2010 Sun Microsystems, Inc.
3 Use is subject to license terms.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; version 2 of the License.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 /****************************************************************************
20 Add all options from files named "group".cnf from the default_directories
21 before the command line arguments.
22 On Windows defaults will also search in the Windows directory for a file
24 As long as the program uses the last argument for conflicting
25 options one only have to add a call to "load_defaults" to enable
26 use of default values.
27 pre- and end 'blank space' are removed from options and values. The
28 following escape sequences are recognized in values: \b \t \n \r \\
30 The following arguments are handled automaticly; If used, they must be
31 first argument on the command line!
32 --no-defaults ; no options are read.
33 --defaults-file=full-path-to-default-file ; Only this file will be read.
34 --defaults-extra-file=full-path-to-default-file ; Read this file before ~/
35 --defaults-group-suffix ; Also read groups with concat(group, suffix)
36 --print-defaults ; Print the modified command line and exit
37 ****************************************************************************/
39 #include "mysys_priv.h"
47 const char *my_defaults_file
=0;
48 const char *my_defaults_group_suffix
=0;
49 char *my_defaults_extra_file
=0;
51 /* Which directories are searched for options (and in which order) */
53 #define MAX_DEFAULT_DIRS 6
54 #define DEFAULT_DIRS_SIZE (MAX_DEFAULT_DIRS + 1) /* Terminate with NULL */
55 static const char **default_directories
= NULL
;
58 static const char *f_extensions
[]= { ".ini", ".cnf", 0 };
59 #define NEWLINE "\r\n"
61 static const char *f_extensions
[]= { ".cnf", 0 };
65 static int handle_default_option(void *in_ctx
, const char *group_name
,
69 This structure defines the context that we pass to callback
70 function 'handle_default_option' used in search_default_file
71 to process each option. This context is used if search_default_file
72 was called from load_defaults.
75 struct handle_option_ctx
82 static int search_default_file(Process_option_func func
, void *func_ctx
,
83 const char *dir
, const char *config_file
);
84 static int search_default_file_with_ext(Process_option_func func
,
86 const char *dir
, const char *ext
,
87 const char *config_file
, int recursion_level
);
91 Create the list of default directories.
93 @param alloc MEM_ROOT where the list of directories is stored
96 The directories searched, in order, are:
97 - Windows: GetSystemWindowsDirectory()
98 - Windows: GetWindowsDirectory()
100 - Windows: Directory above where the executable is located
104 - Unix: --sysconfdir=<path> (compile-time option)
105 - ALL: getenv(DEFAULT_HOME_ENV)
106 - ALL: --defaults-extra-file=<path> (run-time option)
109 On all systems, if a directory is already in the list, it will be moved
110 to the end of the list. This avoids reading defaults files multiple times,
111 while ensuring the correct precedence.
113 @retval NULL Failure (out of memory, probably)
114 @retval other Pointer to NULL-terminated array of default directories
117 static const char **init_default_directories(MEM_ROOT
*alloc
);
120 static char *remove_end_comment(char *ptr
);
124 Process config files in default directories.
127 my_search_option_files()
128 conf_file Basename for configuration file to search for.
129 If this is a path, then only this file is read.
130 argc Pointer to argc of original program
131 argv Pointer to argv of original program
132 args_used Pointer to variable for storing the number of
134 func Pointer to the function to process options
135 func_ctx It's context. Usually it is the structure to
136 store additional options.
138 Process the default options from argc & argv
139 Read through each found config file looks and calls 'func' to process
143 --defaults-group-suffix is only processed if we are called from
149 1 given cinf_file doesn't exist
152 The global variable 'my_defaults_group_suffix' is updated with value for
153 --defaults_group_suffix
156 int my_search_option_files(const char *conf_file
, int *argc
, char ***argv
,
157 uint
*args_used
, Process_option_func func
,
158 void *func_ctx
, const char **default_directories
)
160 const char **dirs
, *forced_default_file
, *forced_extra_defaults
;
162 DBUG_ENTER("my_search_option_files");
164 /* Check if we want to force the use a specific default file */
165 *args_used
+= get_defaults_options(*argc
- *args_used
, *argv
+ *args_used
,
166 (char **) &forced_default_file
,
167 (char **) &forced_extra_defaults
,
168 (char **) &my_defaults_group_suffix
);
170 if (! my_defaults_group_suffix
)
171 my_defaults_group_suffix
= getenv(STRINGIFY_ARG(DEFAULT_GROUP_SUFFIX_ENV
));
173 if (forced_extra_defaults
)
174 my_defaults_extra_file
= (char *) forced_extra_defaults
;
176 if (forced_default_file
)
177 my_defaults_file
= forced_default_file
;
180 We can only handle 'defaults-group-suffix' if we are called from
181 load_defaults() as otherwise we can't know the type of 'func_ctx'
184 if (my_defaults_group_suffix
&& func
== handle_default_option
)
186 /* Handle --defaults-group-suffix= */
188 const char **extra_groups
;
189 const size_t instance_len
= strlen(my_defaults_group_suffix
);
190 struct handle_option_ctx
*ctx
= (struct handle_option_ctx
*) func_ctx
;
192 TYPELIB
*group
= ctx
->group
;
195 (const char**)alloc_root(ctx
->alloc
,
196 (2*group
->count
+1)*sizeof(char*))))
199 for (i
= 0; i
< group
->count
; i
++)
202 extra_groups
[i
]= group
->type_names
[i
]; /** copy group */
204 len
= strlen(extra_groups
[i
]);
205 if (!(ptr
= alloc_root(ctx
->alloc
, (uint
) (len
+instance_len
+1))))
208 extra_groups
[i
+group
->count
]= ptr
;
210 /** Construct new group */
211 memcpy(ptr
, extra_groups
[i
], len
);
212 memcpy(ptr
+len
, my_defaults_group_suffix
, instance_len
+1);
216 group
->type_names
= extra_groups
;
217 group
->type_names
[group
->count
]= 0;
220 if (forced_default_file
)
222 if ((error
= search_default_file_with_ext(func
, func_ctx
, "", "",
223 forced_default_file
, 0)) < 0)
227 fprintf(stderr
, "Could not open required defaults file: %s\n",
228 forced_default_file
);
232 else if (dirname_length(conf_file
))
234 if ((error
= search_default_file(func
, func_ctx
, NullS
, conf_file
)) < 0)
239 for (dirs
= default_directories
; *dirs
; dirs
++)
243 if (search_default_file(func
, func_ctx
, *dirs
, conf_file
) < 0)
246 else if (my_defaults_extra_file
)
248 if ((error
= search_default_file_with_ext(func
, func_ctx
, "", "",
249 my_defaults_extra_file
, 0)) < 0)
250 goto err
; /* Fatal error */
253 fprintf(stderr
, "Could not open required defaults file: %s\n",
254 my_defaults_extra_file
);
264 fprintf(stderr
,"Fatal error in defaults handling. Program aborted\n");
270 The option handler for load_defaults.
273 handle_deault_option()
274 in_ctx Handler context. In this case it is a
275 handle_option_ctx structure.
276 group_name The name of the group the option belongs to.
277 option The very option to be processed. It is already
278 prepared to be used in argv (has -- prefix). If it
279 is NULL, we are handling a new group (section).
282 This handler checks whether a group is one of the listed and adds an option
283 to the array if yes. Some other handler can record, for instance, all
284 groups and their options, not knowing in advance the names and amount of
292 static int handle_default_option(void *in_ctx
, const char *group_name
,
296 struct handle_option_ctx
*ctx
= (struct handle_option_ctx
*) in_ctx
;
301 if (find_type((char *)group_name
, ctx
->group
, 3))
303 if (!(tmp
= alloc_root(ctx
->alloc
, strlen(option
) + 1)))
305 if (insert_dynamic(ctx
->args
, (uchar
*) &tmp
))
315 Gets options from the command line
318 get_defaults_options()
319 argc Pointer to argc of original program
320 argv Pointer to argv of original program
321 defaults --defaults-file option
322 extra_defaults --defaults-extra-file option
325 # Number of arguments used from *argv
326 defaults and extra_defaults will be set to option of the appropriate
327 items of argv array, or to NULL if there are no such options
330 int get_defaults_options(int argc
, char **argv
,
332 char **extra_defaults
,
335 int org_argc
= argc
, prev_argc
= 0;
336 *defaults
= *extra_defaults
= *group_suffix
= 0;
338 while (argc
>= 2 && argc
!= prev_argc
)
340 /* Skip program name or previously handled argument */
342 prev_argc
= argc
; /* To check if we found */
343 if (!*defaults
&& is_prefix(*argv
,"--defaults-file="))
345 *defaults
= *argv
+ sizeof("--defaults-file=")-1;
349 if (!*extra_defaults
&& is_prefix(*argv
,"--defaults-extra-file="))
351 *extra_defaults
= *argv
+ sizeof("--defaults-extra-file=")-1;
355 if (!*group_suffix
&& is_prefix(*argv
, "--defaults-group-suffix="))
357 *group_suffix
= *argv
+ sizeof("--defaults-group-suffix=")-1;
362 return org_argc
- argc
;
366 Wrapper around my_load_defaults() for interface compatibility.
370 conf_file Basename for configuration file to search for.
371 If this is a path, then only this file is read.
372 groups Which [group] entrys to read.
373 Points to an null terminated array of pointers
374 argc Pointer to argc of original program
375 argv Pointer to argv of original program
379 This function is NOT thread-safe as it uses a global pointer internally.
380 See also notes for my_load_defaults().
384 1 The given conf_file didn't exists
386 int load_defaults(const char *conf_file
, const char **groups
,
387 int *argc
, char ***argv
)
389 return my_load_defaults(conf_file
, groups
, argc
, argv
, &default_directories
);
393 Read options from configurations files
397 conf_file Basename for configuration file to search for.
398 If this is a path, then only this file is read.
399 groups Which [group] entrys to read.
400 Points to an null terminated array of pointers
401 argc Pointer to argc of original program
402 argv Pointer to argv of original program
403 default_directories Pointer to a location where a pointer to the list
404 of default directories will be stored
408 Read options from configuration files and put them BEFORE the arguments
409 that are already in argc and argv. This way the calling program can
410 easily command line options override options in configuration files
413 In case of fatal error, the function will print a warning and do
416 To free used memory one should call free_defaults() with the argument
417 that was put in *argv
420 - If successful, 0 is returned. If 'default_directories' is not NULL,
421 a pointer to the array of default directory paths is stored to a location
422 it points to. That stored value must be passed to my_search_option_files()
425 - 1 is returned if the given conf_file didn't exist. In this case, the
426 value pointed to by default_directories is undefined.
430 int my_load_defaults(const char *conf_file
, const char **groups
,
431 int *argc
, char ***argv
, const char ***default_directories
)
435 my_bool found_print_defaults
= 0;
440 struct handle_option_ctx ctx
;
442 DBUG_ENTER("load_defaults");
444 init_alloc_root(&alloc
,512,0);
445 if ((dirs
= init_default_directories(&alloc
)) == NULL
)
448 Check if the user doesn't want any default option processing
449 --no-defaults is always the first option
451 if (*argc
>= 2 && !strcmp(argv
[0][1],"--no-defaults"))
453 /* remove the --no-defaults argument and return only the other arguments */
455 if (!(ptr
=(char*) alloc_root(&alloc
,sizeof(alloc
)+
456 (*argc
+ 1)*sizeof(char*))))
458 res
= (char**) (ptr
+sizeof(alloc
));
459 res
[0]= **argv
; /* Copy program name */
460 for (i
=2 ; i
< (uint
) *argc
; i
++)
462 res
[i
-1]=0; /* End pointer */
465 *(MEM_ROOT
*) ptr
= alloc
; /* Save alloc root for free */
466 if (default_directories
)
467 *default_directories
= dirs
;
472 group
.name
= "defaults";
473 group
.type_names
= groups
;
475 for (; *groups
; groups
++)
478 if (my_init_dynamic_array(&args
, sizeof(char*),*argc
, 32))
485 error
= my_search_option_files(conf_file
, argc
, argv
, &args_used
,
486 handle_default_option
, (void *) &ctx
,
489 Here error contains <> 0 only if we have a fully specified conf_file
490 or a forced default file
492 if (!(ptr
=(char*) alloc_root(&alloc
,sizeof(alloc
)+
493 (args
.elements
+ *argc
+1) *sizeof(char*))))
495 res
= (char**) (ptr
+sizeof(alloc
));
497 /* copy name + found arguments + command line arguments to new array */
498 res
[0]= argv
[0][0]; /* Name MUST be set, even by embedded library */
499 memcpy((uchar
*) (res
+1), args
.buffer
, args
.elements
*sizeof(char*));
500 /* Skip --defaults-xxx options */
505 Check if we wan't to see the new argument list
506 This options must always be the last of the default options
508 if (*argc
>= 2 && !strcmp(argv
[0][1],"--print-defaults"))
510 found_print_defaults
=1;
511 --*argc
; ++*argv
; /* skip argument */
515 memcpy((uchar
*) (res
+1+args
.elements
), (char*) ((*argv
)+1),
516 (*argc
-1)*sizeof(char*));
517 res
[args
.elements
+ *argc
]=0; /* last null */
519 (*argc
)+=args
.elements
;
521 *(MEM_ROOT
*) ptr
= alloc
; /* Save alloc root for free */
522 delete_dynamic(&args
);
523 if (found_print_defaults
)
526 printf("%s would have been started with the following arguments:\n",
528 for (i
=1 ; i
< *argc
; i
++)
529 printf("%s ", (*argv
)[i
]);
534 if (error
== 0 && default_directories
)
535 *default_directories
= dirs
;
540 fprintf(stderr
,"Fatal error in defaults handling. Program aborted\n");
542 return 0; /* Keep compiler happy */
546 void free_defaults(char **argv
)
549 memcpy_fixed((char*) &ptr
,(char *) argv
- sizeof(ptr
), sizeof(ptr
));
550 free_root(&ptr
,MYF(0));
554 static int search_default_file(Process_option_func opt_handler
,
557 const char *config_file
)
560 const char *empty_list
[]= { "", 0 };
561 my_bool have_ext
= fn_ext(config_file
)[0] != 0;
562 const char **exts_to_use
= have_ext
? empty_list
: f_extensions
;
564 for (ext
= (char**) exts_to_use
; *ext
; ext
++)
567 if ((error
= search_default_file_with_ext(opt_handler
, handler_ctx
,
569 config_file
, 0)) < 0)
577 Skip over keyword and get argument after keyword
581 keyword Include directive keyword
582 kwlen Length of keyword
583 ptr Pointer to the keword in the line under process
588 # Returns pointer to the argument after the keyword.
591 static char *get_argument(const char *keyword
, size_t kwlen
,
592 char *ptr
, char *name
, uint line
)
596 /* Skip over "include / includedir keyword" and following whitespace */
598 for (ptr
+= kwlen
- 1;
599 my_isspace(&my_charset_latin1
, ptr
[0]);
604 Trim trailing whitespace from directory name
605 The -1 below is for the newline added by fgets()
606 Note that my_isspace() is true for \r and \n
608 for (end
= ptr
+ strlen(ptr
) - 1;
609 my_isspace(&my_charset_latin1
, *(end
- 1));
612 end
[0]= 0; /* Cut off end space */
614 /* Print error msg if there is nothing after !include* directive */
618 "error: Wrong '!%s' directive in config file: %s at line %d\n",
619 keyword
, name
, line
);
627 Open a configuration file (if exists) and read given options from it
630 search_default_file_with_ext()
631 opt_handler Option handler function. It is used to process
632 every separate option.
633 handler_ctx Pointer to the structure to store actual
634 parameters of the function.
635 dir directory to read
636 ext Extension for configuration file
637 config_file Name of configuration file
639 recursion_level the level of recursion, got while processing
640 "!include" or "!includedir"
644 -1 Fatal error, abort
645 1 File not found (Warning)
648 static int search_default_file_with_ext(Process_option_func opt_handler
,
652 const char *config_file
,
655 char name
[FN_REFLEN
+ 10], buff
[4096], curr_gr
[4096], *ptr
, *end
, **tmp_ext
;
656 char *value
, option
[4096+2], tmp
[FN_REFLEN
];
657 static const char includedir_keyword
[]= "includedir";
658 static const char include_keyword
[]= "include";
659 const int max_recursion_level
= 10;
662 my_bool found_group
=0;
665 FILEINFO
*search_file
;
667 if ((dir
? strlen(dir
) : 0 )+strlen(config_file
) >= FN_REFLEN
-3)
668 return 0; /* Ignore wrong paths */
671 end
=convert_dirname(name
, dir
, NullS
);
672 if (dir
[0] == FN_HOMELIB
) /* Add . to filenames in home */
674 strxmov(end
,config_file
,ext
,NullS
);
678 strmov(name
,config_file
);
680 fn_format(name
,name
,"","",4);
681 #if !defined(__WIN__) && !defined(__NETWARE__)
684 if (!my_stat(name
,&stat_info
,MYF(0)))
687 Ignore world-writable regular files.
688 This is mainly done to protect us to not read a file created by
689 the mysqld server, but the check is still valid in most context.
691 if ((stat_info
.st_mode
& S_IWOTH
) &&
692 (stat_info
.st_mode
& S_IFMT
) == S_IFREG
)
694 fprintf(stderr
, "Warning: World-writable config file '%s' is ignored\n",
700 if (!(fp
= my_fopen(name
, O_RDONLY
, MYF(0))))
701 return 1; /* Ignore wrong files */
703 while (fgets(buff
, sizeof(buff
) - 1, fp
))
706 /* Ignore comment and empty lines */
707 for (ptr
= buff
; my_isspace(&my_charset_latin1
, *ptr
); ptr
++)
710 if (*ptr
== '#' || *ptr
== ';' || !*ptr
)
713 /* Configuration File Directives */
716 if (recursion_level
>= max_recursion_level
)
718 for (end
= ptr
+ strlen(ptr
) - 1;
719 my_isspace(&my_charset_latin1
, *(end
- 1));
724 "Warning: skipping '%s' directive as maximum include"
725 "recursion level was reached in file %s at line %d\n",
730 /* skip over `!' and following whitespace */
731 for (++ptr
; my_isspace(&my_charset_latin1
, ptr
[0]); ptr
++)
734 if ((!strncmp(ptr
, includedir_keyword
,
735 sizeof(includedir_keyword
) - 1)) &&
736 my_isspace(&my_charset_latin1
, ptr
[sizeof(includedir_keyword
) - 1]))
738 if (!(ptr
= get_argument(includedir_keyword
,
739 sizeof(includedir_keyword
),
743 if (!(search_dir
= my_dir(ptr
, MYF(MY_WME
))))
746 for (i
= 0; i
< (uint
) search_dir
->number_off_files
; i
++)
748 search_file
= search_dir
->dir_entry
+ i
;
749 ext
= fn_ext(search_file
->name
);
751 /* check extension */
752 for (tmp_ext
= (char**) f_extensions
; *tmp_ext
; tmp_ext
++)
754 if (!strcmp(ext
, *tmp_ext
))
760 fn_format(tmp
, search_file
->name
, ptr
, "",
761 MY_UNPACK_FILENAME
| MY_SAFE_PATH
);
763 search_default_file_with_ext(opt_handler
, handler_ctx
, "", "", tmp
,
764 recursion_level
+ 1);
768 my_dirend(search_dir
);
770 else if ((!strncmp(ptr
, include_keyword
, sizeof(include_keyword
) - 1)) &&
771 my_isspace(&my_charset_latin1
, ptr
[sizeof(include_keyword
)-1]))
773 if (!(ptr
= get_argument(include_keyword
,
774 sizeof(include_keyword
), ptr
,
778 search_default_file_with_ext(opt_handler
, handler_ctx
, "", "", ptr
,
779 recursion_level
+ 1);
785 if (*ptr
== '[') /* Group name */
788 if (!(end
=(char *) strchr(++ptr
,']')))
791 "error: Wrong group definition in config file: %s at line %d\n",
795 /* Remove end space */
796 for ( ; my_isspace(&my_charset_latin1
,end
[-1]) ; end
--) ;
799 strmake(curr_gr
, ptr
, min((size_t) (end
-ptr
)+1, sizeof(curr_gr
)-1));
801 /* signal that a new group is found */
802 opt_handler(handler_ctx
, curr_gr
, NULL
);
809 "error: Found option without preceding group in config file: %s at line: %d\n",
815 end
= remove_end_comment(ptr
);
816 if ((value
= strchr(ptr
, '=')))
817 end
= value
; /* Option without argument */
818 for ( ; my_isspace(&my_charset_latin1
,end
[-1]) ; end
--) ;
821 strmake(strmov(option
,"--"),ptr
, (size_t) (end
-ptr
));
822 if (opt_handler(handler_ctx
, curr_gr
, option
))
827 /* Remove pre- and end space */
829 for (value
++ ; my_isspace(&my_charset_latin1
,*value
); value
++) ;
830 value_end
=strend(value
);
832 We don't have to test for value_end >= value as we know there is
835 for ( ; my_isspace(&my_charset_latin1
,value_end
[-1]) ; value_end
--) ;
836 if (value_end
< value
) /* Empty string */
839 /* remove quotes around argument */
840 if ((*value
== '\"' || *value
== '\'') && /* First char is quote */
841 (value
+ 1 < value_end
) && /* String is longer than 1 */
842 *value
== value_end
[-1] ) /* First char is equal to last char */
847 ptr
=strnmov(strmov(option
,"--"),ptr
,(size_t) (end
-ptr
));
850 for ( ; value
!= value_end
; value
++)
852 if (*value
== '\\' && value
!= value_end
-1)
868 *ptr
++= ' '; /* space */
879 default: /* Unknown; Keep '\' */
889 if (opt_handler(handler_ctx
, curr_gr
, option
))
893 my_fclose(fp
,MYF(0));
897 my_fclose(fp
,MYF(0));
898 return -1; /* Fatal error */
902 static char *remove_end_comment(char *ptr
)
904 char quote
= 0; /* we are inside quote marks */
905 char escape
= 0; /* symbol is protected by escape chagacter */
909 if ((*ptr
== '\'' || *ptr
== '\"') && !escape
)
913 else if (quote
== *ptr
)
916 /* We are not inside a string */
917 if (!quote
&& *ptr
== '#')
922 escape
= (quote
&& *ptr
== '\\' && !escape
);
927 #include <help_start.h>
929 void my_print_default_files(const char *conf_file
)
931 const char *empty_list
[]= { "", 0 };
932 my_bool have_ext
= fn_ext(conf_file
)[0] != 0;
933 const char **exts_to_use
= have_ext
? empty_list
: f_extensions
;
934 char name
[FN_REFLEN
], **ext
;
936 puts("\nDefault options are read from the following files in the given order:");
938 if (dirname_length(conf_file
))
939 fputs(conf_file
,stdout
);
944 init_alloc_root(&alloc
,512,0);
946 if ((dirs
= init_default_directories(&alloc
)) == NULL
)
948 fputs("Internal error initializing default directories list", stdout
);
952 for ( ; *dirs
; dirs
++)
954 for (ext
= (char**) exts_to_use
; *ext
; ext
++)
960 else if (my_defaults_extra_file
)
961 pos
= my_defaults_extra_file
;
964 end
= convert_dirname(name
, pos
, NullS
);
965 if (name
[0] == FN_HOMELIB
) /* Add . to filenames in home */
967 strxmov(end
, conf_file
, *ext
, " ", NullS
);
973 free_root(&alloc
, MYF(0));
978 void print_defaults(const char *conf_file
, const char **groups
)
980 const char **groups_save
= groups
;
981 my_print_default_files(conf_file
);
983 fputs("The following groups are read:",stdout
);
984 for ( ; *groups
; groups
++)
987 fputs(*groups
,stdout
);
990 if (my_defaults_group_suffix
)
993 for ( ; *groups
; groups
++)
996 fputs(*groups
,stdout
);
997 fputs(my_defaults_group_suffix
,stdout
);
1000 puts("\nThe following options may be given as the first argument:\n\
1001 --print-defaults Print the program argument list and exit.\n\
1002 --no-defaults Don't read default options from any option file.\n\
1003 --defaults-file=# Only read default options from the given file #.\n\
1004 --defaults-extra-file=# Read this file after the global files are read.");
1007 #include <help_end.h>
1010 static int add_directory(MEM_ROOT
*alloc
, const char *dir
, const char **dirs
)
1012 char buf
[FN_REFLEN
];
1015 my_bool err
__attribute__((unused
));
1017 len
= normalize_dirname(buf
, dir
);
1018 if (!(p
= strmake_root(alloc
, buf
, len
)))
1019 return 1; /* Failure */
1020 /* Should never fail if DEFAULT_DIRS_SIZE is correct size */
1021 err
= array_append_string_unique(p
, dirs
, DEFAULT_DIRS_SIZE
);
1022 DBUG_ASSERT(err
== FALSE
);
1030 This wrapper for GetSystemWindowsDirectory() will dynamically bind to the
1031 function if it is available, emulate it on NT4 Terminal Server by stripping
1032 the \SYSTEM32 from the end of the results of GetSystemDirectory(), or just
1033 return GetSystemDirectory().
1036 typedef UINT (WINAPI
*GET_SYSTEM_WINDOWS_DIRECTORY
)(LPSTR
, UINT
);
1038 static size_t my_get_system_windows_directory(char *buffer
, size_t size
)
1041 GET_SYSTEM_WINDOWS_DIRECTORY
1042 func_ptr
= (GET_SYSTEM_WINDOWS_DIRECTORY
)
1043 GetProcAddress(GetModuleHandle("kernel32.dll"),
1044 "GetSystemWindowsDirectoryA");
1047 return func_ptr(buffer
, (uint
) size
);
1050 Windows NT 4.0 Terminal Server Edition:
1051 To retrieve the shared Windows directory, call GetSystemDirectory and
1052 trim the "System32" element from the end of the returned path.
1054 count
= GetSystemDirectory(buffer
, (uint
) size
);
1055 if (count
> 8 && stricmp(buffer
+(count
-8), "\\System32") == 0)
1058 buffer
[count
] = '\0';
1064 static const char *my_get_module_parent(char *buf
, size_t size
)
1068 if (!GetModuleFileName(NULL
, buf
, (DWORD
) size
))
1073 Look for the second-to-last \ in the filename, but hang on
1074 to a pointer after the last \ in case we're in the root of
1077 for ( ; end
> buf
; end
--)
1079 if (*end
== FN_LIBCHAR
)
1083 /* Keep the last '\' as this works both with D:\ and a directory */
1093 #endif /* __WIN__ */
1096 static const char **init_default_directories(MEM_ROOT
*alloc
)
1102 dirs
= (const char **)alloc_root(alloc
, DEFAULT_DIRS_SIZE
* sizeof(char *));
1105 bzero((char *) dirs
, DEFAULT_DIRS_SIZE
* sizeof(char *));
1110 char fname_buffer
[FN_REFLEN
];
1111 if (my_get_system_windows_directory(fname_buffer
, sizeof(fname_buffer
)))
1112 errors
+= add_directory(alloc
, fname_buffer
, dirs
);
1114 if (GetWindowsDirectory(fname_buffer
, sizeof(fname_buffer
)))
1115 errors
+= add_directory(alloc
, fname_buffer
, dirs
);
1117 errors
+= add_directory(alloc
, "C:/", dirs
);
1119 if (my_get_module_parent(fname_buffer
, sizeof(fname_buffer
)) != NULL
)
1120 errors
+= add_directory(alloc
, fname_buffer
, dirs
);
1123 #elif defined(__NETWARE__)
1125 errors
+= add_directory(alloc
, "sys:/etc/", dirs
);
1129 errors
+= add_directory(alloc
, "/etc/", dirs
);
1130 errors
+= add_directory(alloc
, "/etc/mysql/", dirs
);
1132 #if defined(DEFAULT_SYSCONFDIR)
1133 if (DEFAULT_SYSCONFDIR
[0])
1134 errors
+= add_directory(alloc
, DEFAULT_SYSCONFDIR
, dirs
);
1135 #endif /* DEFAULT_SYSCONFDIR */
1139 if ((env
= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV
))))
1140 errors
+= add_directory(alloc
, env
, dirs
);
1142 /* Placeholder for --defaults-extra-file=<path> */
1143 errors
+= add_directory(alloc
, "", dirs
);
1145 #if !defined(__WIN__) && !defined(__NETWARE__)
1146 errors
+= add_directory(alloc
, "~/", dirs
);
1149 return (errors
> 0 ? NULL
: dirs
);