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_pthread.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 #if !defined(__WIN__)
43 #ifdef HAVE_SELECT_H
44 #  include <select.h>
45 #endif
46 #ifdef HAVE_SYS_SELECT_H
47 #include <sys/select.h>
48 #endif
49 #endif
50 #ifdef HAVE_SYS_UN_H
51 #  include <sys/un.h>
52 #endif
53 #ifndef INADDR_NONE
54 #define INADDR_NONE	-1
55 #endif
56 
57 extern ulong net_buffer_length;
58 extern ulong max_allowed_packet;
59 
60 #if defined(__WIN__)
61 #define ERRNO WSAGetLastError()
62 #define perror(A)
63 #else
64 #include <errno.h>
65 #define ERRNO errno
66 #define SOCKET_ERROR -1
67 #define closesocket(A) close(A)
68 #endif
69 
70 #ifdef HAVE_GETPWUID
71 struct passwd *getpwuid(uid_t);
72 char* getlogin(void);
73 #endif
74 
75 #ifdef __WIN__
is_NT(void)76 static my_bool is_NT(void)
77 {
78   char *os=getenv("OS");
79   return (os && !strcmp(os, "Windows_NT")) ? 1 : 0;
80 }
81 #endif
82 
83 
84 int mysql_init_character_set(MYSQL *mysql);
85 
86 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)87 mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
88 		   const char *passwd, const char *db,
89 		   uint port, const char *unix_socket,ulong client_flag)
90 {
91   char name_buff[USERNAME_LENGTH + 1];
92 
93   DBUG_ENTER("mysql_real_connect");
94   DBUG_PRINT("enter",("host: %s  db: %s  user: %s (libmysqld)",
95 		      host ? host : "(Null)",
96 		      db ? db : "(Null)",
97 		      user ? user : "(Null)"));
98 
99   /* Test whether we're already connected */
100   if (mysql->server_version)
101   {
102     set_mysql_error(mysql, CR_ALREADY_CONNECTED, unknown_sqlstate);
103     DBUG_RETURN(0);
104   }
105 
106   if (!host || !host[0])
107     host= mysql->options.host;
108 
109   if (mysql->options.methods_to_use == MYSQL_OPT_USE_REMOTE_CONNECTION ||
110       (mysql->options.methods_to_use == MYSQL_OPT_GUESS_CONNECTION &&
111        host && *host && strcmp(host,LOCAL_HOST)))
112     DBUG_RETURN(cli_mysql_real_connect(mysql, host, user,
113 				       passwd, db, port,
114 				       unix_socket, client_flag));
115 
116   mysql->methods= &embedded_methods;
117 
118   /* use default options */
119   if (mysql->options.my_cnf_file || mysql->options.my_cnf_group)
120   {
121     mysql_read_default_options(&mysql->options,
122 			       (mysql->options.my_cnf_file ?
123 				mysql->options.my_cnf_file : "my"),
124 			       mysql->options.my_cnf_group);
125     my_free(mysql->options.my_cnf_file);
126     my_free(mysql->options.my_cnf_group);
127     mysql->options.my_cnf_file=mysql->options.my_cnf_group=0;
128   }
129 
130   if (!db || !db[0])
131     db=mysql->options.db;
132 
133   if (!user || !user[0])
134     user=mysql->options.user;
135 
136 #ifndef NO_EMBEDDED_ACCESS_CHECKS
137   if (!passwd)
138   {
139     passwd=mysql->options.password;
140 #if !defined(DONT_USE_MYSQL_PWD)
141     if (!passwd)
142       passwd=getenv("MYSQL_PWD");		/* get it from environment */
143 #endif
144   }
145   mysql->passwd= passwd ? my_strdup(passwd,MYF(0)) : NULL;
146 #endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
147   if (!user || !user[0])
148   {
149     read_user_name(name_buff);
150     if (name_buff[0])
151       user= name_buff;
152   }
153 
154   if (!user)
155     user= "";
156    /*
157       We need to alloc some space for mysql->info but don't want to
158       put extra 'my_free's in mysql_close.
159       So we alloc it with the 'user' string to be freed at once
160    */
161   mysql->user= my_strdup(user, MYF(0));
162 
163   port=0;
164   unix_socket=0;
165 
166   client_flag|=mysql->options.client_flag;
167   /* Send client information for access check */
168   client_flag|=CLIENT_CAPABILITIES;
169   if (client_flag & CLIENT_MULTI_STATEMENTS)
170     client_flag|= CLIENT_MULTI_RESULTS;
171   /*
172     no compression in embedded as we don't send any data,
173     and no pluggable auth, as we cannot do a client-server dialog
174   */
175   client_flag&= ~(CLIENT_COMPRESS | CLIENT_PLUGIN_AUTH);
176   if (db)
177     client_flag|=CLIENT_CONNECT_WITH_DB;
178 
179   if (embedded_ssl_check(mysql))
180     goto error;
181 
182   mysql->info_buffer= my_malloc(MYSQL_ERRMSG_SIZE, MYF(0));
183   mysql->thd= create_embedded_thd(client_flag);
184 
185   init_embedded_mysql(mysql, client_flag);
186 
187   if (mysql_init_character_set(mysql))
188     goto error;
189 
190   if (check_embedded_connection(mysql, db))
191     goto error;
192 
193   mysql->server_status= SERVER_STATUS_AUTOCOMMIT;
194 
195   if (mysql->options.init_commands)
196   {
197     DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
198     char **ptr= (char**)init_commands->buffer;
199     char **end= ptr + init_commands->elements;
200 
201     for (; ptr<end; ptr++)
202     {
203       MYSQL_RES *res;
204       if (mysql_query(mysql,*ptr))
205 	goto error;
206       if (mysql->fields)
207       {
208 	if (!(res= (*mysql->methods->use_result)(mysql)))
209 	  goto error;
210 	mysql_free_result(res);
211       }
212     }
213   }
214 
215   DBUG_PRINT("exit",("Mysql handler: 0x%lx", (long) mysql));
216   DBUG_RETURN(mysql);
217 
218 error:
219   DBUG_PRINT("error",("message: %u (%s)",
220                       mysql->net.last_errno,
221                       mysql->net.last_error));
222   {
223     /* Free alloced memory */
224     my_bool free_me=mysql->free_me;
225     free_old_query(mysql);
226     mysql->free_me=0;
227     mysql_close(mysql);
228     mysql->free_me=free_me;
229   }
230   DBUG_RETURN(0);
231 }
232 
233