📄 ngx_http_perl_module.c
字号:
char *ver, *embedding[6]; PerlInterpreter *perl; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, "create perl interpreter"); if (ngx_set_environment(cf->cycle, NULL) == NULL) { return NULL; } perl = perl_alloc(); if (perl == NULL) { ngx_log_error(NGX_LOG_ALERT, cf->log, 0, "perl_alloc() failed"); return NULL; } { dTHXa(perl); PERL_SET_CONTEXT(perl); perl_construct(perl);#ifdef PERL_EXIT_DESTRUCT_END PL_exit_flags |= PERL_EXIT_DESTRUCT_END;#endif embedding[0] = ""; if (pmcf->modules.data) { embedding[1] = "-I"; embedding[2] = (char *) pmcf->modules.data; n = 3; } else { n = 1; } embedding[n++] = "-Mnginx"; embedding[n++] = "-e"; embedding[n++] = "0"; n = perl_parse(perl, ngx_http_perl_xs_init, n, embedding, NULL); if (n != 0) { ngx_log_error(NGX_LOG_ALERT, cf->log, 0, "perl_parse() failed: %d", n); goto fail; } sv = get_sv("nginx::VERSION", FALSE); ver = SvPV(sv, len); if (ngx_strcmp(ver, NGINX_VERSION) != 0) { ngx_log_error(NGX_LOG_ALERT, cf->log, 0, "version " NGINX_VERSION " of nginx.pm is required, " "but %s was found", ver); goto fail; } if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, cf->log) != NGX_OK) { goto fail; } } return perl;fail: (void) perl_destruct(perl); perl_free(perl); return NULL;}static ngx_int_tngx_http_perl_run_requires(pTHX_ ngx_array_t *requires, ngx_log_t *log){ char **script; STRLEN len; ngx_str_t err; ngx_uint_t i; script = requires->elts; for (i = 0; i < requires->nelts; i++) { require_pv(script[i]); if (SvTRUE(ERRSV)) { err.data = (u_char *) SvPV(ERRSV, len); for (len--; err.data[len] == LF || err.data[len] == CR; len--) { /* void */ } err.len = len + 1; ngx_log_error(NGX_LOG_EMERG, log, 0, "require_pv(\"%s\") failed: \"%V\"", script[i], &err); return NGX_ERROR; } } return NGX_OK;}static ngx_int_tngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, HV *nginx, SV *sub, ngx_str_t **args, ngx_str_t *handler, ngx_str_t *rv){ SV *sv; int n, status; char *line; STRLEN len, n_a; ngx_str_t err; ngx_uint_t i; dSP; status = 0; ENTER; SAVETMPS; PUSHMARK(sp); sv = sv_2mortal(sv_bless(newRV_noinc(newSViv(PTR2IV(r))), nginx)); XPUSHs(sv); if (args) { for (i = 0; args[i]; i++) { /* void */ } EXTEND(sp, (int) i); for (i = 0; args[i]; i++) { PUSHs(sv_2mortal(newSVpvn((char *) args[i]->data, args[i]->len))); } } PUTBACK; n = call_sv(sub, G_EVAL); SPAGAIN; if (n) { if (rv == NULL) { status = POPi; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "call_sv: %d", status); } else { line = SvPVx(POPs, n_a); rv->len = n_a; rv->data = ngx_palloc(r->pool, n_a); if (rv->data == NULL) { return NGX_ERROR; } ngx_memcpy(rv->data, line, n_a); } } PUTBACK; FREETMPS; LEAVE; /* check $@ */ if (SvTRUE(ERRSV)) { err.data = (u_char *) SvPV(ERRSV, len); for (len--; err.data[len] == LF || err.data[len] == CR; len--) { /* void */ } err.len = len + 1; ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "call_sv(\"%V\") failed: \"%V\"", handler, &err); if (rv) { return NGX_ERROR; } return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (n != 1) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "call_sv(\"%V\") returned %d results", handler, n); status = NGX_OK; } if (rv) { return NGX_OK; } return (ngx_int_t) status;}static voidngx_http_perl_eval_anon_sub(pTHX_ ngx_str_t *handler, SV **sv){ u_char *p; for (p = handler->data; *p; p++) { if (*p != ' ' && *p != '\t' && *p != CR && *p != LF) { break; } } if (ngx_strncmp(p, "sub ", 4) == 0 || ngx_strncmp(p, "use ", 4) == 0) { *sv = eval_pv((char *) p, FALSE); /* eval_pv() does not set ERRSV on failure */ return; } *sv = NULL;}static void *ngx_http_perl_create_main_conf(ngx_conf_t *cf){ ngx_http_perl_main_conf_t *pmcf; pmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_perl_main_conf_t)); if (pmcf == NULL) { return NGX_CONF_ERROR; } if (ngx_array_init(&pmcf->requires, cf->pool, 1, sizeof(u_char *)) != NGX_OK) { return NULL; } return pmcf;}static char *ngx_http_perl_init_main_conf(ngx_conf_t *cf, void *conf){ ngx_http_perl_main_conf_t *pmcf = conf; if (pmcf->perl == NULL) { if (ngx_http_perl_init_interpreter(cf, pmcf) != NGX_CONF_OK) { return NGX_CONF_ERROR; } } return NGX_CONF_OK;}#if (NGX_HAVE_PERL_MULTIPLICITY)static voidngx_http_perl_cleanup_perl(void *data){ PerlInterpreter *perl = data; PERL_SET_CONTEXT(perl); (void) perl_destruct(perl); perl_free(perl);}#endifstatic ngx_int_tngx_http_perl_preconfiguration(ngx_conf_t *cf){#if (NGX_HTTP_SSI) ngx_int_t rc; ngx_http_ssi_main_conf_t *smcf; smcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_ssi_filter_module); rc = ngx_hash_add_key(&smcf->commands, &ngx_http_perl_ssi_command.name, &ngx_http_perl_ssi_command, NGX_HASH_READONLY_KEY); if (rc != NGX_OK) { if (rc == NGX_BUSY) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "conflicting SSI command \"%V\"", &ngx_http_perl_ssi_command.name); } return NGX_ERROR; }#endif return NGX_OK;}static void *ngx_http_perl_create_loc_conf(ngx_conf_t *cf){ ngx_http_perl_loc_conf_t *plcf; plcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_perl_loc_conf_t)); if (plcf == NULL) { return NGX_CONF_ERROR; } /* * set by ngx_pcalloc(): * * plcf->handler = { 0, NULL }; */ return plcf;}static char *ngx_http_perl_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child){ ngx_http_perl_loc_conf_t *prev = parent; ngx_http_perl_loc_conf_t *conf = child; if (conf->sub == NULL) { conf->sub = prev->sub; conf->handler = prev->handler; } return NGX_CONF_OK;}static char *ngx_http_perl_require(ngx_conf_t *cf, ngx_command_t *cmd, void *conf){ ngx_http_perl_main_conf_t *pmcf = conf; u_char **p; ngx_str_t *value; value = cf->args->elts; p = ngx_array_push(&pmcf->requires); if (p == NULL) { return NGX_CONF_ERROR; } *p = value[1].data; return NGX_CONF_OK;}static char *ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf){ ngx_http_perl_loc_conf_t *plcf = conf; ngx_str_t *value; ngx_http_core_loc_conf_t *clcf; ngx_http_perl_main_conf_t *pmcf; value = cf->args->elts; if (plcf->handler.data) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate perl handler \"%V\"", &value[1]); return NGX_CONF_ERROR; } pmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_perl_module); if (pmcf->perl == NULL) { if (ngx_http_perl_init_interpreter(cf, pmcf) != NGX_CONF_OK) { return NGX_CONF_ERROR; } } plcf->handler = value[1]; { dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); ngx_http_perl_eval_anon_sub(aTHX_ &value[1], &plcf->sub); if (plcf->sub == &PL_sv_undef) { ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "eval_pv(\"%V\") failed", &value[1]); return NGX_CONF_ERROR; } if (plcf->sub == NULL) { plcf->sub = newSVpvn((char *) value[1].data, value[1].len); } } clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); clcf->handler = ngx_http_perl_handler; return NGX_CONF_OK;}static char *ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf){ ngx_int_t index; ngx_str_t *value; ngx_http_variable_t *v; ngx_http_perl_variable_t *pv; ngx_http_perl_main_conf_t *pmcf; value = cf->args->elts; if (value[1].data[0] != '$') { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid variable name \"%V\"", &value[1]); return NGX_CONF_ERROR; } value[1].len--; value[1].data++; v = ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGABLE); if (v == NULL) { return NGX_CONF_ERROR; } pv = ngx_palloc(cf->pool, sizeof(ngx_http_perl_variable_t)); if (pv == NULL) { return NGX_CONF_ERROR; } index = ngx_http_get_variable_index(cf, &value[1]); if (index == NGX_ERROR) { return NGX_CONF_ERROR; } pmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_perl_module); if (pmcf->perl == NULL) { if (ngx_http_perl_init_interpreter(cf, pmcf) != NGX_CONF_OK) { return NGX_CONF_ERROR; } } pv->handler = value[2]; { dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); ngx_http_perl_eval_anon_sub(aTHX_ &value[2], &pv->sub); if (pv->sub == &PL_sv_undef) { ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "eval_pv(\"%V\") failed", &value[2]); return NGX_CONF_ERROR; } if (pv->sub == NULL) { pv->sub = newSVpvn((char *) value[2].data, value[2].len); } } v->get_handler = ngx_http_perl_variable; v->data = (uintptr_t) pv; return NGX_CONF_OK;}static ngx_int_tngx_http_perl_init_worker(ngx_cycle_t *cycle){ ngx_http_perl_main_conf_t *pmcf; pmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_perl_module); { dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); /* set worker's $$ */ sv_setiv(GvSV(gv_fetchpv("$", TRUE, SVt_PV)), (I32) ngx_pid); } return NGX_OK;}static voidngx_http_perl_exit(ngx_cycle_t *cycle){ PERL_SYS_TERM();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -