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