~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/default.c

  • Committer: Monty Taylor
  • Date: 2008-10-09 22:38:27 UTC
  • mto: This revision was merged to the branch mainline in revision 497.
  • Revision ID: monty@inaugust.com-20081009223827-bc9gvpiplsmvpwyq
Moved test() to its own file.
Made a new function to possibly replace int10_to_str.

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