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