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