2001-12-06 13:10:51 +01:00
|
|
|
/* Copyright (C) 2000 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,
|
2001-04-11 13:04:03 +02:00
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2001-12-06 13:10:51 +01:00
|
|
|
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 */
|
2001-04-25 00:11:29 +02:00
|
|
|
|
2001-10-02 04:53:00 +02:00
|
|
|
#include "embedded_priv.h"
|
2001-04-11 13:04:03 +02:00
|
|
|
#include <my_sys.h>
|
|
|
|
#include <mysys_err.h>
|
|
|
|
#include <m_string.h>
|
|
|
|
#include <m_ctype.h>
|
|
|
|
#include "errmsg.h"
|
|
|
|
#include <violite.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <time.h>
|
|
|
|
#ifdef HAVE_PWD_H
|
|
|
|
#include <pwd.h>
|
|
|
|
#endif
|
|
|
|
#if !defined(MSDOS) && !defined(__WIN__)
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <netdb.h>
|
|
|
|
#ifdef HAVE_SELECT_H
|
|
|
|
# include <select.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_SELECT_H
|
|
|
|
#include <sys/select.h>
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_UN_H
|
|
|
|
# include <sys/un.h>
|
|
|
|
#endif
|
|
|
|
#ifndef INADDR_NONE
|
|
|
|
#define INADDR_NONE -1
|
|
|
|
#endif
|
|
|
|
|
2002-10-02 13:14:36 +02:00
|
|
|
#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS | CLIENT_PROTOCOL_41)
|
2001-04-11 13:04:03 +02:00
|
|
|
|
|
|
|
#if defined(MSDOS) || defined(__WIN__)
|
|
|
|
#define ERRNO WSAGetLastError()
|
|
|
|
#define perror(A)
|
|
|
|
#else
|
|
|
|
#include <errno.h>
|
|
|
|
#define ERRNO errno
|
|
|
|
#define SOCKET_ERROR -1
|
|
|
|
#define closesocket(A) close(A)
|
|
|
|
#endif
|
|
|
|
|
2003-06-17 18:32:31 +02:00
|
|
|
void free_old_query(MYSQL *mysql);
|
2003-08-28 10:39:46 +02:00
|
|
|
my_bool STDCALL
|
2003-06-17 18:32:31 +02:00
|
|
|
emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
|
|
|
|
const char *header, ulong header_length,
|
|
|
|
const char *arg, ulong arg_length, my_bool skip_check);
|
2001-04-11 13:04:03 +02:00
|
|
|
|
2003-07-04 08:40:10 +02:00
|
|
|
/* From client.c */
|
2003-06-17 18:32:31 +02:00
|
|
|
void mysql_read_default_options(struct st_mysql_options *options,
|
|
|
|
const char *filename,const char *group);
|
2003-06-18 12:58:57 +02:00
|
|
|
MYSQL * STDCALL
|
|
|
|
cli_mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
|
|
|
|
const char *passwd, const char *db,
|
|
|
|
uint port, const char *unix_socket,ulong client_flag);
|
2001-04-11 13:04:03 +02:00
|
|
|
|
2003-07-18 13:26:35 +02:00
|
|
|
void STDCALL cli_mysql_close(MYSQL *mysql);
|
|
|
|
|
2001-04-11 13:04:03 +02:00
|
|
|
#ifdef HAVE_GETPWUID
|
|
|
|
struct passwd *getpwuid(uid_t);
|
|
|
|
char* getlogin(void);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef __WIN__
|
|
|
|
static my_bool is_NT(void)
|
|
|
|
{
|
|
|
|
char *os=getenv("OS");
|
|
|
|
return (os && !strcmp(os, "Windows_NT")) ? 1 : 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
** Shut down connection
|
|
|
|
**************************************************************************/
|
|
|
|
|
2003-06-17 18:32:31 +02:00
|
|
|
static void end_server(MYSQL *mysql)
|
2001-04-11 13:04:03 +02:00
|
|
|
{
|
|
|
|
DBUG_ENTER("end_server");
|
|
|
|
free_old_query(mysql);
|
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
** Connect to sql server
|
|
|
|
** If host == 0 then use localhost
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
MYSQL * STDCALL
|
|
|
|
mysql_connect(MYSQL *mysql,const char *host,
|
|
|
|
const char *user, const char *passwd)
|
|
|
|
{
|
|
|
|
MYSQL *res;
|
|
|
|
mysql=mysql_init(mysql); /* Make it thread safe */
|
|
|
|
{
|
|
|
|
DBUG_ENTER("mysql_connect");
|
|
|
|
if (!(res=mysql_real_connect(mysql,host,user,passwd,NullS,0,NullS,0)))
|
|
|
|
{
|
|
|
|
if (mysql->free_me)
|
|
|
|
my_free((gptr) mysql,MYF(0));
|
|
|
|
}
|
|
|
|
DBUG_RETURN(res);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-06-17 13:24:51 +02:00
|
|
|
static inline int mysql_init_charset(MYSQL *mysql)
|
|
|
|
{
|
|
|
|
char charset_name_buff[16], *charset_name;
|
|
|
|
|
|
|
|
if ((charset_name=mysql->options.charset_name))
|
|
|
|
{
|
|
|
|
const char *save=charsets_dir;
|
|
|
|
if (mysql->options.charset_dir)
|
|
|
|
charsets_dir=mysql->options.charset_dir;
|
|
|
|
mysql->charset=get_charset_by_name(mysql->options.charset_name,
|
|
|
|
MYF(MY_WME));
|
|
|
|
charsets_dir=save;
|
|
|
|
}
|
|
|
|
else if (mysql->server_language)
|
|
|
|
{
|
|
|
|
charset_name=charset_name_buff;
|
|
|
|
sprintf(charset_name,"%d",mysql->server_language); /* In case of errors */
|
|
|
|
mysql->charset=get_charset((uint8) mysql->server_language, MYF(MY_WME));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
mysql->charset=default_charset_info;
|
|
|
|
|
|
|
|
if (!mysql->charset)
|
|
|
|
{
|
2003-07-23 12:23:20 +02:00
|
|
|
mysql->net.last_errno=CR_CANT_READ_CHARSET;
|
|
|
|
strmov(mysql->net.sqlstate, "HY0000");
|
2002-06-17 13:24:51 +02:00
|
|
|
if (mysql->options.charset_dir)
|
2003-07-23 12:23:20 +02:00
|
|
|
sprintf(mysql->net.last_error,ER(mysql->net.last_errno),
|
2002-06-17 13:24:51 +02:00
|
|
|
charset_name ? charset_name : "unknown",
|
|
|
|
mysql->options.charset_dir);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char cs_dir_name[FN_REFLEN];
|
|
|
|
get_charsets_dir(cs_dir_name);
|
2003-07-23 12:23:20 +02:00
|
|
|
sprintf(mysql->net.last_error,ER(mysql->net.last_errno),
|
2002-06-17 13:24:51 +02:00
|
|
|
charset_name ? charset_name : "unknown",
|
|
|
|
cs_dir_name);
|
|
|
|
}
|
2003-07-23 12:23:20 +02:00
|
|
|
return mysql->net.last_errno;
|
2002-06-17 13:24:51 +02:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-07-23 12:23:20 +02:00
|
|
|
/**************************************************************************
|
|
|
|
Get column lengths of the current row
|
|
|
|
If one uses mysql_use_result, res->lengths contains the length information,
|
|
|
|
else the lengths are calculated from the offset between pointers.
|
|
|
|
**************************************************************************/
|
|
|
|
|
2003-08-28 10:39:46 +02:00
|
|
|
static void STDCALL emb_fetch_lengths(ulong *to, MYSQL_ROW column, uint field_count)
|
2003-07-23 12:23:20 +02:00
|
|
|
{
|
|
|
|
MYSQL_ROW end;
|
|
|
|
|
|
|
|
for (end=column + field_count; column != end ; column++,to++)
|
|
|
|
{
|
|
|
|
*to= *column ? strlen(*column) : 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-04-11 13:04:03 +02:00
|
|
|
/*
|
|
|
|
** Note that the mysql argument must be initialized with mysql_init()
|
|
|
|
** before calling mysql_real_connect !
|
|
|
|
*/
|
|
|
|
|
2003-06-17 18:32:31 +02:00
|
|
|
static my_bool STDCALL emb_mysql_read_query_result(MYSQL *mysql);
|
|
|
|
static MYSQL_RES * STDCALL emb_mysql_store_result(MYSQL *mysql);
|
|
|
|
static MYSQL_RES * STDCALL emb_mysql_use_result(MYSQL *mysql);
|
|
|
|
|
|
|
|
static MYSQL_METHODS embedded_methods=
|
|
|
|
{
|
|
|
|
emb_mysql_read_query_result,
|
|
|
|
emb_advanced_command,
|
|
|
|
emb_mysql_store_result,
|
|
|
|
emb_mysql_use_result,
|
2003-07-23 12:23:20 +02:00
|
|
|
emb_fetch_lengths
|
2003-06-17 18:32:31 +02:00
|
|
|
};
|
|
|
|
|
2001-04-11 13:04:03 +02:00
|
|
|
MYSQL * STDCALL
|
|
|
|
mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
|
2003-06-18 12:58:57 +02:00
|
|
|
const char *passwd, const char *db,
|
2003-01-20 15:59:45 +01:00
|
|
|
uint port, const char *unix_socket,ulong client_flag)
|
2001-04-11 13:04:03 +02:00
|
|
|
{
|
2002-06-17 13:24:51 +02:00
|
|
|
char *db_name;
|
2001-04-11 13:04:03 +02:00
|
|
|
DBUG_ENTER("mysql_real_connect");
|
|
|
|
DBUG_PRINT("enter",("host: %s db: %s user: %s",
|
|
|
|
host ? host : "(Null)",
|
|
|
|
db ? db : "(Null)",
|
|
|
|
user ? user : "(Null)"));
|
|
|
|
|
2003-09-11 19:24:14 +02:00
|
|
|
if (mysql->options.methods_to_use == MYSQL_OPT_USE_REMOTE_CONNECTION ||
|
|
|
|
(mysql->options.methods_to_use == MYSQL_OPT_GUESS_CONNECTION &&
|
|
|
|
host && strcmp(host,LOCAL_HOST)))
|
2003-06-18 12:58:57 +02:00
|
|
|
cli_mysql_real_connect(mysql, host, user,
|
|
|
|
passwd, db, port, unix_socket, client_flag);
|
|
|
|
|
2003-06-17 18:32:31 +02:00
|
|
|
mysql->methods= &embedded_methods;
|
|
|
|
|
2001-04-11 13:04:03 +02:00
|
|
|
/* use default options */
|
|
|
|
if (mysql->options.my_cnf_file || mysql->options.my_cnf_group)
|
|
|
|
{
|
|
|
|
mysql_read_default_options(&mysql->options,
|
|
|
|
(mysql->options.my_cnf_file ?
|
|
|
|
mysql->options.my_cnf_file : "my"),
|
|
|
|
mysql->options.my_cnf_group);
|
|
|
|
my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
|
|
|
|
my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
|
|
|
|
mysql->options.my_cnf_file=mysql->options.my_cnf_group=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!db || !db[0])
|
|
|
|
db=mysql->options.db;
|
2002-06-17 13:24:51 +02:00
|
|
|
|
2001-04-25 00:11:29 +02:00
|
|
|
port=0;
|
|
|
|
unix_socket=0;
|
2002-06-17 13:24:51 +02:00
|
|
|
db_name = db ? my_strdup(db,MYF(MY_WME)) : NULL;
|
|
|
|
|
2002-12-16 14:33:29 +01:00
|
|
|
mysql->thd= create_embedded_thd(client_flag, db_name);
|
2001-04-11 13:04:03 +02:00
|
|
|
|
2002-06-17 13:24:51 +02:00
|
|
|
init_embedded_mysql(mysql, client_flag, db_name);
|
2001-04-11 13:04:03 +02:00
|
|
|
|
2002-06-17 13:24:51 +02:00
|
|
|
if (mysql_init_charset(mysql))
|
2001-04-11 13:04:03 +02:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
/* Send client information for access check */
|
|
|
|
client_flag|=CLIENT_CAPABILITIES;
|
2001-04-25 00:11:29 +02:00
|
|
|
client_flag&= ~CLIENT_COMPRESS;
|
2001-04-11 13:04:03 +02:00
|
|
|
if (db)
|
|
|
|
client_flag|=CLIENT_CONNECT_WITH_DB;
|
2003-06-24 11:10:35 +02:00
|
|
|
mysql->server_status= SERVER_STATUS_AUTOCOMMIT;
|
2001-04-25 00:11:29 +02:00
|
|
|
|
2002-12-19 09:27:46 +01:00
|
|
|
if (mysql->options.init_commands)
|
2001-04-11 13:04:03 +02:00
|
|
|
{
|
2002-12-19 09:27:46 +01:00
|
|
|
DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
|
|
|
|
char **ptr= (char**)init_commands->buffer;
|
|
|
|
char **end= ptr + init_commands->elements;
|
|
|
|
|
|
|
|
for (; ptr<end; ptr++)
|
|
|
|
{
|
|
|
|
MYSQL_RES *res;
|
|
|
|
if (mysql_query(mysql,*ptr))
|
|
|
|
goto error;
|
|
|
|
if (mysql->fields)
|
|
|
|
{
|
|
|
|
if (!(res= mysql_use_result(mysql)))
|
|
|
|
goto error;
|
|
|
|
mysql_free_result(res);
|
|
|
|
}
|
|
|
|
}
|
2001-04-11 13:04:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
DBUG_PRINT("exit",("Mysql handler: %lx",mysql));
|
|
|
|
DBUG_RETURN(mysql);
|
|
|
|
|
|
|
|
error:
|
2003-09-11 19:24:14 +02:00
|
|
|
DBUG_PRINT("error",("message: %u (%s)", mysql->net.last_errno,
|
|
|
|
mysql->net.last_error));
|
2001-04-11 13:04:03 +02:00
|
|
|
{
|
|
|
|
/* Free alloced memory */
|
|
|
|
my_bool free_me=mysql->free_me;
|
|
|
|
end_server(mysql);
|
|
|
|
mysql->free_me=0;
|
|
|
|
mysql_close(mysql);
|
|
|
|
mysql->free_me=free_me;
|
|
|
|
}
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
** Send a QUIT to the server and close the connection
|
|
|
|
** If handle is alloced by mysql connect free it.
|
|
|
|
*************************************************************************/
|
|
|
|
|
2003-07-18 13:26:35 +02:00
|
|
|
void STDCALL mysql_close(MYSQL *mysql)
|
2001-04-11 13:04:03 +02:00
|
|
|
{
|
|
|
|
DBUG_ENTER("mysql_close");
|
2003-07-18 13:26:35 +02:00
|
|
|
if (mysql->methods != &embedded_methods)
|
|
|
|
{
|
|
|
|
cli_mysql_close(mysql);
|
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
2001-04-11 13:04:03 +02:00
|
|
|
if (mysql) /* Some simple safety */
|
|
|
|
{
|
|
|
|
my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR));
|
|
|
|
my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR));
|
|
|
|
my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR));
|
|
|
|
my_free(mysql->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR));
|
|
|
|
my_free(mysql->options.db,MYF(MY_ALLOW_ZERO_PTR));
|
|
|
|
my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
|
|
|
|
my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
|
|
|
|
my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
|
|
|
|
my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
|
2002-12-17 16:13:07 +01:00
|
|
|
if (mysql->options.init_commands)
|
|
|
|
{
|
2002-12-20 23:53:07 +01:00
|
|
|
DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
|
|
|
|
char **ptr= (char**)init_commands->buffer;
|
|
|
|
char **end= ptr + init_commands->elements;
|
|
|
|
for (; ptr<end; ptr++)
|
|
|
|
my_free(*ptr,MYF(MY_WME));
|
|
|
|
delete_dynamic(init_commands);
|
|
|
|
my_free((char*)init_commands,MYF(MY_WME));
|
2002-12-17 16:13:07 +01:00
|
|
|
}
|
2001-04-11 13:04:03 +02:00
|
|
|
/* Clear pointers for better safety */
|
|
|
|
bzero((char*) &mysql->options,sizeof(mysql->options));
|
|
|
|
#ifdef HAVE_OPENSSL
|
|
|
|
((VioConnectorFd*)(mysql->connector_fd))->delete();
|
|
|
|
mysql->connector_fd = 0;
|
|
|
|
#endif /* HAVE_OPENSSL */
|
|
|
|
if (mysql->free_me)
|
|
|
|
my_free((gptr) mysql,MYF(0));
|
|
|
|
}
|
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
2003-06-17 18:32:31 +02:00
|
|
|
static my_bool STDCALL emb_mysql_read_query_result(MYSQL *mysql)
|
2001-04-11 13:04:03 +02:00
|
|
|
{
|
2003-07-23 12:23:20 +02:00
|
|
|
if (mysql->net.last_errno)
|
2002-06-17 13:24:51 +02:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (mysql->field_count)
|
2001-04-11 13:04:03 +02:00
|
|
|
{
|
2002-06-17 13:24:51 +02:00
|
|
|
mysql->status=MYSQL_STATUS_GET_RESULT;
|
|
|
|
mysql->affected_rows= mysql->result->row_count= mysql->result->data->rows;
|
|
|
|
mysql->result->data_cursor= mysql->result->data->data;
|
2001-04-11 13:04:03 +02:00
|
|
|
}
|
|
|
|
|
2002-06-17 13:24:51 +02:00
|
|
|
return 0;
|
2001-04-11 13:04:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
** Alloc result struct for buffered results. All rows are read to buffer.
|
|
|
|
** mysql_data_seek may be used.
|
|
|
|
**************************************************************************/
|
2003-06-17 18:32:31 +02:00
|
|
|
static MYSQL_RES * STDCALL emb_mysql_store_result(MYSQL *mysql)
|
2001-04-11 13:04:03 +02:00
|
|
|
{
|
2002-06-17 13:24:51 +02:00
|
|
|
MYSQL_RES *result= mysql->result;
|
|
|
|
if (!result)
|
|
|
|
return 0;
|
2003-07-23 12:23:20 +02:00
|
|
|
|
|
|
|
result->methods= mysql->methods;
|
2002-06-17 13:24:51 +02:00
|
|
|
mysql->result= NULL;
|
|
|
|
*result->data->prev_ptr= 0;
|
|
|
|
result->eof= 1;
|
|
|
|
result->lengths= (ulong*)(result + 1);
|
2001-04-11 13:04:03 +02:00
|
|
|
mysql->affected_rows= result->row_count= result->data->rows;
|
2002-06-17 13:24:51 +02:00
|
|
|
result->data_cursor= result->data->data;
|
2001-04-11 13:04:03 +02:00
|
|
|
|
2002-06-17 13:24:51 +02:00
|
|
|
mysql->status=MYSQL_STATUS_READY; /* server is ready */
|
|
|
|
return result;
|
2001-04-11 13:04:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
** Alloc struct for use with unbuffered reads. Data is fetched by domand
|
|
|
|
** when calling to mysql_fetch_row.
|
|
|
|
** mysql_data_seek is a noop.
|
|
|
|
**
|
|
|
|
** No other queries may be specified with the same MYSQL handle.
|
|
|
|
** There shouldn't be much processing per row because mysql server shouldn't
|
|
|
|
** have to wait for the client (and will not wait more than 30 sec/packet).
|
|
|
|
**************************************************************************/
|
|
|
|
|
2003-06-17 18:32:31 +02:00
|
|
|
static MYSQL_RES * STDCALL emb_mysql_use_result(MYSQL *mysql)
|
2001-04-11 13:04:03 +02:00
|
|
|
{
|
|
|
|
DBUG_ENTER("mysql_use_result");
|
2002-06-17 13:24:51 +02:00
|
|
|
if (mysql->options.separate_thread)
|
2001-04-11 13:04:03 +02:00
|
|
|
DBUG_RETURN(0);
|
|
|
|
|
2003-06-17 18:32:31 +02:00
|
|
|
DBUG_RETURN(emb_mysql_store_result(mysql));
|
2003-06-24 11:10:35 +02:00
|
|
|
}
|