home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / libmysql / libmysql.c < prev    next >
C/C++ Source or Header  |  2000-11-21  |  70KB  |  2,563 lines

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