diff --git a/src/lua/init.c b/src/lua/init.c index 8945f5d6b6a522e93d86bad7e6f8d4177c2f8138..fefcf8076da9ced44f55a54496392a880a32bccc 100644 --- a/src/lua/init.c +++ b/src/lua/init.c @@ -465,6 +465,24 @@ tarantool_lua_slab_cache() return &cord()->slabc; } +/** + * Push argument and call a function on the top of Lua stack + */ +static void +lua_main(lua_State *L, int argc, char **argv) +{ + assert(lua_isfunction(L, -1)); + lua_checkstack(L, argc - 1); + for (int i = 1; i < argc; i++) + lua_pushstring(L, argv[i]); + if (luaT_call(L, lua_gettop(L) - 1, 0) != 0) { + struct error *e = diag_last_error(&fiber()->diag); + panic("%s", e->errmsg); + } + /* clear the stack from return values. */ + lua_settop(L, 0); +} + /** * Execute start-up script. */ @@ -473,6 +491,7 @@ run_script_f(va_list ap) { struct lua_State *L = va_arg(ap, struct lua_State *); const char *path = va_arg(ap, const char *); + bool interactive = va_arg(ap, int); int argc = va_arg(ap, int); char **argv = va_arg(ap, char **); @@ -487,11 +506,21 @@ run_script_f(va_list ap) /* Execute script. */ if (luaL_loadfile(L, path) != 0) panic("%s", lua_tostring(L, -1)); + lua_main(L, argc, argv); } else if (!isatty(STDIN_FILENO)) { /* Execute stdin */ if (luaL_loadfile(L, NULL) != 0) panic("%s", lua_tostring(L, -1)); + lua_main(L, argc, argv); } else { + interactive = true; + } + + /* + * Start interactive mode when it was explicitly requested + * by "-i" option or stdin is TTY or there are no script. + */ + if (interactive) { say_crit("version %s\ntype 'help' for interactive help", tarantool_version()); /* get console.start from package.loaded */ @@ -501,17 +530,9 @@ run_script_f(va_list ap) lua_remove(L, -2); /* remove package.loaded.console */ lua_remove(L, -2); /* remove package.loaded */ start_loop = false; - } - lua_checkstack(L, argc - 1); - for (int i = 1; i < argc; i++) - lua_pushstring(L, argv[i]); - if (luaT_call(L, lua_gettop(L) - 1, 0) != 0) { - struct error *e = diag_last_error(&fiber()->diag); - panic("%s", e->errmsg); + lua_main(L, argc, argv); } - /* clear the stack from return values. */ - lua_settop(L, 0); /* * Lua script finished. Stop the auxiliary event loop and * return control back to tarantool_lua_run_script. @@ -521,7 +542,7 @@ run_script_f(va_list ap) } void -tarantool_lua_run_script(char *path, int argc, char **argv) +tarantool_lua_run_script(char *path, bool interactive, int argc, char **argv) { const char *title = path ? basename(path) : "interactive"; /* @@ -534,7 +555,7 @@ tarantool_lua_run_script(char *path, int argc, char **argv) script_fiber = fiber_new(title, run_script_f); if (script_fiber == NULL) panic("%s", diag_last_error(diag_get())->errmsg); - fiber_start(script_fiber, tarantool_L, path, argc, argv); + fiber_start(script_fiber, tarantool_L, path, interactive, argc, argv); /* * Run an auxiliary event loop to re-schedule run_script fiber. diff --git a/src/lua/init.h b/src/lua/init.h index 8330081dd550c0889773fc5c888991c57cd410be..cbe7c6e4e945526e5aedf17f53ae38ed4b643810 100644 --- a/src/lua/init.h +++ b/src/lua/init.h @@ -70,10 +70,13 @@ tarantool_lua_tostring(struct lua_State *L, int index); /** * Load and execute start-up file * - * @param L is a Lua State. + * @param interactive force interactive mode + * @param argc argc the number of command line arguments + * @param argv argv command line arguments */ void -tarantool_lua_run_script(char *path, int argc, char **argv); +tarantool_lua_run_script(char *path, bool force_interactive, int argc, + char **argv); extern char *history; diff --git a/src/main.cc b/src/main.cc index 66561a921efda831e2a6faac6cf39c62564e6d8c..9253de825a4257d34a71af9de364a43b30e7286a 100644 --- a/src/main.cc +++ b/src/main.cc @@ -526,12 +526,13 @@ print_help(const char *program) { puts("Tarantool - a Lua application server"); puts(""); - printf("Usage: %s script.lua [OPTIONS]\n", program); + printf("Usage: %s script.lua [OPTIONS] [SCRIPT [ARGS]]\n", program); puts(""); puts("All command line options are passed to the interpreted script."); puts("When no script name is provided, the server responds to:"); puts(" -h, --help\t\t\tdisplay this help and exit"); puts(" -V, --version\t\t\tprint program version and exit"); + puts(" -i\t\t\t\tenter interactive mode after executing 'SCRIPT'"); puts(""); puts("Please visit project home page at http://tarantool.org"); puts("to see online documentation, submit bugs or contribute a patch."); @@ -548,12 +549,15 @@ main(int argc, char **argv) fprintf(stderr, "Failed to set locale to C.UTF-8\n"); fpconv_check(); + /* Enter interactive mode after executing 'script' */ + bool interactive = false; + static struct option longopts[] = { {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {NULL, 0, 0, 0}, }; - static const char *opts = "+hV"; + static const char *opts = "+hVi"; int ch; while ((ch = getopt_long(argc, argv, opts, longopts, NULL)) != -1) { @@ -564,6 +568,10 @@ main(int argc, char **argv) case 'h': print_help(basename(argv[0])); return 0; + case 'i': + /* Force interactive mode */ + interactive = true; + break; default: /* "invalid option" is printed by getopt */ return EX_USAGE; @@ -647,7 +655,8 @@ main(int argc, char **argv) * is why script must run only after the server was fully * initialized. */ - tarantool_lua_run_script(script, main_argc, main_argv); + tarantool_lua_run_script(script, interactive, main_argc, + main_argv); /* * Start event loop after executing Lua script if signal_cb() * wasn't triggered and there is some new events. Initial value diff --git a/test/box-py/args.result b/test/box-py/args.result index 0ee25fcce771c14571755aa0dd4a9f6c554628ab..90845f52de19385ed67be84e635e42c901e85f2c 100644 --- a/test/box-py/args.result +++ b/test/box-py/args.result @@ -1,12 +1,13 @@ tarantool --help Tarantool - a Lua application server -Usage: tarantool script.lua [OPTIONS] +Usage: tarantool script.lua [OPTIONS] [SCRIPT [ARGS]] All command line options are passed to the interpreted script. When no script name is provided, the server responds to: -h, --help display this help and exit -V, --version print program version and exit + -i enter interactive mode after executing 'SCRIPT' Please visit project home page at http://tarantool.org to see online documentation, submit bugs or contribute a patch. @@ -14,12 +15,13 @@ to see online documentation, submit bugs or contribute a patch. tarantool -h Tarantool - a Lua application server -Usage: tarantool script.lua [OPTIONS] +Usage: tarantool script.lua [OPTIONS] [SCRIPT [ARGS]] All command line options are passed to the interpreted script. When no script name is provided, the server responds to: -h, --help display this help and exit -V, --version print program version and exit + -i enter interactive mode after executing 'SCRIPT' Please visit project home page at http://tarantool.org to see online documentation, submit bugs or contribute a patch.