diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | queue.c | 20 | ||||
-rw-r--r-- | queue.h | 4 | ||||
-rw-r--r-- | shell.c | 86 |
4 files changed, 109 insertions, 5 deletions
@@ -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 @@ -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; +} @@ -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 @@ -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; } |