1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 08:47:17 +01:00
SqMod/vendor/MDBC/libmariadb/ma_default.c

371 lines
9.7 KiB
C
Raw Normal View History

/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
2016 MariaDB Corporation AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02111-1301, USA */
#include <ma_global.h>
#include <ma_sys.h>
#include "ma_string.h"
#include <ctype.h>
#include "mariadb_ctype.h"
#include <mysql.h>
#include <ma_common.h>
#include <mariadb/ma_io.h>
#ifdef _WIN32
#include <io.h>
#include "shlwapi.h"
static const char *ini_exts[]= {"ini", "cnf", 0};
#define R_OK 4
#else
#include <unistd.h>
static const char *ini_exts[]= {"cnf", 0};
#endif
char **configuration_dirs= NULL;
#define MAX_CONFIG_DIRS 6
my_bool _mariadb_read_options(MYSQL *mysql,
const char *config_dir,
const char *config_file,
const char *group,
unsigned int recursion);
static int add_cfg_dir(char **cfg_dirs, const char *directory)
{
int i;
for (i = 0; i < MAX_CONFIG_DIRS && cfg_dirs[i]; i++)
if (!strcmp(cfg_dirs[i], directory)) /* already present */
return 0;
if (i < MAX_CONFIG_DIRS) {
cfg_dirs[i]= strdup(directory);
return 0;
}
return 1;
}
void release_configuration_dirs()
{
if (configuration_dirs)
{
int i= 0;
while (configuration_dirs[i])
free(configuration_dirs[i++]);
free(configuration_dirs);
}
}
char **get_default_configuration_dirs()
{
#ifdef _WIN32
char dirname[FN_REFLEN];
#endif
char *env;
configuration_dirs= (char **)calloc(1, (MAX_CONFIG_DIRS + 1) * sizeof(char *));
if (!configuration_dirs)
goto end;
#ifdef _WIN32
/* On Windows operating systems configuration files are stored in
1. System Windows directory
2. System directory
3. Windows directory
4. C:\
*/
if (!GetSystemWindowsDirectory(dirname, FN_REFLEN) ||
add_cfg_dir(configuration_dirs, dirname))
goto error;
if (!GetWindowsDirectory(dirname, FN_REFLEN) ||
add_cfg_dir(configuration_dirs, dirname))
goto error;
if (add_cfg_dir(configuration_dirs, "C:"))
goto error;
if (GetModuleFileName(NULL, dirname, FN_REFLEN))
{
PathRemoveFileSpec(dirname);
if (add_cfg_dir(configuration_dirs, dirname))
goto error;
}
#else
/* on *nix platforms configuration files are stored in
1. SYSCONFDIR (if build happens inside server package, or
-DDEFAULT_SYSCONFDIR was specified
2. /etc
3. /etc/mysql
*/
#ifdef DEFAULT_SYSCONFDIR
if (add_cfg_dir(configuration_dirs, DEFAULT_SYSCONFDIR))
goto error;
#else
if (add_cfg_dir(configuration_dirs, "/etc"))
goto error;
if (add_cfg_dir(configuration_dirs, "/etc/mysql"))
goto error;
#endif
#endif
/* CONC-537: Read configuration files from MYSQL_HOME directory only if
MARIADB_HOME was not set */
if (!(env= getenv("MARIADB_HOME")))
env= getenv("MYSQL_HOME");
if (env && add_cfg_dir(configuration_dirs, env))
goto error;
end:
return configuration_dirs;
error:
return NULL;
}
extern my_bool _mariadb_set_conf_option(MYSQL *mysql, const char *config_option, const char *config_value);
static my_bool is_group(char *ptr, const char **groups)
{
while (*groups)
{
if (!strcmp(ptr, *groups))
return 1;
groups++;
}
return 0;
}
static my_bool _mariadb_read_options_from_file(MYSQL *mysql,
const char *config_file,
const char *group,
unsigned int recursion)
{
uint line=0;
my_bool read_values= 0, found_group= 0, is_escaped= 0, is_quoted= 0;
char buff[4096],*ptr,*end,*value, *key= 0, *optval;
MA_FILE *file= NULL;
my_bool rc= 1;
const char *groups[5]= {"client",
"client-server",
"client-mariadb",
group,
NULL};
my_bool (*set_option)(MYSQL *mysql, const char *config_option, const char *config_value);
/* if a plugin registered a hook we will call this hook, otherwise
* default (_mariadb_set_conf_option) will be called */
if (mysql->options.extension && mysql->options.extension->set_option)
set_option= mysql->options.extension->set_option;
else
set_option= _mariadb_set_conf_option;
if (!(file = ma_open(config_file, "r", NULL)))
goto err;
while (ma_gets(buff,sizeof(buff)-1,file))
{
line++;
key= 0;
/* Ignore comment and empty lines */
for (ptr=buff ; isspace(*ptr) ; ptr++ );
if (!is_escaped && (*ptr == '\"' || *ptr== '\''))
{
is_quoted= !is_quoted;
continue;
}
/* CONC- 327: !includedir and !include */
if (*ptr == '!')
{
char *val;
ptr++;
if (!(val= strchr(ptr, ' ')))
continue;
*val++= 0;
end= strchr(val, 0);
for ( ; isspace(end[-1]) ; end--) ; /* Remove end space */
*end= 0;
if (!strcmp(ptr, "includedir"))
_mariadb_read_options(mysql, (const char *)val, NULL, group, recursion + 1);
else if (!strcmp(ptr, "include"))
_mariadb_read_options(mysql, NULL, (const char *)val, group, recursion + 1);
continue;
}
if (*ptr == '#' || *ptr == ';' || !*ptr)
continue;
is_escaped= (*ptr == '\\');
if (*ptr == '[') /* Group name */
{
found_group=1;
if (!(end=(char *) strchr(++ptr,']')))
{
/* todo: set error */
goto err;
}
for ( ; isspace(end[-1]) ; end--) ; /* Remove end space */
end[0]=0;
read_values= is_group(ptr, groups);
continue;
}
if (!found_group)
{
/* todo: set error */
goto err;
}
if (!read_values)
continue;
if (!(end=value=strchr(ptr,'=')))
{
end=strchr(ptr, '\0'); /* Option without argument */
set_option(mysql, ptr, NULL);
}
if (!key)
key= ptr;
for ( ; isspace(end[-1]) ; end--) ;
*end= 0;
if (value)
{
/* Remove pre- and end space */
char *value_end;
*value= 0;
value++;
ptr= value;
for ( ; isspace(*value); value++) ;
value_end=strchr(value, '\0');
*value_end= 0;
optval= ptr;
for ( ; isspace(value_end[-1]) ; value_end--) ;
/* remove possible quotes */
if (*value == '\'' || *value == '\"')
{
value++;
if (value_end[-1] == '\'' || value_end[-1] == '\"')
value_end--;
}
if (value_end < value) /* Empty string */
value_end=value;
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;
set_option(mysql, key, optval);
key= optval= 0;
}
}
rc= 0;
err:
if (file)
ma_close(file);
return rc;
}
my_bool _mariadb_read_options(MYSQL *mysql,
const char *config_dir,
const char *config_file,
const char *group,
unsigned int recursion)
{
int i= 0,
exts,
errors= 0;
char filename[FN_REFLEN + 1];
unsigned int recursion_stop= 64;
#ifndef _WIN32
char *env;
#endif
if (recursion >= recursion_stop)
return 1;
if (config_file && config_file[0])
return _mariadb_read_options_from_file(mysql, config_file, group, recursion);
if (config_dir && config_dir[0])
{
for (exts= 0; ini_exts[exts]; exts++)
{
snprintf(filename, FN_REFLEN,
"%s%cmy.%s", config_dir, FN_LIBCHAR, ini_exts[exts]);
if (!access(filename, R_OK))
errors+= _mariadb_read_options_from_file(mysql, filename, group, recursion);
}
return errors;
}
for (i=0; i < MAX_CONFIG_DIRS && configuration_dirs[i]; i++)
{
for (exts= 0; ini_exts[exts]; exts++)
{
snprintf(filename, FN_REFLEN,
"%s%cmy.%s", configuration_dirs[i], FN_LIBCHAR, ini_exts[exts]);
if (!access(filename, R_OK))
errors+= _mariadb_read_options_from_file(mysql, filename, group, recursion);
}
}
#ifndef _WIN32
/* special case: .my.cnf in Home directory */
if ((env= getenv("HOME")))
{
for (exts= 0; ini_exts[exts]; exts++)
{
snprintf(filename, FN_REFLEN,
"%s%c.my.%s", env, FN_LIBCHAR, ini_exts[exts]);
if (!access(filename, R_OK))
errors+= _mariadb_read_options_from_file(mysql, filename, group, recursion);
}
}
#endif
return errors;
}