From owner-svn-src-head@freebsd.org Tue Feb 20 17:46:51 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 156C2F18DBB; Tue, 20 Feb 2018 17:46:51 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id BC54782968; Tue, 20 Feb 2018 17:46:50 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id B74CC4E15; Tue, 20 Feb 2018 17:46:50 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w1KHkopb064758; Tue, 20 Feb 2018 17:46:50 GMT (envelope-from kevans@FreeBSD.org) Received: (from kevans@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w1KHko6n064756; Tue, 20 Feb 2018 17:46:50 GMT (envelope-from kevans@FreeBSD.org) Message-Id: <201802201746.w1KHko6n064756@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kevans set sender to kevans@FreeBSD.org using -f From: Kyle Evans Date: Tue, 20 Feb 2018 17:46:50 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r329644 - in head/stand: common lua X-SVN-Group: head X-SVN-Commit-Author: kevans X-SVN-Commit-Paths: in head/stand: common lua X-SVN-Commit-Revision: 329644 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Feb 2018 17:46:51 -0000 Author: kevans Date: Tue Feb 20 17:46:50 2018 New Revision: 329644 URL: https://svnweb.freebsd.org/changeset/base/329644 Log: lualoader: Add ability to intercept cli commands If we failed to execute the input line as pure lua, run the command through parse for consistent argument parsing. Pass the parsed arguments through to a global "cli_execute" written in Lua, which is expected to either handle it or pass it back through to interp_builtin_cmd (via loader.command). lua-handled cli commands will then exist as globals in whatever module they most belong in, and invocations at the loader prompt will magically dispatch to them if they exist. Reviewed by: imp Differential Revision: https://reviews.freebsd.org/D14450 Modified: head/stand/common/interp_lua.c head/stand/lua/loader.lua Modified: head/stand/common/interp_lua.c ============================================================================== --- head/stand/common/interp_lua.c Tue Feb 20 17:28:59 2018 (r329643) +++ head/stand/common/interp_lua.c Tue Feb 20 17:46:50 2018 (r329644) @@ -128,7 +128,7 @@ interp_init(void) int interp_run(const char *line) { - int argc; + int argc, nargc; char **argv; lua_State *luap; struct interp_lua_softc *softc = &lua_softc; @@ -137,19 +137,39 @@ interp_run(const char *line) luap = softc->luap; LDBG("executing line..."); if ((status = luaL_dostring(luap, line)) != 0) { + lua_pop(luap, 1); /* - * If we could not parse the line as Lua syntax, - * try parsing it as a loader command. + * The line wasn't executable as lua; run it through parse to + * to get consistent parsing of command line arguments, then + * run it through cli_execute. If that fails, then we'll try it + * as a builtin. */ - lua_pop(luap, 1); if (parse(&argc, &argv, line) == 0) { - status = interp_builtin_cmd(argc, argv); - if (status != CMD_OK) + lua_getglobal(luap, "cli_execute"); + for (nargc = 0; nargc < argc; ++nargc) { + lua_pushstring(luap, argv[nargc]); + } + status = lua_pcall(luap, argc, 1, 0); + lua_pop(luap, 1); + if (status != 0) { + /* + * Lua cli_execute will pass the function back + * through loader.command, which is a proxy to + * interp_builtin_cmd. If we failed to interpret + * the command, though, then there's a chance + * that didn't happen. Call interp_builtin_cmd + * directly if our lua_pcall was not successful. + */ + status = interp_builtin_cmd(argc, argv); + } + if (status != 0) { printf("Command failed\n"); + status = CMD_ERROR; + } free(argv); } else { printf("Failed to parse \'%s\'\n", line); - status = -1; + status = CMD_ERROR; } } Modified: head/stand/lua/loader.lua ============================================================================== --- head/stand/lua/loader.lua Tue Feb 20 17:28:59 2018 (r329643) +++ head/stand/lua/loader.lua Tue Feb 20 17:46:50 2018 (r329644) @@ -1,5 +1,6 @@ -- -- Copyright (c) 2015 Pedro Souza +-- Copyright (c) 2018 Kyle Evans -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without @@ -29,6 +30,24 @@ config = require("config"); menu = require("menu"); password = require("password"); + +-- Declares a global function cli_execute that attempts to dispatch the +-- arguments passed as a lua function. This gives lua a chance to intercept +-- builtin CLI commands like "boot" +function cli_execute(...) + local cmd_name, cmd_args = ...; + local cmd = _G[cmd_name]; + if (cmd ~= nil) and (type(cmd) == "function") then + -- Pass argv wholesale into cmd. We could omit argv[0] since the + -- traditional reasons for including it don't necessarily apply, + -- it may not be totally redundant if we want to have one global + -- handling multiple commands + cmd(...); + else + loader.command(...); + end + +end config.load(); password.check();