mod_mysql.c
上传用户:pycemail
上传日期:2007-01-04
资源大小:329k
文件大小:6k
源码类别:

Ftp客户端

开发平台:

Unix_Linux

  1. /*
  2.  * ProFTPD: mod_mysql -- Support for connecting to MySQL databases.
  3.  * Time-stamp: <1999-10-04 03:21:21 root>
  4.  * Copyright (c) 1998-1999 Johnie Ingram.
  5.  *  
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
  19.  */
  20. #define MOD_MYSQL_VERSION "mod_mysql/2.0"
  21. /* -- DO NOT MODIFY THE LINE BELOW UNLESS YOU FEEL LIKE IT --
  22.  * $Libraries: -lm -lmysqlclient $
  23.  */
  24. /* This is mod_mysql, contrib software for proftpd 1.2.0pre3 and above.
  25.    For more information contact Johnie Ingram <johnie@netgod.net>.
  26.    History Log:
  27.    * 1999-09-19: v2.0: Most directives split into mod_sql; invented API.
  28. */
  29. #include "conf.h"
  30. #include <mysql.h>
  31. /* *INDENT-OFF* */
  32. static MYSQL mod_mysql_server;
  33. static MYSQL *mysqldb = 0;
  34. /* Maximum username field to expect, etc. */
  35. #define ARBITRARY_MAX                   128
  36. static struct
  37. {
  38.   char *sql_host; /* Data for connecting, set by MySQLInfo. */
  39.   char *sql_user;
  40.   char *sql_pass;
  41.   char *sql_dbname;
  42.   int ok;
  43.   int opens;
  44. } g;
  45. /* *INDENT-ON* */
  46. /* **************************************************************** */
  47. MODRET
  48. sql_cmd_close (cmd_rec * cmd)
  49. {
  50.   log_debug (DEBUG5, "mysql: close [%i] for %s", g.opens, cmd->argv[0]);
  51.   if (!g.ok || g.opens--)
  52.     return DECLINED (cmd);
  53.   if (mysqldb)
  54.     {
  55.       log_debug (DEBUG4, "mysql: disconnecting: %s", mysql_stat (mysqldb));
  56.       mysql_close (mysqldb);
  57.     }
  58.   mysqldb = NULL;
  59.   return DECLINED (cmd);
  60. }
  61. MODRET
  62. sql_cmd_open (cmd_rec * cmd)
  63. {
  64.   if (!g.ok)
  65.     return DECLINED (cmd);
  66.   g.opens++;
  67.   log_debug (DEBUG5, "mysql: open [%i] for %s", g.opens, cmd->argv[0]);
  68.   if (g.opens > 1)
  69.     return HANDLED (cmd);
  70.   if (!(mysqldb = mysql_connect (&mod_mysql_server, g.sql_host,
  71.  g.sql_user, g.sql_pass)))
  72.     {
  73.       log_pri (LOG_ERR, "mysql: client %s connect FAILED to %s@%s",
  74.        mysql_get_client_info (), g.sql_user, g.sql_host);
  75.       g.ok = FALSE;
  76.       g.opens = 0;
  77.       return DECLINED (cmd);
  78.     }
  79.   log_debug (DEBUG5, "mysql: connect OK %s -> %s (%s@%s)",
  80.      mysql_get_client_info (), mysql_get_server_info (mysqldb),
  81.      g.sql_user, g.sql_host);
  82.   return HANDLED (cmd);
  83. }
  84. MODRET
  85. _do_query (cmd_rec * cmd, const char *query, int update)
  86. {
  87.   int error = 1;
  88.   if (!g.ok)
  89.     return DECLINED (cmd);
  90.   block_signals ();
  91.   /* This forces a quick ping of the remote server, so we know if its there. */
  92.   if (mysqldb)
  93.     mysql_select_db (mysqldb, g.sql_dbname);
  94.   if (!mysqldb
  95.       || ((error = mysql_query (mysqldb, query))
  96.   && !strcasecmp (mysql_error (mysqldb), "mysql server has gone")))
  97.     {
  98.       /* We need to restart the server link. */
  99.       if (mysqldb)
  100. log_pri (LOG_ERR, "mysql: server has wandered off (%s/%s)",
  101.  g.sql_host, g.sql_dbname);
  102.       sql_cmd_open (cmd);
  103.       if (!mysqldb)
  104. return DECLINED (cmd);
  105.       error = mysql_select_db (mysqldb, g.sql_dbname)
  106. || mysql_query (mysqldb, query);
  107.     }
  108.   unblock_signals ();
  109.   if (error)
  110.     {
  111.       log_debug (DEBUG4, "mysql: %s failed: "%s": %s",
  112.  (update) ? "update" : "select",
  113.  query, mysql_error (mysqldb));
  114.       return DECLINED (cmd);
  115.     }
  116.   log_debug (DEBUG5, "mysql: %s OK: [%s] "%s"",
  117.      (update) ? "update" : "select", g.sql_dbname, query);
  118.   return HANDLED (cmd);
  119. }
  120. MODRET
  121. sql_cmd_update (cmd_rec * cmd)
  122. {
  123.   return _do_query (cmd, cmd->argv[1], TRUE);
  124. }
  125. MODRET
  126. sql_cmd_select (cmd_rec * cmd)
  127. {
  128.   MODRET mr;
  129.   MYSQL_RES *result;
  130.   MYSQL_ROW sql_row;
  131.   int i, j;
  132.   mr = _do_query (cmd, cmd->argv[1], FALSE);
  133.   if (!MODRET_ISHANDLED (mr))
  134.     return DECLINED (mr);
  135.   if ((result = mysql_store_result (mysqldb)))
  136.     {
  137.       int rcount = mysql_num_rows (result);
  138.       int fcount = mysql_num_fields (result);
  139.       int count = rcount * fcount;
  140.       char **data = pcalloc (cmd->tmp_pool, sizeof (char *) * (count + 1));
  141.       for (i = 0, count = 0; i < rcount; i++)
  142. {
  143.   sql_row = mysql_fetch_row (result);
  144.   for (j = 0; j < fcount; j++)
  145.     data[count++] = pstrdup (cmd->tmp_pool, sql_row[j]);
  146. }
  147.       mysql_free_result (result);
  148.       data[count] = NULL;
  149.       mr->data = data;
  150.     }
  151.   return mr;
  152. }
  153. static authtable mysql_authtab[] = {
  154.   {0, "dbd_open", sql_cmd_open},
  155.   {0, "dbd_close", sql_cmd_close},
  156.   {0, "dbd_update", sql_cmd_update},
  157.   {0, "dbd_select", sql_cmd_select},
  158.   {0, NULL, NULL}
  159. };
  160. /* **************************************************************** */
  161. MODRET set_sqlinfo (cmd_rec * cmd)
  162. {
  163.   CHECK_ARGS (cmd, 4);
  164.   CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL | CONF_VIRTUAL);
  165.   add_config_param_str ("MySQLInfo", 4,
  166. (void *) cmd->argv[1], (void *) cmd->argv[2],
  167. (void *) cmd->argv[3], (void *) cmd->argv[4]);
  168.   return HANDLED (cmd);
  169. }
  170. static conftable mysql_conftab[] = {
  171. /* *INDENT-OFF* */
  172.   { "MySQLInfo",              set_sqlinfo,       NULL },
  173.   { 0,       NULL }
  174. /* *INDENT-ON* */
  175. };
  176. /* **************************************************************** */
  177. static int
  178. mysql_modinit ()
  179. {
  180.   config_rec *c;
  181.   memset (&g, 0, sizeof (g));
  182.   if (!(c = find_config (CURRENT_CONF, CONF_PARAM, "MySQLInfo", FALSE)))
  183.     return 0;
  184.   g.sql_host = pstrdup (session.pool, c->argv[0]);
  185.   g.sql_user = pstrdup (session.pool, c->argv[1]);
  186.   g.sql_pass = pstrdup (session.pool, c->argv[2]);
  187.   g.sql_dbname = pstrdup (session.pool, c->argv[3]);
  188.   g.ok = TRUE;
  189.   log_debug (DEBUG5, "%s: configured: db %s at %s@%s",
  190.      MOD_MYSQL_VERSION, g.sql_dbname, g.sql_user, g.sql_host);
  191.   return 0;
  192. }
  193. module mysql_module = {
  194.   NULL, NULL, /* Always NULL */
  195.   0x20, /* API Version 2.0 */
  196.   "mysql",
  197.   mysql_conftab, /* SQL configuration handler table */
  198.   NULL, /* SQL command handler table */
  199.   mysql_authtab, /* SQL authentication handler table */
  200.   mysql_modinit, /* Pre-fork "parent-mode" init */
  201.   mysql_modinit /* Post-fork "child mode" init */
  202. };