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

Ftp客户端

开发平台:

Unix_Linux

  1. /*
  2.  * The following is an *EXAMPLE* ProFTPD module.  While it can be compiled
  3.  * in to ProFTPD, it is not by default, and doesn't really do anything all
  4.  * that terribly functional.
  5.  */
  6. /*
  7.  * ProFTPD - FTP server daemon
  8.  * Copyright (c) 1997, 1998 Public Flood Software
  9.  *  
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
  23.  */
  24. /*
  25.  * sample module for ProFTPD
  26.  * $Id: mod_sample.c,v 1.3 1999/09/12 16:30:01 macgyver Exp $
  27.  */
  28. #include "conf.h"
  29. /* This sample configuration directive handler will get called
  30.  * whenever the "FooBarDirective" directive is encountered in the
  31.  * configuration file.
  32.  */
  33. MODRET add_foobardirective(cmd_rec *cmd)
  34. {
  35.   int b;
  36.   config_rec *c;
  37.   /* The CHECK_ARGS macro checks the number of arguments passed to the
  38.    * directive against what we want.  Note that this is *one* less than
  39.    * cmd->argc, because cmd->argc includes cmd->argv[0] (the directive
  40.    * itself).  If CHECK_ARGS fails, a generic error is sent to the user
  41.    */
  42.   CHECK_ARGS(cmd,1);
  43.   /* The CHECK_CONF macro makes sure that this directive is not being
  44.    * "used" in the wrong context (i.e. if the directive is only available
  45.    * or applicable inside certain contexts).  In this case, we are allowing
  46.    * the directive inside of <Anonymous> and <Limit>, but nowhere else.
  47.    * If this macro fails a generic error is logged and the handler aborts.
  48.    */
  49.   CHECK_CONF(cmd,CONF_ANON|CONF_LIMIT);
  50.   b = get_boolean(cmd,1);
  51.   if(b == -1) /* get_boolean couldn't find a */
  52.     CONF_ERROR(cmd,                     /* valid boolean value         */
  53.     "requires a boolean value");
  54.   /* add_config_param adds a configuration paramater to our current
  55.    * configuration context.
  56.    */
  57.   c = add_config_param("FooBarDirective",1,(void*)b);
  58.   /* By adding the CF_MERGEDOWN flag to the parameter we just created
  59.    * we are telling proftpd that this parameter should be copied and
  60.    * "merged" into all "lower" contexts until it either hits a
  61.    * parameter w/ the same name or bottoms out.
  62.    *
  63.    * Example _without_ CF_MERGEDOWN:
  64.    *
  65.    * <VirtualHost>
  66.    *      |----------
  67.    *             <Anonymous>
  68.    *                 | - FooBarDirective  <------- Config places it here
  69.    *                 |-----------
  70.    *                         <Directory>  <------- Doesn't apply here
  71.    *                             |-------------
  72.    *                                        <Limit> <--- Or here.....
  73.    *
  74.    * Now, if we specify CF_MERGDOWN, the tree ends up looking like:
  75.    *
  76.    * <VirtualHost>
  77.    *      |----------
  78.    *             <Anonymous>
  79.    *                 | - FooBarDirective  <------- Config places it here
  80.    *                 |-----------
  81.    *                         <Directory>  <------- Now, it DOES apply here
  82.    *                             | - FooBarDirective
  83.    *                             |-------------
  84.    *                                        <Limit> <-------- And here ...
  85.    *                                           | - FooBarDirective
  86.    *
  87.    */
  88.   c->flags |= CF_MERGEDOWN;
  89.   /* Tell proftpd that we handled the request w/ no problems.
  90.    */
  91.   return HANDLED(cmd);
  92. }
  93. /* Example of a PRE_CMD handler here, which simply logs all received
  94.  * commands via log_debug().  We are careful to return DECLINED, otherwise
  95.  * other PRE_CMD handlers wouldn't get the request.  Note that in order
  96.  * for this to work properly, this module would need to be loaded _last_,
  97.  * or after any other modules which don't return DECLINED for all
  98.  * their precmds.  In practice you should always return DECLINED unless
  99.  * you plan on having your module actually handle the command (or
  100.  * deny it).
  101.  */
  102. MODRET pre_cmd(cmd_rec *cmd)
  103. {
  104.   log_debug(DEBUG0,"RECEIVED: command '%s', arguments '%s'.",
  105.             cmd->argv[0],cmd->arg);
  106.   return DECLINED(cmd);
  107. }
  108. /* Next, an example of a LOG_CMD handler, which receives all commands
  109.  * _after_ they have been processed, and additional only IF they were
  110.  * successful.
  111.  */
  112. MODRET log_cmd(cmd_rec *cmd)
  113. {
  114.   log_debug(DEBUG0,"SUCCESSFUL: command '%s', arguments '%s'.",
  115.             cmd->argv[0],cmd->arg);
  116.   return DECLINED(cmd);
  117. }
  118. /* Now, a _slightly_ more useful handler.  We define POST_CMD handlers
  119.  * for RETR, STOR and LIST/NLST, so we can calculate total data transfer
  120.  * for a session.
  121.  */
  122. static unsigned long total_rx = 0, total_tx = 0;
  123. MODRET post_cmd_retr(cmd_rec *cmd)
  124. {
  125.   /* The global variable 'session' contains lots of important data after
  126.    * a file/directory transfer of any kind.  It doesn't get cleared until
  127.    * mod_xfer gets a LOG_CMD, so we can still get to it here.
  128.    */
  129.   total_tx += session.xfer.total_bytes;
  130.   return DECLINED(cmd);
  131. }
  132. MODRET post_cmd_stor(cmd_rec *cmd)
  133. {
  134.   total_rx += session.xfer.total_bytes;
  135.   return DECLINED(cmd);
  136. }
  137. MODRET post_cmd_list(cmd_rec *cmd)
  138. {
  139.   return post_cmd_retr(cmd);
  140. }
  141. MODRET post_cmd_nlst(cmd_rec *cmd)
  142. {
  143.   return post_cmd_retr(cmd);
  144. }
  145. MODRET cmd_xfoo(cmd_rec *cmd)
  146. {
  147.   char *path;
  148.   if(cmd->argc < 2)
  149.     return ERROR_MSG(cmd,R_500,"XFOO command needs at least one argument");
  150.   path = dir_realpath(cmd->tmp_pool,cmd->arg);
  151.   if(!path) {
  152.     add_response_err(R_500,"It appears that '%s' does not exist.",cmd->arg);
  153.     return ERROR(cmd);
  154.   }
  155.   add_response_err(R_200,"XFOO command successful (yeah right!)");
  156.   return HANDLED(cmd);
  157. }
  158. /* There are three tables which act as the "glue" between proftpd and
  159.  * a module.  None of the tables are _required_ (however having none would
  160.  * make the module fairly useless).
  161.  */
  162. /* The first table is the "configuration directive" table.  It specifies
  163.  * handler routines in the module which will be used during configuration
  164.  * file parsing.
  165.  */
  166. static conftable sample_config[] = {
  167.   { "FooBarDirective", add_foobardirective,                 },
  168.   { NULL }
  169. };
  170. /* Each module can supply up to two initialization routines (via
  171.  * the module structure at the bottom of this file).  The first
  172.  * init function is called immediately after the module is loaded,
  173.  * while the second is called after proftpd is connected to a client,
  174.  * and the main proftpd server (if not in inetd mode) has forked off.
  175.  * The second init function's purpose is to let the module perform
  176.  * any necessary work once a client is connected and proftpd is ready
  177.  * to service the new client.  In inetd mode, the "child init" function
  178.  * will be called immediately after proftpd is loaded, because proftpd
  179.  * is _always_ in "child mode" when run from inetd.  Note that both
  180.  * of these initialization routines are optional.  If you don't need
  181.  * them (or only need one), simply set the function pointer to NULL
  182.  * in the module structure.
  183.  */
  184. static int sample_init()
  185. {
  186.   /* do something useful here, right? */
  187.   return 0;
  188. }
  189. static int sample_child_init()
  190. {
  191.   /* same here */
  192.   return 0;
  193. }
  194. /* command table ...
  195.  * first  : command "type" (see the doc/API for more info)
  196.  *
  197.  * second : command "name", or the actual null-terminated ascii text
  198.  *          sent by a client (in uppercase) for this command.  see
  199.  *          include/ftp.h for macros which define all rfced FTP protocol
  200.  *          commands.  Can also be the special macro C_ANY, which receives
  201.  *          ALL commands.
  202.  *
  203.  * third  : command "group" (used for access control via Limit directives),
  204.  *          this can be either G_DIRS (for commands related to directory
  205.  *          listing), G_READ (for commands related to reading files), 
  206.  *          G_WRITE (for commands related to file writing), or the
  207.  *          special G_NONE for those commands against which the
  208.  *          special <Limit READ|WRITE|DIRS> will not be applied.
  209.  *
  210.  * fourth : function pointer to your handler
  211.  *
  212.  * fifth  : TRUE if the command cannot be used before authentication
  213.  *          (via USER/PASS), otherwise FALSE.
  214.  *
  215.  * sixth  : TRUE if the command can be sent during a file transfer
  216.  *          (note: as of 1.1.5, this is obsolete)
  217.  *
  218.  */
  219. cmdtable sample_commands[] = {
  220.   { PRE_CMD, C_ANY, G_NONE, pre_cmd,  FALSE, FALSE },
  221.   { LOG_CMD, C_ANY, G_NONE, log_cmd,  FALSE, FALSE },
  222.   { POST_CMD, C_RETR, G_NONE, post_cmd_retr, FALSE, FALSE },
  223.   { POST_CMD, C_STOR, G_NONE, post_cmd_stor, FALSE, FALSE },
  224.   { POST_CMD, C_APPE, G_NONE, post_cmd_stor, FALSE, FALSE },
  225.   { POST_CMD, C_LIST, G_NONE, post_cmd_list, FALSE, FALSE },
  226.   { POST_CMD, C_NLST, G_NONE, post_cmd_nlst, FALSE, FALSE },
  227.   { CMD, "XFOO", G_DIRS, cmd_xfoo, TRUE,  FALSE },
  228.   { 0, NULL }
  229. };
  230. module sample_module = {
  231.   NULL,NULL, /* Always NULL */
  232.   0x20, /* API Version 2.0 */
  233.   "sample",
  234.   sample_config, /* Sample configuration handler table */
  235.   sample_commands, /* Sample command handler table */
  236.   NULL, /* No authentication handler table */
  237.   sample_init, /* Initialization function */
  238.   sample_child_init /* Post-fork "child mode" init */
  239. };