Groonga 3.0.9 Source Code Document
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_http_perl_module.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_http.h>
11 #include <ngx_http_perl_module.h>
12 
13 
14 typedef struct {
15  PerlInterpreter *perl;
16  HV *nginx;
20 
21 
22 typedef struct {
23  SV *sub;
26 
27 
28 typedef struct {
29  SV *sub;
32 
33 
34 #if (NGX_HTTP_SSI)
35 static ngx_int_t ngx_http_perl_ssi(ngx_http_request_t *r,
36  ngx_http_ssi_ctx_t *ssi_ctx, ngx_str_t **params);
37 #endif
38 
39 static char *ngx_http_perl_init_interpreter(ngx_conf_t *cf,
41 static PerlInterpreter *ngx_http_perl_create_interpreter(ngx_conf_t *cf,
43 static ngx_int_t ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires,
44  ngx_log_t *log);
45 static ngx_int_t ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r,
46  HV *nginx, SV *sub, SV **args, ngx_str_t *handler, ngx_str_t *rv);
47 static void ngx_http_perl_eval_anon_sub(pTHX_ ngx_str_t *handler, SV **sv);
48 
49 static ngx_int_t ngx_http_perl_preconfiguration(ngx_conf_t *cf);
50 static void *ngx_http_perl_create_main_conf(ngx_conf_t *cf);
51 static char *ngx_http_perl_init_main_conf(ngx_conf_t *cf, void *conf);
52 static void *ngx_http_perl_create_loc_conf(ngx_conf_t *cf);
53 static char *ngx_http_perl_merge_loc_conf(ngx_conf_t *cf, void *parent,
54  void *child);
55 static char *ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
56 static char *ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
57 
58 #if (NGX_HAVE_PERL_MULTIPLICITY)
59 static void ngx_http_perl_cleanup_perl(void *data);
60 #endif
61 
62 static ngx_int_t ngx_http_perl_init_worker(ngx_cycle_t *cycle);
63 static void ngx_http_perl_exit(ngx_cycle_t *cycle);
64 
65 
66 static ngx_command_t ngx_http_perl_commands[] = {
67 
68  { ngx_string("perl_modules"),
72  offsetof(ngx_http_perl_main_conf_t, modules),
73  NULL },
74 
75  { ngx_string("perl_require"),
79  offsetof(ngx_http_perl_main_conf_t, requires),
80  NULL },
81 
82  { ngx_string("perl"),
84  ngx_http_perl,
86  0,
87  NULL },
88 
89  { ngx_string("perl_set"),
91  ngx_http_perl_set,
93  0,
94  NULL },
95 
97 };
98 
99 
100 static ngx_http_module_t ngx_http_perl_module_ctx = {
101  ngx_http_perl_preconfiguration, /* preconfiguration */
102  NULL, /* postconfiguration */
103 
104  ngx_http_perl_create_main_conf, /* create main configuration */
105  ngx_http_perl_init_main_conf, /* init main configuration */
106 
107  NULL, /* create server configuration */
108  NULL, /* merge server configuration */
109 
110  ngx_http_perl_create_loc_conf, /* create location configuration */
111  ngx_http_perl_merge_loc_conf /* merge location configuration */
112 };
113 
114 
117  &ngx_http_perl_module_ctx, /* module context */
118  ngx_http_perl_commands, /* module directives */
119  NGX_HTTP_MODULE, /* module type */
120  NULL, /* init master */
121  NULL, /* init module */
122  ngx_http_perl_init_worker, /* init process */
123  NULL, /* init thread */
124  NULL, /* exit thread */
125  NULL, /* exit process */
126  ngx_http_perl_exit, /* exit master */
128 };
129 
130 
131 #if (NGX_HTTP_SSI)
132 
133 #define NGX_HTTP_PERL_SSI_SUB 0
134 #define NGX_HTTP_PERL_SSI_ARG 1
135 
136 
137 static ngx_http_ssi_param_t ngx_http_perl_ssi_params[] = {
138  { ngx_string("sub"), NGX_HTTP_PERL_SSI_SUB, 1, 0 },
139  { ngx_string("arg"), NGX_HTTP_PERL_SSI_ARG, 0, 1 },
140  { ngx_null_string, 0, 0, 0 }
141 };
142 
143 static ngx_http_ssi_command_t ngx_http_perl_ssi_command = {
144  ngx_string("perl"), ngx_http_perl_ssi, ngx_http_perl_ssi_params, 0, 0, 1
145 };
146 
147 #endif
148 
149 
150 static ngx_str_t ngx_null_name = ngx_null_string;
151 static HV *nginx_stash;
152 
153 #if (NGX_HAVE_PERL_MULTIPLICITY)
154 static ngx_uint_t ngx_perl_term;
155 #else
156 static PerlInterpreter *perl;
157 #endif
158 
159 
160 static void
161 ngx_http_perl_xs_init(pTHX)
162 {
163  newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, __FILE__);
164 
165  nginx_stash = gv_stashpv("nginx", TRUE);
166 }
167 
168 
169 static ngx_int_t
170 ngx_http_perl_handler(ngx_http_request_t *r)
171 {
172  r->main->count++;
173 
175 
176  return NGX_DONE;
177 }
178 
179 
180 void
182 {
183  SV *sub;
184  ngx_int_t rc;
185  ngx_str_t uri, args, *handler;
186  ngx_http_perl_ctx_t *ctx;
189 
190  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl handler");
191 
192  ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
193 
194  if (ctx == NULL) {
195  ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t));
196  if (ctx == NULL) {
198  return;
199  }
200 
201  ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
202  }
203 
204  pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
205 
206  {
207 
208  dTHXa(pmcf->perl);
209  PERL_SET_CONTEXT(pmcf->perl);
210 
211  if (ctx->next == NULL) {
212  plcf = ngx_http_get_module_loc_conf(r, ngx_http_perl_module);
213  sub = plcf->sub;
214  handler = &plcf->handler;
215 
216  } else {
217  sub = ctx->next;
218  handler = &ngx_null_name;
219  ctx->next = NULL;
220  }
221 
222  rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sub, NULL, handler,
223  NULL);
224 
225  }
226 
228  "perl handler done: %i", rc);
229 
230  if (rc == NGX_DONE) {
232  return;
233  }
234 
235  if (rc > 600) {
236  rc = NGX_OK;
237  }
238 
239  if (ctx->redirect_uri.len) {
240  uri = ctx->redirect_uri;
241  args = ctx->redirect_args;
242 
243  } else {
244  uri.len = 0;
245  }
246 
247  ctx->filename.data = NULL;
248  ctx->redirect_uri.len = 0;
249 
250  if (ctx->done || ctx->next) {
252  return;
253  }
254 
255  if (uri.len) {
256  ngx_http_internal_redirect(r, &uri, &args);
258  return;
259  }
260 
261  if (rc == NGX_OK || rc == NGX_HTTP_OK) {
263  ctx->done = 1;
264  }
265 
267 }
268 
269 
270 void
272 {
273  ngx_event_t *wev;
274 
276  "perl sleep handler");
277 
278  wev = r->connection->write;
279 
280  if (wev->timedout) {
281  wev->timedout = 0;
283  return;
284  }
285 
286  if (ngx_handle_write_event(wev, 0) != NGX_OK) {
288  }
289 }
290 
291 
292 static ngx_int_t
293 ngx_http_perl_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
294  uintptr_t data)
295 {
297 
298  ngx_int_t rc;
299  ngx_str_t value;
302 
304  "perl variable handler");
305 
306  ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
307 
308  if (ctx == NULL) {
309  ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t));
310  if (ctx == NULL) {
311  return NGX_ERROR;
312  }
313 
314  ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
315  }
316 
317  pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
318 
319  value.data = NULL;
320 
321  {
322 
323  dTHXa(pmcf->perl);
324  PERL_SET_CONTEXT(pmcf->perl);
325 
326  rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, pv->sub, NULL,
327  &pv->handler, &value);
328 
329  }
330 
331  if (value.data) {
332  v->len = value.len;
333  v->valid = 1;
334  v->no_cacheable = 0;
335  v->not_found = 0;
336  v->data = value.data;
337 
338  } else {
339  v->not_found = 1;
340  }
341 
342  ctx->filename.data = NULL;
343  ctx->redirect_uri.len = 0;
344 
346  "perl variable done");
347 
348  return rc;
349 }
350 
351 
352 #if (NGX_HTTP_SSI)
353 
354 static ngx_int_t
355 ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx,
356  ngx_str_t **params)
357 {
358  SV *sv, **asv;
359  ngx_int_t rc;
360  ngx_str_t *handler, **args;
361  ngx_uint_t i;
362  ngx_http_perl_ctx_t *ctx;
364 
366  "perl ssi handler");
367 
368  ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
369 
370  if (ctx == NULL) {
371  ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t));
372  if (ctx == NULL) {
373  return NGX_ERROR;
374  }
375 
376  ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
377  }
378 
379  pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
380 
381  ctx->ssi = ssi_ctx;
382 
383  handler = params[NGX_HTTP_PERL_SSI_SUB];
384  handler->data[handler->len] = '\0';
385 
386  {
387 
388  dTHXa(pmcf->perl);
389  PERL_SET_CONTEXT(pmcf->perl);
390 
391 #if 0
392 
393  /* the code is disabled to force the precompiled perl code using only */
394 
395  ngx_http_perl_eval_anon_sub(aTHX_ handler, &sv);
396 
397  if (sv == &PL_sv_undef) {
399  "eval_pv(\"%V\") failed", handler);
400  return NGX_ERROR;
401  }
402 
403  if (sv == NULL) {
404  sv = newSVpvn((char *) handler->data, handler->len);
405  }
406 
407 #endif
408 
409  sv = newSVpvn((char *) handler->data, handler->len);
410 
411  args = &params[NGX_HTTP_PERL_SSI_ARG];
412 
413  if (args) {
414 
415  for (i = 0; args[i]; i++) { /* void */ }
416 
417  asv = ngx_pcalloc(r->pool, (i + 1) * sizeof(SV *));
418 
419  if (asv == NULL) {
420  SvREFCNT_dec(sv);
421  return NGX_ERROR;
422  }
423 
424  asv[0] = (SV *) i;
425 
426  for (i = 0; args[i]; i++) {
427  asv[i + 1] = newSVpvn((char *) args[i]->data, args[i]->len);
428  }
429 
430  } else {
431  asv = NULL;
432  }
433 
434  rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sv, asv, handler,
435  NULL);
436 
437  SvREFCNT_dec(sv);
438 
439  }
440 
441  ctx->filename.data = NULL;
442  ctx->redirect_uri.len = 0;
443  ctx->ssi = NULL;
444 
445  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl ssi done");
446 
447  return rc;
448 }
449 
450 #endif
451 
452 
453 static char *
454 ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf)
455 {
456  ngx_str_t *m;
457  ngx_uint_t i;
458 #if (NGX_HAVE_PERL_MULTIPLICITY)
459  ngx_pool_cleanup_t *cln;
460 
461  cln = ngx_pool_cleanup_add(cf->pool, 0);
462  if (cln == NULL) {
463  return NGX_CONF_ERROR;
464  }
465 
466 #endif
467 
468 #ifdef NGX_PERL_MODULES
469  if (pmcf->modules == NGX_CONF_UNSET_PTR) {
470 
471  pmcf->modules = ngx_array_create(cf->pool, 1, sizeof(ngx_str_t));
472  if (pmcf->modules == NULL) {
473  return NGX_CONF_ERROR;
474  }
475 
476  m = ngx_array_push(pmcf->modules);
477  if (m == NULL) {
478  return NGX_CONF_ERROR;
479  }
480 
481  ngx_str_set(m, NGX_PERL_MODULES);
482  }
483 #endif
484 
485  if (pmcf->modules != NGX_CONF_UNSET_PTR) {
486  m = pmcf->modules->elts;
487  for (i = 0; i < pmcf->modules->nelts; i++) {
488  if (ngx_conf_full_name(cf->cycle, &m[i], 0) != NGX_OK) {
489  return NGX_CONF_ERROR;
490  }
491  }
492  }
493 
494 #if !(NGX_HAVE_PERL_MULTIPLICITY)
495 
496  if (perl) {
497 
498  if (ngx_set_environment(cf->cycle, NULL) == NULL) {
499  return NGX_CONF_ERROR;
500  }
501 
502  if (ngx_http_perl_run_requires(aTHX_ pmcf->requires, cf->log)
503  != NGX_OK)
504  {
505  return NGX_CONF_ERROR;
506  }
507 
508  pmcf->perl = perl;
509  pmcf->nginx = nginx_stash;
510 
511  return NGX_CONF_OK;
512  }
513 
514 #endif
515 
516  if (nginx_stash == NULL) {
517  PERL_SYS_INIT(&ngx_argc, &ngx_argv);
518  }
519 
520  pmcf->perl = ngx_http_perl_create_interpreter(cf, pmcf);
521 
522  if (pmcf->perl == NULL) {
523  return NGX_CONF_ERROR;
524  }
525 
526  pmcf->nginx = nginx_stash;
527 
528 #if (NGX_HAVE_PERL_MULTIPLICITY)
529 
530  cln->handler = ngx_http_perl_cleanup_perl;
531  cln->data = pmcf->perl;
532 
533 #else
534 
535  perl = pmcf->perl;
536 
537 #endif
538 
539  return NGX_CONF_OK;
540 }
541 
542 
543 static PerlInterpreter *
544 ngx_http_perl_create_interpreter(ngx_conf_t *cf,
546 {
547  int n;
548  STRLEN len;
549  SV *sv;
550  char *ver, **embedding;
551  ngx_str_t *m;
552  ngx_uint_t i;
553  PerlInterpreter *perl;
554 
555  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, "create perl interpreter");
556 
557  if (ngx_set_environment(cf->cycle, NULL) == NULL) {
558  return NULL;
559  }
560 
561  perl = perl_alloc();
562  if (perl == NULL) {
563  ngx_log_error(NGX_LOG_ALERT, cf->log, 0, "perl_alloc() failed");
564  return NULL;
565  }
566 
567  {
568 
569  dTHXa(perl);
570  PERL_SET_CONTEXT(perl);
571 
572  perl_construct(perl);
573 
574 #ifdef PERL_EXIT_DESTRUCT_END
575  PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
576 #endif
577 
578  n = (pmcf->modules != NGX_CONF_UNSET_PTR) ? pmcf->modules->nelts * 2 : 0;
579 
580  embedding = ngx_palloc(cf->pool, (4 + n) * sizeof(char *));
581  if (embedding == NULL) {
582  goto fail;
583  }
584 
585  embedding[0] = "";
586 
587  if (n++) {
588  m = pmcf->modules->elts;
589  for (i = 0; i < pmcf->modules->nelts; i++) {
590  embedding[2 * i + 1] = "-I";
591  embedding[2 * i + 2] = (char *) m[i].data;
592  }
593  }
594 
595  embedding[n++] = "-Mnginx";
596  embedding[n++] = "-e";
597  embedding[n++] = "0";
598 
599  n = perl_parse(perl, ngx_http_perl_xs_init, n, embedding, NULL);
600 
601  if (n != 0) {
602  ngx_log_error(NGX_LOG_ALERT, cf->log, 0, "perl_parse() failed: %d", n);
603  goto fail;
604  }
605 
606  sv = get_sv("nginx::VERSION", FALSE);
607  ver = SvPV(sv, len);
608 
609  if (ngx_strcmp(ver, NGINX_VERSION) != 0) {
611  "version " NGINX_VERSION " of nginx.pm is required, "
612  "but %s was found", ver);
613  goto fail;
614  }
615 
616  if (ngx_http_perl_run_requires(aTHX_ pmcf->requires, cf->log) != NGX_OK) {
617  goto fail;
618  }
619 
620  }
621 
622  return perl;
623 
624 fail:
625 
626  (void) perl_destruct(perl);
627 
628  perl_free(perl);
629 
630  return NULL;
631 }
632 
633 
634 static ngx_int_t
635 ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires, ngx_log_t *log)
636 {
637  u_char *err;
638  STRLEN len;
639  ngx_str_t *script;
640  ngx_uint_t i;
641 
642  if (requires == NGX_CONF_UNSET_PTR) {
643  return NGX_OK;
644  }
645 
646  script = requires->elts;
647  for (i = 0; i < requires->nelts; i++) {
648 
649  require_pv((char *) script[i].data);
650 
651  if (SvTRUE(ERRSV)) {
652 
653  err = (u_char *) SvPV(ERRSV, len);
654  while (--len && (err[len] == CR || err[len] == LF)) { /* void */ }
655 
657  "require_pv(\"%s\") failed: \"%*s\"",
658  script[i].data, len + 1, err);
659 
660  return NGX_ERROR;
661  }
662  }
663 
664  return NGX_OK;
665 }
666 
667 
668 static ngx_int_t
669 ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, HV *nginx, SV *sub,
670  SV **args, ngx_str_t *handler, ngx_str_t *rv)
671 {
672  SV *sv;
673  int n, status;
674  char *line;
675  u_char *err;
676  STRLEN len, n_a;
677  ngx_uint_t i;
678  ngx_connection_t *c;
679 
680  dSP;
681 
682  status = 0;
683 
684  ENTER;
685  SAVETMPS;
686 
687  PUSHMARK(sp);
688 
689  sv = sv_2mortal(sv_bless(newRV_noinc(newSViv(PTR2IV(r))), nginx));
690  XPUSHs(sv);
691 
692  if (args) {
693  EXTEND(sp, (intptr_t) args[0]);
694 
695  for (i = 1; i <= (ngx_uint_t) args[0]; i++) {
696  PUSHs(sv_2mortal(args[i]));
697  }
698  }
699 
700  PUTBACK;
701 
702  c = r->connection;
703 
704  n = call_sv(sub, G_EVAL);
705 
706  SPAGAIN;
707 
708  if (n) {
709  if (rv == NULL) {
710  status = POPi;
711 
713  "call_sv: %d", status);
714 
715  } else {
716  line = SvPVx(POPs, n_a);
717  rv->len = n_a;
718 
719  rv->data = ngx_pnalloc(r->pool, n_a);
720  if (rv->data == NULL) {
721  return NGX_ERROR;
722  }
723 
724  ngx_memcpy(rv->data, line, n_a);
725  }
726  }
727 
728  PUTBACK;
729 
730  FREETMPS;
731  LEAVE;
732 
733  /* check $@ */
734 
735  if (SvTRUE(ERRSV)) {
736 
737  err = (u_char *) SvPV(ERRSV, len);
738  while (--len && (err[len] == CR || err[len] == LF)) { /* void */ }
739 
741  "call_sv(\"%V\") failed: \"%*s\"", handler, len + 1, err);
742 
743  if (rv) {
744  return NGX_ERROR;
745  }
746 
748  }
749 
750  if (n != 1) {
752  "call_sv(\"%V\") returned %d results", handler, n);
753  status = NGX_OK;
754  }
755 
756  if (rv) {
757  return NGX_OK;
758  }
759 
760  return (ngx_int_t) status;
761 }
762 
763 
764 static void
765 ngx_http_perl_eval_anon_sub(pTHX_ ngx_str_t *handler, SV **sv)
766 {
767  u_char *p;
768 
769  for (p = handler->data; *p; p++) {
770  if (*p != ' ' && *p != '\t' && *p != CR && *p != LF) {
771  break;
772  }
773  }
774 
775  if (ngx_strncmp(p, "sub ", 4) == 0
776  || ngx_strncmp(p, "sub{", 4) == 0
777  || ngx_strncmp(p, "use ", 4) == 0)
778  {
779  *sv = eval_pv((char *) p, FALSE);
780 
781  /* eval_pv() does not set ERRSV on failure */
782 
783  return;
784  }
785 
786  *sv = NULL;
787 }
788 
789 
790 static void *
791 ngx_http_perl_create_main_conf(ngx_conf_t *cf)
792 {
794 
795  pmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_perl_main_conf_t));
796  if (pmcf == NULL) {
797  return NULL;
798  }
799 
800  pmcf->modules = NGX_CONF_UNSET_PTR;
802 
803  return pmcf;
804 }
805 
806 
807 static char *
808 ngx_http_perl_init_main_conf(ngx_conf_t *cf, void *conf)
809 {
810  ngx_http_perl_main_conf_t *pmcf = conf;
811 
812  if (pmcf->perl == NULL) {
813  if (ngx_http_perl_init_interpreter(cf, pmcf) != NGX_CONF_OK) {
814  return NGX_CONF_ERROR;
815  }
816  }
817 
818  return NGX_CONF_OK;
819 }
820 
821 
822 #if (NGX_HAVE_PERL_MULTIPLICITY)
823 
824 static void
825 ngx_http_perl_cleanup_perl(void *data)
826 {
827  PerlInterpreter *perl = data;
828 
829  PERL_SET_CONTEXT(perl);
830 
831  (void) perl_destruct(perl);
832 
833  perl_free(perl);
834 
835  if (ngx_perl_term) {
836  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "perl term");
837 
838  PERL_SYS_TERM();
839  }
840 }
841 
842 #endif
843 
844 
845 static ngx_int_t
846 ngx_http_perl_preconfiguration(ngx_conf_t *cf)
847 {
848 #if (NGX_HTTP_SSI)
849  ngx_int_t rc;
851 
853 
854  rc = ngx_hash_add_key(&smcf->commands, &ngx_http_perl_ssi_command.name,
855  &ngx_http_perl_ssi_command, NGX_HASH_READONLY_KEY);
856 
857  if (rc != NGX_OK) {
858  if (rc == NGX_BUSY) {
860  "conflicting SSI command \"%V\"",
861  &ngx_http_perl_ssi_command.name);
862  }
863 
864  return NGX_ERROR;
865  }
866 #endif
867 
868  return NGX_OK;
869 }
870 
871 
872 static void *
873 ngx_http_perl_create_loc_conf(ngx_conf_t *cf)
874 {
876 
877  plcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_perl_loc_conf_t));
878  if (plcf == NULL) {
879  return NULL;
880  }
881 
882  /*
883  * set by ngx_pcalloc():
884  *
885  * plcf->handler = { 0, NULL };
886  */
887 
888  return plcf;
889 }
890 
891 
892 static char *
893 ngx_http_perl_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
894 {
895  ngx_http_perl_loc_conf_t *prev = parent;
896  ngx_http_perl_loc_conf_t *conf = child;
897 
898  if (conf->sub == NULL) {
899  conf->sub = prev->sub;
900  conf->handler = prev->handler;
901  }
902 
903  return NGX_CONF_OK;
904 }
905 
906 
907 static char *
908 ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
909 {
910  ngx_http_perl_loc_conf_t *plcf = conf;
911 
912  ngx_str_t *value;
915 
916  value = cf->args->elts;
917 
918  if (plcf->handler.data) {
920  "duplicate perl handler \"%V\"", &value[1]);
921  return NGX_CONF_ERROR;
922  }
923 
924  pmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_perl_module);
925 
926  if (pmcf->perl == NULL) {
927  if (ngx_http_perl_init_interpreter(cf, pmcf) != NGX_CONF_OK) {
928  return NGX_CONF_ERROR;
929  }
930  }
931 
932  plcf->handler = value[1];
933 
934  {
935 
936  dTHXa(pmcf->perl);
937  PERL_SET_CONTEXT(pmcf->perl);
938 
939  ngx_http_perl_eval_anon_sub(aTHX_ &value[1], &plcf->sub);
940 
941  if (plcf->sub == &PL_sv_undef) {
943  "eval_pv(\"%V\") failed", &value[1]);
944  return NGX_CONF_ERROR;
945  }
946 
947  if (plcf->sub == NULL) {
948  plcf->sub = newSVpvn((char *) value[1].data, value[1].len);
949  }
950 
951  }
952 
954  clcf->handler = ngx_http_perl_handler;
955 
956  return NGX_CONF_OK;
957 }
958 
959 
960 static char *
961 ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
962 {
964  ngx_str_t *value;
968 
969  value = cf->args->elts;
970 
971  if (value[1].data[0] != '$') {
973  "invalid variable name \"%V\"", &value[1]);
974  return NGX_CONF_ERROR;
975  }
976 
977  value[1].len--;
978  value[1].data++;
979 
981  if (v == NULL) {
982  return NGX_CONF_ERROR;
983  }
984 
985  pv = ngx_palloc(cf->pool, sizeof(ngx_http_perl_variable_t));
986  if (pv == NULL) {
987  return NGX_CONF_ERROR;
988  }
989 
990  index = ngx_http_get_variable_index(cf, &value[1]);
991  if (index == NGX_ERROR) {
992  return NGX_CONF_ERROR;
993  }
994 
995  pmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_perl_module);
996 
997  if (pmcf->perl == NULL) {
998  if (ngx_http_perl_init_interpreter(cf, pmcf) != NGX_CONF_OK) {
999  return NGX_CONF_ERROR;
1000  }
1001  }
1002 
1003  pv->handler = value[2];
1004 
1005  {
1006 
1007  dTHXa(pmcf->perl);
1008  PERL_SET_CONTEXT(pmcf->perl);
1009 
1010  ngx_http_perl_eval_anon_sub(aTHX_ &value[2], &pv->sub);
1011 
1012  if (pv->sub == &PL_sv_undef) {
1014  "eval_pv(\"%V\") failed", &value[2]);
1015  return NGX_CONF_ERROR;
1016  }
1017 
1018  if (pv->sub == NULL) {
1019  pv->sub = newSVpvn((char *) value[2].data, value[2].len);
1020  }
1021 
1022  }
1023 
1024  v->get_handler = ngx_http_perl_variable;
1025  v->data = (uintptr_t) pv;
1026 
1027  return NGX_CONF_OK;
1028 }
1029 
1030 
1031 static ngx_int_t
1032 ngx_http_perl_init_worker(ngx_cycle_t *cycle)
1033 {
1035 
1036  pmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_perl_module);
1037 
1038  if (pmcf) {
1039  dTHXa(pmcf->perl);
1040  PERL_SET_CONTEXT(pmcf->perl);
1041 
1042  /* set worker's $$ */
1043 
1044  sv_setiv(GvSV(gv_fetchpv("$", TRUE, SVt_PV)), (I32) ngx_pid);
1045  }
1046 
1047  return NGX_OK;
1048 }
1049 
1050 
1051 static void
1052 ngx_http_perl_exit(ngx_cycle_t *cycle)
1053 {
1054 #if (NGX_HAVE_PERL_MULTIPLICITY)
1055 
1056  /*
1057  * the master exit hook is run before global pool cleanup,
1058  * therefore just set flag here
1059  */
1060 
1061  ngx_perl_term = 1;
1062 
1063 #else
1064 
1065  if (nginx_stash) {
1066  ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cycle->log, 0, "perl term");
1067 
1068  (void) perl_destruct(perl);
1069 
1070  perl_free(perl);
1071 
1072  PERL_SYS_TERM();
1073  }
1074 
1075 #endif
1076 }