diff options
| author | 2024-09-02 22:55:24 -0400 | |
|---|---|---|
| committer | 2024-09-02 22:55:24 -0400 | |
| commit | ebdd4e88db2738197dd4a47903f28253cfc103e0 (patch) | |
| tree | a9a5e7dd6b57dfa18fdafec0cf912042468a5f56 | |
| parent | added arrow key movement (diff) | |
added basic lua scripting
added exec function to run shell commands from lua
| -rw-r--r-- | .lush/scripts/example.lua | 24 | ||||
| -rw-r--r-- | compile_commands.json | 2 | ||||
| -rw-r--r-- | install.sh | 38 | ||||
| -rw-r--r-- | premake5.lua | 14 | ||||
| -rw-r--r-- | src/lua_api.c | 63 | ||||
| -rw-r--r-- | src/lua_api.h | 27 | ||||
| -rw-r--r-- | src/lush.c | 42 | ||||
| -rw-r--r-- | src/lush.h | 13 |
8 files changed, 206 insertions, 17 deletions
diff --git a/.lush/scripts/example.lua b/.lush/scripts/example.lua new file mode 100644 index 0000000..0357276 --- /dev/null +++ b/.lush/scripts/example.lua @@ -0,0 +1,24 @@ +--[[ +Copyright (c) 2024, Lance Borden +All rights reserved. + +This software is licensed under the BSD 3-Clause License. +You may obtain a copy of the license at: +https://opensource.org/licenses/BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted under the conditions stated in the BSD 3-Clause +License. + +THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTIES, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +]] + +-- the Lua file itself is the executable unit so all code is run line by line + +-- the print function can be used to write to the console +print("Welcome to Lunar Shell scripting") + +-- exec can be used to run any command line prompt +exec('echo "hello world"\n') diff --git a/compile_commands.json b/compile_commands.json index 6578a36..5ba9a1e 100644 --- a/compile_commands.json +++ b/compile_commands.json @@ -2,7 +2,9 @@ { "arguments": [ "/usr/bin/cc", + "-DLUSH_VERSION=\"0.0.1\"", "-DDEBUG", + "-I/usr/include/lua5.4", "-g", "-c", "-o", @@ -1,5 +1,42 @@ #!/bin/sh +# Function to install packages using apt (Debian/Ubuntu) +install_with_apt() { + sudo apt-get update + sudo apt-get install -y lua5.4 liblua5.4-dev +} + +# Function to install packages using yum (Red Hat/CentOS) +install_with_yum() { + sudo yum install -y epel-release + sudo yum install -y lua lua-devel +} + +# New package manager used in Fedora +install_with_dnf() { + sudo dnf install -y lua lua-devel +} + +# Function to install packages using pacman (Arch Linux) +install_with_pacman() { + sudo pacman -Sy --noconfirm lua +} + +if [ -f /etc/arch-release ]; then + install_with_pacman +elif [ -f /etc/debian_version ]; then + install_with_apt +elif [ -f /etc/redhat-release ] || [ -f /etc/centos-release ]; then + if command -v dnf >/dev/null 2>&1; then + install_with_dnf + else + install_with_yum + fi +else + echo "Your linux distro is not supported currently." + echo "You need to manually install those packages: exiftool, jq, glfw" +fi + PREMAKE_VERSION="5.0.0-beta2" OS="linux" @@ -14,6 +51,7 @@ rm premake.tar.gz premake5 gmake make +cp -rf ./.lush ~/ # Install the new shell binary to a temporary location sudo cp ./bin/Debug/lush/lush /usr/bin/lush.new diff --git a/premake5.lua b/premake5.lua index 3818236..34d98dd 100644 --- a/premake5.lua +++ b/premake5.lua @@ -7,6 +7,20 @@ kind("ConsoleApp") language("C") targetdir("bin/%{cfg.buildcfg}/lush") +local lua_inc_path = "/usr/include" +local lua_lib_path = "/usr/lib" + +if os.findlib("lua5.4") then + lua_inc_path = "/usr/include/lua5.4" + lua_lib_path = "/usr/lib/5.4" + links({ "lua5.4" }) +else + links({ "lua" }) +end + +includedirs({ lua_inc_path }) +libdirs({ lua_lib_path }) + files({ "src/**.h", "src/**.c", diff --git a/src/lua_api.c b/src/lua_api.c new file mode 100644 index 0000000..becd2b7 --- /dev/null +++ b/src/lua_api.c @@ -0,0 +1,63 @@ +/* +Copyright (c) 2024, Lance Borden +All rights reserved. + +This software is licensed under the BSD 3-Clause License. +You may obtain a copy of the license at: +https://opensource.org/licenses/BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted under the conditions stated in the BSD 3-Clause +License. + +THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTIES, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +*/ + +#include "lua_api.h" +#include "lush.h" +#include <lauxlib.h> +#include <lua.h> +#include <lualib.h> +#include <stdio.h> +#include <stdlib.h> + +// -- script execution -- +void lua_load_script(lua_State *L, const char *script) { + if (luaL_dofile(L, script) != LUA_OK) { + printf("[C] Error reading script\n"); + luaL_error(L, "Error: %s\n", lua_tostring(L, -1)); + } +} + +// -- C funtions -- +static void execute_command(lua_State *L, const char *line) { + int status = 0; + char **commands = lush_split_pipes((char *)line); + char ***args = lush_split_args(commands, &status); + if (status == -1) { + fprintf(stderr, "lush: Expected end of quoted string\n"); + } else if (lush_run(L, args, status) == 0) { + exit(1); + } + + for (int i = 0; args[i]; i++) { + free(args[i]); + } + free(args); + free(commands); +} + +// -- Lua wrappers -- +static int l_execute_command(lua_State *L) { + const char *command = luaL_checkstring(L, 1); + execute_command(L, command); + return 0; +} + +// -- register Lua functions -- + +void lua_register_api(lua_State *L) { + lua_register(L, "exec", l_execute_command); +} diff --git a/src/lua_api.h b/src/lua_api.h new file mode 100644 index 0000000..915b4ab --- /dev/null +++ b/src/lua_api.h @@ -0,0 +1,27 @@ +/* +Copyright (c) 2024, Lance Borden +All rights reserved. + +This software is licensed under the BSD 3-Clause License. +You may obtain a copy of the license at: +https://opensource.org/licenses/BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted under the conditions stated in the BSD 3-Clause +License. + +THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTIES, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +*/ + +#ifndef LUA_API_H +#define LUA_API_H + +#include <lua.h> + +void lua_load_script(lua_State *L, const char *script); +void lua_register_api(lua_State *L); + +#endif + @@ -17,6 +17,10 @@ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. #include "lush.h" #include "help.h" +#include "lauxlib.h" +#include "lua.h" +#include "lua_api.h" +#include "lualib.h" #include <bits/time.h> #include <linux/limits.h> #include <pwd.h> @@ -34,14 +38,14 @@ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. #define BUFFER_SIZE 1024 // -- builtin functions -- -char *builtin_strs[] = {"cd", "help", "exit", "time"}; +char *builtin_strs[] = {"cd", "help", "exit", "time", "lush"}; -int (*builtin_func[])(char ***) = {&lush_cd, &lush_help, &lush_exit, - &lush_time}; +int (*builtin_func[])(lua_State *, char ***) = { + &lush_cd, &lush_help, &lush_exit, &lush_time, &lush_lush}; int lush_num_builtins() { return sizeof(builtin_strs) / sizeof(char *); } -int lush_cd(char ***args) { +int lush_cd(lua_State *L, char ***args) { uid_t uid = getuid(); struct passwd *pw = getpwuid(uid); if (!pw) { @@ -75,7 +79,7 @@ int lush_cd(char ***args) { return 1; } -int lush_help(char ***args) { +int lush_help(lua_State *L, char ***args) { printf("%s\n", lush_get_help_text()); #ifdef LUSH_VERSION printf("Lunar Shell, version %s\n", LUSH_VERSION); @@ -89,9 +93,9 @@ int lush_help(char ***args) { return 1; } -int lush_exit(char ***args) { return 0; } +int lush_exit(lua_State *L, char ***args) { return 0; } -int lush_time(char ***args) { +int lush_time(lua_State *L, char ***args) { // advance past time command args[0]++; @@ -106,7 +110,7 @@ int lush_time(char ***args) { double elapsed_time; clock_gettime(CLOCK_MONOTONIC, &start); - int rc = lush_run(args, i); + int rc = lush_run(L, args, i); clock_gettime(CLOCK_MONOTONIC, &end); elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0 + @@ -118,6 +122,16 @@ int lush_time(char ***args) { return rc; } +int lush_lush(lua_State *L, char ***args) { + // run the lua file given + args[0]++; + lua_load_script(L, *args[0]); + + // return pointer back for free() + args[0]--; + return 1; +} + // -- shell utility -- // -- static helpers for input -- @@ -423,7 +437,7 @@ void lush_execute_command(char **args, int input_fd, int output_fd) { } } -int lush_run(char ***commands, int num_commands) { +int lush_run(lua_State *L, char ***commands, int num_commands) { if (commands[0][0] == NULL) { // no command given return 1; @@ -432,7 +446,7 @@ int lush_run(char ***commands, int num_commands) { // check shell builtins for (int i = 0; i < lush_num_builtins(); i++) { if (strcmp(commands[0][0], builtin_strs[i]) == 0) { - return ((*builtin_func[i])(commands)); + return ((*builtin_func[i])(L, commands)); } } @@ -440,6 +454,9 @@ int lush_run(char ***commands, int num_commands) { } int main() { + lua_State *L = luaL_newstate(); + luaL_openlibs(L); + lua_register_api(L); // eat ^C in main struct sigaction sa; sa.sa_handler = SIG_IGN; @@ -452,16 +469,16 @@ int main() { // Prompt print_prompt(); char *line = lush_read_line(); + printf("\n"); if (line == NULL || strlen(line) == 0) { free(line); continue; } - printf("\n"); char **commands = lush_split_pipes(line); char ***args = lush_split_args(commands, &status); if (status == -1) { fprintf(stderr, "lush: Expected end of quoted string\n"); - } else if (lush_run(args, status) == 0) { + } else if (lush_run(L, args, status) == 0) { exit(1); } @@ -472,4 +489,5 @@ int main() { free(commands); free(line); } + lua_close(L); } @@ -18,14 +18,17 @@ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. #ifndef LUSH_H #define LUSH_H -int lush_cd(char ***args); -int lush_help(char ***args); -int lush_exit(char ***args); -int lush_time(char ***args); +#include <lua.h> + +int lush_cd(lua_State *L, char ***args); +int lush_help(lua_State *L, char ***args); +int lush_exit(lua_State *L, char ***args); +int lush_time(lua_State *L, char ***args); +int lush_lush(lua_State *L, char ***args); int lush_num_builtins(); -int lush_run(char ***commands, int num_commands); +int lush_run(lua_State *L, char ***commands, int num_commands); char *lush_read_line(); char **lush_split_pipes(char *line); |
