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

Ftp客户端

开发平台:

Unix_Linux

  1. /*
  2.  * ProFTPD - FTP server daemon
  3.  * Copyright (c) 1997, 1998 Public Flood Software
  4.  *  
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
  18.  */
  19. /*
  20.  * Module handling routines
  21.  */
  22. #include "conf.h"
  23. /* local symbol hash structure to vastly speed up module symbol lookups
  24.  */
  25. #define HASH_TABLE_SIZE 40
  26. #define SYM_CONF 1
  27. #define SYM_CMD 2
  28. #define SYM_AUTH 3
  29. struct symbol_hash {
  30.   struct symbol_hash *next,*prev;
  31.   char *sym_name; /* pointer to the directive, 
  32.                                                    command, or other symbol */
  33.   char sym_type; /* one of the SYM_* macros */
  34.   module *sym_module;
  35.   union {
  36.     conftable *sym_conf;
  37.     cmdtable    *sym_cmd;
  38.     authtable *sym_auth;
  39.     void *sym_generic;
  40.   } ptr;
  41. };
  42. static xaset_t *symtable[HASH_TABLE_SIZE];
  43. static xaset_t *installed_modules = NULL;
  44. static array_header *mconfarr; /* masterconf array */
  45. static array_header *mcmdarr; /* mastercmd array */
  46. static array_header *mautharr; /* masterauth array */
  47. conftable *m_conftable;  /* Master conf table */
  48. cmdtable *m_cmdtable; /* Master cmd table */
  49. authtable *m_authtable; /* Master auth table */
  50. module *curmodule = NULL; /* Current running module */
  51. extern module *static_modules[];
  52. /* hash lookup code and management */
  53. static int _compare_sym(struct symbol_hash *s1, struct symbol_hash *s2)
  54. {
  55.   int ret;
  56.   ret = strcmp(s1->sym_name,s2->sym_name);
  57.   /* higher priority modules must go BEFORE lower priority in the
  58.    * hash tables.
  59.    */
  60.   if(!ret) {
  61.     if(s1->sym_module->priority > s2->sym_module->priority)
  62.       ret = -1;
  63.     else if(s1->sym_module->priority < s2->sym_module->priority)
  64.       ret = 1;
  65.   }
  66.   return ret;
  67. }
  68. static int _hash_index(char *name)
  69. {
  70.   unsigned char *cp;
  71.   int total = 0;
  72.   for(cp = (unsigned char*)name; *cp; cp++)
  73.     total += (int)*cp;
  74.   return (total < HASH_TABLE_SIZE ? total : (total % HASH_TABLE_SIZE));
  75. }
  76. static int _hash_insert(struct symbol_hash *sym)
  77. {
  78.   int index;
  79.   index = _hash_index(sym->sym_name);
  80.   if(!symtable[index])
  81.     symtable[index] = xaset_create(permanent_pool,
  82.                       (XASET_COMPARE)_compare_sym);
  83.   xaset_insert_sort(symtable[index],(xasetmember_t*)sym,TRUE);
  84.   return index;
  85. }
  86. static int _hash_insert_conf(conftable *conf)
  87. {
  88.   struct symbol_hash *sym;
  89.   sym = palloc(permanent_pool,sizeof(struct symbol_hash));
  90.   sym->sym_type = SYM_CONF;
  91.   sym->sym_name = conf->directive;
  92.   sym->ptr.sym_conf = conf;
  93.   sym->sym_module = conf->m;
  94.   return _hash_insert(sym);
  95. }
  96. static int _hash_insert_cmd(cmdtable *cmd)
  97. {
  98.   struct symbol_hash *sym;
  99.   sym = palloc(permanent_pool,sizeof(struct symbol_hash));
  100.   sym->sym_type = SYM_CMD;
  101.   sym->sym_name = cmd->command;
  102.   sym->ptr.sym_cmd = cmd;
  103.   sym->sym_module = cmd->m;
  104.   return _hash_insert(sym);
  105. }
  106. static int _hash_insert_auth(authtable *auth)
  107. {
  108.   struct symbol_hash *sym;
  109.   sym = pcalloc(permanent_pool,sizeof(struct symbol_hash));
  110.   sym->sym_type = SYM_AUTH;
  111.   sym->sym_name = auth->name;
  112.   sym->ptr.sym_auth = auth;
  113.   sym->sym_module = auth->m;
  114.   return _hash_insert(sym);
  115. }
  116. static struct symbol_hash *_hash_find(int index, char *name, int type)
  117. {
  118.   struct symbol_hash *sym = NULL;
  119.   if(name && symtable[index]) {
  120.     for(sym = (struct symbol_hash*)symtable[index]->xas_list; sym; sym=sym->next)
  121.       if(sym->sym_type == type && !strcmp(sym->sym_name,name))
  122.         break;
  123.   }
  124.   return sym;
  125. }
  126. static struct symbol_hash *_hash_find_next(int index, char *name,
  127.                                            int type, void *last)
  128. {
  129.   struct symbol_hash *sym = NULL;
  130.   int last_hit = 0;
  131.   if(symtable[index]) {
  132.     for(sym = (struct symbol_hash*)symtable[index]->xas_list; sym; sym=sym->next) {
  133.       if(last_hit && sym->sym_type == type && !strcmp(sym->sym_name,name))
  134.         break;
  135.       if(sym->ptr.sym_generic == last)
  136.         last_hit++;
  137.     }
  138.   }
  139.   return sym;
  140. }
  141. conftable *mod_find_conf_symbol(char *name, int *idx_cache, conftable *last)
  142. {
  143.   int index;
  144.   struct symbol_hash *sym;
  145.   if(idx_cache && *idx_cache != -1)
  146.     index = *idx_cache;
  147.   else {
  148.     index = _hash_index(name);
  149.     if(idx_cache)
  150.       *idx_cache = index;
  151.   }
  152.   if(last)
  153.     sym = _hash_find_next(index,name,SYM_CONF,last);
  154.   else
  155.     sym = _hash_find(index,name,SYM_CONF);
  156.   return (sym ? sym->ptr.sym_conf : NULL);
  157. }
  158. cmdtable *mod_find_cmd_symbol(char *name, int *idx_cache, cmdtable *last)
  159. {
  160.   int index;
  161.   struct symbol_hash *sym;
  162.   
  163.   if(idx_cache && *idx_cache != -1)
  164.     index = *idx_cache;
  165.   else {
  166.     index = _hash_index(name);
  167.     if(idx_cache)
  168.       *idx_cache = index;
  169.   }
  170.   if(last)
  171.     sym = _hash_find_next(index,name,SYM_CMD,last);
  172.   else
  173.     sym = _hash_find(index,name,SYM_CMD);
  174.   return (sym ? sym->ptr.sym_cmd : NULL);
  175. }
  176. authtable *mod_find_auth_symbol(char *name, int *idx_cache, authtable *last)
  177. {
  178.   int index;
  179.   struct symbol_hash *sym;
  180.   
  181.   if(idx_cache && *idx_cache != -1)
  182.     index = *idx_cache;
  183.   else {
  184.     index = _hash_index(name);
  185.     if(idx_cache)
  186.       *idx_cache = index;
  187.   }
  188.   if(last)
  189.     sym = _hash_find_next(index,name,SYM_AUTH,last);
  190.   else
  191.     sym = _hash_find(index,name,SYM_AUTH);
  192.   return (sym ? sym->ptr.sym_auth : NULL);
  193. }
  194. /* functions to manage modular privdata structure inside cmd_rec */
  195. privdata_t *mod_privdata_alloc(cmd_rec *cmd, char *tag, int size)
  196. {
  197.   privdata_t **pp;
  198.   privdata_t *p;
  199.   if(!tag)
  200.     return NULL;
  201.   p = pcalloc(cmd->pool,sizeof(privdata_t));
  202.   p->tag = pstrdup(cmd->pool,tag);
  203.   if(size)
  204.     p->value.ptr_val = palloc(cmd->pool,size);
  205.   p->m = curmodule;
  206.   if(!cmd->privarr)
  207.     cmd->privarr = make_array(cmd->pool,2,sizeof(privdata_t*));
  208.   pp = (privdata_t**)push_array(cmd->privarr);
  209.   *pp = p;
  210.   cmd->private = (privdata_t*)cmd->privarr->elts;
  211.   return p;
  212. }
  213. privdata_t *mod_privdata_find(cmd_rec *cmd, char *tag, module *m)
  214. {
  215.   int i;
  216.   privdata_t **p;
  217.   if(!tag)
  218.     return NULL;
  219.   if(!m)
  220.     m = curmodule;
  221.   for(i = 0, p = (privdata_t**)cmd->privarr->elts; i < cmd->privarr->nelts; i++, p++) {
  222.     if(!strcmp((*p)->tag,tag) && (m == ANY_MODULE || (*p)->m == m))
  223.       break;
  224.   }
  225.   return (i < cmd->privarr->nelts ? *p : NULL);
  226. }
  227. modret_t *call_module_auth(module *m, modret_t *(*func)(cmd_rec*), cmd_rec *cmd)
  228. {
  229.   modret_t *res;
  230.   module *prev_module = curmodule;
  231.   if(!cmd->tmp_pool)
  232.     cmd->tmp_pool = make_named_sub_pool(cmd->pool,"temp - auth module call");
  233.   curmodule = m;
  234.   res = func(cmd);
  235.   curmodule = prev_module;
  236.   return res;
  237. }
  238. modret_t *call_module_cmd(module *m, modret_t *(*func)(cmd_rec*), cmd_rec *cmd)
  239. {
  240.   modret_t *res;
  241.   module *prev_module = curmodule;
  242.   if(!cmd->tmp_pool)
  243.     cmd->tmp_pool = make_named_sub_pool(cmd->pool,"temp - cmd module call");
  244.   curmodule = m;
  245.   res = func(cmd);
  246.   curmodule = prev_module;
  247.   return res;
  248. }
  249. modret_t *call_module(module *m, modret_t *(*func)(cmd_rec*), cmd_rec *cmd)
  250. {
  251.   modret_t *res;
  252.   module *prev_module = curmodule;
  253.   if(!cmd->tmp_pool)
  254.     cmd->tmp_pool = make_named_sub_pool(cmd->pool,"temp - generic module call");
  255.   
  256.   curmodule = m;
  257.   res = func(cmd);
  258.   curmodule = prev_module;
  259.   /* Note that we don't clear the pool here because the function may
  260.    * return data which resides in this pool.
  261.    */
  262.   return res;
  263. }
  264. modret_t *mod_create_data(cmd_rec *cmd,void *d)
  265. {
  266.   modret_t *ret;
  267.   ret = pcalloc(cmd->tmp_pool,sizeof(modret_t));
  268.   ret->data = d;
  269.   return ret;
  270. }
  271. modret_t *mod_create_ret(cmd_rec *cmd,unsigned char err,char *n,char *m)
  272. {
  273.   modret_t *ret;
  274.   ret = pcalloc(cmd->tmp_pool,sizeof(modret_t));
  275.   ret->mr_handler_module = curmodule;
  276.   ret->mr_error = err;
  277.   if(n)
  278.     ret->mr_numeric = pstrdup(cmd->tmp_pool,n);
  279.   if(m)
  280.     ret->mr_message = pstrdup(cmd->tmp_pool,m);
  281.   return ret;
  282. }
  283. modret_t *mod_create_error(cmd_rec *cmd,int mr_errno)
  284. {
  285.   modret_t *ret;
  286.   ret = pcalloc(cmd->tmp_pool,sizeof(modret_t));
  287.   ret->mr_handler_module = curmodule;
  288.   ret->mr_error = mr_errno;
  289.   return ret;
  290. }
  291. /* Called after forking in order to inform/initialize modules
  292.  * need to know we are a child and have a connection.
  293.  */
  294. int init_child_modules()
  295. {
  296.   module *prev_module = curmodule;
  297.   module *m;
  298.   for(m = (module*)installed_modules->xas_list; m; m=m->next)
  299.     if(m && m->module_init_child) {
  300.       curmodule = m;
  301.       m->module_init_child();
  302.     }
  303.   
  304.   curmodule = prev_module;
  305.   return 0;
  306. }
  307. void list_modules()
  308. {
  309.   int i;
  310.   module *m;
  311.   printf("Compiled-in modules:n");
  312.   for(i = 0; static_modules[i]; i++)
  313.   {
  314.     m = static_modules[i];
  315.     printf("  mod_%s.cn",m->name);
  316.   }
  317. }
  318. int init_modules()
  319. {
  320.   int i,numconf = 0,numcmd = 0,numauth = 0;
  321.   module *m;
  322.   conftable *c,*wrk;
  323.   cmdtable *cmd,*cmdwrk;
  324.   authtable *auth,*authwrk;
  325.   bzero(symtable,sizeof(symtable));
  326.   installed_modules = xaset_create(permanent_pool,NULL);
  327.   for(i = 0; static_modules[i]; i++)
  328.   {
  329.     m = static_modules[i];
  330.     m->priority = i;
  331.     if(m->ver < 0x20) {
  332. log_pri(LOG_ERR,"Fatal: module '%s' API version (0x%x) is "
  333.                 "too old (need at least 0x%x).",m->name,m->ver,0x20);
  334. exit(1);
  335.     }
  336.     if(!m->module_init ||
  337.        (m->module_init() != -1)) {
  338.       xaset_insert(installed_modules,(xasetmember_t*)m);
  339.       if(m->conftable)
  340.         for(c = m->conftable; c->directive; c++)
  341.           ++numconf;
  342.       if(m->cmdtable)
  343.         for(cmd = m->cmdtable; cmd->command; cmd++)
  344.           ++numcmd;
  345.       if(m->authtable)
  346.         for(auth = m->authtable; auth->name; auth++)
  347.           ++numauth;
  348.     }
  349.   }
  350.   /* Allow for an empty entry */
  351.   ++numconf;
  352.   ++numcmd;
  353.   ++numauth;
  354.   /* Create an array to store the master conf dispatch table */
  355.   mconfarr = make_array(permanent_pool,numconf,sizeof(conftable));
  356.   mcmdarr = make_array(permanent_pool,numcmd,sizeof(cmdtable));
  357.   mautharr = make_array(permanent_pool,numauth,sizeof(authtable));
  358.   for(m = (module*)installed_modules->xas_list; m; m=m->next) {
  359.     if(m->conftable)
  360.       for(c = m->conftable; c->directive; c++) {
  361.         wrk = (conftable*)push_array(mconfarr);
  362.         memcpy(wrk,c,sizeof(conftable));
  363.         wrk->m = m;
  364.         /* insert into our hash table */
  365.         _hash_insert_conf(wrk);
  366.       }
  367.     if(m->cmdtable)
  368.       for(cmd = m->cmdtable; cmd->command; cmd++) {
  369.         cmdwrk = (cmdtable*)push_array(mcmdarr);
  370.         memcpy(cmdwrk,cmd,sizeof(cmdtable));
  371.         cmdwrk->m = m;
  372.         _hash_insert_cmd(cmdwrk);
  373.       }
  374.     if(m->authtable)
  375.       for(auth = m->authtable; auth->name; auth++) {
  376.         authwrk = (authtable*)push_array(mautharr);
  377.         memcpy(authwrk,auth,sizeof(authtable));
  378.         authwrk->m = m;
  379.         _hash_insert_auth(authwrk);
  380.       }
  381.   }
  382.  
  383.   /* add a null entry (pcalloc zeros the memory for us) */
  384.   push_array(mconfarr);  
  385.   push_array(mcmdarr);
  386.   push_array(mautharr);
  387.   m_conftable = (conftable*)mconfarr->elts;
  388.   m_cmdtable = (cmdtable*)mcmdarr->elts;
  389.   m_authtable = (authtable*)mautharr->elts;
  390.   return 0;
  391. }