home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / mysys / default.c < prev    next >
C/C++ Source or Header  |  2000-10-11  |  11KB  |  389 lines

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This library is free software; you can redistribute it and/or
  4.    modify it under the terms of the GNU Library General Public
  5.    License as published by the Free Software Foundation; either
  6.    version 2 of the License, or (at your option) any later version.
  7.    
  8.    This library is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.    Library General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU Library General Public
  14.    License along with this library; if not, write to the Free
  15.    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  16.    MA 02111-1307, USA */
  17.  
  18. /****************************************************************************
  19. ** Add all options from files named "group".cnf from the default_directories
  20. ** before the command line arguments.
  21. ** On Windows defaults will also search in the Windows directory for a file
  22. ** called 'group'.ini
  23. ** As long as the program uses the last argument for conflicting
  24. ** options one only have to add a call to "load_defaults" to enable
  25. ** use of default values.
  26. ** pre- and end 'blank space' are removed from options and values. The
  27. ** following escape sequences are recognized in values:  \b \t \n \r \\
  28. **
  29. ** The following arguments are handled automaticly;  If used, they must be
  30. ** first argument on the command line!
  31. ** --no-defaults    ; no options are read.
  32. ** --defaults-file=full-path-to-default-file    ; Only this file will be read.
  33. ** --defaults-extra-file=full-path-to-default-file ; Read this file before ~/
  34. ** --print-defaults    ; Print the modified command line and exit
  35. ****************************************************************************/
  36.  
  37. #undef SAFEMALLOC        /* safe_malloc is not yet initailized */
  38.  
  39. #include "mysys_priv.h"
  40. #include "m_string.h"
  41. #include "m_ctype.h"
  42.  
  43. char *defaults_extra_file=0;
  44.  
  45. /* Which directories are searched for options (and in which order) */
  46.  
  47. const char *default_directories[]= {
  48. #ifdef __WIN__
  49. "C:/",
  50. #else
  51. "/etc/",
  52. #endif
  53. #ifdef DATADIR
  54. DATADIR,
  55. #endif
  56. "",                    /* Place for defaults_extra_dir */
  57. #ifndef __WIN__
  58. "~/",
  59. #endif
  60. NullS,
  61. };
  62.  
  63. #define default_ext       ".cnf"        /* extension for config file */
  64. #ifdef __WIN__
  65. #include <winbase.h>
  66. #define windows_ext    ".ini"
  67. #endif
  68.  
  69. static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
  70.                    const char *dir, const char *config_file,
  71.                    const char *ext, TYPELIB *group);
  72.  
  73.  
  74. void load_defaults(const char *conf_file, const char **groups,
  75.            int *argc, char ***argv)
  76. {
  77.   DYNAMIC_ARRAY args;
  78.   const char **dirs, *forced_default_file;
  79.   TYPELIB group;
  80.   my_bool found_print_defaults=0;
  81.   uint args_used=0;
  82.   MEM_ROOT alloc;
  83.   char *ptr,**res;
  84.   DBUG_ENTER("load_defaults");
  85.  
  86.   init_alloc_root(&alloc,128,0);
  87.   if (*argc >= 2 && !strcmp(argv[0][1],"--no-defaults"))
  88.   {
  89.     /* remove the --no-defaults argument and return only the other arguments */
  90.     uint i;
  91.     if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
  92.                  (*argc + 1)*sizeof(char*))))
  93.       goto err;
  94.     res= (char**) (ptr+sizeof(alloc));
  95.     res[0]= **argv;                /* Copy program name */
  96.     for (i=2 ; i < (uint) *argc ; i++)
  97.       res[i-1]=argv[0][i];
  98.     (*argc)--;
  99.     *argv=res;
  100.     *(MEM_ROOT*) ptr= alloc;            /* Save alloc root for free */
  101.     DBUG_VOID_RETURN;
  102.   }
  103.  
  104.   /* Check if we want to force the use a specific default file */
  105.   forced_default_file=0;
  106.   if (*argc >= 2)
  107.   {
  108.     if (is_prefix(argv[0][1],"--defaults-file="))
  109.     {
  110.       forced_default_file=strchr(argv[0][1],'=')+1;
  111.       args_used++;
  112.     }
  113.     else if (is_prefix(argv[0][1],"--defaults-extra-file="))
  114.     {
  115.       defaults_extra_file=strchr(argv[0][1],'=')+1;
  116.       args_used++;
  117.     }
  118.   }
  119.  
  120.   group.count=0;
  121.   group.name= "defaults";
  122.   group.type_names= groups;
  123.   for (; *groups ; groups++)
  124.     group.count++;
  125.  
  126.   if (init_dynamic_array(&args, sizeof(char*),*argc, 32))
  127.     goto err;
  128.   if (forced_default_file)
  129.   {
  130.     if (search_default_file(&args, &alloc, "", forced_default_file, "",
  131.                 &group))
  132.       goto err;
  133.   }
  134.   else if (dirname_length(conf_file))
  135.   {
  136.     if (search_default_file(&args, &alloc, NullS, conf_file, default_ext,
  137.                 &group))
  138.       goto err;
  139.   }
  140.   else
  141.   {
  142. #ifdef __WIN__
  143.     char system_dir[FN_REFLEN];
  144.     GetWindowsDirectory(system_dir,sizeof(system_dir));
  145.     if (search_default_file(&args, &alloc, system_dir, conf_file, windows_ext,
  146.                 &group))
  147.       goto err;
  148. #endif
  149.     for (dirs=default_directories ; *dirs; dirs++)
  150.     {
  151.       int error=0;
  152.       if (**dirs)
  153.     error=search_default_file(&args, &alloc, *dirs, conf_file,
  154.                   default_ext, &group);
  155.       else if (defaults_extra_file)
  156.     error=search_default_file(&args, &alloc, NullS, defaults_extra_file,
  157.                   default_ext, &group);
  158.       if (error)
  159.     goto err;
  160.     }
  161.   }
  162.   if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
  163.                    (args.elements + *argc +1) *sizeof(char*))))
  164.     goto err;
  165.   res= (char**) (ptr+sizeof(alloc));
  166.  
  167.   /* copy name + found arguments + command line arguments to new array */
  168.   res[0]=argv[0][0];
  169.   memcpy((gptr) (res+1), args.buffer, args.elements*sizeof(char*));
  170.   /* Skipp --defaults-file and --defaults-extra-file */
  171.   (*argc)-= args_used;
  172.   (*argv)+= args_used;
  173.  
  174.   /* Check if we wan't to see the new argument list */
  175.   if (*argc >= 2 && !strcmp(argv[0][1],"--print-defaults"))
  176.   {
  177.     found_print_defaults=1;
  178.     --*argc; ++*argv;                /* skipp argument */
  179.   }
  180.  
  181.   memcpy((gptr) (res+1+args.elements), (char*) ((*argv)+1),
  182.      (*argc-1)*sizeof(char*));
  183.   res[args.elements+ *argc]=0;            /* last null */
  184.  
  185.   (*argc)+=args.elements;
  186.   *argv= (char**) res;
  187.   *(MEM_ROOT*) ptr= alloc;            /* Save alloc root for free */
  188.   delete_dynamic(&args);
  189.   if (found_print_defaults)
  190.   {
  191.     int i;
  192.     printf("%s would have been started with the following arguments:\n",
  193.        **argv);
  194.     for (i=1 ; i < *argc ; i++)
  195.       printf("%s ", (*argv)[i]);
  196.     puts("");
  197.     exit(1);
  198.   }
  199.   DBUG_VOID_RETURN;
  200.  
  201.  err:
  202.   fprintf(stderr,"Program aborted\n");
  203.   exit(1);
  204. }
  205.  
  206.  
  207. void free_defaults(char **argv)
  208. {
  209.   MEM_ROOT ptr;
  210.   memcpy_fixed((char*) &ptr,(char *) argv - sizeof(ptr), sizeof(ptr));
  211.   free_root(&ptr,MYF(0));
  212. }
  213.  
  214.  
  215. static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
  216.                    const char *dir, const char *config_file,
  217.                    const char *ext, TYPELIB *group)
  218. {
  219.   char name[FN_REFLEN+10],buff[257],*ptr,*end,*value,*tmp;
  220.   FILE *fp;
  221.   uint line=0;
  222.   my_bool read_values=0,found_group=0;
  223.  
  224.   if ((dir ? strlen(dir) : 0 )+strlen(config_file) >= FN_REFLEN-3)
  225.     return 0;                    /* Ignore wrong paths */
  226.   if (dir)
  227.   {
  228.     strmov(name,dir);
  229.     convert_dirname(name);
  230.     if (dir[0] == FN_HOMELIB)        /* Add . to filenames in home */
  231.       strcat(name,".");
  232.     strxmov(strend(name),config_file,ext,NullS);
  233.   }
  234.   else
  235.   {
  236.     strmov(name,config_file);
  237.   }
  238.   if (!(fp = my_fopen(fn_format(name,name,"","",4),O_RDONLY,MYF(0))))
  239.     return 0;                    /* Ignore wrong files */
  240.  
  241.   while (fgets(buff,sizeof(buff)-1,fp))
  242.   {
  243.     line++;
  244.     /* Ignore comment and empty lines */
  245.     for (ptr=buff ; isspace(*ptr) ; ptr++ ) ;
  246.     if (*ptr == '#' || *ptr == ';' || !*ptr)
  247.       continue;
  248.     if (*ptr == '[')                /* Group name */
  249.     {
  250.       found_group=1;
  251.       if (!(end=(char *) strchr(++ptr,']')))
  252.       {
  253.     fprintf(stderr,
  254.         "error: Wrong group definition in config file: %s at line %d\n",
  255.         name,line);
  256.     goto err;
  257.       }
  258.       for ( ; isspace(end[-1]) ; end--) ;    /* Remove end space */
  259.       end[0]=0;
  260.       read_values=find_type(ptr,group,3) > 0;
  261.       continue;
  262.     }
  263.     if (!found_group)
  264.     {
  265.       fprintf(stderr,
  266.           "error: Found option without preceding group in config file: %s at line: %d\n",
  267.           name,line);
  268.       goto err;
  269.     }
  270.     if (!read_values)
  271.       continue;
  272.     if (!(end=value=strchr(ptr,'=')))
  273.       end=strend(ptr);                /* Option without argument */
  274.     for ( ; isspace(end[-1]) ; end--) ;
  275.     if (!value)
  276.     {
  277.       if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3)))
  278.     goto err;
  279.       strmake(strmov(tmp,"--"),ptr,(uint) (end-ptr));
  280.       if (insert_dynamic(args,(gptr) &tmp))
  281.     goto err;
  282.     }
  283.     else
  284.     {
  285.       /* Remove pre- and end space */
  286.       char *value_end;
  287.       for (value++ ; isspace(*value); value++) ;
  288.       value_end=strend(value);
  289.       for ( ; isspace(value_end[-1]) ; value_end--) ;
  290.       if (value_end < value)            /* Empty string */
  291.     value_end=value;
  292.       if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3 +
  293.                (uint) (value_end-value)+1)))
  294.     goto err;
  295.       if (insert_dynamic(args,(gptr) &tmp))
  296.     goto err;
  297.       ptr=strnmov(strmov(tmp,"--"),ptr,(uint) (end-ptr));
  298.       *ptr++= '=';
  299.       for ( ; value != value_end; value++)
  300.       {
  301.     if (*value == '\\' && value != value_end-1)
  302.     {
  303.       switch(*++value) {
  304.       case 'n':
  305.         *ptr++='\n';
  306.         break;
  307.       case 't':
  308.         *ptr++= '\t';
  309.         break;
  310.       case 'r':
  311.         *ptr++ = '\r';
  312.         break;
  313.       case 'b':
  314.         *ptr++ = '\b';
  315.         break;
  316.       case 's':
  317.         *ptr++= ' ';            /* space */
  318.         break;
  319.       case '\\':
  320.         *ptr++= '\\';
  321.         break;
  322.       default:                /* Unknown; Keep '\' */
  323.         *ptr++= '\\';
  324.         *ptr++= *value;
  325.         break;
  326.       }
  327.     }
  328.     else
  329.       *ptr++= *value;
  330.       }
  331.       *ptr=0;
  332.     }
  333.   }
  334.   my_fclose(fp,MYF(0));
  335.   return(0);
  336.  
  337.  err:
  338.   my_fclose(fp,MYF(0));
  339.   return 1;
  340. }
  341.  
  342.  
  343. void print_defaults(const char *conf_file, const char **groups)
  344. {
  345. #ifdef __WIN__
  346.   bool have_ext=fn_ext(conf_file)[0] != 0;
  347. #endif
  348.   char name[FN_REFLEN];
  349.   const char **dirs;
  350.   puts("\nDefault options are read from the following files in the given order:");
  351.  
  352.   if (dirname_length(conf_file))
  353.     fputs(conf_file,stdout);
  354.   else
  355.   {
  356. #ifdef __WIN__
  357.     GetWindowsDirectory(name,sizeof(name));
  358.     printf("%s\\%s%s ",name,conf_file,have_ext ? "" : windows_ext);
  359. #endif
  360.     for (dirs=default_directories ; *dirs; dirs++)
  361.     {
  362.       if (**dirs)
  363.     strmov(name,*dirs);
  364.       else if (defaults_extra_file)
  365.     strmov(name,defaults_extra_file);
  366.       else
  367.     continue;
  368.       convert_dirname(name);
  369.       if (name[0] == FN_HOMELIB)    /* Add . to filenames in home */
  370.     strcat(name,".");
  371.       strxmov(strend(name),conf_file,default_ext," ",NullS);
  372.       fputs(name,stdout);
  373.     }
  374.     puts("");
  375.   }
  376.   fputs("The following groups are read:",stdout);
  377.   for ( ; *groups ; groups++)
  378.   {
  379.     fputc(' ',stdout);
  380.     fputs(*groups,stdout);
  381.   }
  382.   puts("\nThe following options may be given as the first argument:\n\
  383. --print-defaults    Print the program argument list and exit\n\
  384. --no-defaults        Don't read default options from any options file\n\
  385. --defaults-file=#    Only read default options from the given file #\n\
  386. --defaults-extra-file=# Read this file after the global files are read");
  387. }
  388.  
  389.