From 882cdcc2b61f1c3767e4a3dbab96548bc8e246aa Mon Sep 17 00:00:00 2001 From: Roberto De Ioris Date: Thu, 14 Nov 2013 06:24:56 +0100 Subject: [PATCH] added --plshell and Perl uwsgi::rpc --- plugins/psgi/psgi.h | 3 ++ plugins/psgi/psgi_loader.c | 2 +- plugins/psgi/psgi_plugin.c | 53 +++++++++++++++++++++++++++++++++++ plugins/psgi/uwsgi_plmodule.c | 36 ++++++++++++++++++++++++ plugins/rack/rack_plugin.c | 4 --- 5 files changed, 93 insertions(+), 5 deletions(-) diff --git a/plugins/psgi/psgi.h b/plugins/psgi/psgi.h index 696a1191..db4326c7 100644 --- a/plugins/psgi/psgi.h +++ b/plugins/psgi/psgi.h @@ -60,6 +60,9 @@ struct uwsgi_perl { HV *auto_reload_hash; int enable_psgix_io; + + char *shell; + int shell_oneshot; }; void init_perl_embedded_module(void); diff --git a/plugins/psgi/psgi_loader.c b/plugins/psgi/psgi_loader.c index ba1763fc..ead460c7 100644 --- a/plugins/psgi/psgi_loader.c +++ b/plugins/psgi/psgi_loader.c @@ -463,7 +463,7 @@ void uwsgi_psgi_app() { init_psgi_app(NULL, uperl.psgi, strlen(uperl.psgi), uperl.main); } // create a perl environment (if needed) - else if (uperl.exec) { + else if (uperl.exec || uperl.shell) { PERL_SET_CONTEXT(uperl.main[0]); perl_parse(uperl.main[0], xs_init, 2, uperl.embedding, NULL); } diff --git a/plugins/psgi/psgi_plugin.c b/plugins/psgi/psgi_plugin.c index 59b9a000..a89cf842 100644 --- a/plugins/psgi/psgi_plugin.c +++ b/plugins/psgi/psgi_plugin.c @@ -11,6 +11,21 @@ struct uwsgi_perl uperl; struct uwsgi_plugin psgi_plugin; +static void uwsgi_opt_plshell(char *opt, char *value, void *foobar) { + + uwsgi.honour_stdin = 1; + if (value) { + uperl.shell = value; + } + else { + uperl.shell = ""; + } + + if (!strcmp("plshell-oneshot", opt)) { + uperl.shell_oneshot = 1; + } +} + struct uwsgi_option uwsgi_perl_options[] = { {"psgi", required_argument, 0, "load a psgi app", uwsgi_opt_set_str, &uperl.psgi, 0}, @@ -26,6 +41,9 @@ struct uwsgi_option uwsgi_perl_options[] = { {"perl-exec-post-fork", required_argument, 0, "exec the specified perl file after fork()", uwsgi_opt_add_string_list, &uperl.exec_post_fork, 0}, {"perl-auto-reload", required_argument, 0, "enable perl auto-reloader with the specified frequency", uwsgi_opt_set_int, &uperl.auto_reload, UWSGI_OPT_MASTER}, {"perl-auto-reload-ignore", required_argument, 0, "ignore the specified files when auto-reload is enabled", uwsgi_opt_add_string_list, &uperl.auto_reload_ignore, UWSGI_OPT_MASTER}, + + {"plshell", optional_argument, 0, "run a perl interactive shell", uwsgi_opt_plshell, NULL, 0}, + {"plshell-oneshot", no_argument, 0, "run a perl interactive shell (one shot)", uwsgi_opt_plshell, NULL, 0}, {0, 0, 0, 0, 0, 0, 0}, }; @@ -836,6 +854,39 @@ static uint64_t uwsgi_perl_rpc(void *func, uint8_t argc, char **argv, uint16_t a return ret; } +static void uwsgi_perl_hijack(void) { + if (uperl.shell_oneshot && uwsgi.workers[uwsgi.mywid].hijacked_count > 0) { + uwsgi.workers[uwsgi.mywid].hijacked = 0; + return; + } + if (uperl.shell && uwsgi.mywid == 1) { + uwsgi.workers[uwsgi.mywid].hijacked = 1; + uwsgi.workers[uwsgi.mywid].hijacked_count++; + // re-map stdin to stdout and stderr if we are logging to a file + if (uwsgi.logfile) { + if (dup2(0, 1) < 0) { + uwsgi_error("dup2()"); + } + if (dup2(0, 2) < 0) { + uwsgi_error("dup2()"); + } + } + + if (uperl.shell[0] != 0) { + perl_eval_pv(uperl.shell, 0); + } + else { + perl_eval_pv("use Devel::REPL;my $repl = Devel::REPL->new;$repl->run;", 0); + } + if (uperl.shell_oneshot) { + exit(UWSGI_DE_HIJACKED_CODE); + } + exit(0); + } + +} + + struct uwsgi_plugin psgi_plugin = { .name = "psgi", @@ -852,6 +903,8 @@ struct uwsgi_plugin psgi_plugin = { .mule = uwsgi_perl_mule, + .hijack_worker = uwsgi_perl_hijack, + .post_fork = uwsgi_perl_post_fork, .request = uwsgi_perl_request, .after_request = uwsgi_perl_after_request, diff --git a/plugins/psgi/uwsgi_plmodule.c b/plugins/psgi/uwsgi_plmodule.c index 9fa28f39..42faa9fe 100644 --- a/plugins/psgi/uwsgi_plmodule.c +++ b/plugins/psgi/uwsgi_plmodule.c @@ -351,6 +351,41 @@ XS(XS_call) { XSRETURN_UNDEF; } +XS(XS_rpc) { + + dXSARGS; + + char *node; + char *func; + uint64_t size = 0; + int i; + char *argv[256]; + uint16_t argvs[256]; + STRLEN arg_len; + + psgi_check_args(2); + + node = SvPV_nolen(ST(0)); + func = SvPV_nolen(ST(1)); + + for(i=0;i<(items-2);i++) { + argv[i] = SvPV(ST(i+2), arg_len); + argvs[i] = arg_len; + } + + // response must be always freed + char *response = uwsgi_do_rpc(node, func, items-2, argv, argvs, &size); + if (response) { + ST(0) = newSVpv(response, size); + sv_2mortal(ST(0)); + free(response); + XSRETURN(1); + } + + XSRETURN_UNDEF; +} + + XS(XS_suspend) { @@ -644,6 +679,7 @@ void init_perl_embedded_module() { psgi_xs(cache_clear); psgi_xs(call); + psgi_xs(rpc); psgi_xs(wait_fd_read); psgi_xs(wait_fd_write); psgi_xs(async_sleep); diff --git a/plugins/rack/rack_plugin.c b/plugins/rack/rack_plugin.c index 6d7860c4..4e7a7015 100644 --- a/plugins/rack/rack_plugin.c +++ b/plugins/rack/rack_plugin.c @@ -1107,7 +1107,6 @@ static void uwsgi_rack_hijack(void) { uwsgi_error("dup2()"); } } - int ret = -1; int error = 0; if (ur.rbshell[0] != 0) { rb_eval_string(ur.rbshell); @@ -1123,9 +1122,6 @@ static void uwsgi_rack_hijack(void) { exit(UWSGI_DE_HIJACKED_CODE); } - if (ret == 0) { - exit(UWSGI_QUIET_CODE); - } exit(0); }