aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar BanceDev 2024-09-23 12:08:03 -0400
committerGravatar BanceDev 2024-09-23 12:08:03 -0400
commite85cb6bc1028fc9aa53ce8ecdaa45b11f416fa89 (patch)
tree49bce9b54d575120d6f34beeb4667b8f1bf0447c /src
parentMerge pull request #2 from BanceDev/chaining-operators (diff)
implemented background process operator
Diffstat (limited to 'src')
-rw-r--r--src/builtins.c144
-rw-r--r--src/history.c2
-rw-r--r--src/history.h24
-rw-r--r--src/lua_api.c1
-rw-r--r--src/lush.c210
-rw-r--r--src/lush.h11
6 files changed, 238 insertions, 154 deletions
diff --git a/src/builtins.c b/src/builtins.c
new file mode 100644
index 0000000..5b032c1
--- /dev/null
+++ b/src/builtins.c
@@ -0,0 +1,144 @@
+/*
+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 "help.h"
+#include "lua.h"
+#include "lua_api.h"
+#include "lush.h"
+#include <asm-generic/ioctls.h>
+#include <bits/time.h>
+#include <dirent.h>
+#include <linux/limits.h>
+#include <locale.h>
+#include <pwd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <termios.h>
+#include <time.h>
+#include <unistd.h>
+
+char *builtin_strs[] = {"cd", "help", "exit", "time"};
+char *builtin_usage[] = {"[dirname]", "", "", "[pipeline]"};
+
+int (*builtin_func[])(lua_State *, char ***) = {
+ &lush_cd, &lush_help, &lush_exit, &lush_time, &lush_lua};
+
+int lush_num_builtins() { return sizeof(builtin_strs) / sizeof(char *); }
+
+int lush_cd(lua_State *L, char ***args) {
+ uid_t uid = getuid();
+ struct passwd *pw = getpwuid(uid);
+ if (!pw) {
+ perror("retrieve home dir");
+ return 0;
+ }
+ if (args[0][1] == NULL) {
+ if (chdir(pw->pw_dir) != 0) {
+ perror("lush: cd");
+ }
+ } else {
+ char path[PATH_MAX];
+ char extended_path[PATH_MAX];
+ char *tilda = strchr(args[0][1], '~');
+ // first check if they want to go to old dir
+ if (strcmp("-", args[0][1]) == 0) {
+ strcpy(path, getenv("OLDPWD"));
+ } else if (tilda) {
+ strcpy(path, pw->pw_dir);
+ strcat(path, tilda + 1);
+ } else {
+ strcpy(path, args[0][1]);
+ }
+
+ char *exp_path = realpath(path, extended_path);
+ if (!exp_path) {
+ perror("realpath");
+ return 1;
+ }
+
+ char *cwd = getcwd(NULL, 0);
+ setenv("OLDPWD", cwd, 1);
+ free(cwd);
+
+ if (chdir(exp_path) != 0) {
+ perror("lush: cd");
+ }
+ }
+
+ return 1;
+}
+
+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);
+#endif
+ printf("These shell commands are defined internally. Type 'help' at any "
+ "time to reference this list.\n");
+ printf("Available commands: \n");
+ for (int i = 0; i < lush_num_builtins(); i++) {
+ printf("- %s %s\n", builtin_strs[i], builtin_usage[i]);
+ }
+ return 1;
+}
+
+int lush_exit(lua_State *L, char ***args) { exit(0); }
+
+int lush_time(lua_State *L, char ***args) {
+ // advance past time command
+ args[0]++;
+
+ // count commands
+ int i = 0;
+ while (args[i++]) {
+ ;
+ }
+
+ // get time
+ struct timespec start, end;
+ double elapsed_time;
+
+ clock_gettime(CLOCK_MONOTONIC, &start);
+ int rc = lush_run(L, args, i);
+ clock_gettime(CLOCK_MONOTONIC, &end);
+
+ elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0 +
+ (end.tv_nsec - start.tv_nsec) / 1e6;
+ printf("Time: %.3f milliseconds\n", elapsed_time);
+
+ // return pointer back to "time" for free()
+ args[0]--;
+ return rc;
+}
+
+int lush_lua(lua_State *L, char ***args) {
+ // run the lua file given
+ const char *script = args[0][0];
+ // move args forward to any command line args
+ args[0]++;
+
+ lua_load_script(L, script, args[0]);
+
+ // return pointer back to lua file
+ args[0]--;
+ return 1;
+}
diff --git a/src/history.c b/src/history.c
index 511f12a..93d6983 100644
--- a/src/history.c
+++ b/src/history.c
@@ -15,7 +15,7 @@ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include "history.h"
+#include "lush.h"
#include <linux/limits.h>
#include <pwd.h>
#include <stdbool.h>
diff --git a/src/history.h b/src/history.h
deleted file mode 100644
index 9507126..0000000
--- a/src/history.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-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 HISTORY_H
-#define HISTORY_H
-
-char *lush_get_past_command(int pos);
-void lush_push_history(const char* line);
-
-#endif
diff --git a/src/lua_api.c b/src/lua_api.c
index d40489c..05742cc 100644
--- a/src/lua_api.c
+++ b/src/lua_api.c
@@ -16,7 +16,6 @@ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "lua_api.h"
-#include "history.h"
#include "lush.h"
#include <dirent.h>
#include <lauxlib.h>
diff --git a/src/lush.c b/src/lush.c
index 1cdb50d..3318807 100644
--- a/src/lush.c
+++ b/src/lush.c
@@ -17,8 +17,6 @@ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#include "lush.h"
#include "hashmap.h"
-#include "help.h"
-#include "history.h"
#include "lauxlib.h"
#include "lua.h"
#include "lua_api.h"
@@ -73,114 +71,6 @@ void lush_add_alias(const char *alias, const char *command) {
char *lush_get_alias(char *alias) { return hm_get(aliases, alias); }
-// -- builtin functions --
-char *builtin_strs[] = {"cd", "help", "exit", "time"};
-char *builtin_usage[] = {"[dirname]", "", "", "[pipeline]"};
-
-int (*builtin_func[])(lua_State *, char ***) = {
- &lush_cd, &lush_help, &lush_exit, &lush_time, &lush_lua};
-
-int lush_num_builtins() { return sizeof(builtin_strs) / sizeof(char *); }
-
-int lush_cd(lua_State *L, char ***args) {
- uid_t uid = getuid();
- struct passwd *pw = getpwuid(uid);
- if (!pw) {
- perror("retrieve home dir");
- return 0;
- }
- if (args[0][1] == NULL) {
- if (chdir(pw->pw_dir) != 0) {
- perror("lush: cd");
- }
- } else {
- char path[PATH_MAX];
- char extended_path[PATH_MAX];
- char *tilda = strchr(args[0][1], '~');
- // first check if they want to go to old dir
- if (strcmp("-", args[0][1]) == 0) {
- strcpy(path, getenv("OLDPWD"));
- } else if (tilda) {
- strcpy(path, pw->pw_dir);
- strcat(path, tilda + 1);
- } else {
- strcpy(path, args[0][1]);
- }
-
- char *exp_path = realpath(path, extended_path);
- if (!exp_path) {
- perror("realpath");
- return 1;
- }
-
- char *cwd = getcwd(NULL, 0);
- setenv("OLDPWD", cwd, 1);
- free(cwd);
-
- if (chdir(exp_path) != 0) {
- perror("lush: cd");
- }
- }
-
- return 1;
-}
-
-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);
-#endif
- printf("These shell commands are defined internally. Type 'help' at any "
- "time to reference this list.\n");
- printf("Available commands: \n");
- for (int i = 0; i < lush_num_builtins(); i++) {
- printf("- %s %s\n", builtin_strs[i], builtin_usage[i]);
- }
- return 1;
-}
-
-int lush_exit(lua_State *L, char ***args) { exit(0); }
-
-int lush_time(lua_State *L, char ***args) {
- // advance past time command
- args[0]++;
-
- // count commands
- int i = 0;
- while (args[i++]) {
- ;
- }
-
- // get time
- struct timespec start, end;
- double elapsed_time;
-
- clock_gettime(CLOCK_MONOTONIC, &start);
- int rc = lush_run(L, args, i);
- clock_gettime(CLOCK_MONOTONIC, &end);
-
- elapsed_time = (end.tv_sec - start.tv_sec) * 1000.0 +
- (end.tv_nsec - start.tv_nsec) / 1e6;
- printf("Time: %.3f milliseconds\n", elapsed_time);
-
- // return pointer back to "time" for free()
- args[0]--;
- return rc;
-}
-
-int lush_lua(lua_State *L, char ***args) {
- // run the lua file given
- const char *script = args[0][0];
- // move args forward to any command line args
- args[0]++;
-
- lua_load_script(L, script, args[0]);
-
- // return pointer back to lua file
- args[0]--;
- return 1;
-}
-
// -- shell utility --
static void set_raw_mode(struct termios *orig_termios) {
@@ -949,8 +839,7 @@ char *lush_resolve_aliases(char *line) {
}
static int is_operator(const char *str) {
- const char *operators[] = {"||", "&&", "&", ";", ">>", ">", "<",
- "\\", "(", ")", "{", "}", "!", "|"};
+ const char *operators[] = {"||", "&&", ">>", ">", "<", "&", ";", "|"};
int num_operators = sizeof(operators) / sizeof(operators[0]);
for (int i = 0; i < num_operators; i++) {
if (strncmp(str, operators[i], strlen(operators[i])) == 0) {
@@ -960,25 +849,55 @@ static int is_operator(const char *str) {
case 1:
return OP_AND;
case 2:
- return OP_BACKGROUND;
+ return OP_APPEND_OUT;
case 3:
- return OP_SEMICOLON;
+ return OP_REDIRECT_OUT;
case 4:
- return OP_APPEND_OUT;
+ return OP_REDIRECT_IN;
case 5:
- return OP_REDIRECT_OUT;
+ return OP_BACKGROUND;
case 6:
- return OP_REDIRECT_IN;
- case 13:
+ return OP_SEMICOLON;
+ case 7:
return OP_PIPE;
default:
- return OP_OTHER; // Parentheses, braces, etc.
+ return 0;
}
}
}
return 0; // Not an operator
}
+static int operator_length(const char *str) {
+ const char *operators[] = {"||", "&&", ">>", ">", "<", "&", ";", "|"};
+ int num_operators = sizeof(operators) / sizeof(operators[0]);
+ for (int i = 0; i < num_operators; i++) {
+ if (strncmp(str, operators[i], strlen(operators[i])) == 0) {
+ switch (i) {
+ case 0:
+ return 2;
+ case 1:
+ return 2;
+ case 2:
+ return 2;
+ case 3:
+ return 1;
+ case 4:
+ return 1;
+ case 5:
+ return 1;
+ case 6:
+ return 1;
+ case 7:
+ return 1;
+ default:
+ return 0;
+ }
+ }
+ }
+ return 0;
+}
+
static char *trim_whitespace(char *str) {
char *end;
@@ -1015,7 +934,7 @@ char **lush_split_commands(char *line) {
start++;
// Check for operators
- int op_len = is_operator(start);
+ int op_len = operator_length(start);
if (op_len > 0) {
// Allocate memory for operator command
char *operator_cmd = calloc(op_len + 1, sizeof(char));
@@ -1147,6 +1066,22 @@ static int run_command(lua_State *L, char ***commands) {
return lush_execute_command(commands[0], STDIN_FILENO, STDOUT_FILENO);
}
+static int run_command_background(lua_State *L, char ***commands) {
+ pid_t pid = fork();
+
+ if (pid < 0) {
+ perror("fork");
+ return -1;
+ } else if (pid == 0) {
+ execvp(commands[0][0], commands[0]);
+ perror("execvp background");
+ exit(EXIT_FAILURE);
+ } else {
+ printf("Process %d running in background\n", pid);
+ return 0;
+ }
+}
+
int lush_execute_chain(lua_State *L, char ***commands, int num_commands) {
if (commands[0][0][0] == '\0') {
return 1;
@@ -1190,6 +1125,13 @@ int lush_execute_chain(lua_State *L, char ***commands, int num_commands) {
commands += 2;
continue;
}
+ // Handle '&' operator for background execution
+ if (op_type == OP_BACKGROUND) {
+
+ run_command_background(L, commands);
+ commands += 2;
+ continue;
+ }
}
if (!is_operator(commands[0][0])) {
@@ -1198,7 +1140,7 @@ int lush_execute_chain(lua_State *L, char ***commands, int num_commands) {
}
}
- return last_result;
+ return 1;
}
int lush_execute_pipeline(char ***commands, int num_commands) {
@@ -1273,6 +1215,7 @@ int lush_execute_command(char **args, int input_fd, int output_fd) {
// execute the command
if (execvp(args[0], args) == -1) {
perror("execvp");
+ printf("%s\n", args[0]);
exit(EXIT_FAILURE);
}
} else if (pid < 0) {
@@ -1288,9 +1231,8 @@ int lush_execute_command(char **args, int input_fd, int output_fd) {
if (WIFEXITED(status)) {
return WEXITSTATUS(status);
- } else {
- return -1;
}
+ return -1;
}
int lush_run(lua_State *L, char ***commands, int num_commands) {
@@ -1302,6 +1244,12 @@ int lush_run(lua_State *L, char ***commands, int num_commands) {
return lush_execute_chain(L, commands, num_commands);
}
+static void background_handler(int sig) {
+ // Reap all child processes
+ while (waitpid(-1, NULL, WNOHANG) > 0)
+ ;
+}
+
int main(int argc, char *argv[]) {
// check if the --version arg was passed
if (argc > 1 && strcmp(argv[1], "--version") == 0) {
@@ -1343,11 +1291,17 @@ int main(int argc, char *argv[]) {
}
// eat ^C in main
- struct sigaction sa;
- sa.sa_handler = SIG_IGN;
- sa.sa_flags = 0;
- sigemptyset(&sa.sa_mask);
- sigaction(SIGINT, &sa, NULL);
+ struct sigaction sa_int;
+ sa_int.sa_handler = SIG_IGN;
+ sa_int.sa_flags = 0;
+ sigemptyset(&sa_int.sa_mask);
+ sigaction(SIGINT, &sa_int, NULL);
+
+ struct sigaction sa_bk;
+ sa_bk.sa_handler = &background_handler;
+ sigemptyset(&sa_bk.sa_mask);
+ sa_bk.sa_flags = SA_RESTART;
+ sigaction(SIGCHLD, &sa_bk, NULL);
// set custom envars
char hostname[256];
diff --git a/src/lush.h b/src/lush.h
index 291a8dd..d6022b4 100644
--- a/src/lush.h
+++ b/src/lush.h
@@ -20,10 +20,17 @@ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#include <lua.h>
+// alias
void lush_add_alias(const char *alias, const char *command);
char *lush_get_alias(char *alias);
char *lush_resolve_aliases(char *line);
+// builtins
+extern char *builtin_strs[];
+extern char *builtin_usage[];
+
+extern int (*builtin_func[])(lua_State *, char ***);
+
int lush_cd(lua_State *L, char ***args);
int lush_help(lua_State *L, char ***args);
int lush_exit(lua_State *L, char ***args);
@@ -47,4 +54,8 @@ void lush_format_prompt(const char *prompt_format);
// format spec for the prompt
extern char *prompt_format;
+// history
+char *lush_get_past_command(int pos);
+void lush_push_history(const char* line);
+
#endif // LUSH_H