xref: /lighttpd1.4/src/plugin.c (revision 15dc40cd)
1bcdc6a3bSJan Kneschke #include <string.h>
2bcdc6a3bSJan Kneschke #include <stdlib.h>
3bcdc6a3bSJan Kneschke 
4bcdc6a3bSJan Kneschke #include <stdio.h>
5bcdc6a3bSJan Kneschke 
6bcdc6a3bSJan Kneschke #include "plugin.h"
7bcdc6a3bSJan Kneschke #include "log.h"
8bcdc6a3bSJan Kneschke #include "config.h"
9bcdc6a3bSJan Kneschke 
10bcdc6a3bSJan Kneschke #ifdef HAVE_VALGRIND_VALGRIND_H
11bcdc6a3bSJan Kneschke #include <valgrind/valgrind.h>
12bcdc6a3bSJan Kneschke #endif
13bcdc6a3bSJan Kneschke 
14bcdc6a3bSJan Kneschke #ifndef __WIN32
15bcdc6a3bSJan Kneschke #include <dlfcn.h>
16bcdc6a3bSJan Kneschke #endif
17bcdc6a3bSJan Kneschke /*
18bcdc6a3bSJan Kneschke  *
19bcdc6a3bSJan Kneschke  * if you change this enum to add a new callback, be sure
20bcdc6a3bSJan Kneschke  * - that PLUGIN_FUNC_SIZEOF is the last entry
21bcdc6a3bSJan Kneschke  * - that you add PLUGIN_TO_SLOT twice:
22bcdc6a3bSJan Kneschke  *   1. as callback-dispatcher
23bcdc6a3bSJan Kneschke  *   2. in plugins_call_init()
24bcdc6a3bSJan Kneschke  *
25bcdc6a3bSJan Kneschke  */
26bcdc6a3bSJan Kneschke 
27bcdc6a3bSJan Kneschke typedef struct {
28bcdc6a3bSJan Kneschke 	PLUGIN_DATA;
29bcdc6a3bSJan Kneschke } plugin_data;
30bcdc6a3bSJan Kneschke 
31bcdc6a3bSJan Kneschke typedef enum {
32bcdc6a3bSJan Kneschke 	PLUGIN_FUNC_UNSET,
33bcdc6a3bSJan Kneschke 		PLUGIN_FUNC_HANDLE_URI_CLEAN,
34bcdc6a3bSJan Kneschke 		PLUGIN_FUNC_HANDLE_URI_RAW,
35bcdc6a3bSJan Kneschke 		PLUGIN_FUNC_HANDLE_REQUEST_DONE,
36bcdc6a3bSJan Kneschke 		PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE,
37bcdc6a3bSJan Kneschke 		PLUGIN_FUNC_HANDLE_TRIGGER,
38bcdc6a3bSJan Kneschke 		PLUGIN_FUNC_HANDLE_SIGHUP,
39bcdc6a3bSJan Kneschke 		PLUGIN_FUNC_HANDLE_SUBREQUEST,
40bcdc6a3bSJan Kneschke 		PLUGIN_FUNC_HANDLE_SUBREQUEST_START,
41bcdc6a3bSJan Kneschke 		PLUGIN_FUNC_HANDLE_JOBLIST,
42bcdc6a3bSJan Kneschke 		PLUGIN_FUNC_HANDLE_DOCROOT,
436adaad54SJan Kneschke 		PLUGIN_FUNC_HANDLE_PHYSICAL,
44bcdc6a3bSJan Kneschke 		PLUGIN_FUNC_CONNECTION_RESET,
45bcdc6a3bSJan Kneschke 		PLUGIN_FUNC_INIT,
46bcdc6a3bSJan Kneschke 		PLUGIN_FUNC_CLEANUP,
47bcdc6a3bSJan Kneschke 		PLUGIN_FUNC_SET_DEFAULTS,
48bcdc6a3bSJan Kneschke 
49bcdc6a3bSJan Kneschke 		PLUGIN_FUNC_SIZEOF
50bcdc6a3bSJan Kneschke } plugin_t;
51bcdc6a3bSJan Kneschke 
52bcdc6a3bSJan Kneschke static plugin *plugin_init(void) {
53bcdc6a3bSJan Kneschke 	plugin *p;
54bcdc6a3bSJan Kneschke 
55bcdc6a3bSJan Kneschke 	p = calloc(1, sizeof(*p));
56bcdc6a3bSJan Kneschke 
57bcdc6a3bSJan Kneschke 	return p;
58bcdc6a3bSJan Kneschke }
59bcdc6a3bSJan Kneschke 
60bcdc6a3bSJan Kneschke static void plugin_free(plugin *p) {
61bcdc6a3bSJan Kneschke 	int use_dlclose = 1;
62bcdc6a3bSJan Kneschke 	if (p->name) buffer_free(p->name);
63bcdc6a3bSJan Kneschke #ifdef HAVE_VALGRIND_VALGRIND_H
6475c3a839SJan Kneschke 	/*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/
65bcdc6a3bSJan Kneschke #endif
66bcdc6a3bSJan Kneschke 
67bcdc6a3bSJan Kneschke 	if (use_dlclose && p->lib) {
68bcdc6a3bSJan Kneschke #ifdef __WIN32
69bcdc6a3bSJan Kneschke 		FreeLibrary(p->lib);
70bcdc6a3bSJan Kneschke #else
71bcdc6a3bSJan Kneschke 		dlclose(p->lib);
72bcdc6a3bSJan Kneschke #endif
73bcdc6a3bSJan Kneschke 	}
74bcdc6a3bSJan Kneschke 
75bcdc6a3bSJan Kneschke 	free(p);
76bcdc6a3bSJan Kneschke }
77bcdc6a3bSJan Kneschke 
78bcdc6a3bSJan Kneschke static int plugins_register(server *srv, plugin *p) {
79bcdc6a3bSJan Kneschke 	plugin **ps;
80bcdc6a3bSJan Kneschke 	if (0 == srv->plugins.size) {
81bcdc6a3bSJan Kneschke 		srv->plugins.size = 4;
82bcdc6a3bSJan Kneschke 		srv->plugins.ptr  = malloc(srv->plugins.size * sizeof(*ps));
83bcdc6a3bSJan Kneschke 		srv->plugins.used = 0;
84bcdc6a3bSJan Kneschke 	} else if (srv->plugins.used == srv->plugins.size) {
85bcdc6a3bSJan Kneschke 		srv->plugins.size += 4;
86bcdc6a3bSJan Kneschke 		srv->plugins.ptr   = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps));
87bcdc6a3bSJan Kneschke 	}
88bcdc6a3bSJan Kneschke 
89bcdc6a3bSJan Kneschke 	ps = srv->plugins.ptr;
90bcdc6a3bSJan Kneschke 	ps[srv->plugins.used++] = p;
91bcdc6a3bSJan Kneschke 
92bcdc6a3bSJan Kneschke 	return 0;
93bcdc6a3bSJan Kneschke }
94bcdc6a3bSJan Kneschke 
95bcdc6a3bSJan Kneschke /**
96bcdc6a3bSJan Kneschke  *
97bcdc6a3bSJan Kneschke  *
98bcdc6a3bSJan Kneschke  *
99bcdc6a3bSJan Kneschke  */
100bcdc6a3bSJan Kneschke 
101bcdc6a3bSJan Kneschke 
102bcdc6a3bSJan Kneschke int plugins_load(server *srv) {
103bcdc6a3bSJan Kneschke 	plugin *p;
104bcdc6a3bSJan Kneschke 	int (*init)(plugin *pl);
105bcdc6a3bSJan Kneschke 	const char *error;
106bcdc6a3bSJan Kneschke 	size_t i;
107bcdc6a3bSJan Kneschke 
108bcdc6a3bSJan Kneschke 	for (i = 0; i < srv->srvconf.modules->used; i++) {
109bcdc6a3bSJan Kneschke 		data_string *d = (data_string *)srv->srvconf.modules->data[i];
110bcdc6a3bSJan Kneschke 		char *modules = d->value->ptr;
111bcdc6a3bSJan Kneschke 
112c7ec5012SJan Kneschke 		buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.modules_dir);
113*15dc40cdSJan Kneschke 
114bcdc6a3bSJan Kneschke 		buffer_append_string(srv->tmp_buf, "/");
115bcdc6a3bSJan Kneschke 		buffer_append_string(srv->tmp_buf, modules);
116bcdc6a3bSJan Kneschke #if defined(__WIN32) || defined(__CYGWIN__)
117bcdc6a3bSJan Kneschke 		buffer_append_string(srv->tmp_buf, ".dll");
118bcdc6a3bSJan Kneschke #else
119bcdc6a3bSJan Kneschke 		buffer_append_string(srv->tmp_buf, ".so");
120bcdc6a3bSJan Kneschke #endif
121bcdc6a3bSJan Kneschke 
122bcdc6a3bSJan Kneschke 		p = plugin_init();
123bcdc6a3bSJan Kneschke #ifdef __WIN32
124bcdc6a3bSJan Kneschke 		if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) {
125bcdc6a3bSJan Kneschke 			LPVOID lpMsgBuf;
126bcdc6a3bSJan Kneschke 			FormatMessage(
127bcdc6a3bSJan Kneschke 		        	FORMAT_MESSAGE_ALLOCATE_BUFFER |
128bcdc6a3bSJan Kneschke 		       		FORMAT_MESSAGE_FROM_SYSTEM,
129bcdc6a3bSJan Kneschke 		        	NULL,
130bcdc6a3bSJan Kneschke 		        	GetLastError(),
131bcdc6a3bSJan Kneschke 		        	MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
132bcdc6a3bSJan Kneschke 		        	(LPTSTR) &lpMsgBuf,
133bcdc6a3bSJan Kneschke 		        	0, NULL );
134bcdc6a3bSJan Kneschke 
135bcdc6a3bSJan Kneschke 			log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
136bcdc6a3bSJan Kneschke 					lpMsgBuf, srv->tmp_buf);
137bcdc6a3bSJan Kneschke 
138bcdc6a3bSJan Kneschke 			plugin_free(p);
139bcdc6a3bSJan Kneschke 
140bcdc6a3bSJan Kneschke 			return -1;
141bcdc6a3bSJan Kneschke 
142bcdc6a3bSJan Kneschke 		}
143bcdc6a3bSJan Kneschke #else
144bcdc6a3bSJan Kneschke 		if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_LAZY))) {
1456b5c314cSJan Kneschke 			log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
1466b5c314cSJan Kneschke 					srv->tmp_buf, dlerror());
147bcdc6a3bSJan Kneschke 
148bcdc6a3bSJan Kneschke 			plugin_free(p);
149bcdc6a3bSJan Kneschke 
150bcdc6a3bSJan Kneschke 			return -1;
151bcdc6a3bSJan Kneschke 		}
152bcdc6a3bSJan Kneschke 
153bcdc6a3bSJan Kneschke #endif
154bcdc6a3bSJan Kneschke 		buffer_reset(srv->tmp_buf);
155bcdc6a3bSJan Kneschke 		buffer_copy_string(srv->tmp_buf, modules);
156bcdc6a3bSJan Kneschke 		buffer_append_string(srv->tmp_buf, "_plugin_init");
157bcdc6a3bSJan Kneschke 
158bcdc6a3bSJan Kneschke #ifdef __WIN32
159bcdc6a3bSJan Kneschke 		init = GetProcAddress(p->lib, srv->tmp_buf->ptr);
160bcdc6a3bSJan Kneschke 
161bcdc6a3bSJan Kneschke 		if (init == NULL)  {
162bcdc6a3bSJan Kneschke 			LPVOID lpMsgBuf;
163bcdc6a3bSJan Kneschke 			FormatMessage(
164bcdc6a3bSJan Kneschke 		        	FORMAT_MESSAGE_ALLOCATE_BUFFER |
165bcdc6a3bSJan Kneschke 		       		FORMAT_MESSAGE_FROM_SYSTEM,
166bcdc6a3bSJan Kneschke 		        	NULL,
167bcdc6a3bSJan Kneschke 		        	GetLastError(),
168bcdc6a3bSJan Kneschke 		        	MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
169bcdc6a3bSJan Kneschke 		        	(LPTSTR) &lpMsgBuf,
170bcdc6a3bSJan Kneschke 		        	0, NULL );
171bcdc6a3bSJan Kneschke 
172bcdc6a3bSJan Kneschke 			log_error_write(srv, __FILE__, __LINE__, "sbs", "getprocaddress failed:", srv->tmp_buf, lpMsgBuf);
173bcdc6a3bSJan Kneschke 
174bcdc6a3bSJan Kneschke 			plugin_free(p);
175bcdc6a3bSJan Kneschke 			return -1;
176bcdc6a3bSJan Kneschke 		}
177bcdc6a3bSJan Kneschke 
178bcdc6a3bSJan Kneschke #else
179bcdc6a3bSJan Kneschke 		*(void **)(&init) = dlsym(p->lib, srv->tmp_buf->ptr);
180bcdc6a3bSJan Kneschke 		if ((error = dlerror()) != NULL)  {
181bcdc6a3bSJan Kneschke 			log_error_write(srv, __FILE__, __LINE__, "s", error);
182bcdc6a3bSJan Kneschke 
183bcdc6a3bSJan Kneschke 			plugin_free(p);
184bcdc6a3bSJan Kneschke 			return -1;
185bcdc6a3bSJan Kneschke 		}
186bcdc6a3bSJan Kneschke 
187bcdc6a3bSJan Kneschke #endif
188bcdc6a3bSJan Kneschke 		if ((*init)(p)) {
189bcdc6a3bSJan Kneschke 			log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin init failed" );
190bcdc6a3bSJan Kneschke 
191bcdc6a3bSJan Kneschke 			plugin_free(p);
192bcdc6a3bSJan Kneschke 			return -1;
193bcdc6a3bSJan Kneschke 		}
194bcdc6a3bSJan Kneschke #if 0
195bcdc6a3bSJan Kneschke 		log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin loaded" );
196bcdc6a3bSJan Kneschke #endif
197bcdc6a3bSJan Kneschke 		plugins_register(srv, p);
198bcdc6a3bSJan Kneschke 	}
199bcdc6a3bSJan Kneschke 
200bcdc6a3bSJan Kneschke 	return 0;
201bcdc6a3bSJan Kneschke }
202bcdc6a3bSJan Kneschke 
203bcdc6a3bSJan Kneschke #define PLUGIN_TO_SLOT(x, y) \
204bcdc6a3bSJan Kneschke 	handler_t plugins_call_##y(server *srv, connection *con) {\
205bcdc6a3bSJan Kneschke 		plugin **slot;\
206bcdc6a3bSJan Kneschke 		size_t j;\
207bcdc6a3bSJan Kneschke                 if (!srv->plugin_slots) return HANDLER_GO_ON;\
208bcdc6a3bSJan Kneschke                 slot = ((plugin ***)(srv->plugin_slots))[x];\
209bcdc6a3bSJan Kneschke 		if (!slot) return HANDLER_GO_ON;\
210bcdc6a3bSJan Kneschke 		for (j = 0; j < srv->plugins.used && slot[j]; j++) { \
211bcdc6a3bSJan Kneschke 			plugin *p = slot[j];\
212bcdc6a3bSJan Kneschke 			handler_t r;\
213bcdc6a3bSJan Kneschke 			switch(r = p->y(srv, con, p->data)) {\
214bcdc6a3bSJan Kneschke 			case HANDLER_GO_ON:\
215bcdc6a3bSJan Kneschke 				break;\
216bcdc6a3bSJan Kneschke 			case HANDLER_FINISHED:\
217bcdc6a3bSJan Kneschke 			case HANDLER_COMEBACK:\
218bcdc6a3bSJan Kneschke 			case HANDLER_WAIT_FOR_EVENT:\
219bcdc6a3bSJan Kneschke 			case HANDLER_WAIT_FOR_FD:\
220bcdc6a3bSJan Kneschke 			case HANDLER_ERROR:\
221bcdc6a3bSJan Kneschke 				return r;\
222bcdc6a3bSJan Kneschke 			default:\
223bcdc6a3bSJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "sbs", #x, p->name, "unknown state");\
224bcdc6a3bSJan Kneschke 				return HANDLER_ERROR;\
225bcdc6a3bSJan Kneschke 			}\
226bcdc6a3bSJan Kneschke 		}\
227bcdc6a3bSJan Kneschke 		return HANDLER_GO_ON;\
228bcdc6a3bSJan Kneschke 	}
229bcdc6a3bSJan Kneschke 
230bcdc6a3bSJan Kneschke /**
231bcdc6a3bSJan Kneschke  * plugins that use
232bcdc6a3bSJan Kneschke  *
233bcdc6a3bSJan Kneschke  * - server *srv
234bcdc6a3bSJan Kneschke  * - connection *con
235bcdc6a3bSJan Kneschke  * - void *p_d (plugin_data *)
236bcdc6a3bSJan Kneschke  */
237bcdc6a3bSJan Kneschke 
238bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean)
239bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw)
240bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done)
241bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close)
242bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST, handle_subrequest)
243bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST_START, handle_subrequest_start)
244bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_JOBLIST, handle_joblist)
245bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_DOCROOT, handle_docroot)
2466adaad54SJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_PHYSICAL, handle_physical)
247bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET, connection_reset)
248bcdc6a3bSJan Kneschke 
249bcdc6a3bSJan Kneschke #undef PLUGIN_TO_SLOT
250bcdc6a3bSJan Kneschke 
251bcdc6a3bSJan Kneschke #define PLUGIN_TO_SLOT(x, y) \
252bcdc6a3bSJan Kneschke 	handler_t plugins_call_##y(server *srv) {\
253bcdc6a3bSJan Kneschke 		plugin **slot;\
254bcdc6a3bSJan Kneschke 		size_t j;\
255bcdc6a3bSJan Kneschke                 if (!srv->plugin_slots) return HANDLER_GO_ON;\
256bcdc6a3bSJan Kneschke                 slot = ((plugin ***)(srv->plugin_slots))[x];\
257bcdc6a3bSJan Kneschke 		if (!slot) return HANDLER_GO_ON;\
258bcdc6a3bSJan Kneschke 		for (j = 0; j < srv->plugins.used && slot[j]; j++) { \
259bcdc6a3bSJan Kneschke 			plugin *p = slot[j];\
260bcdc6a3bSJan Kneschke 			handler_t r;\
261bcdc6a3bSJan Kneschke 			switch(r = p->y(srv, p->data)) {\
262bcdc6a3bSJan Kneschke 			case HANDLER_GO_ON:\
263bcdc6a3bSJan Kneschke 				break;\
264bcdc6a3bSJan Kneschke 			case HANDLER_FINISHED:\
265bcdc6a3bSJan Kneschke 			case HANDLER_COMEBACK:\
266bcdc6a3bSJan Kneschke 			case HANDLER_WAIT_FOR_EVENT:\
267bcdc6a3bSJan Kneschke 			case HANDLER_WAIT_FOR_FD:\
268bcdc6a3bSJan Kneschke 			case HANDLER_ERROR:\
269bcdc6a3bSJan Kneschke 				return r;\
270bcdc6a3bSJan Kneschke 			default:\
271bcdc6a3bSJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "sbsd", #x, p->name, "unknown state:", r);\
272bcdc6a3bSJan Kneschke 				return HANDLER_ERROR;\
273bcdc6a3bSJan Kneschke 			}\
274bcdc6a3bSJan Kneschke 		}\
275bcdc6a3bSJan Kneschke 		return HANDLER_GO_ON;\
276bcdc6a3bSJan Kneschke 	}
277bcdc6a3bSJan Kneschke 
278bcdc6a3bSJan Kneschke /**
279bcdc6a3bSJan Kneschke  * plugins that use
280bcdc6a3bSJan Kneschke  *
281bcdc6a3bSJan Kneschke  * - server *srv
282bcdc6a3bSJan Kneschke  * - void *p_d (plugin_data *)
283bcdc6a3bSJan Kneschke  */
284bcdc6a3bSJan Kneschke 
285bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger)
286bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup)
287bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup)
288bcdc6a3bSJan Kneschke PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults)
289bcdc6a3bSJan Kneschke 
290bcdc6a3bSJan Kneschke #undef PLUGIN_TO_SLOT
291bcdc6a3bSJan Kneschke 
292bcdc6a3bSJan Kneschke #if 0
293bcdc6a3bSJan Kneschke /**
294bcdc6a3bSJan Kneschke  *
295bcdc6a3bSJan Kneschke  * special handler
296bcdc6a3bSJan Kneschke  *
297bcdc6a3bSJan Kneschke  */
298bcdc6a3bSJan Kneschke handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) {
299bcdc6a3bSJan Kneschke 	size_t i;
300bcdc6a3bSJan Kneschke 	plugin **ps;
301bcdc6a3bSJan Kneschke 
302bcdc6a3bSJan Kneschke 	ps = srv->plugins.ptr;
303bcdc6a3bSJan Kneschke 
304bcdc6a3bSJan Kneschke 	for (i = 0; i < srv->plugins.used; i++) {
305bcdc6a3bSJan Kneschke 		plugin *p = ps[i];
306bcdc6a3bSJan Kneschke 		if (p->handle_fdevent) {
307bcdc6a3bSJan Kneschke 			handler_t r;
308bcdc6a3bSJan Kneschke 			switch(r = p->handle_fdevent(srv, fdc, p->data)) {
309bcdc6a3bSJan Kneschke 			case HANDLER_GO_ON:
310bcdc6a3bSJan Kneschke 				break;
311bcdc6a3bSJan Kneschke 			case HANDLER_FINISHED:
312bcdc6a3bSJan Kneschke 			case HANDLER_COMEBACK:
313bcdc6a3bSJan Kneschke 			case HANDLER_WAIT_FOR_EVENT:
314bcdc6a3bSJan Kneschke 			case HANDLER_ERROR:
315bcdc6a3bSJan Kneschke 				return r;
316bcdc6a3bSJan Kneschke 			default:
317bcdc6a3bSJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "d", r);
318bcdc6a3bSJan Kneschke 				break;
319bcdc6a3bSJan Kneschke 			}
320bcdc6a3bSJan Kneschke 		}
321bcdc6a3bSJan Kneschke 	}
322bcdc6a3bSJan Kneschke 
323bcdc6a3bSJan Kneschke 	return HANDLER_GO_ON;
324bcdc6a3bSJan Kneschke }
325bcdc6a3bSJan Kneschke #endif
326bcdc6a3bSJan Kneschke /**
327bcdc6a3bSJan Kneschke  *
328bcdc6a3bSJan Kneschke  * - call init function of all plugins to init the plugin-internals
329bcdc6a3bSJan Kneschke  * - added each plugin that supports has callback to the corresponding slot
330bcdc6a3bSJan Kneschke  *
331bcdc6a3bSJan Kneschke  * - is only called once.
332bcdc6a3bSJan Kneschke  */
333bcdc6a3bSJan Kneschke 
334bcdc6a3bSJan Kneschke handler_t plugins_call_init(server *srv) {
335bcdc6a3bSJan Kneschke 	size_t i;
336bcdc6a3bSJan Kneschke 	plugin **ps;
337bcdc6a3bSJan Kneschke 
338bcdc6a3bSJan Kneschke 	ps = srv->plugins.ptr;
339bcdc6a3bSJan Kneschke 
340bcdc6a3bSJan Kneschke 	/* fill slots */
341bcdc6a3bSJan Kneschke 
342bcdc6a3bSJan Kneschke 	srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps));
343bcdc6a3bSJan Kneschke 
344bcdc6a3bSJan Kneschke 	for (i = 0; i < srv->plugins.used; i++) {
345bcdc6a3bSJan Kneschke 		size_t j;
346bcdc6a3bSJan Kneschke 		/* check which calls are supported */
347bcdc6a3bSJan Kneschke 
348bcdc6a3bSJan Kneschke 		plugin *p = ps[i];
349bcdc6a3bSJan Kneschke 
350bcdc6a3bSJan Kneschke #define PLUGIN_TO_SLOT(x, y) \
351bcdc6a3bSJan Kneschke 	if (p->y) { \
352bcdc6a3bSJan Kneschke 		plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \
353bcdc6a3bSJan Kneschke 		if (!slot) { \
354bcdc6a3bSJan Kneschke 			slot = calloc(srv->plugins.used, sizeof(*slot));\
355bcdc6a3bSJan Kneschke 			((plugin ***)(srv->plugin_slots))[x] = slot; \
356bcdc6a3bSJan Kneschke 		} \
357bcdc6a3bSJan Kneschke 		for (j = 0; j < srv->plugins.used; j++) { \
358bcdc6a3bSJan Kneschke 			if (slot[j]) continue;\
359bcdc6a3bSJan Kneschke 			slot[j] = p;\
360bcdc6a3bSJan Kneschke 			break;\
361bcdc6a3bSJan Kneschke 		}\
362bcdc6a3bSJan Kneschke 	}
363bcdc6a3bSJan Kneschke 
364bcdc6a3bSJan Kneschke 
365bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
366bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
367bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done);
368bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close);
369bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger);
370bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup);
371bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST, handle_subrequest);
372bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SUBREQUEST_START, handle_subrequest_start);
373bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_JOBLIST, handle_joblist);
374bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_DOCROOT, handle_docroot);
3756adaad54SJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_PHYSICAL, handle_physical);
376bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET, connection_reset);
377bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup);
378bcdc6a3bSJan Kneschke 		PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults);
379bcdc6a3bSJan Kneschke #undef PLUGIN_TO_SLOT
380bcdc6a3bSJan Kneschke 
381bcdc6a3bSJan Kneschke 		if (p->init) {
382bcdc6a3bSJan Kneschke 			if (NULL == (p->data = p->init())) {
383bcdc6a3bSJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "sb",
384bcdc6a3bSJan Kneschke 						"plugin-init failed for module", p->name);
385bcdc6a3bSJan Kneschke 				return HANDLER_ERROR;
386bcdc6a3bSJan Kneschke 			}
387bcdc6a3bSJan Kneschke 
388bcdc6a3bSJan Kneschke 			/* used for con->mode, DIRECT == 0, plugins above that */
389bcdc6a3bSJan Kneschke 			((plugin_data *)(p->data))->id = i + 1;
390bcdc6a3bSJan Kneschke 
391bcdc6a3bSJan Kneschke 			if (p->version != LIGHTTPD_VERSION_ID) {
392bcdc6a3bSJan Kneschke 				log_error_write(srv, __FILE__, __LINE__, "sb",
393bcdc6a3bSJan Kneschke 						"plugin-version doesn't match lighttpd-version for", p->name);
394bcdc6a3bSJan Kneschke 				return HANDLER_ERROR;
395bcdc6a3bSJan Kneschke 			}
396bcdc6a3bSJan Kneschke 		} else {
397bcdc6a3bSJan Kneschke 			p->data = NULL;
398bcdc6a3bSJan Kneschke 		}
399bcdc6a3bSJan Kneschke 	}
400bcdc6a3bSJan Kneschke 
401bcdc6a3bSJan Kneschke 	return HANDLER_GO_ON;
402bcdc6a3bSJan Kneschke }
403bcdc6a3bSJan Kneschke 
404bcdc6a3bSJan Kneschke void plugins_free(server *srv) {
405bcdc6a3bSJan Kneschke 	size_t i;
406bcdc6a3bSJan Kneschke 	plugins_call_cleanup(srv);
407bcdc6a3bSJan Kneschke 
408bcdc6a3bSJan Kneschke 	for (i = 0; i < srv->plugins.used; i++) {
409bcdc6a3bSJan Kneschke 		plugin *p = ((plugin **)srv->plugins.ptr)[i];
410bcdc6a3bSJan Kneschke 
411bcdc6a3bSJan Kneschke 		plugin_free(p);
412bcdc6a3bSJan Kneschke 	}
413bcdc6a3bSJan Kneschke 
414bcdc6a3bSJan Kneschke 	for (i = 0; srv->plugin_slots && i < PLUGIN_FUNC_SIZEOF; i++) {
415bcdc6a3bSJan Kneschke 		plugin **slot = ((plugin ***)(srv->plugin_slots))[i];
416bcdc6a3bSJan Kneschke 
417bcdc6a3bSJan Kneschke 		if (slot) free(slot);
418bcdc6a3bSJan Kneschke 	}
419bcdc6a3bSJan Kneschke 
420bcdc6a3bSJan Kneschke 	free(srv->plugin_slots);
421bcdc6a3bSJan Kneschke 	srv->plugin_slots = NULL;
422bcdc6a3bSJan Kneschke 
423bcdc6a3bSJan Kneschke 	free(srv->plugins.ptr);
424bcdc6a3bSJan Kneschke 	srv->plugins.ptr = NULL;
425bcdc6a3bSJan Kneschke }
426