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

Ftp客户端

开发平台:

Unix_Linux

  1. /*
  2.  * ProFTPD: mod_ratio -- Support upload/download ratios.
  3.  * Time-stamp: <1999-10-04 03:31:31 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_RATIO_VERSION "mod_ratio/3.0"
  21. /* This is mod_ratio, contrib software for proftpd 1.2.0pre3 and above.
  22.    For more information contact Johnie Ingram <johnie@netgod.net>.
  23.    History Log:
  24.    * 1999-10-03: v3.0: Uses generic API to access SQL data at runtime.
  25.      Supports negative ratios (upload X to get 1) by popular demand.
  26.      Added proper SITE command and help.  Various presentation
  27.      idiosyncracies fixed.
  28.    * 1999-06-13: v2.2: fixed ratio display, it was printing ratios in
  29.      reverse order.
  30.    * 1999-05-03: v2.1: mod_mysql bugfix; rearranged CWD reply so
  31.      Netscape shows ratios; fixed recalculation in XRATIO.  Added
  32.      CwdRatioMsg directive for showing equivalent URLs (always
  33.      enabled).
  34.    
  35.    * 1999-04-08: v2.0: Reformat and rewrite.  Add FileRatioErrMsg,
  36.      ByteRatioErrMsg, and LeechRatioMsg directives and support for
  37.      proftpd mod_mysql.
  38.    * 1998-09-08: v1.0: Accepted into CVS as a contrib module.
  39.    * 1998-07-14: v0.2: Trimmed some debug output, added HostRatio
  40.      directive, included in Debian ProFTPD binary package.
  41.    * 1998-04-18: v0.1: Initial release.
  42. */
  43. #include "conf.h"
  44. /* *INDENT-OFF* */
  45. /* Maximum username field to expect, etc. */
  46. #define ARBITRARY_MAX                   128
  47. static struct
  48. {
  49.   int fstor;
  50.   int fretr;
  51.   int bstor;
  52.   int bretr;
  53.   int frate;
  54.   int fcred;
  55.   int brate;
  56.   int bcred;
  57.   int files;
  58.   int bytes;
  59.   char ftext [64];
  60.   char btext [64];
  61. } stats;
  62. static struct
  63. {
  64.   int enable;
  65.   char user [ARBITRARY_MAX];
  66.   const char *rtype;          /* The ratio type currently in effect. */
  67.   const char *filemsg;
  68.   const char *bytemsg;
  69.   const char *leechmsg;
  70. } g;
  71. #define RATIO_ENFORCE (stats.frate || stats.brate)
  72. #define RATIO_STUFFS "-%i/%i +%i/%i (%i %i %i %i) = %i/%i%s%s", 
  73.     stats.fretr, stats.bretr, stats.fstor, stats.bstor, 
  74.             stats.frate, stats.fcred, stats.brate, stats.bcred, 
  75.             stats.files, stats.bytes, 
  76.     (stats.frate && stats.files < 1) ? " [NO F]" : "", 
  77.     (stats.brate && stats.bytes < 32768) ? " [LO B]" : ""
  78. #define SHORT_RATIO_STUFFS "-%i/%i +%i/%i = %i/%i%s%s", 
  79.     stats.fretr, stats.bretr, stats.fstor, stats.bstor, 
  80.             stats.files, stats.bytes, 
  81.     (stats.frate && stats.files < 1) ? " [NO F]" : "", 
  82.     (stats.brate && stats.bytes < 32768) ? " [LO B]" : ""
  83. /* *INDENT-ON* */
  84. static cmd_rec *
  85. _make_cmd (pool * cp, int argc, ...)
  86. {
  87.   va_list args;
  88.   cmd_rec *c;
  89.   int i;
  90.   c = pcalloc (cp, sizeof (cmd_rec));
  91.   c->argc = argc;
  92.   c->symtable_index = -1;
  93.   c->argv = pcalloc (cp, sizeof (void *) * (argc + 1));
  94.   c->argv[0] = MOD_RATIO_VERSION;
  95.   va_start (args, argc);
  96.   for (i = 0; i < argc; i++)
  97.     c->argv[i + 1] = (void *) va_arg (args, char *);
  98.   va_end (args);
  99.   return c;
  100. }
  101. static modret_t *
  102. _dispatch_ratio (cmd_rec * cmd, char *match)
  103. {
  104.   authtable *m;
  105.   modret_t *mr = NULL;
  106.   m = mod_find_auth_symbol (match, &cmd->symtable_index, NULL);
  107.   while (m)
  108.     {
  109.       mr = call_module_auth (m->m, m->handler, cmd);
  110.       if (MODRET_ISHANDLED (mr) || MODRET_ISERROR (mr))
  111. break;
  112.       m = mod_find_auth_symbol (match, &cmd->symtable_index, m);
  113.     }
  114.   if (MODRET_ISERROR (mr))
  115.     log_debug (DEBUG0, "Aiee! mod_ratio internal!  %s", MODRET_ERRMSG (mr));
  116.   return mr;
  117. }
  118. static modret_t *
  119. _dispatch (cmd_rec * cmd, char *match)
  120. {
  121.   cmd_rec *cr;
  122.   modret_t *mr = 0;
  123.   cr = _make_cmd (cmd->tmp_pool, 0);
  124.   mr = _dispatch_ratio (cr, match);
  125.   if (cr->tmp_pool)
  126.     destroy_pool (cr->tmp_pool);
  127.   return mr;
  128. }
  129. static void
  130. _set_stats (char *fstor, char *fretr, char *bstor, char *bretr)
  131. {
  132.   if (fstor)
  133.     stats.fstor = atoi (fstor);
  134.   if (fretr)
  135.     stats.fretr = atoi (fretr);
  136.   if (bstor)
  137.     stats.bstor = atoi (bretr);
  138.   if (bretr)
  139.     stats.bretr = atoi (bretr);
  140. }
  141. static void
  142. _set_ratios (char *frate, char *fcred, char *brate, char *bcred)
  143. {
  144.   stats.frate = stats.fcred = stats.brate = stats.bcred = 0;
  145.   if (frate)
  146.     stats.frate = atoi (frate);
  147.   if (fcred)
  148.     stats.fcred = atoi (fcred);
  149.   if (brate)
  150.     stats.brate = atoi (brate);
  151.   if (bcred)
  152.     stats.bcred = atoi (bcred);
  153.   if (stats.frate >= 0)
  154.     {
  155.       stats.files = (stats.frate * stats.fstor) + stats.fcred - stats.fretr;
  156.       snprintf (stats.ftext, sizeof(stats.ftext), "%i:1F", stats.frate);
  157.     }
  158.   else
  159.     {
  160.       stats.files = (stats.fstor / (stats.frate * -1))
  161. + stats.fcred - stats.fretr;
  162.       snprintf (stats.ftext, sizeof(stats.ftext), "1:%iF", stats.frate * -1);
  163.     }
  164.   if (stats.brate >= 0)
  165.     {
  166.       stats.bytes = (stats.brate * stats.bstor) + stats.bcred - stats.bretr;
  167.       snprintf (stats.btext, sizeof(stats.btext), "%i:1B", stats.brate);
  168.     }
  169.   else
  170.     {
  171.       stats.bytes = (stats.bstor / (stats.brate * -1))
  172. + stats.bcred - stats.bretr;
  173.       snprintf (stats.btext, sizeof(stats.btext), "1:%iB", stats.brate * -1);
  174.     }
  175. }
  176. MODRET _calc_ratios (cmd_rec * cmd)
  177. {
  178.   modret_t *mr = 0;
  179.   config_rec *c;
  180.   char buf[1024];
  181.   char *mask;
  182.   char **data;
  183.   if (!(g.enable = get_param_int (CURRENT_CONF, "Ratios", FALSE) == TRUE))
  184.     return DECLINED (cmd);
  185.   mr = _dispatch (cmd, "getstats");
  186.   if (MODRET_HASDATA (mr))
  187.     {
  188.       data = mr->data;
  189.       if (data[4])
  190. log_debug (DEBUG4, "ratio: warning: getstats on %s not unique",
  191.    g.user);
  192.       _set_stats (data[0], data[1], data[2], data[3]);
  193.     }
  194.   mr = _dispatch (cmd, "getratio");
  195.   if (MODRET_HASDATA (mr))
  196.     {
  197.       data = mr->data;
  198.       if (data[4])
  199. log_debug (DEBUG4, "ratio: warning: getratio on %s not unique",
  200.    g.user);
  201.       _set_ratios (data[0], data[1], data[2], data[3]);
  202.       g.rtype = "U";
  203.       return DECLINED (cmd);
  204.     }
  205.   c = find_config (CURRENT_CONF, CONF_PARAM, "HostRatio", TRUE);
  206.   while (c)
  207.     {
  208.       mask = buf;
  209.       if (*(char *) c->argv[0] == '.')
  210. {
  211.   *mask++ = '*';
  212.   sstrncpy (mask, c->argv[0], sizeof (buf));
  213. }
  214.       else if (*(char *) (c->argv[0] + (strlen (c->argv[0]) - 1)) == '.')
  215. {
  216.   sstrncpy (mask, c->argv[0], sizeof(buf) - 2);
  217.   sstrcat(buf, "*", sizeof(buf));
  218. }
  219.       else
  220. sstrncpy (mask, c->argv[0], sizeof (buf));
  221.       if (!fnmatch (buf, session.c->remote_name, FNM_NOESCAPE) ||
  222.   !fnmatch (buf, inet_ntoa (*session.c->remote_ipaddr), FNM_NOESCAPE))
  223. {
  224.   _set_ratios (c->argv[1], c->argv[2], c->argv[3], c->argv[4]);
  225.   g.rtype = "h";
  226.   return DECLINED (cmd);
  227. }
  228.       c = find_config_next (c, c->next, CONF_PARAM, "HostRatio", FALSE);
  229.     }
  230.   c = find_config (CURRENT_CONF, CONF_PARAM, "AnonRatio", TRUE);
  231.   while (c)
  232.     {
  233.       if (session.anon_user && !strcmp (c->argv[0], session.anon_user))
  234. {
  235.   _set_ratios (c->argv[1], c->argv[2], c->argv[3], c->argv[4]);
  236.   g.rtype = "a";
  237.   return DECLINED (cmd);
  238. }
  239.       c = find_config_next (c, c->next, CONF_PARAM, "AnonRatio", FALSE);
  240.     }
  241.   c = find_config (CURRENT_CONF, CONF_PARAM, "UserRatio", TRUE);
  242.   while (c)
  243.     {
  244.       if (*(char *) c->argv[0] == '*' || !strcmp (c->argv[0], g.user))
  245. {
  246.   _set_ratios (c->argv[1], c->argv[2], c->argv[3], c->argv[4]);
  247.   g.rtype = "u";
  248.   return DECLINED (cmd);
  249. }
  250.       c = find_config_next (c, c->next, CONF_PARAM, "UserRatio", FALSE);
  251.     }
  252.   c = find_config (CURRENT_CONF, CONF_PARAM, "GroupRatio", TRUE);
  253.   while (c)
  254.     {
  255.       if (!strcmp (c->argv[0], session.group))
  256. {
  257.   _set_ratios (c->argv[1], c->argv[2], c->argv[3], c->argv[4]);
  258.   g.rtype = "g";
  259.   return DECLINED (cmd);
  260. }
  261.       c = find_config_next (c, c->next, CONF_PARAM, "GroupRatio", FALSE);
  262.     }
  263.   return DECLINED (cmd);
  264. }
  265. static void
  266. _log_ratios (cmd_rec * cmd)
  267. {
  268.   char buf[1024];
  269.   snprintf (buf, sizeof(buf), SHORT_RATIO_STUFFS);
  270.   log_debug (DEBUG0, "%s in %s: %s %s%s%s", g.user,
  271.      session.cwd, cmd->argv[0], cmd->arg,
  272.      RATIO_ENFORCE ? " :" : "", RATIO_ENFORCE ? buf : "");
  273. }
  274. MODRET
  275. pre_cmd_retr (cmd_rec * cmd)
  276. {
  277.   char *path;
  278.   int fsize = 0;
  279.   struct stat sbuf;
  280.   _calc_ratios (cmd);
  281.   if (!g.enable)
  282.     return DECLINED (cmd);
  283.   _log_ratios (cmd);
  284.   if (!RATIO_ENFORCE)
  285.     return DECLINED (cmd);
  286.   if (stats.frate && stats.files < 1)
  287.     {
  288.       add_response_err (R_550, g.filemsg);
  289.       add_response_err (R_550,
  290. "%s: FILE RATIO: %s  Down: %i  Up: only %i!",
  291. cmd->arg, stats.ftext, stats.fretr, stats.fstor);
  292.       return ERROR (cmd);
  293.     }
  294.   if (stats.brate)
  295.     {
  296.       path = dir_realpath (cmd->tmp_pool, cmd->arg);
  297.       if (path
  298.   && dir_check (cmd->tmp_pool, cmd->argv[0], cmd->group, path, NULL)
  299.   && fs_stat (path, &sbuf) > -1)
  300. fsize = sbuf.st_size;
  301.       if ((stats.bytes - fsize) < 0)
  302. {
  303.   add_response_err (R_550, g.bytemsg);
  304.   add_response_err (R_550,
  305.     "%s: BYTE RATIO: %s  Down: %i  Up: only %i!",
  306.     cmd->arg, stats.btext, stats.bretr, stats.bstor);
  307.   return ERROR (cmd);
  308. }
  309.     }
  310.   return DECLINED (cmd);
  311. }
  312. MODRET
  313. log_cmd_pass (cmd_rec * cmd)
  314. {
  315.   char buf[120];
  316.   if (session.anon_user)
  317.     sstrncpy (g.user, session.anon_user, sizeof(g.user));
  318.   _calc_ratios (cmd);
  319.   if (g.enable)
  320.     {
  321.       snprintf (buf, sizeof(buf), RATIO_STUFFS);
  322.       log_pri (LOG_NOTICE, "ratio: %s/%s %s[%s]: %s", g.user,
  323.        session.group, session.c->remote_name,
  324.        inet_ntoa (*session.c->remote_ipaddr), buf);
  325.     }
  326.   return DECLINED (cmd);
  327. }
  328. MODRET
  329. pre_cmd (cmd_rec * cmd)
  330. {
  331.   if (g.enable)
  332.     {
  333.       if (!strcasecmp (cmd->argv[0], "STOR"))
  334. _calc_ratios (cmd);
  335.       _log_ratios (cmd);
  336.     }
  337.   return DECLINED (cmd);
  338. }
  339. /* FIXME: Unnecessarily site-specific directive best left undocumented. */
  340. MODRET
  341. cmd_cwd (cmd_rec * cmd)
  342. {
  343.   char *dir;
  344.   config_rec *c = find_config (CURRENT_CONF, CONF_PARAM, "CwdRatioMsg", TRUE);
  345.   if (c)
  346.     {
  347.       dir = dir_realpath (cmd->tmp_pool, cmd->argv[1]);
  348.       while (dir && c)
  349. {
  350.   if (!*((char *) c->argv[0]))
  351.     return DECLINED (cmd);
  352.   add_response (R_250, "%s?user=%s&dir=%s",
  353. c->argv[0], g.user, &dir[1]);
  354.   c = find_config_next (c, c->next, CONF_PARAM, "CwdRatioMsg", FALSE);
  355. }
  356.     }
  357.   return DECLINED (cmd);
  358. }
  359. MODRET
  360. ratio_cmd (cmd_rec * cmd)
  361. {
  362.   char sbuf1[128];
  363.   char sbuf2[128];
  364.   char sbuf3[128];
  365.   if (g.enable)
  366.     {
  367.       int cwding = !strcasecmp (cmd->argv[0], "CWD");
  368.       char *r = (cwding) ? R_250 : R_DUP;
  369.       sbuf1[0] = sbuf2[0] = sbuf3[0] = 0;
  370.       if (cwding || !strcasecmp (cmd->argv[0], "PASS"))
  371. _calc_ratios (cmd);
  372.       snprintf (sbuf1, sizeof(sbuf1), "Down: %iF (%iB)  Up: %iF (%iB)",
  373. stats.fretr, stats.bretr, stats.fstor, stats.bstor);
  374.       if (stats.frate)
  375. snprintf (sbuf2, sizeof(sbuf2), 
  376.   "   %s CR: %i", stats.ftext, stats.files);
  377.       if (stats.brate)
  378. snprintf (sbuf3, sizeof(sbuf3),
  379.   "   %s CR: %i", stats.btext, stats.bytes);
  380.       if (RATIO_ENFORCE)
  381. {
  382.   add_response (r, "%s%s%s", sbuf1, sbuf2, sbuf3);
  383.   if (stats.frate && stats.files < 0)
  384.     add_response (r, g.filemsg);
  385.   if (stats.brate && stats.bytes < 0)
  386.     add_response (r, g.bytemsg);
  387. }
  388.       else
  389. add_response (r, "%s%s%s", sbuf1, g.leechmsg ? "  " : "", g.leechmsg);
  390.     }
  391.   return DECLINED (cmd);
  392. }
  393. MODRET
  394. cmd_site (cmd_rec * cmd)
  395. {
  396.   char buf[128];
  397.   if (!strcasecmp (cmd->argv[1], "RATIO"))
  398.     {
  399.       _calc_ratios (cmd);
  400.       snprintf (buf, sizeof(buf), RATIO_STUFFS);
  401.       add_response (R_214, ""%s" is current ratio.", buf);
  402.       if (stats.frate)
  403. add_response (R_214,
  404.       "Files: %s  Down: %i  Up: %i  CR: %i more file%s",
  405.       stats.ftext, stats.fretr, stats.fstor,
  406.       stats.files, (stats.files != 1) ? "s" : "");
  407.       if (stats.brate)
  408. add_response (R_214,
  409.       "Bytes: %s  Down: %i  Up: %i  CR: %i more byte%s",
  410.       stats.btext, stats.bretr, stats.bstor,
  411.       stats.bytes, (stats.bytes != 1) ? "s" : "");
  412.       return HANDLED (cmd);
  413.     }
  414.   if (!strcasecmp (cmd->argv[1], "HELP"))
  415.     {
  416.       add_response (R_214,
  417.     "The following mod_ratio SITE extensions are recognized.");
  418.       add_response (R_214, "RATIO        " "-- show all ratios in effect");
  419.     }
  420.   return DECLINED (cmd);
  421. }
  422. /* FIXME: because of how ratio and sql interact, the status sent after
  423.    STOR and RETR commands is always out-of-date.  Reorder module loading?  */
  424. MODRET
  425. post_cmd_stor (cmd_rec * cmd)
  426. {
  427.   stats.fstor++;
  428.   stats.bstor += session.xfer.total_bytes;
  429.   _calc_ratios (cmd);
  430.   return ratio_cmd (cmd);
  431. }
  432. MODRET
  433. post_cmd_retr (cmd_rec * cmd)
  434. {
  435.   stats.fretr++;
  436.   stats.bretr += session.xfer.total_bytes;
  437.   _calc_ratios (cmd);
  438.   return ratio_cmd (cmd);
  439. }
  440. MODRET
  441. cmd_user (cmd_rec * cmd)
  442. {
  443.   if (!g.user[0])
  444.     sstrncpy (g.user, cmd->argv[1], ARBITRARY_MAX);
  445.   return DECLINED (cmd);
  446. }
  447. static cmdtable ratio_cmdtab[] = {
  448. /* *INDENT-OFF* */
  449.   { LOG_CMD,  C_PASS, G_NONE, log_cmd_pass,  FALSE, FALSE },
  450.   { PRE_CMD,  C_RETR,   G_NONE, pre_cmd_retr, FALSE, FALSE },
  451.   { PRE_CMD,  C_CWD, G_NONE, pre_cmd,  FALSE, FALSE },
  452.   { PRE_CMD,  C_STOR, G_NONE, pre_cmd,  FALSE, FALSE },
  453.   { PRE_CMD,  C_LIST, G_NONE, pre_cmd,  FALSE, FALSE },
  454.   { PRE_CMD,  C_NLST, G_NONE, pre_cmd,  FALSE, FALSE },
  455.   { CMD,      C_USER, G_NONE, cmd_user,  FALSE, FALSE },
  456.   { CMD,      C_SITE, G_NONE, cmd_site,  FALSE, FALSE },
  457.   { CMD,      C_CWD, G_NONE, cmd_cwd,  FALSE, FALSE },
  458.   { PRE_CMD,  C_CWD, G_NONE, ratio_cmd,  FALSE, FALSE },
  459.   { POST_CMD, C_NOOP, G_NONE, ratio_cmd,  FALSE, FALSE },
  460.   { POST_CMD, C_LIST, G_NONE, ratio_cmd,  FALSE, FALSE },
  461.   { POST_CMD, C_NLST, G_NONE, ratio_cmd,  FALSE, FALSE },
  462.   { POST_CMD, C_PASS, G_NONE, ratio_cmd,  FALSE, FALSE },
  463.   { POST_CMD, C_STOR, G_NONE, post_cmd_stor, FALSE, FALSE },
  464.   { POST_CMD, C_RETR,   G_NONE, post_cmd_retr, FALSE, FALSE },
  465.   { 0, NULL }
  466. /* *INDENT-ON* */
  467. };
  468. /* **************************************************************** */
  469. MODRET
  470. add_ratiodata (cmd_rec * cmd)
  471. {
  472.   CHECK_ARGS (cmd, 5);
  473.   CHECK_CONF (cmd,
  474.       CONF_ROOT | CONF_VIRTUAL | CONF_ANON | CONF_DIR | CONF_GLOBAL);
  475.   add_config_param_str (cmd->argv[0], 5, (void *) cmd->argv[1],
  476. (void *) cmd->argv[2], (void *) cmd->argv[3],
  477. (void *) cmd->argv[4], (void *) cmd->argv[5]);
  478.   return HANDLED (cmd);
  479. }
  480. MODRET
  481. add_ratios (cmd_rec * cmd)
  482. {
  483.   int b;
  484.   config_rec *c;
  485.   CHECK_ARGS (cmd, 1);
  486.   CHECK_CONF (cmd, CONF_ROOT | CONF_VIRTUAL
  487.       | CONF_ANON | CONF_DIR | CONF_GLOBAL);
  488.   b = get_boolean (cmd, 1);
  489.   if (b == -1)
  490.     CONF_ERROR (cmd, "requires a boolean value");
  491.   c = add_config_param ("Ratios", 1, (void *) b);
  492.   c->flags |= CF_MERGEDOWN;
  493.   return HANDLED (cmd);
  494. }
  495. MODRET
  496. add_str (cmd_rec * cmd)
  497. {
  498.   CHECK_ARGS (cmd, 1);
  499.   CHECK_CONF (cmd, CONF_ROOT | CONF_VIRTUAL
  500.       | CONF_ANON | CONF_DIR | CONF_GLOBAL);
  501.   add_config_param_str (cmd->argv[0], 1, (void *) cmd->argv[1]);
  502.   return HANDLED (cmd);
  503. }
  504. static conftable ratio_conftab[] = {
  505. /* *INDENT-OFF* */
  506.   { "UserRatio", add_ratiodata,       NULL },
  507.   { "GroupRatio", add_ratiodata,       NULL },
  508.   { "AnonRatio", add_ratiodata,       NULL },
  509.   { "HostRatio", add_ratiodata,       NULL },
  510.   { "Ratios",         add_ratios,          NULL },
  511.   { "FileRatioErrMsg", add_str,             NULL },
  512.   { "ByteRatioErrMsg", add_str,             NULL },
  513.   { "LeechRatioMsg", add_str,             NULL },
  514.   { "CwdRatioMsg", add_str,             NULL },
  515.   { NULL, NULL, NULL }
  516. /* *INDENT-ON* */
  517. };
  518. /* **************************************************************** */
  519. static int
  520. ratio_child_init ()
  521. {
  522.   memset (&g, 0, sizeof (g));
  523.   g.enable = get_param_int (TOPLEVEL_CONF, "Ratios", FALSE) == TRUE;
  524.   if (!(g.filemsg = get_param_ptr (TOPLEVEL_CONF, "FileRatioErrMsg", FALSE)))
  525.     g.filemsg = "Too few files uploaded to earn file -- please upload more.";
  526.   if (!(g.bytemsg = get_param_ptr (TOPLEVEL_CONF, "ByteRatioErrMsg", FALSE)))
  527.     g.bytemsg = "Too few bytes uploaded to earn more data -- please upload.";
  528.   if (!(g.leechmsg = get_param_ptr (TOPLEVEL_CONF, "LeechRatioMsg", FALSE)))
  529.     g.leechmsg = "[10,000,000:1]  CR: LEECH";
  530.   return 0;
  531. }
  532. module ratio_module = {
  533.   NULL, NULL, /* Always NULL */
  534.   0x20, /* API Version 2.0 */
  535.   "ratio",
  536.   ratio_conftab, /* Ratio configuration handler table */
  537.   ratio_cmdtab, /* Ratio command handler table */
  538.   NULL, /* No authentication handler table */
  539.   NULL, /* No initial initialization needed */
  540.   ratio_child_init /* Post-fork "child mode" init */
  541. };