aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar BanceDev 2024-09-02 22:55:24 -0400
committerGravatar BanceDev 2024-09-02 22:55:24 -0400
commitebdd4e88db2738197dd4a47903f28253cfc103e0 (patch)
treea9a5e7dd6b57dfa18fdafec0cf912042468a5f56
parentadded arrow key movement (diff)
added basic lua scripting
added exec function to run shell commands from lua
-rw-r--r--.lush/scripts/example.lua24
-rw-r--r--compile_commands.json2
-rw-r--r--install.sh38
-rw-r--r--premake5.lua14
-rw-r--r--src/lua_api.c63
-rw-r--r--src/lua_api.h27
-rw-r--r--src/lush.c42
-rw-r--r--src/lush.h13
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",
diff --git a/install.sh b/install.sh
index 68b7238..704de75 100644
--- a/install.sh
+++ b/install.sh
@@ -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
+
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 <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);
}
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 <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);