Mercurial > hg > nginx-mail
comparison src/http/modules/perl/ngx_http_perl_module.c @ 665:0b460e61bdcd default tip
Merge with nginx 1.0.0.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 25 Apr 2011 04:22:17 +0400 |
parents | ff463db0be31 |
children |
comparison
equal
deleted
inserted
replaced
572:06419a2298a9 | 665:0b460e61bdcd |
---|---|
11 | 11 |
12 | 12 |
13 typedef struct { | 13 typedef struct { |
14 PerlInterpreter *perl; | 14 PerlInterpreter *perl; |
15 HV *nginx; | 15 HV *nginx; |
16 ngx_str_t modules; | 16 ngx_array_t *modules; |
17 ngx_array_t requires; | 17 ngx_array_t *requires; |
18 } ngx_http_perl_main_conf_t; | 18 } ngx_http_perl_main_conf_t; |
19 | 19 |
20 | 20 |
21 typedef struct { | 21 typedef struct { |
22 SV *sub; | 22 SV *sub; |
26 | 26 |
27 typedef struct { | 27 typedef struct { |
28 SV *sub; | 28 SV *sub; |
29 ngx_str_t handler; | 29 ngx_str_t handler; |
30 } ngx_http_perl_variable_t; | 30 } ngx_http_perl_variable_t; |
31 | |
32 | |
33 typedef struct { | |
34 SV *sv; | |
35 PerlInterpreter *perl; | |
36 } ngx_http_perl_cleanup_t; | |
37 | 31 |
38 | 32 |
39 #if (NGX_HTTP_SSI) | 33 #if (NGX_HTTP_SSI) |
40 static ngx_int_t ngx_http_perl_ssi(ngx_http_request_t *r, | 34 static ngx_int_t ngx_http_perl_ssi(ngx_http_request_t *r, |
41 ngx_http_ssi_ctx_t *ssi_ctx, ngx_str_t **params); | 35 ngx_http_ssi_ctx_t *ssi_ctx, ngx_str_t **params); |
55 static void *ngx_http_perl_create_main_conf(ngx_conf_t *cf); | 49 static void *ngx_http_perl_create_main_conf(ngx_conf_t *cf); |
56 static char *ngx_http_perl_init_main_conf(ngx_conf_t *cf, void *conf); | 50 static char *ngx_http_perl_init_main_conf(ngx_conf_t *cf, void *conf); |
57 static void *ngx_http_perl_create_loc_conf(ngx_conf_t *cf); | 51 static void *ngx_http_perl_create_loc_conf(ngx_conf_t *cf); |
58 static char *ngx_http_perl_merge_loc_conf(ngx_conf_t *cf, void *parent, | 52 static char *ngx_http_perl_merge_loc_conf(ngx_conf_t *cf, void *parent, |
59 void *child); | 53 void *child); |
60 static char *ngx_http_perl_require(ngx_conf_t *cf, ngx_command_t *cmd, | |
61 void *conf); | |
62 static char *ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | 54 static char *ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
63 static char *ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | 55 static char *ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
64 | 56 |
65 #if (NGX_HAVE_PERL_MULTIPLICITY) | 57 #if (NGX_HAVE_PERL_MULTIPLICITY) |
66 static void ngx_http_perl_cleanup_perl(void *data); | 58 static void ngx_http_perl_cleanup_perl(void *data); |
72 | 64 |
73 static ngx_command_t ngx_http_perl_commands[] = { | 65 static ngx_command_t ngx_http_perl_commands[] = { |
74 | 66 |
75 { ngx_string("perl_modules"), | 67 { ngx_string("perl_modules"), |
76 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, | 68 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, |
77 ngx_conf_set_str_slot, | 69 ngx_conf_set_str_array_slot, |
78 NGX_HTTP_MAIN_CONF_OFFSET, | 70 NGX_HTTP_MAIN_CONF_OFFSET, |
79 offsetof(ngx_http_perl_main_conf_t, modules), | 71 offsetof(ngx_http_perl_main_conf_t, modules), |
80 NULL }, | 72 NULL }, |
81 | 73 |
82 { ngx_string("perl_require"), | 74 { ngx_string("perl_require"), |
83 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, | 75 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, |
84 ngx_http_perl_require, | 76 ngx_conf_set_str_array_slot, |
85 NGX_HTTP_MAIN_CONF_OFFSET, | 77 NGX_HTTP_MAIN_CONF_OFFSET, |
86 0, | 78 offsetof(ngx_http_perl_main_conf_t, requires), |
87 NULL }, | 79 NULL }, |
88 | 80 |
89 { ngx_string("perl"), | 81 { ngx_string("perl"), |
90 NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1, | 82 NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1, |
91 ngx_http_perl, | 83 ngx_http_perl, |
152 }; | 144 }; |
153 | 145 |
154 #endif | 146 #endif |
155 | 147 |
156 | 148 |
157 static ngx_str_t ngx_null_name = ngx_null_string; | 149 static ngx_str_t ngx_null_name = ngx_null_string; |
158 | 150 static HV *nginx_stash; |
159 static HV *nginx_stash; | |
160 | 151 |
161 #if (NGX_HAVE_PERL_MULTIPLICITY) | 152 #if (NGX_HAVE_PERL_MULTIPLICITY) |
162 static ngx_uint_t ngx_perl_term; | 153 static ngx_uint_t ngx_perl_term; |
154 #else | |
155 static PerlInterpreter *perl; | |
163 #endif | 156 #endif |
164 | 157 |
165 | 158 |
166 static void | 159 static void |
167 ngx_http_perl_xs_init(pTHX) | 160 ngx_http_perl_xs_init(pTHX) |
173 | 166 |
174 | 167 |
175 static ngx_int_t | 168 static ngx_int_t |
176 ngx_http_perl_handler(ngx_http_request_t *r) | 169 ngx_http_perl_handler(ngx_http_request_t *r) |
177 { | 170 { |
178 if (r->zero_in_uri) { | |
179 return NGX_HTTP_NOT_FOUND; | |
180 } | |
181 | |
182 r->main->count++; | 171 r->main->count++; |
183 | 172 |
184 ngx_http_perl_handle_request(r); | 173 ngx_http_perl_handle_request(r); |
185 | 174 |
186 return NGX_DONE; | 175 return NGX_DONE; |
461 | 450 |
462 | 451 |
463 static char * | 452 static char * |
464 ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf) | 453 ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf) |
465 { | 454 { |
455 ngx_str_t *m; | |
456 ngx_uint_t i; | |
466 #if (NGX_HAVE_PERL_MULTIPLICITY) | 457 #if (NGX_HAVE_PERL_MULTIPLICITY) |
467 ngx_pool_cleanup_t *cln; | 458 ngx_pool_cleanup_t *cln; |
468 | 459 |
469 cln = ngx_pool_cleanup_add(cf->pool, 0); | 460 cln = ngx_pool_cleanup_add(cf->pool, 0); |
470 if (cln == NULL) { | 461 if (cln == NULL) { |
471 return NGX_CONF_ERROR; | 462 return NGX_CONF_ERROR; |
472 } | 463 } |
473 | 464 |
474 #else | |
475 static PerlInterpreter *perl; | |
476 #endif | 465 #endif |
477 | 466 |
478 #ifdef NGX_PERL_MODULES | 467 #ifdef NGX_PERL_MODULES |
479 if (pmcf->modules.data == NULL) { | 468 if (pmcf->modules == NGX_CONF_UNSET_PTR) { |
480 pmcf->modules.data = NGX_PERL_MODULES; | 469 |
481 } | 470 pmcf->modules = ngx_array_create(cf->pool, 1, sizeof(ngx_str_t)); |
482 #endif | 471 if (pmcf->modules == NULL) { |
483 | |
484 if (pmcf->modules.data) { | |
485 if (ngx_conf_full_name(cf->cycle, &pmcf->modules, 0) != NGX_OK) { | |
486 return NGX_CONF_ERROR; | 472 return NGX_CONF_ERROR; |
473 } | |
474 | |
475 m = ngx_array_push(pmcf->modules); | |
476 if (m == NULL) { | |
477 return NGX_CONF_ERROR; | |
478 } | |
479 | |
480 ngx_str_set(m, NGX_PERL_MODULES); | |
481 } | |
482 #endif | |
483 | |
484 if (pmcf->modules != NGX_CONF_UNSET_PTR) { | |
485 m = pmcf->modules->elts; | |
486 for (i = 0; i < pmcf->modules->nelts; i++) { | |
487 if (ngx_conf_full_name(cf->cycle, &m[i], 0) != NGX_OK) { | |
488 return NGX_CONF_ERROR; | |
489 } | |
487 } | 490 } |
488 } | 491 } |
489 | 492 |
490 #if !(NGX_HAVE_PERL_MULTIPLICITY) | 493 #if !(NGX_HAVE_PERL_MULTIPLICITY) |
491 | 494 |
493 | 496 |
494 if (ngx_set_environment(cf->cycle, NULL) == NULL) { | 497 if (ngx_set_environment(cf->cycle, NULL) == NULL) { |
495 return NGX_CONF_ERROR; | 498 return NGX_CONF_ERROR; |
496 } | 499 } |
497 | 500 |
498 if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, cf->log) | 501 if (ngx_http_perl_run_requires(aTHX_ pmcf->requires, cf->log) |
499 != NGX_OK) | 502 != NGX_OK) |
500 { | 503 { |
501 return NGX_CONF_ERROR; | 504 return NGX_CONF_ERROR; |
502 } | 505 } |
503 | 506 |
541 ngx_http_perl_main_conf_t *pmcf) | 544 ngx_http_perl_main_conf_t *pmcf) |
542 { | 545 { |
543 int n; | 546 int n; |
544 STRLEN len; | 547 STRLEN len; |
545 SV *sv; | 548 SV *sv; |
546 char *ver, *embedding[6]; | 549 char *ver, **embedding; |
550 ngx_str_t *m; | |
551 ngx_uint_t i; | |
547 PerlInterpreter *perl; | 552 PerlInterpreter *perl; |
548 | 553 |
549 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, "create perl interpreter"); | 554 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, "create perl interpreter"); |
550 | 555 |
551 if (ngx_set_environment(cf->cycle, NULL) == NULL) { | 556 if (ngx_set_environment(cf->cycle, NULL) == NULL) { |
567 | 572 |
568 #ifdef PERL_EXIT_DESTRUCT_END | 573 #ifdef PERL_EXIT_DESTRUCT_END |
569 PL_exit_flags |= PERL_EXIT_DESTRUCT_END; | 574 PL_exit_flags |= PERL_EXIT_DESTRUCT_END; |
570 #endif | 575 #endif |
571 | 576 |
577 n = (pmcf->modules != NGX_CONF_UNSET_PTR) ? pmcf->modules->nelts * 2 : 0; | |
578 | |
579 embedding = ngx_palloc(cf->pool, (4 + n) * sizeof(char *)); | |
580 if (embedding == NULL) { | |
581 goto fail; | |
582 } | |
583 | |
572 embedding[0] = ""; | 584 embedding[0] = ""; |
573 | 585 |
574 if (pmcf->modules.data) { | 586 if (n++) { |
575 embedding[1] = "-I"; | 587 m = pmcf->modules->elts; |
576 embedding[2] = (char *) pmcf->modules.data; | 588 for (i = 0; i < pmcf->modules->nelts; i++) { |
577 n = 3; | 589 embedding[2 * i + 1] = "-I"; |
578 | 590 embedding[2 * i + 2] = (char *) m[i].data; |
579 } else { | 591 } |
580 n = 1; | |
581 } | 592 } |
582 | 593 |
583 embedding[n++] = "-Mnginx"; | 594 embedding[n++] = "-Mnginx"; |
584 embedding[n++] = "-e"; | 595 embedding[n++] = "-e"; |
585 embedding[n++] = "0"; | 596 embedding[n++] = "0"; |
599 "version " NGINX_VERSION " of nginx.pm is required, " | 610 "version " NGINX_VERSION " of nginx.pm is required, " |
600 "but %s was found", ver); | 611 "but %s was found", ver); |
601 goto fail; | 612 goto fail; |
602 } | 613 } |
603 | 614 |
604 if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, cf->log) != NGX_OK) { | 615 if (ngx_http_perl_run_requires(aTHX_ pmcf->requires, cf->log) != NGX_OK) { |
605 goto fail; | 616 goto fail; |
606 } | 617 } |
607 | 618 |
608 } | 619 } |
609 | 620 |
620 | 631 |
621 | 632 |
622 static ngx_int_t | 633 static ngx_int_t |
623 ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires, ngx_log_t *log) | 634 ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires, ngx_log_t *log) |
624 { | 635 { |
625 char **script; | 636 u_char *err; |
626 STRLEN len; | 637 STRLEN len; |
627 ngx_str_t err; | 638 ngx_str_t *script; |
628 ngx_uint_t i; | 639 ngx_uint_t i; |
640 | |
641 if (requires == NGX_CONF_UNSET_PTR) { | |
642 return NGX_OK; | |
643 } | |
629 | 644 |
630 script = requires->elts; | 645 script = requires->elts; |
631 for (i = 0; i < requires->nelts; i++) { | 646 for (i = 0; i < requires->nelts; i++) { |
632 | 647 |
633 require_pv(script[i]); | 648 require_pv((char *) script[i].data); |
634 | 649 |
635 if (SvTRUE(ERRSV)) { | 650 if (SvTRUE(ERRSV)) { |
636 | 651 |
637 err.data = (u_char *) SvPV(ERRSV, len); | 652 err = (u_char *) SvPV(ERRSV, len); |
638 for (len--; err.data[len] == LF || err.data[len] == CR; len--) { | 653 while (--len && (err[len] == CR || err[len] == LF)) { /* void */ } |
639 /* void */ | |
640 } | |
641 err.len = len + 1; | |
642 | 654 |
643 ngx_log_error(NGX_LOG_EMERG, log, 0, | 655 ngx_log_error(NGX_LOG_EMERG, log, 0, |
644 "require_pv(\"%s\") failed: \"%V\"", script[i], &err); | 656 "require_pv(\"%s\") failed: \"%*s\"", |
657 script[i].data, len + 1, err); | |
645 | 658 |
646 return NGX_ERROR; | 659 return NGX_ERROR; |
647 } | 660 } |
648 } | 661 } |
649 | 662 |
656 SV **args, ngx_str_t *handler, ngx_str_t *rv) | 669 SV **args, ngx_str_t *handler, ngx_str_t *rv) |
657 { | 670 { |
658 SV *sv; | 671 SV *sv; |
659 int n, status; | 672 int n, status; |
660 char *line; | 673 char *line; |
674 u_char *err; | |
661 STRLEN len, n_a; | 675 STRLEN len, n_a; |
662 ngx_str_t err; | |
663 ngx_uint_t i; | 676 ngx_uint_t i; |
664 ngx_connection_t *c; | 677 ngx_connection_t *c; |
665 | 678 |
666 dSP; | 679 dSP; |
667 | 680 |
718 | 731 |
719 /* check $@ */ | 732 /* check $@ */ |
720 | 733 |
721 if (SvTRUE(ERRSV)) { | 734 if (SvTRUE(ERRSV)) { |
722 | 735 |
723 err.data = (u_char *) SvPV(ERRSV, len); | 736 err = (u_char *) SvPV(ERRSV, len); |
724 for (len--; err.data[len] == LF || err.data[len] == CR; len--) { | 737 while (--len && (err[len] == CR || err[len] == LF)) { /* void */ } |
725 /* void */ | |
726 } | |
727 err.len = len + 1; | |
728 | 738 |
729 ngx_log_error(NGX_LOG_ERR, c->log, 0, | 739 ngx_log_error(NGX_LOG_ERR, c->log, 0, |
730 "call_sv(\"%V\") failed: \"%V\"", handler, &err); | 740 "call_sv(\"%V\") failed: \"%*s\"", handler, len + 1, err); |
731 | 741 |
732 if (rv) { | 742 if (rv) { |
733 return NGX_ERROR; | 743 return NGX_ERROR; |
734 } | 744 } |
735 | 745 |
784 pmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_perl_main_conf_t)); | 794 pmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_perl_main_conf_t)); |
785 if (pmcf == NULL) { | 795 if (pmcf == NULL) { |
786 return NULL; | 796 return NULL; |
787 } | 797 } |
788 | 798 |
789 if (ngx_array_init(&pmcf->requires, cf->pool, 1, sizeof(u_char *)) | 799 pmcf->modules = NGX_CONF_UNSET_PTR; |
790 != NGX_OK) | 800 pmcf->requires = NGX_CONF_UNSET_PTR; |
791 { | |
792 return NULL; | |
793 } | |
794 | 801 |
795 return pmcf; | 802 return pmcf; |
796 } | 803 } |
797 | 804 |
798 | 805 |
895 return NGX_CONF_OK; | 902 return NGX_CONF_OK; |
896 } | 903 } |
897 | 904 |
898 | 905 |
899 static char * | 906 static char * |
900 ngx_http_perl_require(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
901 { | |
902 ngx_http_perl_main_conf_t *pmcf = conf; | |
903 | |
904 u_char **p; | |
905 ngx_str_t *value; | |
906 | |
907 value = cf->args->elts; | |
908 | |
909 p = ngx_array_push(&pmcf->requires); | |
910 | |
911 if (p == NULL) { | |
912 return NGX_CONF_ERROR; | |
913 } | |
914 | |
915 *p = value[1].data; | |
916 | |
917 return NGX_CONF_OK; | |
918 } | |
919 | |
920 | |
921 static char * | |
922 ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 907 ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
923 { | 908 { |
924 ngx_http_perl_loc_conf_t *plcf = conf; | 909 ngx_http_perl_loc_conf_t *plcf = conf; |
925 | 910 |
926 ngx_str_t *value; | 911 ngx_str_t *value; |
1065 static void | 1050 static void |
1066 ngx_http_perl_exit(ngx_cycle_t *cycle) | 1051 ngx_http_perl_exit(ngx_cycle_t *cycle) |
1067 { | 1052 { |
1068 #if (NGX_HAVE_PERL_MULTIPLICITY) | 1053 #if (NGX_HAVE_PERL_MULTIPLICITY) |
1069 | 1054 |
1055 /* | |
1056 * the master exit hook is run before global pool cleanup, | |
1057 * therefore just set flag here | |
1058 */ | |
1059 | |
1070 ngx_perl_term = 1; | 1060 ngx_perl_term = 1; |
1071 | 1061 |
1072 #else | 1062 #else |
1073 ngx_http_perl_main_conf_t *pmcf; | 1063 |
1074 | 1064 if (nginx_stash) { |
1075 pmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_perl_module); | |
1076 | |
1077 if (pmcf && nginx_stash) { | |
1078 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cycle->log, 0, "perl term"); | 1065 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cycle->log, 0, "perl term"); |
1079 | 1066 |
1080 (void) perl_destruct(pmcf->perl); | 1067 (void) perl_destruct(perl); |
1081 | 1068 |
1082 perl_free(pmcf->perl); | 1069 perl_free(perl); |
1083 | 1070 |
1084 PERL_SYS_TERM(); | 1071 PERL_SYS_TERM(); |
1085 } | 1072 } |
1086 | 1073 |
1087 #endif | 1074 #endif |