summaryrefslogtreecommitdiff
path: root/src/modl.cpp
blob: ca620ce5bc2399bfee10161e73e8976910faf3df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#ifndef MODL_CPP 

#define MODL_CPP

#include <limits.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <stdio.h>

#include "modl.h"
#include "tool/dir.h"

using namespace std;

modl::modl(  ) : smap<dynmod*,string>(HMAPOCC)
{
#ifdef NCURSES
    print_cached( 0 );
#endif
    
    if ( wrap::CONF->get_elem( "httpd.modules.preloadcommands" ).compare( "true" ) == 0 )
     preload_modules( wrap::CONF->get_elem("httpd.modules.commandsdir") );

    if ( wrap::CONF->get_elem( "httpd.modules.preloadhtml" ).compare( "true" ) == 0 )
     preload_modules( wrap::CONF->get_elem("httpd.modules.htmldir") );
}

modl::~modl()
{
    // dlclose all the_module's first!
    run_func( &modl::dlclose_ );

    // then clean the hash map.
    unload_modules(); 
}

void
modl::preload_modules( string s_path )
{
 dir* p_dir = new dir();
 p_dir->open_dir( s_path );

 p_dir->read_dir();
 
 vector<string> dir_vec = p_dir->get_dir_vec();

 if ( ! dir_vec.empty() ) 
 {
  vector<string>::iterator iter = dir_vec.begin();

  do
  {
   if ( iter->length() >= 3 && iter->compare( iter->length()-3, 3, ".so" ) == 0 )
    cache_module( s_path + *iter );
  }
  while ( ++iter != dir_vec.end() );
 }

 dir_vec.clear();

 // This also closes the dir.
 delete p_dir;
}

void
modl::dlclose_( dynmod* mod )
{
    dlclose( mod->the_module );
    free   ( mod );
}

dynmod*
modl::cache_module( string s_name )
{
    void     *the_module = NULL;
    function *the_func   = NULL;

    the_module = dlopen( s_name.c_str(), RTLD_LAZY );
    //the_module = dlopen( s_name.c_str(), RTLD_NOW );

    if ( the_module == NULL )
    {
        wrap::system_message( dlerror() );
        return NULL;
    }

    the_func = (function*) dlsym( the_module, "extern_function" );

    if ( the_func == NULL )
    {
        wrap::system_message( dlerror() );
        return NULL;
    }

    wrap::system_message( MODULEC + s_name.substr( s_name.find_last_of("/")+1 ) ); 


    dynmod *mod     = new dynmod; // encapsulates the function and module handler.
    mod->the_func   = the_func  ; // the function to execute
    mod->the_module = the_module; // the module handler to close if function

    // is not needed anymore.
    add_elem( mod, s_name  );

    // DO NOT CLOSE AS LONG THERE EXIST A POINTER TO THE FUNCTION
    // dlclose( module ); will be called in modl::~modl()!

#ifdef NCURSES
    print_cached( get_size() ); 
#endif
    
    return mod;
}

dynmod*
modl::get_module( string s_name )
{
    wrap::system_message( MODULER + s_name.substr( s_name.find_last_of("/")+1 ) ); 
    dynmod* mod = get_elem( s_name );
    return ! mod ? cache_module( s_name ) : mod;
}

void
modl::unload_modules()
{
    wrap::system_message( MODUNLO );

    // dlclose all the_module's first!
    run_func( &modl::dlclose_ );
    
    // then clean the hash map.
    make_empty();

#ifdef NCURSES
    print_cached( get_size() ); 
#endif
    
}

void
modl::reload_modules()
{
    unload_modules();

    wrap::system_message( MODRELO );
    preload_modules( wrap::CONF->get_elem("httpd.modules.commandsdir") );
    preload_modules( wrap::CONF->get_elem("httpd.modules.htmldir") );
}
#ifdef NCURSES
void
modl::print_cached( int i_mods )
{
    if ( !wrap::NCUR->is_ready() )
      return;

    mvprintw( NCUR_CACHED_MODS_X, NCUR_CACHED_MODS_Y, "Mods: %d ", i_mods);
    refresh();
}
#endif

#endif