~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>
612.2.6 by Monty Taylor
OpenSolaris builds.
39
#include <mysys/my_dir.h>
722.1.4 by Monty Taylor
Removed all the setting of DEFS everywhere. Use configmake.h to get the values
40
#include <drizzled/configmake.h>
612.2.6 by Monty Taylor
OpenSolaris builds.
41
42
#include <stdio.h>
1 by brian
clean slate
43
44
const char *my_defaults_file=0;
45
const char *my_defaults_group_suffix=0;
46
char *my_defaults_extra_file=0;
47
48
/* Which directories are searched for options (and in which order) */
49
50
#define MAX_DEFAULT_DIRS 6
51
const char *default_directories[MAX_DEFAULT_DIRS + 1];
52
53
static const char *f_extensions[]= { ".cnf", 0 };
54
632.1.11 by Monty Taylor
Fixed Sun Studio warnings in mysys.
55
int handle_default_option(void *in_ctx, const char *group_name,
56
                          const char *option);
1 by brian
clean slate
57
58
/*
59
   This structure defines the context that we pass to callback
60
   function 'handle_default_option' used in search_default_file
61
   to process each option. This context is used if search_default_file
62
   was called from load_defaults.
63
*/
64
65
struct handle_option_ctx
66
{
67
   MEM_ROOT *alloc;
68
   DYNAMIC_ARRAY *args;
69
   TYPELIB *group;
70
};
71
72
static int search_default_file(Process_option_func func, void *func_ctx,
73
			       const char *dir, const char *config_file);
74
static int search_default_file_with_ext(Process_option_func func,
75
                                        void *func_ctx,
76
					const char *dir, const char *ext,
77
					const char *config_file, int recursion_level);
78
79
80
81
/**
82
  Create the list of default directories.
83
84
  @details
85
  On all systems, if a directory is already in the list, it will be moved
86
  to the end of the list.  This avoids reading defaults files multiple times,
87
  while ensuring the correct precedence.
88
89
  @return void
90
*/
91
182.1.2 by Jim Winstead
Various fixes to enable compilation on Mac OS X, and remove the glib dependency.
92
static void init_default_directories(void);
1 by brian
clean slate
93
94
95
static char *remove_end_comment(char *ptr);
96
97
98
/*
99
  Process config files in default directories.
100
101
  SYNOPSIS
102
  my_search_option_files()
103
  conf_file                   Basename for configuration file to search for.
104
                              If this is a path, then only this file is read.
105
  argc                        Pointer to argc of original program
106
  argv                        Pointer to argv of original program
107
  args_used                   Pointer to variable for storing the number of
108
                              arguments used.
109
  func                        Pointer to the function to process options
110
  func_ctx                    It's context. Usually it is the structure to
111
                              store additional options.
112
  DESCRIPTION
113
    Process the default options from argc & argv
114
    Read through each found config file looks and calls 'func' to process
115
    each option.
116
117
  NOTES
118
    --defaults-group-suffix is only processed if we are called from
119
    load_defaults().
120
121
122
  RETURN
123
    0  ok
124
    1  given cinf_file doesn't exist
125
126
    The global variable 'my_defaults_group_suffix' is updated with value for
127
    --defaults_group_suffix
128
*/
129
130
int my_search_option_files(const char *conf_file, int *argc, char ***argv,
482 by Brian Aker
Remove uint.
131
                           uint32_t *args_used, Process_option_func func,
1 by brian
clean slate
132
                           void *func_ctx)
133
{
134
  const char **dirs, *forced_default_file, *forced_extra_defaults;
135
  int error= 0;
136
137
  /* Check if we want to force the use a specific default file */
138
  *args_used+= get_defaults_options(*argc - *args_used, *argv + *args_used,
139
                                    (char **) &forced_default_file,
140
                                    (char **) &forced_extra_defaults,
141
                                    (char **) &my_defaults_group_suffix);
142
143
  if (! my_defaults_group_suffix)
722.1.4 by Monty Taylor
Removed all the setting of DEFS everywhere. Use configmake.h to get the values
144
    my_defaults_group_suffix= getenv("DRIZZLE_GROUP_SUFFIX");
1 by brian
clean slate
145
146
  if (forced_extra_defaults)
147
    my_defaults_extra_file= (char *) forced_extra_defaults;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
148
1 by brian
clean slate
149
  if (forced_default_file)
150
    my_defaults_file= forced_default_file;
151
152
  /*
153
    We can only handle 'defaults-group-suffix' if we are called from
154
    load_defaults() as otherwise we can't know the type of 'func_ctx'
155
  */
156
632.1.11 by Monty Taylor
Fixed Sun Studio warnings in mysys.
157
  if (my_defaults_group_suffix && (func == handle_default_option))
1 by brian
clean slate
158
  {
159
    /* Handle --defaults-group-suffix= */
482 by Brian Aker
Remove uint.
160
    uint32_t i;
1 by brian
clean slate
161
    const char **extra_groups;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
162
    const uint32_t instance_len= strlen(my_defaults_group_suffix);
1 by brian
clean slate
163
    struct handle_option_ctx *ctx= (struct handle_option_ctx*) func_ctx;
164
    char *ptr;
165
    TYPELIB *group= ctx->group;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
166
167
    if (!(extra_groups=
1 by brian
clean slate
168
	  (const char**)alloc_root(ctx->alloc,
169
                                   (2*group->count+1)*sizeof(char*))))
170
      goto err;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
171
1 by brian
clean slate
172
    for (i= 0; i < group->count; i++)
173
    {
482 by Brian Aker
Remove uint.
174
      uint32_t len;
1 by brian
clean slate
175
      extra_groups[i]= group->type_names[i]; /** copy group */
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
176
1 by brian
clean slate
177
      len= strlen(extra_groups[i]);
575.3.1 by Monty Taylor
Made mysys and mystrings c++. Fixed the resulting bugs the compiler found.
178
      if (!(ptr= (char *)alloc_root(ctx->alloc, len+instance_len+1)))
1 by brian
clean slate
179
	goto err;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
180
1 by brian
clean slate
181
      extra_groups[i+group->count]= ptr;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
182
1 by brian
clean slate
183
      /** Construct new group */
184
      memcpy(ptr, extra_groups[i], len);
185
      memcpy(ptr+len, my_defaults_group_suffix, instance_len+1);
186
    }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
187
1 by brian
clean slate
188
    group->count*= 2;
189
    group->type_names= extra_groups;
190
    group->type_names[group->count]= 0;
191
  }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
192
1 by brian
clean slate
193
  if (forced_default_file)
194
  {
195
    if ((error= search_default_file_with_ext(func, func_ctx, "", "",
196
                                             forced_default_file, 0)) < 0)
197
      goto err;
198
    if (error > 0)
199
    {
200
      fprintf(stderr, "Could not open required defaults file: %s\n",
201
              forced_default_file);
202
      goto err;
203
    }
204
  }
205
  else if (dirname_length(conf_file))
206
  {
461 by Monty Taylor
Removed NullS. bu-bye.
207
    if ((error= search_default_file(func, func_ctx, NULL, conf_file)) < 0)
1 by brian
clean slate
208
      goto err;
209
  }
210
  else
211
  {
212
    for (dirs= default_directories ; *dirs; dirs++)
213
    {
214
      if (**dirs)
215
      {
216
	if (search_default_file(func, func_ctx, *dirs, conf_file) < 0)
217
	  goto err;
218
      }
219
      else if (my_defaults_extra_file)
220
      {
221
        if ((error= search_default_file_with_ext(func, func_ctx, "", "",
222
                                                my_defaults_extra_file, 0)) < 0)
223
	  goto err;				/* Fatal error */
224
        if (error > 0)
225
        {
226
          fprintf(stderr, "Could not open required defaults file: %s\n",
227
                  my_defaults_extra_file);
228
          goto err;
229
        }
230
      }
231
    }
232
  }
233
51.3.22 by Jay Pipes
Final round of removal of DBUG in mysys/, including Makefile
234
  return(error);
1 by brian
clean slate
235
236
err:
237
  fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
238
  exit(1);
239
}
240
241
242
/*
243
  The option handler for load_defaults.
244
245
  SYNOPSIS
246
    handle_deault_option()
247
    in_ctx                  Handler context. In this case it is a
248
                            handle_option_ctx structure.
249
    group_name              The name of the group the option belongs to.
250
    option                  The very option to be processed. It is already
251
                            prepared to be used in argv (has -- prefix). If it
252
                            is NULL, we are handling a new group (section).
253
254
  DESCRIPTION
255
    This handler checks whether a group is one of the listed and adds an option
256
    to the array if yes. Some other handler can record, for instance, all
257
    groups and their options, not knowing in advance the names and amount of
258
    groups.
259
260
  RETURN
261
    0 - ok
262
    1 - error occured
263
*/
264
632.1.11 by Monty Taylor
Fixed Sun Studio warnings in mysys.
265
int handle_default_option(void *in_ctx, const char *group_name,
266
                          const char *option)
1 by brian
clean slate
267
{
268
  char *tmp;
269
  struct handle_option_ctx *ctx= (struct handle_option_ctx *) in_ctx;
270
271
  if (!option)
272
    return 0;
273
274
  if (find_type((char *)group_name, ctx->group, 3))
275
  {
575.3.1 by Monty Taylor
Made mysys and mystrings c++. Fixed the resulting bugs the compiler found.
276
    if (!(tmp= (char *)alloc_root(ctx->alloc, strlen(option) + 1)))
1 by brian
clean slate
277
      return 1;
481 by Brian Aker
Remove all of uchar.
278
    if (insert_dynamic(ctx->args, (unsigned char*) &tmp))
1 by brian
clean slate
279
      return 1;
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
280
    strcpy(tmp, option);
1 by brian
clean slate
281
  }
282
283
  return 0;
284
}
285
286
287
/*
288
  Gets options from the command line
289
290
  SYNOPSIS
291
    get_defaults_options()
292
    argc			Pointer to argc of original program
293
    argv			Pointer to argv of original program
294
    defaults                    --defaults-file option
295
    extra_defaults              --defaults-extra-file option
296
297
  RETURN
298
    # Number of arguments used from *argv
299
      defaults and extra_defaults will be set to option of the appropriate
300
      items of argv array, or to NULL if there are no such options
301
*/
302
303
int get_defaults_options(int argc, char **argv,
304
                         char **defaults,
305
                         char **extra_defaults,
306
                         char **group_suffix)
307
{
308
  int org_argc= argc, prev_argc= 0;
309
  *defaults= *extra_defaults= *group_suffix= 0;
310
311
  while (argc >= 2 && argc != prev_argc)
312
  {
313
    /* Skip program name or previously handled argument */
314
    argv++;
315
    prev_argc= argc;                            /* To check if we found */
316
    if (!*defaults && is_prefix(*argv,"--defaults-file="))
317
    {
318
      *defaults= *argv + sizeof("--defaults-file=")-1;
319
       argc--;
320
       continue;
321
    }
322
    if (!*extra_defaults && is_prefix(*argv,"--defaults-extra-file="))
323
    {
324
      *extra_defaults= *argv + sizeof("--defaults-extra-file=")-1;
325
      argc--;
326
      continue;
327
    }
328
    if (!*group_suffix && is_prefix(*argv, "--defaults-group-suffix="))
329
    {
330
      *group_suffix= *argv + sizeof("--defaults-group-suffix=")-1;
331
      argc--;
332
      continue;
333
    }
334
  }
335
  return org_argc - argc;
336
}
337
338
339
/*
340
  Read options from configurations files
341
342
  SYNOPSIS
343
    load_defaults()
344
    conf_file			Basename for configuration file to search for.
345
    				If this is a path, then only this file is read.
346
    groups			Which [group] entrys to read.
347
				Points to an null terminated array of pointers
348
    argc			Pointer to argc of original program
349
    argv			Pointer to argv of original program
350
351
  IMPLEMENTATION
352
353
   Read options from configuration files and put them BEFORE the arguments
354
   that are already in argc and argv.  This way the calling program can
355
   easily command line options override options in configuration files
356
357
   NOTES
358
    In case of fatal error, the function will print a warning and do
359
    exit(1)
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
360
1 by brian
clean slate
361
    To free used memory one should call free_defaults() with the argument
362
    that was put in *argv
363
364
   RETURN
365
     0	ok
366
     1	The given conf_file didn't exists
367
*/
368
369
370
int load_defaults(const char *conf_file, const char **groups,
371
                  int *argc, char ***argv)
372
{
373
  DYNAMIC_ARRAY args;
374
  TYPELIB group;
146 by Brian Aker
my_bool cleanup.
375
  bool found_print_defaults= 0;
482 by Brian Aker
Remove uint.
376
  uint32_t args_used= 0;
1 by brian
clean slate
377
  int error= 0;
378
  MEM_ROOT alloc;
379
  char *ptr,**res;
380
  struct handle_option_ctx ctx;
381
382
  init_default_directories();
383
  init_alloc_root(&alloc,512,0);
384
  /*
385
    Check if the user doesn't want any default option processing
386
    --no-defaults is always the first option
387
  */
388
  if (*argc >= 2 && !strcmp(argv[0][1],"--no-defaults"))
389
  {
390
    /* remove the --no-defaults argument and return only the other arguments */
482 by Brian Aker
Remove uint.
391
    uint32_t i;
1 by brian
clean slate
392
    if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
393
				 (*argc + 1)*sizeof(char*))))
394
      goto err;
395
    res= (char**) (ptr+sizeof(alloc));
896.1.2 by Monty Taylor
Ugly null-termination problem.
396
    memset(res,0,(*argc + 1));
1 by brian
clean slate
397
    res[0]= **argv;				/* Copy program name */
895 by Brian Aker
Completion (?) of uint conversion.
398
    for (i=2 ; i < (uint32_t) *argc ; i++)
1 by brian
clean slate
399
      res[i-1]=argv[0][i];
400
    res[i-1]=0;					/* End pointer */
401
    (*argc)--;
402
    *argv=res;
403
    *(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
404
    return(0);
1 by brian
clean slate
405
  }
406
407
  group.count=0;
408
  group.name= "defaults";
409
  group.type_names= groups;
410
411
  for (; *groups ; groups++)
412
    group.count++;
413
414
  if (my_init_dynamic_array(&args, sizeof(char*),*argc, 32))
415
    goto err;
416
417
  ctx.alloc= &alloc;
418
  ctx.args= &args;
419
  ctx.group= &group;
420
421
  error= my_search_option_files(conf_file, argc, argv, &args_used,
422
                                handle_default_option, (void *) &ctx);
423
  /*
424
    Here error contains <> 0 only if we have a fully specified conf_file
425
    or a forced default file
426
  */
427
  if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
428
			       (args.elements + *argc +1) *sizeof(char*))))
429
    goto err;
430
  res= (char**) (ptr+sizeof(alloc));
431
432
  /* copy name + found arguments + command line arguments to new array */
433
  res[0]= argv[0][0];  /* Name MUST be set, even by embedded library */
212.6.14 by Mats Kindahl
Removing redundant use of casts in mysys for memcmp(), memcpy(), memset(), and memmove().
434
  memcpy(res+1, args.buffer, args.elements*sizeof(char*));
1 by brian
clean slate
435
  /* Skip --defaults-xxx options */
436
  (*argc)-= args_used;
437
  (*argv)+= args_used;
438
439
  /*
440
    Check if we wan't to see the new argument list
441
    This options must always be the last of the default options
442
  */
443
  if (*argc >= 2 && !strcmp(argv[0][1],"--print-defaults"))
444
  {
445
    found_print_defaults=1;
446
    --*argc; ++*argv;				/* skip argument */
447
  }
448
449
  if (*argc)
212.6.14 by Mats Kindahl
Removing redundant use of casts in mysys for memcmp(), memcpy(), memset(), and memmove().
450
    memcpy(res+1+args.elements, *argv + 1, (*argc-1)*sizeof(char*));
1 by brian
clean slate
451
  res[args.elements+ *argc]=0;			/* last null */
452
453
  (*argc)+=args.elements;
454
  *argv= (char**) res;
455
  *(MEM_ROOT*) ptr= alloc;			/* Save alloc root for free */
456
  delete_dynamic(&args);
457
  if (found_print_defaults)
458
  {
459
    int i;
460
    printf("%s would have been started with the following arguments:\n",
461
	   **argv);
462
    for (i=1 ; i < *argc ; i++)
463
      printf("%s ", (*argv)[i]);
464
    puts("");
465
    exit(0);
466
  }
51.3.22 by Jay Pipes
Final round of removal of DBUG in mysys/, including Makefile
467
  return(error);
1 by brian
clean slate
468
469
 err:
470
  fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
471
  exit(1);
472
}
473
474
475
void free_defaults(char **argv)
476
{
477
  MEM_ROOT ptr;
212.6.14 by Mats Kindahl
Removing redundant use of casts in mysys for memcmp(), memcpy(), memset(), and memmove().
478
  memcpy(&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,
482 by Brian Aker
Remove uint.
521
                          char *ptr, char *name, uint32_t line)
1 by brian
clean slate
522
{
523
  char *end;
524
525
  /* Skip over "include / includedir keyword" and following whitespace */
526
527
  for (ptr+= kwlen - 1;
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
528
       my_isspace(&my_charset_utf8_general_ci, ptr[0]);
1 by brian
clean slate
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;
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
538
       my_isspace(&my_charset_utf8_general_ci, *(end - 1));
1 by brian
clean slate
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.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
562
    handler_ctx                 Pointer to the structure to store actual
1 by brian
clean slate
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;
482 by Brian Aker
Remove uint.
590
  uint32_t line=0;
146 by Brian Aker
my_bool cleanup.
591
  bool found_group=0;
482 by Brian Aker
Remove uint.
592
  uint32_t i;
1 by brian
clean slate
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
  {
461 by Monty Taylor
Removed NullS. bu-bye.
600
    end=convert_dirname(name, dir, NULL);
1 by brian
clean slate
601
    if (dir[0] == FN_HOMELIB)		/* Add . to filenames in home */
602
      *end++='.';
673.2.1 by Toru Maesaka
First pass of replacing MySQL's strxmov with libc alternatives
603
    sprintf(end,"%s%s",config_file,ext);
1 by brian
clean slate
604
  }
605
  else
606
  {
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
607
    strcpy(name,config_file);
1 by brian
clean slate
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
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
617
      the mysqld server, but the check is still valid in most context.
1 by brian
clean slate
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
  }
910.1.3 by Brian Aker
Remove my_fopen() and key_map.cc file (thanks to Jay's lcov)
627
  if (!(fp= fopen(name, "r")))
1 by brian
clean slate
628
    return 1;					/* Ignore wrong files */
629
896.1.2 by Monty Taylor
Ugly null-termination problem.
630
  memset(buff,0,sizeof(buff));
1 by brian
clean slate
631
  while (fgets(buff, sizeof(buff) - 1, fp))
632
  {
633
    line++;
634
    /* Ignore comment and empty lines */
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
635
    for (ptr= buff; my_isspace(&my_charset_utf8_general_ci, *ptr); ptr++)
1 by brian
clean slate
636
    {}
637
638
    if (*ptr == '#' || *ptr == ';' || !*ptr)
639
      continue;
640
641
    /* Configuration File Directives */
642
    if ((*ptr == '!'))
643
    {
644
      if (recursion_level >= max_recursion_level)
645
      {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
646
        for (end= ptr + strlen(ptr) - 1;
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
647
             my_isspace(&my_charset_utf8_general_ci, *(end - 1));
1 by brian
clean slate
648
             end--)
649
        {}
650
        end[0]= 0;
651
        fprintf(stderr,
652
                "Warning: skipping '%s' directive as maximum include"
653
                "recursion level was reached in file %s at line %d\n",
654
                ptr, name, line);
655
        continue;
656
      }
657
658
      /* skip over `!' and following whitespace */
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
659
      for (++ptr; my_isspace(&my_charset_utf8_general_ci, ptr[0]); ptr++)
1 by brian
clean slate
660
      {}
661
662
      if ((!strncmp(ptr, includedir_keyword,
663
                    sizeof(includedir_keyword) - 1)) &&
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
664
          my_isspace(&my_charset_utf8_general_ci, ptr[sizeof(includedir_keyword) - 1]))
1 by brian
clean slate
665
      {
666
	if (!(ptr= get_argument(includedir_keyword,
667
                                sizeof(includedir_keyword),
668
                                ptr, name, line)))
669
	  goto err;
670
671
        if (!(search_dir= my_dir(ptr, MYF(MY_WME))))
672
          goto err;
673
895 by Brian Aker
Completion (?) of uint conversion.
674
        for (i= 0; i < (uint32_t) search_dir->number_off_files; i++)
1 by brian
clean slate
675
        {
676
          search_file= search_dir->dir_entry + i;
677
          ext= fn_ext(search_file->name);
678
679
          /* check extension */
680
          for (tmp_ext= (char**) f_extensions; *tmp_ext; tmp_ext++)
681
          {
682
            if (!strcmp(ext, *tmp_ext))
683
              break;
684
          }
685
686
          if (*tmp_ext)
687
          {
688
            fn_format(tmp, search_file->name, ptr, "",
689
                      MY_UNPACK_FILENAME | MY_SAFE_PATH);
690
691
            search_default_file_with_ext(opt_handler, handler_ctx, "", "", tmp,
692
                                         recursion_level + 1);
693
          }
694
        }
695
696
        my_dirend(search_dir);
697
      }
698
      else if ((!strncmp(ptr, include_keyword, sizeof(include_keyword) - 1)) &&
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
699
               my_isspace(&my_charset_utf8_general_ci, ptr[sizeof(include_keyword)-1]))
1 by brian
clean slate
700
      {
701
	if (!(ptr= get_argument(include_keyword,
702
                                sizeof(include_keyword), ptr,
703
                                name, line)))
704
	  goto err;
705
706
        search_default_file_with_ext(opt_handler, handler_ctx, "", "", ptr,
707
                                     recursion_level + 1);
708
      }
709
710
      continue;
711
    }
712
713
    if (*ptr == '[')				/* Group name */
714
    {
715
      found_group=1;
716
      if (!(end=(char *) strchr(++ptr,']')))
717
      {
718
	fprintf(stderr,
719
		"error: Wrong group definition in config file: %s at line %d\n",
720
		name,line);
721
	goto err;
722
      }
723
      /* Remove end space */
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
724
      for ( ; my_isspace(&my_charset_utf8_general_ci,end[-1]) ; end--) ;
1 by brian
clean slate
725
      end[0]=0;
726
629.5.2 by Toru Maesaka
Second pass of replacing MySQL's strmake() with libc calls
727
      strncpy(curr_gr, ptr, cmin((size_t) (end-ptr)+1, sizeof(curr_gr)-1));
728
      curr_gr[cmin((size_t)(end-ptr)+1, sizeof(curr_gr)-1)] = '\0';
1 by brian
clean slate
729
730
      /* signal that a new group is found */
731
      opt_handler(handler_ctx, curr_gr, NULL);
732
733
      continue;
734
    }
735
    if (!found_group)
736
    {
737
      fprintf(stderr,
738
	      "error: Found option without preceding group in config file: %s at line: %d\n",
739
	      name,line);
740
      goto err;
741
    }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
742
743
1 by brian
clean slate
744
    end= remove_end_comment(ptr);
745
    if ((value= strchr(ptr, '=')))
746
      end= value;				/* Option without argument */
896.1.2 by Monty Taylor
Ugly null-termination problem.
747
    for ( ; my_isspace(&my_charset_utf8_general_ci,end[-1]) || end[-1]== '\n'; end--) ;
1 by brian
clean slate
748
    if (!value)
749
    {
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
750
      strncpy(strcpy(option,"--")+2,ptr,strlen(ptr)+1);
1 by brian
clean slate
751
      if (opt_handler(handler_ctx, curr_gr, option))
752
        goto err;
753
    }
754
    else
755
    {
756
      /* Remove pre- and end space */
757
      char *value_end;
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
758
      for (value++ ; my_isspace(&my_charset_utf8_general_ci,*value); value++) ;
376 by Brian Aker
strend remove
759
      value_end= strchr(value, '\0');
1 by brian
clean slate
760
      /*
670.3.1 by Toru Maesaka
Replaced MySQL's my_stpncpy() with libc and c++ calls
761
       We don't have to test for value_end >= value as we know there is
762
       an '=' before
1 by brian
clean slate
763
      */
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
764
      for ( ; my_isspace(&my_charset_utf8_general_ci,value_end[-1]) ; value_end--) ;
1 by brian
clean slate
765
      if (value_end < value)			/* Empty string */
670.3.1 by Toru Maesaka
Replaced MySQL's my_stpncpy() with libc and c++ calls
766
        value_end=value;
1 by brian
clean slate
767
768
      /* remove quotes around argument */
769
      if ((*value == '\"' || *value == '\'') && /* First char is quote */
770
          (value + 1 < value_end ) && /* String is longer than 1 */
771
          *value == value_end[-1] ) /* First char is equal to last char */
772
      {
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
773
        value++;
774
        value_end--;
1 by brian
clean slate
775
      }
896.1.2 by Monty Taylor
Ugly null-termination problem.
776
      
777
      memset(option,0,2+(size_t)(end-ptr)+1);
670.3.1 by Toru Maesaka
Replaced MySQL's my_stpncpy() with libc and c++ calls
778
      ptr= strncpy(strcpy(option,"--")+2,ptr,(size_t) (end-ptr));
896.1.2 by Monty Taylor
Ugly null-termination problem.
779
      ptr[end-ptr]= '\0';
670.3.1 by Toru Maesaka
Replaced MySQL's my_stpncpy() with libc and c++ calls
780
      ptr+= strlen(ptr);
1 by brian
clean slate
781
      *ptr++= '=';
782
783
      for ( ; value != value_end; value++)
784
      {
785
	if (*value == '\\' && value != value_end-1)
786
	{
787
	  switch(*++value) {
788
	  case 'n':
789
	    *ptr++='\n';
790
	    break;
791
	  case 't':
792
	    *ptr++= '\t';
793
	    break;
794
	  case 'r':
795
	    *ptr++ = '\r';
796
	    break;
797
	  case 'b':
798
	    *ptr++ = '\b';
799
	    break;
800
	  case 's':
801
	    *ptr++= ' ';			/* space */
802
	    break;
803
	  case '\"':
804
	    *ptr++= '\"';
805
	    break;
806
	  case '\'':
807
	    *ptr++= '\'';
808
	    break;
809
	  case '\\':
810
	    *ptr++= '\\';
811
	    break;
812
	  default:				/* Unknown; Keep '\' */
813
	    *ptr++= '\\';
814
	    *ptr++= *value;
815
	    break;
816
	  }
817
	}
818
	else
819
	  *ptr++= *value;
820
      }
821
      *ptr=0;
822
      if (opt_handler(handler_ctx, curr_gr, option))
823
        goto err;
824
    }
825
  }
910.1.3 by Brian Aker
Remove my_fopen() and key_map.cc file (thanks to Jay's lcov)
826
  fclose(fp);
1 by brian
clean slate
827
  return(0);
828
829
 err:
910.1.3 by Brian Aker
Remove my_fopen() and key_map.cc file (thanks to Jay's lcov)
830
  fclose(fp);
831
1 by brian
clean slate
832
  return -1;					/* Fatal error */
833
}
834
835
836
static char *remove_end_comment(char *ptr)
837
{
838
  char quote= 0;	/* we are inside quote marks */
839
  char escape= 0;	/* symbol is protected by escape chagacter */
840
841
  for (; *ptr; ptr++)
842
  {
843
    if ((*ptr == '\'' || *ptr == '\"') && !escape)
844
    {
845
      if (!quote)
846
	quote= *ptr;
847
      else if (quote == *ptr)
848
	quote= 0;
849
    }
850
    /* We are not inside a string */
851
    if (!quote && *ptr == '#')
852
    {
853
      *ptr= 0;
854
      return ptr;
855
    }
856
    escape= (quote && *ptr == '\\' && !escape);
857
  }
858
  return ptr;
859
}
860
861
void my_print_default_files(const char *conf_file)
862
{
863
  const char *empty_list[]= { "", 0 };
146 by Brian Aker
my_bool cleanup.
864
  bool have_ext= fn_ext(conf_file)[0] != 0;
1 by brian
clean slate
865
  const char **exts_to_use= have_ext ? empty_list : f_extensions;
866
  char name[FN_REFLEN], **ext;
867
  const char **dirs;
868
869
  init_default_directories();
870
  puts("\nDefault options are read from the following files in the given order:");
871
872
  if (dirname_length(conf_file))
873
    fputs(conf_file,stdout);
874
  else
875
  {
876
    for (dirs=default_directories ; *dirs; dirs++)
877
    {
878
      for (ext= (char**) exts_to_use; *ext; ext++)
879
      {
880
	const char *pos;
881
	char *end;
882
	if (**dirs)
883
	  pos= *dirs;
884
	else if (my_defaults_extra_file)
885
	  pos= my_defaults_extra_file;
886
	else
887
	  continue;
461 by Monty Taylor
Removed NullS. bu-bye.
888
	end= convert_dirname(name, pos, NULL);
1 by brian
clean slate
889
	if (name[0] == FN_HOMELIB)	/* Add . to filenames in home */
890
	  *end++='.';
673.2.1 by Toru Maesaka
First pass of replacing MySQL's strxmov with libc alternatives
891
  sprintf(end,"%s%s ",conf_file, *ext);
1 by brian
clean slate
892
	fputs(name,stdout);
893
      }
894
    }
895
  }
896
  puts("");
897
}
898
899
void print_defaults(const char *conf_file, const char **groups)
900
{
901
  const char **groups_save= groups;
902
  my_print_default_files(conf_file);
903
904
  fputs("The following groups are read:",stdout);
905
  for ( ; *groups ; groups++)
906
  {
907
    fputc(' ',stdout);
908
    fputs(*groups,stdout);
909
  }
910
911
  if (my_defaults_group_suffix)
912
  {
913
    groups= groups_save;
914
    for ( ; *groups ; groups++)
915
    {
916
      fputc(' ',stdout);
917
      fputs(*groups,stdout);
918
      fputs(my_defaults_group_suffix,stdout);
919
    }
920
  }
921
  puts("\nThe following options may be given as the first argument:\n\
922
--print-defaults	Print the program argument list and exit\n\
923
--no-defaults		Don't read default options from any options file\n\
924
--defaults-file=#	Only read default options from the given file #\n\
925
--defaults-extra-file=# Read this file after the global files are read");
926
}
927
928
/*
929
  This extra complexity is to avoid declaring 'rc' if it won't be
930
  used.
931
*/
51.3.22 by Jay Pipes
Final round of removal of DBUG in mysys/, including Makefile
932
#define ADD_DIRECTORY(DIR)  (void) array_append_string_unique((DIR), default_directories, \
1 by brian
clean slate
933
                             array_elements(default_directories))
934
935
#define ADD_COMMON_DIRECTORIES() \
936
  do { \
722.1.4 by Monty Taylor
Removed all the setting of DEFS everywhere. Use configmake.h to get the values
937
    const char *env; \
938
    if ((env= getenv("DRIZZLE_HOME"))) \
1 by brian
clean slate
939
      ADD_DIRECTORY(env); \
940
    /* Placeholder for --defaults-extra-file=<path> */ \
941
    ADD_DIRECTORY(""); \
942
  } while (0)
943
944
945
/**
946
  Initialize default directories for Unix
947
948
  @details
949
    1. /etc/
520.4.28 by Monty Taylor
Changed my.cnf to drizzle.cnf and /etc/mysql to /etc/drizzle.
950
    2. /etc/drizzle/
1 by brian
clean slate
951
    3. --sysconfdir=<path> (compile-time option)
722.1.4 by Monty Taylor
Removed all the setting of DEFS everywhere. Use configmake.h to get the values
952
    4. getenv("DRIZZLE_HOME")
1 by brian
clean slate
953
    5. --defaults-extra-file=<path> (run-time option)
954
    6. "~/"
955
*/
956
182.1.2 by Jim Winstead
Various fixes to enable compilation on Mac OS X, and remove the glib dependency.
957
static void init_default_directories(void)
1 by brian
clean slate
958
{
212.6.14 by Mats Kindahl
Removing redundant use of casts in mysys for memcmp(), memcpy(), memset(), and memmove().
959
  memset(default_directories, 0, sizeof(default_directories));
1 by brian
clean slate
960
  ADD_DIRECTORY("/etc/");
520.4.28 by Monty Taylor
Changed my.cnf to drizzle.cnf and /etc/mysql to /etc/drizzle.
961
  ADD_DIRECTORY("/etc/drizzle/");
722.1.4 by Monty Taylor
Removed all the setting of DEFS everywhere. Use configmake.h to get the values
962
  ADD_DIRECTORY(SYSCONFDIR);
1 by brian
clean slate
963
  ADD_COMMON_DIRECTORIES();
964
  ADD_DIRECTORY("~/");
965
}