~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
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
1 by brian
clean slate
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;
482 by Brian Aker
Remove uint.
402
  uint32_t args_used= 0;
1 by brian
clean slate
403
  int error= 0;
1485 by Brian Aker
Updates to confine memroot
404
  memory::Root alloc(512);
1 by brian
clean slate
405
  char *ptr,**res;
406
  struct handle_option_ctx ctx;
407
408
  init_default_directories();
409
  /*
410
    Check if the user doesn't want any default option processing
411
    --no-defaults is always the first option
412
  */
413
  if (*argc >= 2 && !strcmp(argv[0][1],"--no-defaults"))
414
  {
415
    /* remove the --no-defaults argument and return only the other arguments */
482 by Brian Aker
Remove uint.
416
    uint32_t i;
1485 by Brian Aker
Updates to confine memroot
417
    if (!(ptr=(char*) alloc.alloc_root(sizeof(alloc)+ (*argc + 1)*sizeof(char*))))
1 by brian
clean slate
418
      goto err;
419
    res= (char**) (ptr+sizeof(alloc));
896.1.2 by Monty Taylor
Ugly null-termination problem.
420
    memset(res,0,(*argc + 1));
1 by brian
clean slate
421
    res[0]= **argv;				/* Copy program name */
895 by Brian Aker
Completion (?) of uint conversion.
422
    for (i=2 ; i < (uint32_t) *argc ; i++)
1 by brian
clean slate
423
      res[i-1]=argv[0][i];
424
    res[i-1]=0;					/* End pointer */
425
    (*argc)--;
426
    *argv=res;
1253.1.3 by Monty Taylor
MEM_ROOT == memory::Root
427
    *(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
428
    return(0);
1 by brian
clean slate
429
  }
430
431
  group.count=0;
432
  group.name= "defaults";
433
  group.type_names= groups;
434
435
  for (; *groups ; groups++)
436
    group.count++;
437
438
  if (my_init_dynamic_array(&args, sizeof(char*),*argc, 32))
439
    goto err;
440
441
  ctx.alloc= &alloc;
442
  ctx.args= &args;
443
  ctx.group= &group;
444
445
  error= my_search_option_files(conf_file, argc, argv, &args_used,
446
                                handle_default_option, (void *) &ctx);
447
  /*
448
    Here error contains <> 0 only if we have a fully specified conf_file
449
    or a forced default file
450
  */
1485 by Brian Aker
Updates to confine memroot
451
  if (!(ptr=(char*) alloc.alloc_root(sizeof(alloc)+ (args.elements + *argc +1) *sizeof(char*))))
1 by brian
clean slate
452
    goto err;
453
  res= (char**) (ptr+sizeof(alloc));
454
455
  /* copy name + found arguments + command line arguments to new array */
456
  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().
457
  memcpy(res+1, args.buffer, args.elements*sizeof(char*));
1 by brian
clean slate
458
  /* Skip --defaults-xxx options */
459
  (*argc)-= args_used;
460
  (*argv)+= args_used;
461
462
  /*
463
    Check if we wan't to see the new argument list
464
    This options must always be the last of the default options
465
  */
466
  if (*argc)
212.6.14 by Mats Kindahl
Removing redundant use of casts in mysys for memcmp(), memcpy(), memset(), and memmove().
467
    memcpy(res+1+args.elements, *argv + 1, (*argc-1)*sizeof(char*));
1 by brian
clean slate
468
  res[args.elements+ *argc]=0;			/* last null */
469
1090.4.2 by Monty Taylor
Some changes that I lost...
470
  (*argc)+=int(args.elements);
471
  *argv= static_cast<char**>(res);
1253.1.3 by Monty Taylor
MEM_ROOT == memory::Root
472
  *(memory::Root*) ptr= alloc;			/* Save alloc root for free */
1 by brian
clean slate
473
  delete_dynamic(&args);
1743.3.2 by LinuxJedi
Make --print-defaults ack as old behaviour for the defaults list at the end of --help because this is still needed in drizzled for dtr. Killing 2 birds with one stone.
474
51.3.22 by Jay Pipes
Final round of removal of DBUG in mysys/, including Makefile
475
  return(error);
1 by brian
clean slate
476
477
 err:
478
  fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
479
  exit(1);
480
}
481
482
483
void free_defaults(char **argv)
484
{
1253.1.3 by Monty Taylor
MEM_ROOT == memory::Root
485
  memory::Root ptr;
212.6.14 by Mats Kindahl
Removing redundant use of casts in mysys for memcmp(), memcpy(), memset(), and memmove().
486
  memcpy(&ptr, (char*) argv - sizeof(ptr), sizeof(ptr));
1487 by Brian Aker
More updates for memory::Root
487
  ptr.free_root(MYF(0));
1 by brian
clean slate
488
}
489
490
491
static int search_default_file(Process_option_func opt_handler,
492
                               void *handler_ctx,
493
			       const char *dir,
494
			       const char *config_file)
495
{
496
  char **ext;
497
  const char *empty_list[]= { "", 0 };
146 by Brian Aker
my_bool cleanup.
498
  bool have_ext= fn_ext(config_file)[0] != 0;
1 by brian
clean slate
499
  const char **exts_to_use= have_ext ? empty_list : f_extensions;
500
501
  for (ext= (char**) exts_to_use; *ext; ext++)
502
  {
503
    int error;
504
    if ((error= search_default_file_with_ext(opt_handler, handler_ctx,
505
                                             dir, *ext,
506
					     config_file, 0)) < 0)
507
      return error;
508
  }
509
  return 0;
510
}
511
512
513
/*
514
  Skip over keyword and get argument after keyword
515
516
  SYNOPSIS
517
   get_argument()
518
   keyword		Include directive keyword
519
   kwlen		Length of keyword
520
   ptr			Pointer to the keword in the line under process
521
   line			line number
522
523
  RETURN
524
   0	error
525
   #	Returns pointer to the argument after the keyword.
526
*/
527
528
static char *get_argument(const char *keyword, size_t kwlen,
482 by Brian Aker
Remove uint.
529
                          char *ptr, char *name, uint32_t line)
1 by brian
clean slate
530
{
531
  char *end;
532
533
  /* Skip over "include / includedir keyword" and following whitespace */
534
535
  for (ptr+= kwlen - 1;
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
536
       my_isspace(&my_charset_utf8_general_ci, ptr[0]);
1 by brian
clean slate
537
       ptr++)
538
  {}
539
540
  /*
541
    Trim trailing whitespace from directory name
542
    The -1 below is for the newline added by fgets()
543
    Note that my_isspace() is true for \r and \n
544
  */
545
  for (end= ptr + strlen(ptr) - 1;
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
546
       my_isspace(&my_charset_utf8_general_ci, *(end - 1));
1 by brian
clean slate
547
       end--)
548
  {}
549
  end[0]= 0;                                    /* Cut off end space */
550
551
  /* Print error msg if there is nothing after !include* directive */
552
  if (end <= ptr)
553
  {
554
    fprintf(stderr,
555
	    "error: Wrong '!%s' directive in config file: %s at line %d\n",
556
	    keyword, name, line);
557
    return 0;
558
  }
559
  return ptr;
560
}
561
562
563
/*
564
  Open a configuration file (if exists) and read given options from it
565
566
  SYNOPSIS
567
    search_default_file_with_ext()
568
    opt_handler                 Option handler function. It is used to process
569
                                every separate option.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
570
    handler_ctx                 Pointer to the structure to store actual
1 by brian
clean slate
571
                                parameters of the function.
572
    dir				directory to read
573
    ext				Extension for configuration file
574
    config_file                 Name of configuration file
575
    group			groups to read
576
    recursion_level             the level of recursion, got while processing
577
                                "!include" or "!includedir"
578
579
  RETURN
580
    0   Success
581
    -1	Fatal error, abort
582
     1	File not found (Warning)
583
*/
584
585
static int search_default_file_with_ext(Process_option_func opt_handler,
586
                                        void *handler_ctx,
587
                                        const char *dir,
588
                                        const char *ext,
589
                                        const char *config_file,
590
                                        int recursion_level)
591
{
592
  char name[FN_REFLEN + 10], buff[4096], curr_gr[4096], *ptr, *end, **tmp_ext;
593
  char *value, option[4096], tmp[FN_REFLEN];
594
  static const char includedir_keyword[]= "includedir";
595
  static const char include_keyword[]= "include";
596
  const int max_recursion_level= 10;
597
  FILE *fp;
482 by Brian Aker
Remove uint.
598
  uint32_t line=0;
146 by Brian Aker
my_bool cleanup.
599
  bool found_group=0;
1 by brian
clean slate
600
601
  if ((dir ? strlen(dir) : 0 )+strlen(config_file) >= FN_REFLEN-3)
602
    return 0;					/* Ignore wrong paths */
603
  if (dir)
604
  {
461 by Monty Taylor
Removed NullS. bu-bye.
605
    end=convert_dirname(name, dir, NULL);
1 by brian
clean slate
606
    if (dir[0] == FN_HOMELIB)		/* Add . to filenames in home */
607
      *end++='.';
673.2.1 by Toru Maesaka
First pass of replacing MySQL's strxmov with libc alternatives
608
    sprintf(end,"%s%s",config_file,ext);
1 by brian
clean slate
609
  }
610
  else
611
  {
641.4.1 by Toru Maesaka
First pass of replacing MySQL's my_stpcpy() with appropriate libc calls
612
    strcpy(name,config_file);
1 by brian
clean slate
613
  }
614
  fn_format(name,name,"","",4);
615
  {
15 by brian
Fix for stat, NETWARE removal
616
    struct stat stat_info;
617
    if (stat(name,&stat_info))
1 by brian
clean slate
618
      return 1;
619
    /*
620
      Ignore world-writable regular files.
621
      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:
622
      the mysqld server, but the check is still valid in most context.
1 by brian
clean slate
623
    */
624
    if ((stat_info.st_mode & S_IWOTH) &&
625
	(stat_info.st_mode & S_IFMT) == S_IFREG)
626
    {
627
      fprintf(stderr, "Warning: World-writable config file '%s' is ignored\n",
628
              name);
629
      return 0;
630
    }
631
  }
910.1.3 by Brian Aker
Remove my_fopen() and key_map.cc file (thanks to Jay's lcov)
632
  if (!(fp= fopen(name, "r")))
1 by brian
clean slate
633
    return 1;					/* Ignore wrong files */
634
896.1.2 by Monty Taylor
Ugly null-termination problem.
635
  memset(buff,0,sizeof(buff));
1 by brian
clean slate
636
  while (fgets(buff, sizeof(buff) - 1, fp))
637
  {
638
    line++;
639
    /* Ignore comment and empty lines */
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
640
    for (ptr= buff; my_isspace(&my_charset_utf8_general_ci, *ptr); ptr++)
1 by brian
clean slate
641
    {}
642
643
    if (*ptr == '#' || *ptr == ';' || !*ptr)
644
      continue;
645
646
    /* Configuration File Directives */
647
    if ((*ptr == '!'))
648
    {
649
      if (recursion_level >= max_recursion_level)
650
      {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
651
        for (end= ptr + strlen(ptr) - 1;
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
652
             my_isspace(&my_charset_utf8_general_ci, *(end - 1));
1 by brian
clean slate
653
             end--)
654
        {}
655
        end[0]= 0;
656
        fprintf(stderr,
657
                "Warning: skipping '%s' directive as maximum include"
658
                "recursion level was reached in file %s at line %d\n",
659
                ptr, name, line);
660
        continue;
661
      }
662
663
      /* skip over `!' and following whitespace */
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
664
      for (++ptr; my_isspace(&my_charset_utf8_general_ci, ptr[0]); ptr++)
1 by brian
clean slate
665
      {}
666
667
      if ((!strncmp(ptr, includedir_keyword,
668
                    sizeof(includedir_keyword) - 1)) &&
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
669
          my_isspace(&my_charset_utf8_general_ci, ptr[sizeof(includedir_keyword) - 1]))
1 by brian
clean slate
670
      {
671
	if (!(ptr= get_argument(includedir_keyword,
672
                                sizeof(includedir_keyword),
673
                                ptr, name, line)))
674
	  goto err;
675
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
676
        CachedDirectory dir_cache(ptr);
1089.2.2 by David Shrewsbury
Replace use of opendir/readdir in default.cc with CachedDirectory
677
678
        if (dir_cache.fail())
1079.1.1 by David Shrewsbury
Remove use of my_dir() from default.cc.
679
        {
680
          /**
681
           * @todo
682
           * Since clients still use this code, we use fprintf here.
683
           * This fprintf needs to be turned into errmsg_printf
684
           * as soon as the client programs no longer use mysys
685
           * and can use the pluggable error message system.
686
           */
687
          fprintf(stderr, _("error: could not open directory: %s\n"), ptr);
1 by brian
clean slate
688
          goto err;
1079.1.1 by David Shrewsbury
Remove use of my_dir() from default.cc.
689
        }
690
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
691
        CachedDirectory::Entries files= dir_cache.getEntries();
692
        CachedDirectory::Entries::iterator file_iter= files.begin();
1079.1.1 by David Shrewsbury
Remove use of my_dir() from default.cc.
693
1089.2.2 by David Shrewsbury
Replace use of opendir/readdir in default.cc with CachedDirectory
694
        while (file_iter != files.end())
1 by brian
clean slate
695
        {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
696
          CachedDirectory::Entry *entry= *file_iter;
1089.2.2 by David Shrewsbury
Replace use of opendir/readdir in default.cc with CachedDirectory
697
          ext= fn_ext(entry->filename.c_str());
1 by brian
clean slate
698
699
          /* check extension */
700
          for (tmp_ext= (char**) f_extensions; *tmp_ext; tmp_ext++)
701
          {
702
            if (!strcmp(ext, *tmp_ext))
1079.1.1 by David Shrewsbury
Remove use of my_dir() from default.cc.
703
            {
1089.2.2 by David Shrewsbury
Replace use of opendir/readdir in default.cc with CachedDirectory
704
              fn_format(tmp, entry->filename.c_str(), ptr, "",
1079.1.1 by David Shrewsbury
Remove use of my_dir() from default.cc.
705
                        MY_UNPACK_FILENAME | MY_SAFE_PATH);
706
707
              search_default_file_with_ext(opt_handler, handler_ctx, "", "",
708
                                           tmp, recursion_level + 1);
709
            }
710
          }
711
1089.2.2 by David Shrewsbury
Replace use of opendir/readdir in default.cc with CachedDirectory
712
          ++file_iter;
1 by brian
clean slate
713
        }
714
      }
715
      else if ((!strncmp(ptr, include_keyword, sizeof(include_keyword) - 1)) &&
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
716
               my_isspace(&my_charset_utf8_general_ci, ptr[sizeof(include_keyword)-1]))
1 by brian
clean slate
717
      {
718
	if (!(ptr= get_argument(include_keyword,
719
                                sizeof(include_keyword), ptr,
720
                                name, line)))
721
	  goto err;
722
723
        search_default_file_with_ext(opt_handler, handler_ctx, "", "", ptr,
724
                                     recursion_level + 1);
725
      }
726
727
      continue;
728
    }
729
730
    if (*ptr == '[')				/* Group name */
731
    {
732
      found_group=1;
733
      if (!(end=(char *) strchr(++ptr,']')))
734
      {
735
	fprintf(stderr,
736
		"error: Wrong group definition in config file: %s at line %d\n",
737
		name,line);
738
	goto err;
739
      }
740
      /* Remove end space */
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
741
      for ( ; my_isspace(&my_charset_utf8_general_ci,end[-1]) ; end--) ;
1 by brian
clean slate
742
      end[0]=0;
743
1067.4.10 by Nathan Williams
Converted all cmin/cmax usages in the mysys directory to std::min/max.
744
      strncpy(curr_gr, ptr, min((size_t) (end-ptr)+1, sizeof(curr_gr)-1));
745
      curr_gr[min((size_t)(end-ptr)+1, sizeof(curr_gr)-1)] = '\0';
1 by brian
clean slate
746
747
      /* signal that a new group is found */
748
      opt_handler(handler_ctx, curr_gr, NULL);
749
750
      continue;
751
    }
752
    if (!found_group)
753
    {
754
      fprintf(stderr,
755
	      "error: Found option without preceding group in config file: %s at line: %d\n",
756
	      name,line);
757
      goto err;
758
    }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
759
760
1 by brian
clean slate
761
    end= remove_end_comment(ptr);
762
    if ((value= strchr(ptr, '=')))
763
      end= value;				/* Option without argument */
896.1.2 by Monty Taylor
Ugly null-termination problem.
764
    for ( ; my_isspace(&my_charset_utf8_general_ci,end[-1]) || end[-1]== '\n'; end--) ;
1 by brian
clean slate
765
    if (!value)
766
    {
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
767
      strncpy(strcpy(option,"--")+2,ptr,strlen(ptr)+1);
1 by brian
clean slate
768
      if (opt_handler(handler_ctx, curr_gr, option))
769
        goto err;
770
    }
771
    else
772
    {
773
      /* Remove pre- and end space */
774
      char *value_end;
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
775
      for (value++ ; my_isspace(&my_charset_utf8_general_ci,*value); value++) ;
376 by Brian Aker
strend remove
776
      value_end= strchr(value, '\0');
1 by brian
clean slate
777
      /*
670.3.1 by Toru Maesaka
Replaced MySQL's my_stpncpy() with libc and c++ calls
778
       We don't have to test for value_end >= value as we know there is
779
       an '=' before
1 by brian
clean slate
780
      */
383.1.10 by Brian Aker
More cleanup/test fixup around utf8
781
      for ( ; my_isspace(&my_charset_utf8_general_ci,value_end[-1]) ; value_end--) ;
1 by brian
clean slate
782
      if (value_end < value)			/* Empty string */
670.3.1 by Toru Maesaka
Replaced MySQL's my_stpncpy() with libc and c++ calls
783
        value_end=value;
1 by brian
clean slate
784
785
      /* remove quotes around argument */
786
      if ((*value == '\"' || *value == '\'') && /* First char is quote */
787
          (value + 1 < value_end ) && /* String is longer than 1 */
788
          *value == value_end[-1] ) /* First char is equal to last char */
789
      {
641.4.3 by Toru Maesaka
Final pass of replacing MySQL's my_stpcpy() with appropriate libc calls
790
        value++;
791
        value_end--;
1 by brian
clean slate
792
      }
896.1.2 by Monty Taylor
Ugly null-termination problem.
793
      
794
      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
795
      ptr= strncpy(strcpy(option,"--")+2,ptr,(size_t) (end-ptr));
896.1.2 by Monty Taylor
Ugly null-termination problem.
796
      ptr[end-ptr]= '\0';
670.3.1 by Toru Maesaka
Replaced MySQL's my_stpncpy() with libc and c++ calls
797
      ptr+= strlen(ptr);
1 by brian
clean slate
798
      *ptr++= '=';
799
800
      for ( ; value != value_end; value++)
801
      {
802
	if (*value == '\\' && value != value_end-1)
803
	{
804
	  switch(*++value) {
805
	  case 'n':
806
	    *ptr++='\n';
807
	    break;
808
	  case 't':
809
	    *ptr++= '\t';
810
	    break;
811
	  case 'r':
812
	    *ptr++ = '\r';
813
	    break;
814
	  case 'b':
815
	    *ptr++ = '\b';
816
	    break;
817
	  case 's':
818
	    *ptr++= ' ';			/* space */
819
	    break;
820
	  case '\"':
821
	    *ptr++= '\"';
822
	    break;
823
	  case '\'':
824
	    *ptr++= '\'';
825
	    break;
826
	  case '\\':
827
	    *ptr++= '\\';
828
	    break;
829
	  default:				/* Unknown; Keep '\' */
830
	    *ptr++= '\\';
831
	    *ptr++= *value;
832
	    break;
833
	  }
834
	}
835
	else
836
	  *ptr++= *value;
837
      }
838
      *ptr=0;
839
      if (opt_handler(handler_ctx, curr_gr, option))
840
        goto err;
841
    }
842
  }
910.1.3 by Brian Aker
Remove my_fopen() and key_map.cc file (thanks to Jay's lcov)
843
  fclose(fp);
1 by brian
clean slate
844
  return(0);
845
846
 err:
910.1.3 by Brian Aker
Remove my_fopen() and key_map.cc file (thanks to Jay's lcov)
847
  fclose(fp);
848
1 by brian
clean slate
849
  return -1;					/* Fatal error */
850
}
851
852
853
static char *remove_end_comment(char *ptr)
854
{
855
  char quote= 0;	/* we are inside quote marks */
856
  char escape= 0;	/* symbol is protected by escape chagacter */
857
858
  for (; *ptr; ptr++)
859
  {
860
    if ((*ptr == '\'' || *ptr == '\"') && !escape)
861
    {
862
      if (!quote)
863
	quote= *ptr;
864
      else if (quote == *ptr)
865
	quote= 0;
866
    }
867
    /* We are not inside a string */
868
    if (!quote && *ptr == '#')
869
    {
870
      *ptr= 0;
871
      return ptr;
872
    }
873
    escape= (quote && *ptr == '\\' && !escape);
874
  }
875
  return ptr;
876
}
877
878
void my_print_default_files(const char *conf_file)
879
{
880
  const char *empty_list[]= { "", 0 };
146 by Brian Aker
my_bool cleanup.
881
  bool have_ext= fn_ext(conf_file)[0] != 0;
1 by brian
clean slate
882
  const char **exts_to_use= have_ext ? empty_list : f_extensions;
883
  char name[FN_REFLEN], **ext;
884
  const char **dirs;
885
886
  init_default_directories();
887
  puts("\nDefault options are read from the following files in the given order:");
888
889
  if (dirname_length(conf_file))
890
    fputs(conf_file,stdout);
891
  else
892
  {
893
    for (dirs=default_directories ; *dirs; dirs++)
894
    {
895
      for (ext= (char**) exts_to_use; *ext; ext++)
896
      {
897
	const char *pos;
898
	char *end;
899
	if (**dirs)
900
	  pos= *dirs;
901
	else if (my_defaults_extra_file)
902
	  pos= my_defaults_extra_file;
903
	else
904
	  continue;
461 by Monty Taylor
Removed NullS. bu-bye.
905
	end= convert_dirname(name, pos, NULL);
1 by brian
clean slate
906
	if (name[0] == FN_HOMELIB)	/* Add . to filenames in home */
907
	  *end++='.';
673.2.1 by Toru Maesaka
First pass of replacing MySQL's strxmov with libc alternatives
908
  sprintf(end,"%s%s ",conf_file, *ext);
1 by brian
clean slate
909
	fputs(name,stdout);
910
      }
911
    }
912
  }
913
  puts("");
914
}
915
916
void print_defaults(const char *conf_file, const char **groups)
917
{
918
  const char **groups_save= groups;
919
  my_print_default_files(conf_file);
920
921
  fputs("The following groups are read:",stdout);
922
  for ( ; *groups ; groups++)
923
  {
924
    fputc(' ',stdout);
925
    fputs(*groups,stdout);
926
  }
927
928
  if (my_defaults_group_suffix)
929
  {
930
    groups= groups_save;
931
    for ( ; *groups ; groups++)
932
    {
933
      fputc(' ',stdout);
934
      fputs(*groups,stdout);
935
      fputs(my_defaults_group_suffix,stdout);
936
    }
937
  }
938
  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
939
  --no-defaults		Don't read default options from any options file\n\
940
  --defaults-file=#	Only read default options from the given file #\n\
941
  --defaults-extra-file=# Read this file after the global files are read");
1 by brian
clean slate
942
}
943
944
/*
945
  This extra complexity is to avoid declaring 'rc' if it won't be
946
  used.
947
*/
51.3.22 by Jay Pipes
Final round of removal of DBUG in mysys/, including Makefile
948
#define ADD_DIRECTORY(DIR)  (void) array_append_string_unique((DIR), default_directories, \
1 by brian
clean slate
949
                             array_elements(default_directories))
950
951
#define ADD_COMMON_DIRECTORIES() \
952
  do { \
722.1.4 by Monty Taylor
Removed all the setting of DEFS everywhere. Use configmake.h to get the values
953
    const char *env; \
954
    if ((env= getenv("DRIZZLE_HOME"))) \
1 by brian
clean slate
955
      ADD_DIRECTORY(env); \
956
    /* Placeholder for --defaults-extra-file=<path> */ \
957
    ADD_DIRECTORY(""); \
958
  } while (0)
959
960
961
/**
962
  Initialize default directories for Unix
963
964
  @details
965
    1. /etc/
520.4.28 by Monty Taylor
Changed my.cnf to drizzle.cnf and /etc/mysql to /etc/drizzle.
966
    2. /etc/drizzle/
1 by brian
clean slate
967
    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
968
    4. getenv("DRIZZLE_HOME")
1 by brian
clean slate
969
    5. --defaults-extra-file=<path> (run-time option)
970
    6. "~/"
971
*/
972
182.1.2 by Jim Winstead
Various fixes to enable compilation on Mac OS X, and remove the glib dependency.
973
static void init_default_directories(void)
1 by brian
clean slate
974
{
212.6.14 by Mats Kindahl
Removing redundant use of casts in mysys for memcmp(), memcpy(), memset(), and memmove().
975
  memset(default_directories, 0, sizeof(default_directories));
1 by brian
clean slate
976
  ADD_DIRECTORY("/etc/");
520.4.28 by Monty Taylor
Changed my.cnf to drizzle.cnf and /etc/mysql to /etc/drizzle.
977
  ADD_DIRECTORY("/etc/drizzle/");
722.1.4 by Monty Taylor
Removed all the setting of DEFS everywhere. Use configmake.h to get the values
978
  ADD_DIRECTORY(SYSCONFDIR);
1 by brian
clean slate
979
  ADD_COMMON_DIRECTORIES();
980
  ADD_DIRECTORY("~/");
981
}
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
982
983
} /* namespace internal */
984
} /* namespace drizzled */