~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/internal/default.cc

  • Committer: Brian Aker
  • Date: 2010-12-08 22:35:56 UTC
  • mfrom: (1819.9.158 update-innobase)
  • Revision ID: brian@tangent.org-20101208223556-37mi4omqg7lkjzf3
Merge in Stewart's changes, 1.3 changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
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 */
 
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
15
15
 
16
16
/****************************************************************************
17
17
 Add all options from files named "group".cnf from the default_directories
33
33
 --print-defaults         ; Print the modified command line and exit
34
34
****************************************************************************/
35
35
 
36
 
#include "mysys_priv.h"
37
 
#include <mystrings/m_string.h>
38
 
#include <mystrings/m_ctype.h>
39
 
#include <mysys/my_dir.h>
40
 
 
41
 
#include <stdio.h>
 
36
#include "config.h"
 
37
 
 
38
#include "drizzled/internal/my_sys.h"
 
39
#include "drizzled/internal/m_string.h"
 
40
#include "drizzled/charset_info.h"
 
41
#include <drizzled/configmake.h>
 
42
#include <drizzled/gettext.h>
 
43
 
 
44
#include "drizzled/cached_directory.h"
 
45
 
 
46
#ifdef HAVE_SYS_STAT_H
 
47
# include <sys/stat.h>
 
48
#endif
 
49
 
 
50
#include <cstdio>
 
51
#include <algorithm>
 
52
 
 
53
using namespace std;
 
54
 
 
55
namespace drizzled
 
56
{
 
57
namespace internal
 
58
{
42
59
 
43
60
const char *my_defaults_file=0;
44
61
const char *my_defaults_group_suffix=0;
51
68
 
52
69
static const char *f_extensions[]= { ".cnf", 0 };
53
70
 
54
 
static int handle_default_option(void *in_ctx, const char *group_name,
55
 
                                 const char *option);
 
71
int handle_default_option(void *in_ctx, const char *group_name,
 
72
                          const char *option);
56
73
 
57
74
/*
58
75
   This structure defines the context that we pass to callback
63
80
 
64
81
struct handle_option_ctx
65
82
{
66
 
   MEM_ROOT *alloc;
 
83
   memory::Root *alloc;
67
84
   DYNAMIC_ARRAY *args;
68
85
   TYPELIB *group;
69
86
};
140
157
                                    (char **) &my_defaults_group_suffix);
141
158
 
142
159
  if (! my_defaults_group_suffix)
143
 
    my_defaults_group_suffix= getenv(STRINGIFY_ARG(DEFAULT_GROUP_SUFFIX_ENV));
 
160
    my_defaults_group_suffix= getenv("DRIZZLE_GROUP_SUFFIX");
144
161
 
145
162
  if (forced_extra_defaults)
146
163
    my_defaults_extra_file= (char *) forced_extra_defaults;
147
 
  
 
164
 
148
165
  if (forced_default_file)
149
166
    my_defaults_file= forced_default_file;
150
167
 
153
170
    load_defaults() as otherwise we can't know the type of 'func_ctx'
154
171
  */
155
172
 
156
 
  if (my_defaults_group_suffix && func == handle_default_option)
 
173
  if (my_defaults_group_suffix && (func == handle_default_option))
157
174
  {
158
175
    /* Handle --defaults-group-suffix= */
159
176
    uint32_t i;
160
177
    const char **extra_groups;
161
 
    const uint32_t instance_len= strlen(my_defaults_group_suffix); 
 
178
    const size_t instance_len= strlen(my_defaults_group_suffix);
162
179
    struct handle_option_ctx *ctx= (struct handle_option_ctx*) func_ctx;
163
180
    char *ptr;
164
181
    TYPELIB *group= ctx->group;
165
 
    
166
 
    if (!(extra_groups= 
167
 
          (const char**)alloc_root(ctx->alloc,
 
182
 
 
183
    if (!(extra_groups=
 
184
          (const char**)ctx->alloc->alloc_root(
168
185
                                   (2*group->count+1)*sizeof(char*))))
169
186
      goto err;
170
 
    
 
187
 
171
188
    for (i= 0; i < group->count; i++)
172
189
    {
173
 
      uint32_t len;
 
190
      size_t len;
174
191
      extra_groups[i]= group->type_names[i]; /** copy group */
175
 
      
 
192
 
176
193
      len= strlen(extra_groups[i]);
177
 
      if (!(ptr= (char *)alloc_root(ctx->alloc, len+instance_len+1)))
 
194
      if (!(ptr= (char *)ctx->alloc->alloc_root( len+instance_len+1)))
178
195
        goto err;
179
 
      
 
196
 
180
197
      extra_groups[i+group->count]= ptr;
181
 
      
 
198
 
182
199
      /** Construct new group */
183
200
      memcpy(ptr, extra_groups[i], len);
184
201
      memcpy(ptr+len, my_defaults_group_suffix, instance_len+1);
185
202
    }
186
 
    
 
203
 
187
204
    group->count*= 2;
188
205
    group->type_names= extra_groups;
189
206
    group->type_names[group->count]= 0;
190
207
  }
191
 
  
 
208
 
192
209
  if (forced_default_file)
193
210
  {
194
211
    if ((error= search_default_file_with_ext(func, func_ctx, "", "",
235
252
err:
236
253
  fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
237
254
  exit(1);
238
 
  return 0;                                     /* Keep compiler happy */
239
255
}
240
256
 
241
257
 
262
278
    1 - error occured
263
279
*/
264
280
 
265
 
static int handle_default_option(void *in_ctx, const char *group_name,
266
 
                                 const char *option)
 
281
int handle_default_option(void *in_ctx, const char *group_name,
 
282
                          const char *option)
267
283
{
268
284
  char *tmp;
269
285
  struct handle_option_ctx *ctx= (struct handle_option_ctx *) in_ctx;
273
289
 
274
290
  if (find_type((char *)group_name, ctx->group, 3))
275
291
  {
276
 
    if (!(tmp= (char *)alloc_root(ctx->alloc, strlen(option) + 1)))
 
292
    if (!(tmp= (char *)ctx->alloc->alloc_root(strlen(option) + 1)))
277
293
      return 1;
278
294
    if (insert_dynamic(ctx->args, (unsigned char*) &tmp))
279
295
      return 1;
280
 
    my_stpcpy(tmp, option);
 
296
    strcpy(tmp, option);
281
297
  }
282
298
 
283
299
  return 0;
308
324
  int org_argc= argc, prev_argc= 0;
309
325
  *defaults= *extra_defaults= *group_suffix= 0;
310
326
 
 
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
 
311
331
  while (argc >= 2 && argc != prev_argc)
312
332
  {
313
333
    /* Skip program name or previously handled argument */
314
334
    argv++;
315
335
    prev_argc= argc;                            /* To check if we found */
316
 
    if (!*defaults && is_prefix(*argv,"--defaults-file="))
 
336
    if (!*defaults && (strncmp(*argv,
 
337
                               DEFAULTS_FILE.c_str(),
 
338
                               DEFAULTS_FILE.size()) == 0))
317
339
    {
318
 
      *defaults= *argv + sizeof("--defaults-file=")-1;
 
340
      *defaults= *argv + DEFAULTS_FILE.size();
319
341
       argc--;
320
342
       continue;
321
343
    }
322
 
    if (!*extra_defaults && is_prefix(*argv,"--defaults-extra-file="))
 
344
    if (!*extra_defaults && (strncmp(*argv, 
 
345
                                     DEFAULTS_EXTRA_FILE.c_str(),
 
346
                                     DEFAULTS_EXTRA_FILE.size()) == 0))
323
347
    {
324
 
      *extra_defaults= *argv + sizeof("--defaults-extra-file=")-1;
 
348
      *extra_defaults= *argv + DEFAULTS_EXTRA_FILE.size();
325
349
      argc--;
326
350
      continue;
327
351
    }
328
 
    if (!*group_suffix && is_prefix(*argv, "--defaults-group-suffix="))
 
352
    if (!*group_suffix && (strncmp(*argv, 
 
353
                                   DEFAULTS_GROUP_SUFFIX.c_str(),
 
354
                                   DEFAULTS_GROUP_SUFFIX.size()) == 0))
 
355
 
329
356
    {
330
 
      *group_suffix= *argv + sizeof("--defaults-group-suffix=")-1;
 
357
      *group_suffix= *argv + DEFAULTS_GROUP_SUFFIX.size();
331
358
      argc--;
332
359
      continue;
333
360
    }
357
384
   NOTES
358
385
    In case of fatal error, the function will print a warning and do
359
386
    exit(1)
360
 
 
 
387
 
361
388
    To free used memory one should call free_defaults() with the argument
362
389
    that was put in *argv
363
390
 
372
399
{
373
400
  DYNAMIC_ARRAY args;
374
401
  TYPELIB group;
375
 
  bool found_print_defaults= 0;
376
402
  uint32_t args_used= 0;
377
403
  int error= 0;
378
 
  MEM_ROOT alloc;
 
404
  memory::Root alloc(512);
379
405
  char *ptr,**res;
380
406
  struct handle_option_ctx ctx;
381
407
 
382
408
  init_default_directories();
383
 
  init_alloc_root(&alloc,512,0);
384
409
  /*
385
410
    Check if the user doesn't want any default option processing
386
411
    --no-defaults is always the first option
389
414
  {
390
415
    /* remove the --no-defaults argument and return only the other arguments */
391
416
    uint32_t i;
392
 
    if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
393
 
                                 (*argc + 1)*sizeof(char*))))
 
417
    if (!(ptr=(char*) alloc.alloc_root(sizeof(alloc)+ (*argc + 1)*sizeof(char*))))
394
418
      goto err;
395
419
    res= (char**) (ptr+sizeof(alloc));
 
420
    memset(res,0,(*argc + 1));
396
421
    res[0]= **argv;                             /* Copy program name */
397
 
    for (i=2 ; i < (uint) *argc ; i++)
 
422
    for (i=2 ; i < (uint32_t) *argc ; i++)
398
423
      res[i-1]=argv[0][i];
399
424
    res[i-1]=0;                                 /* End pointer */
400
425
    (*argc)--;
401
426
    *argv=res;
402
 
    *(MEM_ROOT*) ptr= alloc;                    /* Save alloc root for free */
 
427
    *(memory::Root*) ptr= alloc;                        /* Save alloc root for free */
403
428
    return(0);
404
429
  }
405
430
 
423
448
    Here error contains <> 0 only if we have a fully specified conf_file
424
449
    or a forced default file
425
450
  */
426
 
  if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
427
 
                               (args.elements + *argc +1) *sizeof(char*))))
 
451
  if (!(ptr=(char*) alloc.alloc_root(sizeof(alloc)+ (args.elements + *argc +1) *sizeof(char*))))
428
452
    goto err;
429
453
  res= (char**) (ptr+sizeof(alloc));
430
454
 
439
463
    Check if we wan't to see the new argument list
440
464
    This options must always be the last of the default options
441
465
  */
442
 
  if (*argc >= 2 && !strcmp(argv[0][1],"--print-defaults"))
443
 
  {
444
 
    found_print_defaults=1;
445
 
    --*argc; ++*argv;                           /* skip argument */
446
 
  }
447
 
 
448
466
  if (*argc)
449
467
    memcpy(res+1+args.elements, *argv + 1, (*argc-1)*sizeof(char*));
450
468
  res[args.elements+ *argc]=0;                  /* last null */
451
469
 
452
 
  (*argc)+=args.elements;
453
 
  *argv= (char**) res;
454
 
  *(MEM_ROOT*) ptr= alloc;                      /* Save alloc root for free */
 
470
  (*argc)+=int(args.elements);
 
471
  *argv= static_cast<char**>(res);
 
472
  *(memory::Root*) ptr= alloc;                  /* Save alloc root for free */
455
473
  delete_dynamic(&args);
456
 
  if (found_print_defaults)
457
 
  {
458
 
    int i;
459
 
    printf("%s would have been started with the following arguments:\n",
460
 
           **argv);
461
 
    for (i=1 ; i < *argc ; i++)
462
 
      printf("%s ", (*argv)[i]);
463
 
    puts("");
464
 
    exit(0);
465
 
  }
 
474
 
466
475
  return(error);
467
476
 
468
477
 err:
469
478
  fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
470
479
  exit(1);
471
 
  return 0;                                     /* Keep compiler happy */
472
480
}
473
481
 
474
482
 
475
483
void free_defaults(char **argv)
476
484
{
477
 
  MEM_ROOT ptr;
 
485
  memory::Root ptr;
478
486
  memcpy(&ptr, (char*) argv - sizeof(ptr), sizeof(ptr));
479
 
  free_root(&ptr,MYF(0));
 
487
  ptr.free_root(MYF(0));
480
488
}
481
489
 
482
490
 
559
567
    search_default_file_with_ext()
560
568
    opt_handler                 Option handler function. It is used to process
561
569
                                every separate option.
562
 
    handler_ctx                 Pointer to the structure to store actual 
 
570
    handler_ctx                 Pointer to the structure to store actual
563
571
                                parameters of the function.
564
572
    dir                         directory to read
565
573
    ext                         Extension for configuration file
589
597
  FILE *fp;
590
598
  uint32_t line=0;
591
599
  bool found_group=0;
592
 
  uint32_t i;
593
 
  MY_DIR *search_dir;
594
 
  FILEINFO *search_file;
595
600
 
596
601
  if ((dir ? strlen(dir) : 0 )+strlen(config_file) >= FN_REFLEN-3)
597
602
    return 0;                                   /* Ignore wrong paths */
600
605
    end=convert_dirname(name, dir, NULL);
601
606
    if (dir[0] == FN_HOMELIB)           /* Add . to filenames in home */
602
607
      *end++='.';
603
 
    strxmov(end,config_file,ext,NULL);
 
608
    sprintf(end,"%s%s",config_file,ext);
604
609
  }
605
610
  else
606
611
  {
607
 
    my_stpcpy(name,config_file);
 
612
    strcpy(name,config_file);
608
613
  }
609
614
  fn_format(name,name,"","",4);
610
615
  {
614
619
    /*
615
620
      Ignore world-writable regular files.
616
621
      This is mainly done to protect us to not read a file created by
617
 
      the mysqld server, but the check is still valid in most context. 
 
622
      the mysqld server, but the check is still valid in most context.
618
623
    */
619
624
    if ((stat_info.st_mode & S_IWOTH) &&
620
625
        (stat_info.st_mode & S_IFMT) == S_IFREG)
624
629
      return 0;
625
630
    }
626
631
  }
627
 
  if (!(fp= my_fopen(name, O_RDONLY, MYF(0))))
 
632
  if (!(fp= fopen(name, "r")))
628
633
    return 1;                                   /* Ignore wrong files */
629
634
 
 
635
  memset(buff,0,sizeof(buff));
630
636
  while (fgets(buff, sizeof(buff) - 1, fp))
631
637
  {
632
638
    line++;
642
648
    {
643
649
      if (recursion_level >= max_recursion_level)
644
650
      {
645
 
        for (end= ptr + strlen(ptr) - 1; 
 
651
        for (end= ptr + strlen(ptr) - 1;
646
652
             my_isspace(&my_charset_utf8_general_ci, *(end - 1));
647
653
             end--)
648
654
        {}
667
673
                                ptr, name, line)))
668
674
          goto err;
669
675
 
670
 
        if (!(search_dir= my_dir(ptr, MYF(MY_WME))))
 
676
        CachedDirectory dir_cache(ptr);
 
677
 
 
678
        if (dir_cache.fail())
 
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);
671
688
          goto err;
672
 
 
673
 
        for (i= 0; i < (uint) search_dir->number_off_files; i++)
 
689
        }
 
690
 
 
691
        CachedDirectory::Entries files= dir_cache.getEntries();
 
692
        CachedDirectory::Entries::iterator file_iter= files.begin();
 
693
 
 
694
        while (file_iter != files.end())
674
695
        {
675
 
          search_file= search_dir->dir_entry + i;
676
 
          ext= fn_ext(search_file->name);
 
696
          CachedDirectory::Entry *entry= *file_iter;
 
697
          ext= fn_ext(entry->filename.c_str());
677
698
 
678
699
          /* check extension */
679
700
          for (tmp_ext= (char**) f_extensions; *tmp_ext; tmp_ext++)
680
701
          {
681
702
            if (!strcmp(ext, *tmp_ext))
682
 
              break;
683
 
          }
684
 
 
685
 
          if (*tmp_ext)
686
 
          {
687
 
            fn_format(tmp, search_file->name, ptr, "",
688
 
                      MY_UNPACK_FILENAME | MY_SAFE_PATH);
689
 
 
690
 
            search_default_file_with_ext(opt_handler, handler_ctx, "", "", tmp,
691
 
                                         recursion_level + 1);
692
 
          }
 
703
            {
 
704
              fn_format(tmp, entry->filename.c_str(), ptr, "",
 
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
 
 
712
          ++file_iter;
693
713
        }
694
 
 
695
 
        my_dirend(search_dir);
696
714
      }
697
715
      else if ((!strncmp(ptr, include_keyword, sizeof(include_keyword) - 1)) &&
698
716
               my_isspace(&my_charset_utf8_general_ci, ptr[sizeof(include_keyword)-1]))
723
741
      for ( ; my_isspace(&my_charset_utf8_general_ci,end[-1]) ; end--) ;
724
742
      end[0]=0;
725
743
 
726
 
      strmake(curr_gr, ptr, cmin((size_t) (end-ptr)+1, sizeof(curr_gr)-1));
 
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';
727
746
 
728
747
      /* signal that a new group is found */
729
748
      opt_handler(handler_ctx, curr_gr, NULL);
737
756
              name,line);
738
757
      goto err;
739
758
    }
740
 
    
741
 
   
 
759
 
 
760
 
742
761
    end= remove_end_comment(ptr);
743
762
    if ((value= strchr(ptr, '=')))
744
763
      end= value;                               /* Option without argument */
745
 
    for ( ; my_isspace(&my_charset_utf8_general_ci,end[-1]) ; end--) ;
 
764
    for ( ; my_isspace(&my_charset_utf8_general_ci,end[-1]) || end[-1]== '\n'; end--) ;
746
765
    if (!value)
747
766
    {
748
 
      strmake(my_stpcpy(option,"--"),ptr, (size_t) (end-ptr));
 
767
      strncpy(strcpy(option,"--")+2,ptr,strlen(ptr)+1);
749
768
      if (opt_handler(handler_ctx, curr_gr, option))
750
769
        goto err;
751
770
    }
756
775
      for (value++ ; my_isspace(&my_charset_utf8_general_ci,*value); value++) ;
757
776
      value_end= strchr(value, '\0');
758
777
      /*
759
 
        We don't have to test for value_end >= value as we know there is
760
 
        an '=' before
 
778
       We don't have to test for value_end >= value as we know there is
 
779
       an '=' before
761
780
      */
762
781
      for ( ; my_isspace(&my_charset_utf8_general_ci,value_end[-1]) ; value_end--) ;
763
782
      if (value_end < value)                    /* Empty string */
764
 
        value_end=value;
 
783
        value_end=value;
765
784
 
766
785
      /* remove quotes around argument */
767
786
      if ((*value == '\"' || *value == '\'') && /* First char is quote */
768
787
          (value + 1 < value_end ) && /* String is longer than 1 */
769
788
          *value == value_end[-1] ) /* First char is equal to last char */
770
789
      {
771
 
        value++;
772
 
        value_end--;
 
790
        value++;
 
791
        value_end--;
773
792
      }
774
 
      ptr=my_stpncpy(my_stpcpy(option,"--"),ptr,(size_t) (end-ptr));
 
793
      
 
794
      memset(option,0,2+(size_t)(end-ptr)+1);
 
795
      ptr= strncpy(strcpy(option,"--")+2,ptr,(size_t) (end-ptr));
 
796
      ptr[end-ptr]= '\0';
 
797
      ptr+= strlen(ptr);
775
798
      *ptr++= '=';
776
799
 
777
800
      for ( ; value != value_end; value++)
817
840
        goto err;
818
841
    }
819
842
  }
820
 
  my_fclose(fp,MYF(0));
 
843
  fclose(fp);
821
844
  return(0);
822
845
 
823
846
 err:
824
 
  my_fclose(fp,MYF(0));
 
847
  fclose(fp);
 
848
 
825
849
  return -1;                                    /* Fatal error */
826
850
}
827
851
 
881
905
        end= convert_dirname(name, pos, NULL);
882
906
        if (name[0] == FN_HOMELIB)      /* Add . to filenames in home */
883
907
          *end++='.';
884
 
        strxmov(end, conf_file, *ext, " ", NULL);
 
908
  sprintf(end,"%s%s ",conf_file, *ext);
885
909
        fputs(name,stdout);
886
910
      }
887
911
    }
912
936
    }
913
937
  }
914
938
  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");
 
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");
919
942
}
920
943
 
921
944
/*
927
950
 
928
951
#define ADD_COMMON_DIRECTORIES() \
929
952
  do { \
930
 
    char *env; \
931
 
    if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV)))) \
 
953
    const char *env; \
 
954
    if ((env= getenv("DRIZZLE_HOME"))) \
932
955
      ADD_DIRECTORY(env); \
933
956
    /* Placeholder for --defaults-extra-file=<path> */ \
934
957
    ADD_DIRECTORY(""); \
942
965
    1. /etc/
943
966
    2. /etc/drizzle/
944
967
    3. --sysconfdir=<path> (compile-time option)
945
 
    4. getenv(DEFAULT_HOME_ENV)
 
968
    4. getenv("DRIZZLE_HOME")
946
969
    5. --defaults-extra-file=<path> (run-time option)
947
970
    6. "~/"
948
971
*/
952
975
  memset(default_directories, 0, sizeof(default_directories));
953
976
  ADD_DIRECTORY("/etc/");
954
977
  ADD_DIRECTORY("/etc/drizzle/");
955
 
#if defined(DEFAULT_SYSCONFDIR)
956
 
    ADD_DIRECTORY(DEFAULT_SYSCONFDIR);
957
 
#endif
 
978
  ADD_DIRECTORY(SYSCONFDIR);
958
979
  ADD_COMMON_DIRECTORIES();
959
980
  ADD_DIRECTORY("~/");
960
981
}
 
982
 
 
983
} /* namespace internal */
 
984
} /* namespace drizzled */