1
/* Copyright (C) 2000-2003 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
/****************************************************************************
17
Add all options from files named "group".cnf from the default_directories
18
before the command line arguments.
19
On Windows defaults will also search in the Windows directory for a file
21
As long as the program uses the last argument for conflicting
22
options one only have to add a call to "load_defaults" to enable
23
use of default values.
24
pre- and end 'blank space' are removed from options and values. The
25
following escape sequences are recognized in values: \b \t \n \r \\
27
The following arguments are handled automaticly; If used, they must be
28
first argument on the command line!
29
--no-defaults ; no options are read.
30
--defaults-file=full-path-to-default-file ; Only this file will be read.
31
--defaults-extra-file=full-path-to-default-file ; Read this file before ~/
32
--defaults-group-suffix ; Also read groups with concat(group, suffix)
33
--print-defaults ; Print the modified command line and exit
34
****************************************************************************/
36
#include "mysys_priv.h"
41
const char *my_defaults_file=0;
42
const char *my_defaults_group_suffix=0;
43
char *my_defaults_extra_file=0;
45
/* Which directories are searched for options (and in which order) */
47
#define MAX_DEFAULT_DIRS 6
48
const char *default_directories[MAX_DEFAULT_DIRS + 1];
50
static const char *f_extensions[]= { ".cnf", 0 };
53
static int handle_default_option(void *in_ctx, const char *group_name,
57
This structure defines the context that we pass to callback
58
function 'handle_default_option' used in search_default_file
59
to process each option. This context is used if search_default_file
60
was called from load_defaults.
63
struct handle_option_ctx
70
static int search_default_file(Process_option_func func, void *func_ctx,
71
const char *dir, const char *config_file);
72
static int search_default_file_with_ext(Process_option_func func,
74
const char *dir, const char *ext,
75
const char *config_file, int recursion_level);
80
Create the list of default directories.
83
On all systems, if a directory is already in the list, it will be moved
84
to the end of the list. This avoids reading defaults files multiple times,
85
while ensuring the correct precedence.
90
static void (*init_default_directories)();
93
static char *remove_end_comment(char *ptr);
97
Process config files in default directories.
100
my_search_option_files()
101
conf_file Basename for configuration file to search for.
102
If this is a path, then only this file is read.
103
argc Pointer to argc of original program
104
argv Pointer to argv of original program
105
args_used Pointer to variable for storing the number of
107
func Pointer to the function to process options
108
func_ctx It's context. Usually it is the structure to
109
store additional options.
111
Process the default options from argc & argv
112
Read through each found config file looks and calls 'func' to process
116
--defaults-group-suffix is only processed if we are called from
122
1 given cinf_file doesn't exist
124
The global variable 'my_defaults_group_suffix' is updated with value for
125
--defaults_group_suffix
128
int my_search_option_files(const char *conf_file, int *argc, char ***argv,
129
uint *args_used, Process_option_func func,
132
const char **dirs, *forced_default_file, *forced_extra_defaults;
134
DBUG_ENTER("my_search_option_files");
136
/* Check if we want to force the use a specific default file */
137
*args_used+= get_defaults_options(*argc - *args_used, *argv + *args_used,
138
(char **) &forced_default_file,
139
(char **) &forced_extra_defaults,
140
(char **) &my_defaults_group_suffix);
142
if (! my_defaults_group_suffix)
143
my_defaults_group_suffix= getenv(STRINGIFY_ARG(DEFAULT_GROUP_SUFFIX_ENV));
145
if (forced_extra_defaults)
146
my_defaults_extra_file= (char *) forced_extra_defaults;
148
if (forced_default_file)
149
my_defaults_file= forced_default_file;
152
We can only handle 'defaults-group-suffix' if we are called from
153
load_defaults() as otherwise we can't know the type of 'func_ctx'
156
if (my_defaults_group_suffix && func == handle_default_option)
158
/* Handle --defaults-group-suffix= */
160
const char **extra_groups;
161
const uint instance_len= strlen(my_defaults_group_suffix);
162
struct handle_option_ctx *ctx= (struct handle_option_ctx*) func_ctx;
164
TYPELIB *group= ctx->group;
167
(const char**)alloc_root(ctx->alloc,
168
(2*group->count+1)*sizeof(char*))))
171
for (i= 0; i < group->count; i++)
174
extra_groups[i]= group->type_names[i]; /** copy group */
176
len= strlen(extra_groups[i]);
177
if (!(ptr= alloc_root(ctx->alloc, len+instance_len+1)))
180
extra_groups[i+group->count]= ptr;
182
/** Construct new group */
183
memcpy(ptr, extra_groups[i], len);
184
memcpy(ptr+len, my_defaults_group_suffix, instance_len+1);
188
group->type_names= extra_groups;
189
group->type_names[group->count]= 0;
192
if (forced_default_file)
194
if ((error= search_default_file_with_ext(func, func_ctx, "", "",
195
forced_default_file, 0)) < 0)
199
fprintf(stderr, "Could not open required defaults file: %s\n",
200
forced_default_file);
204
else if (dirname_length(conf_file))
206
if ((error= search_default_file(func, func_ctx, NullS, conf_file)) < 0)
211
for (dirs= default_directories ; *dirs; dirs++)
215
if (search_default_file(func, func_ctx, *dirs, conf_file) < 0)
218
else if (my_defaults_extra_file)
220
if ((error= search_default_file_with_ext(func, func_ctx, "", "",
221
my_defaults_extra_file, 0)) < 0)
222
goto err; /* Fatal error */
225
fprintf(stderr, "Could not open required defaults file: %s\n",
226
my_defaults_extra_file);
236
fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
238
return 0; /* Keep compiler happy */
243
The option handler for load_defaults.
246
handle_deault_option()
247
in_ctx Handler context. In this case it is a
248
handle_option_ctx structure.
249
group_name The name of the group the option belongs to.
250
option The very option to be processed. It is already
251
prepared to be used in argv (has -- prefix). If it
252
is NULL, we are handling a new group (section).
255
This handler checks whether a group is one of the listed and adds an option
256
to the array if yes. Some other handler can record, for instance, all
257
groups and their options, not knowing in advance the names and amount of
265
static int handle_default_option(void *in_ctx, const char *group_name,
269
struct handle_option_ctx *ctx= (struct handle_option_ctx *) in_ctx;
274
if (find_type((char *)group_name, ctx->group, 3))
276
if (!(tmp= alloc_root(ctx->alloc, strlen(option) + 1)))
278
if (insert_dynamic(ctx->args, (uchar*) &tmp))
288
Gets options from the command line
291
get_defaults_options()
292
argc Pointer to argc of original program
293
argv Pointer to argv of original program
294
defaults --defaults-file option
295
extra_defaults --defaults-extra-file option
298
# Number of arguments used from *argv
299
defaults and extra_defaults will be set to option of the appropriate
300
items of argv array, or to NULL if there are no such options
303
int get_defaults_options(int argc, char **argv,
305
char **extra_defaults,
308
int org_argc= argc, prev_argc= 0;
309
*defaults= *extra_defaults= *group_suffix= 0;
311
while (argc >= 2 && argc != prev_argc)
313
/* Skip program name or previously handled argument */
315
prev_argc= argc; /* To check if we found */
316
if (!*defaults && is_prefix(*argv,"--defaults-file="))
318
*defaults= *argv + sizeof("--defaults-file=")-1;
322
if (!*extra_defaults && is_prefix(*argv,"--defaults-extra-file="))
324
*extra_defaults= *argv + sizeof("--defaults-extra-file=")-1;
328
if (!*group_suffix && is_prefix(*argv, "--defaults-group-suffix="))
330
*group_suffix= *argv + sizeof("--defaults-group-suffix=")-1;
335
return org_argc - argc;
340
Read options from configurations files
344
conf_file Basename for configuration file to search for.
345
If this is a path, then only this file is read.
346
groups Which [group] entrys to read.
347
Points to an null terminated array of pointers
348
argc Pointer to argc of original program
349
argv Pointer to argv of original program
353
Read options from configuration files and put them BEFORE the arguments
354
that are already in argc and argv. This way the calling program can
355
easily command line options override options in configuration files
358
In case of fatal error, the function will print a warning and do
361
To free used memory one should call free_defaults() with the argument
362
that was put in *argv
366
1 The given conf_file didn't exists
370
int load_defaults(const char *conf_file, const char **groups,
371
int *argc, char ***argv)
375
my_bool found_print_defaults= 0;
380
struct handle_option_ctx ctx;
381
DBUG_ENTER("load_defaults");
383
init_default_directories();
384
init_alloc_root(&alloc,512,0);
386
Check if the user doesn't want any default option processing
387
--no-defaults is always the first option
389
if (*argc >= 2 && !strcmp(argv[0][1],"--no-defaults"))
391
/* remove the --no-defaults argument and return only the other arguments */
393
if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
394
(*argc + 1)*sizeof(char*))))
396
res= (char**) (ptr+sizeof(alloc));
397
res[0]= **argv; /* Copy program name */
398
for (i=2 ; i < (uint) *argc ; i++)
400
res[i-1]=0; /* End pointer */
403
*(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */
408
group.name= "defaults";
409
group.type_names= groups;
411
for (; *groups ; groups++)
414
if (my_init_dynamic_array(&args, sizeof(char*),*argc, 32))
421
error= my_search_option_files(conf_file, argc, argv, &args_used,
422
handle_default_option, (void *) &ctx);
424
Here error contains <> 0 only if we have a fully specified conf_file
425
or a forced default file
427
if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
428
(args.elements + *argc +1) *sizeof(char*))))
430
res= (char**) (ptr+sizeof(alloc));
432
/* copy name + found arguments + command line arguments to new array */
433
res[0]= argv[0][0]; /* Name MUST be set, even by embedded library */
434
memcpy((uchar*) (res+1), args.buffer, args.elements*sizeof(char*));
435
/* Skip --defaults-xxx options */
440
Check if we wan't to see the new argument list
441
This options must always be the last of the default options
443
if (*argc >= 2 && !strcmp(argv[0][1],"--print-defaults"))
445
found_print_defaults=1;
446
--*argc; ++*argv; /* skip argument */
450
memcpy((uchar*) (res+1+args.elements), (char*) ((*argv)+1),
451
(*argc-1)*sizeof(char*));
452
res[args.elements+ *argc]=0; /* last null */
454
(*argc)+=args.elements;
456
*(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */
457
delete_dynamic(&args);
458
if (found_print_defaults)
461
printf("%s would have been started with the following arguments:\n",
463
for (i=1 ; i < *argc ; i++)
464
printf("%s ", (*argv)[i]);
471
fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
473
return 0; /* Keep compiler happy */
477
void free_defaults(char **argv)
480
memcpy_fixed((char*) &ptr,(char *) argv - sizeof(ptr), sizeof(ptr));
481
free_root(&ptr,MYF(0));
485
static int search_default_file(Process_option_func opt_handler,
488
const char *config_file)
491
const char *empty_list[]= { "", 0 };
492
my_bool have_ext= fn_ext(config_file)[0] != 0;
493
const char **exts_to_use= have_ext ? empty_list : f_extensions;
495
for (ext= (char**) exts_to_use; *ext; ext++)
498
if ((error= search_default_file_with_ext(opt_handler, handler_ctx,
500
config_file, 0)) < 0)
508
Skip over keyword and get argument after keyword
512
keyword Include directive keyword
513
kwlen Length of keyword
514
ptr Pointer to the keword in the line under process
519
# Returns pointer to the argument after the keyword.
522
static char *get_argument(const char *keyword, size_t kwlen,
523
char *ptr, char *name, uint line)
527
/* Skip over "include / includedir keyword" and following whitespace */
529
for (ptr+= kwlen - 1;
530
my_isspace(&my_charset_latin1, ptr[0]);
535
Trim trailing whitespace from directory name
536
The -1 below is for the newline added by fgets()
537
Note that my_isspace() is true for \r and \n
539
for (end= ptr + strlen(ptr) - 1;
540
my_isspace(&my_charset_latin1, *(end - 1));
543
end[0]= 0; /* Cut off end space */
545
/* Print error msg if there is nothing after !include* directive */
549
"error: Wrong '!%s' directive in config file: %s at line %d\n",
550
keyword, name, line);
558
Open a configuration file (if exists) and read given options from it
561
search_default_file_with_ext()
562
opt_handler Option handler function. It is used to process
563
every separate option.
564
handler_ctx Pointer to the structure to store actual
565
parameters of the function.
566
dir directory to read
567
ext Extension for configuration file
568
config_file Name of configuration file
570
recursion_level the level of recursion, got while processing
571
"!include" or "!includedir"
575
-1 Fatal error, abort
576
1 File not found (Warning)
579
static int search_default_file_with_ext(Process_option_func opt_handler,
583
const char *config_file,
586
char name[FN_REFLEN + 10], buff[4096], curr_gr[4096], *ptr, *end, **tmp_ext;
587
char *value, option[4096], tmp[FN_REFLEN];
588
static const char includedir_keyword[]= "includedir";
589
static const char include_keyword[]= "include";
590
const int max_recursion_level= 10;
593
my_bool found_group=0;
596
FILEINFO *search_file;
598
if ((dir ? strlen(dir) : 0 )+strlen(config_file) >= FN_REFLEN-3)
599
return 0; /* Ignore wrong paths */
602
end=convert_dirname(name, dir, NullS);
603
if (dir[0] == FN_HOMELIB) /* Add . to filenames in home */
605
strxmov(end,config_file,ext,NullS);
609
strmov(name,config_file);
611
fn_format(name,name,"","",4);
614
if (!my_stat(name,&stat_info,MYF(0)))
617
Ignore world-writable regular files.
618
This is mainly done to protect us to not read a file created by
619
the mysqld server, but the check is still valid in most context.
621
if ((stat_info.st_mode & S_IWOTH) &&
622
(stat_info.st_mode & S_IFMT) == S_IFREG)
624
fprintf(stderr, "Warning: World-writable config file '%s' is ignored\n",
629
if (!(fp= my_fopen(name, O_RDONLY, MYF(0))))
630
return 1; /* Ignore wrong files */
632
while (fgets(buff, sizeof(buff) - 1, fp))
635
/* Ignore comment and empty lines */
636
for (ptr= buff; my_isspace(&my_charset_latin1, *ptr); ptr++)
639
if (*ptr == '#' || *ptr == ';' || !*ptr)
642
/* Configuration File Directives */
645
if (recursion_level >= max_recursion_level)
647
for (end= ptr + strlen(ptr) - 1;
648
my_isspace(&my_charset_latin1, *(end - 1));
653
"Warning: skipping '%s' directive as maximum include"
654
"recursion level was reached in file %s at line %d\n",
659
/* skip over `!' and following whitespace */
660
for (++ptr; my_isspace(&my_charset_latin1, ptr[0]); ptr++)
663
if ((!strncmp(ptr, includedir_keyword,
664
sizeof(includedir_keyword) - 1)) &&
665
my_isspace(&my_charset_latin1, ptr[sizeof(includedir_keyword) - 1]))
667
if (!(ptr= get_argument(includedir_keyword,
668
sizeof(includedir_keyword),
672
if (!(search_dir= my_dir(ptr, MYF(MY_WME))))
675
for (i= 0; i < (uint) search_dir->number_off_files; i++)
677
search_file= search_dir->dir_entry + i;
678
ext= fn_ext(search_file->name);
680
/* check extension */
681
for (tmp_ext= (char**) f_extensions; *tmp_ext; tmp_ext++)
683
if (!strcmp(ext, *tmp_ext))
689
fn_format(tmp, search_file->name, ptr, "",
690
MY_UNPACK_FILENAME | MY_SAFE_PATH);
692
search_default_file_with_ext(opt_handler, handler_ctx, "", "", tmp,
693
recursion_level + 1);
697
my_dirend(search_dir);
699
else if ((!strncmp(ptr, include_keyword, sizeof(include_keyword) - 1)) &&
700
my_isspace(&my_charset_latin1, ptr[sizeof(include_keyword)-1]))
702
if (!(ptr= get_argument(include_keyword,
703
sizeof(include_keyword), ptr,
707
search_default_file_with_ext(opt_handler, handler_ctx, "", "", ptr,
708
recursion_level + 1);
714
if (*ptr == '[') /* Group name */
717
if (!(end=(char *) strchr(++ptr,']')))
720
"error: Wrong group definition in config file: %s at line %d\n",
724
/* Remove end space */
725
for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;
728
strmake(curr_gr, ptr, min((size_t) (end-ptr)+1, sizeof(curr_gr)-1));
730
/* signal that a new group is found */
731
opt_handler(handler_ctx, curr_gr, NULL);
738
"error: Found option without preceding group in config file: %s at line: %d\n",
744
end= remove_end_comment(ptr);
745
if ((value= strchr(ptr, '=')))
746
end= value; /* Option without argument */
747
for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;
750
strmake(strmov(option,"--"),ptr, (size_t) (end-ptr));
751
if (opt_handler(handler_ctx, curr_gr, option))
756
/* Remove pre- and end space */
758
for (value++ ; my_isspace(&my_charset_latin1,*value); value++) ;
759
value_end=strend(value);
761
We don't have to test for value_end >= value as we know there is
764
for ( ; my_isspace(&my_charset_latin1,value_end[-1]) ; value_end--) ;
765
if (value_end < value) /* Empty string */
768
/* remove quotes around argument */
769
if ((*value == '\"' || *value == '\'') && /* First char is quote */
770
(value + 1 < value_end ) && /* String is longer than 1 */
771
*value == value_end[-1] ) /* First char is equal to last char */
776
ptr=strnmov(strmov(option,"--"),ptr,(size_t) (end-ptr));
779
for ( ; value != value_end; value++)
781
if (*value == '\\' && value != value_end-1)
797
*ptr++= ' '; /* space */
808
default: /* Unknown; Keep '\' */
818
if (opt_handler(handler_ctx, curr_gr, option))
822
my_fclose(fp,MYF(0));
826
my_fclose(fp,MYF(0));
827
return -1; /* Fatal error */
831
static char *remove_end_comment(char *ptr)
833
char quote= 0; /* we are inside quote marks */
834
char escape= 0; /* symbol is protected by escape chagacter */
838
if ((*ptr == '\'' || *ptr == '\"') && !escape)
842
else if (quote == *ptr)
845
/* We are not inside a string */
846
if (!quote && *ptr == '#')
851
escape= (quote && *ptr == '\\' && !escape);
856
#include <help_start.h>
858
void my_print_default_files(const char *conf_file)
860
const char *empty_list[]= { "", 0 };
861
my_bool have_ext= fn_ext(conf_file)[0] != 0;
862
const char **exts_to_use= have_ext ? empty_list : f_extensions;
863
char name[FN_REFLEN], **ext;
866
init_default_directories();
867
puts("\nDefault options are read from the following files in the given order:");
869
if (dirname_length(conf_file))
870
fputs(conf_file,stdout);
873
for (dirs=default_directories ; *dirs; dirs++)
875
for (ext= (char**) exts_to_use; *ext; ext++)
881
else if (my_defaults_extra_file)
882
pos= my_defaults_extra_file;
885
end= convert_dirname(name, pos, NullS);
886
if (name[0] == FN_HOMELIB) /* Add . to filenames in home */
888
strxmov(end, conf_file, *ext, " ", NullS);
896
void print_defaults(const char *conf_file, const char **groups)
898
const char **groups_save= groups;
899
my_print_default_files(conf_file);
901
fputs("The following groups are read:",stdout);
902
for ( ; *groups ; groups++)
905
fputs(*groups,stdout);
908
if (my_defaults_group_suffix)
911
for ( ; *groups ; groups++)
914
fputs(*groups,stdout);
915
fputs(my_defaults_group_suffix,stdout);
918
puts("\nThe following options may be given as the first argument:\n\
919
--print-defaults Print the program argument list and exit\n\
920
--no-defaults Don't read default options from any options file\n\
921
--defaults-file=# Only read default options from the given file #\n\
922
--defaults-extra-file=# Read this file after the global files are read");
925
#include <help_end.h>
929
This extra complexity is to avoid declaring 'rc' if it won't be
932
#define ADD_DIRECTORY_INTERNAL(DIR) \
933
array_append_string_unique((DIR), default_directories, \
934
array_elements(default_directories))
936
# define ADD_DIRECTORY(DIR) (void) ADD_DIRECTORY_INTERNAL(DIR)
938
#define ADD_DIRECTORY(DIR) \
940
my_bool rc= ADD_DIRECTORY_INTERNAL(DIR); \
941
DBUG_ASSERT(rc == FALSE); /* Success */ \
946
#define ADD_COMMON_DIRECTORIES() \
949
if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV)))) \
950
ADD_DIRECTORY(env); \
951
/* Placeholder for --defaults-extra-file=<path> */ \
957
Initialize default directories for Unix
962
3. --sysconfdir=<path> (compile-time option)
963
4. getenv(DEFAULT_HOME_ENV)
964
5. --defaults-extra-file=<path> (run-time option)
968
static void init_default_directories_unix()
970
bzero((char *) default_directories, sizeof(default_directories));
971
ADD_DIRECTORY("/etc/");
972
ADD_DIRECTORY("/etc/mysql/");
973
#ifdef DEFAULT_SYSCONFDIR
974
if (DEFAULT_SYSCONFDIR != "")
975
ADD_DIRECTORY(DEFAULT_SYSCONFDIR);
977
ADD_COMMON_DIRECTORIES();
981
static void (*init_default_directories)()= init_default_directories_unix;