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