Add a plugin interface to wiretap.
[obnox/wireshark/wip.git] / wiretap / wtap-plugins.c
1 /* wtap.h
2 *
3 * $Id: wtap.h 21651 2007-05-02 20:09:42Z lego $
4 *
5 * Wiretap Library
6 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26
27 #include <glib.h>
28 #include <gmodule.h>
29
30 #ifdef HAVE_DIRENT_H
31 #include <dirent.h>
32 #endif
33
34 #ifdef HAVE_DIRECT_H
35 #include <direct.h>
36 #endif
37
38 #include <string.h>
39 #include <stdlib.h>
40 #include <errno.h>
41
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
45
46 #include "wtap.h"
47 #include "file_util.h"
48
49 #define PLUGINS_DIR_NAME        "wiretap_plugins"
50
51 static gboolean plugins_loaded = FALSE;
52
53 void wtap_load_plugins(char* dirname) {
54
55 #define FILENAME_LEN    1024
56                 ETH_DIR       *dir;             /* scanned directory */
57                 ETH_DIRENT    *file;            /* current file */
58                 const char    *name;
59 #if GLIB_MAJOR_VERSION < 2
60                 gchar         *hack_path;       /* pathname used to construct lt_lib_ext */
61                 gchar         *lt_lib_ext;      /* extension for loadable modules */
62 #endif
63                 gchar          filename[FILENAME_LEN];   /* current file name */
64                 GModule       *handle;          /* handle returned by dlopen */
65                 gchar         *version;
66                 gpointer       gp;
67                 gchar         *dot;
68                 
69                 if (plugins_loaded || ! dirname) return;
70                 
71                 plugins_loaded = TRUE;
72                 
73 #if GLIB_MAJOR_VERSION < 2
74                 /*
75                  * We find the extension used on this platform for loadable modules
76                  * by the sneaky hack of calling "g_module_build_path" to build
77                  * the pathname for a module with an empty directory name and
78                  * empty module name, and then search for the last "." and use
79                  * everything from the last "." on.
80                  */
81                 hack_path = g_module_build_path("", "");
82                 lt_lib_ext = strrchr(hack_path, '.');
83                 if (lt_lib_ext == NULL)
84                 {
85                         /*
86                          * Does this mean there *is* no extension?  Assume so.
87                          *
88                          * XXX - the code below assumes that all loadable modules have
89                          * an extension....
90                          */
91                         lt_lib_ext = "";
92                 }
93 #endif
94                 
95                 if ((dir = eth_dir_open(dirname, 0, NULL)) != NULL)
96                 {
97                         while ((file = eth_dir_read_name(dir)) != NULL)
98                         {
99                                 name = eth_dir_get_name(file);
100 #if GLIB_MAJOR_VERSION < 2
101                                 /* don't try to open "." and ".." */
102                                 if (!(strcmp(name, "..") &&
103                                           strcmp(name, ".")))
104                                         continue;
105                                 
106                                 /* skip anything but files with lt_lib_ext */
107                                 dot = strrchr(name, '.');
108                                 if (dot == NULL || strcmp(dot, lt_lib_ext) != 0)
109                                         continue;
110                                 
111 #else /* GLIB 2 */
112                                 /*
113                                  * GLib 2.x defines G_MODULE_SUFFIX as the extension used on
114                                  * this platform for loadable modules.
115                                  */
116                                 /* skip anything but files with G_MODULE_SUFFIX */
117                                 dot = strrchr(name, '.');
118                                 if (dot == NULL || strcmp(dot+1, G_MODULE_SUFFIX) != 0)
119                                         continue;
120                                 
121 #endif
122                                 g_snprintf(filename, FILENAME_LEN, "%s" G_DIR_SEPARATOR_S "%s",
123                                                    dirname, name);
124                                 if ((handle = g_module_open(filename, 0)) == NULL)
125                                 {
126                                         g_warning("Couldn't load module %s: %s", filename,
127                                                                    g_module_error());
128                                         continue;
129                                 }
130                                 if (!g_module_symbol(handle, "version", &gp))
131                                 {
132                                         g_warning("The plugin %s has no version symbol", name);
133                                         g_module_close(handle);
134                                         continue;
135                                 }
136                                 version = gp;
137                                 
138                                 if (g_module_symbol(handle, "register_wtap_module", &gp))
139                                 {
140                                         void (*register_wtap_module)(void) = gp;
141                                         register_wtap_module();
142                                 }
143                         }
144                         eth_dir_close(dir);
145                 }
146 #if GLIB_MAJOR_VERSION < 2
147                 g_free(hack_path);
148                 g_free(dirname);
149 #endif
150
151 }
152