MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
my_default.cc
1 /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
2 
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.
6 
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.
11 
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
15 
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
20  called 'group'.ini
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 \\
26 
27  The following arguments are handled automatically; If used, they must be
28  first argument on the command line!
29  --no-defaults ; no options are read, except for the ones provided in the
30  login file.
31  --defaults-file=full-path-to-default-file ; Only this file will be read.
32  --defaults-extra-file=full-path-to-default-file ; Read this file before ~/
33  --defaults-group-suffix ; Also read groups with concat(group, suffix)
34  --print-defaults ; Print the modified command line and exit
35  --login-path=login-path-name ; Read options under login-path-name from
36  the login file.
37 ****************************************************************************/
38 
39 #include "../mysys/mysys_priv.h"
40 #include "my_default.h"
41 #include "my_default_priv.h"
42 #include "m_string.h"
43 #include "m_ctype.h"
44 #include <my_dir.h>
45 #include <my_aes.h>
46 #ifdef __WIN__
47 #include <winbase.h>
48 #endif
49 
50 C_MODE_START
51 #ifdef HAVE_PSI_INTERFACE
52 extern PSI_file_key key_file_cnf;
53 #endif
54 C_MODE_END
55 
82 static const char *args_separator= "----args-separator----";
83 inline static void set_args_separator(char** arg)
84 {
85  DBUG_ASSERT(my_getopt_use_args_separator);
86  *arg= (char*)args_separator;
87 }
88 
89 /*
90  This flag indicates that the argument separator string
91  (args_separator) should be added to the list of arguments,
92  in order to separate arguments received from config file
93  and command line.
94 */
95 my_bool my_getopt_use_args_separator= FALSE;
96 my_bool my_getopt_is_args_separator(const char* arg)
97 {
98  return (arg == args_separator);
99 }
100 const char *my_defaults_file=0;
101 const char *my_defaults_group_suffix=0;
102 const char *my_defaults_extra_file=0;
103 
104 static const char *my_login_path= 0;
105 
106 static char my_defaults_file_buffer[FN_REFLEN];
107 static char my_defaults_extra_file_buffer[FN_REFLEN];
108 
109 static char my_login_file[FN_REFLEN];
110 static char my_key[LOGIN_KEY_LEN];
111 
112 static my_bool defaults_already_read= FALSE;
113 
114 /* Set to TRUE, if --no-defaults is found. */
115 static my_bool found_no_defaults= FALSE;
116 
117 /* Set to TRUE, when login file is being processed. */
118 static my_bool is_login_file= FALSE;
119 
120 /* Which directories are searched for options (and in which order) */
121 
122 #define MAX_DEFAULT_DIRS 6
123 #define DEFAULT_DIRS_SIZE (MAX_DEFAULT_DIRS + 1) /* Terminate with NULL */
124 static const char **default_directories = NULL;
125 
126 #ifdef __WIN__
127 static const char *f_extensions[]= { ".ini", ".cnf", 0 };
128 #define NEWLINE "\r\n"
129 #else
130 static const char *f_extensions[]= { ".cnf", 0 };
131 #define NEWLINE "\n"
132 #endif
133 
134 static int handle_default_option(void *in_ctx, const char *group_name,
135  const char *option);
136 
137 /*
138  This structure defines the context that we pass to callback
139  function 'handle_default_option' used in search_default_file
140  to process each option. This context is used if search_default_file
141  was called from load_defaults.
142 */
143 
145 {
146  MEM_ROOT *alloc;
147  DYNAMIC_ARRAY *args;
148  TYPELIB *group;
149 };
150 
151 static int search_default_file(Process_option_func func, void *func_ctx,
152  const char *dir, const char *config_file);
153 static int search_default_file_with_ext(Process_option_func func,
154  void *func_ctx,
155  const char *dir, const char *ext,
156  const char *config_file, int recursion_level);
157 static my_bool mysql_file_getline(char *str, int size, MYSQL_FILE *file);
158 static int check_file_permissions(const char *file_name);
159 
160 
187 static const char **init_default_directories(MEM_ROOT *alloc);
188 
189 
190 static char *remove_end_comment(char *ptr);
191 
192 
193 /*
194  Expand a file name so that the current working directory is added if
195  the name is relative.
196 
197  RETURNS
198  0 All OK
199  2 Out of memory or path too long
200  3 Not able to get working directory
201  */
202 
203 static int
204 fn_expand(const char *filename, char *result_buf)
205 {
206  char dir[FN_REFLEN];
207  const int flags= MY_UNPACK_FILENAME | MY_SAFE_PATH | MY_RELATIVE_PATH;
208  DBUG_ENTER("fn_expand");
209  DBUG_PRINT("enter", ("filename: %s, result_buf: 0x%lx",
210  filename, (unsigned long) result_buf));
211  if (my_getwd(dir, sizeof(dir), MYF(0)))
212  DBUG_RETURN(3);
213  DBUG_PRINT("debug", ("dir: %s", dir));
214  if (fn_format(result_buf, filename, dir, "", flags) == NULL)
215  DBUG_RETURN(2);
216  DBUG_PRINT("return", ("result: %s", result_buf));
217  DBUG_RETURN(0);
218 }
219 
220 /*
221  Process config files in default directories.
222 
223  SYNOPSIS
224  my_search_option_files()
225  conf_file Basename for configuration file to search for.
226  If this is a path, then only this file is read.
227  argc Pointer to argc of original program
228  argv Pointer to argv of original program
229  args_used Pointer to variable for storing the number of
230  arguments used.
231  func Pointer to the function to process options
232  func_ctx It's context. Usually it is the structure to
233  store additional options.
234  default_directories List of default directories.
235 
236  DESCRIPTION
237  Process the default options from argc & argv
238  Read through each found config file looks and calls 'func' to process
239  each option. This function also reads options from login file.
240 
241  NOTES
242  --defaults-group-suffix is only processed if we are called from
243  load_defaults().
244 
245 
246  RETURN
247  0 ok
248  1 given cinf_file doesn't exist
249  2 out of memory
250  3 Can't get current working directory
251 
252  The global variable 'my_defaults_group_suffix' is updated with value for
253  --defaults_group_suffix
254 */
255 
256 int my_search_option_files(const char *conf_file, int *argc, char ***argv,
257  uint *args_used, Process_option_func func,
258  void *func_ctx, const char **default_directories)
259 {
260  const char **dirs, *forced_default_file, *forced_extra_defaults;
261  int error= 0;
262  DBUG_ENTER("my_search_option_files");
263 
264  /* Skip for login file. */
265  if (! is_login_file)
266  {
267  /* Check if we want to force the use a specific default file */
268  *args_used+= get_defaults_options(*argc - *args_used, *argv + *args_used,
269  (char **) &forced_default_file,
270  (char **) &forced_extra_defaults,
271  (char **) &my_defaults_group_suffix,
272  (char **) &my_login_path);
273 
274  if (! my_defaults_group_suffix)
275  my_defaults_group_suffix= getenv(STRINGIFY_ARG(DEFAULT_GROUP_SUFFIX_ENV));
276 
277  if (forced_extra_defaults && !defaults_already_read)
278  {
279  int error= fn_expand(forced_extra_defaults,
280  my_defaults_extra_file_buffer);
281  if (error)
282  DBUG_RETURN(error);
283 
284  my_defaults_extra_file= my_defaults_extra_file_buffer;
285  }
286 
287  if (forced_default_file && !defaults_already_read)
288  {
289  int error= fn_expand(forced_default_file, my_defaults_file_buffer);
290  if (error)
291  DBUG_RETURN(error);
292  my_defaults_file= my_defaults_file_buffer;
293  }
294 
295  defaults_already_read= TRUE;
296 
297  /*
298  We can only handle 'defaults-group-suffix' if we are called from
299  load_defaults() as otherwise we can't know the type of 'func_ctx'
300  */
301 
302  if (my_defaults_group_suffix && func == handle_default_option)
303  {
304  /* Handle --defaults-group-suffix= */
305  uint i;
306  const char **extra_groups;
307  const size_t instance_len= strlen(my_defaults_group_suffix);
308  struct handle_option_ctx *ctx= (struct handle_option_ctx*) func_ctx;
309  char *ptr;
310  TYPELIB *group= ctx->group;
311 
312  if (!(extra_groups=
313  (const char**)alloc_root(ctx->alloc,
314  (2*group->count+1)*sizeof(char*))))
315  DBUG_RETURN(2);
316 
317  for (i= 0; i < group->count; i++)
318  {
319  size_t len;
320  extra_groups[i]= group->type_names[i];
322  len= strlen(extra_groups[i]);
323  if (!(ptr= (char *) alloc_root(ctx->alloc,
324  (uint) (len + instance_len + 1))))
325  DBUG_RETURN(2);
326 
327  extra_groups[i+group->count]= ptr;
328 
330  memcpy(ptr, extra_groups[i], len);
331  memcpy(ptr+len, my_defaults_group_suffix, instance_len+1);
332  }
333 
334  group->count*= 2;
335  group->type_names= extra_groups;
336  group->type_names[group->count]= 0;
337  }
338  }
339  else if (my_login_path && func == handle_default_option)
340  {
341  /* Handle --login_path= */
342  uint i;
343  size_t len;
344  const char **extra_groups;
345  size_t instance_len= 0;
346  struct handle_option_ctx *ctx= (struct handle_option_ctx*) func_ctx;
347  char *ptr;
348  TYPELIB *group= ctx->group;
349 
350  if (!(extra_groups= (const char**)alloc_root(ctx->alloc,
351  (group->count + 3)
352  * sizeof(char *))))
353  DBUG_RETURN(2);
354 
355  for (i= 0; i < group->count; i++)
356  {
357  extra_groups[i]= group->type_names[i];
358  }
359 
360  extra_groups[i]= my_login_path;
361 
362  if (my_defaults_group_suffix && func == handle_default_option)
363  {
364  instance_len= strlen(my_defaults_group_suffix);
365  len= strlen(extra_groups[i]);
366 
367  if (!(ptr= (char *) alloc_root(ctx->alloc,
368  (uint) (len + instance_len + 1))))
369  DBUG_RETURN(2);
370 
371  extra_groups[i + 1]= ptr;
372 
374  memcpy(ptr, extra_groups[i], len);
375  memcpy(ptr+len, my_defaults_group_suffix, instance_len + 1);
376  group->count += 1;
377  }
378 
379  group->count += 1;
380  group->type_names= extra_groups;
381  group->type_names[group->count]= 0;
382  }
383 
384  // If conf_file is an absolute path, we only read it
385  if (dirname_length(conf_file))
386  {
387  if ((error= search_default_file(func, func_ctx, NullS, conf_file)) < 0)
388  goto err;
389  }
390  // If my defaults file is set (from a previous run), we read it
391  else if (my_defaults_file)
392  {
393  if ((error= search_default_file_with_ext(func, func_ctx, "", "",
394  my_defaults_file, 0)) < 0)
395  goto err;
396  if (error > 0)
397  {
398  fprintf(stderr, "Could not open required defaults file: %s\n",
399  my_defaults_file);
400  goto err;
401  }
402  }
403  else if (! found_no_defaults)
404  {
405  for (dirs= default_directories ; *dirs; dirs++)
406  {
407  if (**dirs)
408  {
409  if (search_default_file(func, func_ctx, *dirs, conf_file) < 0)
410  goto err;
411  }
412  else if (my_defaults_extra_file)
413  {
414  if ((error= search_default_file_with_ext(func, func_ctx, "", "",
415  my_defaults_extra_file, 0)) < 0)
416  goto err; /* Fatal error */
417  if (error > 0)
418  {
419  fprintf(stderr, "Could not open required defaults file: %s\n",
420  my_defaults_extra_file);
421  goto err;
422  }
423  }
424  }
425  }
426 
427  DBUG_RETURN(0);
428 
429 err:
430  fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
431  DBUG_RETURN(1);
432 }
433 
434 
435 /*
436  The option handler for load_defaults.
437 
438  SYNOPSIS
439  handle_deault_option()
440  in_ctx Handler context. In this case it is a
441  handle_option_ctx structure.
442  group_name The name of the group the option belongs to.
443  option The very option to be processed. It is already
444  prepared to be used in argv (has -- prefix). If it
445  is NULL, we are handling a new group (section).
446 
447  DESCRIPTION
448  This handler checks whether a group is one of the listed and adds an option
449  to the array if yes. Some other handler can record, for instance, all
450  groups and their options, not knowing in advance the names and amount of
451  groups.
452 
453  RETURN
454  0 - ok
455  1 - error occured
456 */
457 
458 static int handle_default_option(void *in_ctx, const char *group_name,
459  const char *option)
460 {
461  char *tmp;
462  struct handle_option_ctx *ctx= (struct handle_option_ctx *) in_ctx;
463 
464  if (!option)
465  return 0;
466 
467  if (find_type((char *)group_name, ctx->group, FIND_TYPE_NO_PREFIX))
468  {
469  if (!(tmp= (char *) alloc_root(ctx->alloc, strlen(option) + 1)))
470  return 1;
471  if (insert_dynamic(ctx->args, &tmp))
472  return 1;
473  strmov(tmp, option);
474  }
475 
476  return 0;
477 }
478 
479 
480 /*
481  Gets options from the command line, however if --no-defaults
482  option is used, --defaults-file & --defaults-extra-file options
483  would be ignored.
484 
485  SYNOPSIS
486  get_defaults_options()
487  argc Pointer to argc of original program
488  argv Pointer to argv of original program
489  defaults --defaults-file option
490  extra_defaults --defaults-extra-file option
491  group_suffix --defaults-group-suffix option
492  login_path --login-path option
493 
494  RETURN
495  # Number of arguments used from *argv
496  defaults and extra_defaults will be set to option of the appropriate
497  items of argv array, or to NULL if there are no such options
498 */
499 
500 int get_defaults_options(int argc, char **argv,
501  char **defaults,
502  char **extra_defaults,
503  char **group_suffix,
504  char **login_path)
505 {
506  int org_argc= argc, prev_argc= 0, default_option_count= 0;
507  *defaults= *extra_defaults= *group_suffix= *login_path= 0;
508 
509  while (argc >= 2 && argc != prev_argc)
510  {
511  /* Skip program name or previously handled argument */
512  argv++;
513  prev_argc= argc; /* To check if we found */
514  /* --no-defaults is always the first option. */
515  if (is_prefix(*argv,"--no-defaults") && ! default_option_count)
516  {
517  argc--;
518  default_option_count ++;
519  continue;
520  }
521  if (!*defaults && is_prefix(*argv, "--defaults-file=") && ! found_no_defaults)
522  {
523  *defaults= *argv + sizeof("--defaults-file=")-1;
524  argc--;
525  default_option_count ++;
526  continue;
527  }
528  if (!*extra_defaults && is_prefix(*argv, "--defaults-extra-file=")
529  && ! found_no_defaults)
530  {
531  *extra_defaults= *argv + sizeof("--defaults-extra-file=")-1;
532  argc--;
533  default_option_count ++;
534  continue;
535  }
536  if (!*group_suffix && is_prefix(*argv, "--defaults-group-suffix="))
537  {
538  *group_suffix= *argv + sizeof("--defaults-group-suffix=")-1;
539  argc--;
540  default_option_count ++;
541  continue;
542  }
543  if (!*login_path && is_prefix(*argv, "--login-path="))
544  {
545  *login_path= *argv + sizeof("--login-path=")-1;
546  argc--;
547  default_option_count ++;
548  continue;
549  }
550  }
551  return org_argc - argc;
552 }
553 
554 /*
555  Wrapper around my_load_defaults() for interface compatibility.
556 
557  SYNOPSIS
558  load_defaults()
559  conf_file Basename for configuration file to search for.
560  If this is a path, then only this file is read.
561  groups Which [group] entrys to read.
562  Points to an null terminated array of pointers
563  argc Pointer to argc of original program
564  argv Pointer to argv of original program
565 
566  NOTES
567 
568  This function is NOT thread-safe as it uses a global pointer internally.
569  See also notes for my_load_defaults().
570 
571  RETURN
572  0 ok
573  1 The given conf_file didn't exists
574 */
575 int load_defaults(const char *conf_file, const char **groups,
576  int *argc, char ***argv)
577 {
578  return my_load_defaults(conf_file, groups, argc, argv, &default_directories);
579 }
580 
581 /*
582  Read options from configurations files
583 
584  SYNOPSIS
585  my_load_defaults()
586  conf_file Basename for configuration file to search for.
587  If this is a path, then only this file is read.
588  groups Which [group] entrys to read.
589  Points to an null terminated array of pointers
590  argc Pointer to argc of original program
591  argv Pointer to argv of original program
592  default_directories Pointer to a location where a pointer to the list
593  of default directories will be stored
594 
595  IMPLEMENTATION
596 
597  Read options from configuration files and put them BEFORE the arguments
598  that are already in argc and argv. This way the calling program can
599  easily command line options override options in configuration files
600 
601  NOTES
602  In case of fatal error, the function will print a warning and do
603  exit(1)
604 
605  To free used memory one should call free_defaults() with the argument
606  that was put in *argv
607 
608  RETURN
609  - If successful, 0 is returned. If 'default_directories' is not NULL,
610  a pointer to the array of default directory paths is stored to a location
611  it points to. That stored value must be passed to my_search_option_files()
612  later.
613 
614  - 1 is returned if the given conf_file didn't exist. In this case, the
615  value pointed to by default_directories is undefined.
616 */
617 
618 
619 int my_load_defaults(const char *conf_file, const char **groups,
620  int *argc, char ***argv, const char ***default_directories)
621 {
622  DYNAMIC_ARRAY args;
623  TYPELIB group;
624  my_bool found_print_defaults= 0;
625  uint args_used= 0;
626  int error= 0;
627  MEM_ROOT alloc;
628  char *ptr,**res;
629  struct handle_option_ctx ctx;
630  const char **dirs;
631  uint args_sep= my_getopt_use_args_separator ? 1 : 0;
632  DBUG_ENTER("load_defaults");
633 
634  init_alloc_root(&alloc,512,0);
635  if ((dirs= init_default_directories(&alloc)) == NULL)
636  goto err;
637  /*
638  Check if the user doesn't want any default option processing
639  --no-defaults is always the first option
640  */
641  if (*argc >= 2 && !strcmp(argv[0][1], "--no-defaults"))
642  found_no_defaults= TRUE;
643 
644  group.count=0;
645  group.name= "defaults";
646  group.type_names= groups;
647 
648  for (; *groups ; groups++)
649  group.count++;
650 
651  if (my_init_dynamic_array(&args, sizeof(char*),*argc, 32))
652  goto err;
653 
654  ctx.alloc= &alloc;
655  ctx.args= &args;
656  ctx.group= &group;
657 
658  if ((error= my_search_option_files(conf_file, argc, argv,
659  &args_used, handle_default_option,
660  (void *) &ctx, dirs)))
661  {
662  free_root(&alloc,MYF(0));
663  DBUG_RETURN(error);
664  }
665 
666  /* Read options from login group. */
667  is_login_file= TRUE;
668  if (my_default_get_login_file(my_login_file, sizeof(my_login_file)) &&
669  (error= my_search_option_files(my_login_file,argc, argv, &args_used,
670  handle_default_option, (void *) &ctx,
671  dirs)))
672  {
673  free_root(&alloc,MYF(0));
674  DBUG_RETURN(error);
675  }
676  is_login_file= FALSE;
677 
678  /*
679  Here error contains <> 0 only if we have a fully specified conf_file
680  or a forced default file
681  */
682  if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
683  (args.elements + *argc + 1 + args_sep) *sizeof(char*))))
684  goto err;
685  res= (char**) (ptr+sizeof(alloc));
686 
687  /* copy name + found arguments + command line arguments to new array */
688  res[0]= argv[0][0]; /* Name MUST be set, even by embedded library */
689  memcpy((uchar*) (res+1), args.buffer, args.elements*sizeof(char*));
690  /* Skip --defaults-xxx options */
691  (*argc)-= args_used;
692  (*argv)+= args_used;
693 
694  /*
695  Check if we wan't to see the new argument list
696  This options must always be the last of the default options
697  */
698  if (*argc >= 2 && !strcmp(argv[0][1],"--print-defaults"))
699  {
700  found_print_defaults=1;
701  --*argc; ++*argv; /* skip argument */
702  }
703 
704  if (my_getopt_use_args_separator)
705  {
706  /* set arguments separator for arguments from config file and
707  command line */
708  set_args_separator(&res[args.elements+1]);
709  }
710 
711  if (*argc)
712  memcpy((uchar*) (res+1+args.elements+args_sep), (char*) ((*argv)+1),
713  (*argc-1)*sizeof(char*));
714  res[args.elements+ *argc+args_sep]=0; /* last null */
715 
716  (*argc)+=args.elements+args_sep;
717  *argv= (char**) res;
718  *(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */
719  delete_dynamic(&args);
720 
721  if (default_directories)
722  *default_directories= dirs;
723 
724  if (found_no_defaults)
725  DBUG_RETURN(0);
726 
727  if (found_print_defaults)
728  {
729  int i;
730  printf("%s would have been started with the following arguments:\n",
731  **argv);
732  for (i=1 ; i < *argc ; i++)
733  if (!my_getopt_is_args_separator((*argv)[i])) /* skip arguments separator */
734  printf("%s ", (*argv)[i]);
735  puts("");
736  exit(0);
737  }
738 
739  DBUG_RETURN(0);
740 
741  err:
742  fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
743  exit(1);
744  return 0; /* Keep compiler happy */
745 }
746 
747 
748 void free_defaults(char **argv)
749 {
750  MEM_ROOT ptr;
751  memcpy(&ptr, ((char *) argv) - sizeof(ptr), sizeof(ptr));
752  free_root(&ptr,MYF(0));
753 }
754 
755 
756 static int search_default_file(Process_option_func opt_handler,
757  void *handler_ctx,
758  const char *dir,
759  const char *config_file)
760 {
761  char **ext;
762  const char *empty_list[]= { "", 0 };
763  my_bool have_ext= fn_ext(config_file)[0] != 0;
764  const char **exts_to_use= have_ext ? empty_list : f_extensions;
765 
766  for (ext= (char**) exts_to_use; *ext; ext++)
767  {
768  int error;
769  if ((error= search_default_file_with_ext(opt_handler, handler_ctx,
770  dir, *ext,
771  config_file, 0)) < 0)
772  return error;
773  }
774  return 0;
775 }
776 
777 
778 /*
779  Skip over keyword and get argument after keyword
780 
781  SYNOPSIS
782  get_argument()
783  keyword Include directive keyword
784  kwlen Length of keyword
785  ptr Pointer to the keword in the line under process
786  line line number
787 
788  RETURN
789  0 error
790  # Returns pointer to the argument after the keyword.
791 */
792 
793 static char *get_argument(const char *keyword, size_t kwlen,
794  char *ptr, char *name, uint line)
795 {
796  char *end;
797 
798  /* Skip over "include / includedir keyword" and following whitespace */
799 
800  for (ptr+= kwlen - 1;
801  my_isspace(&my_charset_latin1, ptr[0]);
802  ptr++)
803  {}
804 
805  /*
806  Trim trailing whitespace from directory name
807  The -1 below is for the newline added by fgets()
808  Note that my_isspace() is true for \r and \n
809  */
810  for (end= ptr + strlen(ptr) - 1;
811  my_isspace(&my_charset_latin1, *(end - 1));
812  end--)
813  {}
814  end[0]= 0; /* Cut off end space */
815 
816  /* Print error msg if there is nothing after !include* directive */
817  if (end <= ptr)
818  {
819  fprintf(stderr,
820  "error: Wrong '!%s' directive in config file: %s at line %d\n",
821  keyword, name, line);
822  return 0;
823  }
824  return ptr;
825 }
826 
827 
828 /*
829  Open a configuration file (if exists) and read given options from it
830 
831  SYNOPSIS
832  search_default_file_with_ext()
833  opt_handler Option handler function. It is used to process
834  every separate option.
835  handler_ctx Pointer to the structure to store actual
836  parameters of the function.
837  dir directory to read
838  ext Extension for configuration file
839  config_file Name of configuration file
840  group groups to read
841  recursion_level the level of recursion, got while processing
842  "!include" or "!includedir"
843 
844  RETURN
845  0 Success
846  -1 Fatal error, abort
847  1 File not found (Warning)
848 */
849 
850 static int search_default_file_with_ext(Process_option_func opt_handler,
851  void *handler_ctx,
852  const char *dir,
853  const char *ext,
854  const char *config_file,
855  int recursion_level)
856 {
857  char name[FN_REFLEN + 10], buff[4096], curr_gr[4096], *ptr, *end, **tmp_ext;
858  char *value, option[4096+2], tmp[FN_REFLEN];
859  static const char includedir_keyword[]= "includedir";
860  static const char include_keyword[]= "include";
861  const int max_recursion_level= 10;
862  MYSQL_FILE *fp;
863  uint line=0;
864  my_bool found_group=0;
865  uint i, rc;
866  MY_DIR *search_dir;
867  FILEINFO *search_file;
868 
869  if ((dir ? strlen(dir) : 0 )+strlen(config_file) >= FN_REFLEN-3)
870  return 0; /* Ignore wrong paths */
871  if (dir)
872  {
873  end=convert_dirname(name, dir, NullS);
874  if (dir[0] == FN_HOMELIB) /* Add . to filenames in home */
875  *end++='.';
876  strxmov(end,config_file,ext,NullS);
877  }
878  else
879  {
880  strmov(name,config_file);
881  }
882  fn_format(name,name,"","",4);
883 
884  if ((rc= check_file_permissions(name)) < 2)
885  return (int) rc;
886 
887  if (is_login_file)
888  {
889  if ( !(fp = mysql_file_fopen(key_file_cnf, name, (O_RDONLY | O_BINARY),
890  MYF(0))))
891  return 1; /* Ignore wrong files. */
892  }
893  else
894  {
895  if ( !(fp = mysql_file_fopen(key_file_cnf, name, O_RDONLY, MYF(0))))
896  return 1; /* Ignore wrong files */
897  }
898 
899  while (mysql_file_getline(buff, sizeof(buff) - 1, fp))
900  {
901  line++;
902  /* Ignore comment and empty lines */
903  for (ptr= buff; my_isspace(&my_charset_latin1, *ptr); ptr++)
904  {}
905 
906  if (*ptr == '#' || *ptr == ';' || !*ptr)
907  continue;
908 
909  /* Configuration File Directives */
910  if (*ptr == '!')
911  {
912  if (recursion_level >= max_recursion_level)
913  {
914  for (end= ptr + strlen(ptr) - 1;
915  my_isspace(&my_charset_latin1, *(end - 1));
916  end--)
917  {}
918  end[0]= 0;
919  fprintf(stderr,
920  "Warning: skipping '%s' directive as maximum include"
921  "recursion level was reached in file %s at line %d\n",
922  ptr, name, line);
923  continue;
924  }
925 
926  /* skip over `!' and following whitespace */
927  for (++ptr; my_isspace(&my_charset_latin1, ptr[0]); ptr++)
928  {}
929 
930  if ((!strncmp(ptr, includedir_keyword,
931  sizeof(includedir_keyword) - 1)) &&
932  my_isspace(&my_charset_latin1, ptr[sizeof(includedir_keyword) - 1]))
933  {
934  if (!(ptr= get_argument(includedir_keyword,
935  sizeof(includedir_keyword),
936  ptr, name, line)))
937  goto err;
938 
939  if (!(search_dir= my_dir(ptr, MYF(MY_WME))))
940  goto err;
941 
942  for (i= 0; i < (uint) search_dir->number_off_files; i++)
943  {
944  search_file= search_dir->dir_entry + i;
945  ext= fn_ext(search_file->name);
946 
947  /* check extension */
948  for (tmp_ext= (char**) f_extensions; *tmp_ext; tmp_ext++)
949  {
950  if (!strcmp(ext, *tmp_ext))
951  break;
952  }
953 
954  if (*tmp_ext)
955  {
956  fn_format(tmp, search_file->name, ptr, "",
957  MY_UNPACK_FILENAME | MY_SAFE_PATH);
958 
959  search_default_file_with_ext(opt_handler, handler_ctx, "", "", tmp,
960  recursion_level + 1);
961  }
962  }
963 
964  my_dirend(search_dir);
965  }
966  else if ((!strncmp(ptr, include_keyword, sizeof(include_keyword) - 1)) &&
967  my_isspace(&my_charset_latin1, ptr[sizeof(include_keyword)-1]))
968  {
969  if (!(ptr= get_argument(include_keyword,
970  sizeof(include_keyword), ptr,
971  name, line)))
972  goto err;
973 
974  search_default_file_with_ext(opt_handler, handler_ctx, "", "", ptr,
975  recursion_level + 1);
976  }
977 
978  continue;
979  }
980 
981  if (*ptr == '[') /* Group name */
982  {
983  found_group=1;
984  if (!(end=(char *) strchr(++ptr,']')))
985  {
986  fprintf(stderr,
987  "error: Wrong group definition in config file: %s at line %d\n",
988  name,line);
989  goto err;
990  }
991  /* Remove end space */
992  for ( ; my_isspace(&my_charset_latin1, end[-1]); end --)
993  {}
994 
995  end[0]=0;
996 
997  strmake(curr_gr, ptr, MY_MIN((size_t) (end-ptr)+1, sizeof(curr_gr)-1));
998 
999  /* signal that a new group is found */
1000  opt_handler(handler_ctx, curr_gr, NULL);
1001 
1002  continue;
1003  }
1004  if (!found_group)
1005  {
1006  fprintf(stderr,
1007  "error: Found option without preceding group in config file: %s at line: %d\n",
1008  name,line);
1009  goto err;
1010  }
1011 
1012 
1013  end= remove_end_comment(ptr);
1014  if ((value= strchr(ptr, '=')))
1015  end= value; /* Option without argument */
1016  for ( ; my_isspace(&my_charset_latin1, end[-1]) ; end--)
1017  {}
1018 
1019  if (!value)
1020  {
1021  strmake(strmov(option,"--"),ptr, (size_t) (end-ptr));
1022  if (opt_handler(handler_ctx, curr_gr, option))
1023  goto err;
1024  }
1025  else
1026  {
1027  /* Remove pre- and end space */
1028  char *value_end;
1029  for (value++ ; my_isspace(&my_charset_latin1, *value); value ++)
1030  {}
1031 
1032  value_end=strend(value);
1033  /*
1034  We don't have to test for value_end >= value as we know there is
1035  an '=' before
1036  */
1037  for ( ; my_isspace(&my_charset_latin1, value_end[-1]); value_end --)
1038  {}
1039 
1040  if (value_end < value) /* Empty string */
1041  value_end=value;
1042 
1043  /* remove quotes around argument */
1044  if ((*value == '\"' || *value == '\'') && /* First char is quote */
1045  (value + 1 < value_end ) && /* String is longer than 1 */
1046  *value == value_end[-1] ) /* First char is equal to last char */
1047  {
1048  value++;
1049  value_end--;
1050  }
1051  ptr=strnmov(strmov(option,"--"),ptr,(size_t) (end-ptr));
1052  *ptr++= '=';
1053 
1054  for ( ; value != value_end; value++)
1055  {
1056  if (*value == '\\' && value != value_end-1)
1057  {
1058  switch(*++value) {
1059  case 'n':
1060  *ptr++='\n';
1061  break;
1062  case 't':
1063  *ptr++= '\t';
1064  break;
1065  case 'r':
1066  *ptr++ = '\r';
1067  break;
1068  case 'b':
1069  *ptr++ = '\b';
1070  break;
1071  case 's':
1072  *ptr++= ' '; /* space */
1073  break;
1074  case '\"':
1075  *ptr++= '\"';
1076  break;
1077  case '\'':
1078  *ptr++= '\'';
1079  break;
1080  case '\\':
1081  *ptr++= '\\';
1082  break;
1083  default: /* Unknown; Keep '\' */
1084  *ptr++= '\\';
1085  *ptr++= *value;
1086  break;
1087  }
1088  }
1089  else
1090  *ptr++= *value;
1091  }
1092  *ptr=0;
1093  if (opt_handler(handler_ctx, curr_gr, option))
1094  goto err;
1095  }
1096  }
1097  mysql_file_fclose(fp, MYF(0));
1098  return(0);
1099 
1100  err:
1101  mysql_file_fclose(fp, MYF(0));
1102  return -1; /* Fatal error */
1103 }
1104 
1105 
1106 static char *remove_end_comment(char *ptr)
1107 {
1108  char quote= 0; /* we are inside quote marks */
1109  char escape= 0; /* symbol is protected by escape chagacter */
1110 
1111  for (; *ptr; ptr++)
1112  {
1113  if ((*ptr == '\'' || *ptr == '\"') && !escape)
1114  {
1115  if (!quote)
1116  quote= *ptr;
1117  else if (quote == *ptr)
1118  quote= 0;
1119  }
1120  /* We are not inside a string */
1121  if (!quote && *ptr == '#')
1122  {
1123  *ptr= 0;
1124  return ptr;
1125  }
1126  escape= (quote && *ptr == '\\' && !escape);
1127  }
1128  return ptr;
1129 }
1130 
1131 
1145 static my_bool mysql_file_getline(char *str, int size, MYSQL_FILE *file)
1146 {
1147  uchar cipher[4096], len_buf[MAX_CIPHER_STORE_LEN];
1148  int length= 0, cipher_len= 0;
1149 
1150  if (is_login_file)
1151  {
1152  if (mysql_file_ftell(file, MYF(MY_WME)) == 0)
1153  {
1154  /* Move past unused bytes. */
1155  mysql_file_fseek(file, 4, SEEK_SET, MYF(MY_WME));
1156  if (mysql_file_fread(file, (uchar *) my_key, LOGIN_KEY_LEN,
1157  MYF(MY_WME)) != LOGIN_KEY_LEN)
1158  return 0;
1159  }
1160 
1161  if (mysql_file_fread(file, len_buf, MAX_CIPHER_STORE_LEN,
1162  MYF(MY_WME)) == MAX_CIPHER_STORE_LEN)
1163  {
1164  cipher_len= sint4korr(len_buf);
1165  if (cipher_len > size)
1166  return 0;
1167  }
1168  else
1169  return 0;
1170 
1171  mysql_file_fread(file, cipher, cipher_len, MYF(MY_WME));
1172  if ((length= my_aes_decrypt((const char *) cipher, cipher_len, str,
1173  my_key, LOGIN_KEY_LEN)) < 0)
1174  {
1175  /* Attempt to decrypt failed. */
1176  return 0;
1177  }
1178  str[length]= 0;
1179  return 1;
1180  }
1181  else
1182  {
1183  if (mysql_file_fgets(str, size, file))
1184  return 1;
1185  else
1186  return 0;
1187  }
1188 }
1189 
1190 
1191 void my_print_default_files(const char *conf_file)
1192 {
1193  const char *empty_list[]= { "", 0 };
1194  my_bool have_ext= fn_ext(conf_file)[0] != 0;
1195  const char **exts_to_use= have_ext ? empty_list : f_extensions;
1196  char name[FN_REFLEN], **ext;
1197 
1198  puts("\nDefault options are read from the following files in the given order:");
1199 
1200  if (dirname_length(conf_file))
1201  fputs(conf_file,stdout);
1202  else
1203  {
1204  const char **dirs;
1205  MEM_ROOT alloc;
1206  init_alloc_root(&alloc,512,0);
1207 
1208  if ((dirs= init_default_directories(&alloc)) == NULL)
1209  {
1210  fputs("Internal error initializing default directories list", stdout);
1211  }
1212  else
1213  {
1214  for ( ; *dirs; dirs++)
1215  {
1216  for (ext= (char**) exts_to_use; *ext; ext++)
1217  {
1218  const char *pos;
1219  char *end;
1220  if (**dirs)
1221  pos= *dirs;
1222  else if (my_defaults_extra_file)
1223  pos= my_defaults_extra_file;
1224  else
1225  continue;
1226  end= convert_dirname(name, pos, NullS);
1227  if (name[0] == FN_HOMELIB) /* Add . to filenames in home */
1228  *end++= '.';
1229 
1230  if (my_defaults_extra_file == pos)
1231  end[(strlen(end)-1)] = ' ';
1232  else
1233  strxmov(end, conf_file, *ext , " ", NullS);
1234  fputs(name, stdout);
1235  }
1236  }
1237  }
1238 
1239  free_root(&alloc, MYF(0));
1240  }
1241  puts("");
1242 }
1243 
1244 void print_defaults(const char *conf_file, const char **groups)
1245 {
1246  const char **groups_save= groups;
1247  my_print_default_files(conf_file);
1248 
1249  fputs("The following groups are read:",stdout);
1250  for ( ; *groups ; groups++)
1251  {
1252  fputc(' ',stdout);
1253  fputs(*groups,stdout);
1254  }
1255 
1256  if (my_defaults_group_suffix)
1257  {
1258  groups= groups_save;
1259  for ( ; *groups ; groups++)
1260  {
1261  fputc(' ',stdout);
1262  fputs(*groups,stdout);
1263  fputs(my_defaults_group_suffix,stdout);
1264  }
1265  }
1266  puts("\nThe following options may be given as the first argument:\n\
1267 --print-defaults Print the program argument list and exit.\n\
1268 --no-defaults Don't read default options from any option file,\n\
1269  except for login file.\n\
1270 --defaults-file=# Only read default options from the given file #.\n\
1271 --defaults-extra-file=# Read this file after the global files are read.\n\
1272 --defaults-group-suffix=#\n\
1273  Also read groups with concat(group, suffix)\n\
1274 --login-path=# Read this path from the login file.");
1275 }
1276 
1277 
1278 static int add_directory(MEM_ROOT *alloc, const char *dir, const char **dirs)
1279 {
1280  char buf[FN_REFLEN];
1281  size_t len;
1282  char *p;
1283  my_bool err __attribute__((unused));
1284 
1285  len= normalize_dirname(buf, dir);
1286  if (!(p= strmake_root(alloc, buf, len)))
1287  return 1; /* Failure */
1288  /* Should never fail if DEFAULT_DIRS_SIZE is correct size */
1289  err= array_append_string_unique(p, dirs, DEFAULT_DIRS_SIZE);
1290  DBUG_ASSERT(err == FALSE);
1291 
1292  return 0;
1293 }
1294 
1295 
1296 #ifdef __WIN__
1297 /*
1298  This wrapper for GetSystemWindowsDirectory() will dynamically bind to the
1299  function if it is available, emulate it on NT4 Terminal Server by stripping
1300  the \SYSTEM32 from the end of the results of GetSystemDirectory(), or just
1301  return GetSystemDirectory().
1302  */
1303 
1304 typedef UINT (WINAPI *GET_SYSTEM_WINDOWS_DIRECTORY)(LPSTR, UINT);
1305 
1306 static size_t my_get_system_windows_directory(char *buffer, size_t size)
1307 {
1308  size_t count;
1309  GET_SYSTEM_WINDOWS_DIRECTORY
1310  func_ptr= (GET_SYSTEM_WINDOWS_DIRECTORY)
1311  GetProcAddress(GetModuleHandle("kernel32.dll"),
1312  "GetSystemWindowsDirectoryA");
1313 
1314  if (func_ptr)
1315  return func_ptr(buffer, (uint) size);
1316 
1317  /*
1318  Windows NT 4.0 Terminal Server Edition:
1319  To retrieve the shared Windows directory, call GetSystemDirectory and
1320  trim the "System32" element from the end of the returned path.
1321  */
1322  count= GetSystemDirectory(buffer, (uint) size);
1323  if (count > 8 && stricmp(buffer+(count-8), "\\System32") == 0)
1324  {
1325  count-= 8;
1326  buffer[count] = '\0';
1327  }
1328  return count;
1329 }
1330 
1331 
1332 static const char *my_get_module_parent(char *buf, size_t size)
1333 {
1334  char *last= NULL;
1335  char *end;
1336  if (!GetModuleFileName(NULL, buf, (DWORD) size))
1337  return NULL;
1338  end= strend(buf);
1339 
1340  /*
1341  Look for the second-to-last \ in the filename, but hang on
1342  to a pointer after the last \ in case we're in the root of
1343  a drive.
1344  */
1345  for ( ; end > buf; end--)
1346  {
1347  if (*end == FN_LIBCHAR)
1348  {
1349  if (last)
1350  {
1351  /* Keep the last '\' as this works both with D:\ and a directory */
1352  end[1]= 0;
1353  break;
1354  }
1355  last= end;
1356  }
1357  }
1358 
1359  return buf;
1360 }
1361 #endif /* __WIN__ */
1362 
1363 
1364 static const char **init_default_directories(MEM_ROOT *alloc)
1365 {
1366  const char **dirs;
1367  char *env;
1368  int errors= 0;
1369 
1370  dirs= (const char **)alloc_root(alloc, DEFAULT_DIRS_SIZE * sizeof(char *));
1371  if (dirs == NULL)
1372  return NULL;
1373  memset(dirs, 0, DEFAULT_DIRS_SIZE * sizeof(char *));
1374 
1375 #ifdef __WIN__
1376 
1377  {
1378  char fname_buffer[FN_REFLEN];
1379  if (my_get_system_windows_directory(fname_buffer, sizeof(fname_buffer)))
1380  errors += add_directory(alloc, fname_buffer, dirs);
1381 
1382  if (GetWindowsDirectory(fname_buffer, sizeof(fname_buffer)))
1383  errors += add_directory(alloc, fname_buffer, dirs);
1384 
1385  errors += add_directory(alloc, "C:/", dirs);
1386 
1387  if (my_get_module_parent(fname_buffer, sizeof(fname_buffer)) != NULL)
1388  errors += add_directory(alloc, fname_buffer, dirs);
1389  }
1390 
1391 #else
1392 
1393  errors += add_directory(alloc, "/etc/", dirs);
1394  errors += add_directory(alloc, "/etc/mysql/", dirs);
1395 
1396 #if defined(DEFAULT_SYSCONFDIR)
1397  if (DEFAULT_SYSCONFDIR[0])
1398  errors += add_directory(alloc, DEFAULT_SYSCONFDIR, dirs);
1399 #endif /* DEFAULT_SYSCONFDIR */
1400 
1401 #endif
1402 
1403  if ((env= getenv("MYSQL_HOME")))
1404  errors += add_directory(alloc, env, dirs);
1405 
1406  /* Placeholder for --defaults-extra-file=<path> */
1407  errors += add_directory(alloc, "", dirs);
1408 
1409 #if !defined(__WIN__)
1410  errors += add_directory(alloc, "~/", dirs);
1411 #endif
1412 
1413  return (errors > 0 ? NULL : dirs);
1414 }
1415 
1426 int my_default_get_login_file(char *file_name, size_t file_name_size)
1427 {
1428  size_t rc;
1429 
1430  if (getenv("MYSQL_TEST_LOGIN_FILE"))
1431  rc= my_snprintf(file_name, file_name_size, "%s",
1432  getenv("MYSQL_TEST_LOGIN_FILE"));
1433 #ifdef _WIN32
1434  else if (getenv("APPDATA"))
1435  rc= my_snprintf(file_name, file_name_size, "%s\\MySQL\\.mylogin.cnf",
1436  getenv("APPDATA"));
1437 #else
1438  else if (getenv("HOME"))
1439  rc= my_snprintf(file_name, file_name_size, "%s/.mylogin.cnf",
1440  getenv("HOME"));
1441 #endif
1442  else
1443  {
1444  memset(file_name, 0, file_name_size);
1445  return 0;
1446  }
1447  /* Anything <= 0 will be treated as error. */
1448  if (rc <= 0)
1449  return 0;
1450 
1451  return 1;
1452 }
1453 
1463 static int check_file_permissions(const char *file_name)
1464 {
1465 #if !defined(__WIN__)
1466  MY_STAT stat_info;
1467 
1468  if (!my_stat(file_name,&stat_info,MYF(0)))
1469  return 1;
1470  /*
1471  Ignore .mylogin.cnf file if not exclusively readable/writable
1472  by current user.
1473  */
1474  if (is_login_file && (stat_info.st_mode & (S_IXUSR | S_IRWXG | S_IRWXO))
1475  && (stat_info.st_mode & S_IFMT) == S_IFREG)
1476  {
1477  fprintf(stderr, "Warning: %s should be readable/writable only by "
1478  "current user.\n", file_name);
1479  return 0;
1480  }
1481  /*
1482  Ignore world-writable regular files.
1483  This is mainly done to protect us to not read a file created by
1484  the mysqld server, but the check is still valid in most context.
1485  */
1486  else if ((stat_info.st_mode & S_IWOTH) &&
1487  (stat_info.st_mode & S_IFMT) == S_IFREG)
1488 
1489  {
1490  fprintf(stderr, "Warning: World-writable config file '%s' is ignored\n",
1491  file_name);
1492  return 0;
1493  }
1494 #endif
1495  return 2; /* Success */
1496 }
1497