commit 4e94a2a055d5a8d4c6abe648010310963d3694e4
parent 6e8a21ed66304aee7c5f88aa9b4fa89a9b7a11f6
Author: night0721 <[email protected]>
Date: Fri, 2 Feb 2024 16:52:21 +0000
export and source command
Diffstat:
4 files changed, 82 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
@@ -20,13 +20,22 @@ $ ./rush
- Syntax highlighting on valid commands using ANSI colors
- History navigation using up and down keys with history command
- Built in commands
+- Export environment variable
+- Source commands from a file
+
+# Built in commands
+- cd
+- help
+- exit
+- history
+- export
+- source
# Todo Features
- Pipe
- stdin, stdout, stderr redirect
- background jobs
- editing using left and right arrow keys
-- export command to setenv
- tab completion
# Credits
diff --git a/commands.c b/commands.c
@@ -7,27 +7,35 @@
#include <sys/wait.h>
#include "commands.h"
+#include "constants.h"
#include "history.h"
+#include "rush.h"
// Function declarations for builtin commands
int cd(char **args);
int help(char **args);
int quit(char **args);
int history(char **args);
+int export(char **args);
+int source(char **args);
// List of builtin commands' names
char *builtin_cmds[] = {
"cd",
"help",
"exit",
- "history"
+ "history",
+ "export",
+ "source"
};
int (*builtin_func[]) (char **) = {
&cd,
&help,
&quit, // cant name it exit as it is taken
- &history
+ &history,
+ &export,
+ &source
};
// number of built in commands
@@ -80,6 +88,57 @@ int history(char **args) {
return 1;
}
+int export(char **args) {
+ args++; // skip the command
+ while (*args != NULL) {
+ char *variable = strtok(*args, "=\n");
+ char *value = strtok(NULL, "=\n");
+ if (variable != NULL && value != NULL) {
+ if (setenv(variable, value, 1) != 0) {
+ fprintf(stderr, "rush: Error setting environment variable\n");
+ return 0;
+ }
+ } else {
+ printf("rush: [arg0: %s] [arg1: %s]", args[0], args[1]);
+ printf("rush: [Variable: %s] [Value: %s]\n", variable, value);
+ fprintf(stderr, "rush: Syntax error when setting environment variable\nUse \"export VARIABLE=VALUE\"\n");
+ return 0;
+ }
+ args++;
+ }
+ return 1;
+}
+
+int source(char **args) {
+ if (args[1] == NULL) {
+ fprintf(stderr, "rush: not enough arguments\n");
+ return -1;
+ }
+
+ FILE *file = fopen(args[1], "r");
+
+ if (file == NULL) {
+ fprintf(stderr, "rush: no such file or directory '%s'\n", args[1]);
+ return -1;
+ }
+
+ char line[RL_BUFSIZE];
+ int status;
+ while (fgets(line, sizeof(line), file) != NULL) {
+ // Remove newline character if present
+ size_t len = strlen(line);
+ if (len > 0 && line[len - 1] == '\n') {
+ line[len - 1] = '\0';
+ }
+
+ char **args = argsplit(line);
+ status = execute(args);
+ }
+
+ fclose(file);
+ return status; // Indicate success
+}
+
bool is_builtin(char *command) {
for (int i = 0; i < num_builtins(); i++) {
if (strcmp(command, builtin_cmds[i]) == 0) {
diff --git a/rush.c b/rush.c
@@ -92,17 +92,18 @@ char *readline(char **paths) {
while (1) {
c = getchar(); // read a character
int buf_len = strlen(buffer);
- //printf("buflen %i\n", buf_len);
if (buf_len > 0) {
printf("\033[%ldD", strlen(buffer)); // move cursor to the beginning
printf("\033[K"); // clear line to the right of cursor
}
// check each character user has input
- // printf("%i\n", c);
switch (c) {
case EOF:
exit(EXIT_SUCCESS);
case 10: // enter/new line feed
+ if (buf_len == 0) {
+ break;
+ }
buffer[buf_len] = '\0';
// clear all characters after the command
for (int start = buf_len + 1; buffer[start] != '\0'; start++) {
@@ -124,14 +125,14 @@ char *readline(char **paths) {
char *last_command = read_command(1);
if (last_command != NULL) {
strcpy(buffer, last_command);
- buf_len = strlen(buffer);
+ buf_len = strlen(buffer) - 1;
}
break;
} else if (arrow_key == 66) { // down
char *last_command = read_command(0);
if (last_command != NULL) {
strcpy(buffer, last_command);
- buf_len = strlen(buffer);
+ buf_len = strlen(buffer) - 1;
}
break;
} else if (arrow_key == 67) { // right
diff --git a/rush.h b/rush.h
@@ -0,0 +1,6 @@
+#ifndef RUSH_H_
+#define RUSH_H_
+
+char **argsplit(char * line);
+
+#endif