back to scratko.xyz
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorscratko <m@scratko.xyz>2024-05-25 21:36:07 +0300
committerscratko <m@scratko.xyz>2024-05-25 22:05:47 +0300
commitfb322edd72bebddee1a9828baec2f8bc83666ddf (patch)
treefab49e1e88ab1b3b20a45aba354b85b5fdafeff4
parentc1e5cffb43977f5a2f8d9623e40c01dab6d80c46 (diff)
downloadshell-II.tar.gz
shell-II.tar.bz2
shell-II.zip
Shell-II releaseshell-II
Implementation of launching external programs via fork(). Running cd as a change to the current process directory (chdir). Ability to change to user's home directory (cd without arguments).
-rw-r--r--Makefile4
-rw-r--r--queue.c20
-rw-r--r--queue.h4
-rw-r--r--shell.c86
4 files changed, 109 insertions, 5 deletions
diff --git a/Makefile b/Makefile
index 671c740..0fc988b 100644
--- a/Makefile
+++ b/Makefile
@@ -3,12 +3,12 @@ OBJMODULES = $(SRCMODULES:.c=.o)
CC = gcc
CFLAGS = -Wall -g -c
-all: shell1
+all: shell-II
%.o: %.с %.h
$(CC) $(CFLAGS) $< -o $@
-shell1: $(OBJMODULES)
+shell-II: $(OBJMODULES)
$(CC) $(LIBS) $^ -o $@
-include deps.mk
diff --git a/queue.c b/queue.c
index 861f1e5..eed3cf8 100644
--- a/queue.c
+++ b/queue.c
@@ -33,6 +33,7 @@ void queue_clear(struct queue *q)
q->last = NULL;
}
+#if 0
void queue_processing(const struct queue *q, void (*callback)(char*))
{
struct word_item *tmp;
@@ -42,3 +43,22 @@ void queue_processing(const struct queue *q, void (*callback)(char*))
tmp = tmp->next;
}
}
+#endif
+
+int queue_get_word_count(const struct queue *q)
+{
+ struct word_item *tmp;
+ int counter;
+ for(counter = 0, tmp = q->first; tmp; tmp = tmp->next, ++counter)
+ {}
+ return counter;
+}
+
+void queue_copy_words_to_args(const struct queue *q, char **cmdline)
+{
+ struct word_item *tmp;
+ int mas_idx;
+ for(tmp = q->first, mas_idx = 0; tmp; tmp = tmp->next, ++mas_idx)
+ cmdline[mas_idx] = tmp->word;
+ cmdline[mas_idx] = NULL;
+}
diff --git a/queue.h b/queue.h
index db8ac54..fedcd0b 100644
--- a/queue.h
+++ b/queue.h
@@ -14,6 +14,10 @@ struct queue {
void queue_init(struct queue *q);
void queue_push(struct queue *q, char *word);
void queue_clear(struct queue *q);
+#if 0
void queue_processing(const struct queue *q, void (*callback)(char*));
+#endif
+int queue_get_word_count(const struct queue *q);
+void queue_copy_words_to_args(const struct queue *q, char **cmdline);
#endif
diff --git a/shell.c b/shell.c
index f635c12..a1b5b29 100644
--- a/shell.c
+++ b/shell.c
@@ -2,6 +2,9 @@
#include "dynamic_array.h"
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/wait.h>
enum modes { word_separation, whole_word };
enum {
@@ -57,7 +60,8 @@ static int is_double_quotes_pair(struct param_type params)
static int check_separation(int ch, struct param_type params)
{
- return (ch == whitespace || ch == tab) && params.is_word && !params.escape_sequences;
+ return (ch == whitespace || ch == tab) && params.is_word &&
+ !params.escape_sequences;
}
static int ignore_spaces(int ch, struct param_type params)
@@ -87,6 +91,7 @@ static void add_word(struct queue *word_chain,
params->is_word = 0;
}
+#if 0
static void print_word(char *word)
{
putchar('[');
@@ -101,6 +106,77 @@ static void print_line(const struct queue *word_chain)
{
queue_processing(word_chain, print_word);
}
+#endif
+
+static char** create_cmdline(const struct queue *word_chain,
+ int word_counter)
+{
+ char **cmdline = malloc((word_counter + 1) * sizeof(char*));
+ queue_copy_words_to_args(word_chain, cmdline);
+ return cmdline;
+}
+
+static int check_cd(const char *arg)
+{
+ return !strcmp(arg, "cd");
+}
+
+static void change_directory(char **cmdline)
+{
+ int result;
+ char *first_arg = cmdline[1];
+ char *path = NULL;
+ /* change to user home directory */
+ if(first_arg == NULL) {
+ path = getenv("HOME");
+ if(!path) {
+ perror("I don't know where's your home...");
+ return;
+ }
+ } else {
+ if(cmdline[2]) {
+ perror("cd: too many arguments");
+ return;
+ }
+ path = first_arg;
+ }
+ result = chdir(path);
+ if(result == -1)
+ perror(path);
+}
+
+static void clean_up_memory(struct queue *word_chain, char **cmdline)
+{
+ queue_clear(word_chain);
+ free(cmdline);
+}
+
+static void run_external_program(struct queue *word_chain)
+{
+ int pid, result;
+ char **cmdline = create_cmdline(word_chain,
+ queue_get_word_count(word_chain));
+ if(check_cd(cmdline[0])) {
+ change_directory(cmdline);
+ clean_up_memory(word_chain, cmdline);
+ }
+ else {
+ pid = fork();
+ if(pid == -1) {
+ perror("fork error");
+ exit(1);
+ }
+ /* child process */
+ if(pid == 0) {
+ execvp(cmdline[0], cmdline);
+ perror(cmdline[0]);
+ exit(1);
+ }
+ /* parent process */
+ wait(&result);
+ clean_up_memory(word_chain, cmdline);
+ }
+}
static void new_line_processing(struct param_type *params,
enum modes *current_mode,
@@ -119,14 +195,18 @@ static void new_line_processing(struct param_type *params,
dynarr_push_back(tmp_word, '\0');
add_word(word_chain, tmp_word, params);
}
+ run_external_program(word_chain);
+#if 0
print_line(word_chain);
+#endif
prepare_new_line(params, current_mode, word_chain, tmp_word);
show_invitation();
}
static int is_empty_word(int ch, struct param_type params)
{
- return (ch == whitespace || ch == tab) && !params.is_word && params.empty_word_flag;
+ return (ch == whitespace || ch == tab) && !params.is_word &&
+ params.empty_word_flag;
}
static void word_separation_processing(int ch, struct param_type *params,
@@ -198,6 +278,7 @@ static void whole_word_processing(int ch, struct param_type *params,
if(escape_double_quotes_or_backslash(ch, *params)) {
dynarr_push_back(tmp_word, ch);
params->escape_sequences = 0;
+ params->is_word = 1;
return;
}
if(start_escape_sequence(ch, *params)) {
@@ -235,7 +316,6 @@ int main()
&tmp_word);
}
putchar(new_line);
- queue_clear(&word_chain);
dynarr_clear(&tmp_word);
return 0;
}