~ubuntu-branches/ubuntu/wily/scim/wily-proposed

« back to all changes in this revision

Viewing changes to .pc/32_scim-1.4.8-fix-dlopen.patch/src/scim_module.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Rolf Leggewie
  • Date: 2010-08-11 18:28:44 UTC
  • mfrom: (3.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100811182844-rnn95k63cwehtm75
Tags: 1.4.9-5
* debian/copyright: add my copyright
* debian/control: update to standard 3.9.1, no further changes necessary

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Smart Common Input Method
 
3
 * 
 
4
 * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
 
5
 *
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU Lesser General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with this program; if not, write to the
 
19
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 
20
 * Boston, MA  02111-1307  USA
 
21
 *
 
22
 * $Id: scim_module.cpp,v 1.26 2005/05/24 12:22:51 suzhe Exp $
 
23
 *
 
24
 */
 
25
 
 
26
#define Uses_SCIM_MODULE
 
27
#define Uses_STL_ALGORITHM
 
28
#include "scim_private.h"
 
29
#include "scim.h"
 
30
extern "C" {
 
31
  #include <ltdl.h>
 
32
}
 
33
#include <dirent.h>
 
34
#include <sys/types.h>
 
35
#include <sys/stat.h>
 
36
#include <unistd.h>
 
37
 
 
38
namespace scim {
 
39
 
 
40
typedef void (*ModuleInitFunc) (void);
 
41
typedef void (*ModuleExitFunc) (void);
 
42
 
 
43
struct Module::ModuleImpl
 
44
{
 
45
    lt_dlhandle handle;
 
46
    ModuleInitFunc init;
 
47
    ModuleExitFunc exit;
 
48
    String path;
 
49
    String name;
 
50
 
 
51
    ModuleImpl () : handle (0), init (0), exit (0) { }
 
52
};
 
53
 
 
54
static std::vector <ModuleInitFunc> _scim_modules;
 
55
 
 
56
static void
 
57
_scim_get_module_paths (std::vector <String> &paths, const String &type)
 
58
{
 
59
    const char *module_path_env;
 
60
 
 
61
    std::vector <String> module_paths;
 
62
    std::vector <String>::iterator it;
 
63
 
 
64
    paths.clear ();
 
65
 
 
66
    module_path_env = getenv ("SCIM_MODULE_PATH");
 
67
 
 
68
    if (module_path_env)
 
69
        module_paths.push_back (String (module_path_env));
 
70
 
 
71
    module_paths.push_back (String (SCIM_MODULE_PATH));
 
72
 
 
73
    // append version to the end of the paths
 
74
    for (it = module_paths.begin (); it != module_paths.end (); ++it) {
 
75
        String tmp_dir;
 
76
 
 
77
        tmp_dir = *it + String (SCIM_PATH_DELIM_STRING) +
 
78
                    String (SCIM_BINARY_VERSION) +
 
79
                    String (SCIM_PATH_DELIM_STRING) + type;
 
80
 
 
81
        paths.push_back (tmp_dir);
 
82
 
 
83
        tmp_dir = *it + String (SCIM_PATH_DELIM_STRING) + type;
 
84
        paths.push_back (tmp_dir);
 
85
    }
 
86
}
 
87
 
 
88
int
 
89
scim_get_module_list (std::vector <String>& mod_list, const String& type)
 
90
{
 
91
    std::vector<String> paths;
 
92
    _scim_get_module_paths (paths, type);
 
93
 
 
94
    mod_list.clear ();
 
95
 
 
96
    for (std::vector<String>::iterator i = paths.begin (); i!= paths.end (); ++i) {
 
97
        DIR *dir = opendir (i->c_str ());
 
98
        if (dir) {
 
99
            struct dirent *file = readdir (dir);
 
100
            while (file) {
 
101
                struct stat filestat;
 
102
                String absfn = *i + String (SCIM_PATH_DELIM_STRING) + file->d_name;
 
103
                stat (absfn.c_str (), &filestat);
 
104
                if (S_ISREG (filestat.st_mode)) {
 
105
                    std::vector<String> vec;
 
106
                    scim_split_string_list (vec, String (file->d_name), '.');
 
107
                    mod_list.push_back (vec [0]);
 
108
                }
 
109
                file = readdir (dir);
 
110
            }
 
111
            closedir (dir);
 
112
        }
 
113
    }
 
114
    std::sort (mod_list.begin (), mod_list.end ());
 
115
    mod_list.erase (std::unique (mod_list.begin(), mod_list.end()), mod_list.end());
 
116
    return mod_list.size ();
 
117
}
 
118
 
 
119
Module::Module ()
 
120
    : m_impl (new ModuleImpl)
 
121
{
 
122
    lt_dlinit ();
 
123
}
 
124
 
 
125
Module::Module (const String &name, const String &type)
 
126
    : m_impl (new ModuleImpl)
 
127
{
 
128
    lt_dlinit ();
 
129
    load (name, type);
 
130
}
 
131
 
 
132
Module::~Module ()
 
133
{
 
134
    unload ();
 
135
    lt_dlexit ();
 
136
    delete m_impl;
 
137
}
 
138
 
 
139
static String
 
140
_concatenate_ltdl_prefix (const String &name, const String &symbol)
 
141
{
 
142
    String prefix (name);
 
143
 
 
144
    for (size_t i=0; i<prefix.length (); i++)
 
145
        if (!isalnum ((int)prefix[i]))
 
146
            prefix[i] = '_';
 
147
 
 
148
    return prefix + String ("_LTX_") + symbol;
 
149
}
 
150
 
 
151
bool
 
152
Module::load (const String &name, const String &type)
 
153
{
 
154
    // If cannot unload original module (it's resident), then return false.
 
155
    if (is_resident ())
 
156
        return false;
 
157
 
 
158
    std::vector <String> paths;
 
159
    std::vector <String>::iterator it; 
 
160
 
 
161
    String module_path;
 
162
 
 
163
    lt_dlhandle    new_handle = 0;
 
164
 
 
165
    ModuleInitFunc new_init;
 
166
    ModuleExitFunc new_exit;
 
167
 
 
168
    _scim_get_module_paths (paths, type);
 
169
 
 
170
    for (it = paths.begin (); it != paths.end (); ++it) {
 
171
        module_path = *it + String (SCIM_PATH_DELIM_STRING) + name;
 
172
        new_handle = lt_dlopenext (module_path.c_str ());
 
173
        if (new_handle)
 
174
            break;
 
175
    }
 
176
 
 
177
    if (!new_handle) {
 
178
        new_handle = lt_dlopenext (name.c_str ());
 
179
    }
 
180
 
 
181
    if (!new_handle)
 
182
        return false;
 
183
 
 
184
    String symbol;
 
185
 
 
186
    // Try to load the symbol scim_module_init
 
187
    symbol = "scim_module_init";
 
188
    new_init = (ModuleInitFunc) lt_dlsym (new_handle, symbol.c_str ());
 
189
 
 
190
    // If symbol load failed, try to add LTX prefix and load again.
 
191
    // This will occurred when name.la is missing.
 
192
    if (!new_init) {
 
193
        symbol = _concatenate_ltdl_prefix (name, symbol);
 
194
        new_init = (ModuleInitFunc) lt_dlsym (new_handle, symbol.c_str ());
 
195
 
 
196
        // Failed again? Try to prepend a under score to the symbol name.
 
197
        if (!new_init) {
 
198
            symbol.insert (symbol.begin (),'_');
 
199
            new_init = (ModuleInitFunc) lt_dlsym (new_handle, symbol.c_str ());
 
200
        }
 
201
    }
 
202
 
 
203
    // Could not load the module!
 
204
    if (!new_init) {
 
205
        lt_dlclose (new_handle);
 
206
        return false;
 
207
    }
 
208
 
 
209
    // Try to load the symbol scim_module_exit
 
210
    symbol = "scim_module_exit";
 
211
    new_exit = (ModuleExitFunc) lt_dlsym (new_handle, symbol.c_str ());
 
212
 
 
213
    // If symbol load failed, try to add LTX prefix and load again.
 
214
    // This will occurred when name.la is missing.
 
215
    if (!new_exit) {
 
216
        symbol = _concatenate_ltdl_prefix (name, symbol);
 
217
        new_exit = (ModuleExitFunc) lt_dlsym (new_handle, symbol.c_str ());
 
218
 
 
219
        // Failed again? Try to prepend a under score to the symbol name.
 
220
        if (!new_exit) {
 
221
            symbol.insert (symbol.begin (),'_');
 
222
            new_exit = (ModuleExitFunc) lt_dlsym (new_handle, symbol.c_str ());
 
223
        }
 
224
    }
 
225
 
 
226
    //Check if the module is already loaded.
 
227
    if (std::find (_scim_modules.begin (), _scim_modules.end (), new_init)
 
228
        != _scim_modules.end ()) {
 
229
        lt_dlclose (new_handle);
 
230
        return false;
 
231
    }
 
232
 
 
233
    if (unload ()) {
 
234
        _scim_modules.push_back (new_init);
 
235
 
 
236
        const lt_dlinfo *info = lt_dlgetinfo (new_handle);
 
237
 
 
238
        m_impl->handle = new_handle;
 
239
        m_impl->init   = new_init;
 
240
        m_impl->exit   = new_exit;
 
241
        m_impl->path   = String (info->filename);
 
242
        m_impl->name   = name;
 
243
 
 
244
        try {
 
245
            m_impl->init ();
 
246
            return true;
 
247
        } catch (...) {
 
248
            unload ();
 
249
        }
 
250
    } else {
 
251
        lt_dlclose (new_handle);
 
252
    }
 
253
 
 
254
    return false;
 
255
}
 
256
 
 
257
bool
 
258
Module::unload ()
 
259
{
 
260
    if (!m_impl->handle)
 
261
        return true;
 
262
 
 
263
    if (is_resident ())
 
264
        return false;
 
265
 
 
266
    if (m_impl->exit) {
 
267
        try { m_impl->exit (); } catch (...) { }
 
268
    }
 
269
 
 
270
    lt_dlclose (m_impl->handle);
 
271
 
 
272
    std::vector <ModuleInitFunc>::iterator it =
 
273
        std::find (_scim_modules.begin (), _scim_modules.end (), m_impl->init);
 
274
 
 
275
    if (it != _scim_modules.end ())
 
276
        _scim_modules.erase (it);
 
277
 
 
278
    m_impl->handle = 0;
 
279
    m_impl->init   = 0;
 
280
    m_impl->exit   = 0;
 
281
    m_impl->path   = String ();
 
282
    m_impl->name   = String ();
 
283
 
 
284
    return true;
 
285
}
 
286
 
 
287
bool
 
288
Module::make_resident () const
 
289
{
 
290
    if (m_impl->handle) {
 
291
        return lt_dlmakeresident (m_impl->handle) == 0;
 
292
    }
 
293
    return false;
 
294
}
 
295
 
 
296
bool
 
297
Module::is_resident () const
 
298
{
 
299
    if (m_impl->handle) {
 
300
        return lt_dlisresident (m_impl->handle) == 1;
 
301
    }
 
302
    return false;
 
303
}
 
304
 
 
305
bool
 
306
Module::valid () const
 
307
{
 
308
    return (m_impl->handle && m_impl->init);
 
309
}
 
310
 
 
311
String
 
312
Module::get_path () const
 
313
{
 
314
    return m_impl->path;
 
315
}
 
316
 
 
317
void *
 
318
Module::symbol (const String & sym) const
 
319
{
 
320
    void * func = 0;
 
321
 
 
322
    if (m_impl->handle) {
 
323
        String symbol = sym;
 
324
        func = lt_dlsym (m_impl->handle, symbol.c_str ());
 
325
        if (!func) {
 
326
            symbol = _concatenate_ltdl_prefix (m_impl->name, symbol);
 
327
            func = lt_dlsym (m_impl->handle, symbol.c_str ());
 
328
            if (!func) {
 
329
                symbol.insert (symbol.begin (), '_');
 
330
                func = lt_dlsym (m_impl->handle, symbol.c_str ());
 
331
            }
 
332
        }
 
333
    }
 
334
    return func;
 
335
}
 
336
 
 
337
} // namespace scim
 
338
 
 
339
/*
 
340
vi:ts=4:nowrap:ai:expandtab
 
341
*/