mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / mysys / default.c
blob1c0f997520a2a4f422376de9a9e3ecc8998597a1
1 /*
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
23 called 'group'.ini
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"
40 #include "m_string.h"
41 #include "m_ctype.h"
42 #include <my_dir.h>
43 #ifdef __WIN__
44 #include <winbase.h>
45 #endif
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;
57 #ifdef __WIN__
58 static const char *f_extensions[]= { ".ini", ".cnf", 0 };
59 #define NEWLINE "\r\n"
60 #else
61 static const char *f_extensions[]= { ".cnf", 0 };
62 #define NEWLINE "\n"
63 #endif
65 static int handle_default_option(void *in_ctx, const char *group_name,
66 const char *option);
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
77 MEM_ROOT *alloc;
78 DYNAMIC_ARRAY *args;
79 TYPELIB *group;
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,
85 void *func_ctx,
86 const char *dir, const char *ext,
87 const char *config_file, int recursion_level);
90 /**
91 Create the list of default directories.
93 @param alloc MEM_ROOT where the list of directories is stored
95 @details
96 The directories searched, in order, are:
97 - Windows: GetSystemWindowsDirectory()
98 - Windows: GetWindowsDirectory()
99 - Windows: C:/
100 - Windows: Directory above where the executable is located
101 - Netware: sys:/etc/
102 - Unix: /etc/
103 - Unix: /etc/mysql/
104 - Unix: --sysconfdir=<path> (compile-time option)
105 - ALL: getenv(DEFAULT_HOME_ENV)
106 - ALL: --defaults-extra-file=<path> (run-time option)
107 - Unix: ~/
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.
126 SYNOPSIS
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
133 arguments used.
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.
137 DESCRIPTION
138 Process the default options from argc & argv
139 Read through each found config file looks and calls 'func' to process
140 each option.
142 NOTES
143 --defaults-group-suffix is only processed if we are called from
144 load_defaults().
147 RETURN
148 0 ok
149 1 given cinf_file doesn't exist
150 2 out of memory
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;
161 int error= 0;
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= */
187 uint i;
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;
191 char *ptr;
192 TYPELIB *group= ctx->group;
194 if (!(extra_groups=
195 (const char**)alloc_root(ctx->alloc,
196 (2*group->count+1)*sizeof(char*))))
197 DBUG_RETURN(2);
199 for (i= 0; i < group->count; i++)
201 size_t len;
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))))
206 DBUG_RETURN(2);
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);
215 group->count*= 2;
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)
224 goto err;
225 if (error > 0)
227 fprintf(stderr, "Could not open required defaults file: %s\n",
228 forced_default_file);
229 goto err;
232 else if (dirname_length(conf_file))
234 if ((error= search_default_file(func, func_ctx, NullS, conf_file)) < 0)
235 goto err;
237 else
239 for (dirs= default_directories ; *dirs; dirs++)
241 if (**dirs)
243 if (search_default_file(func, func_ctx, *dirs, conf_file) < 0)
244 goto err;
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 */
251 if (error > 0)
253 fprintf(stderr, "Could not open required defaults file: %s\n",
254 my_defaults_extra_file);
255 goto err;
261 DBUG_RETURN(0);
263 err:
264 fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
265 DBUG_RETURN(1);
270 The option handler for load_defaults.
272 SYNOPSIS
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).
281 DESCRIPTION
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
285 groups.
287 RETURN
288 0 - ok
289 1 - error occured
292 static int handle_default_option(void *in_ctx, const char *group_name,
293 const char *option)
295 char *tmp;
296 struct handle_option_ctx *ctx= (struct handle_option_ctx *) in_ctx;
298 if (!option)
299 return 0;
301 if (find_type((char *)group_name, ctx->group, 3))
303 if (!(tmp= alloc_root(ctx->alloc, strlen(option) + 1)))
304 return 1;
305 if (insert_dynamic(ctx->args, (uchar*) &tmp))
306 return 1;
307 strmov(tmp, option);
310 return 0;
315 Gets options from the command line
317 SYNOPSIS
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
324 RETURN
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,
331 char **defaults,
332 char **extra_defaults,
333 char **group_suffix)
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 */
341 argv++;
342 prev_argc= argc; /* To check if we found */
343 if (!*defaults && is_prefix(*argv,"--defaults-file="))
345 *defaults= *argv + sizeof("--defaults-file=")-1;
346 argc--;
347 continue;
349 if (!*extra_defaults && is_prefix(*argv,"--defaults-extra-file="))
351 *extra_defaults= *argv + sizeof("--defaults-extra-file=")-1;
352 argc--;
353 continue;
355 if (!*group_suffix && is_prefix(*argv, "--defaults-group-suffix="))
357 *group_suffix= *argv + sizeof("--defaults-group-suffix=")-1;
358 argc--;
359 continue;
362 return org_argc - argc;
366 Wrapper around my_load_defaults() for interface compatibility.
368 SYNOPSIS
369 load_defaults()
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
377 NOTES
379 This function is NOT thread-safe as it uses a global pointer internally.
380 See also notes for my_load_defaults().
382 RETURN
383 0 ok
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
395 SYNOPSIS
396 my_load_defaults()
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
406 IMPLEMENTATION
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
412 NOTES
413 In case of fatal error, the function will print a warning and do
414 exit(1)
416 To free used memory one should call free_defaults() with the argument
417 that was put in *argv
419 RETURN
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()
423 later.
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)
433 DYNAMIC_ARRAY args;
434 TYPELIB group;
435 my_bool found_print_defaults= 0;
436 uint args_used= 0;
437 int error= 0;
438 MEM_ROOT alloc;
439 char *ptr,**res;
440 struct handle_option_ctx ctx;
441 const char **dirs;
442 DBUG_ENTER("load_defaults");
444 init_alloc_root(&alloc,512,0);
445 if ((dirs= init_default_directories(&alloc)) == NULL)
446 goto err;
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 */
454 uint i;
455 if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
456 (*argc + 1)*sizeof(char*))))
457 goto err;
458 res= (char**) (ptr+sizeof(alloc));
459 res[0]= **argv; /* Copy program name */
460 for (i=2 ; i < (uint) *argc ; i++)
461 res[i-1]=argv[0][i];
462 res[i-1]=0; /* End pointer */
463 (*argc)--;
464 *argv=res;
465 *(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */
466 if (default_directories)
467 *default_directories= dirs;
468 DBUG_RETURN(0);
471 group.count=0;
472 group.name= "defaults";
473 group.type_names= groups;
475 for (; *groups ; groups++)
476 group.count++;
478 if (my_init_dynamic_array(&args, sizeof(char*),*argc, 32))
479 goto err;
481 ctx.alloc= &alloc;
482 ctx.args= &args;
483 ctx.group= &group;
485 error= my_search_option_files(conf_file, argc, argv, &args_used,
486 handle_default_option, (void *) &ctx,
487 dirs);
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*))))
494 goto err;
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 */
501 (*argc)-= args_used;
502 (*argv)+= args_used;
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 */
514 if (*argc)
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;
520 *argv= (char**) res;
521 *(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */
522 delete_dynamic(&args);
523 if (found_print_defaults)
525 int i;
526 printf("%s would have been started with the following arguments:\n",
527 **argv);
528 for (i=1 ; i < *argc ; i++)
529 printf("%s ", (*argv)[i]);
530 puts("");
531 exit(0);
534 if (error == 0 && default_directories)
535 *default_directories= dirs;
537 DBUG_RETURN(error);
539 err:
540 fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
541 exit(1);
542 return 0; /* Keep compiler happy */
546 void free_defaults(char **argv)
548 MEM_ROOT ptr;
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,
555 void *handler_ctx,
556 const char *dir,
557 const char *config_file)
559 char **ext;
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++)
566 int error;
567 if ((error= search_default_file_with_ext(opt_handler, handler_ctx,
568 dir, *ext,
569 config_file, 0)) < 0)
570 return error;
572 return 0;
577 Skip over keyword and get argument after keyword
579 SYNOPSIS
580 get_argument()
581 keyword Include directive keyword
582 kwlen Length of keyword
583 ptr Pointer to the keword in the line under process
584 line line number
586 RETURN
587 0 error
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)
594 char *end;
596 /* Skip over "include / includedir keyword" and following whitespace */
598 for (ptr+= kwlen - 1;
599 my_isspace(&my_charset_latin1, ptr[0]);
600 ptr++)
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));
610 end--)
612 end[0]= 0; /* Cut off end space */
614 /* Print error msg if there is nothing after !include* directive */
615 if (end <= ptr)
617 fprintf(stderr,
618 "error: Wrong '!%s' directive in config file: %s at line %d\n",
619 keyword, name, line);
620 return 0;
622 return ptr;
627 Open a configuration file (if exists) and read given options from it
629 SYNOPSIS
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
638 group groups to read
639 recursion_level the level of recursion, got while processing
640 "!include" or "!includedir"
642 RETURN
643 0 Success
644 -1 Fatal error, abort
645 1 File not found (Warning)
648 static int search_default_file_with_ext(Process_option_func opt_handler,
649 void *handler_ctx,
650 const char *dir,
651 const char *ext,
652 const char *config_file,
653 int recursion_level)
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;
660 FILE *fp;
661 uint line=0;
662 my_bool found_group=0;
663 uint i;
664 MY_DIR *search_dir;
665 FILEINFO *search_file;
667 if ((dir ? strlen(dir) : 0 )+strlen(config_file) >= FN_REFLEN-3)
668 return 0; /* Ignore wrong paths */
669 if (dir)
671 end=convert_dirname(name, dir, NullS);
672 if (dir[0] == FN_HOMELIB) /* Add . to filenames in home */
673 *end++='.';
674 strxmov(end,config_file,ext,NullS);
676 else
678 strmov(name,config_file);
680 fn_format(name,name,"","",4);
681 #if !defined(__WIN__) && !defined(__NETWARE__)
683 MY_STAT stat_info;
684 if (!my_stat(name,&stat_info,MYF(0)))
685 return 1;
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",
695 name);
696 return 0;
699 #endif
700 if (!(fp= my_fopen(name, O_RDONLY, MYF(0))))
701 return 1; /* Ignore wrong files */
703 while (fgets(buff, sizeof(buff) - 1, fp))
705 line++;
706 /* Ignore comment and empty lines */
707 for (ptr= buff; my_isspace(&my_charset_latin1, *ptr); ptr++)
710 if (*ptr == '#' || *ptr == ';' || !*ptr)
711 continue;
713 /* Configuration File Directives */
714 if ((*ptr == '!'))
716 if (recursion_level >= max_recursion_level)
718 for (end= ptr + strlen(ptr) - 1;
719 my_isspace(&my_charset_latin1, *(end - 1));
720 end--)
722 end[0]= 0;
723 fprintf(stderr,
724 "Warning: skipping '%s' directive as maximum include"
725 "recursion level was reached in file %s at line %d\n",
726 ptr, name, line);
727 continue;
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),
740 ptr, name, line)))
741 goto err;
743 if (!(search_dir= my_dir(ptr, MYF(MY_WME))))
744 goto err;
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))
755 break;
758 if (*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,
775 name, line)))
776 goto err;
778 search_default_file_with_ext(opt_handler, handler_ctx, "", "", ptr,
779 recursion_level + 1);
782 continue;
785 if (*ptr == '[') /* Group name */
787 found_group=1;
788 if (!(end=(char *) strchr(++ptr,']')))
790 fprintf(stderr,
791 "error: Wrong group definition in config file: %s at line %d\n",
792 name,line);
793 goto err;
795 /* Remove end space */
796 for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;
797 end[0]=0;
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);
804 continue;
806 if (!found_group)
808 fprintf(stderr,
809 "error: Found option without preceding group in config file: %s at line: %d\n",
810 name,line);
811 goto err;
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--) ;
819 if (!value)
821 strmake(strmov(option,"--"),ptr, (size_t) (end-ptr));
822 if (opt_handler(handler_ctx, curr_gr, option))
823 goto err;
825 else
827 /* Remove pre- and end space */
828 char *value_end;
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
833 an '=' before
835 for ( ; my_isspace(&my_charset_latin1,value_end[-1]) ; value_end--) ;
836 if (value_end < value) /* Empty string */
837 value_end=value;
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 */
844 value++;
845 value_end--;
847 ptr=strnmov(strmov(option,"--"),ptr,(size_t) (end-ptr));
848 *ptr++= '=';
850 for ( ; value != value_end; value++)
852 if (*value == '\\' && value != value_end-1)
854 switch(*++value) {
855 case 'n':
856 *ptr++='\n';
857 break;
858 case 't':
859 *ptr++= '\t';
860 break;
861 case 'r':
862 *ptr++ = '\r';
863 break;
864 case 'b':
865 *ptr++ = '\b';
866 break;
867 case 's':
868 *ptr++= ' '; /* space */
869 break;
870 case '\"':
871 *ptr++= '\"';
872 break;
873 case '\'':
874 *ptr++= '\'';
875 break;
876 case '\\':
877 *ptr++= '\\';
878 break;
879 default: /* Unknown; Keep '\' */
880 *ptr++= '\\';
881 *ptr++= *value;
882 break;
885 else
886 *ptr++= *value;
888 *ptr=0;
889 if (opt_handler(handler_ctx, curr_gr, option))
890 goto err;
893 my_fclose(fp,MYF(0));
894 return(0);
896 err:
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 */
907 for (; *ptr; ptr++)
909 if ((*ptr == '\'' || *ptr == '\"') && !escape)
911 if (!quote)
912 quote= *ptr;
913 else if (quote == *ptr)
914 quote= 0;
916 /* We are not inside a string */
917 if (!quote && *ptr == '#')
919 *ptr= 0;
920 return ptr;
922 escape= (quote && *ptr == '\\' && !escape);
924 return ptr;
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);
940 else
942 const char **dirs;
943 MEM_ROOT alloc;
944 init_alloc_root(&alloc,512,0);
946 if ((dirs= init_default_directories(&alloc)) == NULL)
948 fputs("Internal error initializing default directories list", stdout);
950 else
952 for ( ; *dirs; dirs++)
954 for (ext= (char**) exts_to_use; *ext; ext++)
956 const char *pos;
957 char *end;
958 if (**dirs)
959 pos= *dirs;
960 else if (my_defaults_extra_file)
961 pos= my_defaults_extra_file;
962 else
963 continue;
964 end= convert_dirname(name, pos, NullS);
965 if (name[0] == FN_HOMELIB) /* Add . to filenames in home */
966 *end++= '.';
967 strxmov(end, conf_file, *ext, " ", NullS);
968 fputs(name, stdout);
973 free_root(&alloc, MYF(0));
975 puts("");
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++)
986 fputc(' ',stdout);
987 fputs(*groups,stdout);
990 if (my_defaults_group_suffix)
992 groups= groups_save;
993 for ( ; *groups ; groups++)
995 fputc(' ',stdout);
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];
1013 size_t len;
1014 char *p;
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);
1024 return 0;
1028 #ifdef __WIN__
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)
1040 size_t count;
1041 GET_SYSTEM_WINDOWS_DIRECTORY
1042 func_ptr= (GET_SYSTEM_WINDOWS_DIRECTORY)
1043 GetProcAddress(GetModuleHandle("kernel32.dll"),
1044 "GetSystemWindowsDirectoryA");
1046 if (func_ptr)
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)
1057 count-= 8;
1058 buffer[count] = '\0';
1060 return count;
1064 static const char *my_get_module_parent(char *buf, size_t size)
1066 char *last= NULL;
1067 char *end;
1068 if (!GetModuleFileName(NULL, buf, (DWORD) size))
1069 return NULL;
1070 end= strend(buf);
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
1075 a drive.
1077 for ( ; end > buf; end--)
1079 if (*end == FN_LIBCHAR)
1081 if (last)
1083 /* Keep the last '\' as this works both with D:\ and a directory */
1084 end[1]= 0;
1085 break;
1087 last= end;
1091 return buf;
1093 #endif /* __WIN__ */
1096 static const char **init_default_directories(MEM_ROOT *alloc)
1098 const char **dirs;
1099 char *env;
1100 int errors= 0;
1102 dirs= (const char **)alloc_root(alloc, DEFAULT_DIRS_SIZE * sizeof(char *));
1103 if (dirs == NULL)
1104 return NULL;
1105 bzero((char *) dirs, DEFAULT_DIRS_SIZE * sizeof(char *));
1107 #ifdef __WIN__
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);
1127 #else
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 */
1137 #endif
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);
1147 #endif
1149 return (errors > 0 ? NULL : dirs);