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