libmysql.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:69k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This library is free software; you can redistribute it and/or
  4.    modify it under the terms of the GNU Library General Public
  5.    License as published by the Free Software Foundation; either
  6.    version 2 of the License, or (at your option) any later version.
  7.    
  8.    This library is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.    Library General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU Library General Public
  14.    License along with this library; if not, write to the Free
  15.    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  16.    MA 02111-1307, USA */
  17. #define DONT_USE_RAID
  18. #if defined(__WIN__) || defined(_WIN32) || defined(_WIN64)
  19. #include <winsock.h>
  20. #include <odbcinst.h>
  21. #endif
  22. #include <global.h>
  23. #include <my_sys.h>
  24. #include <mysys_err.h>
  25. #include <m_string.h>
  26. #include <m_ctype.h>
  27. #include "mysql.h"
  28. #include "mysql_version.h"
  29. #include "mysqld_error.h"
  30. #include "errmsg.h"
  31. #include <violite.h>
  32. #include <sys/stat.h>
  33. #include <signal.h>
  34. #include <time.h>
  35. #ifdef  HAVE_PWD_H
  36. #include <pwd.h>
  37. #endif
  38. #if !defined(MSDOS) && !defined(__WIN__)
  39. #include <sys/socket.h>
  40. #include <netinet/in.h>
  41. #include <arpa/inet.h>
  42. #include <netdb.h>
  43. #ifdef HAVE_SELECT_H
  44. #  include <select.h>
  45. #endif
  46. #ifdef HAVE_SYS_SELECT_H
  47. #include <sys/select.h>
  48. #endif
  49. #endif
  50. #ifdef HAVE_SYS_UN_H
  51. #  include <sys/un.h>
  52. #endif
  53. #if defined(THREAD) && !defined(__WIN__)
  54. #include <my_pthread.h> /* because of signal() */
  55. #endif
  56. #ifndef INADDR_NONE
  57. #define INADDR_NONE -1
  58. #endif
  59. static my_bool mysql_client_init=0;
  60. uint mysql_port=0;
  61. my_string mysql_unix_port=0;
  62. #define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS)
  63. #ifdef __WIN__
  64. #define CONNECT_TIMEOUT 20
  65. #else
  66. #define CONNECT_TIMEOUT 0
  67. #endif
  68. #if defined(MSDOS) || defined(__WIN__)
  69. #define ERRNO WSAGetLastError()
  70. #define perror(A)
  71. #else
  72. #include <errno.h>
  73. #define ERRNO errno
  74. #define SOCKET_ERROR -1
  75. #define closesocket(A) close(A)
  76. #endif
  77. static void mysql_once_init(void);
  78. static MYSQL_DATA *read_rows (MYSQL *mysql,MYSQL_FIELD *fields,
  79.       uint field_count);
  80. static int read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row,
  81. ulong *lengths);
  82. static void end_server(MYSQL *mysql);
  83. static void read_user_name(char *name);
  84. static void append_wild(char *to,char *end,const char *wild);
  85. static my_bool mysql_reconnect(MYSQL *mysql);
  86. static int send_file_to_server(MYSQL *mysql,const char *filename);
  87. static sig_handler pipe_sig_handler(int sig);
  88. static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
  89.      const char *from, ulong length);
  90. /*
  91.   Let the user specify that we don't want SIGPIPE;  This doesn't however work
  92.   with threaded applications as we can have multiple read in progress.
  93. */
  94. #if !defined(__WIN__) && defined(SIGPIPE) && !defined(THREAD)
  95. #define init_sigpipe_variables  sig_return old_signal_handler=(sig_return) 0;
  96. #define set_sigpipe(mysql)     if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) old_signal_handler=signal(SIGPIPE,pipe_sig_handler)
  97. #define reset_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) signal(SIGPIPE,old_signal_handler);
  98. #else
  99. #define init_sigpipe_variables
  100. #define set_sigpipe(mysql)
  101. #define reset_sigpipe(mysql)
  102. #endif
  103. /****************************************************************************
  104. * A modified version of connect().  connect2() allows you to specify
  105. * a timeout value, in seconds, that we should wait until we
  106. * derermine we can't connect to a particular host.  If timeout is 0,
  107. * connect2() will behave exactly like connect().
  108. *
  109. * Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
  110. *****************************************************************************/
  111. static int connect2(my_socket s, const struct sockaddr *name, uint namelen,
  112.     uint timeout)
  113. {
  114. #if defined(__WIN__)
  115.   return connect(s, (struct sockaddr*) name, namelen);
  116. #else
  117.   int flags, res, s_err;
  118.   SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
  119.   fd_set sfds;
  120.   struct timeval tv;
  121.   time_t start_time, now_time;
  122.   /* If they passed us a timeout of zero, we should behave
  123.    * exactly like the normal connect() call does.
  124.    */
  125.   if (timeout == 0)
  126.     return connect(s, (struct sockaddr*) name, namelen);
  127.   flags = fcntl(s, F_GETFL, 0);   /* Set socket to not block */
  128. #ifdef O_NONBLOCK
  129.   fcntl(s, F_SETFL, flags | O_NONBLOCK);  /* and save the flags..  */
  130. #endif
  131.   res = connect(s, (struct sockaddr*) name, namelen);
  132.   s_err = errno; /* Save the error... */
  133.   fcntl(s, F_SETFL, flags);
  134.   if ((res != 0) && (s_err != EINPROGRESS))
  135.   {
  136.     errno = s_err; /* Restore it */
  137.     return(-1);
  138.   }
  139.   if (res == 0) /* Connected quickly! */
  140.     return(0);
  141.   /* Otherwise, our connection is "in progress."  We can use
  142.    * the select() call to wait up to a specified period of time
  143.    * for the connection to suceed.  If select() returns 0
  144.    * (after waiting howevermany seconds), our socket never became
  145.    * writable (host is probably unreachable.)  Otherwise, if
  146.    * select() returns 1, then one of two conditions exist:
  147.    *
  148.    * 1. An error occured.  We use getsockopt() to check for this.
  149.    * 2. The connection was set up sucessfully: getsockopt() will
  150.    * return 0 as an error.
  151.    *
  152.    * Thanks goes to Andrew Gierth <andrew@erlenstar.demon.co.uk>
  153.    * who posted this method of timing out a connect() in
  154.    * comp.unix.programmer on August 15th, 1997.
  155.    */
  156.   FD_ZERO(&sfds);
  157.   FD_SET(s, &sfds);
  158.   /*
  159.    * select could be interrupted by a signal, and if it is, 
  160.    * the timeout should be adjusted and the select restarted
  161.    * to work around OSes that don't restart select and 
  162.    * implementations of select that don't adjust tv upon
  163.    * failure to reflect the time remaining
  164.    */
  165.   start_time = time(NULL);
  166.   for (;;)
  167.   {
  168.     tv.tv_sec = (long) timeout;
  169.     tv.tv_usec = 0;
  170.     if ((res = select(s+1, NULL, &sfds, NULL, &tv)) >= 0)
  171.       break;
  172.     now_time=time(NULL);
  173.     timeout-= (uint) (now_time - start_time);
  174.     if (errno != EINTR || (int) timeout <= 0)
  175.       return -1;
  176.   }
  177.   /* select() returned something more interesting than zero, let's
  178.    * see if we have any errors.  If the next two statements pass,
  179.    * we've got an open socket!
  180.    */
  181.   s_err=0;
  182.   if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
  183.     return(-1);
  184.   if (s_err)
  185.   { /* getsockopt could succeed */
  186.     errno = s_err;
  187.     return(-1); /* but return an error... */
  188.   }
  189.   return(0); /* It's all good! */
  190. #endif
  191. }
  192. /*
  193. ** Create a named pipe connection
  194. */
  195. #ifdef __WIN__
  196. HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host,
  197.  char **arg_unix_socket)
  198. {
  199.   HANDLE hPipe=INVALID_HANDLE_VALUE;
  200.   char szPipeName [ 257 ];
  201.   DWORD dwMode;
  202.   int i;
  203.   my_bool testing_named_pipes=0;
  204.   char *host= *arg_host, *unix_socket= *arg_unix_socket;
  205.   if ( ! unix_socket || (unix_socket)[0] == 0x00)
  206.     unix_socket = mysql_unix_port;
  207.   if (!host || !strcmp(host,LOCAL_HOST))
  208.     host=LOCAL_HOST_NAMEDPIPE;
  209.   sprintf( szPipeName, "\\%s\pipe\%s", host, unix_socket);
  210.   DBUG_PRINT("info",("Server name: '%s'.  Named Pipe: %s",
  211.      host, unix_socket));
  212.   for (i=0 ; i < 100 ; i++) /* Don't retry forever */
  213.   {
  214.     if ((hPipe = CreateFile(szPipeName,
  215.     GENERIC_READ | GENERIC_WRITE,
  216.     0,
  217.     NULL,
  218.     OPEN_EXISTING,
  219.     0,
  220.     NULL )) != INVALID_HANDLE_VALUE)
  221.       break;
  222.     if (GetLastError() != ERROR_PIPE_BUSY)
  223.     {
  224.       net->last_errno=CR_NAMEDPIPEOPEN_ERROR;
  225.       sprintf(net->last_error,ER(net->last_errno),host, unix_socket,
  226.       (ulong) GetLastError());
  227.       return INVALID_HANDLE_VALUE;
  228.     }
  229.     /* wait for for an other instance */
  230.     if (! WaitNamedPipe(szPipeName, connect_timeout*1000) )
  231.     {
  232.       net->last_errno=CR_NAMEDPIPEWAIT_ERROR;
  233.       sprintf(net->last_error,ER(net->last_errno),host, unix_socket,
  234.       (ulong) GetLastError());
  235.       return INVALID_HANDLE_VALUE;
  236.     }
  237.   }
  238.   if (hPipe == INVALID_HANDLE_VALUE)
  239.   {
  240.     net->last_errno=CR_NAMEDPIPEOPEN_ERROR;
  241.     sprintf(net->last_error,ER(net->last_errno),host, unix_socket,
  242.     (ulong) GetLastError());
  243.     return INVALID_HANDLE_VALUE;
  244.   }
  245.   dwMode = PIPE_READMODE_BYTE | PIPE_WAIT;
  246.   if ( !SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL) )
  247.   {
  248.     CloseHandle( hPipe );
  249.     net->last_errno=CR_NAMEDPIPESETSTATE_ERROR;
  250.     sprintf(net->last_error,ER(net->last_errno),host, unix_socket,
  251.     (ulong) GetLastError());
  252.     return INVALID_HANDLE_VALUE;
  253.   }
  254.   *arg_host=host ; *arg_unix_socket=unix_socket; /* connect arg */
  255.   return (hPipe);
  256. }
  257. #endif
  258. /*****************************************************************************
  259. ** read a packet from server. Give error message if socket was down
  260. ** or packet is an error message
  261. *****************************************************************************/
  262. static uint
  263. net_safe_read(MYSQL *mysql)
  264. {
  265.   NET *net= &mysql->net;
  266.   uint len=0;
  267.   init_sigpipe_variables
  268.   /* Don't give sigpipe errors if the client doesn't want them */
  269.   set_sigpipe(mysql);
  270.   if (net->vio != 0)
  271.     len=my_net_read(net);
  272.   reset_sigpipe(mysql);
  273.   if (len == packet_error || len == 0)
  274.   {
  275.     DBUG_PRINT("error",("Wrong connection or packet. fd: %s  len: %d",
  276. vio_description(net->vio),len));
  277.     end_server(mysql);
  278.     net->last_errno=(net->last_errno == ER_NET_PACKET_TOO_LARGE ? 
  279.      CR_NET_PACKET_TOO_LARGE:
  280.      CR_SERVER_LOST);
  281.     strmov(net->last_error,ER(net->last_errno));
  282.     return(packet_error);
  283.   }
  284.   if (net->read_pos[0] == 255)
  285.   {
  286.     if (len > 3)
  287.     {
  288.       char *pos=(char*) net->read_pos+1;
  289.       if (mysql->protocol_version > 9)
  290.       { /* New client protocol */
  291. net->last_errno=uint2korr(pos);
  292. pos+=2;
  293. len-=2;
  294.       }
  295.       else
  296.       {
  297. net->last_errno=CR_UNKNOWN_ERROR;
  298. len--;
  299.       }
  300.       (void) strmake(net->last_error,(char*) pos,
  301.      min(len,sizeof(net->last_error)-1));
  302.     }
  303.     else
  304.     {
  305.       net->last_errno=CR_UNKNOWN_ERROR;
  306.       (void) strmov(net->last_error,ER(net->last_errno));
  307.     }
  308.     DBUG_PRINT("error",("Got error: %d (%s)", net->last_errno,
  309. net->last_error));
  310.     return(packet_error);
  311.   }
  312.   return len;
  313. }
  314. /* Get the length of next field. Change parameter to point at fieldstart */
  315. static ulong
  316. net_field_length(uchar **packet)
  317. {
  318.   reg1 uchar *pos= *packet;
  319.   if (*pos < 251)
  320.   {
  321.     (*packet)++;
  322.     return (ulong) *pos;
  323.   }
  324.   if (*pos == 251)
  325.   {
  326.     (*packet)++;
  327.     return NULL_LENGTH;
  328.   }
  329.   if (*pos == 252)
  330.   {
  331.     (*packet)+=3;
  332.     return (ulong) uint2korr(pos+1);
  333.   }
  334.   if (*pos == 253)
  335.   {
  336.     (*packet)+=4;
  337.     return (ulong) uint3korr(pos+1);
  338.   }
  339.   (*packet)+=9; /* Must be 254 when here */
  340.   return (ulong) uint4korr(pos+1);
  341. }
  342. /* Same as above, but returns ulonglong values */
  343. static my_ulonglong
  344. net_field_length_ll(uchar **packet)
  345. {
  346.   reg1 uchar *pos= *packet;
  347.   if (*pos < 251)
  348.   {
  349.     (*packet)++;
  350.     return (my_ulonglong) *pos;
  351.   }
  352.   if (*pos == 251)
  353.   {
  354.     (*packet)++;
  355.     return (my_ulonglong) NULL_LENGTH;
  356.   }
  357.   if (*pos == 252)
  358.   {
  359.     (*packet)+=3;
  360.     return (my_ulonglong) uint2korr(pos+1);
  361.   }
  362.   if (*pos == 253)
  363.   {
  364.     (*packet)+=4;
  365.     return (my_ulonglong) uint3korr(pos+1);
  366.   }
  367.   (*packet)+=9; /* Must be 254 when here */
  368. #ifdef NO_CLIENT_LONGLONG
  369.   return (my_ulonglong) uint4korr(pos+1);
  370. #else
  371.   return (my_ulonglong) uint8korr(pos+1);
  372. #endif
  373. }
  374. static void free_rows(MYSQL_DATA *cur)
  375. {
  376.   if (cur)
  377.   {
  378.     free_root(&cur->alloc,MYF(0));
  379.     my_free((gptr) cur,MYF(0));
  380.   }
  381. }
  382. static int
  383. simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
  384.        uint length, my_bool skipp_check)
  385. {
  386.   NET *net= &mysql->net;
  387.   int result= -1;
  388.   init_sigpipe_variables
  389.   /* Don't give sigpipe errors if the client doesn't want them */
  390.   set_sigpipe(mysql);
  391.   if (mysql->net.vio == 0)
  392.   { /* Do reconnect if possible */
  393.     if (mysql_reconnect(mysql))
  394.     {
  395.       net->last_errno=CR_SERVER_GONE_ERROR;
  396.       strmov(net->last_error,ER(net->last_errno));
  397.       goto end;
  398.     }
  399.   }
  400.   if (mysql->status != MYSQL_STATUS_READY)
  401.   {
  402.     strmov(net->last_error,ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC));
  403.     goto end;
  404.   }
  405.   mysql->net.last_error[0]=0;
  406.   mysql->net.last_errno=0;
  407.   mysql->info=0;
  408.   mysql->affected_rows= ~(my_ulonglong) 0;
  409.   net_clear(net); /* Clear receive buffer */
  410.   if (!arg)
  411.     arg="";
  412.   if (net_write_command(net,(uchar) command,arg,
  413. length ? length : (ulong) strlen(arg)))
  414.   {
  415.     DBUG_PRINT("error",("Can't send command to server. Error: %d",errno));
  416.     end_server(mysql);
  417.     if (mysql_reconnect(mysql) ||
  418. net_write_command(net,(uchar) command,arg,
  419.   length ? length : (ulong) strlen(arg)))
  420.     {
  421.       net->last_errno=CR_SERVER_GONE_ERROR;
  422.       strmov(net->last_error,ER(net->last_errno));
  423.       goto end;
  424.     }
  425.   }
  426.   result=0;
  427.   if (!skipp_check)
  428.     result= ((mysql->packet_length=net_safe_read(mysql)) == packet_error ?
  429.      -1 : 0);
  430.  end:
  431.   reset_sigpipe(mysql);
  432.   return result;
  433. }
  434. static void free_old_query(MYSQL *mysql)
  435. {
  436.   DBUG_ENTER("free_old_query");
  437.   if (mysql->fields)
  438.     free_root(&mysql->field_alloc,MYF(0));
  439.   init_alloc_root(&mysql->field_alloc,8192,0); /* Assume rowlength < 8192 */
  440.   mysql->fields=0;
  441.   mysql->field_count=0; /* For API */
  442.   DBUG_VOID_RETURN;
  443. }
  444. #if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
  445. struct passwd *getpwuid(uid_t);
  446. char* getlogin(void);
  447. #endif
  448. #if !defined(MSDOS) && ! defined(VMS) && !defined(__WIN__)
  449. static void read_user_name(char *name)
  450. {
  451.   DBUG_ENTER("read_user_name");
  452.   if (geteuid() == 0)
  453.     (void) strmov(name,"root"); /* allow use of surun */
  454.   else
  455.   {
  456. #ifdef HAVE_GETPWUID
  457.     struct passwd *skr;
  458.     const char *str;
  459.     if ((str=getlogin()) == NULL)
  460.     {
  461.       if ((skr=getpwuid(geteuid())) != NULL)
  462. str=skr->pw_name;
  463.       else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) &&
  464.        !(str=getenv("LOGIN")))
  465. str="UNKNOWN_USER";
  466.     }
  467.     (void) strmake(name,str,USERNAME_LENGTH);
  468. #elif HAVE_CUSERID
  469.     (void) cuserid(name);
  470. #else
  471.     strmov(name,"UNKNOWN_USER");
  472. #endif
  473.   }
  474.   DBUG_VOID_RETURN;
  475. }
  476. #else /* If MSDOS || VMS */
  477. static void read_user_name(char *name)
  478. {
  479.   char *str=getenv("USER"); /* ODBC will send user variable */
  480.   strmake(name,str ? str : "ODBC", USERNAME_LENGTH);
  481. }
  482. #endif
  483. #ifdef __WIN__
  484. static my_bool is_NT(void)
  485. {
  486.   char *os=getenv("OS");
  487.   return (os && !strcmp(os, "Windows_NT")) ? 1 : 0;
  488. }
  489. #endif
  490. /*
  491. ** Expand wildcard to a sql string
  492. */
  493. static void
  494. append_wild(char *to, char *end, const char *wild)
  495. {
  496.   end-=5; /* Some extra */
  497.   if (wild && wild[0])
  498.   {
  499.     to=strmov(to," like '");
  500.     while (*wild && to < end)
  501.     {
  502.       if (*wild == '\' || *wild == ''')
  503. *to++='\';
  504.       *to++= *wild++;
  505.     }
  506.     if (*wild) /* Too small buffer */
  507.       *to++='%'; /* Nicer this way */
  508.     to[0]=''';
  509.     to[1]=0;
  510.   }
  511. }
  512. /**************************************************************************
  513. ** Init debugging if MYSQL_DEBUG environment variable is found
  514. **************************************************************************/
  515. void STDCALL
  516. mysql_debug(const char *debug __attribute__((unused)))
  517. {
  518. #ifndef DBUG_OFF
  519.   char *env;
  520.   if (_db_on_)
  521.     return; /* Already using debugging */
  522.   if (debug)
  523.   {
  524.     DEBUGGER_ON;
  525.     DBUG_PUSH(debug);
  526.   }
  527.   else if ((env = getenv("MYSQL_DEBUG")))
  528.   {
  529.     DEBUGGER_ON;
  530.     DBUG_PUSH(env);
  531. #if !defined(_WINVER) && !defined(WINVER)
  532.     puts("n-------------------------------------------------------");
  533.     puts("MYSQL_DEBUG found. libmysql started with the following:");
  534.     puts(env);
  535.     puts("-------------------------------------------------------n");
  536. #else
  537.     {
  538.       char buff[80];
  539.       strmov(strmov(buff,"libmysql: "),env);
  540.       MessageBox((HWND) 0,"Debugging variable MYSQL_DEBUG used",buff,MB_OK);
  541.     }
  542. #endif
  543.   }
  544. #endif
  545. }
  546. /**************************************************************************
  547. ** Close the server connection if we get a SIGPIPE
  548.    ARGSUSED
  549. **************************************************************************/
  550. static sig_handler
  551. pipe_sig_handler(int sig __attribute__((unused)))
  552. {
  553.   DBUG_PRINT("info",("Hit by signal %d",sig));
  554. #ifdef DONT_REMEMBER_SIGNAL
  555.   (void) signal(SIGPIPE,pipe_sig_handler);
  556. #endif
  557. }
  558. /**************************************************************************
  559. ** Shut down connection
  560. **************************************************************************/
  561. static void
  562. end_server(MYSQL *mysql)
  563. {
  564.   DBUG_ENTER("end_server");
  565.   if (mysql->net.vio != 0)
  566.   {
  567.     init_sigpipe_variables
  568.     DBUG_PRINT("info",("Net: %s", vio_description(mysql->net.vio)));
  569.     set_sigpipe(mysql);
  570.     vio_delete(mysql->net.vio);
  571.     reset_sigpipe(mysql);
  572.     mysql->net.vio= 0;          /* Marker */
  573.   }
  574.   net_end(&mysql->net);
  575.   free_old_query(mysql);
  576.   DBUG_VOID_RETURN;
  577. }
  578. void STDCALL
  579. mysql_free_result(MYSQL_RES *result)
  580. {
  581.   DBUG_ENTER("mysql_free_result");
  582.   DBUG_PRINT("enter",("mysql_res: %lx",result));
  583.   if (result)
  584.   {
  585.     if (result->handle && result->handle->status == MYSQL_STATUS_USE_RESULT)
  586.     {
  587.       DBUG_PRINT("warning",("Not all rows in set were read; Ignoring rows"));
  588.       for (;;)
  589.       {
  590. uint pkt_len;
  591. if ((pkt_len=(uint) net_safe_read(result->handle)) == packet_error)
  592.   break;
  593. if (pkt_len == 1 && result->handle->net.read_pos[0] == 254)
  594.   break; /* End of data */
  595.       }
  596.       result->handle->status=MYSQL_STATUS_READY;
  597.     }
  598.     free_rows(result->data);
  599.     if (result->fields)
  600.       free_root(&result->field_alloc,MYF(0));
  601.     if (result->row)
  602.       my_free((gptr) result->row,MYF(0));
  603.     my_free((gptr) result,MYF(0));
  604.   }
  605.   DBUG_VOID_RETURN;
  606. }
  607. /****************************************************************************
  608. ** Get options from my.cnf
  609. ****************************************************************************/
  610. static const char *default_options[]=
  611. {"port","socket","compress","password","pipe", "timeout", "user",
  612.  "init-command", "host", "database", "debug", "return-found-rows",
  613.  "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath",
  614.  "character-set-dir", "default-character-set", "interactive-timeout",
  615.  "connect_timeout",
  616.  NullS
  617. };
  618. static TYPELIB option_types={array_elements(default_options)-1,
  619.      "options",default_options};
  620. static void mysql_read_default_options(struct st_mysql_options *options,
  621.        const char *filename,const char *group)
  622. {
  623.   int argc;
  624.   char *argv_buff[1],**argv;
  625.   const char *groups[3];
  626.   DBUG_ENTER("mysql_read_default_options");
  627.   DBUG_PRINT("enter",("file: %s  group: %s",filename,group ? group :"NULL"));
  628.   argc=1; argv=argv_buff; argv_buff[0]= (char*) "client";
  629.   groups[0]= (char*) "client"; groups[1]= (char*) group; groups[2]=0;
  630.   load_defaults(filename, groups, &argc, &argv);
  631.   if (argc != 1) /* If some default option */
  632.   {
  633.     char **option=argv;
  634.     while (*++option)
  635.     {
  636.       /* DBUG_PRINT("info",("option: %s",option[0])); */
  637.       if (option[0][0] == '-' && option[0][1] == '-')
  638.       {
  639. char *end=strcend(*option,'=');
  640. char *opt_arg=0;
  641. if (*end)
  642. {
  643.   opt_arg=end+1;
  644.   *end=0; /* Remove '=' */
  645. }
  646. switch (find_type(*option+2,&option_types,2)) {
  647. case 1: /* port */
  648.   if (opt_arg)
  649.     options->port=atoi(opt_arg);
  650.   break;
  651. case 2: /* socket */
  652.   if (opt_arg)
  653.   {
  654.     my_free(options->unix_socket,MYF(MY_ALLOW_ZERO_PTR));
  655.     options->unix_socket=my_strdup(opt_arg,MYF(MY_WME));
  656.   }
  657.   break;
  658. case 3: /* compress */
  659.   options->compress=1;
  660.   break;
  661. case 4: /* password */
  662.   if (opt_arg)
  663.   {
  664.     my_free(options->password,MYF(MY_ALLOW_ZERO_PTR));
  665.     options->password=my_strdup(opt_arg,MYF(MY_WME));
  666.   }
  667.   break;
  668. case 5: /* pipe */
  669.   options->named_pipe=1; /* Force named pipe */
  670.   break;
  671. case 20: /* connect_timeout */
  672. case 6: /* timeout */
  673.   if (opt_arg)
  674.     options->connect_timeout=atoi(opt_arg);
  675.   break;
  676. case 7: /* user */
  677.   if (opt_arg)
  678.   {
  679.     my_free(options->user,MYF(MY_ALLOW_ZERO_PTR));
  680.     options->user=my_strdup(opt_arg,MYF(MY_WME));
  681.   }
  682.   break;
  683. case 8: /* init-command */
  684.   if (opt_arg)
  685.   {
  686.     my_free(options->init_command,MYF(MY_ALLOW_ZERO_PTR));
  687.     options->init_command=my_strdup(opt_arg,MYF(MY_WME));
  688.   }
  689.   break;
  690. case 9: /* host */
  691.   if (opt_arg)
  692.   {
  693.     my_free(options->host,MYF(MY_ALLOW_ZERO_PTR));
  694.     options->host=my_strdup(opt_arg,MYF(MY_WME));
  695.   }
  696.   break;
  697. case 10: /* database */
  698.   if (opt_arg)
  699.   {
  700.     my_free(options->db,MYF(MY_ALLOW_ZERO_PTR));
  701.     options->db=my_strdup(opt_arg,MYF(MY_WME));
  702.   }
  703.   break;
  704. case 11: /* debug */
  705.   mysql_debug(opt_arg ? opt_arg : "d:t:o,/tmp/client.trace");
  706.   break;
  707. case 12: /* return-found-rows */
  708.   options->client_flag|=CLIENT_FOUND_ROWS;
  709.   break;
  710. #ifdef HAVE_OPENSSL
  711. case 13: /* ssl_key */
  712.   my_free(options->ssl_key, MYF(MY_ALLOW_ZERO_PTR));
  713.           options->ssl_key = my_strdup(opt_arg, MYF(MY_WME));
  714.           break;
  715. case 14: /* ssl_cert */
  716.   my_free(options->ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
  717.           options->ssl_cert = my_strdup(opt_arg, MYF(MY_WME));
  718.           break;
  719. case 15: /* ssl_ca */
  720.   my_free(options->ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
  721.           options->ssl_ca = my_strdup(opt_arg, MYF(MY_WME));
  722.           break;
  723. case 16: /* ssl_capath */
  724.   my_free(options->ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
  725.           options->ssl_capath = my_strdup(opt_arg, MYF(MY_WME));
  726.           break;
  727. #else
  728. case 13: /* Ignore SSL options */
  729. case 14:
  730. case 15:
  731. case 16:
  732.   break;
  733. #endif /* HAVE_OPENSSL */
  734. case 17: /* charset-lib */
  735.   my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR));
  736.           options->charset_dir = my_strdup(opt_arg, MYF(MY_WME));
  737.   break;
  738. case 18:
  739.   my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR));
  740.           options->charset_name = my_strdup(opt_arg, MYF(MY_WME));
  741.   break;
  742. case 19: /* Interactive-timeout */
  743.   options->client_flag|=CLIENT_INTERACTIVE;
  744.   break;
  745. default:
  746.   DBUG_PRINT("warning",("unknown option: %s",option[0]));
  747. }
  748.       }
  749.     }
  750.   }
  751.   free_defaults(argv);
  752.   DBUG_VOID_RETURN;
  753. }
  754. /***************************************************************************
  755. ** Change field rows to field structs
  756. ***************************************************************************/
  757. static MYSQL_FIELD *
  758. unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
  759.       my_bool default_value, my_bool long_flag_protocol)
  760. {
  761.   MYSQL_ROWS *row;
  762.   MYSQL_FIELD *field,*result;
  763.   DBUG_ENTER("unpack_fields");
  764.   field=result=(MYSQL_FIELD*) alloc_root(alloc,sizeof(MYSQL_FIELD)*fields);
  765.   if (!result)
  766.     DBUG_RETURN(0);
  767.   for (row=data->data; row ; row = row->next,field++)
  768.   {
  769.     field->table=  strdup_root(alloc,(char*) row->data[0]);
  770.     field->name=   strdup_root(alloc,(char*) row->data[1]);
  771.     field->length= (uint) uint3korr(row->data[2]);
  772.     field->type=   (enum enum_field_types) (uchar) row->data[3][0];
  773.     if (long_flag_protocol)
  774.     {
  775.       field->flags=   uint2korr(row->data[4]);
  776.       field->decimals=(uint) (uchar) row->data[4][2];
  777.     }
  778.     else
  779.     {
  780.       field->flags=   (uint) (uchar) row->data[4][0];
  781.       field->decimals=(uint) (uchar) row->data[4][1];
  782.     }
  783.     if (INTERNAL_NUM_FIELD(field))
  784.       field->flags|= NUM_FLAG;
  785.     if (default_value && row->data[5])
  786.       field->def=strdup_root(alloc,(char*) row->data[5]);
  787.     else
  788.       field->def=0;
  789.     field->max_length= 0;
  790.   }
  791.   free_rows(data); /* Free old data */
  792.   DBUG_RETURN(result);
  793. }
  794. /* Read all rows (fields or data) from server */
  795. static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
  796.      uint fields)
  797. {
  798.   uint field,pkt_len;
  799.   ulong len;
  800.   uchar *cp;
  801.   char *to;
  802.   MYSQL_DATA *result;
  803.   MYSQL_ROWS **prev_ptr,*cur;
  804.   NET *net = &mysql->net;
  805.   DBUG_ENTER("read_rows");
  806.   if ((pkt_len=(uint) net_safe_read(mysql)) == packet_error)
  807.     DBUG_RETURN(0);
  808.   if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA),
  809.        MYF(MY_WME | MY_ZEROFILL))))
  810.   {
  811.     net->last_errno=CR_OUT_OF_MEMORY;
  812.     strmov(net->last_error,ER(net->last_errno));
  813.     DBUG_RETURN(0);
  814.   }
  815.   init_alloc_root(&result->alloc,8192,0); /* Assume rowlength < 8192 */
  816.   result->alloc.min_malloc=sizeof(MYSQL_ROWS);
  817.   prev_ptr= &result->data;
  818.   result->rows=0;
  819.   result->fields=fields;
  820.   while (*(cp=net->read_pos) != 254 || pkt_len != 1)
  821.   {
  822.     result->rows++;
  823.     if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,
  824.     sizeof(MYSQL_ROWS))) ||
  825. !(cur->data= ((MYSQL_ROW)
  826.       alloc_root(&result->alloc,
  827.      (fields+1)*sizeof(char *)+pkt_len))))
  828.     {
  829.       free_rows(result);
  830.       net->last_errno=CR_OUT_OF_MEMORY;
  831.       strmov(net->last_error,ER(net->last_errno));
  832.       DBUG_RETURN(0);
  833.     }
  834.     *prev_ptr=cur;
  835.     prev_ptr= &cur->next;
  836.     to= (char*) (cur->data+fields+1);
  837.     for (field=0 ; field < fields ; field++)
  838.     {
  839.       if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH)
  840.       { /* null field */
  841. cur->data[field] = 0;
  842.       }
  843.       else
  844.       {
  845. cur->data[field] = to;
  846. memcpy(to,(char*) cp,len); to[len]=0;
  847. to+=len+1;
  848. cp+=len;
  849. if (mysql_fields)
  850. {
  851.   if (mysql_fields[field].max_length < len)
  852.     mysql_fields[field].max_length=len;
  853. }
  854.       }
  855.     }
  856.     cur->data[field]=to; /* End of last field */
  857.     if ((pkt_len=net_safe_read(mysql)) == packet_error)
  858.     {
  859.       free_rows(result);
  860.       DBUG_RETURN(0);
  861.     }
  862.   }
  863.   *prev_ptr=0; /* last pointer is null */
  864.   DBUG_PRINT("exit",("Got %d rows",result->rows));
  865.   DBUG_RETURN(result);
  866. }
  867. /*
  868. ** Read one row. Uses packet buffer as storage for fields.
  869. ** When next packet is read, the previous field values are destroyed
  870. */
  871. static int
  872. read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
  873. {
  874.   uint field;
  875.   ulong pkt_len,len;
  876.   uchar *pos,*prev_pos;
  877.   if ((pkt_len=(uint) net_safe_read(mysql)) == packet_error)
  878.     return -1;
  879.   if (pkt_len == 1 && mysql->net.read_pos[0] == 254)
  880.     return 1; /* End of data */
  881.   prev_pos= 0; /* allowed to write at packet[-1] */
  882.   pos=mysql->net.read_pos;
  883.   for (field=0 ; field < fields ; field++)
  884.   {
  885.     if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH)
  886.     { /* null field */
  887.       row[field] = 0;
  888.       *lengths++=0;
  889.     }
  890.     else
  891.     {
  892.       row[field] = (char*) pos;
  893.       pos+=len;
  894.       *lengths++=len;
  895.     }
  896.     if (prev_pos)
  897.       *prev_pos=0; /* Terminate prev field */
  898.     prev_pos=pos;
  899.   }
  900.   row[field]=(char*) prev_pos+1; /* End of last field */
  901.   *prev_pos=0; /* Terminate last field */
  902.   return 0;
  903. }
  904. /****************************************************************************
  905. ** Init MySQL structure or allocate one
  906. ****************************************************************************/
  907. MYSQL * STDCALL
  908. mysql_init(MYSQL *mysql)
  909. {
  910.   mysql_once_init();
  911.   if (!mysql)
  912.   {
  913.     if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL))))
  914.       return 0;
  915.     mysql->free_me=1;
  916.     mysql->net.vio = 0;
  917.   }
  918.   else
  919.     bzero((char*) (mysql),sizeof(*(mysql)));
  920.   mysql->options.connect_timeout=CONNECT_TIMEOUT;
  921. #if defined(SIGPIPE) && defined(THREAD)
  922.   if (!((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE))
  923.     (void) signal(SIGPIPE,pipe_sig_handler);
  924. #endif
  925.   return mysql;
  926. }
  927. static void mysql_once_init()
  928. {
  929.   if (!mysql_client_init)
  930.   {
  931.     mysql_client_init=1;
  932.     my_init(); /* Will init threads */
  933.     init_client_errs();
  934.     if (!mysql_port)
  935.     {
  936.       mysql_port = MYSQL_PORT;
  937. #ifndef MSDOS
  938.       {
  939. struct servent *serv_ptr;
  940. char *env;
  941. if ((serv_ptr = getservbyname("mysql", "tcp")))
  942.   mysql_port = (uint) ntohs((ushort) serv_ptr->s_port);
  943. if ((env = getenv("MYSQL_TCP_PORT")))
  944.   mysql_port =(uint) atoi(env);
  945.       }
  946. #endif
  947.     }
  948.     if (!mysql_unix_port)
  949.     {
  950.       char *env;
  951. #ifdef __WIN__
  952.       mysql_unix_port = (char*) MYSQL_NAMEDPIPE;
  953. #else
  954.       mysql_unix_port = (char*) MYSQL_UNIX_ADDR;
  955. #endif
  956.       if ((env = getenv("MYSQL_UNIX_PORT")))
  957. mysql_unix_port = env;
  958.     }
  959.     mysql_debug(NullS);
  960. #if defined(SIGPIPE) && !defined(THREAD)
  961.     (void) signal(SIGPIPE,SIG_IGN);
  962. #endif
  963.   }
  964. #ifdef THREAD
  965.   else
  966.     my_thread_init();         /* Init if new thread */
  967. #endif
  968. }
  969. #ifdef HAVE_OPENSSL
  970. /**************************************************************************
  971. ** Fill in SSL part of MYSQL structure and set 'use_ssl' flag.
  972. ** NB! Errors are not reported until you do mysql_real_connect.
  973. **************************************************************************/
  974. int STDCALL
  975. mysql_ssl_set(MYSQL *mysql, const char *key, const char *cert,
  976.               const char *ca, const char *capath)
  977. {
  978.   mysql->options.ssl_key = key==0 ? 0 : my_strdup(key,MYF(0));
  979.   mysql->options.ssl_cert = cert==0 ? 0 : my_strdup(cert,MYF(0));
  980.   mysql->options.ssl_ca = ca==0 ? 0 : my_strdup(ca,MYF(0));
  981.   mysql->options.ssl_capath = capath==0 ? 0 : my_strdup(capath,MYF(0));
  982.   mysql->options.use_ssl = true;
  983.   mysql->connector_fd = new_VioSSLConnectorFd(key, cert, ca, capath);
  984.   return 0;
  985. }
  986. /**************************************************************************
  987. **************************************************************************/
  988. char * STDCALL
  989. mysql_ssl_cipher(MYSQL *mysql)
  990. {
  991.   return (char *)mysql->net.vio->cipher_description();
  992. }
  993. /**************************************************************************
  994. ** Free strings in the SSL structure and clear 'use_ssl' flag.
  995. ** NB! Errors are not reported until you do mysql_real_connect.
  996. **************************************************************************/
  997. int STDCALL
  998. mysql_ssl_clear(MYSQL *mysql)
  999. {
  1000.   my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR));
  1001.   my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR));
  1002.   my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR));
  1003.   my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR));
  1004.   mysql->options.ssl_key = 0;
  1005.   mysql->options.ssl_cert = 0;
  1006.   mysql->options.ssl_ca = 0;
  1007.   mysql->options.ssl_capath = 0;
  1008.   mysql->options.use_ssl = false;
  1009.   mysql->connector_fd->delete();
  1010.   mysql->connector_fd = 0;
  1011.   return 0;
  1012. }
  1013. #endif /* HAVE_OPENSSL */
  1014. /**************************************************************************
  1015. ** Connect to sql server
  1016. ** If host == 0 then use localhost
  1017. **************************************************************************/
  1018. MYSQL * STDCALL
  1019. mysql_connect(MYSQL *mysql,const char *host,
  1020.       const char *user, const char *passwd)
  1021. {
  1022.   MYSQL *res;
  1023.   mysql=mysql_init(mysql); /* Make it thread safe */
  1024.   {
  1025.     DBUG_ENTER("mysql_connect");
  1026.     if (!(res=mysql_real_connect(mysql,host,user,passwd,NullS,0,NullS,0)))
  1027.     {
  1028.       if (mysql->free_me)
  1029. my_free((gptr) mysql,MYF(0));
  1030.     }
  1031.     DBUG_RETURN(res);
  1032.   }
  1033. }
  1034. /*
  1035. ** Note that the mysql argument must be initialized with mysql_init()
  1036. ** before calling mysql_real_connect !
  1037. */
  1038. MYSQL * STDCALL
  1039. mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
  1040.    const char *passwd, const char *db,
  1041.    uint port, const char *unix_socket,uint client_flag)
  1042. {
  1043.   char buff[NAME_LEN+USERNAME_LENGTH+100],charset_name_buff[16];
  1044.   char *end,*host_info,*charset_name;
  1045.   my_socket sock;
  1046.   uint32 ip_addr;
  1047.   struct sockaddr_in sock_addr;
  1048.   uint pkt_length;
  1049.   NET *net= &mysql->net;
  1050. #ifdef __WIN__
  1051.   HANDLE hPipe=INVALID_HANDLE_VALUE;
  1052. #endif
  1053. #ifdef HAVE_SYS_UN_H
  1054.   struct sockaddr_un UNIXaddr;
  1055. #endif
  1056.   init_sigpipe_variables
  1057.   DBUG_ENTER("mysql_real_connect");
  1058.   DBUG_PRINT("enter",("host: %s  db: %s  user: %s",
  1059.       host ? host : "(Null)",
  1060.       db ? db : "(Null)",
  1061.       user ? user : "(Null)"));
  1062.   /* Don't give sigpipe errors if the client doesn't want them */
  1063.   set_sigpipe(mysql);
  1064.   net->vio = 0; /* If something goes wrong */
  1065.   /* use default options */
  1066.   if (mysql->options.my_cnf_file || mysql->options.my_cnf_group)
  1067.   {
  1068.     mysql_read_default_options(&mysql->options,
  1069.        (mysql->options.my_cnf_file ?
  1070. mysql->options.my_cnf_file : "my"),
  1071.        mysql->options.my_cnf_group);
  1072.     my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
  1073.     my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
  1074.     mysql->options.my_cnf_file=mysql->options.my_cnf_group=0;
  1075.   }
  1076.   /* Some empty-string-tests are done because of ODBC */
  1077.   if (!host || !host[0])
  1078.     host=mysql->options.host;
  1079.   if (!user || !user[0])
  1080.     user=mysql->options.user;
  1081.   if (!passwd)
  1082.   {
  1083.     passwd=mysql->options.password;
  1084. #ifndef DONT_USE_MYSQL_PWD
  1085.     if (!passwd)
  1086.       passwd=getenv("MYSQL_PWD");  /* get it from environment (haneke) */
  1087. #endif
  1088.   }
  1089.   if (!db || !db[0])
  1090.     db=mysql->options.db;
  1091.   if (!port)
  1092.     port=mysql->options.port;
  1093.   if (!unix_socket)
  1094.     unix_socket=mysql->options.unix_socket;
  1095.   mysql->reconnect=1; /* Reconnect as default */
  1096.   mysql->server_status=SERVER_STATUS_AUTOCOMMIT;
  1097.   /*
  1098.   ** Grab a socket and connect it to the server
  1099.   */
  1100. #if defined(HAVE_SYS_UN_H)
  1101.   if ((!host || !strcmp(host,LOCAL_HOST)) && (unix_socket || mysql_unix_port))
  1102.   {
  1103.     host=LOCAL_HOST;
  1104.     if (!unix_socket)
  1105.       unix_socket=mysql_unix_port;
  1106.     host_info=(char*) ER(CR_LOCALHOST_CONNECTION);
  1107.     DBUG_PRINT("info",("Using UNIX sock '%s'",unix_socket));
  1108.     if ((sock = socket(AF_UNIX,SOCK_STREAM,0)) == SOCKET_ERROR)
  1109.     {
  1110.       net->last_errno=CR_SOCKET_CREATE_ERROR;
  1111.       sprintf(net->last_error,ER(net->last_errno),ERRNO);
  1112.       goto error;
  1113.     }
  1114.     net->vio = vio_new(sock, VIO_TYPE_SOCKET, TRUE);
  1115.     bzero((char*) &UNIXaddr,sizeof(UNIXaddr));
  1116.     UNIXaddr.sun_family = AF_UNIX;
  1117.     strmov(UNIXaddr.sun_path, unix_socket);
  1118.     if (connect2(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
  1119.  mysql->options.connect_timeout) <0)
  1120.     {
  1121.       DBUG_PRINT("error",("Got error %d on connect to local server",ERRNO));
  1122.       net->last_errno=CR_CONNECTION_ERROR;
  1123.       sprintf(net->last_error,ER(net->last_errno),unix_socket,ERRNO);
  1124.       goto error;
  1125.     }
  1126.   }
  1127.   else
  1128. #elif defined(__WIN__)
  1129.   {
  1130.     if ((unix_socket ||
  1131.  !host && is_NT() ||
  1132.  host && !strcmp(host,LOCAL_HOST_NAMEDPIPE) ||
  1133.  mysql->options.named_pipe || !have_tcpip))
  1134.     {
  1135.       sock=0;
  1136.       if ((hPipe=create_named_pipe(net, mysql->options.connect_timeout,
  1137.    (char**) &host, (char**) &unix_socket)) ==
  1138.   INVALID_HANDLE_VALUE)
  1139.       {
  1140. DBUG_PRINT("error",
  1141.    ("host: '%s'  socket: '%s'  named_pipe: %d  have_tcpip: %d",
  1142.     host ? host : "<null>",
  1143.     unix_socket ? unix_socket : "<null>",
  1144.     (int) mysql->options.named_pipe,
  1145.     (int) have_tcpip));
  1146. if (mysql->options.named_pipe ||
  1147.     (host && !strcmp(host,LOCAL_HOST_NAMEDPIPE)) ||
  1148.     (unix_socket && !strcmp(unix_socket,MYSQL_NAMEDPIPE)))
  1149.   goto error; /* User only requested named pipes */
  1150. /* Try also with TCP/IP */
  1151.       }
  1152.       else
  1153.       {
  1154. net->vio=vio_new_win32pipe(hPipe);
  1155. sprintf(host_info=buff, ER(CR_NAMEDPIPE_CONNECTION), host,
  1156. unix_socket);
  1157.       }
  1158.     }
  1159.   }
  1160.   if (hPipe == INVALID_HANDLE_VALUE)
  1161. #endif
  1162.   {
  1163.     unix_socket=0; /* This is not used */
  1164.     if (!port)
  1165.       port=mysql_port;
  1166.     if (!host)
  1167.       host=LOCAL_HOST;
  1168.     sprintf(host_info=buff,ER(CR_TCP_CONNECTION),host);
  1169.     DBUG_PRINT("info",("Server name: '%s'.  TCP sock: %d", host,port));
  1170.     /* _WIN64 ;  Assume that the (int) range is enough for socket() */
  1171.     if ((sock = (my_socket) socket(AF_INET,SOCK_STREAM,0)) == SOCKET_ERROR)
  1172.     {
  1173.       net->last_errno=CR_IPSOCK_ERROR;
  1174.       sprintf(net->last_error,ER(net->last_errno),ERRNO);
  1175.       goto error;
  1176.     }
  1177.     net->vio = vio_new(sock,VIO_TYPE_TCPIP,FALSE);
  1178.     bzero((char*) &sock_addr,sizeof(sock_addr));
  1179.     sock_addr.sin_family = AF_INET;
  1180.     /*
  1181.     ** The server name may be a host name or IP address
  1182.     */
  1183.     if ((int) (ip_addr = inet_addr(host)) != (int) INADDR_NONE)
  1184.     {
  1185.       memcpy_fixed(&sock_addr.sin_addr,&ip_addr,sizeof(ip_addr));
  1186.     }
  1187.     else
  1188. #if defined(HAVE_GETHOSTBYNAME_R) && defined(_REENTRANT) && defined(THREAD)
  1189.     {
  1190.       int tmp_errno;
  1191.       struct hostent tmp_hostent,*hp;
  1192.       char buff2[GETHOSTBYNAME_BUFF_SIZE];
  1193.       hp = my_gethostbyname_r(host,&tmp_hostent,buff2,sizeof(buff2),
  1194.       &tmp_errno);
  1195.       if (!hp)
  1196.       {
  1197. net->last_errno=CR_UNKNOWN_HOST;
  1198. sprintf(net->last_error, ER(CR_UNKNOWN_HOST), host, tmp_errno);
  1199. goto error;
  1200.       }
  1201.       memcpy(&sock_addr.sin_addr,hp->h_addr, (size_t) hp->h_length);
  1202.     }
  1203. #else
  1204.     {
  1205.       struct hostent *hp;
  1206.       if (!(hp=gethostbyname(host)))
  1207.       {
  1208. net->last_errno=CR_UNKNOWN_HOST;
  1209. sprintf(net->last_error, ER(CR_UNKNOWN_HOST), host, errno);
  1210. goto error;
  1211.       }
  1212.       memcpy(&sock_addr.sin_addr,hp->h_addr, (size_t) hp->h_length);
  1213.     }
  1214. #endif
  1215.     sock_addr.sin_port = (ushort) htons((ushort) port);
  1216.     if (connect2(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr),
  1217.  mysql->options.connect_timeout) <0)
  1218.     {
  1219.       DBUG_PRINT("error",("Got error %d on connect to '%s'",ERRNO,host));
  1220.       net->last_errno= CR_CONN_HOST_ERROR;
  1221.       sprintf(net->last_error ,ER(CR_CONN_HOST_ERROR), host, ERRNO);
  1222.       goto error;
  1223.     }
  1224.   }
  1225.   if (!net->vio || my_net_init(net, net->vio))
  1226.   {
  1227.     vio_delete(net->vio);
  1228.     net->vio = 0;
  1229.     net->last_errno=CR_OUT_OF_MEMORY;
  1230.     strmov(net->last_error,ER(net->last_errno));
  1231.     goto error;
  1232.   }
  1233.   vio_keepalive(net->vio,TRUE);
  1234.   /* Get version info */
  1235.   mysql->protocol_version= PROTOCOL_VERSION; /* Assume this */
  1236.   if (mysql->options.connect_timeout &&
  1237.       vio_poll_read(net->vio, mysql->options.connect_timeout))
  1238.   {
  1239.     net->last_errno= CR_SERVER_LOST;
  1240.     strmov(net->last_error,ER(net->last_errno));    
  1241.     goto error;
  1242.   }
  1243.   if ((pkt_length=net_safe_read(mysql)) == packet_error)
  1244.     goto error;
  1245.   /* Check if version of protocoll matches current one */
  1246.   mysql->protocol_version= net->read_pos[0];
  1247.   DBUG_DUMP("packet",(char*) net->read_pos,10);
  1248.   DBUG_PRINT("info",("mysql protocol version %d, server=%d",
  1249.      PROTOCOL_VERSION, mysql->protocol_version));
  1250.   if (mysql->protocol_version != PROTOCOL_VERSION &&
  1251.       mysql->protocol_version != PROTOCOL_VERSION-1)
  1252.   {
  1253.     net->last_errno= CR_VERSION_ERROR;
  1254.     sprintf(net->last_error, ER(CR_VERSION_ERROR), mysql->protocol_version,
  1255.     PROTOCOL_VERSION);
  1256.     goto error;
  1257.   }
  1258.   end=strend((char*) net->read_pos+1);
  1259.   mysql->thread_id=uint4korr(end+1);
  1260.   end+=5;
  1261.   strmake(mysql->scramble_buff,end,8);
  1262.   end+=9;
  1263.   if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
  1264.     mysql->server_capabilities=uint2korr(end);
  1265.   if (pkt_length >= (uint) (end+18 - (char*) net->read_pos))
  1266.   {
  1267.     /* New protocol with 16 bytes to describe server characteristics */
  1268.     mysql->server_language=end[2];
  1269.     mysql->server_status=uint2korr(end+3);
  1270.   }
  1271.   /* Set character set */
  1272.   if ((charset_name=mysql->options.charset_name))
  1273.   {
  1274.     const char *save=charsets_dir;
  1275.     if (mysql->options.charset_dir)
  1276.       charsets_dir=mysql->options.charset_dir;
  1277.     mysql->charset=get_charset_by_name(mysql->options.charset_name,
  1278.                                        MYF(MY_WME));
  1279.     charsets_dir=save;
  1280.   }
  1281.   else if (mysql->server_language)
  1282.   {
  1283.     charset_name=charset_name_buff;
  1284.     sprintf(charset_name,"%d",mysql->server_language); /* In case of errors */
  1285.     if (!(mysql->charset =
  1286.   get_charset((uint8) mysql->server_language, MYF(MY_WME))))
  1287.       mysql->charset = default_charset_info; /* shouldn't be fatal */
  1288.   }
  1289.   else
  1290.     mysql->charset=default_charset_info;
  1291.   if (!mysql->charset)
  1292.   {
  1293.     net->last_errno=CR_CANT_READ_CHARSET;
  1294.     if (mysql->options.charset_dir)
  1295.       sprintf(net->last_error,ER(net->last_errno),
  1296.               charset_name ? charset_name : "unknown",
  1297.               mysql->options.charset_dir);
  1298.     else
  1299.     {
  1300.       char cs_dir_name[FN_REFLEN];
  1301.       get_charsets_dir(cs_dir_name);
  1302.       sprintf(net->last_error,ER(net->last_errno),
  1303.               charset_name ? charset_name : "unknown",
  1304.               cs_dir_name);
  1305.     }
  1306.     goto error;
  1307.   }
  1308.   /* Save connection information */
  1309.   if (!user) user="";
  1310.   if (!passwd) passwd="";
  1311.   if (!my_multi_malloc(MYF(0),
  1312.        &mysql->host_info, (uint) strlen(host_info)+1,
  1313.        &mysql->host,      (uint) strlen(host)+1,
  1314.        &mysql->unix_socket,unix_socket ?
  1315.        (uint) strlen(unix_socket)+1 : (uint) 1,
  1316.        &mysql->server_version,
  1317.        (uint) (end - (char*) net->read_pos),
  1318.        NullS) ||
  1319.       !(mysql->user=my_strdup(user,MYF(0))) ||
  1320.       !(mysql->passwd=my_strdup(passwd,MYF(0))))
  1321.   {
  1322.     strmov(net->last_error, ER(net->last_errno=CR_OUT_OF_MEMORY));
  1323.     goto error;
  1324.   }
  1325.   strmov(mysql->host_info,host_info);
  1326.   strmov(mysql->host,host);
  1327.   if (unix_socket)
  1328.     strmov(mysql->unix_socket,unix_socket);
  1329.   else
  1330.     mysql->unix_socket=0;
  1331.   strmov(mysql->server_version,(char*) net->read_pos+1);
  1332.   mysql->port=port;
  1333.   client_flag|=mysql->options.client_flag;
  1334.   /* Send client information for access check */
  1335.   client_flag|=CLIENT_CAPABILITIES;
  1336. #ifdef HAVE_OPENSSL
  1337.   if (mysql->options.use_ssl)
  1338.     client_flag|=CLIENT_SSL;
  1339. #endif /* HAVE_OPENSSL */
  1340.   if (db)
  1341.     client_flag|=CLIENT_CONNECT_WITH_DB;
  1342. #ifdef HAVE_COMPRESS
  1343.   if ((mysql->server_capabilities & CLIENT_COMPRESS) &&
  1344.       (mysql->options.compress || (client_flag & CLIENT_COMPRESS)))
  1345.     client_flag|=CLIENT_COMPRESS; /* We will use compression */
  1346.   else
  1347. #endif
  1348.     client_flag&= ~CLIENT_COMPRESS;
  1349. #ifdef HAVE_OPENSSL
  1350.   if ((mysql->server_capabilities & CLIENT_SSL) &&
  1351.       (mysql->options.use_ssl || (client_flag & CLIENT_SSL)))
  1352.   {
  1353.     DBUG_PRINT("info", ("Changing IO layer to SSL"));
  1354.     client_flag |= CLIENT_SSL;
  1355.   }
  1356.   else
  1357.   {
  1358.     if (client_flag & CLIENT_SSL)
  1359.     {
  1360.       DBUG_PRINT("info", ("Leaving IO layer intact because server doesn't support SSL"));
  1361.     }
  1362.     client_flag &= ~CLIENT_SSL;
  1363.   }
  1364. #endif /* HAVE_OPENSSL */
  1365.   int2store(buff,client_flag);
  1366.   mysql->client_flag=client_flag;
  1367. #ifdef HAVE_OPENSSL
  1368.   /* Oops.. are we careful enough to not send ANY information */
  1369.   /* without encryption? */
  1370.   if (client_flag & CLIENT_SSL)
  1371.   {
  1372.     if (my_net_write(net,buff,(uint) (2)) || net_flush(net))
  1373.       goto error;
  1374.     /* Do the SSL layering. */
  1375.     DBUG_PRINT("info", ("IO layer change in progress..."));
  1376.     VioSSLConnectorFd* connector_fd = (VioSSLConnectorFd*)
  1377.       (mysql->connector_fd);
  1378.     VioSocket* vio_socket = (VioSocket*)(mysql->net.vio);
  1379.     VioSSL* vio_ssl =    connector_fd->connect(vio_socket);
  1380.     mysql->net.vio =         (NetVio*)(vio_ssl);
  1381.   }
  1382. #endif /* HAVE_OPENSSL */
  1383.   DBUG_PRINT("info",("Server version = '%s'  capabilites: %ld  status: %d  client_flag: %d",
  1384.      mysql->server_version,mysql->server_capabilities,
  1385.      mysql->server_status, client_flag));
  1386.   int3store(buff+2,max_allowed_packet);
  1387.   if (user && user[0])
  1388.     strmake(buff+5,user,32); /* Max user name */
  1389.   else
  1390.     read_user_name((char*) buff+5);
  1391. #ifdef _CUSTOMCONFIG_
  1392. #include "_cust_libmysql.h";
  1393. #endif
  1394.   DBUG_PRINT("info",("user: %s",buff+5));
  1395.   end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd,
  1396.        (my_bool) (mysql->protocol_version == 9));
  1397.   if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
  1398.   {
  1399.     end=strmake(end+1,db,NAME_LEN);
  1400.     mysql->db=my_strdup(db,MYF(MY_WME));
  1401.     db=0;
  1402.   }
  1403.   if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net) ||
  1404.       net_safe_read(mysql) == packet_error)
  1405.     goto error;
  1406.   if (client_flag & CLIENT_COMPRESS) /* We will use compression */
  1407.     net->compress=1;
  1408.   if (db && mysql_select_db(mysql,db))
  1409.     goto error;
  1410.   if (mysql->options.init_command)
  1411.   {
  1412.     my_bool reconnect=mysql->reconnect;
  1413.     mysql->reconnect=0;
  1414.     if (mysql_query(mysql,mysql->options.init_command))
  1415.       goto error;
  1416.     mysql_free_result(mysql_use_result(mysql));
  1417.     mysql->reconnect=reconnect;
  1418.   }
  1419.   DBUG_PRINT("exit",("Mysql handler: %lx",mysql));
  1420.   reset_sigpipe(mysql);
  1421.   DBUG_RETURN(mysql);
  1422. error:
  1423.   reset_sigpipe(mysql);
  1424.   DBUG_PRINT("error",("message: %u (%s)",net->last_errno,net->last_error));
  1425.   {
  1426.     /* Free alloced memory */
  1427.     my_bool free_me=mysql->free_me;
  1428.     end_server(mysql);
  1429.     mysql->free_me=0;
  1430.     mysql_close(mysql);
  1431.     mysql->free_me=free_me;
  1432.   }
  1433.   DBUG_RETURN(0);
  1434. }
  1435. static my_bool mysql_reconnect(MYSQL *mysql)
  1436. {
  1437.   MYSQL tmp_mysql;
  1438.   DBUG_ENTER("mysql_reconnect");
  1439.   if (!mysql->reconnect ||
  1440.       (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info)
  1441.   {
  1442.    /* Allov reconnect next time */
  1443.     mysql->server_status&= ~SERVER_STATUS_IN_TRANS;
  1444.     DBUG_RETURN(1);
  1445.   }
  1446.   mysql_init(&tmp_mysql);
  1447.   tmp_mysql.options=mysql->options;
  1448.   if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd,
  1449.   mysql->db, mysql->port, mysql->unix_socket,
  1450.   mysql->client_flag))
  1451.     DBUG_RETURN(1);
  1452.   tmp_mysql.free_me=mysql->free_me;
  1453.   mysql->free_me=0;
  1454.   bzero((char*) &mysql->options,sizeof(mysql->options));
  1455.   mysql_close(mysql);
  1456.   *mysql=tmp_mysql;
  1457.   net_clear(&mysql->net);
  1458.   mysql->affected_rows= ~(my_ulonglong) 0;
  1459.   DBUG_RETURN(0);
  1460. }
  1461. /**************************************************************************
  1462. ** Change user and database 
  1463. **************************************************************************/
  1464. my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, 
  1465.   const char *passwd, const char *db)
  1466. {
  1467.   char buff[512],*pos=buff;
  1468.   DBUG_ENTER("mysql_change_user");
  1469.   if (!user)
  1470.     user="";
  1471.   if (!passwd)
  1472.     passwd="";
  1473.   pos=strmov(pos,user)+1;
  1474.   pos=scramble(pos, mysql->scramble_buff, passwd,
  1475.        (my_bool) (mysql->protocol_version == 9));
  1476.   pos=strmov(pos+1,db ? db : "");
  1477.   if (simple_command(mysql,COM_CHANGE_USER, buff,(uint) (pos-buff),0))
  1478.     DBUG_RETURN(1);
  1479.   my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
  1480.   my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
  1481.   my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
  1482.   mysql->user=  my_strdup(user,MYF(MY_WME));
  1483.   mysql->passwd=my_strdup(passwd,MYF(MY_WME));
  1484.   mysql->db=    db ? my_strdup(db,MYF(MY_WME)) : 0;
  1485.   DBUG_RETURN(0);
  1486. }
  1487. /**************************************************************************
  1488. ** Set current database
  1489. **************************************************************************/
  1490. int STDCALL
  1491. mysql_select_db(MYSQL *mysql, const char *db)
  1492. {
  1493.   int error;
  1494.   DBUG_ENTER("mysql_select_db");
  1495.   DBUG_PRINT("enter",("db: '%s'",db));
  1496.   if ((error=simple_command(mysql,COM_INIT_DB,db,(uint) strlen(db),0)))
  1497.     DBUG_RETURN(error);
  1498.   my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
  1499.   mysql->db=my_strdup(db,MYF(MY_WME));
  1500.   DBUG_RETURN(0);
  1501. }
  1502. /*************************************************************************
  1503. ** Send a QUIT to the server and close the connection
  1504. ** If handle is alloced by mysql connect free it.
  1505. *************************************************************************/
  1506. void STDCALL
  1507. mysql_close(MYSQL *mysql)
  1508. {
  1509.   DBUG_ENTER("mysql_close");
  1510.   if (mysql) /* Some simple safety */
  1511.   {
  1512.     if (mysql->net.vio != 0)
  1513.     {
  1514.       free_old_query(mysql);
  1515.       mysql->status=MYSQL_STATUS_READY; /* Force command */
  1516.       simple_command(mysql,COM_QUIT,NullS,0,1);
  1517.       end_server(mysql);
  1518.     }
  1519.     my_free((gptr) mysql->host_info,MYF(MY_ALLOW_ZERO_PTR));
  1520.     my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
  1521.     my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
  1522.     my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
  1523.     my_free(mysql->options.init_command,MYF(MY_ALLOW_ZERO_PTR));
  1524.     my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR));
  1525.     my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR));
  1526.     my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR));
  1527.     my_free(mysql->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR));
  1528.     my_free(mysql->options.db,MYF(MY_ALLOW_ZERO_PTR));
  1529.     my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
  1530.     my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
  1531.     my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
  1532.     my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
  1533.     /* Clear pointers for better safety */
  1534.     mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
  1535.     bzero((char*) &mysql->options,sizeof(mysql->options));
  1536.     mysql->net.vio = 0;
  1537. #ifdef HAVE_OPENSSL
  1538.     ((VioConnectorFd*)(mysql->connector_fd))->delete();
  1539.     mysql->connector_fd = 0;
  1540. #endif /* HAVE_OPENSSL */
  1541.     if (mysql->free_me)
  1542.       my_free((gptr) mysql,MYF(0));
  1543.   }
  1544.   DBUG_VOID_RETURN;
  1545. }
  1546. /**************************************************************************
  1547. ** Do a query. If query returned rows, free old rows.
  1548. ** Read data by mysql_store_result or by repeat call of mysql_fetch_row
  1549. **************************************************************************/
  1550. int STDCALL
  1551. mysql_query(MYSQL *mysql, const char *query)
  1552. {
  1553.   return mysql_real_query(mysql,query, (uint) strlen(query));
  1554. }
  1555. /*
  1556.   Send the query and return so we can do something else.
  1557.   Needs to be followed by mysql_read_query_result() when we want to
  1558.   finish processing it.
  1559. */  
  1560. int STDCALL
  1561. mysql_send_query(MYSQL* mysql, const char* query, uint length)
  1562. {
  1563.   return simple_command(mysql, COM_QUERY, query, length, 1);
  1564. }
  1565. int STDCALL mysql_read_query_result(MYSQL *mysql)
  1566. {
  1567.   uchar *pos;
  1568.   ulong field_count;
  1569.   MYSQL_DATA *fields;
  1570.   uint length;
  1571.   DBUG_ENTER("mysql_read_query_result");
  1572.   if ((length = net_safe_read(mysql)) == packet_error)
  1573.     DBUG_RETURN(-1);
  1574.   free_old_query(mysql); /* Free old result */
  1575. get_info:
  1576.   pos=(uchar*) mysql->net.read_pos;
  1577.   if ((field_count= net_field_length(&pos)) == 0)
  1578.   {
  1579.     mysql->affected_rows= net_field_length_ll(&pos);
  1580.     mysql->insert_id=   net_field_length_ll(&pos);
  1581.     if (mysql->server_capabilities & CLIENT_TRANSACTIONS)
  1582.     {
  1583.       mysql->server_status=uint2korr(pos); pos+=2;
  1584.     }
  1585.     if (pos < mysql->net.read_pos+length && net_field_length(&pos))
  1586.       mysql->info=(char*) pos;
  1587.     DBUG_RETURN(0);
  1588.   }
  1589.   if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */
  1590.   {
  1591.     int error=send_file_to_server(mysql,(char*) pos);
  1592.     if ((length=net_safe_read(mysql)) == packet_error || error)
  1593.       DBUG_RETURN(-1);
  1594.     goto get_info; /* Get info packet */
  1595.   }
  1596.   if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
  1597.     mysql->server_status|= SERVER_STATUS_IN_TRANS;
  1598.   mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */
  1599.   if (!(fields=read_rows(mysql,(MYSQL_FIELD*) 0,5)))
  1600.     DBUG_RETURN(-1);
  1601.   if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,
  1602.     (uint) field_count,0,
  1603.     (my_bool) test(mysql->server_capabilities &
  1604.    CLIENT_LONG_FLAG))))
  1605.     DBUG_RETURN(-1);
  1606.   mysql->status=MYSQL_STATUS_GET_RESULT;
  1607.   mysql->field_count=field_count;
  1608.   DBUG_RETURN(0);
  1609. }
  1610. int STDCALL
  1611. mysql_real_query(MYSQL *mysql, const char *query, uint length)
  1612. {
  1613.   DBUG_ENTER("mysql_real_query");
  1614.   DBUG_PRINT("enter",("handle: %lx",mysql));
  1615.   DBUG_PRINT("query",("Query = "%s"",query));
  1616.   if (simple_command(mysql,COM_QUERY,query,length,1))
  1617.     DBUG_RETURN(-1);
  1618.   DBUG_RETURN(mysql_read_query_result(mysql));
  1619. }
  1620. static int
  1621. send_file_to_server(MYSQL *mysql, const char *filename)
  1622. {
  1623.   int fd, readcount;
  1624.   char buf[IO_SIZE*15],*tmp_name;
  1625.   DBUG_ENTER("send_file_to_server");
  1626.   fn_format(buf,filename,"","",4); /* Convert to client format */
  1627.   if (!(tmp_name=my_strdup(buf,MYF(0))))
  1628.   {
  1629.     strmov(mysql->net.last_error, ER(mysql->net.last_errno=CR_OUT_OF_MEMORY));
  1630.     DBUG_RETURN(-1);
  1631.   }
  1632.   if ((fd = my_open(tmp_name,O_RDONLY, MYF(0))) < 0)
  1633.   {
  1634.     mysql->net.last_errno=EE_FILENOTFOUND;
  1635.     sprintf(buf,EE(mysql->net.last_errno),tmp_name,errno);
  1636.     strmake(mysql->net.last_error,buf,sizeof(mysql->net.last_error)-1);
  1637.     my_net_write(&mysql->net,"",0); net_flush(&mysql->net);
  1638.     my_free(tmp_name,MYF(0));
  1639.     DBUG_RETURN(-1);
  1640.   }
  1641.   while ((readcount = (int) my_read(fd,buf,sizeof(buf),MYF(0))) > 0)
  1642.   {
  1643.     if (my_net_write(&mysql->net,buf,readcount))
  1644.     {
  1645.       mysql->net.last_errno=CR_SERVER_LOST;
  1646.       strmov(mysql->net.last_error,ER(mysql->net.last_errno));
  1647.       DBUG_PRINT("error",("Lost connection to MySQL server during LOAD DATA of local file"));
  1648.       (void) my_close(fd,MYF(0));
  1649.       my_free(tmp_name,MYF(0));
  1650.       DBUG_RETURN(-1);
  1651.     }
  1652.   }
  1653.   (void) my_close(fd,MYF(0));
  1654.   /* Send empty packet to mark end of file */
  1655.   if (my_net_write(&mysql->net,"",0) || net_flush(&mysql->net))
  1656.   {
  1657.     mysql->net.last_errno=CR_SERVER_LOST;
  1658.     sprintf(mysql->net.last_error,ER(mysql->net.last_errno),errno);
  1659.     my_free(tmp_name,MYF(0));
  1660.     DBUG_RETURN(-1);
  1661.   }
  1662.   if (readcount < 0)
  1663.   {
  1664.     mysql->net.last_errno=EE_READ; /* the errmsg for not entire file read */
  1665.     sprintf(buf,EE(mysql->net.last_errno),tmp_name,errno);
  1666.     strmake(mysql->net.last_error,buf,sizeof(mysql->net.last_error)-1);
  1667.     my_free(tmp_name,MYF(0));
  1668.     DBUG_RETURN(-1);
  1669.   }
  1670.   DBUG_RETURN(0);
  1671. }
  1672. /**************************************************************************
  1673. ** Alloc result struct for buffered results. All rows are read to buffer.
  1674. ** mysql_data_seek may be used.
  1675. **************************************************************************/
  1676. MYSQL_RES * STDCALL
  1677. mysql_store_result(MYSQL *mysql)
  1678. {
  1679.   MYSQL_RES *result;
  1680.   DBUG_ENTER("mysql_store_result");
  1681.   if (!mysql->fields)
  1682.     DBUG_RETURN(0);
  1683.   if (mysql->status != MYSQL_STATUS_GET_RESULT)
  1684.   {
  1685.     strmov(mysql->net.last_error,
  1686.    ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC));
  1687.     DBUG_RETURN(0);
  1688.   }
  1689.   mysql->status=MYSQL_STATUS_READY; /* server is ready */
  1690.   if (!(result=(MYSQL_RES*) my_malloc(sizeof(MYSQL_RES)+
  1691.       sizeof(ulong)*mysql->field_count,
  1692.       MYF(MY_WME | MY_ZEROFILL))))
  1693.   {
  1694.     mysql->net.last_errno=CR_OUT_OF_MEMORY;
  1695.     strmov(mysql->net.last_error, ER(mysql->net.last_errno));
  1696.     DBUG_RETURN(0);
  1697.   }
  1698.   result->eof=1; /* Marker for buffered */
  1699.   result->lengths=(ulong*) (result+1);
  1700.   if (!(result->data=read_rows(mysql,mysql->fields,mysql->field_count)))
  1701.   {
  1702.     my_free((gptr) result,MYF(0));
  1703.     DBUG_RETURN(0);
  1704.   }
  1705.   mysql->affected_rows= result->row_count= result->data->rows;
  1706.   result->data_cursor= result->data->data;
  1707.   result->fields= mysql->fields;
  1708.   result->field_alloc= mysql->field_alloc;
  1709.   result->field_count= mysql->field_count;
  1710.   result->current_field=0;
  1711.   result->current_row=0; /* Must do a fetch first */
  1712.   mysql->fields=0; /* fields is now in result */
  1713.   DBUG_RETURN(result); /* Data fetched */
  1714. }
  1715. /**************************************************************************
  1716. ** Alloc struct for use with unbuffered reads. Data is fetched by domand
  1717. ** when calling to mysql_fetch_row.
  1718. ** mysql_data_seek is a noop.
  1719. **
  1720. ** No other queries may be specified with the same MYSQL handle.
  1721. ** There shouldn't be much processing per row because mysql server shouldn't
  1722. ** have to wait for the client (and will not wait more than 30 sec/packet).
  1723. **************************************************************************/
  1724. MYSQL_RES * STDCALL
  1725. mysql_use_result(MYSQL *mysql)
  1726. {
  1727.   MYSQL_RES *result;
  1728.   DBUG_ENTER("mysql_use_result");
  1729.   if (!mysql->fields)
  1730.     DBUG_RETURN(0);
  1731.   if (mysql->status != MYSQL_STATUS_GET_RESULT)
  1732.   {
  1733.     strmov(mysql->net.last_error,
  1734.    ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC));
  1735.     DBUG_RETURN(0);
  1736.   }
  1737.   if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+
  1738.       sizeof(ulong)*mysql->field_count,
  1739.       MYF(MY_WME | MY_ZEROFILL))))
  1740.     DBUG_RETURN(0);
  1741.   result->lengths=(ulong*) (result+1);
  1742.   if (!(result->row=(MYSQL_ROW)
  1743. my_malloc(sizeof(result->row[0])*(mysql->field_count+1), MYF(MY_WME))))
  1744.   { /* Ptrs: to one row */
  1745.     my_free((gptr) result,MYF(0));
  1746.     DBUG_RETURN(0);
  1747.   }
  1748.   result->fields= mysql->fields;
  1749.   result->field_alloc= mysql->field_alloc;
  1750.   result->field_count= mysql->field_count;
  1751.   result->current_field=0;
  1752.   result->handle= mysql;
  1753.   result->current_row= 0;
  1754.   mysql->fields=0; /* fields is now in result */
  1755.   mysql->status=MYSQL_STATUS_USE_RESULT;
  1756.   DBUG_RETURN(result); /* Data is read to be fetched */
  1757. }
  1758. /**************************************************************************
  1759. ** Return next field of the query results
  1760. **************************************************************************/
  1761. MYSQL_FIELD * STDCALL
  1762. mysql_fetch_field(MYSQL_RES *result)
  1763. {
  1764.   if (result->current_field >= result->field_count)
  1765.     return(NULL);
  1766.   return &result->fields[result->current_field++];
  1767. }
  1768. /**************************************************************************
  1769. **  Return next row of the query results
  1770. **************************************************************************/
  1771. MYSQL_ROW STDCALL
  1772. mysql_fetch_row(MYSQL_RES *res)
  1773. {
  1774.   DBUG_ENTER("mysql_fetch_row");
  1775.   if (!res->data)
  1776.   { /* Unbufferred fetch */
  1777.     if (!res->eof)
  1778.     {
  1779.       if (!(read_one_row(res->handle,res->field_count,res->row, res->lengths)))
  1780.       {
  1781. res->row_count++;
  1782. DBUG_RETURN(res->current_row=res->row);
  1783.       }
  1784.       else
  1785.       {
  1786. DBUG_PRINT("info",("end of data"));
  1787. res->eof=1;
  1788. res->handle->status=MYSQL_STATUS_READY;
  1789.       }
  1790.     }
  1791.     DBUG_RETURN((MYSQL_ROW) NULL);
  1792.   }
  1793.   {
  1794.     MYSQL_ROW tmp;
  1795.     if (!res->data_cursor)
  1796.     {
  1797.       DBUG_PRINT("info",("end of data"));
  1798.       DBUG_RETURN(res->current_row=(MYSQL_ROW) NULL);
  1799.     }
  1800.     tmp = res->data_cursor->data;
  1801.     res->data_cursor = res->data_cursor->next;
  1802.     DBUG_RETURN(res->current_row=tmp);
  1803.   }
  1804. }
  1805. /**************************************************************************
  1806. ** Get column lengths of the current row
  1807. ** If one uses mysql_use_result, res->lengths contains the length information,
  1808. ** else the lengths are calculated from the offset between pointers.
  1809. **************************************************************************/
  1810. ulong * STDCALL
  1811. mysql_fetch_lengths(MYSQL_RES *res)
  1812. {
  1813.   ulong *lengths,*prev_length;
  1814.   byte *start;
  1815.   MYSQL_ROW column,end;
  1816.   if (!(column=res->current_row))
  1817.     return 0; /* Something is wrong */
  1818.   if (res->data)
  1819.   {
  1820.     start=0;
  1821.     prev_length=0; /* Keep gcc happy */
  1822.     lengths=res->lengths;
  1823.     for (end=column+res->field_count+1 ; column != end ; column++,lengths++)
  1824.     {
  1825.       if (!*column)
  1826.       {
  1827. *lengths=0; /* Null */
  1828. continue;
  1829.       }
  1830.       if (start) /* Found end of prev string */
  1831. *prev_length= (uint) (*column-start-1);
  1832.       start= *column;
  1833.       prev_length=lengths;
  1834.     }
  1835.   }
  1836.   return res->lengths;
  1837. }
  1838. /**************************************************************************
  1839. ** Move to a specific row and column
  1840. **************************************************************************/
  1841. void STDCALL
  1842. mysql_data_seek(MYSQL_RES *result, my_ulonglong row)
  1843. {
  1844.   MYSQL_ROWS *tmp=0;
  1845.   DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row));
  1846.   if (result->data)
  1847.     for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ;
  1848.   result->current_row=0;
  1849.   result->data_cursor = tmp;
  1850. }
  1851. /*************************************************************************
  1852. ** put the row or field cursor one a position one got from mysql_row_tell()
  1853. ** This doesn't restore any data. The next mysql_fetch_row or
  1854. ** mysql_fetch_field will return the next row or field after the last used
  1855. *************************************************************************/
  1856. MYSQL_ROW_OFFSET STDCALL
  1857. mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET row)
  1858. {
  1859.   MYSQL_ROW_OFFSET return_value=result->data_cursor;
  1860.   result->current_row= 0;
  1861.   result->data_cursor= row;
  1862.   return return_value;
  1863. }
  1864. MYSQL_FIELD_OFFSET STDCALL
  1865. mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET field_offset)
  1866. {
  1867.   MYSQL_FIELD_OFFSET return_value=result->current_field;
  1868.   result->current_field=field_offset;
  1869.   return return_value;
  1870. }
  1871. /*****************************************************************************
  1872. ** List all databases
  1873. *****************************************************************************/
  1874. MYSQL_RES * STDCALL
  1875. mysql_list_dbs(MYSQL *mysql, const char *wild)
  1876. {
  1877.   char buff[255];
  1878.   DBUG_ENTER("mysql_list_dbs");
  1879.   append_wild(strmov(buff,"show databases"),buff+sizeof(buff),wild);
  1880.   if (mysql_query(mysql,buff))
  1881.     DBUG_RETURN(0);
  1882.   DBUG_RETURN (mysql_store_result(mysql));
  1883. }
  1884. /*****************************************************************************
  1885. ** List all tables in a database
  1886. ** If wild is given then only the tables matching wild is returned
  1887. *****************************************************************************/
  1888. MYSQL_RES * STDCALL
  1889. mysql_list_tables(MYSQL *mysql, const char *wild)
  1890. {
  1891.   char buff[255];
  1892.   DBUG_ENTER("mysql_list_tables");
  1893.   append_wild(strmov(buff,"show tables"),buff+sizeof(buff),wild);
  1894.   if (mysql_query(mysql,buff))
  1895.     DBUG_RETURN(0);
  1896.   DBUG_RETURN (mysql_store_result(mysql));
  1897. }
  1898. /**************************************************************************
  1899. ** List all fields in a table
  1900. ** If wild is given then only the fields matching wild is returned
  1901. ** Instead of this use query:
  1902. ** show fields in 'table' like "wild"
  1903. **************************************************************************/
  1904. MYSQL_RES * STDCALL
  1905. mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
  1906. {
  1907.   MYSQL_RES *result;
  1908.   MYSQL_DATA *query;
  1909.   char      buff[257],*end;
  1910.   DBUG_ENTER("mysql_list_fields");
  1911.   DBUG_PRINT("enter",("table: '%s'  wild: '%s'",table,wild ? wild : ""));
  1912.   LINT_INIT(query);
  1913.   end=strmake(strmake(buff, table,128)+1,wild ? wild : "",128);
  1914.   if (simple_command(mysql,COM_FIELD_LIST,buff,(uint) (end-buff),1) ||
  1915.       !(query = read_rows(mysql,(MYSQL_FIELD*) 0,6)))
  1916.     DBUG_RETURN(NULL);
  1917.   free_old_query(mysql);
  1918.   if (!(result = (MYSQL_RES *) my_malloc(sizeof(MYSQL_RES),
  1919.  MYF(MY_WME | MY_ZEROFILL))))
  1920.   {
  1921.     free_rows(query);
  1922.     DBUG_RETURN(NULL);
  1923.   }
  1924.   result->field_alloc=mysql->field_alloc;
  1925.   mysql->fields=0;
  1926.   result->field_count = (uint) query->rows;
  1927.   result->fields= unpack_fields(query,&result->field_alloc,
  1928. result->field_count,1,
  1929. (my_bool) test(mysql->server_capabilities &
  1930.        CLIENT_LONG_FLAG));
  1931.   result->eof=1;
  1932.   DBUG_RETURN(result);
  1933. }
  1934. /* List all running processes (threads) in server */
  1935. MYSQL_RES * STDCALL
  1936. mysql_list_processes(MYSQL *mysql)
  1937. {
  1938.   MYSQL_DATA *fields;
  1939.   uint field_count;
  1940.   uchar *pos;
  1941.   DBUG_ENTER("mysql_list_processes");
  1942.   LINT_INIT(fields);
  1943.   if (simple_command(mysql,COM_PROCESS_INFO,0,0,0))
  1944.     DBUG_RETURN(0);
  1945.   free_old_query(mysql);
  1946.   pos=(uchar*) mysql->net.read_pos;
  1947.   field_count=(uint) net_field_length(&pos);
  1948.   if (!(fields = read_rows(mysql,(MYSQL_FIELD*) 0,5)))
  1949.     DBUG_RETURN(NULL);
  1950.   if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,field_count,0,
  1951.     (my_bool) test(mysql->server_capabilities &
  1952.    CLIENT_LONG_FLAG))))
  1953.     DBUG_RETURN(0);
  1954.   mysql->status=MYSQL_STATUS_GET_RESULT;
  1955.   mysql->field_count=field_count;
  1956.   DBUG_RETURN(mysql_store_result(mysql));
  1957. }
  1958. int  STDCALL
  1959. mysql_create_db(MYSQL *mysql, const char *db)
  1960. {
  1961.   DBUG_ENTER("mysql_createdb");
  1962.   DBUG_PRINT("enter",("db: %s",db));
  1963.   DBUG_RETURN(simple_command(mysql,COM_CREATE_DB,db, (uint) strlen(db),0));
  1964. }
  1965. int  STDCALL
  1966. mysql_drop_db(MYSQL *mysql, const char *db)
  1967. {
  1968.   DBUG_ENTER("mysql_drop_db");
  1969.   DBUG_PRINT("enter",("db: %s",db));
  1970.   DBUG_RETURN(simple_command(mysql,COM_DROP_DB,db,(uint) strlen(db),0));
  1971. }
  1972. int STDCALL
  1973. mysql_shutdown(MYSQL *mysql)
  1974. {
  1975.   DBUG_ENTER("mysql_shutdown");
  1976.   DBUG_RETURN(simple_command(mysql,COM_SHUTDOWN,0,0,0));
  1977. }
  1978. int STDCALL
  1979. mysql_refresh(MYSQL *mysql,uint options)
  1980. {
  1981.   uchar bits[1];
  1982.   DBUG_ENTER("mysql_refresh");
  1983.   bits[0]= (uchar) options;
  1984.   DBUG_RETURN(simple_command(mysql,COM_REFRESH,(char*) bits,1,0));
  1985. }
  1986. int STDCALL
  1987. mysql_kill(MYSQL *mysql,ulong pid)
  1988. {
  1989.   char buff[12];
  1990.   DBUG_ENTER("mysql_kill");
  1991.   int4store(buff,pid);
  1992.   DBUG_RETURN(simple_command(mysql,COM_PROCESS_KILL,buff,4,0));
  1993. }
  1994. int STDCALL
  1995. mysql_dump_debug_info(MYSQL *mysql)
  1996. {
  1997.   DBUG_ENTER("mysql_dump_debug_info");
  1998.   DBUG_RETURN(simple_command(mysql,COM_DEBUG,0,0,0));
  1999. }
  2000. char * STDCALL
  2001. mysql_stat(MYSQL *mysql)
  2002. {
  2003.   DBUG_ENTER("mysql_stat");
  2004.   if (simple_command(mysql,COM_STATISTICS,0,0,0))
  2005.     return mysql->net.last_error;
  2006.   mysql->net.read_pos[mysql->packet_length]=0; /* End of stat string */
  2007.   if (!mysql->net.read_pos[0])
  2008.   {
  2009.     mysql->net.last_errno=CR_WRONG_HOST_INFO;
  2010.     strmov(mysql->net.last_error, ER(mysql->net.last_errno));
  2011.     return mysql->net.last_error;
  2012.   }
  2013.   DBUG_RETURN((char*) mysql->net.read_pos);
  2014. }
  2015. int STDCALL
  2016. mysql_ping(MYSQL *mysql)
  2017. {
  2018.   DBUG_ENTER("mysql_ping");
  2019.   DBUG_RETURN(simple_command(mysql,COM_PING,0,0,0));
  2020. }
  2021. char * STDCALL
  2022. mysql_get_server_info(MYSQL *mysql)
  2023. {
  2024.   return((char*) mysql->server_version);
  2025. }
  2026. char * STDCALL
  2027. mysql_get_host_info(MYSQL *mysql)
  2028. {
  2029.   return(mysql->host_info);
  2030. }
  2031. uint STDCALL
  2032. mysql_get_proto_info(MYSQL *mysql)
  2033. {
  2034.   return (mysql->protocol_version);
  2035. }
  2036. char * STDCALL
  2037. mysql_get_client_info(void)
  2038. {
  2039.   return (char*) MYSQL_SERVER_VERSION;
  2040. }
  2041. int STDCALL
  2042. mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg)
  2043. {
  2044.   DBUG_ENTER("mysql_option");
  2045.   DBUG_PRINT("enter",("option: %d",(int) option));
  2046.   switch (option) {
  2047.   case MYSQL_OPT_CONNECT_TIMEOUT:
  2048.     mysql->options.connect_timeout= *(uint*) arg;
  2049.     break;
  2050.   case MYSQL_OPT_COMPRESS:
  2051.     mysql->options.compress=1; /* Remember for connect */
  2052.     break;
  2053.   case MYSQL_OPT_NAMED_PIPE:
  2054.     mysql->options.named_pipe=1; /* Force named pipe */
  2055.     break;
  2056.   case MYSQL_INIT_COMMAND:
  2057.     my_free(mysql->options.init_command,MYF(MY_ALLOW_ZERO_PTR));
  2058.     mysql->options.init_command=my_strdup(arg,MYF(MY_WME));
  2059.     break;
  2060.   case MYSQL_READ_DEFAULT_FILE:
  2061.     my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
  2062.     mysql->options.my_cnf_file=my_strdup(arg,MYF(MY_WME));
  2063.     break;
  2064.   case MYSQL_READ_DEFAULT_GROUP:
  2065.     my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
  2066.     mysql->options.my_cnf_group=my_strdup(arg,MYF(MY_WME));
  2067.     break;
  2068.   case MYSQL_SET_CHARSET_DIR:
  2069.     my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
  2070.     mysql->options.charset_dir=my_strdup(arg,MYF(MY_WME));
  2071.     break;
  2072.   case MYSQL_SET_CHARSET_NAME:
  2073.     my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
  2074.     mysql->options.charset_name=my_strdup(arg,MYF(MY_WME));
  2075.     break;
  2076.   default:
  2077.     DBUG_RETURN(-1);
  2078.   }
  2079.   DBUG_RETURN(0);
  2080. }
  2081. /****************************************************************************
  2082. ** Functions to get information from the MySQL structure
  2083. ** These are functions to make shared libraries more usable.
  2084. ****************************************************************************/
  2085. /* MYSQL_RES */
  2086. my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res)
  2087. {
  2088.   return res->row_count;
  2089. }
  2090. unsigned int STDCALL mysql_num_fields(MYSQL_RES *res)
  2091. {
  2092.   return res->field_count;
  2093. }
  2094. my_bool STDCALL mysql_eof(MYSQL_RES *res)
  2095. {
  2096.   return res->eof;
  2097. }
  2098. MYSQL_FIELD * STDCALL mysql_fetch_field_direct(MYSQL_RES *res,uint fieldnr)
  2099. {
  2100.   return &(res)->fields[fieldnr];
  2101. }
  2102. MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res)
  2103. {
  2104.   return (res)->fields;
  2105. }
  2106. MYSQL_ROWS * STDCALL mysql_row_tell(MYSQL_RES *res)
  2107. {
  2108.   return res->data_cursor;
  2109. }
  2110. uint STDCALL mysql_field_tell(MYSQL_RES *res)
  2111. {
  2112.   return (res)->current_field;
  2113. }
  2114. /* MYSQL */
  2115. unsigned int STDCALL mysql_field_count(MYSQL *mysql)
  2116. {
  2117.   return mysql->field_count;
  2118. }
  2119. my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql)
  2120. {
  2121.   return (mysql)->affected_rows;
  2122. }
  2123. my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql)
  2124. {
  2125.   return (mysql)->insert_id;
  2126. }
  2127. uint STDCALL mysql_errno(MYSQL *mysql)
  2128. {
  2129.   return (mysql)->net.last_errno;
  2130. }
  2131. char * STDCALL mysql_error(MYSQL *mysql)
  2132. {
  2133.   return (mysql)->net.last_error;
  2134. }
  2135. char *STDCALL mysql_info(MYSQL *mysql)
  2136. {
  2137.   return (mysql)->info;
  2138. }
  2139. ulong STDCALL mysql_thread_id(MYSQL *mysql)
  2140. {
  2141.   return (mysql)->thread_id;
  2142. }
  2143. const char * STDCALL mysql_character_set_name(MYSQL *mysql)
  2144. {
  2145.   return mysql->charset->name;
  2146. }
  2147. uint STDCALL mysql_thread_safe(void)
  2148. {
  2149. #ifdef THREAD
  2150.   return 1;
  2151. #else
  2152.   return 0;
  2153. #endif
  2154. }
  2155. /****************************************************************************
  2156. ** Some support functions
  2157. ****************************************************************************/
  2158. /*
  2159. ** Add escape characters to a string (blob?) to make it suitable for a insert
  2160. ** to should at least have place for length*2+1 chars
  2161. ** Returns the length of the to string
  2162. */
  2163. ulong STDCALL
  2164. mysql_escape_string(char *to,const char *from,ulong length)
  2165. {
  2166.   return mysql_sub_escape_string(default_charset_info,to,from,length);
  2167. }
  2168. ulong STDCALL
  2169. mysql_real_escape_string(MYSQL *mysql, char *to,const char *from,
  2170.  ulong length)
  2171. {
  2172.   return mysql_sub_escape_string(mysql->charset,to,from,length);
  2173. }
  2174. static ulong
  2175. mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
  2176. const char *from, ulong length)
  2177. {
  2178.   const char *to_start=to;
  2179.   const char *end;
  2180. #ifdef USE_MB
  2181.   my_bool use_mb_flag=use_mb(charset_info);
  2182. #endif
  2183.   for (end=from+length; from != end ; from++)
  2184.   {
  2185. #ifdef USE_MB
  2186.     int l;
  2187.     if (use_mb_flag && (l = my_ismbchar(charset_info, from, end)))
  2188.     {
  2189.       while (l--)
  2190.   *to++ = *from++;
  2191.       from--;
  2192.       continue;
  2193.     }
  2194. #endif
  2195.     switch (*from) {
  2196.     case 0: /* Must be escaped for 'mysql' */
  2197.       *to++= '\';
  2198.       *to++= '0';
  2199.       break;
  2200.     case 'n': /* Must be escaped for logs */
  2201.       *to++= '\';
  2202.       *to++= 'n';
  2203.       break;
  2204.     case 'r':
  2205.       *to++= '\';
  2206.       *to++= 'r';
  2207.       break;
  2208.     case '\':
  2209.       *to++= '\';
  2210.       *to++= '\';
  2211.       break;
  2212.     case ''':
  2213.       *to++= '\';
  2214.       *to++= ''';
  2215.       break;
  2216.     case '"': /* Better safe than sorry */
  2217.       *to++= '\';
  2218.       *to++= '"';
  2219.       break;
  2220.     case '32': /* This gives problems on Win32 */
  2221.       *to++= '\';
  2222.       *to++= 'Z';
  2223.       break;
  2224.     default:
  2225.       *to++= *from;
  2226.     }
  2227.   }
  2228.   *to=0;
  2229.   return (ulong) (to-to_start);
  2230. }
  2231. char * STDCALL
  2232. mysql_odbc_escape_string(MYSQL *mysql,
  2233.  char *to, ulong to_length,
  2234.  const char *from, ulong from_length,
  2235.  void *param,
  2236.  char * (*extend_buffer)
  2237.  (void *, char *, ulong *))
  2238. {
  2239.   char *to_end=to+to_length-5;
  2240.   const char *end;
  2241. #ifdef USE_MB
  2242.   my_bool use_mb_flag=use_mb(mysql->charset);
  2243. #endif
  2244.   for (end=from+from_length; from != end ; from++)
  2245.   {
  2246.     if (to >= to_end)
  2247.     {
  2248.       to_length = (ulong) (end-from)+512; /* We want this much more */
  2249.       if (!(to=(*extend_buffer)(param, to, &to_length)))
  2250. return to;
  2251.       to_end=to+to_length-5;
  2252.     }
  2253. #ifdef USE_MB
  2254.     {
  2255.       int l;
  2256.       if (use_mb_flag && (l = my_ismbchar(mysql->charset, from, end)))
  2257.       {
  2258. while (l--)
  2259.   *to++ = *from++;
  2260. from--;
  2261. continue;
  2262.       }
  2263.     }
  2264. #endif
  2265.     switch (*from) {
  2266.     case 0: /* Must be escaped for 'mysql' */
  2267.       *to++= '\';
  2268.       *to++= '0';
  2269.       break;
  2270.     case 'n': /* Must be escaped for logs */
  2271.       *to++= '\';
  2272.       *to++= 'n';
  2273.       break;
  2274.     case 'r':
  2275.       *to++= '\';
  2276.       *to++= 'r';
  2277.       break;
  2278.     case '\':
  2279.       *to++= '\';
  2280.       *to++= '\';
  2281.       break;
  2282.     case ''':
  2283.       *to++= '\';
  2284.       *to++= ''';
  2285.       break;
  2286.     case '"': /* Better safe than sorry */
  2287.       *to++= '\';
  2288.       *to++= '"';
  2289.       break;
  2290.     case '32': /* This gives problems on Win32 */
  2291.       *to++= '\';
  2292.       *to++= 'Z';
  2293.       break;
  2294.     default:
  2295.       *to++= *from;
  2296.     }
  2297.   }
  2298.   return to;
  2299. }
  2300. void STDCALL
  2301. myodbc_remove_escape(MYSQL *mysql,char *name)
  2302. {
  2303.   char *to;
  2304. #ifdef USE_MB
  2305.   my_bool use_mb_flag=use_mb(mysql->charset);
  2306.   char *end;
  2307.   LINT_INIT(end);
  2308.   if (use_mb_flag)
  2309.     for (end=name; *end ; end++) ;
  2310. #endif
  2311.   for (to=name ; *name ; name++)
  2312.   {
  2313. #ifdef USE_MB
  2314.     int l;
  2315.     if (use_mb_flag && (l = my_ismbchar( mysql->charset, name , end ) ) )
  2316.     {
  2317.       while (l--)
  2318. *to++ = *name++;
  2319.       name--;
  2320.       continue;
  2321.     }
  2322. #endif
  2323.     if (*name == '\' && name[1])
  2324.       name++;
  2325.     *to++= *name;
  2326.   }
  2327.   *to=0;
  2328. }