~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql-common/client.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000-2003 MySQL AB
 
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 as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
/*
 
17
  This file is included by both libmysql.c (the MySQL client C API)
 
18
  and the mysqld server to connect to another MYSQL server.
 
19
 
 
20
  The differences for the two cases are:
 
21
 
 
22
  - Things that only works for the client:
 
23
  - Trying to automaticly determinate user name if not supplied to
 
24
    mysql_real_connect()
 
25
  - Support for reading local file with LOAD DATA LOCAL
 
26
  - SHARED memory handling
 
27
  - Protection against sigpipe
 
28
  - Prepared statements
 
29
  
 
30
  - Things that only works for the server
 
31
  - Alarm handling on connect
 
32
  
 
33
  In all other cases, the code should be idential for the client and
 
34
  server.
 
35
*/ 
 
36
 
 
37
#include <my_global.h>
 
38
 
 
39
#include "mysql.h"
 
40
 
 
41
/* Windows lacks a netdb.h */
 
42
#ifdef __WIN__
 
43
#include <Ws2tcpip.h>
 
44
#else
 
45
#include <netdb.h>
 
46
#endif
 
47
 
 
48
/* Remove client convenience wrappers */
 
49
#undef max_allowed_packet
 
50
#undef net_buffer_length
 
51
 
 
52
#ifdef EMBEDDED_LIBRARY
 
53
 
 
54
#undef MYSQL_SERVER
 
55
 
 
56
#ifndef MYSQL_CLIENT
 
57
#define MYSQL_CLIENT
 
58
#endif
 
59
 
 
60
#define CLI_MYSQL_REAL_CONNECT STDCALL cli_mysql_real_connect
 
61
 
 
62
#undef net_flush
 
63
my_bool net_flush(NET *net);
 
64
 
 
65
#else  /*EMBEDDED_LIBRARY*/
 
66
#define CLI_MYSQL_REAL_CONNECT STDCALL mysql_real_connect
 
67
#endif /*EMBEDDED_LIBRARY*/
 
68
#include <my_sys.h>
 
69
#include <mysys_err.h>
 
70
#include <m_string.h>
 
71
#include <m_ctype.h>
 
72
#include "mysql_version.h"
 
73
#include "mysqld_error.h"
 
74
#include "errmsg.h"
 
75
#include <violite.h>
 
76
#if defined(THREAD) && !defined(__WIN__)
 
77
#include <my_pthread.h>                         /* because of signal()  */
 
78
#endif /* defined(THREAD) && !defined(__WIN__) */
 
79
 
 
80
#include <sys/stat.h>
 
81
#include <signal.h>
 
82
#include <time.h>
 
83
#ifdef   HAVE_PWD_H
 
84
#include <pwd.h>
 
85
#endif
 
86
#if !defined(MSDOS) && !defined(__WIN__)
 
87
#include <sys/socket.h>
 
88
#include <netinet/in.h>
 
89
#include <arpa/inet.h>
 
90
#include <netdb.h>
 
91
#ifdef HAVE_SELECT_H
 
92
#  include <select.h>
 
93
#endif
 
94
#ifdef HAVE_SYS_SELECT_H
 
95
#include <sys/select.h>
 
96
#endif
 
97
#endif /*!defined(MSDOS) && !defined(__WIN__) */
 
98
#ifdef HAVE_SYS_UN_H
 
99
#  include <sys/un.h>
 
100
#endif
 
101
 
 
102
#if defined(MSDOS) || defined(__WIN__)
 
103
#define perror(A)
 
104
#else
 
105
#include <errno.h>
 
106
#define SOCKET_ERROR -1
 
107
#endif
 
108
 
 
109
#ifdef __WIN__
 
110
#define CONNECT_TIMEOUT 20
 
111
#else
 
112
#define CONNECT_TIMEOUT 0
 
113
#endif
 
114
 
 
115
#include "client_settings.h"
 
116
#include <sql_common.h>
 
117
 
 
118
uint            mysql_port=0;
 
119
char            *mysql_unix_port= 0;
 
120
const char      *unknown_sqlstate= "HY000";
 
121
const char      *not_error_sqlstate= "00000";
 
122
const char      *cant_connect_sqlstate= "08001";
 
123
#ifdef HAVE_SMEM
 
124
char             *shared_memory_base_name= 0;
 
125
const char      *def_shared_memory_base_name= default_shared_memory_base_name;
 
126
#endif
 
127
 
 
128
static void mysql_close_free_options(MYSQL *mysql);
 
129
static void mysql_close_free(MYSQL *mysql);
 
130
 
 
131
#if !(defined(__WIN__) || defined(__NETWARE__))
 
132
static int wait_for_data(my_socket fd, uint timeout);
 
133
#endif
 
134
 
 
135
CHARSET_INFO *default_client_charset_info = &my_charset_latin1;
 
136
 
 
137
/* Server error code and message */
 
138
unsigned int mysql_server_last_errno;
 
139
char mysql_server_last_error[MYSQL_ERRMSG_SIZE];
 
140
 
 
141
/****************************************************************************
 
142
  A modified version of connect().  my_connect() allows you to specify
 
143
  a timeout value, in seconds, that we should wait until we
 
144
  derermine we can't connect to a particular host.  If timeout is 0,
 
145
  my_connect() will behave exactly like connect().
 
146
 
 
147
  Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
 
148
*****************************************************************************/
 
149
 
 
150
int my_connect(my_socket fd, const struct sockaddr *name, uint namelen,
 
151
               uint timeout)
 
152
{
 
153
#if defined(__WIN__) || defined(__NETWARE__)
 
154
  return connect(fd, (struct sockaddr*) name, namelen);
 
155
#else
 
156
  int flags, res, s_err;
 
157
 
 
158
  /*
 
159
    If they passed us a timeout of zero, we should behave
 
160
    exactly like the normal connect() call does.
 
161
  */
 
162
 
 
163
  if (timeout == 0)
 
164
    return connect(fd, (struct sockaddr*) name, namelen);
 
165
 
 
166
  flags = fcntl(fd, F_GETFL, 0);          /* Set socket to not block */
 
167
#ifdef O_NONBLOCK
 
168
  fcntl(fd, F_SETFL, flags | O_NONBLOCK);  /* and save the flags..  */
 
169
#endif
 
170
 
 
171
  res= connect(fd, (struct sockaddr*) name, namelen);
 
172
  s_err= errno;                 /* Save the error... */
 
173
  fcntl(fd, F_SETFL, flags);
 
174
  if ((res != 0) && (s_err != EINPROGRESS))
 
175
  {
 
176
    errno= s_err;                       /* Restore it */
 
177
    return(-1);
 
178
  }
 
179
  if (res == 0)                         /* Connected quickly! */
 
180
    return(0);
 
181
  return wait_for_data(fd, timeout);
 
182
#endif
 
183
}
 
184
 
 
185
 
 
186
/*
 
187
  Wait up to timeout seconds for a connection to be established.
 
188
 
 
189
  We prefer to do this with poll() as there is no limitations with this.
 
190
  If not, we will use select()
 
191
*/
 
192
 
 
193
#if !(defined(__WIN__) || defined(__NETWARE__))
 
194
 
 
195
static int wait_for_data(my_socket fd, uint timeout)
 
196
{
 
197
#ifdef HAVE_POLL
 
198
  struct pollfd ufds;
 
199
  int res;
 
200
 
 
201
  ufds.fd= fd;
 
202
  ufds.events= POLLIN | POLLPRI;
 
203
  if (!(res= poll(&ufds, 1, (int) timeout*1000)))
 
204
  {
 
205
    errno= EINTR;
 
206
    return -1;
 
207
  }
 
208
  if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
 
209
    return -1;
 
210
  return 0;
 
211
#else
 
212
  SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
 
213
  fd_set sfds;
 
214
  struct timeval tv;
 
215
  time_t start_time, now_time;
 
216
  int res, s_err;
 
217
 
 
218
  if (fd >= FD_SETSIZE)                         /* Check if wrong error */
 
219
    return 0;                                   /* Can't use timeout */
 
220
 
 
221
  /*
 
222
    Our connection is "in progress."  We can use the select() call to wait
 
223
    up to a specified period of time for the connection to suceed.
 
224
    If select() returns 0 (after waiting howevermany seconds), our socket
 
225
    never became writable (host is probably unreachable.)  Otherwise, if
 
226
    select() returns 1, then one of two conditions exist:
 
227
   
 
228
    1. An error occured.  We use getsockopt() to check for this.
 
229
    2. The connection was set up sucessfully: getsockopt() will
 
230
    return 0 as an error.
 
231
   
 
232
    Thanks goes to Andrew Gierth <andrew@erlenstar.demon.co.uk>
 
233
    who posted this method of timing out a connect() in
 
234
    comp.unix.programmer on August 15th, 1997.
 
235
  */
 
236
 
 
237
  FD_ZERO(&sfds);
 
238
  FD_SET(fd, &sfds);
 
239
  /*
 
240
    select could be interrupted by a signal, and if it is, 
 
241
    the timeout should be adjusted and the select restarted
 
242
    to work around OSes that don't restart select and 
 
243
    implementations of select that don't adjust tv upon
 
244
    failure to reflect the time remaining
 
245
   */
 
246
  start_time= my_time(0);
 
247
  for (;;)
 
248
  {
 
249
    tv.tv_sec = (long) timeout;
 
250
    tv.tv_usec = 0;
 
251
#if defined(HPUX10) && defined(THREAD)
 
252
    if ((res = select(fd+1, NULL, (int*) &sfds, NULL, &tv)) > 0)
 
253
      break;
 
254
#else
 
255
    if ((res = select(fd+1, NULL, &sfds, NULL, &tv)) > 0)
 
256
      break;
 
257
#endif
 
258
    if (res == 0)                                       /* timeout */
 
259
      return -1;
 
260
    now_time= my_time(0);
 
261
    timeout-= (uint) (now_time - start_time);
 
262
    if (errno != EINTR || (int) timeout <= 0)
 
263
      return -1;
 
264
  }
 
265
 
 
266
  /*
 
267
    select() returned something more interesting than zero, let's
 
268
    see if we have any errors.  If the next two statements pass,
 
269
    we've got an open socket!
 
270
  */
 
271
 
 
272
  s_err=0;
 
273
  if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
 
274
    return(-1);
 
275
 
 
276
  if (s_err)
 
277
  {                                             /* getsockopt could succeed */
 
278
    errno = s_err;
 
279
    return(-1);                                 /* but return an error... */
 
280
  }
 
281
  return (0);                                   /* ok */
 
282
#endif /* HAVE_POLL */
 
283
}
 
284
#endif /* defined(__WIN__) || defined(__NETWARE__) */
 
285
 
 
286
/**
 
287
  Set the internal error message to mysql handler
 
288
 
 
289
  @param mysql    connection handle (client side)
 
290
  @param errcode  CR_ error code, passed to ER macro to get
 
291
                  error text
 
292
  @parma sqlstate SQL standard sqlstate
 
293
*/
 
294
 
 
295
void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate)
 
296
{
 
297
  NET *net;
 
298
  DBUG_ENTER("set_mysql_error");
 
299
  DBUG_PRINT("enter", ("error :%d '%s'", errcode, ER(errcode)));
 
300
  DBUG_ASSERT(mysql != 0);
 
301
 
 
302
  if (mysql)
 
303
  {
 
304
    net= &mysql->net;
 
305
    net->last_errno= errcode;
 
306
    strmov(net->last_error, ER(errcode));
 
307
    strmov(net->sqlstate, sqlstate);
 
308
  }
 
309
  else
 
310
  {
 
311
    mysql_server_last_errno= errcode;
 
312
    strmov(mysql_server_last_error, ER(errcode));
 
313
  }
 
314
  DBUG_VOID_RETURN;
 
315
}
 
316
 
 
317
/**
 
318
  Clear possible error state of struct NET
 
319
 
 
320
  @param net  clear the state of the argument
 
321
*/
 
322
 
 
323
void net_clear_error(NET *net)
 
324
{
 
325
  net->last_errno= 0;
 
326
  net->last_error[0]= '\0';
 
327
  strmov(net->sqlstate, not_error_sqlstate);
 
328
}
 
329
 
 
330
/**
 
331
  Set an error message on the client.
 
332
 
 
333
  @param mysql     connection handle
 
334
  @param errcode   CR_* errcode, for client errors
 
335
  @param sqlstate  SQL standard sql state, unknown_sqlstate for the
 
336
                   majority of client errors.
 
337
  @param format    error message template, in sprintf format
 
338
  @param ...       variable number of arguments
 
339
*/
 
340
 
 
341
static void set_mysql_extended_error(MYSQL *mysql, int errcode,
 
342
                                     const char *sqlstate,
 
343
                                     const char *format, ...)
 
344
{
 
345
  NET *net;
 
346
  va_list args;
 
347
  DBUG_ENTER("set_mysql_extended_error");
 
348
  DBUG_PRINT("enter", ("error :%d '%s'", errcode, format));
 
349
  DBUG_ASSERT(mysql != 0);
 
350
 
 
351
  net= &mysql->net;
 
352
  net->last_errno= errcode;
 
353
  va_start(args, format);
 
354
  my_vsnprintf(net->last_error, sizeof(net->last_error)-1,
 
355
               format, args);
 
356
  va_end(args);
 
357
  strmov(net->sqlstate, sqlstate);
 
358
 
 
359
  DBUG_VOID_RETURN;
 
360
}
 
361
 
 
362
 
 
363
 
 
364
/*
 
365
  Create a named pipe connection
 
366
*/
 
367
 
 
368
#ifdef __WIN__
 
369
 
 
370
HANDLE create_named_pipe(MYSQL *mysql, uint connect_timeout, char **arg_host,
 
371
                         char **arg_unix_socket)
 
372
{
 
373
  HANDLE hPipe=INVALID_HANDLE_VALUE;
 
374
  char pipe_name[1024];
 
375
  DWORD dwMode;
 
376
  int i;
 
377
  my_bool testing_named_pipes=0;
 
378
  char *host= *arg_host, *unix_socket= *arg_unix_socket;
 
379
 
 
380
  if ( ! unix_socket || (unix_socket)[0] == 0x00)
 
381
    unix_socket = mysql_unix_port;
 
382
  if (!host || !strcmp(host,LOCAL_HOST))
 
383
    host=LOCAL_HOST_NAMEDPIPE;
 
384
 
 
385
  
 
386
  pipe_name[sizeof(pipe_name)-1]= 0;            /* Safety if too long string */
 
387
  strxnmov(pipe_name, sizeof(pipe_name)-1, "\\\\", host, "\\pipe\\",
 
388
           unix_socket, NullS);
 
389
  DBUG_PRINT("info",("Server name: '%s'.  Named Pipe: %s", host, unix_socket));
 
390
 
 
391
  for (i=0 ; i < 100 ; i++)                     /* Don't retry forever */
 
392
  {
 
393
    if ((hPipe = CreateFile(pipe_name,
 
394
                            GENERIC_READ | GENERIC_WRITE,
 
395
                            0,
 
396
                            NULL,
 
397
                            OPEN_EXISTING,
 
398
                            0,
 
399
                            NULL )) != INVALID_HANDLE_VALUE)
 
400
      break;
 
401
    if (GetLastError() != ERROR_PIPE_BUSY)
 
402
    {
 
403
      set_mysql_extended_error(mysql, CR_NAMEDPIPEOPEN_ERROR,
 
404
                               unknown_sqlstate, ER(CR_NAMEDPIPEOPEN_ERROR),
 
405
                               host, unix_socket, (ulong) GetLastError());
 
406
      return INVALID_HANDLE_VALUE;
 
407
    }
 
408
    /* wait for for an other instance */
 
409
    if (! WaitNamedPipe(pipe_name, connect_timeout*1000) )
 
410
    {
 
411
      set_mysql_extended_error(mysql, CR_NAMEDPIPEWAIT_ERROR, unknown_sqlstate,
 
412
                               ER(CR_NAMEDPIPEWAIT_ERROR),
 
413
                               host, unix_socket, (ulong) GetLastError());
 
414
      return INVALID_HANDLE_VALUE;
 
415
    }
 
416
  }
 
417
  if (hPipe == INVALID_HANDLE_VALUE)
 
418
  {
 
419
    set_mysql_extended_error(mysql, CR_NAMEDPIPEOPEN_ERROR, unknown_sqlstate,
 
420
                             ER(CR_NAMEDPIPEOPEN_ERROR), host, unix_socket,
 
421
                             (ulong) GetLastError());
 
422
    return INVALID_HANDLE_VALUE;
 
423
  }
 
424
  dwMode = PIPE_READMODE_BYTE | PIPE_WAIT;
 
425
  if ( !SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL) )
 
426
  {
 
427
    CloseHandle( hPipe );
 
428
    set_mysql_extended_error(mysql, CR_NAMEDPIPESETSTATE_ERROR,
 
429
                             unknown_sqlstate, ER(CR_NAMEDPIPESETSTATE_ERROR),
 
430
                             host, unix_socket, (ulong) GetLastError());
 
431
    return INVALID_HANDLE_VALUE;
 
432
  }
 
433
  *arg_host=host ; *arg_unix_socket=unix_socket;        /* connect arg */
 
434
  return (hPipe);
 
435
}
 
436
#endif
 
437
 
 
438
 
 
439
/*
 
440
  Create new shared memory connection, return handler of connection
 
441
 
 
442
  SYNOPSIS
 
443
    create_shared_memory()
 
444
    mysql               Pointer of mysql structure
 
445
    net                 Pointer of net structure
 
446
    connect_timeout     Timeout of connection
 
447
*/
 
448
 
 
449
#ifdef HAVE_SMEM
 
450
HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout)
 
451
{
 
452
  ulong smem_buffer_length = shared_memory_buffer_length + 4;
 
453
  /*
 
454
    event_connect_request is event object for start connection actions
 
455
    event_connect_answer is event object for confirm, that server put data
 
456
    handle_connect_file_map is file-mapping object, use for create shared
 
457
    memory
 
458
    handle_connect_map is pointer on shared memory
 
459
    handle_map is pointer on shared memory for client
 
460
    event_server_wrote,
 
461
    event_server_read,
 
462
    event_client_wrote,
 
463
    event_client_read are events for transfer data between server and client
 
464
    handle_file_map is file-mapping object, use for create shared memory
 
465
  */
 
466
  HANDLE event_connect_request = NULL;
 
467
  HANDLE event_connect_answer = NULL;
 
468
  HANDLE handle_connect_file_map = NULL;
 
469
  char *handle_connect_map = NULL;
 
470
 
 
471
  char *handle_map = NULL;
 
472
  HANDLE event_server_wrote = NULL;
 
473
  HANDLE event_server_read = NULL;
 
474
  HANDLE event_client_wrote = NULL;
 
475
  HANDLE event_client_read = NULL;
 
476
  HANDLE event_conn_closed = NULL;
 
477
  HANDLE handle_file_map = NULL;
 
478
  ulong connect_number;
 
479
  char connect_number_char[22], *p;
 
480
  char *tmp= NULL;
 
481
  char *suffix_pos;
 
482
  DWORD error_allow = 0;
 
483
  DWORD error_code = 0;
 
484
  DWORD event_access_rights= SYNCHRONIZE | EVENT_MODIFY_STATE;
 
485
  char *shared_memory_base_name = mysql->options.shared_memory_base_name;
 
486
 
 
487
  /*
 
488
     get enough space base-name + '_' + longest suffix we might ever send
 
489
   */
 
490
  if (!(tmp= (char *)my_malloc(strlen(shared_memory_base_name) + 32L, MYF(MY_FAE))))
 
491
    goto err;
 
492
 
 
493
  /*
 
494
    The name of event and file-mapping events create agree next rule:
 
495
    shared_memory_base_name+unique_part
 
496
    Where:
 
497
    shared_memory_base_name is unique value for each server
 
498
    unique_part is uniquel value for each object (events and file-mapping)
 
499
  */
 
500
  suffix_pos = strxmov(tmp, "Global\\", shared_memory_base_name, "_", NullS);
 
501
  strmov(suffix_pos, "CONNECT_REQUEST");
 
502
  if (!(event_connect_request= OpenEvent(event_access_rights, FALSE, tmp)))
 
503
  {
 
504
    error_allow = CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR;
 
505
    goto err;
 
506
  }
 
507
  strmov(suffix_pos, "CONNECT_ANSWER");
 
508
  if (!(event_connect_answer= OpenEvent(event_access_rights,FALSE,tmp)))
 
509
  {
 
510
    error_allow = CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR;
 
511
    goto err;
 
512
  }
 
513
  strmov(suffix_pos, "CONNECT_DATA");
 
514
  if (!(handle_connect_file_map= OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp)))
 
515
  {
 
516
    error_allow = CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR;
 
517
    goto err;
 
518
  }
 
519
  if (!(handle_connect_map= MapViewOfFile(handle_connect_file_map,
 
520
                                          FILE_MAP_WRITE,0,0,sizeof(DWORD))))
 
521
  {
 
522
    error_allow = CR_SHARED_MEMORY_CONNECT_MAP_ERROR;
 
523
    goto err;
 
524
  }
 
525
 
 
526
  /* Send to server request of connection */
 
527
  if (!SetEvent(event_connect_request))
 
528
  {
 
529
    error_allow = CR_SHARED_MEMORY_CONNECT_SET_ERROR;
 
530
    goto err;
 
531
  }
 
532
 
 
533
  /* Wait of answer from server */
 
534
  if (WaitForSingleObject(event_connect_answer,connect_timeout*1000) !=
 
535
      WAIT_OBJECT_0)
 
536
  {
 
537
    error_allow = CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR;
 
538
    goto err;
 
539
  }
 
540
 
 
541
  /* Get number of connection */
 
542
  connect_number = uint4korr(handle_connect_map);/*WAX2*/
 
543
  p= int10_to_str(connect_number, connect_number_char, 10);
 
544
 
 
545
  /*
 
546
    The name of event and file-mapping events create agree next rule:
 
547
    shared_memory_base_name+unique_part+number_of_connection
 
548
 
 
549
    Where:
 
550
    shared_memory_base_name is uniquel value for each server
 
551
    unique_part is uniquel value for each object (events and file-mapping)
 
552
    number_of_connection is number of connection between server and client
 
553
  */
 
554
  suffix_pos = strxmov(tmp, "Global\\", shared_memory_base_name, "_", connect_number_char,
 
555
                       "_", NullS);
 
556
  strmov(suffix_pos, "DATA");
 
557
  if ((handle_file_map = OpenFileMapping(FILE_MAP_WRITE,FALSE,tmp)) == NULL)
 
558
  {
 
559
    error_allow = CR_SHARED_MEMORY_FILE_MAP_ERROR;
 
560
    goto err2;
 
561
  }
 
562
  if ((handle_map = MapViewOfFile(handle_file_map,FILE_MAP_WRITE,0,0,
 
563
                                  smem_buffer_length)) == NULL)
 
564
  {
 
565
    error_allow = CR_SHARED_MEMORY_MAP_ERROR;
 
566
    goto err2;
 
567
  }
 
568
 
 
569
  strmov(suffix_pos, "SERVER_WROTE");
 
570
  if ((event_server_wrote = OpenEvent(event_access_rights,FALSE,tmp)) == NULL)
 
571
  {
 
572
    error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
 
573
    goto err2;
 
574
  }
 
575
 
 
576
  strmov(suffix_pos, "SERVER_READ");
 
577
  if ((event_server_read = OpenEvent(event_access_rights,FALSE,tmp)) == NULL)
 
578
  {
 
579
    error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
 
580
    goto err2;
 
581
  }
 
582
 
 
583
  strmov(suffix_pos, "CLIENT_WROTE");
 
584
  if ((event_client_wrote = OpenEvent(event_access_rights,FALSE,tmp)) == NULL)
 
585
  {
 
586
    error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
 
587
    goto err2;
 
588
  }
 
589
 
 
590
  strmov(suffix_pos, "CLIENT_READ");
 
591
  if ((event_client_read = OpenEvent(event_access_rights,FALSE,tmp)) == NULL)
 
592
  {
 
593
    error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
 
594
    goto err2;
 
595
  }
 
596
 
 
597
  strmov(suffix_pos, "CONNECTION_CLOSED");
 
598
  if ((event_conn_closed = OpenEvent(event_access_rights,FALSE,tmp)) == NULL)
 
599
  {
 
600
    error_allow = CR_SHARED_MEMORY_EVENT_ERROR;
 
601
    goto err2;
 
602
  }
 
603
  /*
 
604
    Set event that server should send data
 
605
  */
 
606
  SetEvent(event_server_read);
 
607
 
 
608
err2:
 
609
  if (error_allow == 0)
 
610
  {
 
611
    net->vio= vio_new_win32shared_memory(net,handle_file_map,handle_map,
 
612
                                         event_server_wrote,
 
613
                                         event_server_read,event_client_wrote,
 
614
                                         event_client_read,event_conn_closed);
 
615
  }
 
616
  else
 
617
  {
 
618
    error_code = GetLastError();
 
619
    if (event_server_read)
 
620
      CloseHandle(event_server_read);
 
621
    if (event_server_wrote)
 
622
      CloseHandle(event_server_wrote);
 
623
    if (event_client_read)
 
624
      CloseHandle(event_client_read);
 
625
    if (event_client_wrote)
 
626
      CloseHandle(event_client_wrote);
 
627
    if (event_conn_closed)
 
628
      CloseHandle(event_conn_closed);
 
629
    if (handle_map)
 
630
      UnmapViewOfFile(handle_map);
 
631
    if (handle_file_map)
 
632
      CloseHandle(handle_file_map);
 
633
  }
 
634
err:
 
635
  if (tmp)
 
636
    my_free(tmp, MYF(0));
 
637
  if (error_allow)
 
638
    error_code = GetLastError();
 
639
  if (event_connect_request)
 
640
    CloseHandle(event_connect_request);
 
641
  if (event_connect_answer)
 
642
    CloseHandle(event_connect_answer);
 
643
  if (handle_connect_map)
 
644
    UnmapViewOfFile(handle_connect_map);
 
645
  if (handle_connect_file_map)
 
646
    CloseHandle(handle_connect_file_map);
 
647
  if (error_allow)
 
648
  {
 
649
    if (error_allow == CR_SHARED_MEMORY_EVENT_ERROR)
 
650
      set_mysql_extended_error(mysql, error_allow, unknown_sqlstate,
 
651
                               ER(error_allow), suffix_pos, error_code);
 
652
    else
 
653
      set_mysql_extended_error(mysql, error_allow, unknown_sqlstate,
 
654
                               ER(error_allow), error_code);
 
655
    return(INVALID_HANDLE_VALUE);
 
656
  }
 
657
  return(handle_map);
 
658
}
 
659
#endif
 
660
 
 
661
/*****************************************************************************
 
662
  Read a packet from server. Give error message if socket was down
 
663
  or packet is an error message
 
664
*****************************************************************************/
 
665
 
 
666
ulong
 
667
cli_safe_read(MYSQL *mysql)
 
668
{
 
669
  NET *net= &mysql->net;
 
670
  ulong len=0;
 
671
  init_sigpipe_variables
 
672
 
 
673
  /* Don't give sigpipe errors if the client doesn't want them */
 
674
  set_sigpipe(mysql);
 
675
  if (net->vio != 0)
 
676
    len=my_net_read(net);
 
677
  reset_sigpipe(mysql);
 
678
 
 
679
  if (len == packet_error || len == 0)
 
680
  {
 
681
    DBUG_PRINT("error",("Wrong connection or packet. fd: %s  len: %lu",
 
682
                        vio_description(net->vio),len));
 
683
#ifdef MYSQL_SERVER
 
684
    if (net->vio && vio_was_interrupted(net->vio))
 
685
      return (packet_error);
 
686
#endif /*MYSQL_SERVER*/
 
687
    end_server(mysql);
 
688
    set_mysql_error(mysql, net->last_errno == ER_NET_PACKET_TOO_LARGE ?
 
689
                    CR_NET_PACKET_TOO_LARGE: CR_SERVER_LOST, unknown_sqlstate);
 
690
    return (packet_error);
 
691
  }
 
692
  if (net->read_pos[0] == 255)
 
693
  {
 
694
    if (len > 3)
 
695
    {
 
696
      char *pos=(char*) net->read_pos+1;
 
697
      net->last_errno=uint2korr(pos);
 
698
      pos+=2;
 
699
      len-=2;
 
700
      if (protocol_41(mysql) && pos[0] == '#')
 
701
      {
 
702
        strmake(net->sqlstate, pos+1, SQLSTATE_LENGTH);
 
703
        pos+= SQLSTATE_LENGTH+1;
 
704
      }
 
705
      else
 
706
      {
 
707
        /*
 
708
          The SQL state hasn't been received -- it should be reset to HY000
 
709
          (unknown error sql state).
 
710
        */
 
711
 
 
712
        strmov(net->sqlstate, unknown_sqlstate);
 
713
      }
 
714
 
 
715
      (void) strmake(net->last_error,(char*) pos,
 
716
                     min((uint) len,(uint) sizeof(net->last_error)-1));
 
717
    }
 
718
    else
 
719
      set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
 
720
    /*
 
721
      Cover a protocol design error: error packet does not
 
722
      contain the server status. Therefore, the client has no way
 
723
      to find out whether there are more result sets of
 
724
      a multiple-result-set statement pending. Luckily, in 5.0 an
 
725
      error always aborts execution of a statement, wherever it is
 
726
      a multi-statement or a stored procedure, so it should be
 
727
      safe to unconditionally turn off the flag here.
 
728
    */
 
729
    mysql->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
 
730
 
 
731
    DBUG_PRINT("error",("Got error: %d/%s (%s)",
 
732
                        net->last_errno,
 
733
                        net->sqlstate,
 
734
                        net->last_error));
 
735
    return(packet_error);
 
736
  }
 
737
  return len;
 
738
}
 
739
 
 
740
void free_rows(MYSQL_DATA *cur)
 
741
{
 
742
  if (cur)
 
743
  {
 
744
    free_root(&cur->alloc,MYF(0));
 
745
    my_free((uchar*) cur,MYF(0));
 
746
  }
 
747
}
 
748
 
 
749
my_bool
 
750
cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
 
751
                     const uchar *header, ulong header_length,
 
752
                     const uchar *arg, ulong arg_length, my_bool skip_check,
 
753
                     MYSQL_STMT *stmt)
 
754
{
 
755
  NET *net= &mysql->net;
 
756
  my_bool result= 1;
 
757
  init_sigpipe_variables
 
758
  my_bool stmt_skip= stmt ? stmt->state != MYSQL_STMT_INIT_DONE : FALSE;
 
759
  DBUG_ENTER("cli_advanced_command");
 
760
 
 
761
  /* Don't give sigpipe errors if the client doesn't want them */
 
762
  set_sigpipe(mysql);
 
763
 
 
764
  if (mysql->net.vio == 0)
 
765
  {                                             /* Do reconnect if possible */
 
766
    if (mysql_reconnect(mysql) || stmt_skip)
 
767
      DBUG_RETURN(1);
 
768
  }
 
769
  if (mysql->status != MYSQL_STATUS_READY ||
 
770
      mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
 
771
  {
 
772
    DBUG_PRINT("error",("state: %d", mysql->status));
 
773
    set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
 
774
    DBUG_RETURN(1);
 
775
  }
 
776
 
 
777
  net_clear_error(net);
 
778
  mysql->info=0;
 
779
  mysql->affected_rows= ~(my_ulonglong) 0;
 
780
  /*
 
781
    We don't want to clear the protocol buffer on COM_QUIT, because if
 
782
    the previous command was a shutdown command, we may have the
 
783
    response for the COM_QUIT already in the communication buffer
 
784
  */
 
785
  net_clear(&mysql->net, (command != COM_QUIT));
 
786
 
 
787
  if (net_write_command(net,(uchar) command, header, header_length,
 
788
                        arg, arg_length))
 
789
  {
 
790
    DBUG_PRINT("error",("Can't send command to server. Error: %d",
 
791
                        socket_errno));
 
792
    if (net->last_errno == ER_NET_PACKET_TOO_LARGE)
 
793
    {
 
794
      set_mysql_error(mysql, CR_NET_PACKET_TOO_LARGE, unknown_sqlstate);
 
795
      goto end;
 
796
    }
 
797
    end_server(mysql);
 
798
    if (mysql_reconnect(mysql) || stmt_skip)
 
799
      goto end;
 
800
    if (net_write_command(net,(uchar) command, header, header_length,
 
801
                          arg, arg_length))
 
802
    {
 
803
      set_mysql_error(mysql, CR_SERVER_GONE_ERROR, unknown_sqlstate);
 
804
      goto end;
 
805
    }
 
806
  }
 
807
  result=0;
 
808
  if (!skip_check)
 
809
    result= ((mysql->packet_length=cli_safe_read(mysql)) == packet_error ?
 
810
             1 : 0);
 
811
end:
 
812
  reset_sigpipe(mysql);
 
813
  DBUG_PRINT("exit",("result: %d", result));
 
814
  DBUG_RETURN(result);
 
815
}
 
816
 
 
817
void free_old_query(MYSQL *mysql)
 
818
{
 
819
  DBUG_ENTER("free_old_query");
 
820
  if (mysql->fields)
 
821
    free_root(&mysql->field_alloc,MYF(0));
 
822
  init_alloc_root(&mysql->field_alloc,8192,0); /* Assume rowlength < 8192 */
 
823
  mysql->fields= 0;
 
824
  mysql->field_count= 0;                        /* For API */
 
825
  mysql->warning_count= 0;
 
826
  mysql->info= 0;
 
827
  DBUG_VOID_RETURN;
 
828
}
 
829
 
 
830
/*
 
831
  Flush result set sent from server
 
832
*/
 
833
 
 
834
static void cli_flush_use_result(MYSQL *mysql)
 
835
{
 
836
  /* Clear the current execution status */
 
837
  DBUG_ENTER("cli_flush_use_result");
 
838
  DBUG_PRINT("warning",("Not all packets read, clearing them"));
 
839
  for (;;)
 
840
  {
 
841
    ulong pkt_len;
 
842
    if ((pkt_len=cli_safe_read(mysql)) == packet_error)
 
843
      break;
 
844
    if (pkt_len <= 8 && mysql->net.read_pos[0] == 254)
 
845
    {
 
846
      if (protocol_41(mysql))
 
847
      {
 
848
        char *pos= (char*) mysql->net.read_pos + 1;
 
849
        mysql->warning_count=uint2korr(pos); pos+=2;
 
850
        mysql->server_status=uint2korr(pos); pos+=2;
 
851
      }
 
852
      break;                            /* End of data */
 
853
    }
 
854
  }
 
855
  DBUG_VOID_RETURN;
 
856
}
 
857
 
 
858
 
 
859
#ifdef __WIN__
 
860
static my_bool is_NT(void)
 
861
{
 
862
  char *os=getenv("OS");
 
863
  return (os && !strcmp(os, "Windows_NT")) ? 1 : 0;
 
864
}
 
865
#endif
 
866
 
 
867
 
 
868
#ifdef CHECK_LICENSE
 
869
/**
 
870
  Check server side variable 'license'.
 
871
 
 
872
  If the variable does not exist or does not contain 'Commercial',
 
873
  we're talking to non-commercial server from commercial client.
 
874
 
 
875
  @retval  0   success
 
876
  @retval  !0  network error or the server is not commercial.
 
877
               Error code is saved in mysql->net.last_errno.
 
878
*/
 
879
 
 
880
static int check_license(MYSQL *mysql)
 
881
{
 
882
  MYSQL_ROW row;
 
883
  MYSQL_RES *res;
 
884
  NET *net= &mysql->net;
 
885
  static const char query[]= "SELECT @@license";
 
886
  static const char required_license[]= STRINGIFY_ARG(LICENSE);
 
887
 
 
888
  if (mysql_real_query(mysql, query, sizeof(query)-1))
 
889
  {
 
890
    if (net->last_errno == ER_UNKNOWN_SYSTEM_VARIABLE)
 
891
    {
 
892
      set_mysql_extended_error(mysql, CR_WRONG_LICENSE, unknown_sqlstate,
 
893
                               ER(CR_WRONG_LICENSE), required_license);
 
894
    }
 
895
    return 1;
 
896
  }
 
897
  if (!(res= mysql_use_result(mysql)))
 
898
    return 1;
 
899
  row= mysql_fetch_row(res);
 
900
  /* 
 
901
    If no rows in result set, or column value is NULL (none of these
 
902
    two is ever true for server variables now), or column value
 
903
    mismatch, set wrong license error.
 
904
  */
 
905
  if (!net->last_errno &&
 
906
      (!row || !row[0] ||
 
907
       strncmp(row[0], required_license, sizeof(required_license))))
 
908
  {
 
909
    set_mysql_extended_error(mysql, CR_WRONG_LICENSE, unknown_sqlstate,
 
910
                             ER(CR_WRONG_LICENSE), required_license);
 
911
  }
 
912
  mysql_free_result(res);
 
913
  return net->last_errno;
 
914
}
 
915
#endif /* CHECK_LICENSE */
 
916
 
 
917
 
 
918
/**************************************************************************
 
919
  Shut down connection
 
920
**************************************************************************/
 
921
 
 
922
void end_server(MYSQL *mysql)
 
923
{
 
924
  int save_errno= errno;
 
925
  DBUG_ENTER("end_server");
 
926
  if (mysql->net.vio != 0)
 
927
  {
 
928
    init_sigpipe_variables
 
929
    DBUG_PRINT("info",("Net: %s", vio_description(mysql->net.vio)));
 
930
    set_sigpipe(mysql);
 
931
    vio_delete(mysql->net.vio);
 
932
    reset_sigpipe(mysql);
 
933
    mysql->net.vio= 0;          /* Marker */
 
934
  }
 
935
  net_end(&mysql->net);
 
936
  free_old_query(mysql);
 
937
  errno= save_errno;
 
938
  DBUG_VOID_RETURN;
 
939
}
 
940
 
 
941
 
 
942
void STDCALL
 
943
mysql_free_result(MYSQL_RES *result)
 
944
{
 
945
  DBUG_ENTER("mysql_free_result");
 
946
  DBUG_PRINT("enter",("mysql_res: 0x%lx", (long) result));
 
947
  if (result)
 
948
  {
 
949
    MYSQL *mysql= result->handle;
 
950
    if (mysql)
 
951
    {
 
952
      if (mysql->unbuffered_fetch_owner == &result->unbuffered_fetch_cancelled)
 
953
        mysql->unbuffered_fetch_owner= 0;
 
954
      if (mysql->status == MYSQL_STATUS_USE_RESULT)
 
955
      {
 
956
        (*mysql->methods->flush_use_result)(mysql);
 
957
        mysql->status=MYSQL_STATUS_READY;
 
958
        if (mysql->unbuffered_fetch_owner)
 
959
          *mysql->unbuffered_fetch_owner= TRUE;
 
960
      }
 
961
    }
 
962
    free_rows(result->data);
 
963
    if (result->fields)
 
964
      free_root(&result->field_alloc,MYF(0));
 
965
    if (result->row)
 
966
      my_free((uchar*) result->row,MYF(0));
 
967
    my_free((uchar*) result,MYF(0));
 
968
  }
 
969
  DBUG_VOID_RETURN;
 
970
}
 
971
 
 
972
/****************************************************************************
 
973
  Get options from my.cnf
 
974
****************************************************************************/
 
975
 
 
976
static const char *default_options[]=
 
977
{
 
978
  "port","socket","compress","password","pipe", "timeout", "user",
 
979
  "init-command", "host", "database", "debug", "return-found-rows",
 
980
  "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath",
 
981
  "character-sets-dir", "default-character-set", "interactive-timeout",
 
982
  "connect-timeout", "local-infile", "disable-local-infile",
 
983
  "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
 
984
  "multi-results", "multi-statements", "multi-queries", "secure-auth",
 
985
  "report-data-truncation",
 
986
  NullS
 
987
};
 
988
 
 
989
static TYPELIB option_types={array_elements(default_options)-1,
 
990
                             "options",default_options, NULL};
 
991
 
 
992
const char *sql_protocol_names_lib[] =
 
993
{ "TCP", "SOCKET", "PIPE", "MEMORY", NullS };
 
994
TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"",
 
995
                                sql_protocol_names_lib, NULL};
 
996
 
 
997
static int add_init_command(struct st_mysql_options *options, const char *cmd)
 
998
{
 
999
  char *tmp;
 
1000
 
 
1001
  if (!options->init_commands)
 
1002
  {
 
1003
    options->init_commands= (DYNAMIC_ARRAY*)my_malloc(sizeof(DYNAMIC_ARRAY),
 
1004
                                                      MYF(MY_WME));
 
1005
    init_dynamic_array(options->init_commands,sizeof(char*),0,5 CALLER_INFO);
 
1006
  }
 
1007
 
 
1008
  if (!(tmp= my_strdup(cmd,MYF(MY_WME))) ||
 
1009
      insert_dynamic(options->init_commands, (uchar*)&tmp))
 
1010
  {
 
1011
    my_free(tmp, MYF(MY_ALLOW_ZERO_PTR));
 
1012
    return 1;
 
1013
  }
 
1014
 
 
1015
  return 0;
 
1016
}
 
1017
 
 
1018
void mysql_read_default_options(struct st_mysql_options *options,
 
1019
                                const char *filename,const char *group)
 
1020
{
 
1021
  int argc;
 
1022
  char *argv_buff[1],**argv;
 
1023
  const char *groups[3];
 
1024
  DBUG_ENTER("mysql_read_default_options");
 
1025
  DBUG_PRINT("enter",("file: %s  group: %s",filename,group ? group :"NULL"));
 
1026
 
 
1027
  argc=1; argv=argv_buff; argv_buff[0]= (char*) "client";
 
1028
  groups[0]= (char*) "client"; groups[1]= (char*) group; groups[2]=0;
 
1029
 
 
1030
  load_defaults(filename, groups, &argc, &argv);
 
1031
  if (argc != 1)                                /* If some default option */
 
1032
  {
 
1033
    char **option=argv;
 
1034
    while (*++option)
 
1035
    {
 
1036
      /* DBUG_PRINT("info",("option: %s",option[0])); */
 
1037
      if (option[0][0] == '-' && option[0][1] == '-')
 
1038
      {
 
1039
        char *end=strcend(*option,'=');
 
1040
        char *opt_arg=0;
 
1041
        if (*end)
 
1042
        {
 
1043
          opt_arg=end+1;
 
1044
          *end=0;                               /* Remove '=' */
 
1045
        }
 
1046
        /* Change all '_' in variable name to '-' */
 
1047
        for (end= *option ; *(end= strcend(end,'_')) ; )
 
1048
          *end= '-';
 
1049
        switch (find_type(*option+2,&option_types,2)) {
 
1050
        case 1:                         /* port */
 
1051
          if (opt_arg)
 
1052
            options->port=atoi(opt_arg);
 
1053
          break;
 
1054
        case 2:                         /* socket */
 
1055
          if (opt_arg)
 
1056
          {
 
1057
            my_free(options->unix_socket,MYF(MY_ALLOW_ZERO_PTR));
 
1058
            options->unix_socket=my_strdup(opt_arg,MYF(MY_WME));
 
1059
          }
 
1060
          break;
 
1061
        case 3:                         /* compress */
 
1062
          options->compress=1;
 
1063
          options->client_flag|= CLIENT_COMPRESS;
 
1064
          break;
 
1065
        case 4:                         /* password */
 
1066
          if (opt_arg)
 
1067
          {
 
1068
            my_free(options->password,MYF(MY_ALLOW_ZERO_PTR));
 
1069
            options->password=my_strdup(opt_arg,MYF(MY_WME));
 
1070
          }
 
1071
          break;
 
1072
        case 5:
 
1073
          options->protocol = MYSQL_PROTOCOL_PIPE;
 
1074
        case 20:                        /* connect_timeout */
 
1075
        case 6:                         /* timeout */
 
1076
          if (opt_arg)
 
1077
            options->connect_timeout=atoi(opt_arg);
 
1078
          break;
 
1079
        case 7:                         /* user */
 
1080
          if (opt_arg)
 
1081
          {
 
1082
            my_free(options->user,MYF(MY_ALLOW_ZERO_PTR));
 
1083
            options->user=my_strdup(opt_arg,MYF(MY_WME));
 
1084
          }
 
1085
          break;
 
1086
        case 8:                         /* init-command */
 
1087
          add_init_command(options,opt_arg);
 
1088
          break;
 
1089
        case 9:                         /* host */
 
1090
          if (opt_arg)
 
1091
          {
 
1092
            my_free(options->host,MYF(MY_ALLOW_ZERO_PTR));
 
1093
            options->host=my_strdup(opt_arg,MYF(MY_WME));
 
1094
          }
 
1095
          break;
 
1096
        case 10:                        /* database */
 
1097
          if (opt_arg)
 
1098
          {
 
1099
            my_free(options->db,MYF(MY_ALLOW_ZERO_PTR));
 
1100
            options->db=my_strdup(opt_arg,MYF(MY_WME));
 
1101
          }
 
1102
          break;
 
1103
        case 11:                        /* debug */
 
1104
#ifdef MYSQL_CLIENT
 
1105
          mysql_debug(opt_arg ? opt_arg : "d:t:o,/tmp/client.trace");
 
1106
          break;
 
1107
#endif
 
1108
        case 12:                        /* return-found-rows */
 
1109
          options->client_flag|=CLIENT_FOUND_ROWS;
 
1110
          break;
 
1111
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
1112
        case 13:                        /* ssl_key */
 
1113
          my_free(options->ssl_key, MYF(MY_ALLOW_ZERO_PTR));
 
1114
          options->ssl_key = my_strdup(opt_arg, MYF(MY_WME));
 
1115
          break;
 
1116
        case 14:                        /* ssl_cert */
 
1117
          my_free(options->ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
 
1118
          options->ssl_cert = my_strdup(opt_arg, MYF(MY_WME));
 
1119
          break;
 
1120
        case 15:                        /* ssl_ca */
 
1121
          my_free(options->ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
 
1122
          options->ssl_ca = my_strdup(opt_arg, MYF(MY_WME));
 
1123
          break;
 
1124
        case 16:                        /* ssl_capath */
 
1125
          my_free(options->ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
 
1126
          options->ssl_capath = my_strdup(opt_arg, MYF(MY_WME));
 
1127
          break;
 
1128
        case 23:                        /* ssl_cipher */
 
1129
          my_free(options->ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
 
1130
          options->ssl_cipher= my_strdup(opt_arg, MYF(MY_WME));
 
1131
          break;
 
1132
#else
 
1133
        case 13:                                /* Ignore SSL options */
 
1134
        case 14:
 
1135
        case 15:
 
1136
        case 16:
 
1137
        case 23:
 
1138
          break;
 
1139
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
 
1140
        case 17:                        /* charset-lib */
 
1141
          my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR));
 
1142
          options->charset_dir = my_strdup(opt_arg, MYF(MY_WME));
 
1143
          break;
 
1144
        case 18:
 
1145
          my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR));
 
1146
          options->charset_name = my_strdup(opt_arg, MYF(MY_WME));
 
1147
          break;
 
1148
        case 19:                                /* Interactive-timeout */
 
1149
          options->client_flag|= CLIENT_INTERACTIVE;
 
1150
          break;
 
1151
        case 21:
 
1152
          if (!opt_arg || atoi(opt_arg) != 0)
 
1153
            options->client_flag|= CLIENT_LOCAL_FILES;
 
1154
          else
 
1155
            options->client_flag&= ~CLIENT_LOCAL_FILES;
 
1156
          break;
 
1157
        case 22:
 
1158
          options->client_flag&= ~CLIENT_LOCAL_FILES;
 
1159
          break;
 
1160
        case 24: /* max-allowed-packet */
 
1161
          if (opt_arg)
 
1162
            options->max_allowed_packet= atoi(opt_arg);
 
1163
          break;
 
1164
        case 25: /* protocol */
 
1165
          if ((options->protocol= find_type(opt_arg,
 
1166
                                            &sql_protocol_typelib,0)) <= 0)
 
1167
          {
 
1168
            fprintf(stderr, "Unknown option to protocol: %s\n", opt_arg);
 
1169
            exit(1);
 
1170
          }
 
1171
          break;
 
1172
        case 26: /* shared_memory_base_name */
 
1173
#ifdef HAVE_SMEM
 
1174
          if (options->shared_memory_base_name != def_shared_memory_base_name)
 
1175
            my_free(options->shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
 
1176
          options->shared_memory_base_name=my_strdup(opt_arg,MYF(MY_WME));
 
1177
#endif
 
1178
          break;
 
1179
        case 27: /* multi-results */
 
1180
          options->client_flag|= CLIENT_MULTI_RESULTS;
 
1181
          break;
 
1182
        case 28: /* multi-statements */
 
1183
        case 29: /* multi-queries */
 
1184
          options->client_flag|= CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS;
 
1185
          break;
 
1186
        case 30: /* secure-auth */
 
1187
          options->secure_auth= TRUE;
 
1188
          break;
 
1189
        case 31: /* report-data-truncation */
 
1190
          options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
 
1191
          break;
 
1192
        default:
 
1193
          DBUG_PRINT("warning",("unknown option: %s",option[0]));
 
1194
        }
 
1195
      }
 
1196
    }
 
1197
  }
 
1198
  free_defaults(argv);
 
1199
  DBUG_VOID_RETURN;
 
1200
}
 
1201
 
 
1202
 
 
1203
/**************************************************************************
 
1204
  Get column lengths of the current row
 
1205
  If one uses mysql_use_result, res->lengths contains the length information,
 
1206
  else the lengths are calculated from the offset between pointers.
 
1207
**************************************************************************/
 
1208
 
 
1209
static void cli_fetch_lengths(ulong *to, MYSQL_ROW column,
 
1210
                              unsigned int field_count)
 
1211
 
1212
  ulong *prev_length;
 
1213
  char *start=0;
 
1214
  MYSQL_ROW end;
 
1215
 
 
1216
  prev_length=0;                                /* Keep gcc happy */
 
1217
  for (end=column + field_count + 1 ; column != end ; column++, to++)
 
1218
  {
 
1219
    if (!*column)
 
1220
    {
 
1221
      *to= 0;                                   /* Null */
 
1222
      continue;
 
1223
    }
 
1224
    if (start)                                  /* Found end of prev string */
 
1225
      *prev_length= (ulong) (*column-start-1);
 
1226
    start= *column;
 
1227
    prev_length= to;
 
1228
  }
 
1229
}
 
1230
 
 
1231
/***************************************************************************
 
1232
  Change field rows to field structs
 
1233
***************************************************************************/
 
1234
 
 
1235
MYSQL_FIELD *
 
1236
unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
 
1237
              my_bool default_value, uint server_capabilities)
 
1238
{
 
1239
  MYSQL_ROWS    *row;
 
1240
  MYSQL_FIELD   *field,*result;
 
1241
  ulong lengths[9];                             /* Max of fields */
 
1242
  DBUG_ENTER("unpack_fields");
 
1243
 
 
1244
  field= result= (MYSQL_FIELD*) alloc_root(alloc,
 
1245
                                           (uint) sizeof(*field)*fields);
 
1246
  if (!result)
 
1247
  {
 
1248
    free_rows(data);                            /* Free old data */
 
1249
    DBUG_RETURN(0);
 
1250
  }
 
1251
  bzero((char*) field, (uint) sizeof(MYSQL_FIELD)*fields);
 
1252
  if (server_capabilities & CLIENT_PROTOCOL_41)
 
1253
  {
 
1254
    /* server is 4.1, and returns the new field result format */
 
1255
    for (row=data->data; row ; row = row->next,field++)
 
1256
    {
 
1257
      uchar *pos;
 
1258
      /* fields count may be wrong */
 
1259
      DBUG_ASSERT((uint) (field - result) < fields);
 
1260
      cli_fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7);
 
1261
      field->catalog=   strmake_root(alloc,(char*) row->data[0], lengths[0]);
 
1262
      field->db=        strmake_root(alloc,(char*) row->data[1], lengths[1]);
 
1263
      field->table=     strmake_root(alloc,(char*) row->data[2], lengths[2]);
 
1264
      field->org_table= strmake_root(alloc,(char*) row->data[3], lengths[3]);
 
1265
      field->name=      strmake_root(alloc,(char*) row->data[4], lengths[4]);
 
1266
      field->org_name=  strmake_root(alloc,(char*) row->data[5], lengths[5]);
 
1267
 
 
1268
      field->catalog_length=    lengths[0];
 
1269
      field->db_length=         lengths[1];
 
1270
      field->table_length=      lengths[2];
 
1271
      field->org_table_length=  lengths[3];
 
1272
      field->name_length=       lengths[4];
 
1273
      field->org_name_length=   lengths[5];
 
1274
 
 
1275
      /* Unpack fixed length parts */
 
1276
      pos= (uchar*) row->data[6];
 
1277
      field->charsetnr= uint2korr(pos);
 
1278
      field->length=    (uint) uint4korr(pos+2);
 
1279
      field->type=      (enum enum_field_types) pos[6];
 
1280
      field->flags=     uint2korr(pos+7);
 
1281
      field->decimals=  (uint) pos[9];
 
1282
 
 
1283
      if (INTERNAL_NUM_FIELD(field))
 
1284
        field->flags|= NUM_FLAG;
 
1285
      if (default_value && row->data[7])
 
1286
      {
 
1287
        field->def=strmake_root(alloc,(char*) row->data[7], lengths[7]);
 
1288
        field->def_length= lengths[7];
 
1289
      }
 
1290
      else
 
1291
        field->def=0;
 
1292
      field->max_length= 0;
 
1293
    }
 
1294
  }
 
1295
#ifndef DELETE_SUPPORT_OF_4_0_PROTOCOL
 
1296
  else
 
1297
  {
 
1298
    /* old protocol, for backward compatibility */
 
1299
    for (row=data->data; row ; row = row->next,field++)
 
1300
    {
 
1301
      cli_fetch_lengths(&lengths[0], row->data, default_value ? 6 : 5);
 
1302
      field->org_table= field->table=  strdup_root(alloc,(char*) row->data[0]);
 
1303
      field->name=   strdup_root(alloc,(char*) row->data[1]);
 
1304
      field->length= (uint) uint3korr(row->data[2]);
 
1305
      field->type=   (enum enum_field_types) (uchar) row->data[3][0];
 
1306
 
 
1307
      field->catalog=(char*)  "";
 
1308
      field->db=     (char*)  "";
 
1309
      field->catalog_length= 0;
 
1310
      field->db_length= 0;
 
1311
      field->org_table_length=  field->table_length=    lengths[0];
 
1312
      field->name_length=       lengths[1];
 
1313
 
 
1314
      if (server_capabilities & CLIENT_LONG_FLAG)
 
1315
      {
 
1316
        field->flags=   uint2korr(row->data[4]);
 
1317
        field->decimals=(uint) (uchar) row->data[4][2];
 
1318
      }
 
1319
      else
 
1320
      {
 
1321
        field->flags=   (uint) (uchar) row->data[4][0];
 
1322
        field->decimals=(uint) (uchar) row->data[4][1];
 
1323
      }
 
1324
      if (INTERNAL_NUM_FIELD(field))
 
1325
        field->flags|= NUM_FLAG;
 
1326
      if (default_value && row->data[5])
 
1327
      {
 
1328
        field->def=strdup_root(alloc,(char*) row->data[5]);
 
1329
        field->def_length= lengths[5];
 
1330
      }
 
1331
      else
 
1332
        field->def=0;
 
1333
      field->max_length= 0;
 
1334
    }
 
1335
  }
 
1336
#endif /* DELETE_SUPPORT_OF_4_0_PROTOCOL */
 
1337
  free_rows(data);                              /* Free old data */
 
1338
  DBUG_RETURN(result);
 
1339
}
 
1340
 
 
1341
/* Read all rows (fields or data) from server */
 
1342
 
 
1343
MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
 
1344
                          unsigned int fields)
 
1345
{
 
1346
  uint  field;
 
1347
  ulong pkt_len;
 
1348
  ulong len;
 
1349
  uchar *cp;
 
1350
  char  *to, *end_to;
 
1351
  MYSQL_DATA *result;
 
1352
  MYSQL_ROWS **prev_ptr,*cur;
 
1353
  NET *net = &mysql->net;
 
1354
  DBUG_ENTER("cli_read_rows");
 
1355
 
 
1356
  if ((pkt_len= cli_safe_read(mysql)) == packet_error)
 
1357
    DBUG_RETURN(0);
 
1358
  if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
 
1359
                                       MYF(MY_WME | MY_ZEROFILL))))
 
1360
  {
 
1361
    set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
1362
    DBUG_RETURN(0);
 
1363
  }
 
1364
  init_alloc_root(&result->alloc,8192,0);       /* Assume rowlength < 8192 */
 
1365
  result->alloc.min_malloc=sizeof(MYSQL_ROWS);
 
1366
  prev_ptr= &result->data;
 
1367
  result->rows=0;
 
1368
  result->fields=fields;
 
1369
 
 
1370
  /*
 
1371
    The last EOF packet is either a single 254 character or (in MySQL 4.1)
 
1372
    254 followed by 1-7 status bytes.
 
1373
 
 
1374
    This doesn't conflict with normal usage of 254 which stands for a
 
1375
    string where the length of the string is 8 bytes. (see net_field_length())
 
1376
  */
 
1377
 
 
1378
  while (*(cp=net->read_pos) != 254 || pkt_len >= 8)
 
1379
  {
 
1380
    result->rows++;
 
1381
    if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,
 
1382
                                        sizeof(MYSQL_ROWS))) ||
 
1383
        !(cur->data= ((MYSQL_ROW)
 
1384
                      alloc_root(&result->alloc,
 
1385
                                 (fields+1)*sizeof(char *)+pkt_len))))
 
1386
    {
 
1387
      free_rows(result);
 
1388
      set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
1389
      DBUG_RETURN(0);
 
1390
    }
 
1391
    *prev_ptr=cur;
 
1392
    prev_ptr= &cur->next;
 
1393
    to= (char*) (cur->data+fields+1);
 
1394
    end_to=to+pkt_len-1;
 
1395
    for (field=0 ; field < fields ; field++)
 
1396
    {
 
1397
      if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH)
 
1398
      {                                         /* null field */
 
1399
        cur->data[field] = 0;
 
1400
      }
 
1401
      else
 
1402
      {
 
1403
        cur->data[field] = to;
 
1404
        if (len > (ulong) (end_to - to))
 
1405
        {
 
1406
          free_rows(result);
 
1407
          set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
 
1408
          DBUG_RETURN(0);
 
1409
        }
 
1410
        memcpy(to,(char*) cp,len); to[len]=0;
 
1411
        to+=len+1;
 
1412
        cp+=len;
 
1413
        if (mysql_fields)
 
1414
        {
 
1415
          if (mysql_fields[field].max_length < len)
 
1416
            mysql_fields[field].max_length=len;
 
1417
        }
 
1418
      }
 
1419
    }
 
1420
    cur->data[field]=to;                        /* End of last field */
 
1421
    if ((pkt_len=cli_safe_read(mysql)) == packet_error)
 
1422
    {
 
1423
      free_rows(result);
 
1424
      DBUG_RETURN(0);
 
1425
    }
 
1426
  }
 
1427
  *prev_ptr=0;                                  /* last pointer is null */
 
1428
  if (pkt_len > 1)                              /* MySQL 4.1 protocol */
 
1429
  {
 
1430
    mysql->warning_count= uint2korr(cp+1);
 
1431
    mysql->server_status= uint2korr(cp+3);
 
1432
    DBUG_PRINT("info",("status: %u  warning_count:  %u",
 
1433
                       mysql->server_status, mysql->warning_count));
 
1434
  }
 
1435
  DBUG_PRINT("exit", ("Got %lu rows", (ulong) result->rows));
 
1436
  DBUG_RETURN(result);
 
1437
}
 
1438
 
 
1439
/*
 
1440
  Read one row. Uses packet buffer as storage for fields.
 
1441
  When next packet is read, the previous field values are destroyed
 
1442
*/
 
1443
 
 
1444
 
 
1445
static int
 
1446
read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
 
1447
{
 
1448
  uint field;
 
1449
  ulong pkt_len,len;
 
1450
  uchar *pos, *prev_pos, *end_pos;
 
1451
  NET *net= &mysql->net;
 
1452
 
 
1453
  if ((pkt_len=cli_safe_read(mysql)) == packet_error)
 
1454
    return -1;
 
1455
  if (pkt_len <= 8 && net->read_pos[0] == 254)
 
1456
  {
 
1457
    if (pkt_len > 1)                            /* MySQL 4.1 protocol */
 
1458
    {
 
1459
      mysql->warning_count= uint2korr(net->read_pos+1);
 
1460
      mysql->server_status= uint2korr(net->read_pos+3);
 
1461
    }
 
1462
    return 1;                           /* End of data */
 
1463
  }
 
1464
  prev_pos= 0;                          /* allowed to write at packet[-1] */
 
1465
  pos=net->read_pos;
 
1466
  end_pos=pos+pkt_len;
 
1467
  for (field=0 ; field < fields ; field++)
 
1468
  {
 
1469
    if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH)
 
1470
    {                                           /* null field */
 
1471
      row[field] = 0;
 
1472
      *lengths++=0;
 
1473
    }
 
1474
    else
 
1475
    {
 
1476
      if (len > (ulong) (end_pos - pos))
 
1477
      {
 
1478
        set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
 
1479
        return -1;
 
1480
      }
 
1481
      row[field] = (char*) pos;
 
1482
      pos+=len;
 
1483
      *lengths++=len;
 
1484
    }
 
1485
    if (prev_pos)
 
1486
      *prev_pos=0;                              /* Terminate prev field */
 
1487
    prev_pos=pos;
 
1488
  }
 
1489
  row[field]=(char*) prev_pos+1;                /* End of last field */
 
1490
  *prev_pos=0;                                  /* Terminate last field */
 
1491
  return 0;
 
1492
}
 
1493
 
 
1494
 
 
1495
/****************************************************************************
 
1496
  Init MySQL structure or allocate one
 
1497
****************************************************************************/
 
1498
 
 
1499
MYSQL * STDCALL
 
1500
mysql_init(MYSQL *mysql)
 
1501
{
 
1502
  if (mysql_server_init(0, NULL, NULL))
 
1503
    return 0;
 
1504
  if (!mysql)
 
1505
  {
 
1506
    if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL))))
 
1507
    {
 
1508
      set_mysql_error(NULL, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
1509
      return 0;
 
1510
    }
 
1511
    mysql->free_me=1;
 
1512
  }
 
1513
  else
 
1514
    bzero((char*) (mysql), sizeof(*(mysql)));
 
1515
  mysql->options.connect_timeout= CONNECT_TIMEOUT;
 
1516
  mysql->charset=default_client_charset_info;
 
1517
  strmov(mysql->net.sqlstate, not_error_sqlstate);
 
1518
 
 
1519
  /*
 
1520
    Only enable LOAD DATA INFILE by default if configured with
 
1521
    --enable-local-infile
 
1522
  */
 
1523
 
 
1524
#if defined(ENABLED_LOCAL_INFILE) && !defined(MYSQL_SERVER)
 
1525
  mysql->options.client_flag|= CLIENT_LOCAL_FILES;
 
1526
#endif
 
1527
 
 
1528
#ifdef HAVE_SMEM
 
1529
  mysql->options.shared_memory_base_name= (char*) def_shared_memory_base_name;
 
1530
#endif
 
1531
 
 
1532
  mysql->options.methods_to_use= MYSQL_OPT_GUESS_CONNECTION;
 
1533
  mysql->options.report_data_truncation= TRUE;  /* default */
 
1534
 
 
1535
  /*
 
1536
    By default we don't reconnect because it could silently corrupt data (after
 
1537
    reconnection you potentially lose table locks, user variables, session
 
1538
    variables (transactions but they are specifically dealt with in
 
1539
    mysql_reconnect()).
 
1540
    This is a change: < 5.0.3 mysql->reconnect was set to 1 by default.
 
1541
    How this change impacts existing apps:
 
1542
    - existing apps which relyed on the default will see a behaviour change;
 
1543
    they will have to set reconnect=1 after mysql_real_connect().
 
1544
    - existing apps which explicitely asked for reconnection (the only way they
 
1545
    could do it was by setting mysql.reconnect to 1 after mysql_real_connect())
 
1546
    will not see a behaviour change.
 
1547
    - existing apps which explicitely asked for no reconnection
 
1548
    (mysql.reconnect=0) will not see a behaviour change.
 
1549
  */
 
1550
  mysql->reconnect= 0;
 
1551
 
 
1552
  return mysql;
 
1553
}
 
1554
 
 
1555
 
 
1556
/*
 
1557
  Fill in SSL part of MYSQL structure and set 'use_ssl' flag.
 
1558
  NB! Errors are not reported until you do mysql_real_connect.
 
1559
*/
 
1560
 
 
1561
#define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME))
 
1562
 
 
1563
my_bool STDCALL
 
1564
mysql_ssl_set(MYSQL *mysql __attribute__((unused)) ,
 
1565
              const char *key __attribute__((unused)),
 
1566
              const char *cert __attribute__((unused)),
 
1567
              const char *ca __attribute__((unused)),
 
1568
              const char *capath __attribute__((unused)),
 
1569
              const char *cipher __attribute__((unused)))
 
1570
{
 
1571
  DBUG_ENTER("mysql_ssl_set");
 
1572
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
1573
  mysql->options.ssl_key=    strdup_if_not_null(key);
 
1574
  mysql->options.ssl_cert=   strdup_if_not_null(cert);
 
1575
  mysql->options.ssl_ca=     strdup_if_not_null(ca);
 
1576
  mysql->options.ssl_capath= strdup_if_not_null(capath);
 
1577
  mysql->options.ssl_cipher= strdup_if_not_null(cipher);
 
1578
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
 
1579
  DBUG_RETURN(0);
 
1580
}
 
1581
 
 
1582
 
 
1583
/*
 
1584
  Free strings in the SSL structure and clear 'use_ssl' flag.
 
1585
  NB! Errors are not reported until you do mysql_real_connect.
 
1586
*/
 
1587
 
 
1588
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
1589
 
 
1590
static void
 
1591
mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
 
1592
{
 
1593
  struct st_VioSSLFd *ssl_fd= (struct st_VioSSLFd*) mysql->connector_fd;
 
1594
  DBUG_ENTER("mysql_ssl_free");
 
1595
 
 
1596
  my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
 
1597
  my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
 
1598
  my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
 
1599
  my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
 
1600
  my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR));
 
1601
  if (ssl_fd)
 
1602
    SSL_CTX_free(ssl_fd->ssl_context);
 
1603
  my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR));
 
1604
  mysql->options.ssl_key = 0;
 
1605
  mysql->options.ssl_cert = 0;
 
1606
  mysql->options.ssl_ca = 0;
 
1607
  mysql->options.ssl_capath = 0;
 
1608
  mysql->options.ssl_cipher= 0;
 
1609
  mysql->options.use_ssl = FALSE;
 
1610
  mysql->connector_fd = 0;
 
1611
  DBUG_VOID_RETURN;
 
1612
}
 
1613
 
 
1614
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
 
1615
 
 
1616
/*
 
1617
  Return the SSL cipher (if any) used for current
 
1618
  connection to the server.
 
1619
 
 
1620
  SYNOPSYS
 
1621
    mysql_get_ssl_cipher()
 
1622
      mysql pointer to the mysql connection
 
1623
 
 
1624
*/
 
1625
 
 
1626
const char * STDCALL
 
1627
mysql_get_ssl_cipher(MYSQL *mysql __attribute__((unused)))
 
1628
{
 
1629
  DBUG_ENTER("mysql_get_ssl_cipher");
 
1630
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
1631
  if (mysql->net.vio && mysql->net.vio->ssl_arg)
 
1632
    DBUG_RETURN(SSL_get_cipher_name((SSL*)mysql->net.vio->ssl_arg));
 
1633
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
 
1634
  DBUG_RETURN(NULL);
 
1635
}
 
1636
 
 
1637
 
 
1638
/*
 
1639
  Check the server's (subject) Common Name against the
 
1640
  hostname we connected to
 
1641
 
 
1642
  SYNOPSIS
 
1643
  ssl_verify_server_cert()
 
1644
    vio              pointer to a SSL connected vio
 
1645
    server_hostname  name of the server that we connected to
 
1646
 
 
1647
  RETURN VALUES
 
1648
   0 Success
 
1649
   1 Failed to validate server
 
1650
 
 
1651
 */
 
1652
 
 
1653
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
1654
 
 
1655
static int ssl_verify_server_cert(Vio *vio, const char* server_hostname)
 
1656
{
 
1657
  SSL *ssl;
 
1658
  X509 *server_cert;
 
1659
  char *cp1, *cp2;
 
1660
  char buf[256];
 
1661
  DBUG_ENTER("ssl_verify_server_cert");
 
1662
  DBUG_PRINT("enter", ("server_hostname: %s", server_hostname));
 
1663
 
 
1664
  if (!(ssl= (SSL*)vio->ssl_arg))
 
1665
  {
 
1666
    DBUG_PRINT("error", ("No SSL pointer found"));
 
1667
    DBUG_RETURN(1);
 
1668
  }
 
1669
 
 
1670
  if (!server_hostname)
 
1671
  {
 
1672
    DBUG_PRINT("error", ("No server hostname supplied"));
 
1673
    DBUG_RETURN(1);
 
1674
  }
 
1675
 
 
1676
  if (!(server_cert= SSL_get_peer_certificate(ssl)))
 
1677
  {
 
1678
    DBUG_PRINT("error", ("Could not get server certificate"));
 
1679
    DBUG_RETURN(1);
 
1680
  }
 
1681
 
 
1682
  /*
 
1683
    We already know that the certificate exchanged was valid; the SSL library
 
1684
    handled that. Now we need to verify that the contents of the certificate
 
1685
    are what we expect.
 
1686
  */
 
1687
 
 
1688
  X509_NAME_oneline(X509_get_subject_name(server_cert), buf, sizeof(buf));
 
1689
  X509_free (server_cert);
 
1690
 
 
1691
  DBUG_PRINT("info", ("hostname in cert: %s", buf));
 
1692
  cp1= strstr(buf, "/CN=");
 
1693
  if (cp1)
 
1694
  {
 
1695
    cp1+= 4; /* Skip the "/CN=" that we found */
 
1696
    /* Search for next / which might be the delimiter for email */
 
1697
    cp2= strchr(cp1, '/');
 
1698
    if (cp2)
 
1699
      *cp2= '\0';
 
1700
    DBUG_PRINT("info", ("Server hostname in cert: %s", cp1));
 
1701
    if (!strcmp(cp1, server_hostname))
 
1702
    {
 
1703
      /* Success */
 
1704
      DBUG_RETURN(0);
 
1705
    }
 
1706
  }
 
1707
  DBUG_PRINT("error", ("SSL certificate validation failure"));
 
1708
  DBUG_RETURN(1);
 
1709
}
 
1710
 
 
1711
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
 
1712
 
 
1713
 
 
1714
/*
 
1715
  Note that the mysql argument must be initialized with mysql_init()
 
1716
  before calling mysql_real_connect !
 
1717
*/
 
1718
 
 
1719
static my_bool cli_read_query_result(MYSQL *mysql);
 
1720
static MYSQL_RES *cli_use_result(MYSQL *mysql);
 
1721
 
 
1722
static MYSQL_METHODS client_methods=
 
1723
{
 
1724
  cli_read_query_result,                       /* read_query_result */
 
1725
  cli_advanced_command,                        /* advanced_command */
 
1726
  cli_read_rows,                               /* read_rows */
 
1727
  cli_use_result,                              /* use_result */
 
1728
  cli_fetch_lengths,                           /* fetch_lengths */
 
1729
  cli_flush_use_result                         /* flush_use_result */
 
1730
#ifndef MYSQL_SERVER
 
1731
  ,cli_list_fields,                            /* list_fields */
 
1732
  cli_read_prepare_result,                     /* read_prepare_result */
 
1733
  cli_stmt_execute,                            /* stmt_execute */
 
1734
  cli_read_binary_rows,                        /* read_binary_rows */
 
1735
  cli_unbuffered_fetch,                        /* unbuffered_fetch */
 
1736
  NULL,                                        /* free_embedded_thd */
 
1737
  cli_read_statistics,                         /* read_statistics */
 
1738
  cli_read_query_result,                       /* next_result */
 
1739
  cli_read_change_user_result,                 /* read_change_user_result */
 
1740
  cli_read_binary_rows                         /* read_rows_from_cursor */
 
1741
#endif
 
1742
};
 
1743
 
 
1744
C_MODE_START
 
1745
int mysql_init_character_set(MYSQL *mysql)
 
1746
{
 
1747
  const char *default_collation_name;
 
1748
  
 
1749
  /* Set character set */
 
1750
  if (!mysql->options.charset_name)
 
1751
  {
 
1752
    default_collation_name= MYSQL_DEFAULT_COLLATION_NAME;
 
1753
    if (!(mysql->options.charset_name= 
 
1754
       my_strdup(MYSQL_DEFAULT_CHARSET_NAME,MYF(MY_WME))))
 
1755
    return 1;
 
1756
  }
 
1757
  else
 
1758
    default_collation_name= NULL;
 
1759
  
 
1760
  {
 
1761
    const char *save= charsets_dir;
 
1762
    if (mysql->options.charset_dir)
 
1763
      charsets_dir=mysql->options.charset_dir;
 
1764
    mysql->charset=get_charset_by_csname(mysql->options.charset_name,
 
1765
                                         MY_CS_PRIMARY, MYF(MY_WME));
 
1766
    if (mysql->charset && default_collation_name)
 
1767
    {
 
1768
      CHARSET_INFO *collation;
 
1769
      if ((collation= 
 
1770
           get_charset_by_name(default_collation_name, MYF(MY_WME))))
 
1771
      {
 
1772
        if (!my_charset_same(mysql->charset, collation))
 
1773
        {
 
1774
          my_printf_error(ER_UNKNOWN_ERROR, 
 
1775
                         "COLLATION %s is not valid for CHARACTER SET %s",
 
1776
                         MYF(0),
 
1777
                         default_collation_name, mysql->options.charset_name);
 
1778
          mysql->charset= NULL;
 
1779
        }
 
1780
        else
 
1781
        {
 
1782
          mysql->charset= collation;
 
1783
        }
 
1784
      }
 
1785
      else
 
1786
        mysql->charset= NULL;
 
1787
    }
 
1788
    charsets_dir= save;
 
1789
  }
 
1790
 
 
1791
  if (!mysql->charset)
 
1792
  {
 
1793
    if (mysql->options.charset_dir)
 
1794
      set_mysql_extended_error(mysql, CR_CANT_READ_CHARSET, unknown_sqlstate,
 
1795
                               ER(CR_CANT_READ_CHARSET),
 
1796
                               mysql->options.charset_name,
 
1797
                               mysql->options.charset_dir);
 
1798
    else
 
1799
    {
 
1800
      char cs_dir_name[FN_REFLEN];
 
1801
      get_charsets_dir(cs_dir_name);
 
1802
      set_mysql_extended_error(mysql, CR_CANT_READ_CHARSET, unknown_sqlstate,
 
1803
                               ER(CR_CANT_READ_CHARSET),
 
1804
                               mysql->options.charset_name,
 
1805
                               cs_dir_name);
 
1806
    }
 
1807
    return 1;
 
1808
  }
 
1809
  return 0;
 
1810
}
 
1811
C_MODE_END
 
1812
 
 
1813
 
 
1814
MYSQL * STDCALL 
 
1815
CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
 
1816
                       const char *passwd, const char *db,
 
1817
                       uint port, const char *unix_socket,ulong client_flag)
 
1818
{
 
1819
  char          buff[NAME_LEN+USERNAME_LENGTH+100];
 
1820
  char          *end,*host_info;
 
1821
  ulong         pkt_length;
 
1822
  NET           *net= &mysql->net;
 
1823
#ifdef MYSQL_SERVER
 
1824
  thr_alarm_t   alarmed;
 
1825
  ALARM         alarm_buff;
 
1826
#endif
 
1827
#ifdef __WIN__
 
1828
  HANDLE        hPipe=INVALID_HANDLE_VALUE;
 
1829
#endif
 
1830
#ifdef HAVE_SYS_UN_H
 
1831
  struct        sockaddr_un UNIXaddr;
 
1832
#endif
 
1833
  init_sigpipe_variables
 
1834
  DBUG_ENTER("mysql_real_connect");
 
1835
 
 
1836
  DBUG_PRINT("enter",("host: %s  db: %s  user: %s",
 
1837
                      host ? host : "(Null)",
 
1838
                      db ? db : "(Null)",
 
1839
                      user ? user : "(Null)"));
 
1840
 
 
1841
  /* Don't give sigpipe errors if the client doesn't want them */
 
1842
  set_sigpipe(mysql);
 
1843
  mysql->methods= &client_methods;
 
1844
  net->vio = 0;                         /* If something goes wrong */
 
1845
  mysql->client_flag=0;                 /* For handshake */
 
1846
 
 
1847
  /* use default options */
 
1848
  if (mysql->options.my_cnf_file || mysql->options.my_cnf_group)
 
1849
  {
 
1850
    mysql_read_default_options(&mysql->options,
 
1851
                               (mysql->options.my_cnf_file ?
 
1852
                                mysql->options.my_cnf_file : "my"),
 
1853
                               mysql->options.my_cnf_group);
 
1854
    my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
 
1855
    my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
 
1856
    mysql->options.my_cnf_file=mysql->options.my_cnf_group=0;
 
1857
  }
 
1858
 
 
1859
  /* Some empty-string-tests are done because of ODBC */
 
1860
  if (!host || !host[0])
 
1861
    host=mysql->options.host;
 
1862
  if (!user || !user[0])
 
1863
  {
 
1864
    user=mysql->options.user;
 
1865
    if (!user)
 
1866
      user= "";
 
1867
  }
 
1868
  if (!passwd)
 
1869
  {
 
1870
    passwd=mysql->options.password;
 
1871
#if !defined(DONT_USE_MYSQL_PWD) && !defined(MYSQL_SERVER)
 
1872
    if (!passwd)
 
1873
      passwd=getenv("MYSQL_PWD");               /* get it from environment */
 
1874
#endif
 
1875
    if (!passwd)
 
1876
      passwd= "";
 
1877
  }
 
1878
  if (!db || !db[0])
 
1879
    db=mysql->options.db;
 
1880
  if (!port)
 
1881
    port=mysql->options.port;
 
1882
  if (!unix_socket)
 
1883
    unix_socket=mysql->options.unix_socket;
 
1884
 
 
1885
  mysql->server_status=SERVER_STATUS_AUTOCOMMIT;
 
1886
 
 
1887
  /*
 
1888
    Part 0: Grab a socket and connect it to the server
 
1889
  */
 
1890
#if defined(HAVE_SMEM)
 
1891
  if ((!mysql->options.protocol ||
 
1892
       mysql->options.protocol == MYSQL_PROTOCOL_MEMORY) &&
 
1893
      (!host || !strcmp(host,LOCAL_HOST)))
 
1894
  {
 
1895
    if ((create_shared_memory(mysql,net, mysql->options.connect_timeout)) ==
 
1896
        INVALID_HANDLE_VALUE)
 
1897
    {
 
1898
      DBUG_PRINT("error",
 
1899
                 ("host: '%s'  socket: '%s'  shared memory: %s  have_tcpip: %d",
 
1900
                  host ? host : "<null>",
 
1901
                  unix_socket ? unix_socket : "<null>",
 
1902
                  (int) mysql->options.shared_memory_base_name,
 
1903
                  (int) have_tcpip));
 
1904
      if (mysql->options.protocol == MYSQL_PROTOCOL_MEMORY)
 
1905
        goto error;
 
1906
 
 
1907
      /*
 
1908
        Try also with PIPE or TCP/IP. Clear the error from
 
1909
        create_shared_memory().
 
1910
      */
 
1911
 
 
1912
      net_clear_error(net);
 
1913
    }
 
1914
    else
 
1915
    {
 
1916
      mysql->options.protocol=MYSQL_PROTOCOL_MEMORY;
 
1917
      unix_socket = 0;
 
1918
      host=mysql->options.shared_memory_base_name;
 
1919
      my_snprintf(host_info=buff, sizeof(buff)-1,
 
1920
                  ER(CR_SHARED_MEMORY_CONNECTION), host);
 
1921
    }
 
1922
  }
 
1923
#endif /* HAVE_SMEM */
 
1924
#if defined(HAVE_SYS_UN_H)
 
1925
  if (!net->vio &&
 
1926
      (!mysql->options.protocol ||
 
1927
       mysql->options.protocol == MYSQL_PROTOCOL_SOCKET) &&
 
1928
      (unix_socket || mysql_unix_port) &&
 
1929
      (!host || !strcmp(host,LOCAL_HOST)))
 
1930
  {
 
1931
    my_socket sock= socket(AF_UNIX, SOCK_STREAM, 0);
 
1932
    if (sock == SOCKET_ERROR)
 
1933
    {
 
1934
      set_mysql_extended_error(mysql, CR_SOCKET_CREATE_ERROR,
 
1935
                               unknown_sqlstate,
 
1936
                               ER(CR_SOCKET_CREATE_ERROR),
 
1937
                               socket_errno);
 
1938
      goto error;
 
1939
    }
 
1940
 
 
1941
    net->vio= vio_new(sock, VIO_TYPE_SOCKET,
 
1942
                      VIO_LOCALHOST | VIO_BUFFERED_READ);
 
1943
    if (!net->vio)
 
1944
    {
 
1945
      DBUG_PRINT("error",("Unknow protocol %d ", mysql->options.protocol));
 
1946
      set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
 
1947
      closesocket(sock);
 
1948
      goto error;
 
1949
    }
 
1950
 
 
1951
    host= LOCAL_HOST;
 
1952
    if (!unix_socket)
 
1953
      unix_socket= mysql_unix_port;
 
1954
    host_info= (char*) ER(CR_LOCALHOST_CONNECTION);
 
1955
    DBUG_PRINT("info", ("Using UNIX sock '%s'", unix_socket));
 
1956
 
 
1957
    bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
 
1958
    UNIXaddr.sun_family= AF_UNIX;
 
1959
    strmake(UNIXaddr.sun_path, unix_socket, sizeof(UNIXaddr.sun_path)-1);
 
1960
 
 
1961
    if (my_connect(sock, (struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
 
1962
                   mysql->options.connect_timeout))
 
1963
    {
 
1964
      DBUG_PRINT("error",("Got error %d on connect to local server",
 
1965
                          socket_errno));
 
1966
      set_mysql_extended_error(mysql, CR_CONNECTION_ERROR,
 
1967
                               unknown_sqlstate,
 
1968
                               ER(CR_CONNECTION_ERROR),
 
1969
                               unix_socket, socket_errno);
 
1970
      vio_delete(net->vio);
 
1971
      net->vio= 0;
 
1972
      goto error;
 
1973
    }
 
1974
    mysql->options.protocol=MYSQL_PROTOCOL_SOCKET;
 
1975
  }
 
1976
#elif defined(__WIN__)
 
1977
  if (!net->vio &&
 
1978
      (mysql->options.protocol == MYSQL_PROTOCOL_PIPE ||
 
1979
       (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) ||
 
1980
       (! have_tcpip && (unix_socket || !host && is_NT()))))
 
1981
  {
 
1982
    if ((hPipe= create_named_pipe(mysql, mysql->options.connect_timeout,
 
1983
                                  (char**) &host, (char**) &unix_socket)) ==
 
1984
        INVALID_HANDLE_VALUE)
 
1985
    {
 
1986
      DBUG_PRINT("error",
 
1987
                 ("host: '%s'  socket: '%s'  have_tcpip: %d",
 
1988
                  host ? host : "<null>",
 
1989
                  unix_socket ? unix_socket : "<null>",
 
1990
                  (int) have_tcpip));
 
1991
      if (mysql->options.protocol == MYSQL_PROTOCOL_PIPE ||
 
1992
          (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) ||
 
1993
          (unix_socket && !strcmp(unix_socket,MYSQL_NAMEDPIPE)))
 
1994
        goto error;
 
1995
      /* Try also with TCP/IP */
 
1996
    }
 
1997
    else
 
1998
    {
 
1999
      net->vio=vio_new_win32pipe(hPipe);
 
2000
      my_snprintf(host_info=buff, sizeof(buff)-1,
 
2001
                  ER(CR_NAMEDPIPE_CONNECTION), unix_socket);
 
2002
    }
 
2003
  }
 
2004
#endif
 
2005
  if (!net->vio &&
 
2006
      (!mysql->options.protocol ||
 
2007
       mysql->options.protocol == MYSQL_PROTOCOL_TCP))
 
2008
  {
 
2009
    struct addrinfo *res_lst, hints, *t_res;
 
2010
    int gai_errno;
 
2011
    char port_buf[NI_MAXSERV];
 
2012
 
 
2013
    unix_socket=0;                              /* This is not used */
 
2014
 
 
2015
    if (!port)
 
2016
      port= mysql_port;
 
2017
 
 
2018
    if (!host)
 
2019
      host= LOCAL_HOST;
 
2020
 
 
2021
    my_snprintf(host_info=buff, sizeof(buff)-1, ER(CR_TCP_CONNECTION), host);
 
2022
    DBUG_PRINT("info",("Server name: '%s'.  TCP sock: %d", host, port));
 
2023
#ifdef MYSQL_SERVER
 
2024
    thr_alarm_init(&alarmed);
 
2025
    thr_alarm(&alarmed, mysql->options.connect_timeout, &alarm_buff);
 
2026
#endif
 
2027
 
 
2028
    DBUG_PRINT("info",("IP '%s'", "client"));
 
2029
 
 
2030
#ifdef MYSQL_SERVER
 
2031
    thr_end_alarm(&alarmed);
 
2032
#endif
 
2033
 
 
2034
    memset(&hints, 0, sizeof(hints));
 
2035
    hints.ai_socktype= SOCK_STREAM;
 
2036
    hints.ai_protocol= IPPROTO_TCP;
 
2037
    hints.ai_family= AF_UNSPEC;
 
2038
 
 
2039
    DBUG_PRINT("info",("IPV6 getaddrinfo %s", host));
 
2040
    my_snprintf(port_buf, NI_MAXSERV, "%d", port);
 
2041
    gai_errno= getaddrinfo(host, port_buf, &hints, &res_lst);
 
2042
 
 
2043
    if (gai_errno != 0) 
 
2044
    { 
 
2045
      /* 
 
2046
        For DBUG we are keeping the right message but for client we default to
 
2047
        historical error message.
 
2048
      */
 
2049
      DBUG_PRINT("info",("IPV6 getaddrinfo error %d", gai_errno));
 
2050
      set_mysql_extended_error(mysql, CR_UNKNOWN_HOST, unknown_sqlstate,
 
2051
                               ER(CR_UNKNOWN_HOST), host, errno);
 
2052
 
 
2053
      goto error;
 
2054
    }
 
2055
 
 
2056
    /* We only look at the first item (something to think about changing in the future) */
 
2057
    t_res= res_lst; 
 
2058
    {
 
2059
      my_socket sock= socket(t_res->ai_family, t_res->ai_socktype,
 
2060
                             t_res->ai_protocol);
 
2061
      if (sock == SOCKET_ERROR)
 
2062
      {
 
2063
        set_mysql_extended_error(mysql, CR_IPSOCK_ERROR, unknown_sqlstate,
 
2064
                                 ER(CR_IPSOCK_ERROR), socket_errno);
 
2065
        freeaddrinfo(res_lst);
 
2066
        goto error;
 
2067
      }
 
2068
 
 
2069
      net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
 
2070
      if (! net->vio )
 
2071
      {
 
2072
        DBUG_PRINT("error",("Unknow protocol %d ", mysql->options.protocol));
 
2073
        set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
 
2074
        closesocket(sock);
 
2075
        freeaddrinfo(res_lst);
 
2076
        goto error;
 
2077
      }
 
2078
 
 
2079
      if (my_connect(sock, t_res->ai_addr, t_res->ai_addrlen,
 
2080
                     mysql->options.connect_timeout))
 
2081
      {
 
2082
        DBUG_PRINT("error",("Got error %d on connect to '%s'",socket_errno,
 
2083
                            host));
 
2084
        set_mysql_extended_error(mysql, CR_CONN_HOST_ERROR, unknown_sqlstate,
 
2085
                                 ER(CR_CONN_HOST_ERROR), host, socket_errno);
 
2086
        vio_delete(net->vio);
 
2087
        net->vio= 0;
 
2088
        freeaddrinfo(res_lst);
 
2089
        goto error;
 
2090
      }
 
2091
    }
 
2092
 
 
2093
    freeaddrinfo(res_lst);
 
2094
  }
 
2095
 
 
2096
  if (!net->vio)
 
2097
  {
 
2098
    DBUG_PRINT("error",("Unknow protocol %d ",mysql->options.protocol));
 
2099
    set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
 
2100
    goto error;
 
2101
  }
 
2102
 
 
2103
  if (my_net_init(net, net->vio))
 
2104
  {
 
2105
    vio_delete(net->vio);
 
2106
    net->vio = 0;
 
2107
    set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
2108
    goto error;
 
2109
  }
 
2110
  vio_keepalive(net->vio,TRUE);
 
2111
 
 
2112
  /* If user set read_timeout, let it override the default */
 
2113
  if (mysql->options.read_timeout)
 
2114
    my_net_set_read_timeout(net, mysql->options.read_timeout);
 
2115
 
 
2116
  /* If user set write_timeout, let it override the default */
 
2117
  if (mysql->options.write_timeout)
 
2118
    my_net_set_write_timeout(net, mysql->options.write_timeout);
 
2119
 
 
2120
  if (mysql->options.max_allowed_packet)
 
2121
    net->max_packet_size= mysql->options.max_allowed_packet;
 
2122
 
 
2123
  /* Get version info */
 
2124
  mysql->protocol_version= PROTOCOL_VERSION;    /* Assume this */
 
2125
  if (mysql->options.connect_timeout &&
 
2126
      vio_poll_read(net->vio, mysql->options.connect_timeout))
 
2127
  {
 
2128
    set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
 
2129
                             ER(CR_SERVER_LOST_EXTENDED),
 
2130
                             "waiting for initial communication packet",
 
2131
                             errno);
 
2132
    goto error;
 
2133
  }
 
2134
 
 
2135
  /*
 
2136
    Part 1: Connection established, read and parse first packet
 
2137
  */
 
2138
 
 
2139
  if ((pkt_length=cli_safe_read(mysql)) == packet_error)
 
2140
  {
 
2141
    if (mysql->net.last_errno == CR_SERVER_LOST)
 
2142
      set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
 
2143
                               ER(CR_SERVER_LOST_EXTENDED),
 
2144
                               "reading initial communication packet",
 
2145
                               errno);
 
2146
    goto error;
 
2147
  }
 
2148
  /* Check if version of protocol matches current one */
 
2149
 
 
2150
  mysql->protocol_version= net->read_pos[0];
 
2151
  DBUG_DUMP("packet",(uchar*) net->read_pos,10);
 
2152
  DBUG_PRINT("info",("mysql protocol version %d, server=%d",
 
2153
                     PROTOCOL_VERSION, mysql->protocol_version));
 
2154
  if (mysql->protocol_version != PROTOCOL_VERSION)
 
2155
  {
 
2156
    set_mysql_extended_error(mysql, CR_VERSION_ERROR, unknown_sqlstate,
 
2157
                             ER(CR_VERSION_ERROR), mysql->protocol_version,
 
2158
                             PROTOCOL_VERSION);
 
2159
    goto error;
 
2160
  }
 
2161
  end=strend((char*) net->read_pos+1);
 
2162
  mysql->thread_id=uint4korr(end+1);
 
2163
  end+=5;
 
2164
  /* 
 
2165
    Scramble is split into two parts because old clients does not understand
 
2166
    long scrambles; here goes the first part.
 
2167
  */
 
2168
  strmake(mysql->scramble, end, SCRAMBLE_LENGTH_323);
 
2169
  end+= SCRAMBLE_LENGTH_323+1;
 
2170
 
 
2171
  if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
 
2172
    mysql->server_capabilities=uint2korr(end);
 
2173
  if (pkt_length >= (uint) (end+18 - (char*) net->read_pos))
 
2174
  {
 
2175
    /* New protocol with 16 bytes to describe server characteristics */
 
2176
    mysql->server_language=end[2];
 
2177
    mysql->server_status=uint2korr(end+3);
 
2178
  }
 
2179
  end+= 18;
 
2180
  if (pkt_length >= (uint) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 - 
 
2181
                           (char *) net->read_pos))
 
2182
    strmake(mysql->scramble+SCRAMBLE_LENGTH_323, end,
 
2183
            SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323);
 
2184
  else
 
2185
    mysql->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
 
2186
 
 
2187
  if (mysql->options.secure_auth && passwd[0] &&
 
2188
      !(mysql->server_capabilities & CLIENT_SECURE_CONNECTION))
 
2189
  {
 
2190
    set_mysql_error(mysql, CR_SECURE_AUTH, unknown_sqlstate);
 
2191
    goto error;
 
2192
  }
 
2193
 
 
2194
  if (mysql_init_character_set(mysql))
 
2195
    goto error;
 
2196
 
 
2197
  /* Save connection information */
 
2198
  if (!my_multi_malloc(MYF(0),
 
2199
                       &mysql->host_info, (uint) strlen(host_info)+1,
 
2200
                       &mysql->host,      (uint) strlen(host)+1,
 
2201
                       &mysql->unix_socket,unix_socket ?
 
2202
                       (uint) strlen(unix_socket)+1 : (uint) 1,
 
2203
                       &mysql->server_version,
 
2204
                       (uint) (end - (char*) net->read_pos),
 
2205
                       NullS) ||
 
2206
      !(mysql->user=my_strdup(user,MYF(0))) ||
 
2207
      !(mysql->passwd=my_strdup(passwd,MYF(0))))
 
2208
  {
 
2209
    set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
2210
    goto error;
 
2211
  }
 
2212
  strmov(mysql->host_info,host_info);
 
2213
  strmov(mysql->host,host);
 
2214
  if (unix_socket)
 
2215
    strmov(mysql->unix_socket,unix_socket);
 
2216
  else
 
2217
    mysql->unix_socket=0;
 
2218
  strmov(mysql->server_version,(char*) net->read_pos+1);
 
2219
  mysql->port=port;
 
2220
 
 
2221
  /*
 
2222
    Part 2: format and send client info to the server for access check
 
2223
  */
 
2224
  
 
2225
  client_flag|=mysql->options.client_flag;
 
2226
  client_flag|=CLIENT_CAPABILITIES;
 
2227
  if (client_flag & CLIENT_MULTI_STATEMENTS)
 
2228
    client_flag|= CLIENT_MULTI_RESULTS;
 
2229
 
 
2230
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
2231
  if (mysql->options.ssl_key || mysql->options.ssl_cert ||
 
2232
      mysql->options.ssl_ca || mysql->options.ssl_capath ||
 
2233
      mysql->options.ssl_cipher)
 
2234
    mysql->options.use_ssl= 1;
 
2235
  if (mysql->options.use_ssl)
 
2236
    client_flag|=CLIENT_SSL;
 
2237
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY*/
 
2238
  if (db)
 
2239
    client_flag|=CLIENT_CONNECT_WITH_DB;
 
2240
 
 
2241
  /* Remove options that server doesn't support */
 
2242
  client_flag= ((client_flag &
 
2243
                 ~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)) |
 
2244
                (client_flag & mysql->server_capabilities));
 
2245
  client_flag&= ~CLIENT_COMPRESS;
 
2246
 
 
2247
  if (client_flag & CLIENT_PROTOCOL_41)
 
2248
  {
 
2249
    /* 4.1 server and 4.1 client has a 32 byte option flag */
 
2250
    int4store(buff,client_flag);
 
2251
    int4store(buff+4, net->max_packet_size);
 
2252
    buff[8]= (char) mysql->charset->number;
 
2253
    bzero(buff+9, 32-9);
 
2254
    end= buff+32;
 
2255
  }
 
2256
  else
 
2257
  {
 
2258
    int2store(buff,client_flag);
 
2259
    int3store(buff+2,net->max_packet_size);
 
2260
    end= buff+5;
 
2261
  }
 
2262
  mysql->client_flag=client_flag;
 
2263
 
 
2264
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
2265
  if (client_flag & CLIENT_SSL)
 
2266
  {
 
2267
    /* Do the SSL layering. */
 
2268
    struct st_mysql_options *options= &mysql->options;
 
2269
    struct st_VioSSLFd *ssl_fd;
 
2270
 
 
2271
    /*
 
2272
      Send client_flag, max_packet_size - unencrypted otherwise
 
2273
      the server does not know we want to do SSL
 
2274
    */
 
2275
    if (my_net_write(net, (uchar*) buff, (uint) (end-buff)) || net_flush(net))
 
2276
    {
 
2277
      set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
 
2278
                               ER(CR_SERVER_LOST_EXTENDED),
 
2279
                               "sending connection information to server",
 
2280
                               errno);
 
2281
      goto error;
 
2282
    }
 
2283
 
 
2284
    /* Create the VioSSLConnectorFd - init SSL and load certs */
 
2285
    if (!(ssl_fd= new_VioSSLConnectorFd(options->ssl_key,
 
2286
                                        options->ssl_cert,
 
2287
                                        options->ssl_ca,
 
2288
                                        options->ssl_capath,
 
2289
                                        options->ssl_cipher)))
 
2290
    {
 
2291
      set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
 
2292
      goto error;
 
2293
    }
 
2294
    mysql->connector_fd= (void*)ssl_fd;
 
2295
 
 
2296
    /* Connect to the server */
 
2297
    DBUG_PRINT("info", ("IO layer change in progress..."));
 
2298
    if (sslconnect(ssl_fd, mysql->net.vio,
 
2299
                   (long) (mysql->options.connect_timeout)))
 
2300
    {
 
2301
      set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
 
2302
      goto error;
 
2303
    }
 
2304
    DBUG_PRINT("info", ("IO layer change done!"));
 
2305
 
 
2306
    /* Verify server cert */
 
2307
    if ((client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
 
2308
        ssl_verify_server_cert(mysql->net.vio, mysql->host))
 
2309
    {
 
2310
      set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate);
 
2311
      goto error;
 
2312
    }
 
2313
 
 
2314
  }
 
2315
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
 
2316
 
 
2317
  DBUG_PRINT("info",("Server version = '%s'  capabilites: %lu  status: %u  client_flag: %lu",
 
2318
                     mysql->server_version,mysql->server_capabilities,
 
2319
                     mysql->server_status, client_flag));
 
2320
  /* This needs to be changed as it's not useful with big packets */
 
2321
  if (user && user[0])
 
2322
    strmake(end,user,USERNAME_LENGTH);          /* Max user name */
 
2323
  else
 
2324
    read_user_name((char*) end);
 
2325
 
 
2326
  /* We have to handle different version of handshake here */
 
2327
#ifdef _CUSTOMCONFIG_
 
2328
#include "_cust_libmysql.h"
 
2329
#endif
 
2330
  DBUG_PRINT("info",("user: %s",end));
 
2331
  end= strend(end) + 1;
 
2332
  if (passwd[0])
 
2333
  {
 
2334
    if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
 
2335
    {
 
2336
      *end++= SCRAMBLE_LENGTH;
 
2337
      scramble(end, mysql->scramble, passwd);
 
2338
      end+= SCRAMBLE_LENGTH;
 
2339
    }
 
2340
    else
 
2341
    {
 
2342
      scramble_323(end, mysql->scramble, passwd);
 
2343
      end+= SCRAMBLE_LENGTH_323 + 1;
 
2344
    }
 
2345
  }
 
2346
  else
 
2347
    *end++= '\0';                               /* empty password */
 
2348
 
 
2349
  /* Add database if needed */
 
2350
  if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
 
2351
  {
 
2352
    end= strmake(end, db, NAME_LEN) + 1;
 
2353
    mysql->db= my_strdup(db,MYF(MY_WME));
 
2354
    db= 0;
 
2355
  }
 
2356
  /* Write authentication package */
 
2357
  if (my_net_write(net, (uchar*) buff, (size_t) (end-buff)) || net_flush(net))
 
2358
  {
 
2359
    set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
 
2360
                             ER(CR_SERVER_LOST_EXTENDED),
 
2361
                             "sending authentication information",
 
2362
                             errno);
 
2363
    goto error;
 
2364
  }
 
2365
  
 
2366
  /*
 
2367
    Part 3: Authorization data's been sent. Now server can reply with
 
2368
    OK-packet, or re-request scrambled password.
 
2369
  */
 
2370
 
 
2371
  if ((pkt_length=cli_safe_read(mysql)) == packet_error)
 
2372
  {
 
2373
    if (mysql->net.last_errno == CR_SERVER_LOST)
 
2374
      set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
 
2375
                               ER(CR_SERVER_LOST_EXTENDED),
 
2376
                               "reading authorization packet",
 
2377
                               errno);
 
2378
    goto error;
 
2379
  }
 
2380
 
 
2381
  if (pkt_length == 1 && net->read_pos[0] == 254 && 
 
2382
      mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
 
2383
  {
 
2384
    /*
 
2385
      By sending this very specific reply server asks us to send scrambled
 
2386
      password in old format.
 
2387
    */
 
2388
    scramble_323(buff, mysql->scramble, passwd);
 
2389
    if (my_net_write(net, (uchar*) buff, SCRAMBLE_LENGTH_323 + 1) ||
 
2390
        net_flush(net))
 
2391
    {
 
2392
      set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
 
2393
                               ER(CR_SERVER_LOST_EXTENDED),
 
2394
                               "sending password information",
 
2395
                               errno);
 
2396
      goto error;
 
2397
    }
 
2398
    /* Read what server thinks about out new auth message report */
 
2399
    if (cli_safe_read(mysql) == packet_error)
 
2400
    {
 
2401
      if (mysql->net.last_errno == CR_SERVER_LOST)
 
2402
        set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
 
2403
                                 ER(CR_SERVER_LOST_EXTENDED),
 
2404
                                 "reading final connect information",
 
2405
                                 errno);
 
2406
      goto error;
 
2407
    }
 
2408
  }
 
2409
 
 
2410
  if (client_flag & CLIENT_COMPRESS)            /* We will use compression */
 
2411
    net->compress=1;
 
2412
 
 
2413
#ifdef CHECK_LICENSE 
 
2414
  if (check_license(mysql))
 
2415
    goto error;
 
2416
#endif
 
2417
 
 
2418
  if (db && mysql_select_db(mysql, db))
 
2419
  {
 
2420
    if (mysql->net.last_errno == CR_SERVER_LOST)
 
2421
        set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
 
2422
                                 ER(CR_SERVER_LOST_EXTENDED),
 
2423
                                 "Setting intital database",
 
2424
                                 errno);
 
2425
    goto error;
 
2426
  }
 
2427
 
 
2428
  if (mysql->options.init_commands)
 
2429
  {
 
2430
    DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
 
2431
    char **ptr= (char**)init_commands->buffer;
 
2432
    char **end_command= ptr + init_commands->elements;
 
2433
 
 
2434
    my_bool reconnect=mysql->reconnect;
 
2435
    mysql->reconnect=0;
 
2436
 
 
2437
    for (; ptr < end_command; ptr++)
 
2438
    {
 
2439
      MYSQL_RES *res;
 
2440
      if (mysql_real_query(mysql,*ptr, (ulong) strlen(*ptr)))
 
2441
        goto error;
 
2442
      if (mysql->fields)
 
2443
      {
 
2444
        if (!(res= cli_use_result(mysql)))
 
2445
          goto error;
 
2446
        mysql_free_result(res);
 
2447
      }
 
2448
    }
 
2449
    mysql->reconnect=reconnect;
 
2450
  }
 
2451
 
 
2452
  DBUG_PRINT("exit", ("Mysql handler: 0x%lx", (long) mysql));
 
2453
  reset_sigpipe(mysql);
 
2454
  DBUG_RETURN(mysql);
 
2455
 
 
2456
error:
 
2457
  reset_sigpipe(mysql);
 
2458
  DBUG_PRINT("error",("message: %u/%s (%s)",
 
2459
                      net->last_errno,
 
2460
                      net->sqlstate,
 
2461
                      net->last_error));
 
2462
  {
 
2463
    /* Free alloced memory */
 
2464
    end_server(mysql);
 
2465
    mysql_close_free(mysql);
 
2466
    if (!(((ulong) client_flag) & CLIENT_REMEMBER_OPTIONS))
 
2467
      mysql_close_free_options(mysql);
 
2468
  }
 
2469
  DBUG_RETURN(0);
 
2470
}
 
2471
 
 
2472
 
 
2473
my_bool mysql_reconnect(MYSQL *mysql)
 
2474
{
 
2475
  MYSQL tmp_mysql;
 
2476
  DBUG_ENTER("mysql_reconnect");
 
2477
  DBUG_ASSERT(mysql);
 
2478
  DBUG_PRINT("enter", ("mysql->reconnect: %d", mysql->reconnect));
 
2479
 
 
2480
  if (!mysql->reconnect ||
 
2481
      (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info)
 
2482
  {
 
2483
    /* Allow reconnect next time */
 
2484
    mysql->server_status&= ~SERVER_STATUS_IN_TRANS;
 
2485
    set_mysql_error(mysql, CR_SERVER_GONE_ERROR, unknown_sqlstate);
 
2486
    DBUG_RETURN(1);
 
2487
  }
 
2488
  mysql_init(&tmp_mysql);
 
2489
  tmp_mysql.options= mysql->options;
 
2490
  tmp_mysql.options.my_cnf_file= tmp_mysql.options.my_cnf_group= 0;
 
2491
 
 
2492
  if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd,
 
2493
                          mysql->db, mysql->port, mysql->unix_socket,
 
2494
                          mysql->client_flag | CLIENT_REMEMBER_OPTIONS))
 
2495
  {
 
2496
    mysql->net.last_errno= tmp_mysql.net.last_errno;
 
2497
    strmov(mysql->net.last_error, tmp_mysql.net.last_error);
 
2498
    strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate);
 
2499
    DBUG_RETURN(1);
 
2500
  }
 
2501
  if (mysql_set_character_set(&tmp_mysql, mysql->charset->csname))
 
2502
  {
 
2503
    DBUG_PRINT("error", ("mysql_set_character_set() failed"));
 
2504
    bzero((char*) &tmp_mysql.options,sizeof(tmp_mysql.options));
 
2505
    mysql_close(&tmp_mysql);
 
2506
    mysql->net.last_errno= tmp_mysql.net.last_errno;
 
2507
    strmov(mysql->net.last_error, tmp_mysql.net.last_error);
 
2508
    strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate);
 
2509
    DBUG_RETURN(1);
 
2510
  }
 
2511
 
 
2512
  DBUG_PRINT("info", ("reconnect succeded"));
 
2513
  tmp_mysql.reconnect= 1;
 
2514
  tmp_mysql.free_me= mysql->free_me;
 
2515
 
 
2516
  /*
 
2517
    For each stmt in mysql->stmts, move it to tmp_mysql if it is
 
2518
    in state MYSQL_STMT_INIT_DONE, otherwise close it.
 
2519
  */
 
2520
  {
 
2521
    LIST *element= mysql->stmts;
 
2522
    for (; element; element= element->next)
 
2523
    {
 
2524
      MYSQL_STMT *stmt= (MYSQL_STMT *) element->data;
 
2525
      if (stmt->state != MYSQL_STMT_INIT_DONE)
 
2526
      {
 
2527
        stmt->mysql= 0;
 
2528
        stmt->last_errno= CR_SERVER_LOST;
 
2529
        strmov(stmt->last_error, ER(CR_SERVER_LOST));
 
2530
        strmov(stmt->sqlstate, unknown_sqlstate);
 
2531
      }
 
2532
      else
 
2533
      {
 
2534
        tmp_mysql.stmts= list_add(tmp_mysql.stmts, &stmt->list);
 
2535
      }
 
2536
      /* No need to call list_delete for statement here */
 
2537
    }
 
2538
    mysql->stmts= NULL;
 
2539
  }
 
2540
 
 
2541
  /* Don't free options as these are now used in tmp_mysql */
 
2542
  bzero((char*) &mysql->options,sizeof(mysql->options));
 
2543
  mysql->free_me=0;
 
2544
  mysql_close(mysql);
 
2545
  *mysql=tmp_mysql;
 
2546
  net_clear(&mysql->net, 1);
 
2547
  mysql->affected_rows= ~(my_ulonglong) 0;
 
2548
  DBUG_RETURN(0);
 
2549
}
 
2550
 
 
2551
 
 
2552
/**************************************************************************
 
2553
  Set current database
 
2554
**************************************************************************/
 
2555
 
 
2556
int STDCALL
 
2557
mysql_select_db(MYSQL *mysql, const char *db)
 
2558
{
 
2559
  int error;
 
2560
  DBUG_ENTER("mysql_select_db");
 
2561
  DBUG_PRINT("enter",("db: '%s'",db));
 
2562
 
 
2563
  if ((error=simple_command(mysql,COM_INIT_DB, (const uchar*) db,
 
2564
                            (ulong) strlen(db),0)))
 
2565
    DBUG_RETURN(error);
 
2566
  my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
 
2567
  mysql->db=my_strdup(db,MYF(MY_WME));
 
2568
  DBUG_RETURN(0);
 
2569
}
 
2570
 
 
2571
 
 
2572
/*************************************************************************
 
2573
  Send a QUIT to the server and close the connection
 
2574
  If handle is alloced by mysql connect free it.
 
2575
*************************************************************************/
 
2576
 
 
2577
static void mysql_close_free_options(MYSQL *mysql)
 
2578
{
 
2579
  DBUG_ENTER("mysql_close_free_options");
 
2580
 
 
2581
  my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR));
 
2582
  my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR));
 
2583
  my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR));
 
2584
  my_free(mysql->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR));
 
2585
  my_free(mysql->options.db,MYF(MY_ALLOW_ZERO_PTR));
 
2586
  my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
 
2587
  my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
 
2588
  my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
 
2589
  my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
 
2590
  my_free(mysql->options.client_ip,MYF(MY_ALLOW_ZERO_PTR));
 
2591
  if (mysql->options.init_commands)
 
2592
  {
 
2593
    DYNAMIC_ARRAY *init_commands= mysql->options.init_commands;
 
2594
    char **ptr= (char**)init_commands->buffer;
 
2595
    char **end= ptr + init_commands->elements;
 
2596
    for (; ptr<end; ptr++)
 
2597
      my_free(*ptr,MYF(MY_WME));
 
2598
    delete_dynamic(init_commands);
 
2599
    my_free((char*)init_commands,MYF(MY_WME));
 
2600
  }
 
2601
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
 
2602
  mysql_ssl_free(mysql);
 
2603
#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
 
2604
#ifdef HAVE_SMEM
 
2605
  if (mysql->options.shared_memory_base_name != def_shared_memory_base_name)
 
2606
    my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
 
2607
#endif /* HAVE_SMEM */
 
2608
  bzero((char*) &mysql->options,sizeof(mysql->options));
 
2609
  DBUG_VOID_RETURN;
 
2610
}
 
2611
 
 
2612
 
 
2613
static void mysql_close_free(MYSQL *mysql)
 
2614
{
 
2615
  my_free((uchar*) mysql->host_info,MYF(MY_ALLOW_ZERO_PTR));
 
2616
  my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
 
2617
  my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
 
2618
  my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
 
2619
#if defined(EMBEDDED_LIBRARY) || MYSQL_VERSION_ID >= 50100
 
2620
  my_free(mysql->info_buffer,MYF(MY_ALLOW_ZERO_PTR));
 
2621
  mysql->info_buffer= 0;
 
2622
#endif
 
2623
  /* Clear pointers for better safety */
 
2624
  mysql->host_info= mysql->user= mysql->passwd= mysql->db= 0;
 
2625
}
 
2626
 
 
2627
 
 
2628
/*
 
2629
  Clear connection pointer of every statement: this is necessary
 
2630
  to give error on attempt to use a prepared statement of closed
 
2631
  connection.
 
2632
 
 
2633
  SYNOPSYS
 
2634
    mysql_detach_stmt_list()
 
2635
      stmt_list  pointer to mysql->stmts
 
2636
      func_name  name of calling function
 
2637
 
 
2638
  NOTE
 
2639
    There is similar code in mysql_reconnect(), so changes here
 
2640
    should also be reflected there.
 
2641
*/
 
2642
 
 
2643
void mysql_detach_stmt_list(LIST **stmt_list __attribute__((unused)),
 
2644
                            const char *func_name __attribute__((unused)))
 
2645
{
 
2646
#ifdef MYSQL_CLIENT
 
2647
  /* Reset connection handle in all prepared statements. */
 
2648
  LIST *element= *stmt_list;
 
2649
  char buff[MYSQL_ERRMSG_SIZE];
 
2650
  DBUG_ENTER("mysql_detach_stmt_list");
 
2651
 
 
2652
  my_snprintf(buff, sizeof(buff)-1, ER(CR_STMT_CLOSED), func_name);
 
2653
  for (; element; element= element->next)
 
2654
  {
 
2655
    MYSQL_STMT *stmt= (MYSQL_STMT *) element->data;
 
2656
    set_stmt_error(stmt, CR_STMT_CLOSED, unknown_sqlstate, buff);
 
2657
    stmt->mysql= 0;
 
2658
    /* No need to call list_delete for statement here */
 
2659
  }
 
2660
  *stmt_list= 0;
 
2661
  DBUG_VOID_RETURN;
 
2662
#endif /* MYSQL_CLIENT */
 
2663
}
 
2664
 
 
2665
 
 
2666
void STDCALL mysql_close(MYSQL *mysql)
 
2667
{
 
2668
  DBUG_ENTER("mysql_close");
 
2669
  if (mysql)                                    /* Some simple safety */
 
2670
  {
 
2671
    /* If connection is still up, send a QUIT message */
 
2672
    if (mysql->net.vio != 0)
 
2673
    {
 
2674
      free_old_query(mysql);
 
2675
      mysql->status=MYSQL_STATUS_READY; /* Force command */
 
2676
      mysql->reconnect=0;
 
2677
      simple_command(mysql,COM_QUIT,(uchar*) 0,0,1);
 
2678
      end_server(mysql);                        /* Sets mysql->net.vio= 0 */
 
2679
    }
 
2680
    mysql_close_free_options(mysql);
 
2681
    mysql_close_free(mysql);
 
2682
    mysql_detach_stmt_list(&mysql->stmts, "mysql_close");
 
2683
#ifndef MYSQL_SERVER
 
2684
    if (mysql->thd)
 
2685
      (*mysql->methods->free_embedded_thd)(mysql);
 
2686
#endif
 
2687
    if (mysql->free_me)
 
2688
      my_free((uchar*) mysql,MYF(0));
 
2689
  }
 
2690
  DBUG_VOID_RETURN;
 
2691
}
 
2692
 
 
2693
 
 
2694
static my_bool cli_read_query_result(MYSQL *mysql)
 
2695
{
 
2696
  uchar *pos;
 
2697
  ulong field_count;
 
2698
  MYSQL_DATA *fields;
 
2699
  ulong length;
 
2700
  DBUG_ENTER("cli_read_query_result");
 
2701
 
 
2702
  if ((length = cli_safe_read(mysql)) == packet_error)
 
2703
    DBUG_RETURN(1);
 
2704
  free_old_query(mysql);                /* Free old result */
 
2705
#ifdef MYSQL_CLIENT                     /* Avoid warn of unused labels*/
 
2706
get_info:
 
2707
#endif
 
2708
  pos=(uchar*) mysql->net.read_pos;
 
2709
  if ((field_count= net_field_length(&pos)) == 0)
 
2710
  {
 
2711
    mysql->affected_rows= net_field_length_ll(&pos);
 
2712
    mysql->insert_id=     net_field_length_ll(&pos);
 
2713
    DBUG_PRINT("info",("affected_rows: %lu  insert_id: %lu",
 
2714
                       (ulong) mysql->affected_rows,
 
2715
                       (ulong) mysql->insert_id));
 
2716
    if (protocol_41(mysql))
 
2717
    {
 
2718
      mysql->server_status=uint2korr(pos); pos+=2;
 
2719
      mysql->warning_count=uint2korr(pos); pos+=2;
 
2720
    }
 
2721
    else if (mysql->server_capabilities & CLIENT_TRANSACTIONS)
 
2722
    {
 
2723
      /* MySQL 4.0 protocol */
 
2724
      mysql->server_status=uint2korr(pos); pos+=2;
 
2725
      mysql->warning_count= 0;
 
2726
    }
 
2727
    DBUG_PRINT("info",("status: %u  warning_count: %u",
 
2728
                       mysql->server_status, mysql->warning_count));
 
2729
    if (pos < mysql->net.read_pos+length && net_field_length(&pos))
 
2730
      mysql->info=(char*) pos;
 
2731
    DBUG_RETURN(0);
 
2732
  }
 
2733
#ifdef MYSQL_CLIENT
 
2734
  if (field_count == NULL_LENGTH)               /* LOAD DATA LOCAL INFILE */
 
2735
  {
 
2736
    int error;
 
2737
 
 
2738
    if (!(mysql->options.client_flag & CLIENT_LOCAL_FILES))
 
2739
    {
 
2740
      set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
 
2741
      DBUG_RETURN(1);
 
2742
    }   
 
2743
 
 
2744
    error= handle_local_infile(mysql,(char*) pos);
 
2745
    if ((length= cli_safe_read(mysql)) == packet_error || error)
 
2746
      DBUG_RETURN(1);
 
2747
    goto get_info;                              /* Get info packet */
 
2748
  }
 
2749
#endif
 
2750
  if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
 
2751
    mysql->server_status|= SERVER_STATUS_IN_TRANS;
 
2752
 
 
2753
  if (!(fields=cli_read_rows(mysql,(MYSQL_FIELD*)0, protocol_41(mysql) ? 7:5)))
 
2754
    DBUG_RETURN(1);
 
2755
  if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,
 
2756
                                    (uint) field_count,0,
 
2757
                                    mysql->server_capabilities)))
 
2758
    DBUG_RETURN(1);
 
2759
  mysql->status= MYSQL_STATUS_GET_RESULT;
 
2760
  mysql->field_count= (uint) field_count;
 
2761
  DBUG_PRINT("exit",("ok"));
 
2762
  DBUG_RETURN(0);
 
2763
}
 
2764
 
 
2765
 
 
2766
/*
 
2767
  Send the query and return so we can do something else.
 
2768
  Needs to be followed by mysql_read_query_result() when we want to
 
2769
  finish processing it.
 
2770
*/
 
2771
 
 
2772
int STDCALL
 
2773
mysql_send_query(MYSQL* mysql, const char* query, ulong length)
 
2774
{
 
2775
  DBUG_ENTER("mysql_send_query");
 
2776
  DBUG_RETURN(simple_command(mysql, COM_QUERY, (uchar*) query, length, 1));
 
2777
}
 
2778
 
 
2779
 
 
2780
int STDCALL
 
2781
mysql_real_query(MYSQL *mysql, const char *query, ulong length)
 
2782
{
 
2783
  DBUG_ENTER("mysql_real_query");
 
2784
  DBUG_PRINT("enter",("handle: 0x%lx", (long) mysql));
 
2785
  DBUG_PRINT("query",("Query = '%-.4096s'",query));
 
2786
 
 
2787
  if (mysql_send_query(mysql,query,length))
 
2788
    DBUG_RETURN(1);
 
2789
  DBUG_RETURN((int) (*mysql->methods->read_query_result)(mysql));
 
2790
}
 
2791
 
 
2792
 
 
2793
/**************************************************************************
 
2794
  Alloc result struct for buffered results. All rows are read to buffer.
 
2795
  mysql_data_seek may be used.
 
2796
**************************************************************************/
 
2797
 
 
2798
MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql)
 
2799
{
 
2800
  MYSQL_RES *result;
 
2801
  DBUG_ENTER("mysql_store_result");
 
2802
 
 
2803
  if (!mysql->fields)
 
2804
    DBUG_RETURN(0);
 
2805
  if (mysql->status != MYSQL_STATUS_GET_RESULT)
 
2806
  {
 
2807
    set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
 
2808
    DBUG_RETURN(0);
 
2809
  }
 
2810
  mysql->status=MYSQL_STATUS_READY;             /* server is ready */
 
2811
  if (!(result=(MYSQL_RES*) my_malloc((uint) (sizeof(MYSQL_RES)+
 
2812
                                              sizeof(ulong) *
 
2813
                                              mysql->field_count),
 
2814
                                      MYF(MY_WME | MY_ZEROFILL))))
 
2815
  {
 
2816
    set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
2817
    DBUG_RETURN(0);
 
2818
  }
 
2819
  result->methods= mysql->methods;
 
2820
  result->eof=1;                                /* Marker for buffered */
 
2821
  result->lengths=(ulong*) (result+1);
 
2822
  if (!(result->data=
 
2823
        (*mysql->methods->read_rows)(mysql,mysql->fields,mysql->field_count)))
 
2824
  {
 
2825
    my_free((uchar*) result,MYF(0));
 
2826
    DBUG_RETURN(0);
 
2827
  }
 
2828
  mysql->affected_rows= result->row_count= result->data->rows;
 
2829
  result->data_cursor=  result->data->data;
 
2830
  result->fields=       mysql->fields;
 
2831
  result->field_alloc=  mysql->field_alloc;
 
2832
  result->field_count=  mysql->field_count;
 
2833
  /* The rest of result members is bzeroed in malloc */
 
2834
  mysql->fields=0;                              /* fields is now in result */
 
2835
  clear_alloc_root(&mysql->field_alloc);
 
2836
  /* just in case this was mistakenly called after mysql_stmt_execute() */
 
2837
  mysql->unbuffered_fetch_owner= 0;
 
2838
  DBUG_RETURN(result);                          /* Data fetched */
 
2839
}
 
2840
 
 
2841
 
 
2842
/**************************************************************************
 
2843
  Alloc struct for use with unbuffered reads. Data is fetched by domand
 
2844
  when calling to mysql_fetch_row.
 
2845
  mysql_data_seek is a noop.
 
2846
 
 
2847
  No other queries may be specified with the same MYSQL handle.
 
2848
  There shouldn't be much processing per row because mysql server shouldn't
 
2849
  have to wait for the client (and will not wait more than 30 sec/packet).
 
2850
**************************************************************************/
 
2851
 
 
2852
static MYSQL_RES * cli_use_result(MYSQL *mysql)
 
2853
{
 
2854
  MYSQL_RES *result;
 
2855
  DBUG_ENTER("cli_use_result");
 
2856
 
 
2857
  if (!mysql->fields)
 
2858
    DBUG_RETURN(0);
 
2859
  if (mysql->status != MYSQL_STATUS_GET_RESULT)
 
2860
  {
 
2861
    set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
 
2862
    DBUG_RETURN(0);
 
2863
  }
 
2864
  if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+
 
2865
                                      sizeof(ulong)*mysql->field_count,
 
2866
                                      MYF(MY_WME | MY_ZEROFILL))))
 
2867
    DBUG_RETURN(0);
 
2868
  result->lengths=(ulong*) (result+1);
 
2869
  result->methods= mysql->methods;
 
2870
  if (!(result->row=(MYSQL_ROW)
 
2871
        my_malloc(sizeof(result->row[0])*(mysql->field_count+1), MYF(MY_WME))))
 
2872
  {                                     /* Ptrs: to one row */
 
2873
    my_free((uchar*) result,MYF(0));
 
2874
    DBUG_RETURN(0);
 
2875
  }
 
2876
  result->fields=       mysql->fields;
 
2877
  result->field_alloc=  mysql->field_alloc;
 
2878
  result->field_count=  mysql->field_count;
 
2879
  result->current_field=0;
 
2880
  result->handle=       mysql;
 
2881
  result->current_row=  0;
 
2882
  mysql->fields=0;                      /* fields is now in result */
 
2883
  clear_alloc_root(&mysql->field_alloc);
 
2884
  mysql->status=MYSQL_STATUS_USE_RESULT;
 
2885
  mysql->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled;
 
2886
  DBUG_RETURN(result);                  /* Data is read to be fetched */
 
2887
}
 
2888
 
 
2889
 
 
2890
/**************************************************************************
 
2891
  Return next row of the query results
 
2892
**************************************************************************/
 
2893
 
 
2894
MYSQL_ROW STDCALL
 
2895
mysql_fetch_row(MYSQL_RES *res)
 
2896
{
 
2897
  DBUG_ENTER("mysql_fetch_row");
 
2898
  if (!res->data)
 
2899
  {                                             /* Unbufferred fetch */
 
2900
    if (!res->eof)
 
2901
    {
 
2902
      MYSQL *mysql= res->handle;
 
2903
      if (mysql->status != MYSQL_STATUS_USE_RESULT)
 
2904
      {
 
2905
        set_mysql_error(mysql,
 
2906
                        res->unbuffered_fetch_cancelled ? 
 
2907
                        CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
 
2908
                        unknown_sqlstate);
 
2909
      }
 
2910
      else if (!(read_one_row(mysql, res->field_count, res->row, res->lengths)))
 
2911
      {
 
2912
        res->row_count++;
 
2913
        DBUG_RETURN(res->current_row=res->row);
 
2914
      }
 
2915
      DBUG_PRINT("info",("end of data"));
 
2916
      res->eof=1;
 
2917
      mysql->status=MYSQL_STATUS_READY;
 
2918
      /*
 
2919
        Reset only if owner points to us: there is a chance that somebody
 
2920
        started new query after mysql_stmt_close():
 
2921
      */
 
2922
      if (mysql->unbuffered_fetch_owner == &res->unbuffered_fetch_cancelled)
 
2923
        mysql->unbuffered_fetch_owner= 0;
 
2924
      /* Don't clear handle in mysql_free_result */
 
2925
      res->handle=0;
 
2926
    }
 
2927
    DBUG_RETURN((MYSQL_ROW) NULL);
 
2928
  }
 
2929
  {
 
2930
    MYSQL_ROW tmp;
 
2931
    if (!res->data_cursor)
 
2932
    {
 
2933
      DBUG_PRINT("info",("end of data"));
 
2934
      DBUG_RETURN(res->current_row=(MYSQL_ROW) NULL);
 
2935
    }
 
2936
    tmp = res->data_cursor->data;
 
2937
    res->data_cursor = res->data_cursor->next;
 
2938
    DBUG_RETURN(res->current_row=tmp);
 
2939
  }
 
2940
}
 
2941
 
 
2942
 
 
2943
/**************************************************************************
 
2944
  Get column lengths of the current row
 
2945
  If one uses mysql_use_result, res->lengths contains the length information,
 
2946
  else the lengths are calculated from the offset between pointers.
 
2947
**************************************************************************/
 
2948
 
 
2949
ulong * STDCALL
 
2950
mysql_fetch_lengths(MYSQL_RES *res)
 
2951
{
 
2952
  MYSQL_ROW column;
 
2953
 
 
2954
  if (!(column=res->current_row))
 
2955
    return 0;                                   /* Something is wrong */
 
2956
  if (res->data)
 
2957
    (*res->methods->fetch_lengths)(res->lengths, column, res->field_count);
 
2958
  return res->lengths;
 
2959
}
 
2960
 
 
2961
 
 
2962
int STDCALL
 
2963
mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
 
2964
{
 
2965
  DBUG_ENTER("mysql_option");
 
2966
  DBUG_PRINT("enter",("option: %d",(int) option));
 
2967
  switch (option) {
 
2968
  case MYSQL_OPT_CONNECT_TIMEOUT:
 
2969
    mysql->options.connect_timeout= *(uint*) arg;
 
2970
    break;
 
2971
  case MYSQL_OPT_READ_TIMEOUT:
 
2972
    mysql->options.read_timeout= *(uint*) arg;
 
2973
    break;
 
2974
  case MYSQL_OPT_WRITE_TIMEOUT:
 
2975
    mysql->options.write_timeout= *(uint*) arg;
 
2976
    break;
 
2977
  case MYSQL_OPT_COMPRESS:
 
2978
    mysql->options.compress= 1;                 /* Remember for connect */
 
2979
    mysql->options.client_flag|= CLIENT_COMPRESS;
 
2980
    break;
 
2981
  case MYSQL_OPT_NAMED_PIPE:                    /* This option is depricated */
 
2982
    mysql->options.protocol=MYSQL_PROTOCOL_PIPE; /* Force named pipe */
 
2983
    break;
 
2984
  case MYSQL_OPT_LOCAL_INFILE:                  /* Allow LOAD DATA LOCAL ?*/
 
2985
    if (!arg || test(*(uint*) arg))
 
2986
      mysql->options.client_flag|= CLIENT_LOCAL_FILES;
 
2987
    else
 
2988
      mysql->options.client_flag&= ~CLIENT_LOCAL_FILES;
 
2989
    break;
 
2990
  case MYSQL_INIT_COMMAND:
 
2991
    add_init_command(&mysql->options,arg);
 
2992
    break;
 
2993
  case MYSQL_READ_DEFAULT_FILE:
 
2994
    my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
 
2995
    mysql->options.my_cnf_file=my_strdup(arg,MYF(MY_WME));
 
2996
    break;
 
2997
  case MYSQL_READ_DEFAULT_GROUP:
 
2998
    my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
 
2999
    mysql->options.my_cnf_group=my_strdup(arg,MYF(MY_WME));
 
3000
    break;
 
3001
  case MYSQL_SET_CHARSET_DIR:
 
3002
    my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
 
3003
    mysql->options.charset_dir=my_strdup(arg,MYF(MY_WME));
 
3004
    break;
 
3005
  case MYSQL_SET_CHARSET_NAME:
 
3006
    my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
 
3007
    mysql->options.charset_name=my_strdup(arg,MYF(MY_WME));
 
3008
    break;
 
3009
  case MYSQL_OPT_PROTOCOL:
 
3010
    mysql->options.protocol= *(uint*) arg;
 
3011
    break;
 
3012
  case MYSQL_SHARED_MEMORY_BASE_NAME:
 
3013
#ifdef HAVE_SMEM
 
3014
    if (mysql->options.shared_memory_base_name != def_shared_memory_base_name)
 
3015
      my_free(mysql->options.shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
 
3016
    mysql->options.shared_memory_base_name=my_strdup(arg,MYF(MY_WME));
 
3017
#endif
 
3018
    break;
 
3019
  case MYSQL_OPT_USE_REMOTE_CONNECTION:
 
3020
  case MYSQL_OPT_USE_EMBEDDED_CONNECTION:
 
3021
  case MYSQL_OPT_GUESS_CONNECTION:
 
3022
    mysql->options.methods_to_use= option;
 
3023
    break;
 
3024
  case MYSQL_SET_CLIENT_IP:
 
3025
    mysql->options.client_ip= my_strdup(arg, MYF(MY_WME));
 
3026
    break;
 
3027
  case MYSQL_SECURE_AUTH:
 
3028
    mysql->options.secure_auth= *(my_bool *) arg;
 
3029
    break;
 
3030
  case MYSQL_REPORT_DATA_TRUNCATION:
 
3031
    mysql->options.report_data_truncation= test(*(my_bool *) arg);
 
3032
    break;
 
3033
  case MYSQL_OPT_RECONNECT:
 
3034
    mysql->reconnect= *(my_bool *) arg;
 
3035
    break;
 
3036
  case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
 
3037
    if (*(my_bool*) arg)
 
3038
      mysql->options.client_flag|= CLIENT_SSL_VERIFY_SERVER_CERT;
 
3039
    else
 
3040
      mysql->options.client_flag&= ~CLIENT_SSL_VERIFY_SERVER_CERT;
 
3041
    break;
 
3042
  default:
 
3043
    DBUG_RETURN(1);
 
3044
  }
 
3045
  DBUG_RETURN(0);
 
3046
}
 
3047
 
 
3048
 
 
3049
/****************************************************************************
 
3050
  Functions to get information from the MySQL structure
 
3051
  These are functions to make shared libraries more usable.
 
3052
****************************************************************************/
 
3053
 
 
3054
/* MYSQL_RES */
 
3055
my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res)
 
3056
{
 
3057
  return res->row_count;
 
3058
}
 
3059
 
 
3060
unsigned int STDCALL mysql_num_fields(MYSQL_RES *res)
 
3061
{
 
3062
  return res->field_count;
 
3063
}
 
3064
 
 
3065
uint STDCALL mysql_errno(MYSQL *mysql)
 
3066
{
 
3067
  return mysql ? mysql->net.last_errno : mysql_server_last_errno;
 
3068
}
 
3069
 
 
3070
 
 
3071
const char * STDCALL mysql_error(MYSQL *mysql)
 
3072
{
 
3073
  return mysql ? mysql->net.last_error : mysql_server_last_error;
 
3074
}
 
3075
 
 
3076
 
 
3077
/*
 
3078
  Get version number for server in a form easy to test on
 
3079
 
 
3080
  SYNOPSIS
 
3081
    mysql_get_server_version()
 
3082
    mysql               Connection
 
3083
 
 
3084
  EXAMPLE
 
3085
    4.1.0-alfa ->  40100
 
3086
  
 
3087
  NOTES
 
3088
    We will ensure that a newer server always has a bigger number.
 
3089
 
 
3090
  RETURN
 
3091
   Signed number > 323000
 
3092
*/
 
3093
 
 
3094
ulong STDCALL
 
3095
mysql_get_server_version(MYSQL *mysql)
 
3096
{
 
3097
  uint major, minor, version;
 
3098
  char *pos= mysql->server_version, *end_pos;
 
3099
  major=   (uint) strtoul(pos, &end_pos, 10);   pos=end_pos+1;
 
3100
  minor=   (uint) strtoul(pos, &end_pos, 10);   pos=end_pos+1;
 
3101
  version= (uint) strtoul(pos, &end_pos, 10);
 
3102
  return (ulong) major*10000L+(ulong) (minor*100+version);
 
3103
}
 
3104
 
 
3105
 
 
3106
/* 
 
3107
   mysql_set_character_set function sends SET NAMES cs_name to
 
3108
   the server (which changes character_set_client, character_set_result
 
3109
   and character_set_connection) and updates mysql->charset so other
 
3110
   functions like mysql_real_escape will work correctly.
 
3111
*/
 
3112
int STDCALL mysql_set_character_set(MYSQL *mysql, const char *cs_name)
 
3113
{
 
3114
  struct charset_info_st *cs;
 
3115
  const char *save_csdir= charsets_dir;
 
3116
 
 
3117
  if (mysql->options.charset_dir)
 
3118
    charsets_dir= mysql->options.charset_dir;
 
3119
 
 
3120
  if (strlen(cs_name) < MY_CS_NAME_SIZE &&
 
3121
     (cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0))))
 
3122
  {
 
3123
    char buff[MY_CS_NAME_SIZE + 10];
 
3124
    charsets_dir= save_csdir;
 
3125
    /* Skip execution of "SET NAMES" for pre-4.1 servers */
 
3126
    if (mysql_get_server_version(mysql) < 40100)
 
3127
      return 0;
 
3128
    sprintf(buff, "SET NAMES %s", cs_name);
 
3129
    if (!mysql_real_query(mysql, buff, strlen(buff)))
 
3130
    {
 
3131
      mysql->charset= cs;
 
3132
    }
 
3133
  }
 
3134
  else
 
3135
  {
 
3136
    char cs_dir_name[FN_REFLEN];
 
3137
    get_charsets_dir(cs_dir_name);
 
3138
    set_mysql_extended_error(mysql, CR_CANT_READ_CHARSET, unknown_sqlstate,
 
3139
                             ER(CR_CANT_READ_CHARSET), cs_name, cs_dir_name);
 
3140
  }
 
3141
  charsets_dir= save_csdir;
 
3142
  return mysql->net.last_errno;
 
3143
}
 
3144
 
 
3145