~drizzle-trunk/drizzle/development

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