2009-10-11 14:31:42 +00:00
# include "plugin.h"
# include "log.h"
2005-02-20 14:27:00 +00:00
# include <string.h>
# include <stdlib.h>
# include <stdio.h>
# ifdef HAVE_VALGRIND_VALGRIND_H
2009-10-11 14:31:42 +00:00
# include <valgrind / valgrind.h>
2005-02-20 14:27:00 +00:00
# endif
# ifndef __WIN32
2009-10-11 14:31:42 +00:00
# include <dlfcn.h>
2005-02-20 14:27:00 +00:00
# endif
/*
2006-10-04 13:26:23 +00:00
*
2005-02-20 14:27:00 +00:00
* if you change this enum to add a new callback , be sure
* - that PLUGIN_FUNC_SIZEOF is the last entry
* - that you add PLUGIN_TO_SLOT twice :
2006-10-04 13:26:23 +00:00
* 1. as callback - dispatcher
2005-02-20 14:27:00 +00:00
* 2. in plugins_call_init ( )
2006-10-04 13:26:23 +00:00
*
2005-02-20 14:27:00 +00:00
*/
typedef struct {
PLUGIN_DATA ;
} plugin_data ;
2006-10-04 13:26:23 +00:00
typedef enum {
2005-02-20 14:27:00 +00:00
PLUGIN_FUNC_UNSET ,
2006-10-04 13:26:23 +00:00
PLUGIN_FUNC_HANDLE_URI_CLEAN ,
PLUGIN_FUNC_HANDLE_URI_RAW ,
2005-02-20 14:27:00 +00:00
PLUGIN_FUNC_HANDLE_REQUEST_DONE ,
PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE ,
PLUGIN_FUNC_HANDLE_TRIGGER ,
PLUGIN_FUNC_HANDLE_SIGHUP ,
PLUGIN_FUNC_HANDLE_SUBREQUEST ,
PLUGIN_FUNC_HANDLE_SUBREQUEST_START ,
PLUGIN_FUNC_HANDLE_JOBLIST ,
PLUGIN_FUNC_HANDLE_DOCROOT ,
2005-08-08 09:42:27 +00:00
PLUGIN_FUNC_HANDLE_PHYSICAL ,
2005-02-20 14:27:00 +00:00
PLUGIN_FUNC_CONNECTION_RESET ,
2006-10-04 13:26:23 +00:00
PLUGIN_FUNC_INIT ,
2005-02-20 14:27:00 +00:00
PLUGIN_FUNC_CLEANUP ,
PLUGIN_FUNC_SET_DEFAULTS ,
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
PLUGIN_FUNC_SIZEOF
} plugin_t ;
static plugin * plugin_init ( void ) {
plugin * p ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
p = calloc ( 1 , sizeof ( * p ) ) ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
return p ;
}
static void plugin_free ( plugin * p ) {
int use_dlclose = 1 ;
if ( p - > name ) buffer_free ( p - > name ) ;
# ifdef HAVE_VALGRIND_VALGRIND_H
2005-08-09 06:42:33 +00:00
/*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/
2005-02-20 14:27:00 +00:00
# endif
2006-01-03 12:53:12 +00:00
# ifndef LIGHTTPD_STATIC
2006-10-04 13:26:23 +00:00
if ( use_dlclose & & p - > lib ) {
2005-02-20 14:27:00 +00:00
# ifdef __WIN32
FreeLibrary ( p - > lib ) ;
# else
dlclose ( p - > lib ) ;
# endif
}
2006-01-03 12:53:12 +00:00
# endif
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
free ( p ) ;
}
static int plugins_register ( server * srv , plugin * p ) {
plugin * * ps ;
if ( 0 = = srv - > plugins . size ) {
srv - > plugins . size = 4 ;
srv - > plugins . ptr = malloc ( srv - > plugins . size * sizeof ( * ps ) ) ;
srv - > plugins . used = 0 ;
} else if ( srv - > plugins . used = = srv - > plugins . size ) {
srv - > plugins . size + = 4 ;
srv - > plugins . ptr = realloc ( srv - > plugins . ptr , srv - > plugins . size * sizeof ( * ps ) ) ;
}
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
ps = srv - > plugins . ptr ;
ps [ srv - > plugins . used + + ] = p ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
return 0 ;
}
/**
2006-10-04 13:26:23 +00:00
*
*
*
2005-02-20 14:27:00 +00:00
*/
2006-01-03 12:53:12 +00:00
# ifdef LIGHTTPD_STATIC
int plugins_load ( server * srv ) {
plugin * p ;
# define PLUGIN_INIT(x)\
p = plugin_init ( ) ; \
if ( x # # _plugin_init ( p ) ) { \
log_error_write ( srv , __FILE__ , __LINE__ , " ss " , # x , " plugin init failed " ) ; \
plugin_free ( p ) ; \
return - 1 ; \
} \
plugins_register ( srv , p ) ;
2006-01-04 23:31:32 +00:00
# include "plugin-static.h"
2005-02-20 14:27:00 +00:00
2006-01-03 12:53:12 +00:00
return 0 ;
}
# else
2005-02-20 14:27:00 +00:00
int plugins_load ( server * srv ) {
plugin * p ;
int ( * init ) ( plugin * pl ) ;
const char * error ;
2010-08-05 22:55:18 +00:00
size_t i , j ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
for ( i = 0 ; i < srv - > srvconf . modules - > used ; i + + ) {
data_string * d = ( data_string * ) srv - > srvconf . modules - > data [ i ] ;
char * modules = d - > value - > ptr ;
2006-10-04 13:26:23 +00:00
2010-08-05 22:55:18 +00:00
for ( j = 0 ; j < i ; j + + ) {
if ( buffer_is_equal ( d - > value , ( ( data_string * ) srv - > srvconf . modules - > data [ j ] ) - > value ) ) {
2010-08-11 21:10:15 +00:00
log_error_write ( srv , __FILE__ , __LINE__ , " sbs " , " Cannot load plugin " , d - > value , " more than once, please fix your config (we may not accept such configs in future releases " ) ;
continue ;
2010-08-05 22:55:18 +00:00
}
}
2005-08-29 14:11:47 +00:00
buffer_copy_string_buffer ( srv - > tmp_buf , srv - > srvconf . modules_dir ) ;
2008-07-30 19:38:32 +00:00
buffer_append_string_len ( srv - > tmp_buf , CONST_STR_LEN ( " / " ) ) ;
2005-02-20 14:27:00 +00:00
buffer_append_string ( srv - > tmp_buf , modules ) ;
# if defined(__WIN32) || defined(__CYGWIN__)
2008-07-30 19:38:32 +00:00
buffer_append_string_len ( srv - > tmp_buf , CONST_STR_LEN ( " .dll " ) ) ;
2005-02-20 14:27:00 +00:00
# else
2008-07-30 19:38:32 +00:00
buffer_append_string_len ( srv - > tmp_buf , CONST_STR_LEN ( " .so " ) ) ;
2005-02-20 14:27:00 +00:00
# endif
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
p = plugin_init ( ) ;
# ifdef __WIN32
if ( NULL = = ( p - > lib = LoadLibrary ( srv - > tmp_buf - > ptr ) ) ) {
LPVOID lpMsgBuf ;
FormatMessage (
2006-10-04 13:26:23 +00:00
FORMAT_MESSAGE_ALLOCATE_BUFFER |
2005-02-20 14:27:00 +00:00
FORMAT_MESSAGE_FROM_SYSTEM ,
NULL ,
GetLastError ( ) ,
MAKELANGID ( LANG_NEUTRAL , SUBLANG_DEFAULT ) ,
( LPTSTR ) & lpMsgBuf ,
0 , NULL ) ;
2006-10-04 13:26:23 +00:00
log_error_write ( srv , __FILE__ , __LINE__ , " ssb " , " LoadLibrary() failed " ,
2005-02-20 14:27:00 +00:00
lpMsgBuf , srv - > tmp_buf ) ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
plugin_free ( p ) ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
return - 1 ;
}
2006-10-04 13:26:23 +00:00
# else
2006-10-09 13:50:29 +00:00
if ( NULL = = ( p - > lib = dlopen ( srv - > tmp_buf - > ptr , RTLD_NOW | RTLD_GLOBAL ) ) ) {
2006-10-04 13:26:23 +00:00
log_error_write ( srv , __FILE__ , __LINE__ , " sbs " , " dlopen() failed for: " ,
2005-05-05 08:08:45 +00:00
srv - > tmp_buf , dlerror ( ) ) ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
plugin_free ( p ) ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
return - 1 ;
}
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
# endif
buffer_reset ( srv - > tmp_buf ) ;
buffer_copy_string ( srv - > tmp_buf , modules ) ;
2008-07-30 19:38:32 +00:00
buffer_append_string_len ( srv - > tmp_buf , CONST_STR_LEN ( " _plugin_init " ) ) ;
2005-02-20 14:27:00 +00:00
# ifdef __WIN32
init = GetProcAddress ( p - > lib , srv - > tmp_buf - > ptr ) ;
if ( init = = NULL ) {
LPVOID lpMsgBuf ;
FormatMessage (
2006-10-04 13:26:23 +00:00
FORMAT_MESSAGE_ALLOCATE_BUFFER |
2005-02-20 14:27:00 +00:00
FORMAT_MESSAGE_FROM_SYSTEM ,
NULL ,
GetLastError ( ) ,
MAKELANGID ( LANG_NEUTRAL , SUBLANG_DEFAULT ) ,
( LPTSTR ) & lpMsgBuf ,
0 , NULL ) ;
log_error_write ( srv , __FILE__ , __LINE__ , " sbs " , " getprocaddress failed: " , srv - > tmp_buf , lpMsgBuf ) ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
plugin_free ( p ) ;
return - 1 ;
}
2005-11-11 12:53:45 +00:00
# else
# if 1
2008-04-29 11:03:26 +00:00
init = ( int ( * ) ( plugin * ) ) ( intptr_t ) dlsym ( p - > lib , srv - > tmp_buf - > ptr ) ;
2005-02-20 14:27:00 +00:00
# else
* ( void * * ) ( & init ) = dlsym ( p - > lib , srv - > tmp_buf - > ptr ) ;
2005-11-11 12:53:45 +00:00
# endif
2005-02-20 14:27:00 +00:00
if ( ( error = dlerror ( ) ) ! = NULL ) {
log_error_write ( srv , __FILE__ , __LINE__ , " s " , error ) ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
plugin_free ( p ) ;
return - 1 ;
}
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
# endif
if ( ( * init ) ( p ) ) {
log_error_write ( srv , __FILE__ , __LINE__ , " ss " , modules , " plugin init failed " ) ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
plugin_free ( p ) ;
return - 1 ;
}
#if 0
log_error_write ( srv , __FILE__ , __LINE__ , " ss " , modules , " plugin loaded " ) ;
# endif
plugins_register ( srv , p ) ;
}
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
return 0 ;
}
2006-01-03 12:53:12 +00:00
# endif
2005-02-20 14:27:00 +00:00
# define PLUGIN_TO_SLOT(x, y) \
handler_t plugins_call_ # # y ( server * srv , connection * con ) { \
plugin * * slot ; \
size_t j ; \
if ( ! srv - > plugin_slots ) return HANDLER_GO_ON ; \
slot = ( ( plugin * * * ) ( srv - > plugin_slots ) ) [ x ] ; \
if ( ! slot ) return HANDLER_GO_ON ; \
for ( j = 0 ; j < srv - > plugins . used & & slot [ j ] ; j + + ) { \
plugin * p = slot [ j ] ; \
handler_t r ; \
switch ( r = p - > y ( srv , con , p - > data ) ) { \
case HANDLER_GO_ON : \
break ; \
case HANDLER_FINISHED : \
case HANDLER_COMEBACK : \
case HANDLER_WAIT_FOR_EVENT : \
case HANDLER_WAIT_FOR_FD : \
case HANDLER_ERROR : \
return r ; \
default : \
log_error_write ( srv , __FILE__ , __LINE__ , " sbs " , # x , p - > name , " unknown state " ) ; \
return HANDLER_ERROR ; \
} \
} \
return HANDLER_GO_ON ; \
}
/**
2006-10-04 13:26:23 +00:00
* plugins that use
*
2005-02-20 14:27:00 +00:00
* - server * srv
* - connection * con
* - void * p_d ( plugin_data * )
*/
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_URI_CLEAN , handle_uri_clean )
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_URI_RAW , handle_uri_raw )
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_REQUEST_DONE , handle_request_done )
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE , handle_connection_close )
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_SUBREQUEST , handle_subrequest )
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_SUBREQUEST_START , handle_subrequest_start )
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_JOBLIST , handle_joblist )
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_DOCROOT , handle_docroot )
2005-08-08 09:42:27 +00:00
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_PHYSICAL , handle_physical )
2005-02-20 14:27:00 +00:00
PLUGIN_TO_SLOT ( PLUGIN_FUNC_CONNECTION_RESET , connection_reset )
# undef PLUGIN_TO_SLOT
# define PLUGIN_TO_SLOT(x, y) \
handler_t plugins_call_ # # y ( server * srv ) { \
plugin * * slot ; \
size_t j ; \
if ( ! srv - > plugin_slots ) return HANDLER_GO_ON ; \
slot = ( ( plugin * * * ) ( srv - > plugin_slots ) ) [ x ] ; \
if ( ! slot ) return HANDLER_GO_ON ; \
for ( j = 0 ; j < srv - > plugins . used & & slot [ j ] ; j + + ) { \
plugin * p = slot [ j ] ; \
handler_t r ; \
switch ( r = p - > y ( srv , p - > data ) ) { \
case HANDLER_GO_ON : \
break ; \
case HANDLER_FINISHED : \
case HANDLER_COMEBACK : \
case HANDLER_WAIT_FOR_EVENT : \
case HANDLER_WAIT_FOR_FD : \
case HANDLER_ERROR : \
return r ; \
default : \
log_error_write ( srv , __FILE__ , __LINE__ , " sbsd " , # x , p - > name , " unknown state: " , r ) ; \
return HANDLER_ERROR ; \
} \
} \
return HANDLER_GO_ON ; \
}
/**
2006-10-04 13:26:23 +00:00
* plugins that use
*
2005-02-20 14:27:00 +00:00
* - server * srv
* - void * p_d ( plugin_data * )
*/
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_TRIGGER , handle_trigger )
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_SIGHUP , handle_sighup )
PLUGIN_TO_SLOT ( PLUGIN_FUNC_CLEANUP , cleanup )
PLUGIN_TO_SLOT ( PLUGIN_FUNC_SET_DEFAULTS , set_defaults )
# undef PLUGIN_TO_SLOT
2006-10-04 13:26:23 +00:00
#if 0
2005-02-20 14:27:00 +00:00
/**
2006-10-04 13:26:23 +00:00
*
2005-02-20 14:27:00 +00:00
* special handler
2006-10-04 13:26:23 +00:00
*
2005-02-20 14:27:00 +00:00
*/
handler_t plugins_call_handle_fdevent ( server * srv , const fd_conn * fdc ) {
size_t i ;
plugin * * ps ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
ps = srv - > plugins . ptr ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
for ( i = 0 ; i < srv - > plugins . used ; i + + ) {
plugin * p = ps [ i ] ;
if ( p - > handle_fdevent ) {
handler_t r ;
switch ( r = p - > handle_fdevent ( srv , fdc , p - > data ) ) {
case HANDLER_GO_ON :
break ;
case HANDLER_FINISHED :
case HANDLER_COMEBACK :
case HANDLER_WAIT_FOR_EVENT :
case HANDLER_ERROR :
return r ;
default :
log_error_write ( srv , __FILE__ , __LINE__ , " d " , r ) ;
break ;
}
}
}
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
return HANDLER_GO_ON ;
}
# endif
/**
2006-10-04 13:26:23 +00:00
*
2005-02-20 14:27:00 +00:00
* - call init function of all plugins to init the plugin - internals
* - added each plugin that supports has callback to the corresponding slot
2006-10-04 13:26:23 +00:00
*
2005-02-20 14:27:00 +00:00
* - is only called once .
*/
handler_t plugins_call_init ( server * srv ) {
size_t i ;
plugin * * ps ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
ps = srv - > plugins . ptr ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
/* fill slots */
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
srv - > plugin_slots = calloc ( PLUGIN_FUNC_SIZEOF , sizeof ( ps ) ) ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
for ( i = 0 ; i < srv - > plugins . used ; i + + ) {
size_t j ;
/* check which calls are supported */
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
plugin * p = ps [ i ] ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
# define PLUGIN_TO_SLOT(x, y) \
if ( p - > y ) { \
plugin * * slot = ( ( plugin * * * ) ( srv - > plugin_slots ) ) [ x ] ; \
if ( ! slot ) { \
slot = calloc ( srv - > plugins . used , sizeof ( * slot ) ) ; \
( ( plugin * * * ) ( srv - > plugin_slots ) ) [ x ] = slot ; \
} \
for ( j = 0 ; j < srv - > plugins . used ; j + + ) { \
if ( slot [ j ] ) continue ; \
slot [ j ] = p ; \
break ; \
} \
2006-10-04 13:26:23 +00:00
}
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_URI_CLEAN , handle_uri_clean ) ;
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_URI_RAW , handle_uri_raw ) ;
2005-02-20 14:27:00 +00:00
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_REQUEST_DONE , handle_request_done ) ;
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE , handle_connection_close ) ;
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_TRIGGER , handle_trigger ) ;
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_SIGHUP , handle_sighup ) ;
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_SUBREQUEST , handle_subrequest ) ;
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_SUBREQUEST_START , handle_subrequest_start ) ;
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_JOBLIST , handle_joblist ) ;
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_DOCROOT , handle_docroot ) ;
2005-08-08 09:42:27 +00:00
PLUGIN_TO_SLOT ( PLUGIN_FUNC_HANDLE_PHYSICAL , handle_physical ) ;
2005-02-20 14:27:00 +00:00
PLUGIN_TO_SLOT ( PLUGIN_FUNC_CONNECTION_RESET , connection_reset ) ;
PLUGIN_TO_SLOT ( PLUGIN_FUNC_CLEANUP , cleanup ) ;
PLUGIN_TO_SLOT ( PLUGIN_FUNC_SET_DEFAULTS , set_defaults ) ;
# undef PLUGIN_TO_SLOT
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
if ( p - > init ) {
if ( NULL = = ( p - > data = p - > init ( ) ) ) {
2006-10-04 13:26:23 +00:00
log_error_write ( srv , __FILE__ , __LINE__ , " sb " ,
2005-02-20 14:27:00 +00:00
" plugin-init failed for module " , p - > name ) ;
return HANDLER_ERROR ;
}
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
/* used for con->mode, DIRECT == 0, plugins above that */
( ( plugin_data * ) ( p - > data ) ) - > id = i + 1 ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
if ( p - > version ! = LIGHTTPD_VERSION_ID ) {
2006-10-04 13:26:23 +00:00
log_error_write ( srv , __FILE__ , __LINE__ , " sb " ,
2005-02-20 14:27:00 +00:00
" plugin-version doesn't match lighttpd-version for " , p - > name ) ;
return HANDLER_ERROR ;
}
} else {
p - > data = NULL ;
}
}
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
return HANDLER_GO_ON ;
}
void plugins_free ( server * srv ) {
size_t i ;
plugins_call_cleanup ( srv ) ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
for ( i = 0 ; i < srv - > plugins . used ; i + + ) {
plugin * p = ( ( plugin * * ) srv - > plugins . ptr ) [ i ] ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
plugin_free ( p ) ;
}
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
for ( i = 0 ; srv - > plugin_slots & & i < PLUGIN_FUNC_SIZEOF ; i + + ) {
plugin * * slot = ( ( plugin * * * ) ( srv - > plugin_slots ) ) [ i ] ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
if ( slot ) free ( slot ) ;
}
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
free ( srv - > plugin_slots ) ;
srv - > plugin_slots = NULL ;
2006-10-04 13:26:23 +00:00
2005-02-20 14:27:00 +00:00
free ( srv - > plugins . ptr ) ;
srv - > plugins . ptr = NULL ;
2005-09-03 03:08:13 +00:00
srv - > plugins . used = 0 ;
2005-02-20 14:27:00 +00:00
}