1
2 /* Dynamic loading of the sort backend.
3 * We use GLib's multiplatform dl() wrapper
4 * to open up libsortsieve and
5 * populate the global 'sort' structure.
6 *
7 * (c) 2005 Aaron Stone <aaron@serendipity.cx>
8 */
9
10 #include "dbmail.h"
11 #define THIS_MODULE "sort"
12
13 static sort_func *sort = NULL;
14
15 /* Returns:
16 * 1 on modules unsupported
17 * 0 on success
18 * -1 on failure to load module
19 * -2 on missing symbols
20 * -3 on memory error
21 */
sort_load_driver(void)22 int sort_load_driver(void)
23 {
24 GModule *module;
25 char *lib = NULL;
26 char *driver = NULL;
27
28 if (!g_module_supported()) {
29 TRACE(TRACE_EMERG, "loadable modules unsupported on this platform");
30 return 1;
31 }
32
33 sort = g_new0(sort_func,1);
34 if (!sort) {
35 TRACE(TRACE_EMERG, "cannot allocate memory");
36 return -3;
37 }
38
39 /* The only supported driver is Sieve. */
40 driver = "sort_sieve";
41
42 Field_T library_dir;
43 config_get_value("library_directory", "DBMAIL", library_dir);
44 if (strlen(library_dir) == 0) {
45 TRACE(TRACE_DEBUG, "no value for library_directory, using default [%s]", DEFAULT_LIBRARY_DIR);
46 snprintf(library_dir, sizeof(Field_T), "%s", DEFAULT_LIBRARY_DIR);
47 } else {
48 TRACE(TRACE_DEBUG, "library_directory is [%s]", library_dir);
49 }
50
51 /* Try local build area, then dbmail lib paths, then system lib path. */
52 int i;
53 char local_path[PATH_MAX];
54 memset(local_path, 0, sizeof(local_path));
55 g_strlcat(local_path, DM_PWD, PATH_MAX);
56 g_strlcat(local_path, "/src/modules/.libs", PATH_MAX);
57
58 char *lib_path[] = {
59 local_path,
60 library_dir,
61 NULL
62 };
63
64 /* Note that the limit here *includes* the NULL. This is intentional,
65 * to allow g_module_build_path to try the current working directory. */
66 for (i = 0; lib_path[i] != NULL; i++) {
67 lib = g_module_build_path(lib_path[i], driver);
68 module = g_module_open(lib, 0); // non-lazy bind.
69
70 TRACE(TRACE_DEBUG, "looking for %s as %s", driver, lib);
71 g_free(lib);
72
73 if (!module)
74 TRACE(TRACE_INFO, "cannot load %s", g_module_error());
75 if (module)
76 break;
77 }
78
79 /* If the list is exhausted without opening a module, we'll catch it,
80 * but we don't bomb out as we do for db and auth; just deliver normally. */
81 if (!module) {
82 TRACE(TRACE_EMERG, "could not load sort module - turn up debug level for details");
83 return -1;
84 }
85
86 if (!g_module_symbol(module, "sort_process", (gpointer)&sort->process )
87 || !g_module_symbol(module, "sort_validate", (gpointer)&sort->validate )
88 || !g_module_symbol(module, "sort_free_result", (gpointer)&sort->free_result )
89 || !g_module_symbol(module, "sort_listextensions", (gpointer)&sort->listextensions )
90 || !g_module_symbol(module, "sort_get_cancelkeep", (gpointer)&sort->get_cancelkeep )
91 || !g_module_symbol(module, "sort_get_reject", (gpointer)&sort->get_reject )
92 || !g_module_symbol(module, "sort_get_errormsg", (gpointer)&sort->get_errormsg )
93 || !g_module_symbol(module, "sort_get_error", (gpointer)&sort->get_error )
94 || !g_module_symbol(module, "sort_get_mailbox", (gpointer)&sort->get_mailbox )) {
95 TRACE(TRACE_ERR, "cannot find function: %s: Did you enable SIEVE sorting in the DELIVERY "
96 "section of dbmail.conf but forget to build the Sieve loadable module?", g_module_error());
97 return -2;
98 }
99
100 return 0;
101 }
102
sort_process(uint64_t user_idnr,DbmailMessage * message,const char * mailbox)103 SortResult_T *sort_process(uint64_t user_idnr, DbmailMessage *message, const char *mailbox)
104 {
105 if (!sort)
106 sort_load_driver();
107 if (!sort->process) {
108 TRACE(TRACE_ERR, "Error loading sort driver");
109 return NULL;
110 }
111 return sort->process(user_idnr, message, mailbox);
112 }
113
sort_validate(uint64_t user_idnr,char * scriptname)114 SortResult_T *sort_validate(uint64_t user_idnr, char *scriptname)
115 {
116 if (!sort)
117 sort_load_driver();
118 if (!sort->validate) {
119 TRACE(TRACE_ERR, "Error loading sort driver");
120 return NULL;
121 }
122 return sort->validate(user_idnr, scriptname);
123 }
124
sort_listextensions(void)125 const char *sort_listextensions(void)
126 {
127 if (!sort)
128 sort_load_driver();
129 if (!sort->listextensions) {
130 TRACE(TRACE_ERR, "Error loading sort driver");
131 return NULL;
132 }
133 return sort->listextensions();
134 }
135
sort_free_result(SortResult_T * result)136 void sort_free_result(SortResult_T *result)
137 {
138 if (!sort->free_result)
139 return;
140 return sort->free_result(result);
141 }
142
sort_get_cancelkeep(SortResult_T * result)143 int sort_get_cancelkeep(SortResult_T *result)
144 {
145 if (!sort->get_cancelkeep)
146 return 0;
147 return sort->get_cancelkeep(result);
148 }
149
sort_get_reject(SortResult_T * result)150 int sort_get_reject(SortResult_T *result)
151 {
152 if (!sort->get_reject)
153 return 0;
154 return sort->get_reject(result);
155 }
156
sort_get_mailbox(SortResult_T * result)157 const char * sort_get_mailbox(SortResult_T *result)
158 {
159 if (!sort->get_mailbox)
160 return "";
161 return sort->get_mailbox(result);
162 }
163
sort_get_errormsg(SortResult_T * result)164 const char * sort_get_errormsg(SortResult_T *result)
165 {
166 if (!sort->get_errormsg)
167 return "";
168 return sort->get_errormsg(result);
169 }
170
sort_get_error(SortResult_T * result)171 int sort_get_error(SortResult_T *result)
172 {
173 if (!sort->get_error)
174 return 0;
175 return sort->get_error(result);
176 }
177
178