From ebdd4e88db2738197dd4a47903f28253cfc103e0 Mon Sep 17 00:00:00 2001 From: BanceDev Date: Mon, 2 Sep 2024 22:55:24 -0400 Subject: added basic lua scripting added exec function to run shell commands from lua --- src/lua_api.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lua_api.h | 27 +++++++++++++++++++++++++ src/lush.c | 42 +++++++++++++++++++++++++++------------ src/lush.h | 13 +++++++----- 4 files changed, 128 insertions(+), 17 deletions(-) create mode 100644 src/lua_api.c create mode 100644 src/lua_api.h (limited to 'src') 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 +#include +#include +#include +#include + +// -- 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 + +void lua_load_script(lua_State *L, const char *script); +void lua_register_api(lua_State *L); + +#endif + diff --git a/src/lush.c b/src/lush.c index 542aaf4..0b1c21b 100644 --- a/src/lush.c +++ b/src/lush.c @@ -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 #include #include @@ -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); } diff --git a/src/lush.h b/src/lush.h index 65846b0..ef60692 100644 --- a/src/lush.h +++ b/src/lush.h @@ -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 + +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); -- cgit v1.2.3-59-g8ed1b