~drizzle-trunk/drizzle/development

1 by brian
clean slate
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