1 /* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 #include <my_global.h>
24 #include <mysql.h>
25 #include <mysqld_error.h>
26 #include <my_thread.h>
27 #include <my_sys.h>
28 #include <mysys_err.h>
29 #include <m_string.h>
30 #include <m_ctype.h>
31 #include "errmsg.h"
32 #include <violite.h>
33 #include <sys/stat.h>
34 #include <signal.h>
35 #include <time.h>
36 #include <sql_common.h>
37 #include "embedded_priv.h"
38 #include "client_settings.h"
39 #ifdef HAVE_PWD_H
40 #include <pwd.h>
41 #endif
42 #ifdef HAVE_SYS_SELECT_H
43 #include <sys/select.h>
44 #endif
45 #ifdef HAVE_SYS_UN_H
46 # include <sys/un.h>
47 #endif
48 #ifndef INADDR_NONE
49 #define INADDR_NONE -1
50 #endif
51
52 ulong net_buffer_length;
53 ulong max_allowed_packet;
54
55 #if defined(_WIN32)
56 #define ERRNO WSAGetLastError()
57 #define perror(A)
58 #else
59 #include <errno.h>
60 #define ERRNO errno
61 #define SOCKET_ERROR -1
62 #define closesocket(A) close(A)
63 #endif
64
65 #ifdef HAVE_GETPWUID
66 struct passwd *getpwuid(uid_t);
67 char* getlogin(void);
68 #endif
69
70 #ifdef _WIN32
is_NT(void)71 static my_bool is_NT(void)
72 {
73 char *os=getenv("OS");
74 return (os && !strcmp(os, "Windows_NT")) ? 1 : 0;
75 }
76 #endif
77
78
79 int mysql_init_character_set(MYSQL *mysql);
80
81 MYSQL * STDCALL
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)82 mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
83 const char *passwd, const char *db,
84 uint port, const char *unix_socket,ulong client_flag)
85 {
86 char name_buff[USERNAME_LENGTH + 1];
87
88 DBUG_ENTER("mysql_real_connect");
89 DBUG_PRINT("enter",("host: %s db: %s user: %s (libmysqld)",
90 host ? host : "(Null)",
91 db ? db : "(Null)",
92 user ? user : "(Null)"));
93
94 /* Test whether we're already connected */
95 if (mysql->server_version)
96 {
97 set_mysql_error(mysql, CR_ALREADY_CONNECTED, unknown_sqlstate);
98 DBUG_RETURN(0);
99 }
100
101 if (!host || !host[0])
102 host= mysql->options.host;
103
104 if (mysql->options.methods_to_use == MYSQL_OPT_USE_REMOTE_CONNECTION ||
105 (mysql->options.methods_to_use == MYSQL_OPT_GUESS_CONNECTION &&
106 host && *host && strcmp(host,LOCAL_HOST)))
107 DBUG_RETURN(cli_mysql_real_connect(mysql, host, user,
108 passwd, db, port,
109 unix_socket, client_flag));
110
111 mysql->methods= &embedded_methods;
112
113 /* use default options */
114 if (mysql->options.my_cnf_file || mysql->options.my_cnf_group)
115 {
116 mysql_read_default_options(&mysql->options,
117 (mysql->options.my_cnf_file ?
118 mysql->options.my_cnf_file : "my"),
119 mysql->options.my_cnf_group);
120 my_free(mysql->options.my_cnf_file);
121 my_free(mysql->options.my_cnf_group);
122 mysql->options.my_cnf_file=mysql->options.my_cnf_group=0;
123 }
124
125 if (!db || !db[0])
126 db=mysql->options.db;
127
128 if (!user || !user[0])
129 user=mysql->options.user;
130
131 #ifndef NO_EMBEDDED_ACCESS_CHECKS
132 if (!passwd)
133 {
134 passwd=mysql->options.password;
135 if (!passwd)
136 passwd=getenv("MYSQL_PWD"); /* get it from environment */
137 }
138 mysql->passwd= passwd ? my_strdup(PSI_NOT_INSTRUMENTED,
139 passwd,MYF(0)) : NULL;
140 #endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
141 if (!user || !user[0])
142 {
143 read_user_name(name_buff);
144 if (name_buff[0])
145 user= name_buff;
146 }
147
148 if (!user)
149 user= "";
150 /*
151 We need to alloc some space for mysql->info but don't want to
152 put extra 'my_free's in mysql_close.
153 So we alloc it with the 'user' string to be freed at once
154 */
155 mysql->user= my_strdup(PSI_NOT_INSTRUMENTED,
156 user, MYF(0));
157
158 port=0;
159 unix_socket=0;
160
161 client_flag|=mysql->options.client_flag;
162 /* Send client information for access check */
163 client_flag|=CLIENT_CAPABILITIES;
164 if (client_flag & CLIENT_MULTI_STATEMENTS)
165 client_flag|= CLIENT_MULTI_RESULTS;
166 /*
167 no compression in embedded as we don't send any data,
168 and no pluggable auth, as we cannot do a client-server dialog
169 */
170 client_flag&= ~(CLIENT_COMPRESS | CLIENT_PLUGIN_AUTH);
171 if (db)
172 client_flag|=CLIENT_CONNECT_WITH_DB;
173
174 if (embedded_ssl_check(mysql))
175 goto error;
176
177 mysql->info_buffer= my_malloc(PSI_NOT_INSTRUMENTED,
178 MYSQL_ERRMSG_SIZE, MYF(0));
179 mysql->thd= create_embedded_thd(client_flag);
180
181 init_embedded_mysql(mysql, client_flag);
182
183 if (mysql_init_character_set(mysql))
184 goto error;
185
186 if (check_embedded_connection(mysql, db))
187 goto error;
188
189 mysql->server_status= SERVER_STATUS_AUTOCOMMIT;
190
191 if (mysql->options.init_commands)
192 {
193 DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
194 char **ptr= (char**)init_commands->buffer;
195 char **end= ptr + init_commands->elements;
196
197 for (; ptr<end; ptr++)
198 {
199 MYSQL_RES *res;
200 if (mysql_query(mysql,*ptr))
201 goto error;
202 if (mysql->fields)
203 {
204 if (!(res= (*mysql->methods->use_result)(mysql)))
205 goto error;
206 mysql_free_result(res);
207 }
208 }
209 }
210
211 DBUG_PRINT("exit",("Mysql handler: 0x%lx", (long) mysql));
212 DBUG_RETURN(mysql);
213
214 error:
215 DBUG_PRINT("error",("message: %u (%s)",
216 mysql->net.last_errno,
217 mysql->net.last_error));
218 {
219 /* Free alloced memory */
220 my_bool free_me=mysql->free_me;
221 free_old_query(mysql);
222 mysql->free_me=0;
223 mysql_close(mysql);
224 mysql->free_me=free_me;
225 }
226 DBUG_RETURN(0);
227 }
228
229