diff --git a/source/cli/metacallcli/CMakeLists.txt b/source/cli/metacallcli/CMakeLists.txt index 3bb2e64f0..7df77fa87 100644 --- a/source/cli/metacallcli/CMakeLists.txt +++ b/source/cli/metacallcli/CMakeLists.txt @@ -211,10 +211,8 @@ add_test(NAME ${target} COMMAND ${CMAKE_COMMAND} -D "EXECUTABLE=$" -D "INPUT=${TEST_COMMAND_INPUT}.txt" -P ${TEST_COMMAND_RUNNER} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) -set_property(TEST ${target} - PROPERTY LABELS ${target} -) set_tests_properties(${target} PROPERTIES + LABELS ${target} PASS_REGULAR_EXPRESSION "function three_str\\(a_str, b_str, c_str\\)" ) test_environment_variables(${target} @@ -239,10 +237,8 @@ if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_NODE AND OPTION_BUILD_SCRIPTS A COMMAND ${CMAKE_COMMAND} -D "EXECUTABLE=$" -D "INPUT=${TEST_COMMAND_INPUT}-node.txt" -P ${TEST_COMMAND_RUNNER} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) - set_property(TEST ${target}-node - PROPERTY LABELS ${target}-node - ) set_tests_properties(${target}-node PROPERTIES + LABELS ${target}-node PASS_REGULAR_EXPRESSION "4001534" ) test_environment_variables(${target}-node @@ -254,10 +250,8 @@ if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_NODE AND OPTION_BUILD_SCRIPTS A COMMAND ${CMAKE_COMMAND} -D "EXECUTABLE=$" -D "INPUT=${TEST_COMMAND_INPUT}-node-port-py.txt" -P ${TEST_COMMAND_RUNNER} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) - set_property(TEST ${target}-node-port-py - PROPERTY LABELS ${target}-node-port-py - ) set_tests_properties(${target}-node-port-py PROPERTIES + LABELS ${target}-node-port-py PASS_REGULAR_EXPRESSION "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ) test_environment_variables(${target}-node-port-py @@ -284,10 +278,8 @@ if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_NODE AND OPTION_BUILD_SCRIPTS A COMMAND ${CMAKE_COMMAND} -D "EXECUTABLE=$" -D "INPUT=${TEST_COMMAND_INPUT}-node-null.txt" -P ${TEST_COMMAND_RUNNER} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) - set_property(TEST ${target}-node-null - PROPERTY LABELS ${target}-node-null - ) set_tests_properties(${target}-node-null PROPERTIES + LABELS ${target}-node-null PASS_REGULAR_EXPRESSION "Hello 342521512461246!" ) test_environment_variables(${target}-node-null @@ -299,10 +291,8 @@ if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_NODE AND OPTION_BUILD_SCRIPTS A COMMAND ${CMAKE_COMMAND} -D "EXECUTABLE=$" -D "INPUT=${TEST_COMMAND_INPUT}-node-null-empty.txt" -P ${TEST_COMMAND_RUNNER} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) - set_property(TEST ${target}-node-null-empty - PROPERTY LABELS ${target}-node-null-empty - ) set_tests_properties(${target}-node-null-empty PROPERTIES + LABELS ${target}-node-null-empty PASS_REGULAR_EXPRESSION "Hello 342521512461246!" ) test_environment_variables(${target}-node-null-empty @@ -314,10 +304,8 @@ if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_NODE AND OPTION_BUILD_SCRIPTS A COMMAND ${CMAKE_COMMAND} -D "EXECUTABLE=$" -D "INPUT=${TEST_COMMAND_INPUT}-node-null-undefined.txt" -P ${TEST_COMMAND_RUNNER} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) - set_property(TEST ${target}-node-null-undefined - PROPERTY LABELS ${target}-node-null-undefined - ) set_tests_properties(${target}-node-null-undefined PROPERTIES + LABELS ${target}-node-null-undefined PASS_REGULAR_EXPRESSION "(null)" ) test_environment_variables(${target}-node-null-undefined @@ -330,10 +318,8 @@ if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_NODE AND OPTION_BUILD_SCRIPTS A COMMAND ${CMAKE_COMMAND} -D "EXECUTABLE=$" -D "INPUT=${TEST_COMMAND_INPUT}-py-port.txt" -P ${TEST_COMMAND_RUNNER} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) - set_property(TEST ${target}-py-port - PROPERTY LABELS ${target}-py-port - ) set_tests_properties(${target}-py-port PROPERTIES + LABELS ${target}-py-port PASS_REGULAR_EXPRESSION "1234" ) test_environment_variables(${target}-py-port @@ -346,10 +332,8 @@ if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_NODE AND OPTION_BUILD_SCRIPTS A COMMAND ${CMAKE_COMMAND} -D "EXECUTABLE=$" -D "INPUT=${TEST_COMMAND_INPUT}-py-port-rb.txt" -P ${TEST_COMMAND_RUNNER} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) - set_property(TEST ${target}-py-port-rb - PROPERTY LABELS ${target}-py-port-rb - ) set_tests_properties(${target}-py-port-rb PROPERTIES + LABELS ${target}-py-port-rb PASS_REGULAR_EXPRESSION "0123456789ABCDEFasd" ) test_environment_variables(${target}-py-port-rb @@ -365,10 +349,8 @@ if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_FILE AND OPTION_BUILD_SCRIPTS A COMMAND ${CMAKE_COMMAND} -D "EXECUTABLE=$" -D "INPUT=${TEST_COMMAND_INPUT}-file.txt" -P ${TEST_COMMAND_RUNNER} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) - set_property(TEST ${target}-file - PROPERTY LABELS ${target}-file - ) set_tests_properties(${target}-file PROPERTIES + LABELS ${target}-file PASS_REGULAR_EXPRESSION "${LOADER_SCRIPT_PATH}/template.html" ) test_environment_variables(${target}-file @@ -379,10 +361,8 @@ if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_FILE AND OPTION_BUILD_SCRIPTS A COMMAND $ this-does-not-exist WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) - set_property(TEST ${target}-file-fail - PROPERTY LABELS ${target}-file-fail - ) set_tests_properties(${target}-file-fail PROPERTIES + LABELS ${target}-file-fail PASS_REGULAR_EXPRESSION "Error: Failed to load script 'this-does-not-exist' with loader 'file'" ) test_environment_variables(${target}-file-fail @@ -396,10 +376,8 @@ if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_PY) COMMAND $ test.py WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) - set_property(TEST ${target}-py-naming - PROPERTY LABELS ${target}-py-naming - ) set_tests_properties(${target}-py-naming PROPERTIES + LABELS ${target}-py-naming PASS_REGULAR_EXPRESSION "Test: 66673332" ) test_environment_variables(${target}-py-naming @@ -410,10 +388,8 @@ if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_PY) COMMAND $ cli-test-argv.py WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) - set_property(TEST ${target}-py-argv - PROPERTY LABELS ${target}-py-argv - ) set_tests_properties(${target}-py-argv PROPERTIES + LABELS ${target}-py-argv PASS_REGULAR_EXPRESSION "Test: cli-test-argv.py" ) test_environment_variables(${target}-py-argv @@ -424,10 +400,8 @@ if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_PY) COMMAND $ cli-test-main.py WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) - set_property(TEST ${target}-py-main - PROPERTY LABELS ${target}-py-main - ) set_tests_properties(${target}-py-main PROPERTIES + LABELS ${target}-py-main PASS_REGULAR_EXPRESSION "Test: 1234567890abcd" ) test_environment_variables(${target}-py-main @@ -438,10 +412,8 @@ if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_PY) COMMAND ${CMAKE_COMMAND} -D "EXECUTABLE=$" -D "INPUT=${TEST_COMMAND_INPUT}-py-exception.txt" -P ${TEST_COMMAND_RUNNER} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) - set_property(TEST ${target}-py-exception - PROPERTY LABELS ${target}-py-exception - ) set_tests_properties(${target}-py-exception PROPERTIES + LABELS ${target}-py-exception PASS_REGULAR_EXPRESSION "66" ) test_environment_variables(${target}-py-exception @@ -455,10 +427,8 @@ if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_TS AND OPTION_BUILD_SCRIPTS AND COMMAND ${CMAKE_COMMAND} -D "EXECUTABLE=$" -D "INPUT=${TEST_COMMAND_INPUT}-ts.txt" -P ${TEST_COMMAND_RUNNER} WORKING_DIRECTORY ${LOADER_SCRIPT_PATH}/typedfunc ) - set_property(TEST ${target}-ts - PROPERTY LABELS ${target}-ts - ) set_tests_properties(${target}-ts PROPERTIES + LABELS ${target}-ts PASS_REGULAR_EXPRESSION "51354" ) test_environment_variables(${target}-ts @@ -469,10 +439,8 @@ if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_TS AND OPTION_BUILD_SCRIPTS AND COMMAND ${CMAKE_COMMAND} -D "EXECUTABLE=$" -D "INPUT=${TEST_COMMAND_INPUT}-tsx-templating.txt" -P ${TEST_COMMAND_RUNNER} WORKING_DIRECTORY ${LOADER_SCRIPT_PATH}/templating ) - set_property(TEST ${target}-tsx-templating - PROPERTY LABELS ${target}-tsx-templating - ) set_tests_properties(${target}-tsx-templating PROPERTIES + LABELS ${target}-tsx-templating PASS_REGULAR_EXPRESSION "Hello metaprogrammer" ) test_environment_variables(${target}-tsx-templating @@ -506,10 +474,8 @@ if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_TS AND OPTION_BUILD_SCRIPTS AND COMMAND $ loopfail.tsx WORKING_DIRECTORY ${LOADER_SCRIPT_PATH}/loopfail ) - set_property(TEST ${target}-tsx-loop-fail - PROPERTY LABELS ${target}-tsx-loop-fail - ) set_tests_properties(${target}-tsx-loop-fail PROPERTIES + LABELS ${target}-tsx-loop-fail PASS_REGULAR_EXPRESSION "Error: Cannot find module 'yeet-oof/whatever'" ) test_environment_variables(${target}-tsx-loop-fail @@ -523,10 +489,8 @@ if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_TS AND OPTION_BUILD_SCRIPTS AND COMMAND ${CMAKE_COMMAND} -D "EXECUTABLE=$" -D "INPUT=${TEST_COMMAND_INPUT}-py-tsx.txt" -P ${TEST_COMMAND_RUNNER} WORKING_DIRECTORY ${LOADER_SCRIPT_PATH}/templating ) - set_property(TEST ${target}-py-tsx - PROPERTY LABELS ${target}-py-tsx - ) set_tests_properties(${target}-py-tsx PROPERTIES + LABELS ${target}-py-tsx PASS_REGULAR_EXPRESSION "Hello World" ) test_environment_variables(${target}-py-tsx @@ -539,3 +503,20 @@ if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_TS AND OPTION_BUILD_SCRIPTS AND ) endif() endif() + +if(OPTION_BUILD_LOADERS AND OPTION_BUILD_LOADERS_EXT AND OPTION_BUILD_EXTENSIONS AND OPTION_BUILD_LOADERS_NODE AND OPTION_BUILD_LOADERS_PY AND OPTION_BUILD_PLUGINS_SANDBOX AND PROJECT_OS_FAMILY STREQUAL unix) + if(NOT OPTION_BUILD_THREAD_SANITIZER AND NOT OPTION_BUILD_ADDRESS_SANITIZER) + add_test(NAME ${target}-cmd-sandboxing + COMMAND ${CMAKE_COMMAND} -E env $ --sandboxing --disable_time time.py + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) + set_tests_properties(${target}-cmd-sandboxing PROPERTIES + LABELS ${target}-cmd-sandboxing + WILL_FAIL TRUE + ) + test_environment_variables(${target}-cmd-sandboxing + "" + ${TESTS_ENVIRONMENT_VARIABLES} + ) + endif() +endif() diff --git a/source/cli/metacallcli/source/application.cpp b/source/cli/metacallcli/source/application.cpp index e207ad26e..b1b22761b 100644 --- a/source/cli/metacallcli/source/application.cpp +++ b/source/cli/metacallcli/source/application.cpp @@ -98,7 +98,29 @@ bool application::cmd(std::vector &arguments) /* Get the command parsing function */ void *command_parse_func = metacall_handle_function(plugin_cli_handle, "command_parse"); + /* By default, when executing the cmd, it will exit of the REPL */ + exit_condition = true; + if (command_parse_func == NULL) + { + std::cout << "Warning: CLI Arguments Parser was not loaded, " + "using fallback argument parser with positional arguments only. " + << std::endl + << "Any command line option like '--help' will result into error. " + "Only files are allowed: $ metacall a.py b.js c.rb" + << std::endl; + + /* Use fallback parser, it can execute files but does not support command line arguments as options (i.e: -h, --help) */ + /* Parse program arguments if any (e.g metacall (0) a.py (1) b.js (2) c.rb (3)) */ + arguments_parse(arguments); + + return true; + } + + /* Check first if the command function is registered */ + void *command_function_func = metacall_handle_function(plugin_cli_handle, "command_function"); + + if (command_function_func == NULL) { return false; } @@ -149,15 +171,51 @@ bool application::cmd(std::vector &arguments) void **ret_array = metacall_value_to_array(ret); void **command_map = metacall_value_to_map(ret_array[0]); size_t command_size = metacall_value_count(ret_array[0]); - void **positional_array = metacall_value_to_map(ret_array[1]); + void **positional_array = metacall_value_to_array(ret_array[1]); size_t positional_size = metacall_value_count(ret_array[1]); /* Execute arguments */ for (size_t iterator = 0; iterator < command_size; ++iterator) { void **command_pair = metacall_value_to_array(command_map[iterator]); + + void *args[] = { + command_pair[0] + }; + + void *command_func = metacallfv_s(command_function_func, args, sizeof(args) / sizeof(args[0])); + + if (metacall_value_id(command_func) == METACALL_FUNCTION) + { + /* Execute the function */ + void *command_ret = metacallfv_s(command_func, &command_pair[1], 1); + metacall_value_destroy(command_func); + check_for_exception(command_ret); + continue; + } + else if (metacall_value_id(command_func) == METACALL_DOUBLE) + { + static const double COMMAND_NOT_REGISTERED = 0.0; + + /* The command is not registered, skip it */ + if (metacall_value_to_double(command_func) == COMMAND_NOT_REGISTERED) + { + metacall_value_destroy(command_func); + continue; + } + + /* If the function is undefined, try to match the command with a function in the handle scope */ + metacall_value_destroy(command_func); + } + else + { + check_for_exception(command_func); + return false; + } + + /* Otherwise use the cmd handle scope for obtaining the function */ const char *command_str = metacall_value_to_string(command_pair[0]); - void *command_func = metacall_handle_function(plugin_cmd_handle, command_str); + command_func = metacall_handle_function(plugin_cmd_handle, command_str); if (command_func == NULL) { @@ -177,6 +235,7 @@ bool application::cmd(std::vector &arguments) { /* Initialize the REPL */ repl(); + exit_condition = false; } else { @@ -189,7 +248,7 @@ bool application::cmd(std::vector &arguments) positional_arguments.push_back(metacall_value_to_string(positional_array[iterator])); } - arguments_parse(arguments); + arguments_parse(positional_arguments); } metacall_value_destroy(ret); @@ -233,19 +292,8 @@ application::application(int argc, char *argv[]) : /* Launch the CMD (parse arguments) */ if (!cmd(arguments)) { - std::cout << "Warning: CLI Arguments Parser was not loaded, " - "using fallback argument parser with positional arguments only. " - << std::endl - << "Any command line option like '--help' will result into error. " - "Only files are allowed: $ metacall a.py b.js c.rb" - << std::endl; - - /* Use fallback parser, it can execute files but does not support command line arguments as options (i.e: -h, --help) */ - /* Parse program arguments if any (e.g metacall (0) a.py (1) b.js (2) c.rb (3)) */ - arguments_parse(arguments); + /* TODO: Report something? */ } - - exit_condition = true; } } @@ -472,12 +520,24 @@ void application::run() metacall_value_destroy(await_data.v); } - /* Close REPL */ if (plugin_cli_handle != NULL) { + /* Close REPL */ void *ret = metacallhv_s(plugin_cli_handle, "repl_close", metacall_null_args, 0); check_for_exception(ret); + + /* Get the command destroy function */ + void *command_destroy_func = metacall_handle_function(plugin_cli_handle, "command_destroy"); + + /* Destroy the commands */ + if (command_destroy_func != NULL) + { + /* Parse the arguments with the CMD plugin command parse function */ + ret = metacallfv_s(command_destroy_func, metacall_null_args, 0); + + check_for_exception(ret); + } } } diff --git a/source/cli/metacallcli/test/time.py b/source/cli/metacallcli/test/time.py new file mode 100644 index 000000000..d181d115d --- /dev/null +++ b/source/cli/metacallcli/test/time.py @@ -0,0 +1,3 @@ +import time + +time.sleep(1) diff --git a/source/cli/plugins/cli_cmd_plugin/include/cli_cmd_plugin/cli_cmd_plugin.hpp b/source/cli/plugins/cli_cmd_plugin/include/cli_cmd_plugin/cli_cmd_plugin.hpp new file mode 100644 index 000000000..9565754ca --- /dev/null +++ b/source/cli/plugins/cli_cmd_plugin/include/cli_cmd_plugin/cli_cmd_plugin.hpp @@ -0,0 +1,67 @@ +/* + * CLI Command Plugin by Parra Studios + * A plugin implementing command line functionality for MetaCall CLI. + * + * Copyright (C) 2016 - 2024 Vicente Eduardo Ferrer Garcia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef CLI_CMD_PLUGIN_H +#define CLI_CMD_PLUGIN_H 1 + +#include + +#define cli_cmd_plugin() metacall_handle("node", "plugins/cli/internal/cli_cmd_plugin/cli_cmd_plugin.js") + +#define cli_cmd_plugin_register(cli_cmd_handle, name, type, destroy) \ + do \ + { \ + const size_t map_size = destroy == NULL ? 1 : 2; \ +\ + void *args[] = { \ + metacall_value_create_string(name, sizeof(name) - 1), \ + metacall_value_create_map(NULL, map_size) \ + }; \ +\ + void **options = metacall_value_to_map(args[1]); \ + options[0] = metacall_value_create_array(NULL, 2); \ + void **type_tupla = metacall_value_to_array(options[0]); \ +\ + static const char type_key[] = "type"; \ + static const char type_value[] = type; \ +\ + type_tupla[0] = metacall_value_create_string(type_key, sizeof(type_key) - 1); \ + type_tupla[1] = metacall_value_create_string(type_value, sizeof(type_value) - 1); \ +\ + if (destroy != NULL) \ + { \ + options[1] = metacall_value_create_array(NULL, 2); \ + void **destroy_tupla = metacall_value_to_array(options[1]); \ +\ + static const char destroy_key[] = "destroy"; \ +\ + destroy_tupla[0] = metacall_value_create_string(destroy_key, sizeof(destroy_key) - 1); \ + destroy_tupla[1] = metacall_value_create_function(metacall_handle_function(handle, destroy)); \ + } \ +\ + void *ret = metacallhv_s(cli_cmd_handle, "command_register", args, sizeof(args) / sizeof(args[0])); \ +\ + metacall_value_destroy(ret); \ + metacall_value_destroy(args[0]); \ + metacall_value_destroy(args[1]); \ +\ + } while (0) + +#endif /* CLI_CMD_PLUGIN_H */ diff --git a/source/cli/plugins/cli_cmd_plugin/source/cli_cmd_plugin.js b/source/cli/plugins/cli_cmd_plugin/source/cli_cmd_plugin.js index a6d635f18..e5eb42121 100644 --- a/source/cli/plugins/cli_cmd_plugin/source/cli_cmd_plugin.js +++ b/source/cli/plugins/cli_cmd_plugin/source/cli_cmd_plugin.js @@ -1,4 +1,6 @@ const util = require('util'); +const path = require('path'); +const fs = require('fs'); const options = {}; @@ -6,6 +8,16 @@ function command_initialize(plugin_path) { /* Initialize all CMD descriptors * This will load all plugin descriptors like: * plugins/cli/cmd/${plugin_name}/${plugin_name}_cmd.js + * + * The expected format is the following (e.g: cli_help_plugin.js): + * module.exports = { + * 'help': { + * short: 'h', + * type: 'METACALL_BOOL' // This field is required + * fn: () => {} // Function will be executed when the command is called + * destroy: () => {} // Function will be executed at the end of the CLI lifecycle + * } + * }; */ const cmd_path = path.join(plugin_path, 'cli', 'cmd'); const files = fs.readdirSync(cmd_path); @@ -16,17 +28,21 @@ function command_initialize(plugin_path) { if (file_stat.isDirectory()) { const descriptor_path = path.join(file_path, `${file}_cmd.js`); - const descriptor_stat = fs.statSync(descriptor_path); + try { + const descriptor_stat = fs.statSync(descriptor_path); - if (descriptor_stat.isFile()) { - const descriptor = require(descriptor_path); - options = { ...options, ...descriptor }; + if (descriptor_stat.isFile()) { + const descriptor = require(descriptor_path); + options = { ...options, ...descriptor }; + } + } catch (e) { + /* Skip */ } } } } -function command_register(cmd, type, short, multiple) { +function command_register(cmd, { short, type, multiple, func, destroy }) { const type_map = { METACALL_STRING: 'string', METACALL_BOOL: 'boolean' @@ -43,9 +59,17 @@ function command_register(cmd, type, short, multiple) { if (multiple) { options[cmd]['multiple'] = multiple; } + + if (func) { + options[cmd]['func'] = func; + } + + if (destroy) { + options[cmd]['destroy'] = destroy; + } } -function command_parse(args) { +function command_parse(...args) { const { values, positionals } = util.parseArgs({ args, options, @@ -55,8 +79,33 @@ function command_parse(args) { return [ { ...values }, positionals ]; } +function command_function(cmd) { + const COMMAND_NOT_REGISTERED = 0; + const COMMAND_FUNCTION_UNDEFINED = 1; + + if (options[cmd] === undefined) { + return COMMAND_NOT_REGISTERED; + } + + if (options[cmd].func === undefined) { + return COMMAND_FUNCTION_UNDEFINED; + } + + return options[cmd].func; +} + +function command_destroy() { + for (const { destroy } of Object.values(options)) { + if (destroy) { + destroy(); + } + } +} + module.exports = { command_initialize, command_register, - command_parse + command_parse, + command_function, + command_destroy }; diff --git a/source/cli/plugins/cli_cmd_plugin/source/test.js b/source/cli/plugins/cli_cmd_plugin/source/test.js index 4b9fa2e63..c3f8903ec 100644 --- a/source/cli/plugins/cli_cmd_plugin/source/test.js +++ b/source/cli/plugins/cli_cmd_plugin/source/test.js @@ -1,13 +1,15 @@ const assert = require('assert').strict; const { command_register, command_parse } = require('./cli_cmd_plugin') -command_register('help', 'METACALL_BOOL', 'h'); -command_register('option', 'METACALL_STRING', 'o'); -command_register('multiple', 'METACALL_STRING', 'm', true); +command_register('empty', {}); +command_register('help', { short: 'h', type: 'METACALL_BOOL' }); +command_register('option', { short: 'o', type: 'METACALL_STRING' }); +command_register('multiple', { short: 'm', type: 'METACALL_STRING', multiple: true }); -assert.deepEqual(command_parse([]), [{}, []]); -assert.deepEqual(command_parse(['-h']), [{ help: true }, []]); -assert.deepEqual(command_parse(['--help']), [{ help: true }, []]); -assert.deepEqual(command_parse(['--help', 'a.js']), [{ help: true }, ['a.js']]); -assert.deepEqual(command_parse(['--option=hello', 'a.js']), [{ option: 'hello' }, ['a.js']]); -assert.deepEqual(command_parse(['--multiple=a', '--multiple=b', '--multiple=c']), [{ multiple: ['a', 'b', 'c'] }, []]); +assert.deepEqual(command_parse(), [{}, []]); +assert.deepEqual(command_parse('--empty'), [{ empty: true }, []]); +assert.deepEqual(command_parse('-h'), [{ help: true }, []]); +assert.deepEqual(command_parse('--help'), [{ help: true }, []]); +assert.deepEqual(command_parse('--help', 'a.js'), [{ help: true }, ['a.js']]); +assert.deepEqual(command_parse('--option=hello', 'a.js'), [{ option: 'hello' }, ['a.js']]); +assert.deepEqual(command_parse('--multiple=a', '--multiple=b', '--multiple=c'), [{ multiple: ['a', 'b', 'c'] }, []]); diff --git a/source/cli/plugins/cli_core_plugin/CMakeLists.txt b/source/cli/plugins/cli_core_plugin/CMakeLists.txt index 634818484..2dd38f06d 100644 --- a/source/cli/plugins/cli_core_plugin/CMakeLists.txt +++ b/source/cli/plugins/cli_core_plugin/CMakeLists.txt @@ -189,16 +189,19 @@ target_link_libraries(${target} INTERFACE ) +# +# Dependencies +# + add_dependencies(${target} plugin_extension cli_repl_plugin ) # -# Define dependencies +# Configuration # -# Copy metacall.json add_custom_target(${target}_config ALL WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${CMAKE_COMMAND} -E make_directory ${PLUGIN_OUTPUT_DIRECTORY} diff --git a/source/cli/plugins/cli_repl_plugin/source/cli_repl_plugin.js b/source/cli/plugins/cli_repl_plugin/source/cli_repl_plugin.js index c99a69db7..0ff4a09e3 100644 --- a/source/cli/plugins/cli_repl_plugin/source/cli_repl_plugin.js +++ b/source/cli/plugins/cli_repl_plugin/source/cli_repl_plugin.js @@ -44,10 +44,14 @@ function repl_initialize(plugin_path) { if (file_stat.isDirectory()) { const descriptor_path = path.join(file_path, `${file}_repl.js`); - const descriptor_stat = fs.statSync(descriptor_path); - - if (descriptor_stat.isFile()) { - repl_register_from_file(descriptor_path); + try { + const descriptor_stat = fs.statSync(descriptor_path); + + if (descriptor_stat.isFile()) { + repl_register_from_file(descriptor_path); + } + } catch (e) { + /* Skip */ } } } diff --git a/source/cli/plugins/cli_sandbox_plugin/CMakeLists.txt b/source/cli/plugins/cli_sandbox_plugin/CMakeLists.txt index 1bfe369b1..e4d16acd2 100644 --- a/source/cli/plugins/cli_sandbox_plugin/CMakeLists.txt +++ b/source/cli/plugins/cli_sandbox_plugin/CMakeLists.txt @@ -1,5 +1,5 @@ # Check if this loader is enabled -if(NOT OPTION_BUILD_LOADERS OR NOT OPTION_BUILD_LOADERS_EXT OR NOT OPTION_BUILD_EXTENSIONS OR NOT OPTION_BUILD_LOADERS_NODE OR NOT TARGET sandbox_plugin) +if(NOT OPTION_BUILD_LOADERS OR NOT OPTION_BUILD_LOADERS_EXT OR NOT OPTION_BUILD_EXTENSIONS OR NOT OPTION_BUILD_LOADERS_NODE OR NOT OPTION_BUILD_PLUGINS_SANDBOX) return() endif() @@ -13,34 +13,175 @@ set(target cli_sandbox_plugin) # Exit here if required dependencies are not met message(STATUS "Plugin ${target}") +# Set API export file and macro +string(TOUPPER ${target} target_upper) +set(export_file "include/${target}/${target}_api.h") +set(export_macro "${target_upper}_API") + # -# Source +# Compiler warnings # -set(source_path "${CMAKE_CURRENT_SOURCE_DIR}/source") +include(Warnings) # -# Destination +# Compiler security # -set(PLUGIN_OUTPUT_DIRECTORY "${PROJECT_OUTPUT_DIR}/plugins/cli/cmd/${target}") +include(SecurityFlags) # -# Project Target +# Sources # -add_custom_target(${target} ALL - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E copy ${source_path}/cli_sandbox_plugin_cmd.js ${PLUGIN_OUTPUT_DIRECTORY}/cli_sandbox_plugin_cmd.js +set(include_path "${CMAKE_CURRENT_SOURCE_DIR}/include/${target}") +set(source_path "${CMAKE_CURRENT_SOURCE_DIR}/source") + +set(headers + ${include_path}/cli_sandbox_plugin.h ) +set(sources + ${source_path}/cli_sandbox_plugin.cpp +) + +# Group source files +set(header_group "Header Files (API)") +set(source_group "Source Files") +source_group_by_path(${include_path} "\\\\.h$|\\\\.hpp$" + ${header_group} ${headers}) +source_group_by_path(${source_path} "\\\\.cpp$|\\\\.c$|\\\\.h$|\\\\.hpp$" + ${source_group} ${sources}) + # -# Target Properties +# Create library # +# Build library +add_library(${target} MODULE + ${sources} + ${headers} +) + +# Create namespaced alias +add_library(${META_PROJECT_NAME}::${target} ALIAS ${target}) + +# Export library for downstream projects +export(TARGETS ${target} NAMESPACE ${META_PROJECT_NAME}:: FILE ${PROJECT_BINARY_DIR}/cmake/${target}/${target}-export.cmake) + +# Create API export header +generate_export_header(${target} + EXPORT_FILE_NAME ${export_file} + EXPORT_MACRO_NAME ${export_macro} +) + +# +# Project options +# + +set(PLUGIN_OUTPUT_DIRECTORY "${PROJECT_OUTPUT_DIR}/plugins/cli/cmd/${target}") + set_target_properties(${target} PROPERTIES + ${DEFAULT_PROJECT_OPTIONS} FOLDER "${IDE_FOLDER}" + BUNDLE $<$:$<$>> + + # Define custom build output directory + LIBRARY_OUTPUT_DIRECTORY "${PLUGIN_OUTPUT_DIRECTORY}" + LIBRARY_OUTPUT_DIRECTORY_DEBUG "${PLUGIN_OUTPUT_DIRECTORY}" + LIBRARY_OUTPUT_DIRECTORY_RELEASE "${PLUGIN_OUTPUT_DIRECTORY}" + LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO "${PLUGIN_OUTPUT_DIRECTORY}" + LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL "${PLUGIN_OUTPUT_DIRECTORY}" + + RUNTIME_OUTPUT_DIRECTORY "${PLUGIN_OUTPUT_DIRECTORY}" + RUNTIME_OUTPUT_DIRECTORY_DEBUG "${PLUGIN_OUTPUT_DIRECTORY}" + RUNTIME_OUTPUT_DIRECTORY_RELEASE "${PLUGIN_OUTPUT_DIRECTORY}" + RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO "${PLUGIN_OUTPUT_DIRECTORY}" + RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL "${PLUGIN_OUTPUT_DIRECTORY}" + + ARCHIVE_OUTPUT_DIRECTORY "${PLUGIN_OUTPUT_DIRECTORY}" + ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${PLUGIN_OUTPUT_DIRECTORY}" + ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${PLUGIN_OUTPUT_DIRECTORY}" + ARCHIVE_OUTPUT_DIRECTORY_RELWITHDEBINFO "${PLUGIN_OUTPUT_DIRECTORY}" + ARCHIVE_OUTPUT_DIRECTORY_MINSIZEREL "${PLUGIN_OUTPUT_DIRECTORY}" +) + +# +# Include directories +# + +target_include_directories(${target} + PRIVATE + ${PROJECT_BINARY_DIR}/source/include + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_BINARY_DIR}/include + + $ # MetaCall includes + + ${CMAKE_SOURCE_DIR}/source/cli/plugins/cli_cmd_plugin/include # CMD Plugin includes + + PUBLIC + ${DEFAULT_INCLUDE_DIRECTORIES} + + INTERFACE + $ + $ + $ +) + +# +# Libraries +# + +target_link_libraries(${target} + PRIVATE + ${META_PROJECT_NAME}::metacall # MetaCall library + + PUBLIC + ${DEFAULT_LIBRARIES} + + INTERFACE +) + +# +# Compile definitions +# + +target_compile_definitions(${target} + PRIVATE + + PUBLIC + $<$>:${target_upper}_STATIC_DEFINE> + ${DEFAULT_COMPILE_DEFINITIONS} + + INTERFACE +) + +# +# Compile options +# + +target_compile_options(${target} + PRIVATE + + PUBLIC + ${DEFAULT_COMPILE_OPTIONS} + + INTERFACE +) + +# +# Linker options +# + +target_link_libraries(${target} + PRIVATE + + PUBLIC + ${DEFAULT_LINKER_OPTIONS} + + INTERFACE ) # @@ -52,3 +193,18 @@ add_dependencies(${target} node_loader sandbox_plugin ) + +# +# Configuration +# + +add_custom_target(${target}_config ALL + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E make_directory ${PLUGIN_OUTPUT_DIRECTORY} + COMMAND ${CMAKE_COMMAND} -E copy ${source_path}/metacall.json ${PLUGIN_OUTPUT_DIRECTORY}/metacall.json +) + +set_target_properties(${target}_config + PROPERTIES + FOLDER "${IDE_FOLDER}" +) diff --git a/source/cli/plugins/cli_sandbox_plugin/include/cli_sandbox_plugin/cli_sandbox_plugin.h b/source/cli/plugins/cli_sandbox_plugin/include/cli_sandbox_plugin/cli_sandbox_plugin.h new file mode 100644 index 000000000..f0f1aa671 --- /dev/null +++ b/source/cli/plugins/cli_sandbox_plugin/include/cli_sandbox_plugin/cli_sandbox_plugin.h @@ -0,0 +1,40 @@ +/* + * CLI Sandbox Plugin by Parra Studios + * A plugin implementing sandboxing functionality for MetaCall CLI. + * + * Copyright (C) 2016 - 2024 Vicente Eduardo Ferrer Garcia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef CLI_SANDBOX_PLUGIN_H +#define CLI_SANDBOX_PLUGIN_H 1 + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +CLI_SANDBOX_PLUGIN_API int cli_sandbox_plugin(void *loader, void *handle); + +DYNLINK_SYMBOL_EXPORT(cli_sandbox_plugin); + +#ifdef __cplusplus +} +#endif + +#endif /* CLI_SANDBOX_PLUGIN_H */ diff --git a/source/cli/plugins/cli_sandbox_plugin/source/cli_sandbox_plugin.cpp b/source/cli/plugins/cli_sandbox_plugin/source/cli_sandbox_plugin.cpp new file mode 100644 index 000000000..f7a78b130 --- /dev/null +++ b/source/cli/plugins/cli_sandbox_plugin/source/cli_sandbox_plugin.cpp @@ -0,0 +1,188 @@ +/* + * CLI Sandbox Plugin by Parra Studios + * A plugin implementing sandboxing functionality for MetaCall CLI. + * + * Copyright (C) 2016 - 2024 Vicente Eduardo Ferrer Garcia + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include + +#include + +#define SANDBOXING_NOT_INITIALIZED_ERROR "Sandboxing has not been initialized, enable it by passing --sandboxing to the CLI" + +void *sandboxing_handle = NULL; +void *sandboxing_context = NULL; + +void *sandboxing(size_t argc, void *args[], void *data) +{ + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK("Failed to initialize sandboxing", METACALL_BOOL); + + void *init_args[] = { + metacall_value_create_bool(1L) /* Allow everything by default */ + }; + + sandboxing_context = metacallhv_s(sandboxing_handle, "sandbox_initialize", init_args, sizeof(init_args) / sizeof(init_args[0])); + + metacall_value_destroy(init_args[0]); + + if (metacall_value_id(sandboxing_context) != METACALL_PTR) + { + /* It is an exception, rethrow it */ + return sandboxing_context; + } + + return metacall_value_create_int(0); +} + +void *sandboxing_destroy(size_t argc, void *args[], void *data) +{ + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK("Failed to destroy sandboxing"); + + if (sandboxing_context != NULL) + { + void *destroy_args[] = { + sandboxing_context + }; + + /* Destroy sandboxing context */ + void *ret = metacallhv_s(sandboxing_handle, "sandbox_destroy", destroy_args, sizeof(destroy_args) / sizeof(destroy_args[0])); + + metacall_value_destroy(sandboxing_context); + + /* Clear sandboxing data for future use (in case of reinitialization) */ + sandboxing_context = NULL; + sandboxing_handle = NULL; + + return ret; + } + + return metacall_value_create_int(0); +} + +void *disable_filesystem(size_t argc, void *args[], void *data) +{ + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK("Failed to disable filesystem", METACALL_BOOL); + + /* If context is not initialized, skip */ + if (sandboxing_context == NULL) + { + EXTENSION_FUNCTION_THROW(SANDBOXING_NOT_INITIALIZED_ERROR); + } + + /* Disable filesystem */ + void *fs_args[] = { + sandboxing_context, + metacall_value_create_bool(0L) + }; + + void *ret = metacallhv_s(sandboxing_handle, "sandbox_filesystems", fs_args, sizeof(fs_args) / sizeof(fs_args[0])); + + metacall_value_destroy(fs_args[1]); + + return ret; +} + +void *disable_io(size_t argc, void *args[], void *data) +{ + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK("Failed to disable io", METACALL_BOOL); + + /* If context is not initialized, skip */ + if (sandboxing_context == NULL) + { + EXTENSION_FUNCTION_THROW(SANDBOXING_NOT_INITIALIZED_ERROR); + } + + /* Disable io */ + void *io_args[] = { + sandboxing_context, + metacall_value_create_bool(0L) + }; + + void *ret = metacallhv_s(sandboxing_handle, "sandbox_io", io_args, sizeof(io_args) / sizeof(io_args[0])); + + metacall_value_destroy(io_args[1]); + + return ret; +} + +void *disable_time(size_t argc, void *args[], void *data) +{ + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK("Failed to disable time", METACALL_BOOL); + + /* If context is not initialized, skip */ + if (sandboxing_context == NULL) + { + EXTENSION_FUNCTION_THROW(SANDBOXING_NOT_INITIALIZED_ERROR); + } + + /* Disable time */ + void *time_args[] = { + sandboxing_context, + metacall_value_create_bool(0L) + }; + + void *ret = metacallhv_s(sandboxing_handle, "sandbox_time", time_args, sizeof(time_args) / sizeof(time_args[0])); + + metacall_value_destroy(time_args[1]); + + return ret; +} + +int cli_sandbox_plugin(void *loader, void *handle) +{ + /* Initialize the sandbox plugin */ + sandboxing_handle = metacall_handle("ext", "plugins/sandbox_plugin/sandbox_plugin"); + + if (sandboxing_handle != NULL) + { + /* Get CMD handle */ + void *cli_cmd_handle = cli_cmd_plugin(); + + if (cli_cmd_handle == NULL) + { + return 1; + } + + /* Register functions */ + EXTENSION_FUNCTION(METACALL_INT, sandboxing, METACALL_BOOL); + EXTENSION_FUNCTION(METACALL_INT, disable_filesystem, METACALL_BOOL); + EXTENSION_FUNCTION(METACALL_INT, disable_io, METACALL_BOOL); + EXTENSION_FUNCTION(METACALL_INT, disable_time, METACALL_BOOL); + EXTENSION_FUNCTION(METACALL_INT, sandboxing_destroy); + + /* Register sandboxing command */ + cli_cmd_plugin_register(cli_cmd_handle, "sandboxing", "METACALL_BOOL", "sandboxing_destroy"); + + /* Register disable_filesystem command */ + cli_cmd_plugin_register(cli_cmd_handle, "disable_filesystem", "METACALL_BOOL", NULL); + + /* Register disable_io command */ + cli_cmd_plugin_register(cli_cmd_handle, "disable_io", "METACALL_BOOL", NULL); + + /* Register disable_time command */ + cli_cmd_plugin_register(cli_cmd_handle, "disable_time", "METACALL_BOOL", NULL); + } + + return 0; +} diff --git a/source/cli/plugins/cli_sandbox_plugin/source/cli_sandbox_plugin_cmd.js b/source/cli/plugins/cli_sandbox_plugin/source/cli_sandbox_plugin_cmd.js deleted file mode 100644 index 9b09184df..000000000 --- a/source/cli/plugins/cli_sandbox_plugin/source/cli_sandbox_plugin_cmd.js +++ /dev/null @@ -1,4 +0,0 @@ -/* TODO */ -module.exports = { - -}; diff --git a/source/cli/plugins/cli_sandbox_plugin/source/metacall.json b/source/cli/plugins/cli_sandbox_plugin/source/metacall.json new file mode 100644 index 000000000..b6b43b028 --- /dev/null +++ b/source/cli/plugins/cli_sandbox_plugin/source/metacall.json @@ -0,0 +1,7 @@ +{ + "language_id": "ext", + "path": ".", + "scripts": [ + "cli_sandbox_plugin" + ] +} diff --git a/source/loaders/rs_loader/CMakeLists.txt b/source/loaders/rs_loader/CMakeLists.txt index ba9127f61..e6b4bbcff 100644 --- a/source/loaders/rs_loader/CMakeLists.txt +++ b/source/loaders/rs_loader/CMakeLists.txt @@ -3,6 +3,12 @@ if(NOT OPTION_BUILD_LOADERS OR NOT OPTION_BUILD_LOADERS_RS) return() endif() +# TODO: Update support for new rustc compiler, the current version 1.59.0 does not work +# error: package `cc v1.0.95` cannot be built because it requires rustc 1.63 or newer, while the currently active rustc version is 1.59.0-nightly +message(WARNING "Rust loader is out of date, needs to be updated in order to work") +set(OPTION_BUILD_LOADERS_RS OFF CACHE BOOL "" FORCE) +return() + if(OPTION_BUILD_MUSL) # TODO: Implement musl support and remove this message(WARNING "Rust Loader is not implemented yet for musl toolchain, turning off Rust Loader build") diff --git a/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp b/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp index f2c586941..06eed5fd9 100644 --- a/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp +++ b/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp @@ -24,10 +24,8 @@ #include -/* TODO: Use SCMP_ACT_KILL_PROCESS instead of SCMP_ACT_KILL for catching the signal and showing the stack trace? */ -/* TODO: We can disable bool (true/false) for string ("allow"/"kill") */ #define SANDBOX_ACTION(value) \ - metacall_value_to_bool(value) == 0L ? SCMP_ACT_KILL : SCMP_ACT_ALLOW + metacall_value_to_bool(value) == 0L ? SCMP_ACT_KILL_PROCESS : SCMP_ACT_ALLOW /* Error messages */ #define SANDBOX_INITIALIZE_ERROR "Sandbox plugin failed to initialize a context" @@ -430,7 +428,7 @@ static int sandbox_plugin_post_fork_callback(metacall_pid id, void *data) int sandbox_plugin(void *loader, void *handle) { - EXTENSION_FUNCTION(METACALL_PTR, sandbox_initialize); + EXTENSION_FUNCTION(METACALL_PTR, sandbox_initialize, METACALL_BOOL); EXTENSION_FUNCTION(METACALL_INT, sandbox_uname, METACALL_PTR, METACALL_BOOL); EXTENSION_FUNCTION(METACALL_INT, sandbox_io, METACALL_PTR, METACALL_BOOL); EXTENSION_FUNCTION(METACALL_INT, sandbox_sockets, METACALL_PTR, METACALL_BOOL); diff --git a/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp b/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp index 7d48977aa..824da2ae1 100644 --- a/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp +++ b/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp @@ -649,4 +649,4 @@ TEST_F(metacall_sandbox_plugin_test, SANDBOX_SIGNALS_DISABLE_TEST) } EXPECT_EQ((int)0, (int)metacall_destroy()); -} \ No newline at end of file +} diff --git a/tools/cli/Dockerfile b/tools/cli/Dockerfile index 722d64ab4..8eaebf293 100644 --- a/tools/cli/Dockerfile +++ b/tools/cli/Dockerfile @@ -46,7 +46,7 @@ ENV LOADER_LIBRARY_PATH=/usr/local/lib \ WORKDIR $LOADER_SCRIPT_PATH # Copy cli from builder -COPY --from=builder /usr/local/bin/metacallcli* /usr/local/bin/metacall +COPY --from=builder /usr/local/bin/metacallcli /usr/local/bin/metacallcli # Define entry point -ENTRYPOINT [ "metacall" ] +ENTRYPOINT [ "metacallcli" ] diff --git a/tools/metacall-runtime.sh b/tools/metacall-runtime.sh index 606e15496..6c1026602 100755 --- a/tools/metacall-runtime.sh +++ b/tools/metacall-runtime.sh @@ -95,7 +95,7 @@ sub_python(){ if [ "${BUILD_TYPE}" = "Debug" ]; then sub_apt_install_hold python3-dbg libpython3-dbg else - sub_apt_install_hold python3 libpython3 + sub_apt_install_hold python3 fi }