~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2003 MySQL AB
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 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
****************************************************************************/
35
36
#include "mysys_priv.h"
212.5.18 by Monty Taylor
Moved m_ctype, m_string and my_bitmap. Removed t_ctype.
37
#include <mystrings/m_string.h>
38
#include <mystrings/m_ctype.h>
1 by brian
clean slate
39
#include <my_dir.h>
40
41
const char *my_defaults_file=0;
42
const char *my_defaults_group_suffix=0;
43
char *my_defaults_extra_file=0;
44
45
/* Which directories are searched for options (and in which order) */
46
47
#define MAX_DEFAULT_DIRS 6
48
const char *default_directories[MAX_DEFAULT_DIRS + 1];
49
50
static const char *f_extensions[]= { ".cnf", 0 };
51
#define NEWLINE "\n"
52
53
static int handle_default_option(void *in_ctx, const char *group_name,
54
                                 const char *option);
55
56
/*
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.
61
*/
62
63
struct handle_option_ctx
64
{
65
   MEM_ROOT *alloc;
66
   DYNAMIC_ARRAY *args;
67
   TYPELIB *group;
68
};
69
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,
73
                                        void *func_ctx,
74
					const char *dir, const char *ext,
75
					const char *config_file, int recursion_level);
76
77
78
79
/**
80
  Create the list of default directories.
81
82
  @details
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.
86
87
  @return void
88
*/
89
182.1.2 by Jim Winstead
Various fixes to enable compilation on Mac OS X, and remove the glib dependency.
90
static void init_default_directories(void);
1 by brian
clean slate
91
92
93
static char *remove_end_comment(char *ptr);
94
95
96
/*
97
  Process config files in default directories.
98
99
  SYNOPSIS
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
106
                              arguments used.
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.
110
  DESCRIPTION
111
    Process the default options from argc & argv
112
    Read through each found config file looks and calls 'func' to process
113
    each option.
114
115
  NOTES
116
    --defaults-group-suffix is only processed if we are called from
117
    load_defaults().
118
119
120
  RETURN
121
    0  ok
122
    1  given cinf_file doesn't exist
123
124
    The global variable 'my_defaults_group_suffix' is updated with value for
125
    --defaults_group_suffix
126
*/
127
128
int my_search_option_files(const char *conf_file, int *argc, char ***argv,
129
                           uint *args_used, Process_option_func func,
130
                           void *func_ctx)
131
{
132
  const char **dirs, *forced_default_file, *forced_extra_defaults;
133
  int error= 0;
134
135
  /* Check if we want to force the use a specific default file */
136
  *args_used+= get_defaults_options(*argc - *args_used, *argv + *args_used,
137
                                    (char **) &forced_default_file,
138
                                    (char **) &forced_extra_defaults,
139
                                    (char **) &my_defaults_group_suffix);
140
141
  if (! my_defaults_group_suffix)
142
    my_defaults_group_suffix= getenv(STRINGIFY_ARG(DEFAULT_GROUP_SUFFIX_ENV));
143
144
  if (forced_extra_defaults)
145
    my_defaults_extra_file= (char *) forced_extra_defaults;
146
  
147
  if (forced_default_file)
148
    my_defaults_file= forced_default_file;
149
150
  /*
151
    We can only handle 'defaults-group-suffix' if we are called from
152
    load_defaults() as otherwise we can't know the type of 'func_ctx'
153
  */
154
155
  if (my_defaults_group_suffix && func == handle_default_option)
156
  {
157
    /* Handle --defaults-group-suffix= */
158
    uint i;
159
    const char **extra_groups;
160
    const uint instance_len= strlen(my_defaults_group_suffix); 
161
    struct handle_option_ctx *ctx= (struct handle_option_ctx*) func_ctx;
162
    char *ptr;
163
    TYPELIB *group= ctx->group;
164
    
165
    if (!(extra_groups= 
166
	  (const char**)alloc_root(ctx->alloc,
167
                                   (2*group->count+1)*sizeof(char*))))
168
      goto err;
169
    
170
    for (i= 0; i < group->count; i++)
171
    {
172
      uint len;
173
      extra_groups[i]= group->type_names[i]; /** copy group */
174
      
175
      len= strlen(extra_groups[i]);
176
      if (!(ptr= alloc_root(ctx->alloc, len+instance_len+1)))
177
	goto err;
178
      
179
      extra_groups[i+group->count]= ptr;
180
      
181
      /** Construct new group */
182
      memcpy(ptr, extra_groups[i], len);
183
      memcpy(ptr+len, my_defaults_group_suffix, instance_len+1);
184
    }
185
    
186
    group->count*= 2;
187
    group->type_names= extra_groups;
188
    group->type_names[group->count]= 0;
189
  }
190
  
191
  if (forced_default_file)
192
  {
193
    if ((error= search_default_file_with_ext(func, func_ctx, "", "",
194
                                             forced_default_file, 0)) < 0)
195
      goto err;
196
    if (error > 0)
197
    {
198
      fprintf(stderr, "Could not open required defaults file: %s\n",
199
              forced_default_file);
200
      goto err;
201
    }
202
  }
203
  else if (dirname_length(conf_file))
204
  {
205
    if ((error= search_default_file(func, func_ctx, NullS, conf_file)) < 0)
206
      goto err;
207
  }
208
  else
209
  {
210
    for (dirs= default_directories ; *dirs; dirs++)
211
    {
212
      if (**dirs)
213
      {
214
	if (search_default_file(func, func_ctx, *dirs, conf_file) < 0)
215
	  goto err;
216
      }
217
      else if (my_defaults_extra_file)
218
      {
219
        if ((error= search_default_file_with_ext(func, func_ctx, "", "",
220
                                                my_defaults_extra_file, 0)) < 0)
221
	  goto err;				/* Fatal error */
222
        if (error > 0)
223
        {
224
          fprintf(stderr, "Could not open required defaults file: %s\n",
225
                  my_defaults_extra_file);
226
          goto err;
227
        }
228
      }
229
    }
230
  }
231
51.3.22 by Jay Pipes
Final round of removal of DBUG in mysys/, including Makefile
232
  return(error);
1 by brian
clean slate
233
234
err:
235
  fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
236
  exit(1);
237
  return 0;					/* Keep compiler happy */
238
}
239
240
241
/*
242
  The option handler for load_defaults.
243
244
  SYNOPSIS
245
    handle_deault_option()
246
    in_ctx                  Handler context. In this case it is a
247
                            handle_option_ctx structure.
248
    group_name              The name of the group the option belongs to.
249
    option                  The very option to be processed. It is already
250
                            prepared to be used in argv (has -- prefix). If it
251
                            is NULL, we are handling a new group (section).
252
253
  DESCRIPTION
254
    This handler checks whether a group is one of the listed and adds an option
255
    to the array if yes. Some other handler can record, for instance, all
256
    groups and their options, not knowing in advance the names and amount of
257
    groups.
258
259
  RETURN
260
    0 - ok
261
    1 - error occured
262
*/
263
264
static int handle_default_option(void *in_ctx, const char *group_name,
265
                                 const char *option)
266
{
267
  char *tmp;
268
  struct handle_option_ctx *ctx= (struct handle_option_ctx *) in_ctx;
269
270
  if (!option)
271
    return 0;
272
273
  if (find_type((char *)group_name, ctx->group, 3))
274
  {
275
    if (!(tmp= alloc_root(ctx->alloc, strlen(option) + 1)))
276
      return 1;
277
    if (insert_dynamic(ctx->args, (uchar*) &tmp))
278
      return 1;
279
    strmov(tmp, option);
280
  }
281
282
  return 0;
283
}
284
285
286
/*
287
  Gets options from the command line
288
289
  SYNOPSIS
290
    get_defaults_options()
291
    argc			Pointer to argc of original program
292
    argv			Pointer to argv of original program
293
    defaults                    --defaults-file option
294
    extra_defaults              --defaults-extra-file option
295
296
  RETURN
297
    # Number of arguments used from *argv
298
      defaults and extra_defaults will be set to option of the appropriate
299
      items of argv array, or to NULL if there are no such options
300
*/
301
302
int get_defaults_options(int argc, char **argv,
303
                         char **defaults,
304
                         char **extra_defaults,
305
                         char **group_suffix)
306
{
307
  int org_argc= argc, prev_argc= 0;
308
  *defaults= *extra_defaults= *group_suffix= 0;
309
310
  while (argc >= 2 && argc != prev_argc)
311
  {
312
    /* Skip program name or previously handled argument */
313
    argv++;
314
    prev_argc= argc;                            /* To check if we found */
315
    if (!*defaults && is_prefix(*argv,"--defaults-file="))
316
    {
317
      *defaults= *argv + sizeof("--defaults-file=")-1;
318
       argc--;
319
       continue;
320
    }
321
    if (!*extra_defaults && is_prefix(*argv,"--defaults-extra-file="))
322
    {
323
      *extra_defaults= *argv + sizeof("--defaults-extra-file=")-1;
324
      argc--;
325
      continue;
326
    }
327
    if (!*group_suffix && is_prefix(*argv, "--defaults-group-suffix="))
328
    {
329
      *group_suffix= *argv + sizeof("--defaults-group-suffix=")-1;
330
      argc--;
331
      continue;
332
    }
333
  }
334
  return org_argc - argc;
335
}
336
337
338
/*
339
  Read options from configurations files
340
341
  SYNOPSIS
342
    load_defaults()
343
    conf_file			Basename for configuration file to search for.
344
    				If this is a path, then only this file is read.
345
    groups			Which [group] entrys to read.
346
				Points to an null terminated array of pointers
347
    argc			Pointer to argc of original program
348
    argv			Pointer to argv of original program
349
350
  IMPLEMENTATION
351
352
   Read options from configuration files and put them BEFORE the arguments
353
   that are already in argc and argv.  This way the calling program can
354
   easily command line options override options in configuration files
355
356
   NOTES
357
    In case of fatal error, the function will print a warning and do
358
    exit(1)
359
 
360
    To free used memory one should call free_defaults() with the argument
361
    that was put in *argv
362
363
   RETURN
364
     0	ok
365
     1	The given conf_file didn't exists
366
*/
367
368
369
int load_defaults(const char *conf_file, const char **groups,
370
                  int *argc, char ***argv)
371
{
372
  DYNAMIC_ARRAY args;
373
  TYPELIB group;
146 by Brian Aker
my_bool cleanup.
374
  bool found_print_defaults= 0;
1 by brian
clean slate
375
  uint args_used= 0;
376
  int error= 0;
377
  MEM_ROOT alloc;
378
  char *ptr,**res;
379
  struct handle_option_ctx ctx;
380
381
  init_default_directories();
382
  init_alloc_root(&alloc,512,0);
383
  /*
384
    Check if the user doesn't want any default option processing
385
    --no-defaults is always the first option
386
  */
387
  if (*argc >= 2 && !strcmp(argv[0][1],"--no-defaults"))
388
  {
389
    /* remove the --no-defaults argument and return only the other arguments */
390
    uint i;
391
    if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
392
				 (*argc + 1)*sizeof(char*))))
393
      goto err;
394
    res= (char**) (ptr+sizeof(alloc));
395
    res[0]= **argv;				/* Copy program name */
396
    for (i=2 ; i < (uint) *argc ; i++)
397
      res[i-1]=argv[0][i];
398
    res[i-1]=0;					/* End pointer */
399
    (*argc)--;
400
    *argv=res;
401
    *(MEM_ROOT*) ptr= alloc;			/* Save alloc root for free */
51.3.22 by Jay Pipes
Final round of removal of DBUG in mysys/, including Makefile
402
    return(0);
1 by brian
clean slate
403
  }
404
405
  group.count=0;
406
  group.name= "defaults";
407
  group.type_names= groups;
408
409
  for (; *groups ; groups++)
410
    group.count++;
411
412
  if (my_init_dynamic_array(&args, sizeof(char*),*argc, 32))
413
    goto err;
414
415
  ctx.alloc= &alloc;
416
  ctx.args= &args;
417
  ctx.group= &group;
418
419
  error= my_search_option_files(conf_file, argc, argv, &args_used,
420
                                handle_default_option, (void *) &ctx);
421
  /*
422
    Here error contains <> 0 only if we have a fully specified conf_file
423
    or a forced default file
424
  */
425
  if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
426
			       (args.elements + *argc +1) *sizeof(char*))))
427
    goto err;
428
  res= (char**) (ptr+sizeof(alloc));
429
430
  /* copy name + found arguments + command line arguments to new array */
431
  res[0]= argv[0][0];  /* Name MUST be set, even by embedded library */
432
  memcpy((uchar*) (res+1), args.buffer, args.elements*sizeof(char*));
433
  /* Skip --defaults-xxx options */
434
  (*argc)-= args_used;
435
  (*argv)+= args_used;
436
437
  /*
438
    Check if we wan't to see the new argument list
439
    This options must always be the last of the default options
440
  */
441
  if (*argc >= 2 && !strcmp(argv[0][1],"--print-defaults"))
442
  {
443
    found_print_defaults=1;
444
    --*argc; ++*argv;				/* skip argument */
445
  }
446
447
  if (*argc)
448
    memcpy((uchar*) (res+1+args.elements), (char*) ((*argv)+1),
449
	   (*argc-1)*sizeof(char*));
450
  res[args.elements+ *argc]=0;			/* last null */
451
452
  (*argc)+=args.elements;
453
  *argv= (char**) res;
454
  *(MEM_ROOT*) ptr= alloc;			/* Save alloc root for free */
455
  delete_dynamic(&args);
456
  if (found_print_defaults)
457
  {
458
    int i;
459
    printf("%s would have been started with the following arguments:\n",
460
	   **argv);
461
    for (i=1 ; i < *argc ; i++)
462
      printf("%s ", (*argv)[i]);
463
    puts("");
464
    exit(0);
465
  }
51.3.22 by Jay Pipes
Final round of removal of DBUG in mysys/, including Makefile
466
  return(error);
1 by brian
clean slate
467
468
 err:
469
  fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
470
  exit(1);
471
  return 0;					/* Keep compiler happy */
472
}
473
474
475
void free_defaults(char **argv)
476
{
477
  MEM_ROOT ptr;
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
478
  memcpy((char*) &ptr,(char *) argv - sizeof(ptr), sizeof(ptr));
1 by brian
clean slate
479
  free_root(&ptr,MYF(0));
480
}
481
482
483
static int search_default_file(Process_option_func opt_handler,
484
                               void *handler_ctx,
485
			       const char *dir,
486
			       const char *config_file)
487
{
488
  char **ext;
489
  const char *empty_list[]= { "", 0 };
146 by Brian Aker
my_bool cleanup.
490
  bool have_ext= fn_ext(config_file)[0] != 0;
1 by brian
clean slate
491
  const char **exts_to_use= have_ext ? empty_list : f_extensions;
492
493
  for (ext= (char**) exts_to_use; *ext; ext++)
494
  {
495
    int error;
496
    if ((error= search_default_file_with_ext(opt_handler, handler_ctx,
497
                                             dir, *ext,
498
					     config_file, 0)) < 0)
499
      return error;
500
  }
501
  return 0;
502
}
503
504
505
/*
506
  Skip over keyword and get argument after keyword
507
508
  SYNOPSIS
509
   get_argument()
510
   keyword		Include directive keyword
511
   kwlen		Length of keyword
512
   ptr			Pointer to the keword in the line under process
513
   line			line number
514
515
  RETURN
516
   0	error
517
   #	Returns pointer to the argument after the keyword.
518
*/
519
520
static char *get_argument(const char *keyword, size_t kwlen,
521
                          char *ptr, char *name, uint line)
522
{
523
  char *end;
524
525
  /* Skip over "include / includedir keyword" and following whitespace */
526
527
  for (ptr+= kwlen - 1;
528
       my_isspace(&my_charset_latin1, ptr[0]);
529
       ptr++)
530
  {}
531
532
  /*
533
    Trim trailing whitespace from directory name
534
    The -1 below is for the newline added by fgets()
535
    Note that my_isspace() is true for \r and \n
536
  */
537
  for (end= ptr + strlen(ptr) - 1;
538
       my_isspace(&my_charset_latin1, *(end - 1));
539
       end--)
540
  {}
541
  end[0]= 0;                                    /* Cut off end space */
542
543
  /* Print error msg if there is nothing after !include* directive */
544
  if (end <= ptr)
545
  {
546
    fprintf(stderr,
547
	    "error: Wrong '!%s' directive in config file: %s at line %d\n",
548
	    keyword, name, line);
549
    return 0;
550
  }
551
  return ptr;
552
}
553
554
555
/*
556
  Open a configuration file (if exists) and read given options from it
557
558
  SYNOPSIS
559
    search_default_file_with_ext()
560
    opt_handler                 Option handler function. It is used to process
561
                                every separate option.
562
    handler_ctx                 Pointer to the structure to store actual 
563
                                parameters of the function.
564
    dir				directory to read
565
    ext				Extension for configuration file
566
    config_file                 Name of configuration file
567
    group			groups to read
568
    recursion_level             the level of recursion, got while processing
569
                                "!include" or "!includedir"
570
571
  RETURN
572
    0   Success
573
    -1	Fatal error, abort
574
     1	File not found (Warning)
575
*/
576
577
static int search_default_file_with_ext(Process_option_func opt_handler,
578
                                        void *handler_ctx,
579
                                        const char *dir,
580
                                        const char *ext,
581
                                        const char *config_file,
582
                                        int recursion_level)
583
{
584
  char name[FN_REFLEN + 10], buff[4096], curr_gr[4096], *ptr, *end, **tmp_ext;
585
  char *value, option[4096], tmp[FN_REFLEN];
586
  static const char includedir_keyword[]= "includedir";
587
  static const char include_keyword[]= "include";
588
  const int max_recursion_level= 10;
589
  FILE *fp;
590
  uint line=0;
146 by Brian Aker
my_bool cleanup.
591
  bool found_group=0;
1 by brian
clean slate
592
  uint i;
593
  MY_DIR *search_dir;
594
  FILEINFO *search_file;
595
596
  if ((dir ? strlen(dir) : 0 )+strlen(config_file) >= FN_REFLEN-3)
597
    return 0;					/* Ignore wrong paths */
598
  if (dir)
599
  {
600
    end=convert_dirname(name, dir, NullS);
601
    if (dir[0] == FN_HOMELIB)		/* Add . to filenames in home */
602
      *end++='.';
603
    strxmov(end,config_file,ext,NullS);
604
  }
605
  else
606
  {
607
    strmov(name,config_file);
608
  }
609
  fn_format(name,name,"","",4);
610
  {
15 by brian
Fix for stat, NETWARE removal
611
    struct stat stat_info;
612
    if (stat(name,&stat_info))
1 by brian
clean slate
613
      return 1;
614
    /*
615
      Ignore world-writable regular files.
616
      This is mainly done to protect us to not read a file created by
617
      the mysqld server, but the check is still valid in most context. 
618
    */
619
    if ((stat_info.st_mode & S_IWOTH) &&
620
	(stat_info.st_mode & S_IFMT) == S_IFREG)
621
    {
622
      fprintf(stderr, "Warning: World-writable config file '%s' is ignored\n",
623
              name);
624
      return 0;
625
    }
626
  }
627
  if (!(fp= my_fopen(name, O_RDONLY, MYF(0))))
628
    return 1;					/* Ignore wrong files */
629
630
  while (fgets(buff, sizeof(buff) - 1, fp))
631
  {
632
    line++;
633
    /* Ignore comment and empty lines */
634
    for (ptr= buff; my_isspace(&my_charset_latin1, *ptr); ptr++)
635
    {}
636
637
    if (*ptr == '#' || *ptr == ';' || !*ptr)
638
      continue;
639
640
    /* Configuration File Directives */
641
    if ((*ptr == '!'))
642
    {
643
      if (recursion_level >= max_recursion_level)
644
      {
645
        for (end= ptr + strlen(ptr) - 1; 
646
             my_isspace(&my_charset_latin1, *(end - 1));
647
             end--)
648
        {}
649
        end[0]= 0;
650
        fprintf(stderr,
651
                "Warning: skipping '%s' directive as maximum include"
652
                "recursion level was reached in file %s at line %d\n",
653
                ptr, name, line);
654
        continue;
655
      }
656
657
      /* skip over `!' and following whitespace */
658
      for (++ptr; my_isspace(&my_charset_latin1, ptr[0]); ptr++)
659
      {}
660
661
      if ((!strncmp(ptr, includedir_keyword,
662
                    sizeof(includedir_keyword) - 1)) &&
663
          my_isspace(&my_charset_latin1, ptr[sizeof(includedir_keyword) - 1]))
664
      {
665
	if (!(ptr= get_argument(includedir_keyword,
666
                                sizeof(includedir_keyword),
667
                                ptr, name, line)))
668
	  goto err;
669
670
        if (!(search_dir= my_dir(ptr, MYF(MY_WME))))
671
          goto err;
672
673
        for (i= 0; i < (uint) search_dir->number_off_files; i++)
674
        {
675
          search_file= search_dir->dir_entry + i;
676
          ext= fn_ext(search_file->name);
677
678
          /* check extension */
679
          for (tmp_ext= (char**) f_extensions; *tmp_ext; tmp_ext++)
680
          {
681
            if (!strcmp(ext, *tmp_ext))
682
              break;
683
          }
684
685
          if (*tmp_ext)
686
          {
687
            fn_format(tmp, search_file->name, ptr, "",
688
                      MY_UNPACK_FILENAME | MY_SAFE_PATH);
689
690
            search_default_file_with_ext(opt_handler, handler_ctx, "", "", tmp,
691
                                         recursion_level + 1);
692
          }
693
        }
694
695
        my_dirend(search_dir);
696
      }
697
      else if ((!strncmp(ptr, include_keyword, sizeof(include_keyword) - 1)) &&
698
               my_isspace(&my_charset_latin1, ptr[sizeof(include_keyword)-1]))
699
      {
700
	if (!(ptr= get_argument(include_keyword,
701
                                sizeof(include_keyword), ptr,
702
                                name, line)))
703
	  goto err;
704
705
        search_default_file_with_ext(opt_handler, handler_ctx, "", "", ptr,
706
                                     recursion_level + 1);
707
      }
708
709
      continue;
710
    }
711
712
    if (*ptr == '[')				/* Group name */
713
    {
714
      found_group=1;
715
      if (!(end=(char *) strchr(++ptr,']')))
716
      {
717
	fprintf(stderr,
718
		"error: Wrong group definition in config file: %s at line %d\n",
719
		name,line);
720
	goto err;
721
      }
722
      /* Remove end space */
723
      for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;
724
      end[0]=0;
725
726
      strmake(curr_gr, ptr, min((size_t) (end-ptr)+1, sizeof(curr_gr)-1));
727
728
      /* signal that a new group is found */
729
      opt_handler(handler_ctx, curr_gr, NULL);
730
731
      continue;
732
    }
733
    if (!found_group)
734
    {
735
      fprintf(stderr,
736
	      "error: Found option without preceding group in config file: %s at line: %d\n",
737
	      name,line);
738
      goto err;
739
    }
740
    
741
   
742
    end= remove_end_comment(ptr);
743
    if ((value= strchr(ptr, '=')))
744
      end= value;				/* Option without argument */
745
    for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;
746
    if (!value)
747
    {
748
      strmake(strmov(option,"--"),ptr, (size_t) (end-ptr));
749
      if (opt_handler(handler_ctx, curr_gr, option))
750
        goto err;
751
    }
752
    else
753
    {
754
      /* Remove pre- and end space */
755
      char *value_end;
756
      for (value++ ; my_isspace(&my_charset_latin1,*value); value++) ;
757
      value_end=strend(value);
758
      /*
759
	We don't have to test for value_end >= value as we know there is
760
	an '=' before
761
      */
762
      for ( ; my_isspace(&my_charset_latin1,value_end[-1]) ; value_end--) ;
763
      if (value_end < value)			/* Empty string */
764
	value_end=value;
765
766
      /* remove quotes around argument */
767
      if ((*value == '\"' || *value == '\'') && /* First char is quote */
768
          (value + 1 < value_end ) && /* String is longer than 1 */
769
          *value == value_end[-1] ) /* First char is equal to last char */
770
      {
771
	value++;
772
	value_end--;
773
      }
774
      ptr=strnmov(strmov(option,"--"),ptr,(size_t) (end-ptr));
775
      *ptr++= '=';
776
777
      for ( ; value != value_end; value++)
778
      {
779
	if (*value == '\\' && value != value_end-1)
780
	{
781
	  switch(*++value) {
782
	  case 'n':
783
	    *ptr++='\n';
784
	    break;
785
	  case 't':
786
	    *ptr++= '\t';
787
	    break;
788
	  case 'r':
789
	    *ptr++ = '\r';
790
	    break;
791
	  case 'b':
792
	    *ptr++ = '\b';
793
	    break;
794
	  case 's':
795
	    *ptr++= ' ';			/* space */
796
	    break;
797
	  case '\"':
798
	    *ptr++= '\"';
799
	    break;
800
	  case '\'':
801
	    *ptr++= '\'';
802
	    break;
803
	  case '\\':
804
	    *ptr++= '\\';
805
	    break;
806
	  default:				/* Unknown; Keep '\' */
807
	    *ptr++= '\\';
808
	    *ptr++= *value;
809
	    break;
810
	  }
811
	}
812
	else
813
	  *ptr++= *value;
814
      }
815
      *ptr=0;
816
      if (opt_handler(handler_ctx, curr_gr, option))
817
        goto err;
818
    }
819
  }
820
  my_fclose(fp,MYF(0));
821
  return(0);
822
823
 err:
824
  my_fclose(fp,MYF(0));
825
  return -1;					/* Fatal error */
826
}
827
828
829
static char *remove_end_comment(char *ptr)
830
{
831
  char quote= 0;	/* we are inside quote marks */
832
  char escape= 0;	/* symbol is protected by escape chagacter */
833
834
  for (; *ptr; ptr++)
835
  {
836
    if ((*ptr == '\'' || *ptr == '\"') && !escape)
837
    {
838
      if (!quote)
839
	quote= *ptr;
840
      else if (quote == *ptr)
841
	quote= 0;
842
    }
843
    /* We are not inside a string */
844
    if (!quote && *ptr == '#')
845
    {
846
      *ptr= 0;
847
      return ptr;
848
    }
849
    escape= (quote && *ptr == '\\' && !escape);
850
  }
851
  return ptr;
852
}
853
854
void my_print_default_files(const char *conf_file)
855
{
856
  const char *empty_list[]= { "", 0 };
146 by Brian Aker
my_bool cleanup.
857
  bool have_ext= fn_ext(conf_file)[0] != 0;
1 by brian
clean slate
858
  const char **exts_to_use= have_ext ? empty_list : f_extensions;
859
  char name[FN_REFLEN], **ext;
860
  const char **dirs;
861
862
  init_default_directories();
863
  puts("\nDefault options are read from the following files in the given order:");
864
865
  if (dirname_length(conf_file))
866
    fputs(conf_file,stdout);
867
  else
868
  {
869
    for (dirs=default_directories ; *dirs; dirs++)
870
    {
871
      for (ext= (char**) exts_to_use; *ext; ext++)
872
      {
873
	const char *pos;
874
	char *end;
875
	if (**dirs)
876
	  pos= *dirs;
877
	else if (my_defaults_extra_file)
878
	  pos= my_defaults_extra_file;
879
	else
880
	  continue;
881
	end= convert_dirname(name, pos, NullS);
882
	if (name[0] == FN_HOMELIB)	/* Add . to filenames in home */
883
	  *end++='.';
884
	strxmov(end, conf_file, *ext, " ", NullS);
885
	fputs(name,stdout);
886
      }
887
    }
888
  }
889
  puts("");
890
}
891
892
void print_defaults(const char *conf_file, const char **groups)
893
{
894
  const char **groups_save= groups;
895
  my_print_default_files(conf_file);
896
897
  fputs("The following groups are read:",stdout);
898
  for ( ; *groups ; groups++)
899
  {
900
    fputc(' ',stdout);
901
    fputs(*groups,stdout);
902
  }
903
904
  if (my_defaults_group_suffix)
905
  {
906
    groups= groups_save;
907
    for ( ; *groups ; groups++)
908
    {
909
      fputc(' ',stdout);
910
      fputs(*groups,stdout);
911
      fputs(my_defaults_group_suffix,stdout);
912
    }
913
  }
914
  puts("\nThe following options may be given as the first argument:\n\
915
--print-defaults	Print the program argument list and exit\n\
916
--no-defaults		Don't read default options from any options file\n\
917
--defaults-file=#	Only read default options from the given file #\n\
918
--defaults-extra-file=# Read this file after the global files are read");
919
}
920
921
/*
922
  This extra complexity is to avoid declaring 'rc' if it won't be
923
  used.
924
*/
51.3.22 by Jay Pipes
Final round of removal of DBUG in mysys/, including Makefile
925
#define ADD_DIRECTORY(DIR)  (void) array_append_string_unique((DIR), default_directories, \
1 by brian
clean slate
926
                             array_elements(default_directories))
927
928
#define ADD_COMMON_DIRECTORIES() \
929
  do { \
930
    char *env; \
931
    if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV)))) \
932
      ADD_DIRECTORY(env); \
933
    /* Placeholder for --defaults-extra-file=<path> */ \
934
    ADD_DIRECTORY(""); \
935
  } while (0)
936
937
938
/**
939
  Initialize default directories for Unix
940
941
  @details
942
    1. /etc/
943
    2. /etc/mysql/
944
    3. --sysconfdir=<path> (compile-time option)
945
    4. getenv(DEFAULT_HOME_ENV)
946
    5. --defaults-extra-file=<path> (run-time option)
947
    6. "~/"
948
*/
949
182.1.2 by Jim Winstead
Various fixes to enable compilation on Mac OS X, and remove the glib dependency.
950
static void init_default_directories(void)
1 by brian
clean slate
951
{
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
952
  memset((char *) default_directories, 0, sizeof(default_directories));
1 by brian
clean slate
953
  ADD_DIRECTORY("/etc/");
954
  ADD_DIRECTORY("/etc/mysql/");
53.2.19 by Monty Taylor
Fixed prototypes. Cleaned define a little bit.
955
#if defined(DEFAULT_SYSCONFDIR)
1 by brian
clean slate
956
    ADD_DIRECTORY(DEFAULT_SYSCONFDIR);
957
#endif
958
  ADD_COMMON_DIRECTORIES();
959
  ADD_DIRECTORY("~/");
960
}