mariadb/mysys/default.c
unknown bee5d9d462 Simplified 'wrong xxx name' error messages by introducing 'general' ER_WRONG_NAME error
Cleaned up (and disabled part of) date/time/datetime format patch. One can't anymore change default read/write date/time/formats.
This is becasue the non standard datetime formats can't be compared as strings and MySQL does still a lot of datetime comparisons as strings
Changed flag argument to str_to_TIME() and get_date() from bool to uint
Removed THD from str_to_xxxx functions and Item class.
Fixed core dump when doing --print-defaults
Move some common string functions to strfunc.cc
Dates as strings are now of type my_charset_bin instead of default_charset()
Introduce IDENT_QUOTED to not have to create an extra copy of simple identifiers (all chars < 128)
Removed xxx_FORMAT_TYPE enums and replaced them with the old TIMESTAMP_xxx enums
Renamed some TIMESTAMP_xxx enums to more appropriate names
Use defines instead of integers for date/time/datetime string lengths
Added to build system and use the new my_strtoll10() function.



BUILD/compile-pentium-valgrind-max:
  Remove double printing of warning
VC++Files/libmysqld/libmysqld.dsp:
  Added strfunc.cc
VC++Files/sql/mysqld.dsp:
  Added strfunc.cc
VC++Files/sql/mysqldmax.dsp:
  Added strfunc.cc
VC++Files/strings/strings.dsp:
  added my_strtoll10.c
include/m_ctype.h:
  Removed MY_LEX_FOUND_IDENT (not used)
include/m_string.h:
  Added my_strtoll10()
include/mysqld_error.h:
  simplified 'wrong xxx name' error messages
include/sql_state.h:
  simplified 'wrong xxx name' error messages
libmysqld/Makefile.am:
  Added strfunc.cc
mysql-test/mysql-test-run.sh:
  Simplified some options
  changed $@ to "$@" in an attempt to handle options with space (Didn't succeed;  Problem will disappear when mysql-test-run is rewritten in C)
mysql-test/r/ctype_latin1_de.result:
  Added new tests
mysql-test/r/ctype_recoding.result:
  Extended tests
mysql-test/r/date_formats.result:
  Cleaned up tests
  Disabled some tests that can't yet be run
mysql-test/r/func_compress.result:
  New error message
mysql-test/r/rpl_temporary.result:
  Added new test
mysql-test/t/create.test:
  Changed error numbers
mysql-test/t/ctype_latin1_de.test:
  New tests
mysql-test/t/ctype_recoding.test:
  Extended tests
mysql-test/t/date_formats-master.opt:
  Removed datetime_format as we can't handle options with space in mysql-test-run
mysql-test/t/date_formats.test:
  Cleaned up tests
  Disabled some tests that can't yet be run
mysql-test/t/rpl_temporary.test:
  Added testing of open temporary table on slave shutdown
mysql-test/t/symlink.test:
  Fixed error numbers
mysys/default.c:
  Fixed core dump when doing --print-defaults
sql/Makefile.am:
  Added strfunc.cc
sql/derror.cc:
  Fixed compiler warning
sql/field.cc:
  Changed argument to str_to_TIME() from bool to uint
  Removed THD argument from str_to_TIME()
  Moved find_enum() and find_set() to strfunc.cc
sql/field.h:
  Changed type of last argument to get_date() to be able to handle more options
sql/init.cc:
  Remove not used variable dayord
sql/item.cc:
  Changed type of last argument to get_date() to be able to handle more options
  Removed THD* element from item.
  Don't use make_date_time() to generate date/time/datetimes
sql/item.h:
  Changed type of last argument to get_date() to be able to handle more options
  Removed THD* from Item
sql/item_create.cc:
  Indentation cleanup
sql/item_func.cc:
  Use new find_type()
sql/item_func.h:
  Changed type of last argument to get_date() to be able to handle more options
sql/item_strfunc.h:
  space change
sql/item_timefunc.cc:
  Changed month_names[] to be easier to use
  Moved check_names[] to strfunc.cc
  Added back old make_datetime() function
  Optimized extract_date_time()
  Use my_strtoll10() insetad of my_strntoll()
  Optimized make_date_time()
  Replaced short variable names with long ones.
  Use new functions make_time(), make_date() and make_datetime()
  Dates as strings are now of type my_charset_bin instead of default_charset()
  Changed Item_func_str_to_date() to by default return a date.
sql/item_timefunc.h:
  Changed charset for date string from default_charset() to my_charset_bin
  Changed type of last argument to get_date() to be able to handle more options
  Use defines instead of integers for date/time/datetime string lengths
sql/mysql_priv.h:
  Fixed/added new prototypes
sql/mysqld.cc:
  Removed opt_datetime_format_names
  Cleaned up handling of date_time format handling. (Fixed core dump when mysqld had error on startup)
  Removed some unnecessary double init of collation variables
sql/protocol.cc:
  Changed back protocol functions to always return dates in ISO format
sql/set_var.cc:
  Added variables time_format, date_format and datetime_format
  This had to be recoded becasue checking was done in 'update' method and not in 'check' method.
sql/set_var.h:
  Removed class sys_var_datetime_format() as this defined a variable (which doesn't work) instead of updating a variable
sql/share/czech/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/danish/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/dutch/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/english/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/estonian/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/french/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/german/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/greek/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/hungarian/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/italian/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/japanese/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/korean/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/norwegian-ny/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/norwegian/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/polish/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/portuguese/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/romanian/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/russian/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/serbian/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/slovak/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/spanish/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/swedish/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/share/ukrainian/errmsg.txt:
  simplified 'wrong xxx name' error messages
sql/sql_base.cc:
  Use new find_type()
sql/sql_class.cc:
  Allocate/free date_time format variables
sql/sql_class.h:
  Define datetime_format variables
sql/sql_db.cc:
  Use new ER_WRONG_NAME error
sql/sql_lex.cc:
  Change lex to generate IDENT_QUOTED for quoted identifiers or identifers that are using characters > 128.
  This enabled us to not have to copy and convert the identifier to utf8 for simpe identifiers
sql/sql_parse.cc:
  Use new ER_WRONG_NAME error
  Use new find_type() function
sql/sql_prepare.cc:
  Use new defines
sql/sql_table.cc:
  Use new ER_WRONG_NAME error
sql/sql_yacc.yy:
  Don't copy and convert simple identifiers to utf8.
  Replace __FORMAT_TYPE defines with TIMESTAMP... defines
sql/structs.h:
  Renamed DATETIME_FORMAT to DATE_TIME format to indicate that it's for date/time/datetime formats
  Renamed WRONT_TIMESTAMP_FULL to TIMESTAMP_DATETIME_ERROR and TIMESTAMP_FULL to TIMESTAMP_DATETIME
  Added KNOWN_DATE_TIME_FORMAT struct for Item_func_get_format
sql/time.cc:
  Prepare str_to_TIME and str_to_time() for general date/time handling
  Removed THD from str_to... functions
  Renamed date/time/datetime functions to use 'date_time' instead of 'datetime'
  Added functions to make and copy DATE_TIME_FORMAT's
  Added trivial functions 'make_time()', 'make_date()' and 'make_datetime()'
strings/Makefile.am:
  Added my_strtoll10()
strings/ctype-bin.c:
  Cleared upper part of binary state map to be able to easily identify simple identifiers
strings/my_vsnprintf.c:
  F
2003-11-03 14:01:59 +02:00

523 lines
14 KiB
C

/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/****************************************************************************
Add all options from files named "group".cnf from the default_directories
before the command line arguments.
On Windows defaults will also search in the Windows directory for a file
called 'group'.ini
As long as the program uses the last argument for conflicting
options one only have to add a call to "load_defaults" to enable
use of default values.
pre- and end 'blank space' are removed from options and values. The
following escape sequences are recognized in values: \b \t \n \r \\
The following arguments are handled automaticly; If used, they must be
first argument on the command line!
--no-defaults ; no options are read.
--defaults-file=full-path-to-default-file ; Only this file will be read.
--defaults-extra-file=full-path-to-default-file ; Read this file before ~/
--print-defaults ; Print the modified command line and exit
****************************************************************************/
#include "mysys_priv.h"
#include "m_string.h"
#include "m_ctype.h"
#include <my_dir.h>
char *defaults_extra_file=0;
/* Which directories are searched for options (and in which order) */
const char *default_directories[]= {
#ifdef __WIN__
"C:/",
#elif defined(__NETWARE__)
"sys:/etc/",
#else
"/etc/",
#endif
#ifdef DATADIR
DATADIR,
#endif
"", /* Place for defaults_extra_dir */
#if !defined(__WIN__) && !defined(__NETWARE__)
"~/",
#endif
NullS,
};
#define default_ext ".cnf" /* extension for config file */
#ifdef __WIN__
#include <winbase.h>
#define windows_ext ".ini"
#endif
static int search_default_file(DYNAMIC_ARRAY *args,MEM_ROOT *alloc,
const char *dir, const char *config_file,
const char *ext, TYPELIB *group);
static char *remove_end_comment(char *ptr);
/*
Read options from configurations files
SYNOPSIS
load_defaults()
conf_file Basename for configuration file to search for.
If this is a path, then only this file is read.
groups Which [group] entrys to read.
Points to an null terminated array of pointers
argc Pointer to argc of original program
argv Pointer to argv of original program
IMPLEMENTATION
Read options from configuration files and put them BEFORE the arguments
that are already in argc and argv. This way the calling program can
easily command line options override options in configuration files
NOTES
In case of fatal error, the function will print a warning and do
exit(1)
To free used memory one should call free_defaults() with the argument
that was put in *argv
RETURN
0 ok
1 The given conf_file didn't exists
2 The given conf_file was not a normal readable file
*/
int load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv)
{
DYNAMIC_ARRAY args;
const char **dirs, *forced_default_file;
TYPELIB group;
my_bool found_print_defaults=0;
uint args_used=0;
int error= 0;
MEM_ROOT alloc;
char *ptr,**res;
DBUG_ENTER("load_defaults");
init_alloc_root(&alloc,512,0);
if (*argc >= 2 && !strcmp(argv[0][1],"--no-defaults"))
{
/* remove the --no-defaults argument and return only the other arguments */
uint i;
if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
(*argc + 1)*sizeof(char*))))
goto err;
res= (char**) (ptr+sizeof(alloc));
res[0]= **argv; /* Copy program name */
for (i=2 ; i < (uint) *argc ; i++)
res[i-1]=argv[0][i];
res[i-1]=0; /* End pointer */
(*argc)--;
*argv=res;
*(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */
DBUG_RETURN(0);
}
/* Check if we want to force the use a specific default file */
forced_default_file=0;
if (*argc >= 2)
{
if (is_prefix(argv[0][1],"--defaults-file="))
{
forced_default_file=strchr(argv[0][1],'=')+1;
args_used++;
}
else if (is_prefix(argv[0][1],"--defaults-extra-file="))
{
defaults_extra_file=strchr(argv[0][1],'=')+1;
args_used++;
}
}
group.count=0;
group.name= "defaults";
group.type_names= groups;
for (; *groups ; groups++)
group.count++;
if (my_init_dynamic_array(&args, sizeof(char*),*argc, 32))
goto err;
if (forced_default_file)
{
if ((error= search_default_file(&args, &alloc, "",
forced_default_file, "", &group)) < 0)
goto err;
}
else if (dirname_length(conf_file))
{
if ((error= search_default_file(&args, &alloc, NullS, conf_file,
default_ext, &group)) < 0)
goto err;
}
else
{
#ifdef __WIN__
char system_dir[FN_REFLEN];
GetWindowsDirectory(system_dir,sizeof(system_dir));
if ((search_default_file(&args, &alloc, system_dir, conf_file,
windows_ext, &group)))
goto err;
#endif
#if defined(__EMX__) || defined(OS2)
if (getenv("ETC") &&
(search_default_file(&args, &alloc, getenv("ETC"), conf_file,
default_ext, &group)) < 0)
goto err;
#endif
for (dirs=default_directories ; *dirs; dirs++)
{
if (**dirs)
{
if (search_default_file(&args, &alloc, *dirs, conf_file,
default_ext, &group) < 0)
goto err;
}
else if (defaults_extra_file)
{
if (search_default_file(&args, &alloc, NullS, defaults_extra_file,
default_ext, &group) < 0)
goto err; /* Fatal error */
}
}
}
/*
Here error contains <> 0 only if we have a fully specified conf_file
or a forced default file
*/
if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
(args.elements + *argc +1) *sizeof(char*))))
goto err;
res= (char**) (ptr+sizeof(alloc));
/* copy name + found arguments + command line arguments to new array */
res[0]= argv[0][0]; /* Name MUST be set, even by embedded library */
memcpy((gptr) (res+1), args.buffer, args.elements*sizeof(char*));
/* Skipp --defaults-file and --defaults-extra-file */
(*argc)-= args_used;
(*argv)+= args_used;
/* Check if we wan't to see the new argument list */
if (*argc >= 2 && !strcmp(argv[0][1],"--print-defaults"))
{
found_print_defaults=1;
--*argc; ++*argv; /* skipp argument */
}
if (*argc)
memcpy((gptr) (res+1+args.elements), (char*) ((*argv)+1),
(*argc-1)*sizeof(char*));
res[args.elements+ *argc]=0; /* last null */
(*argc)+=args.elements;
*argv= (char**) res;
*(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */
delete_dynamic(&args);
if (found_print_defaults)
{
int i;
printf("%s would have been started with the following arguments:\n",
**argv);
for (i=1 ; i < *argc ; i++)
printf("%s ", (*argv)[i]);
puts("");
exit(0);
}
DBUG_RETURN(error);
err:
fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
exit(1);
}
void free_defaults(char **argv)
{
MEM_ROOT ptr;
memcpy_fixed((char*) &ptr,(char *) argv - sizeof(ptr), sizeof(ptr));
free_root(&ptr,MYF(0));
}
/*
Open a configuration file (if exists) and read given options from it
SYNOPSIS
search_default_file()
args Store pointer to found options here
alloc Allocate strings in this object
dir directory to read
config_file Name of configuration file
ext Extension for configuration file
group groups to read
RETURN
0 Success
-1 Fatal error, abort
1 File not found (Warning)
2 File is not a regular file (Warning)
*/
static int search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
const char *dir, const char *config_file,
const char *ext, TYPELIB *group)
{
char name[FN_REFLEN+10],buff[4096],*ptr,*end,*value,*tmp;
FILE *fp;
uint line=0;
my_bool read_values=0,found_group=0;
if ((dir ? strlen(dir) : 0 )+strlen(config_file) >= FN_REFLEN-3)
return 0; /* Ignore wrong paths */
if (dir)
{
end=convert_dirname(name, dir, NullS);
if (dir[0] == FN_HOMELIB) /* Add . to filenames in home */
*end++='.';
strxmov(end,config_file,ext,NullS);
}
else
{
strmov(name,config_file);
}
fn_format(name,name,"","",4);
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
{
MY_STAT stat_info;
if (!my_stat(name,&stat_info,MYF(0)))
return 1;
/*
Ignore world-writable regular files.
This is mainly done to protect us to not read a file created by
the mysqld server, but the check is still valid in most context.
*/
if ((stat_info.st_mode & S_IWOTH) &&
(stat_info.st_mode & S_IFMT) == S_IFREG)
{
fprintf(stderr, "warning: World-writeable config file %s is ignored\n",
name);
return 0;
}
}
#endif
if (!(fp = my_fopen(fn_format(name,name,"","",4),O_RDONLY,MYF(0))))
return 0; /* Ignore wrong files */
while (fgets(buff,sizeof(buff)-1,fp))
{
line++;
/* Ignore comment and empty lines */
for (ptr=buff ; my_isspace(&my_charset_latin1,*ptr) ; ptr++ ) ;
if (*ptr == '#' || *ptr == ';' || !*ptr)
continue;
if (*ptr == '[') /* Group name */
{
found_group=1;
if (!(end=(char *) strchr(++ptr,']')))
{
fprintf(stderr,
"error: Wrong group definition in config file: %s at line %d\n",
name,line);
goto err;
}
for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;/* Remove end space */
end[0]=0;
read_values=find_type(ptr,group,3) > 0;
continue;
}
if (!found_group)
{
fprintf(stderr,
"error: Found option without preceding group in config file: %s at line: %d\n",
name,line);
goto err;
}
if (!read_values)
continue;
end= remove_end_comment(ptr);
if ((value= strchr(ptr, '=')))
end= value; /* Option without argument */
for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;
if (!value)
{
if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3)))
goto err;
strmake(strmov(tmp,"--"),ptr,(uint) (end-ptr));
if (insert_dynamic(args,(gptr) &tmp))
goto err;
}
else
{
/* Remove pre- and end space */
char *value_end;
for (value++ ; my_isspace(&my_charset_latin1,*value); value++) ;
value_end=strend(value);
/*
We don't have to test for value_end >= value as we know there is
an '=' before
*/
for ( ; my_isspace(&my_charset_latin1,value_end[-1]) ; value_end--) ;
if (value_end < value) /* Empty string */
value_end=value;
/* remove quotes around argument */
if ((*value == '\"' || *value == '\'') && *value == value_end[-1])
{
value++;
value_end--;
}
if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3 +
(uint) (value_end-value)+1)))
goto err;
if (insert_dynamic(args,(gptr) &tmp))
goto err;
ptr=strnmov(strmov(tmp,"--"),ptr,(uint) (end-ptr));
*ptr++= '=';
for ( ; value != value_end; value++)
{
if (*value == '\\' && value != value_end-1)
{
switch(*++value) {
case 'n':
*ptr++='\n';
break;
case 't':
*ptr++= '\t';
break;
case 'r':
*ptr++ = '\r';
break;
case 'b':
*ptr++ = '\b';
break;
case 's':
*ptr++= ' '; /* space */
break;
case '\"':
*ptr++= '\"';
break;
case '\'':
*ptr++= '\'';
break;
case '\\':
*ptr++= '\\';
break;
default: /* Unknown; Keep '\' */
*ptr++= '\\';
*ptr++= *value;
break;
}
}
else
*ptr++= *value;
}
*ptr=0;
}
}
my_fclose(fp,MYF(0));
return(0);
err:
my_fclose(fp,MYF(0));
return -1; /* Fatal error */
}
static char *remove_end_comment(char *ptr)
{
char quote= 0;
for (; *ptr; ptr++)
{
if (*ptr == '\'' || *ptr == '\"')
{
if (!quote)
quote= *ptr;
else if (quote == *ptr)
quote= 0;
}
if (!quote && *ptr == '#') /* We are not inside a comment */
{
*ptr= 0;
return ptr;
}
}
return ptr;
}
void print_defaults(const char *conf_file, const char **groups)
{
#ifdef __WIN__
bool have_ext=fn_ext(conf_file)[0] != 0;
#endif
char name[FN_REFLEN];
const char **dirs;
puts("\nDefault options are read from the following files in the given order:");
if (dirname_length(conf_file))
fputs(conf_file,stdout);
else
{
#ifdef __WIN__
GetWindowsDirectory(name,sizeof(name));
printf("%s\\%s%s ",name,conf_file,have_ext ? "" : windows_ext);
#endif
#if defined(__EMX__) || defined(OS2)
if (getenv("ETC"))
printf("%s\\%s%s ", getenv("ETC"), conf_file, default_ext);
#endif
for (dirs=default_directories ; *dirs; dirs++)
{
const char *pos;
char *end;
if (**dirs)
pos= *dirs;
else if (defaults_extra_file)
pos= defaults_extra_file;
else
continue;
end=convert_dirname(name, pos, NullS);
if (name[0] == FN_HOMELIB) /* Add . to filenames in home */
*end++='.';
strxmov(end,conf_file,default_ext," ",NullS);
fputs(name,stdout);
}
puts("");
}
fputs("The following groups are read:",stdout);
for ( ; *groups ; groups++)
{
fputc(' ',stdout);
fputs(*groups,stdout);
}
puts("\nThe following options may be given as the first argument:\n\
--print-defaults Print the program argument list and exit\n\
--no-defaults Don't read default options from any options file\n\
--defaults-file=# Only read default options from the given file #\n\
--defaults-extra-file=# Read this file after the global files are read");
}