blob: 84de2627add14a564bcb69d9fc8fa66451c7b253 [file] [log] [blame]
Igor Sysoev9bf11aa2006-01-16 14:56:53 +00001
2/*
3 * Copyright (C) Igor Sysoev
4 */
5
6
7#include <ngx_config.h>
8#include <ngx_core.h>
9#include <ngx_http.h>
10#include <ngx_http_perl_module.h>
11
12
13typedef struct {
14 PerlInterpreter **free_perls;
15 ngx_uint_t interp;
16 ngx_uint_t nalloc;
17 ngx_uint_t interp_max;
18
19 PerlInterpreter *perl;
20 ngx_str_t modules;
21 ngx_array_t requires;
22} ngx_http_perl_main_conf_t;
23
24
25typedef struct {
26 SV *sub;
27 ngx_str_t handler;
28} ngx_http_perl_loc_conf_t;
29
30
31typedef struct {
32 SV *sub;
33 ngx_str_t handler;
34} ngx_http_perl_variable_t;
35
36
Igor Sysoevcce886c2006-02-22 19:41:39 +000037#if (NGX_HTTP_SSI)
Igor Sysoev9bf11aa2006-01-16 14:56:53 +000038static ngx_int_t ngx_http_perl_ssi(ngx_http_request_t *r,
39 ngx_http_ssi_ctx_t *ssi_ctx, ngx_str_t **params);
Igor Sysoevcce886c2006-02-22 19:41:39 +000040#endif
41
Igor Sysoev6d16e1e2006-04-05 13:40:54 +000042static void ngx_http_perl_handle_request(ngx_http_request_t *r);
Igor Sysoev9bf11aa2006-01-16 14:56:53 +000043static ngx_int_t
44 ngx_http_perl_get_interpreter(ngx_http_perl_main_conf_t *pmcf,
45 PerlInterpreter **perl, ngx_log_t *log);
46static ngx_inline void
47 ngx_http_perl_free_interpreter(ngx_http_perl_main_conf_t *pmcf,
48 PerlInterpreter *perl);
49static char *ngx_http_perl_init_interpreter(ngx_conf_t *cf,
50 ngx_http_perl_main_conf_t *pmcf);
51static PerlInterpreter *
52 ngx_http_perl_create_interpreter(ngx_http_perl_main_conf_t *pmcf,
53 ngx_log_t *log);
54static ngx_int_t ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r,
55 SV *sub, ngx_str_t **args, ngx_str_t *handler, ngx_str_t *rv);
56static void ngx_http_perl_eval_anon_sub(pTHX_ ngx_str_t *handler, SV **sv);
57
58static ngx_int_t ngx_http_perl_preconfiguration(ngx_conf_t *cf);
59static void *ngx_http_perl_create_main_conf(ngx_conf_t *cf);
60static char *ngx_http_perl_init_main_conf(ngx_conf_t *cf, void *conf);
61static void *ngx_http_perl_create_loc_conf(ngx_conf_t *cf);
62static char *ngx_http_perl_merge_loc_conf(ngx_conf_t *cf, void *parent,
63 void *child);
64static char *ngx_http_perl_require(ngx_conf_t *cf, ngx_command_t *cmd,
65 void *conf);
66static char *ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
67static char *ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
68static char *ngx_http_perl_interp_max_unsupported(ngx_conf_t *cf, void *post,
69 void *data);
70static void ngx_http_perl_cleanup_perl(void *data);
71
72
73static ngx_conf_post_handler_pt ngx_http_perl_interp_max_p =
74 ngx_http_perl_interp_max_unsupported;
75
76
77static ngx_command_t ngx_http_perl_commands[] = {
78
79 { ngx_string("perl_modules"),
80 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
81 ngx_conf_set_str_slot,
82 NGX_HTTP_MAIN_CONF_OFFSET,
83 offsetof(ngx_http_perl_main_conf_t, modules),
84 NULL },
85
86 { ngx_string("perl_require"),
87 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
88 ngx_http_perl_require,
89 NGX_HTTP_MAIN_CONF_OFFSET,
90 0,
91 NULL },
92
93 { ngx_string("perl_interp_max"),
94 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
95 ngx_conf_set_num_slot,
96 NGX_HTTP_MAIN_CONF_OFFSET,
97 offsetof(ngx_http_perl_main_conf_t, interp_max),
98 &ngx_http_perl_interp_max_p },
99
100 { ngx_string("perl"),
101 NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
102 ngx_http_perl,
103 NGX_HTTP_LOC_CONF_OFFSET,
104 0,
105 NULL },
106
107 { ngx_string("perl_set"),
108 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2,
109 ngx_http_perl_set,
110 NGX_HTTP_LOC_CONF_OFFSET,
111 0,
112 NULL },
113
114 ngx_null_command
115};
116
117
118static ngx_http_module_t ngx_http_perl_module_ctx = {
119 ngx_http_perl_preconfiguration, /* preconfiguration */
120 NULL, /* postconfiguration */
121
122 ngx_http_perl_create_main_conf, /* create main configuration */
123 ngx_http_perl_init_main_conf, /* init main configuration */
124
125 NULL, /* create server configuration */
126 NULL, /* merge server configuration */
127
128 ngx_http_perl_create_loc_conf, /* create location configuration */
129 ngx_http_perl_merge_loc_conf /* merge location configuration */
130};
131
132
133ngx_module_t ngx_http_perl_module = {
134 NGX_MODULE_V1,
135 &ngx_http_perl_module_ctx, /* module context */
136 ngx_http_perl_commands, /* module directives */
137 NGX_HTTP_MODULE, /* module type */
138 NULL, /* init master */
139 NULL, /* init module */
140 NULL, /* init process */
141 NULL, /* init thread */
142 NULL, /* exit thread */
143 NULL, /* exit process */
144 NULL, /* exit master */
145 NGX_MODULE_V1_PADDING
146};
147
148
Igor Sysoevcce886c2006-02-22 19:41:39 +0000149#if (NGX_HTTP_SSI)
150
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000151#define NGX_HTTP_PERL_SSI_SUB 0
152#define NGX_HTTP_PERL_SSI_ARG 1
153
154
155static ngx_http_ssi_param_t ngx_http_perl_ssi_params[] = {
156 { ngx_string("sub"), NGX_HTTP_PERL_SSI_SUB, 1, 0 },
157 { ngx_string("arg"), NGX_HTTP_PERL_SSI_ARG, 0, 1 },
158 { ngx_null_string, 0, 0, 0 }
159};
160
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000161static ngx_http_ssi_command_t ngx_http_perl_ssi_command = {
162 ngx_string("perl"), ngx_http_perl_ssi, ngx_http_perl_ssi_params, 0, 1
163};
164
Igor Sysoevcce886c2006-02-22 19:41:39 +0000165#endif
166
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000167
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000168static HV *nginx_stash;
169
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000170static void
171ngx_http_perl_xs_init(pTHX)
172{
173 newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, __FILE__);
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000174
175 nginx_stash = gv_stashpv("nginx", TRUE);
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000176}
177
178
179static ngx_int_t
180ngx_http_perl_handler(ngx_http_request_t *r)
181{
Igor Sysoev6d16e1e2006-04-05 13:40:54 +0000182 ngx_int_t rc;
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000183
184 /* TODO: Win32 */
185 if (r->zero_in_uri) {
186 return NGX_HTTP_NOT_FOUND;
187 }
188
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000189 r->request_body_in_single_buf = 1;
190 r->request_body_in_persistent_file = 1;
191
Igor Sysoev6d16e1e2006-04-05 13:40:54 +0000192 rc = ngx_http_read_client_request_body(r, ngx_http_perl_handle_request);
193
194 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
195 return rc;
196 }
197
198 return NGX_DONE;
199}
200
201
202static void
203ngx_http_perl_handle_request(ngx_http_request_t *r)
204{
205 ngx_int_t rc;
206 ngx_str_t uri, args;
207 ngx_http_perl_ctx_t *ctx;
208 ngx_http_perl_loc_conf_t *plcf;
209 ngx_http_perl_main_conf_t *pmcf;
210
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000211 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl handler");
212
213 /* mod_perl's content handler assumes that content type was already set */
214
215 if (ngx_http_set_content_type(r) != NGX_OK) {
Igor Sysoev6d16e1e2006-04-05 13:40:54 +0000216 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
217 return;
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000218 }
219
220 ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
221
222 if (ctx == NULL) {
223 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t));
224 if (ctx == NULL) {
Igor Sysoev6d16e1e2006-04-05 13:40:54 +0000225 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
226 return;
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000227 }
228
229 ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
230 }
231
232 pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
233
234 rc = ngx_http_perl_get_interpreter(pmcf, &ctx->perl, r->connection->log);
235
236 if (rc != NGX_OK) {
Igor Sysoev6d16e1e2006-04-05 13:40:54 +0000237 ngx_http_finalize_request(r, rc);
238 return;
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000239 }
240
241 {
242
243 dTHXa(ctx->perl);
244
245 plcf = ngx_http_get_module_loc_conf(r, ngx_http_perl_module);
246
247 rc = ngx_http_perl_call_handler(aTHX_ r, plcf->sub, NULL,
248 &plcf->handler, NULL);
249
250 }
251
252 ngx_http_perl_free_interpreter(pmcf, ctx->perl);
253
254 if (rc > 600) {
255 rc = NGX_OK;
256 }
257
258 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
259 "perl handler done: %i", rc);
260
261 if (ctx->redirect_uri.len) {
262 uri = ctx->redirect_uri;
263 args = ctx->redirect_args;
Igor Sysoev6d16e1e2006-04-05 13:40:54 +0000264
265 } else {
266 uri.len = 0;
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000267 }
268
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000269 ctx->filename.data = NULL;
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000270 ctx->redirect_uri.len = 0;
271
272 if (uri.len) {
Igor Sysoev6d16e1e2006-04-05 13:40:54 +0000273 ngx_http_internal_redirect(r, &uri, &args);
274 return;
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000275 }
276
277 if (rc == NGX_OK || rc == NGX_HTTP_OK) {
Igor Sysoev6d16e1e2006-04-05 13:40:54 +0000278 ngx_http_send_special(r, NGX_HTTP_LAST);
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000279 }
280
Igor Sysoev6d16e1e2006-04-05 13:40:54 +0000281 ngx_http_finalize_request(r, rc);
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000282}
283
284
285static ngx_int_t
286ngx_http_perl_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
287 uintptr_t data)
288{
289 ngx_http_perl_variable_t *pv = (ngx_http_perl_variable_t *) data;
290
291 ngx_int_t rc;
292 ngx_str_t value;
293 ngx_http_perl_ctx_t *ctx;
294 ngx_http_perl_main_conf_t *pmcf;
295
296 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
297 "perl variable handler");
298
299 ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
300
301 if (ctx == NULL) {
302 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t));
303 if (ctx == NULL) {
304 return NGX_ERROR;
305 }
306
307 ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
308 }
309
310 pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
311
312 rc = ngx_http_perl_get_interpreter(pmcf, &ctx->perl, r->connection->log);
313
314 if (rc != NGX_OK) {
315 return rc;
316 }
317
318 value.data = NULL;
319
320 {
321
322 dTHXa(ctx->perl);
323
324 rc = ngx_http_perl_call_handler(aTHX_ r, pv->sub, NULL,
325 &pv->handler, &value);
326
327 }
328
329 ngx_http_perl_free_interpreter(pmcf, ctx->perl);
330
331 if (value.data) {
332 v->len = value.len;
333 v->valid = 1;
334 v->no_cachable = 0;
335 v->not_found = 0;
336 v->data = value.data;
337
338 } else {
339 v->not_found = 1;
340 }
341
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000342 ctx->filename.data = NULL;
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000343 ctx->redirect_uri.len = 0;
344
345 return rc;
346}
347
348
Igor Sysoevcce886c2006-02-22 19:41:39 +0000349#if (NGX_HTTP_SSI)
350
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000351static ngx_int_t
352ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx,
353 ngx_str_t **params)
354{
355 SV *sv;
356 ngx_int_t rc;
357 ngx_str_t *handler;
358 ngx_http_perl_ctx_t *ctx;
359 ngx_http_perl_main_conf_t *pmcf;
360
361 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
362 "perl ssi handler");
363
364 pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
365
366 ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
367
368 if (ctx == NULL) {
369 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t));
370 if (ctx == NULL) {
371 return NGX_ERROR;
372 }
373
374 ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
375 }
376
377 rc = ngx_http_perl_get_interpreter(pmcf, &ctx->perl, r->connection->log);
378
379 if (rc != NGX_OK) {
380 return rc;
381 }
382
383 ctx->ssi = ssi_ctx;
384
385 handler = params[NGX_HTTP_PERL_SSI_SUB];
386 handler->data[handler->len] = '\0';
387
388 {
389
390 dTHXa(ctx->perl);
391
392#if 0
393
394 ngx_http_perl_eval_anon_sub(aTHX_ handler, &sv);
395
396 if (sv == &PL_sv_undef) {
397 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
398 "eval_pv(\"%V\") failed", handler);
399 return NGX_ERROR;
400 }
401
402 if (sv == NULL) {
403 sv = newSVpvn((char *) handler->data, handler->len);
404 }
405
406#endif
407
408 sv = newSVpvn((char *) handler->data, handler->len);
409
410 rc = ngx_http_perl_call_handler(aTHX_ r, sv, &params[NGX_HTTP_PERL_SSI_ARG],
411 handler, NULL);
412
413 SvREFCNT_dec(sv);
414
415 }
416
417 ngx_http_perl_free_interpreter(pmcf, ctx->perl);
418
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000419 ctx->filename.data = NULL;
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000420 ctx->redirect_uri.len = 0;
421 ctx->ssi = NULL;
422
423 return rc;
424}
425
Igor Sysoevcce886c2006-02-22 19:41:39 +0000426#endif
427
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000428
429static ngx_int_t
430ngx_http_perl_get_interpreter(ngx_http_perl_main_conf_t *pmcf,
431 PerlInterpreter **perl, ngx_log_t *log)
432{
433 if (pmcf->interp) {
434 pmcf->interp--;
435
436 *perl = pmcf->free_perls[pmcf->interp];
437
438 return NGX_OK;
439 }
440
441 if (pmcf->nalloc < pmcf->interp_max) {
442 *perl = ngx_http_perl_create_interpreter(pmcf, log);
443
444 if (*perl) {
445 return NGX_OK;
446 }
447
448 return NGX_HTTP_INTERNAL_SERVER_ERROR;
449 }
450
451 ngx_log_error(NGX_LOG_ALERT, log, 0, "no free perl interpreter");
452
453 return NGX_HTTP_SERVICE_UNAVAILABLE;
454}
455
456
457static ngx_inline void
458ngx_http_perl_free_interpreter(ngx_http_perl_main_conf_t *pmcf,
459 PerlInterpreter *perl)
460{
461 pmcf->free_perls[pmcf->interp++] = perl;
462}
463
464
465static char *
466ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf)
467{
468 ngx_pool_cleanup_t *cln;
469
470 cln = ngx_pool_cleanup_add(cf->pool, 0);
471 if (cln == NULL) {
472 return NGX_CONF_ERROR;
473 }
474
475#ifdef NGX_PERL_MODULES
476 if (pmcf->modules.data == NULL) {
477 pmcf->modules.data = NGX_PERL_MODULES;
478 }
479#endif
480
Igor Sysoev6d16e1e2006-04-05 13:40:54 +0000481 if (ngx_conf_full_name(cf->cycle, &pmcf->modules) != NGX_OK) {
482 return NGX_CONF_ERROR;
483 }
484
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000485 PERL_SYS_INIT(&ngx_argc, &ngx_argv);
486
487 pmcf->perl = ngx_http_perl_create_interpreter(pmcf, cf->log);
488
489 if (pmcf->perl == NULL) {
490 PERL_SYS_TERM();
491 return NGX_CONF_ERROR;
492 }
493
494 cln->handler = ngx_http_perl_cleanup_perl;
495 cln->data = pmcf->perl;
496
497 return NGX_CONF_OK;
498}
499
500
501static PerlInterpreter *
502ngx_http_perl_create_interpreter(ngx_http_perl_main_conf_t *pmcf,
503 ngx_log_t *log)
504{
505 int n;
506 char *embedding[6];
507 char **script;
508 STRLEN len;
509 ngx_str_t err;
510 ngx_uint_t i;
511 PerlInterpreter *perl;
512
513 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "create perl interpreter");
514
515#if (NGX_HAVE_PERL_CLONE)
516
517 if (pmcf->perl) {
518
519 perl = perl_clone(pmcf->perl, CLONEf_KEEP_PTR_TABLE);
520 if (perl == NULL) {
521 ngx_log_error(NGX_LOG_ALERT, log, 0, "perl_clone() failed");
522 return NULL;
523 }
524
525 {
526
527 dTHXa(perl);
528
529 ptr_table_free(PL_ptr_table);
530 PL_ptr_table = NULL;
531
532 }
533
534 pmcf->nalloc++;
535
536 return perl;
537 }
538
539#endif
540
541 perl = perl_alloc();
542 if (perl == NULL) {
543 ngx_log_error(NGX_LOG_ALERT, log, 0, "perl_alloc() failed");
544 return NULL;
545 }
546
547 perl_construct(perl);
548
549 {
550
551 dTHXa(perl);
552
553#ifdef PERL_EXIT_DESTRUCT_END
554 PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
555#endif
556
557 embedding[0] = "";
558
559 if (pmcf->modules.data) {
560 embedding[1] = "-I";
561 embedding[2] = (char *) pmcf->modules.data;
562 n = 3;
563
564 } else {
565 n = 1;
566 }
567
568 embedding[n++] = "-Mnginx";
569 embedding[n++] = "-e";
570 embedding[n++] = "0";
571
572 n = perl_parse(perl, ngx_http_perl_xs_init, n, embedding, NULL);
573
574 if (n != 0) {
575 ngx_log_error(NGX_LOG_ALERT, log, 0, "perl_parse() failed: %d", n);
576 goto fail;
577 }
578
579 script = pmcf->requires.elts;
580 for (i = 0; i < pmcf->requires.nelts; i++) {
581 require_pv(script[i]);
582
583 if (SvTRUE(ERRSV)) {
584
585 err.data = (u_char *) SvPV(ERRSV, len);
586 for (len--; err.data[len] == LF || err.data[len] == CR; len--) {
587 /* void */
588 }
589 err.len = len + 1;
590
591 ngx_log_error(NGX_LOG_EMERG, log, 0,
592 "require_pv(\"%s\") failed: \"%V\"", script[i], &err);
593 goto fail;
594 }
595 }
596
597 }
598
599 pmcf->nalloc++;
600
601 return perl;
602
603fail:
604
605 (void) perl_destruct(perl);
606
607 perl_free(perl);
608
609 return NULL;
610}
611
612
613#if (__INTEL_COMPILER)
614/*
615 * disable 'declaration hides parameter "my_perl"' warning for ENTER and LEAVE
616 */
617#pragma warning(disable:1599)
618#endif
619
620
621static ngx_int_t
622ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, SV *sub,
623 ngx_str_t **args, ngx_str_t *handler, ngx_str_t *rv)
624{
625 SV *sv;
626 int n, status;
627 char *line;
628 STRLEN len, n_a;
629 ngx_str_t err;
630 ngx_uint_t i;
631
632 dSP;
633
634 status = 0;
635
636 ENTER;
637 SAVETMPS;
638
639 PUSHMARK(sp);
640
Igor Sysoev8a2b2fb2006-04-14 09:53:38 +0000641 sv = sv_2mortal(sv_bless(newRV_noinc(newSViv(PTR2IV(r))), nginx_stash));
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000642 XPUSHs(sv);
643
644 if (args) {
645 for (i = 0; args[i]; i++) { /* void */ }
646
647 EXTEND(sp, (int) i);
648
649 for (i = 0; args[i]; i++) {
650 PUSHs(sv_2mortal(newSVpvn((char *) args[i]->data, args[i]->len)));
651 }
652 }
653
654 PUTBACK;
655
656 n = call_sv(sub, G_EVAL);
657
658 SPAGAIN;
659
660 if (n) {
661 if (rv == NULL) {
662 status = POPi;
663
664 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
665 "call_sv: %d", status);
666
667 } else {
Igor Sysoev13c68742006-03-10 12:51:52 +0000668 line = SvPVx(POPs, n_a);
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000669 rv->len = n_a;
670
671 rv->data = ngx_palloc(r->pool, n_a);
672 if (rv->data == NULL) {
673 return NGX_ERROR;
674 }
675
676 ngx_memcpy(rv->data, line, n_a);
677 }
678 }
679
680 PUTBACK;
681
682 FREETMPS;
683 LEAVE;
684
685 /* check $@ */
686
687 if (SvTRUE(ERRSV)) {
688
689 err.data = (u_char *) SvPV(ERRSV, len);
690 for (len--; err.data[len] == LF || err.data[len] == CR; len--) {
691 /* void */
692 }
693 err.len = len + 1;
694
695 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
696 "call_sv(\"%V\") failed: \"%V\"",
697 handler, &err);
698
699 if (rv) {
700 return NGX_ERROR;
701 }
702
703 return NGX_HTTP_INTERNAL_SERVER_ERROR;
704 }
705
706 if (n != 1) {
707 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
708 "call_sv(\"%V\") returned %d results", handler, n);
709 status = NGX_OK;
710 }
711
712 if (rv) {
713 return NGX_OK;
714 }
715
716 return (ngx_int_t) status;
717}
718
719
720#if (__INTEL_COMPILER)
721#pragma warning(default:1599)
722#endif
723
724
725static void
726ngx_http_perl_eval_anon_sub(pTHX_ ngx_str_t *handler, SV **sv)
727{
Igor Sysoev8fea8852006-03-15 09:53:04 +0000728 u_char *p;
729
730 for (p = handler->data; *p; p++) {
731 if (*p != ' ' && *p != '\t' && *p != CR && *p != LF) {
732 break;
733 }
734 }
735
736 if (ngx_strncmp(p, "sub ", 4) == 0
737 || ngx_strncmp(p, "use ", 4) == 0)
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000738 {
Igor Sysoev8fea8852006-03-15 09:53:04 +0000739 *sv = eval_pv((char *) p, FALSE);
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000740
741 return;
742 }
743
744 *sv = NULL;
745}
746
747
748static void *
749ngx_http_perl_create_main_conf(ngx_conf_t *cf)
750{
751 ngx_http_perl_main_conf_t *pmcf;
752
753 pmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_perl_main_conf_t));
754 if (pmcf == NULL) {
755 return NGX_CONF_ERROR;
756 }
757
758 pmcf->interp_max = NGX_CONF_UNSET_UINT;
759
760 if (ngx_array_init(&pmcf->requires, cf->pool, 1, sizeof(u_char *))
761 != NGX_OK)
762 {
763 return NULL;
764 }
765
766 return pmcf;
767}
768
769
770static char *
771ngx_http_perl_init_main_conf(ngx_conf_t *cf, void *conf)
772{
773 ngx_http_perl_main_conf_t *pmcf = conf;
774
775#if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY)
776 ngx_conf_init_unsigned_value(pmcf->interp_max, 10);
777#else
778 ngx_conf_init_unsigned_value(pmcf->interp_max, 1);
779#endif
780
781 pmcf->free_perls = ngx_pcalloc(cf->pool,
782 pmcf->interp_max * sizeof(PerlInterpreter *));
783 if (pmcf->free_perls == NULL) {
784 return NGX_CONF_ERROR;
785 }
786
787 if (pmcf->perl == NULL) {
788 if (ngx_http_perl_init_interpreter(cf, pmcf) != NGX_CONF_OK) {
789 return NGX_CONF_ERROR;
790 }
791 }
792
793#if !(NGX_HAVE_PERL_CLONE)
794 ngx_http_perl_free_interpreter(pmcf, pmcf->perl);
795#endif
796
797 return NGX_CONF_OK;
798}
799
800
801static void
802ngx_http_perl_cleanup_perl(void *data)
803{
804 PerlInterpreter *perl = data;
805
806 (void) perl_destruct(perl);
807
808 perl_free(perl);
809
810 PERL_SYS_TERM();
811}
812
813
814static ngx_int_t
815ngx_http_perl_preconfiguration(ngx_conf_t *cf)
816{
Igor Sysoevcce886c2006-02-22 19:41:39 +0000817#if (NGX_HTTP_SSI)
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000818 ngx_int_t rc;
819 ngx_http_ssi_main_conf_t *smcf;
820
821 smcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_ssi_filter_module);
822
823 rc = ngx_hash_add_key(&smcf->commands, &ngx_http_perl_ssi_command.name,
824 &ngx_http_perl_ssi_command, NGX_HASH_READONLY_KEY);
825
826 if (rc != NGX_OK) {
827 if (rc == NGX_BUSY) {
828 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
829 "conflicting SSI command \"%V\"",
830 &ngx_http_perl_ssi_command.name);
831 }
832
833 return NGX_ERROR;
834 }
Igor Sysoevcce886c2006-02-22 19:41:39 +0000835#endif
Igor Sysoev9bf11aa2006-01-16 14:56:53 +0000836
837 return NGX_OK;
838}
839
840
841static void *
842ngx_http_perl_create_loc_conf(ngx_conf_t *cf)
843{
844 ngx_http_perl_loc_conf_t *plcf;
845
846 plcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_perl_loc_conf_t));
847 if (plcf == NULL) {
848 return NGX_CONF_ERROR;
849 }
850
851 /*
852 * set by ngx_pcalloc():
853 *
854 * plcf->handler = { 0, NULL };
855 */
856
857 return plcf;
858}
859
860
861static char *
862ngx_http_perl_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
863{
864 ngx_http_perl_loc_conf_t *prev = parent;
865 ngx_http_perl_loc_conf_t *conf = child;
866
867 if (conf->sub == NULL) {
868 conf->sub = prev->sub;
869 conf->handler = prev->handler;
870 }
871
872 return NGX_CONF_OK;
873}
874
875
876static char *
877ngx_http_perl_require(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
878{
879 ngx_http_perl_main_conf_t *pmcf = conf;
880
881 u_char **p;
882 ngx_str_t *value;
883
884 value = cf->args->elts;
885
886 p = ngx_array_push(&pmcf->requires);
887
888 if (p == NULL) {
889 return NGX_CONF_ERROR;
890 }
891
892 *p = value[1].data;
893
894 return NGX_CONF_OK;
895}
896
897
898static char *
899ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
900{
901 ngx_http_perl_loc_conf_t *plcf = conf;
902
903 ngx_str_t *value;
904 ngx_http_core_loc_conf_t *clcf;
905 ngx_http_perl_main_conf_t *pmcf;
906
907 value = cf->args->elts;
908
909 if (plcf->handler.data) {
910 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
911 "duplicate perl handler \"%V\"", &value[1]);
912 return NGX_CONF_ERROR;
913 }
914
915 pmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_perl_module);
916
917 if (pmcf->perl == NULL) {
918 if (ngx_http_perl_init_interpreter(cf, pmcf) != NGX_CONF_OK) {
919 return NGX_CONF_ERROR;
920 }
921 }
922
923 plcf->handler = value[1];
924
925 {
926
927 dTHXa(pmcf->perl);
928
929 ngx_http_perl_eval_anon_sub(aTHX_ &value[1], &plcf->sub);
930
931 if (plcf->sub == &PL_sv_undef) {
932 ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
933 "eval_pv(\"%V\") failed", &value[1]);
934 return NGX_CONF_ERROR;
935 }
936
937 if (plcf->sub == NULL) {
938 plcf->sub = newSVpvn((char *) value[1].data, value[1].len);
939 }
940
941 }
942
943 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
944 clcf->handler = ngx_http_perl_handler;
945
946 return NGX_CONF_OK;
947}
948
949
950static char *
951ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
952{
953 ngx_int_t index;
954 ngx_str_t *value;
955 ngx_http_variable_t *v;
956 ngx_http_perl_variable_t *pv;
957 ngx_http_perl_main_conf_t *pmcf;
958
959 value = cf->args->elts;
960
961 if (value[1].data[0] != '$') {
962 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
963 "invalid variable name \"%V\"", &value[1]);
964 return NGX_CONF_ERROR;
965 }
966
967 value[1].len--;
968 value[1].data++;
969
970 v = ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGABLE);
971 if (v == NULL) {
972 return NGX_CONF_ERROR;
973 }
974
975 pv = ngx_palloc(cf->pool, sizeof(ngx_http_perl_variable_t));
976 if (pv == NULL) {
977 return NGX_CONF_ERROR;
978 }
979
980 index = ngx_http_get_variable_index(cf, &value[1]);
981 if (index == NGX_ERROR) {
982 return NGX_CONF_ERROR;
983 }
984
985 pmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_perl_module);
986
987 if (pmcf->perl == NULL) {
988 if (ngx_http_perl_init_interpreter(cf, pmcf) != NGX_CONF_OK) {
989 return NGX_CONF_ERROR;
990 }
991 }
992
993 pv->handler = value[2];
994
995 {
996
997 dTHXa(pmcf->perl);
998
999 ngx_http_perl_eval_anon_sub(aTHX_ &value[2], &pv->sub);
1000
1001 if (pv->sub == &PL_sv_undef) {
1002 ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
1003 "eval_pv(\"%V\") failed", &value[2]);
1004 return NGX_CONF_ERROR;
1005 }
1006
1007 if (pv->sub == NULL) {
1008 pv->sub = newSVpvn((char *) value[2].data, value[2].len);
1009 }
1010
1011 }
1012
1013 v->handler = ngx_http_perl_variable;
1014 v->data = (uintptr_t) pv;
1015
1016 return NGX_CONF_OK;
1017}
1018
1019
1020static char *
1021ngx_http_perl_interp_max_unsupported(ngx_conf_t *cf, void *post, void *data)
1022{
1023#if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY)
1024
1025 return NGX_CONF_OK;
1026
1027#else
1028
1029 return "to use perl_interp_max you have to build perl with "
1030 "-Dusemultiplicity or -Dusethreads options";
1031
1032#endif
1033}