back to scratko.xyz
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorscratko <m@scratko.xyz>2024-06-23 22:35:56 +0300
committerscratko <m@scratko.xyz>2024-06-23 23:40:20 +0300
commit821b146c54330cecba3ed2cc03a0f71ad83e540f (patch)
tree866fa9808cba7703aba4ce8c81a59c9b2eae76a8
parentef4604d9c146dbab1a653f66209103b74e6feb36 (diff)
downloadshell-VI.tar.gz
shell-VI.tar.bz2
shell-VI.zip
Shell-VI releaseHEADshell-VImaster
Running processes in a single pgid. Changing foreground group to the group of running processes (if readline doesn't end with &).
-rw-r--r--Makefile4
-rw-r--r--shell.c92
-rw-r--r--shell.h65
3 files changed, 135 insertions, 26 deletions
diff --git a/Makefile b/Makefile
index 2bbac5e..9aa167e 100644
--- a/Makefile
+++ b/Makefile
@@ -3,12 +3,12 @@ OBJMODULES = $(SRCMODULES:.c=.o)
CC = gcc
CFLAGS = -Wall -g -c
-all: shell-edit
+all: shell-VI
%.o: %.с %.h
$(CC) $(CFLAGS) $< -o $@
-shell-edit: $(OBJMODULES)
+shell-VI: $(OBJMODULES)
$(CC) $(LIBS) $^ -o $@
-include deps.mk
diff --git a/shell.c b/shell.c
index 2944f00..36eb916 100644
--- a/shell.c
+++ b/shell.c
@@ -23,6 +23,22 @@ MAKE_QUEUE_PUSH(p_queue, pid, int)
enum modes { word_separation, whole_word };
+static void change_terminal_settings(struct termios *cur_terminal_settings,
+ struct termios *save_terminal_settings)
+{
+ tcgetattr(0, save_terminal_settings);
+ memcpy(cur_terminal_settings, save_terminal_settings,
+ sizeof(*save_terminal_settings));
+ cur_terminal_settings->c_lflag &= ~(ICANON | ECHO);
+ tcsetattr(0, TCSANOW, cur_terminal_settings);
+}
+
+static void restore_terminal_settings(struct termios *cur_terminal_settings,
+ struct termios *save_terminal_settings)
+{
+ tcsetattr(0, TCSANOW, save_terminal_settings);
+}
+
static void show_invitation()
{
printf("> ");
@@ -59,6 +75,7 @@ static void init_params(struct param_type *params, enum modes *current_mode)
params->last_execution_status = 0;
params->pipeline = 0;
params->new_readline = 1;
+ params->general_pgid = -1;
*current_mode = word_separation;
}
@@ -90,6 +107,17 @@ static void reset_params(struct param_type *params,
init_params(params, current_mode);
}
+static void prepare_for_next_command_on_line(struct param_type *params,
+ struct w_queue *word_chain,
+ struct c_queue *cmdlines,
+ struct dynamic_array *tmp_word)
+{
+ w_queue_clear(word_chain);
+ c_queue_clear(cmdlines);
+ dynarr_reset_array(tmp_word);
+ clear_filename(params);
+}
+
static void add_letter(int ch, struct dynamic_array *tmp_word,
struct param_type *params)
{
@@ -180,8 +208,11 @@ static void postprocessing(struct w_queue *word_chain, struct c_queue *cmdlines,
{
clean_up_memory(word_chain, cmdlines, params);
close_files(input_fd, output_fd);
- if(params->tokens != '&')
+ if(params->tokens != '&') {
wait_for_process_to_complete(pid_store);
+ signal(SIGTTOU, SIG_IGN);
+ tcsetpgrp(0, getpid());
+ }
p_queue_clear(pid_store);
}
@@ -218,6 +249,15 @@ int is_stream_redirection_set(const struct param_type *params)
params->streams.output_stream_to_append;
}
+static void identify_general_pgid(struct param_type *params, int pid)
+{
+ if(params->general_pgid == -1)
+ params->general_pgid = pid;
+ if(params->tokens != '&')
+ /* foreground group */
+ tcsetpgrp(0, params->general_pgid);
+}
+
static void make_pipeline(struct w_queue *word_chain, struct c_queue *cmdlines,
struct param_type *params,
int input_fd, int output_fd)
@@ -233,12 +273,19 @@ static void make_pipeline(struct w_queue *word_chain, struct c_queue *cmdlines,
set_signal_disposition(params);
pid = fork();
+ /* parent process */
+ if(pid)
+ identify_general_pgid(params, pid);
+
if(pid == 0) {
close(fd[0]);
dup2(fd[1], 1);
close(fd[1]);
if(is_stream_redirection_set(params))
change_streams(input_fd, output_fd, 1, 1);
+ /* change pgid */
+ setpgid(getpid(), params->general_pgid == -1 ?
+ getpid() : params->general_pgid);
execvp(cmdline[0], cmdline);
perror(cmdline[0]);
exit(1);
@@ -270,6 +317,10 @@ static void make_pipeline(struct w_queue *word_chain, struct c_queue *cmdlines,
if(c_queue_is_empty(cmdlines))
if(is_stream_redirection_set(params))
change_streams(input_fd, output_fd, 1, 0);
+
+ /* change pgid */
+ setpgid(getpid(), params->general_pgid);
+
execvp(cmdline[0], cmdline);
perror(cmdline[0]);
exit(1);
@@ -359,10 +410,17 @@ static void run_external_program(struct w_queue *word_chain,
perror("fork error");
exit(1);
}
+ /* parent process */
+ if(pid)
+ identify_general_pgid(params, pid);
+
/* child process */
if(pid == 0) {
if(is_stream_redirection_set(params))
change_streams(input_fd, output_fd, 0, 0);
+ /* change pgid */
+ setpgid(getpid(), params->general_pgid == -1 ?
+ getpid() : params->general_pgid);
execvp(cmdline[0], cmdline);
params->last_execution_status = 1;
perror(cmdline[0]);
@@ -440,10 +498,13 @@ static void echo_characters(int ch)
static void generate_readline(struct readline_type *readline)
{
+ struct termios cur_terminal_settings, save_terminal_settings;
enum keys found_key = none;
int match_result;
char ch;
+ change_terminal_settings(&cur_terminal_settings, &save_terminal_settings);
+
while((ch = getchar()) && !readline_termination_condition(ch, readline)) {
if(ch == tab) {
if(suggestions_for_filename(readline)) {
@@ -494,6 +555,7 @@ static void generate_readline(struct readline_type *readline)
/* print '\n' to end of readline */
if(ch == new_line)
echo_characters(ch);
+ restore_terminal_settings(&cur_terminal_settings, &save_terminal_settings);
}
static void command_processing(struct param_type *params,
@@ -546,13 +608,15 @@ static void command_processing(struct param_type *params,
clean:
error_identification(params);
last_token = params->tokens;
- reset_params(params, current_mode, word_chain, cmdlines, tmp_word,
- readline);
if(last_token == '&' || last_token == 0 || ch == new_line) {
+ reset_params(params, current_mode, word_chain, cmdlines, tmp_word,
+ readline);
show_invitation();
generate_readline(readline);
- }
+ } else
+ prepare_for_next_command_on_line(params, word_chain, cmdlines,
+ tmp_word);
}
static void word_separation_processing(int ch, struct param_type *params,
@@ -651,35 +715,17 @@ static void whole_word_processing(int ch, struct param_type *params,
add_letter(ch, tmp_word, params);
}
-static void change_terminal_settings(struct termios *cur_terminal_settings,
- struct termios *save_terminal_settings)
-{
- tcgetattr(0, save_terminal_settings);
- memcpy(cur_terminal_settings, save_terminal_settings,
- sizeof(*save_terminal_settings));
- cur_terminal_settings->c_lflag &= ~(ICANON | ECHO);
- tcsetattr(0, TCSANOW, cur_terminal_settings);
-}
-
-static void restore_terminal_settings(struct termios *cur_terminal_settings,
- struct termios *save_terminal_settings)
-{
- tcsetattr(0, TCSANOW, save_terminal_settings);
-}
-
int main()
{
char ch;
int i;
struct param_type params;
- struct termios cur_terminal_settings, save_terminal_settings;
struct w_queue word_chain;
struct c_queue cmdlines;
struct dynamic_array tmp_word;
struct readline_type readline;
enum modes current_mode = word_separation;
- change_terminal_settings(&cur_terminal_settings, &save_terminal_settings);
w_queue_init(&word_chain);
c_queue_init(&cmdlines);
dynarr_create_array(&tmp_word);
@@ -710,8 +756,6 @@ int main()
&tmp_word);
i = params.new_readline ? 0 : i + 1;
}
-
- restore_terminal_settings(&cur_terminal_settings, &save_terminal_settings);
putchar(new_line);
dynarr_clear(&tmp_word);
readline_clear(&readline);
diff --git a/shell.h b/shell.h
new file mode 100644
index 0000000..b3dd93d
--- /dev/null
+++ b/shell.h
@@ -0,0 +1,65 @@
+#ifndef SHELL_H_SENTRY
+#define SHELL_H_SENTRY
+
+#include "dynamic_array.h"
+#include "queue.h"
+
+enum {
+ /* CTRL-D */
+ end_of_file = 4,
+ new_line = 10,
+ whitespace = ' ',
+ tab = 9,
+ esc = 27,
+ backslash = '\\',
+ double_quotes = '"'
+};
+
+/* two-letter tokens */
+enum {
+ append = '>' + 1,
+ and = '&' + 1,
+ or = '|' + 1
+};
+
+/* error codes */
+enum {
+ err_filename_expected = 1,
+ err_redirect_stream_again = 2,
+ err_redirect_stream_in_pipeline = 3,
+ err_bg_process = 4,
+ err_empty_command = 5,
+ err_extra_chars_after_filename = 6,
+ err_odd_double_quotes = 7
+};
+
+/* storing file names to redirect standard input/output streams */
+struct io_type {
+ char *input_stream;
+ char *output_stream;
+ char *output_stream_to_append;
+};
+
+struct param_type {
+ int is_word;
+ int escape_sequences;
+ unsigned int double_quotes_counter;
+ char stored_symbol;
+ int empty_word_flag;
+ int tokens;
+ int wrong_command;
+ struct io_type streams;
+ int last_execution_status;
+ int pipeline;
+ int new_readline;
+ int general_pgid;
+};
+
+int filename_waiting(struct param_type *params);
+void add_filename(struct dynamic_array *tmp_word, struct param_type *params);
+void add_word(struct w_queue *word_chain, struct dynamic_array *tmp_word,
+ struct param_type *params);
+int is_stream_redirection_set(const struct param_type *params);
+char** create_cmdline(const struct w_queue *word_chain, int word_counter);
+
+#endif