1e37f4622SKyle Evans-- 272e39d71SKyle Evans-- SPDX-License-Identifier: BSD-2-Clause-FreeBSD 372e39d71SKyle Evans-- 4e37f4622SKyle Evans-- Copyright (c) 2018 Kyle Evans <[email protected]> 5e37f4622SKyle Evans-- 6e37f4622SKyle Evans-- Redistribution and use in source and binary forms, with or without 7e37f4622SKyle Evans-- modification, are permitted provided that the following conditions 8e37f4622SKyle Evans-- are met: 9e37f4622SKyle Evans-- 1. Redistributions of source code must retain the above copyright 10e37f4622SKyle Evans-- notice, this list of conditions and the following disclaimer. 11e37f4622SKyle Evans-- 2. Redistributions in binary form must reproduce the above copyright 12e37f4622SKyle Evans-- notice, this list of conditions and the following disclaimer in the 13e37f4622SKyle Evans-- documentation and/or other materials provided with the distribution. 14e37f4622SKyle Evans-- 15e37f4622SKyle Evans-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16e37f4622SKyle Evans-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17e37f4622SKyle Evans-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18e37f4622SKyle Evans-- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19e37f4622SKyle Evans-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20e37f4622SKyle Evans-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21e37f4622SKyle Evans-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22e37f4622SKyle Evans-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23e37f4622SKyle Evans-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24e37f4622SKyle Evans-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25e37f4622SKyle Evans-- SUCH DAMAGE. 26e37f4622SKyle Evans-- 27e37f4622SKyle Evans-- $FreeBSD$ 28e37f4622SKyle Evans-- 29e37f4622SKyle Evans 303e6c7d54SKyle Evanslocal config = require("config") 313e6c7d54SKyle Evanslocal core = require("core") 32e37f4622SKyle Evans 33e37f4622SKyle Evanslocal cli = {} 34e37f4622SKyle Evans 35e37f4622SKyle Evans-- Internal function 36e37f4622SKyle Evans-- Parses arguments to boot and returns two values: kernel_name, argstr 37e37f4622SKyle Evans-- Defaults to nil and "" respectively. 38e37f4622SKyle Evans-- This will also parse arguments to autoboot, but the with_kernel argument 39e37f4622SKyle Evans-- will need to be explicitly overwritten to false 40322a2dddSKyle Evanslocal function parseBootArgs(argv, with_kernel) 41e37f4622SKyle Evans if with_kernel == nil then 42e37f4622SKyle Evans with_kernel = true 43e37f4622SKyle Evans end 44e37f4622SKyle Evans if #argv == 0 then 45e37f4622SKyle Evans if with_kernel then 46e37f4622SKyle Evans return nil, "" 47e37f4622SKyle Evans else 48e37f4622SKyle Evans return "" 49e37f4622SKyle Evans end 50e37f4622SKyle Evans end 51e37f4622SKyle Evans local kernel_name 52e37f4622SKyle Evans local argstr = "" 53e37f4622SKyle Evans 54e2df27e3SKyle Evans for _, v in ipairs(argv) do 55e37f4622SKyle Evans if with_kernel and v:sub(1,1) ~= "-" then 56e37f4622SKyle Evans kernel_name = v 57e37f4622SKyle Evans else 58e37f4622SKyle Evans argstr = argstr .. " " .. v 59e37f4622SKyle Evans end 60e37f4622SKyle Evans end 61e37f4622SKyle Evans if with_kernel then 62e37f4622SKyle Evans return kernel_name, argstr 63e37f4622SKyle Evans else 64e37f4622SKyle Evans return argstr 65e37f4622SKyle Evans end 66e37f4622SKyle Evansend 67e37f4622SKyle Evans 68e37f4622SKyle Evans-- Declares a global function cli_execute that attempts to dispatch the 69e37f4622SKyle Evans-- arguments passed as a lua function. This gives lua a chance to intercept 70e37f4622SKyle Evans-- builtin CLI commands like "boot" 7122ae8ae1SKyle Evans-- This function intentionally does not follow our general naming guideline for 7222ae8ae1SKyle Evans-- functions. This is global pollution, but the clearly separated 'cli' looks 7322ae8ae1SKyle Evans-- more like a module indicator to serve as a hint of where to look for the 7422ae8ae1SKyle Evans-- corresponding definition. 75e37f4622SKyle Evansfunction cli_execute(...) 76e37f4622SKyle Evans local argv = {...} 77e37f4622SKyle Evans -- Just in case... 78e37f4622SKyle Evans if #argv == 0 then 79c6d9f133SKyle Evans return loader.command(...) 80e37f4622SKyle Evans end 81e37f4622SKyle Evans 82e37f4622SKyle Evans local cmd_name = argv[1] 832e4dad82SKyle Evans local cmd = cli[cmd_name] 84e37f4622SKyle Evans if cmd ~= nil and type(cmd) == "function" then 85e37f4622SKyle Evans -- Pass argv wholesale into cmd. We could omit argv[0] since the 86e37f4622SKyle Evans -- traditional reasons for including it don't necessarily apply, 87e37f4622SKyle Evans -- it may not be totally redundant if we want to have one global 88e37f4622SKyle Evans -- handling multiple commands 89c6d9f133SKyle Evans return cmd(...) 90e37f4622SKyle Evans else 91c6d9f133SKyle Evans return loader.command(...) 92e37f4622SKyle Evans end 93e37f4622SKyle Evans 94e37f4622SKyle Evansend 95e37f4622SKyle Evans 96ca3b8c9fSKyle Evansfunction cli_execute_unparsed(str) 97f6e00525SKyle Evans return cli_execute(loader.parse(str)) 98697f127dSKyle Evansend 99697f127dSKyle Evans 100eca5ca66SKyle Evans-- Module exports 101eca5ca66SKyle Evans 1022e4dad82SKyle Evansfunction cli.boot(...) 103e2df27e3SKyle Evans local _, argv = cli.arguments(...) 104322a2dddSKyle Evans local kernel, argstr = parseBootArgs(argv) 1052e4dad82SKyle Evans if kernel ~= nil then 1062e4dad82SKyle Evans loader.perform("unload") 107322a2dddSKyle Evans config.selectKernel(kernel) 1082e4dad82SKyle Evans end 1092e4dad82SKyle Evans core.boot(argstr) 1102e4dad82SKyle Evansend 1112e4dad82SKyle Evans 1122e4dad82SKyle Evansfunction cli.autoboot(...) 113e2df27e3SKyle Evans local _, argv = cli.arguments(...) 114322a2dddSKyle Evans local argstr = parseBootArgs(argv, false) 1152e4dad82SKyle Evans core.autoboot(argstr) 1162e4dad82SKyle Evansend 1172e4dad82SKyle Evans 118*4532ac98SKyle Evanscli['boot-conf'] = function(...) 119*4532ac98SKyle Evans local _, argv = cli.arguments(...) 120*4532ac98SKyle Evans local kernel, argstr = parseBootArgs(argv) 121*4532ac98SKyle Evans if kernel ~= nil then 122*4532ac98SKyle Evans loader.perform("unload") 123*4532ac98SKyle Evans config.selectKernel(kernel) 124*4532ac98SKyle Evans end 125*4532ac98SKyle Evans core.autoboot(argstr) 126*4532ac98SKyle Evansend 127*4532ac98SKyle Evans 1282e4dad82SKyle Evans-- Used for splitting cli varargs into cmd_name and the rest of argv 129eca5ca66SKyle Evansfunction cli.arguments(...) 130eca5ca66SKyle Evans local argv = {...} 131e2df27e3SKyle Evans local cmd_name 132eca5ca66SKyle Evans cmd_name, argv = core.popFrontTable(argv) 133eca5ca66SKyle Evans return cmd_name, argv 134eca5ca66SKyle Evansend 135eca5ca66SKyle Evans 136e37f4622SKyle Evansreturn cli 137