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