/* * Copyright (c) 2000 * SWsoft company * * This material is provided "as is", with absolutely no warranty expressed * or implied. Any use is at your own risk. * * Permission to use or copy this software for any purpose is hereby granted * without fee, provided the above notices are retained on all copies. * Permission to modify the code and to distribute modified code is granted, * provided the above notices are retained, and a notice that the code was * modified is included with the above copyright notice. * This code was modified by the MySQL team */ /* The following is needed to not cause conflicts when we include mysqld.cc */ #define main main1 #define mysql_unix_port mysql_inix_port1 #define mysql_port mysql_port1 static int fake_argc= 1; static char *fake_argv[]= {(char *)"", 0}; static const char *fake_groups[] = { "server", "embedded", 0 }; static char inited, org_my_init_done; #if defined (__WIN__) #include "../sql/mysqld.cpp" #else #include "../sql/mysqld.cc" #endif #define SCRAMBLE_LENGTH 8 C_MODE_START #include #include "errmsg.h" static int check_connections1(THD * thd); static int check_connections2(THD * thd); static bool check_user(THD *thd, enum_server_command command, const char *user, const char *passwd, const char *db, bool check_count); char * get_mysql_home(){ return mysql_home;}; char * get_mysql_real_data_home(){ return mysql_real_data_home;}; my_bool simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg, ulong length, my_bool skipp_check) { my_bool result= 1; THD *thd=(THD *) mysql->thd; /* Check that we are calling the client functions in right order */ if (mysql->status != MYSQL_STATUS_READY) { strmov(thd->net.last_error, ER(thd->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); return 1; } /* Clear result variables */ thd->net.last_error[0]=0; thd->net.last_errno=0; mysql->affected_rows= ~(my_ulonglong) 0; thd->store_globals(); // Fix if more than one connect result= dispatch_command(command, thd, (char *) arg, length + 1); if (!skipp_check) result= thd->net.last_errno ? -1 : 0; mysql->last_error= thd->net.last_error; mysql->last_errno= thd->net.last_errno; return result; } C_MODE_END void THD::clear_error() { net.last_error[0]= 0; net.last_errno= 0; net.report_error= 0; } static bool check_user(THD *thd,enum_server_command command, const char *user, const char *passwd, const char *db, bool check_count) { thd->db=0; if (!(thd->user = my_strdup(user, MYF(0)))) { send_error(thd,ER_OUT_OF_RESOURCES); return 1; } thd->master_access= ~0L; // No user checking thd->priv_user= thd->user; mysql_log.write(thd,command, (thd->priv_user == thd->user ? (char*) "%s@%s on %s" : (char*) "%s@%s as anonymous on %s"), user, thd->host_or_ip, db ? db : (char*) ""); thd->db_access=0; if (db && db[0]) return test(mysql_change_db(thd,db)); else send_ok(thd); // Ready to handle questions return 0; // ok } /* Make a copy of array and the strings array points to */ char **copy_arguments(int argc, char **argv) { uint length= 0; char **from, **res, **end= argv+argc; for (from=argv ; from != end ; from++) length+= strlen(*from); if ((res= (char**) my_malloc(sizeof(argv)*(argc+1)+length+argc, MYF(MY_WME)))) { char **to= res, *to_str= (char*) (res+argc+1); for (from=argv ; from != end ;) { *to++= to_str; to_str= strmov(to_str, *from++)+1; } *to= 0; // Last ptr should be null } return res; } extern "C" { ulong max_allowed_packet, net_buffer_length; char ** copy_arguments_ptr= 0; int STDCALL mysql_server_init(int argc, char **argv, char **groups) { char glob_hostname[FN_REFLEN]; /* This mess is to allow people to call the init function without * having to mess with a fake argv */ int *argcp; char ***argvp; int fake_argc = 1; char *fake_argv[] = { (char *)"", 0 }; const char *fake_groups[] = { "server", "embedded", 0 }; if (argc) { argcp= &argc; argvp= (char***) &argv; } else { argcp= &fake_argc; argvp= (char ***) &fake_argv; } if (!groups) groups= (char**) fake_groups; /* Only call MY_INIT() if it hasn't been called before */ if (!inited) { inited=1; org_my_init_done=my_init_done; } if (!org_my_init_done) { MY_INIT((char *)"mysql_embedded"); // init my_sys library & pthreads } if (init_common_variables("my", argc, argv, (const char **)groups)) { mysql_server_end(); return 1; } /* Get default temporary directory */ opt_mysql_tmpdir=getenv("TMPDIR"); /* Use this if possible */ #if defined( __WIN__) || defined(OS2) if (!opt_mysql_tmpdir) opt_mysql_tmpdir=getenv("TEMP"); if (!opt_mysql_tmpdir) opt_mysql_tmpdir=getenv("TMP"); #endif if (!opt_mysql_tmpdir || !opt_mysql_tmpdir[0]) opt_mysql_tmpdir=(char*) P_tmpdir; /* purecov: inspected */ if (init_thread_environment()) { mysql_server_end(); return 1; } umask(((~my_umask) & 0666)); if (init_server_components()) { mysql_server_end(); return 1; } error_handler_hook = my_message_sql; opt_noacl = 1; // No permissions if (acl_init((THD *)0, opt_noacl)) { mysql_server_end(); return 1; } if (!opt_noacl) (void) grant_init((THD *)0); init_max_user_conn(); init_update_queries(); #ifdef HAVE_DLOPEN if (!opt_noacl) udf_init(); #endif if (opt_bin_log) { if (!opt_bin_logname) { char tmp[FN_REFLEN]; /* TODO: The following should be using fn_format(); We just need to first change fn_format() to cut the file name if it's too long. */ strmake(tmp,glob_hostname,FN_REFLEN-5); strmov(strcend(tmp,'.'),"-bin"); opt_bin_logname=my_strdup(tmp,MYF(MY_WME)); } open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin", opt_binlog_index_name, LOG_BIN); using_update_log=1; } (void) thr_setconcurrency(concurrency); // 10 by default if ( #ifdef HAVE_BERKELEY_DB !berkeley_skip || #endif (flush_time && flush_time != ~(ulong) 0L)) { pthread_t hThread; if (pthread_create(&hThread,&connection_attrib,handle_manager,0)) sql_print_error("Warning: Can't create thread to manage maintenance"); } /* Update mysqld variables from client variables if set The client variables are set also by get_one_option() in mysqld.cc */ if (max_allowed_packet) global_system_variables.max_allowed_packet= max_allowed_packet; if (net_buffer_length) global_system_variables.net_buffer_length= net_buffer_length; return 0; } void STDCALL mysql_server_end() { my_free((char*) copy_arguments_ptr, MYF(MY_ALLOW_ZERO_PTR)); copy_arguments_ptr=0; clean_up(0); #ifdef THREAD /* Don't call my_thread_end() if the application is using MY_INIT() */ if (!org_my_init_done) my_thread_end(); #endif /* If library called my_init(), free memory allocated by it */ if (!org_my_init_done) my_end(0); } my_bool STDCALL mysql_thread_init() { #ifdef THREAD return my_thread_init(); #else return 0; #endif } void STDCALL mysql_thread_end() { #ifdef THREAD my_thread_end(); #endif } } /* extern "C" */ C_MODE_START void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db) { THD *thd = (THD *)mysql->thd; thd->mysql= mysql; mysql->last_error= thd->net.last_error; } void *create_embedded_thd(int client_flag, char *db) { THD * thd= new THD; thd->thread_id= thread_id++; if (thd->store_globals()) { fprintf(stderr,"store_globals failed.\n"); return NULL; } thd->mysys_var= my_thread_var; thd->dbug_thread_id= my_thread_id(); thd->thread_stack= (char*) &thd; thd->proc_info=0; // Remove 'login' thd->command=COM_SLEEP; thd->version=refresh_version; thd->set_time(); init_sql_alloc(&thd->mem_root,8192,8192); thd->client_capabilities= client_flag; thd->db= db; thd->db_length= db ? strip_sp(db) : 0; thd->db_access= DB_ACLS; thd->master_access= ~NO_ACCESS; thd->net.query_cache_query= 0; return thd; } C_MODE_END bool Protocol::send_fields(List *list, uint flag) { List_iterator_fast it(*list); Item *item; MYSQL_FIELD *field, *client_field; MYSQL *mysql= thd->mysql; DBUG_ENTER("send_fields"); field_count= list->elements; if (!(mysql->result=(MYSQL_RES*) my_malloc(sizeof(MYSQL_RES)+ sizeof(ulong) * (field_count + 1), MYF(MY_WME | MY_ZEROFILL)))) goto err; mysql->result->lengths= (ulong *)(mysql->result + 1); mysql->field_count=field_count; alloc= &mysql->field_alloc; field= (MYSQL_FIELD *)alloc_root(alloc, sizeof(MYSQL_FIELD) * field_count); if (!field) goto err; client_field= field; while ((item= it++)) { Send_field server_field; item->make_field(&server_field); client_field->table= strdup_root(alloc, server_field.table_name); client_field->name= strdup_root(alloc,server_field.col_name); client_field->length= server_field.length; client_field->type= server_field.type; client_field->flags= server_field.flags; client_field->decimals= server_field.decimals; if (INTERNAL_NUM_FIELD(client_field)) client_field->flags|= NUM_FLAG; if (flag & 2) { char buff[80]; String tmp(buff, sizeof(buff), default_charset_info), *res; if (!(res=item->val_str(&tmp))) client_field->def= strdup_root(alloc, ""); else client_field->def= strdup_root(alloc, tmp.ptr()); } else client_field->def=0; client_field->max_length= 0; ++client_field; } mysql->result->fields = field; if (!(mysql->result->data= (MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), MYF(MY_WME | MY_ZEROFILL)))) goto err; init_alloc_root(&mysql->result->data->alloc,8192,0); /* Assume rowlength < 8192 */ mysql->result->data->alloc.min_malloc=sizeof(MYSQL_ROWS); mysql->result->data->rows=0; mysql->result->data->fields=field_count; mysql->result->field_count=field_count; mysql->result->data->prev_ptr= &mysql->result->data->data; mysql->result->field_alloc= mysql->field_alloc; mysql->result->current_field=0; mysql->result->current_row=0; DBUG_RETURN(prepare_for_send(list)); err: send_error(thd, ER_OUT_OF_RESOURCES); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */ } bool Protocol::send_records_num(List *list, ulonglong records) { return false; } bool Protocol::write() { *next_field= 0; return false; } void send_ok(THD *thd,ha_rows affected_rows,ulonglong id,const char *message) { DBUG_ENTER("send_ok"); MYSQL *mysql= current_thd->mysql; mysql->affected_rows= affected_rows; mysql->insert_id= id; if (message) { strmake(thd->net.last_error, message, sizeof(thd->net.last_error)-1); } DBUG_VOID_RETURN; } void send_eof(THD *thd, bool no_flush) { } uint STDCALL mysql_warning_count(MYSQL *mysql) { return ((THD *)mysql->thd)->total_warn_count; } void Protocol_simple::prepare_for_resend() { MYSQL_ROWS *cur; ulong len; MYSQL_DATA *result= thd->mysql->result->data; DBUG_ENTER("send_data"); alloc= &result->alloc; result->rows++; if (!(cur= (MYSQL_ROWS *)alloc_root(alloc, sizeof(MYSQL_ROWS)+(field_count + 1) * sizeof(char *)))) { my_error(ER_OUT_OF_RESOURCES,MYF(0)); DBUG_VOID_RETURN; } cur->data= (MYSQL_ROW)(((char *)cur) + sizeof(MYSQL_ROWS)); *result->prev_ptr= cur; result->prev_ptr= &cur->next; next_field=cur->data; next_mysql_field= thd->mysql->result->fields; DBUG_VOID_RETURN; } bool Protocol_simple::store_null() { *(next_field++)= NULL; ++next_mysql_field; return false; } bool Protocol::net_store_data(const char *from, uint length) { if (!(*next_field=alloc_root(alloc, length + 1))) return true; memcpy(*next_field, from, length); (*next_field)[length]= 0; if (next_mysql_field->max_length < length) next_mysql_field->max_length=length; ++next_field; ++next_mysql_field; return false; } /* The same as Protocol::net_store_data but does the converstion */ bool Protocol::convert_str(const char *from, uint length) { if (!(*next_field=alloc_root(alloc, length + 1))) return true; convert->store_dest(*next_field, from, length); (*next_field)[length]= 0; if (next_mysql_field->max_length < length) next_mysql_field->max_length=length; ++next_field; ++next_mysql_field; return false; }