modules_plugin.h.in 9.45 KB
Newer Older
1
2
3
4
/*****************************************************************************
 * modules_plugin.h : Plugin management functions used by the core application.
 *****************************************************************************
 * Copyright (C) 2001 VideoLAN
Christophe Massiot's avatar
Christophe Massiot committed
5
 * $Id: modules_plugin.h.in,v 1.12 2003/10/04 12:30:53 massiot Exp $
6
7
8
9
10
11
12
 *
 * Authors: Samuel Hocevar <sam@zoy.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
13
 *
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

/*****************************************************************************
 * Inline functions for handling dynamic modules
 *****************************************************************************/

/*****************************************************************************
 * module_load: load a dynamic library
 *****************************************************************************
 * This function loads a dynamically linked library using a system dependant
 * method, and returns a non-zero value on error, zero otherwise.
 *****************************************************************************/
34
static int module_load( const MYCHAR * psz_filename, module_handle_t * handle )
35
{
Sam Hocevar's avatar
Sam Hocevar committed
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
#if defined(HAVE_DL_DYLD)
    NSObjectFileImage image;
    NSObjectFileImageReturnCode ret;

    ret = NSCreateObjectFileImageFromFile( psz_filename, &image );

    if( ret != NSObjectFileImageSuccess )
    {
        return -1;
    }

    /* Open the dynamic module */
    *handle = NSLinkModule( image, psz_filename,
                            NSLINKMODULE_OPTION_RETURN_ON_ERROR );

    if( !*handle )
    {
        NSLinkEditErrors errors;
        const char *psz_file, *psz_err;
        int i_errnum;
        NSLinkEditError( &errors, &i_errnum, &psz_file, &psz_err );
        return -1; /* err */
    }

    /* Destroy our image, we won't need it */
    NSDestroyObjectFileImage( image );

#elif defined(HAVE_IMAGE_H)
64
65
66
    *handle = load_add_on( psz_filename );
    return( *handle < 0 );

67
#elif defined(WIN32) || defined(UNDER_CE)
68
    *handle = LoadLibrary( psz_filename );
69
    return( *handle == NULL );
70

Sam Hocevar's avatar
Sam Hocevar committed
71
#elif defined(HAVE_DL_DLOPEN) && defined(RTLD_NOW)
72
73
74
    /* static is OK, we are called atomically */
    static vlc_bool_t b_kde = VLC_FALSE;

75
#   if defined(SYS_LINUX)
76
77
78
79
    /* XXX HACK #1 - we should NOT open modules with RTLD_GLOBAL, or we
     * are going to get namespace collisions when two modules have common
     * public symbols, but ALSA is being a pest here. */
    if( strstr( psz_filename, "alsa_plugin" ) )
80
81
82
83
84
    {
        *handle = dlopen( psz_filename, RTLD_NOW | RTLD_GLOBAL );
        return( *handle == NULL );
    }
#   endif
85
86
87
    /* XXX HACK #2 - the ugly KDE workaround. It seems that libkdewhatever
     * causes dlopen() to segfault if libstdc++ is not loaded in the caller,
     * so we just load libstdc++. Bwahahaha! ph34r! -- Sam. */
Sam Hocevar's avatar
Sam Hocevar committed
88
    /* Update: FYI, this is Debian bug #180505, and seems to be fixed. */
89
90
91
92
93
94
95
96
97
    if( !b_kde && !strstr( psz_filename, "kde" ) )
    {
        dlopen( "libstdc++.so.6", RTLD_NOW )
         || dlopen( "libstdc++.so.5", RTLD_NOW )
         || dlopen( "libstdc++.so.4", RTLD_NOW )
         || dlopen( "libstdc++.so.3", RTLD_NOW );
        b_kde = VLC_TRUE;
    }

98
99
100
    *handle = dlopen( psz_filename, RTLD_NOW );
    return( *handle == NULL );

Sam Hocevar's avatar
Sam Hocevar committed
101
#elif defined(HAVE_DL_DLOPEN) && defined(DL_LAZY)
102
103
104
    *handle = dlopen( psz_filename, DL_LAZY );
    return( *handle == NULL );

Sam Hocevar's avatar
Sam Hocevar committed
105
106
107
108
109
110
111
#elif defined(HAVE_DL_SHL_LOAD)
    *handle = shl_load( psz_filename, BIND_IMMEDIATE | BIND_NONFATAL, NULL );
    return( *handle == NULL );

#else
    return -1;

112
113
114
115
116
117
118
119
120
121
#endif
}

/*****************************************************************************
 * module_unload: unload a dynamic library
 *****************************************************************************
 * This function unloads a previously opened dynamically linked library
 * using a system dependant method. No return value is taken in consideration,
 * since some libraries sometimes refuse to close properly.
 *****************************************************************************/
122
static void module_unload( module_handle_t handle )
123
{
Sam Hocevar's avatar
Sam Hocevar committed
124
125
126
127
#if defined(HAVE_DL_DYLD)
    NSUnLinkModule( handle, FALSE );

#elif defined(HAVE_IMAGE_H)
128
129
    unload_add_on( handle );

130
#elif defined(WIN32) || defined(UNDER_CE)
131
132
    FreeLibrary( handle );

Sam Hocevar's avatar
Sam Hocevar committed
133
#elif defined(HAVE_DL_DLOPEN)
134
135
    dlclose( handle );

Sam Hocevar's avatar
Sam Hocevar committed
136
137
138
#elif defined(HAVE_DL_SHL_LOAD)
    shl_unload( handle );

139
140
141
142
143
144
145
146
147
148
149
#endif
    return;
}

/*****************************************************************************
 * module_getsymbol: get a symbol from a dynamic library
 *****************************************************************************
 * This function queries a loaded library for a symbol specified in a
 * string, and returns a pointer to it. We don't check for dlerror() or
 * similar functions, since we want a non-NULL symbol anyway.
 *****************************************************************************/
150
151
static void * _module_getsymbol( module_handle_t handle,
                                 const char * psz_function )
152
{
Sam Hocevar's avatar
Sam Hocevar committed
153
154
155
156
157
#if defined(HAVE_DL_DYLD)
    NSSymbol sym = NSLookupSymbolInModule( handle, psz_function );
    return NSAddressOfSymbol( sym );

#elif defined(HAVE_IMAGE_H)
158
159
160
161
    void * p_symbol;
    if( B_OK == get_image_symbol( handle, psz_function,
                                  B_SYMBOL_TYPE_TEXT, &p_symbol ) )
    {
162
        return p_symbol;
163
164
165
    }
    else
    {
166
        return NULL;
167
168
    }

169
170
171
172
173
174
175
176
#elif defined( UNDER_CE )
    wchar_t psz_real[256];
    MultiByteToWideChar( CP_ACP, 0, psz_function, -1, psz_real, 256 );

    return (void *)GetProcAddress( handle, psz_real );

#elif defined( WIN32 )
    return (void *)GetProcAddress( handle, (MYCHAR*)psz_function );
177

Sam Hocevar's avatar
Sam Hocevar committed
178
#elif defined(HAVE_DL_DLOPEN)
179
    return dlsym( handle, psz_function );
180

Sam Hocevar's avatar
Sam Hocevar committed
181
182
183
184
185
#elif defined(HAVE_DL_SHL_LOAD)
    void *p_sym;
    shl_findsym( &handle, psz_function, TYPE_UNDEFINED, &p_sym );
    return p_sym;

186
187
188
#endif
}

189
190
static void * module_getsymbol( module_handle_t handle,
                                const char * psz_function )
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
{
    void * p_symbol = _module_getsymbol( handle, psz_function );

    /* MacOS X dl library expects symbols to begin with "_". So do
     * some other operating systems. That's really lame, but hey, what
     * can we do ? */
    if( p_symbol == NULL )
    {
        char *psz_call = malloc( strlen( psz_function ) + 2 );

        strcpy( psz_call + 1, psz_function );
        psz_call[ 0 ] = '_';
        p_symbol = _module_getsymbol( handle, psz_call );
        free( psz_call );
    }

    return p_symbol;
}

/*****************************************************************************
 * module_error: wrapper for dlerror()
 *****************************************************************************
 * This function returns the error message of the last module operation. It
 * returns the string "failed" on systems which do not have a dlerror() like
 * function. psz_buffer can be used to store temporary data, it is guaranteed
 * to be kept intact until the return value of module_error has been used.
 *****************************************************************************/
218
static const char * module_error( char *psz_buffer )
219
{
Sam Hocevar's avatar
Sam Hocevar committed
220
221
222
223
#if defined(HAVE_DL_DYLD)
    return "failed";

#elif defined(HAVE_IMAGE_H)
224
    return "failed";
225

226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#elif defined(UNDER_CE)
    wchar_t psz_tmp[256];

    int i, i_error = GetLastError();

    FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                   NULL, i_error, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
                   (LPTSTR) psz_tmp, 256, NULL );

    /* Go to the end of the string */
    for( i = 0;
         psz_tmp[i] && psz_tmp[i] != L'\r' && psz_tmp[i] != L'\n';
         i++ ) {};

    if( psz_tmp[i] )
    {
        swprintf( psz_tmp + i, L" (error %i)", i_error );
        psz_tmp[ 255 ] = L'\0';
    }
245

246
247
248
249
250
251
    WideCharToMultiByte( CP_ACP, WC_DEFAULTCHAR, psz_tmp, -1,
                         psz_buffer, 256, NULL, NULL );

    return psz_buffer;

#elif defined(WIN32)
252
253
254
255
    int i, i_error = GetLastError();

    FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                   NULL, i_error, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
256
                   (LPTSTR) psz_buffer, 256, NULL );
257
258
259
260
261
262
263
264
265

    /* Go to the end of the string */
    for( i = 0;
         psz_buffer[i] && psz_buffer[i] != '\r' && psz_buffer[i] != '\n';
         i++ ) {};

    if( psz_buffer[i] )
    {
        snprintf( psz_buffer + i, 256 - i, " (error %i)", i_error );
266
        psz_buffer[ 255 ] = '\0';
267
    }
268

269
270
    return psz_buffer;

Sam Hocevar's avatar
Sam Hocevar committed
271
#elif defined(HAVE_DL_DLOPEN)
272
    return dlerror();
273

Sam Hocevar's avatar
Sam Hocevar committed
274
275
276
#elif defined(HAVE_DL_SHL_LOAD)
    return strerror( errno );

277
278
279
280
281
282
#endif
}

/*****************************************************************************
 * STORE_SYMBOLS: store known symbols into p_symbols for plugin access.
 *****************************************************************************/