From 475cbb53b2d9f49137e3d2933191775ea6f8a315 Mon Sep 17 00:00:00 2001 From: cxb23 <cxb23@tux4.cci.drexel.edu> Date: Tue, 4 Mar 2025 19:26:19 -0500 Subject: [PATCH] completed assignment 5-ShellP3 --- 5-ShellP3/.dshlib.c.swp | Bin 0 -> 16384 bytes 5-ShellP3/bats/student_test.sh | 61 +++++- 5-ShellP3/dragon.txt | 38 ++++ 5-ShellP3/dsh | Bin 0 -> 30528 bytes 5-ShellP3/dshlib.c | 389 ++++++++++++++++++++++++++++++++- 5-ShellP3/dshlib.h | 50 +++-- 5-ShellP3/questions.md | 38 ++++ 7 files changed, 550 insertions(+), 26 deletions(-) create mode 100644 5-ShellP3/.dshlib.c.swp create mode 100644 5-ShellP3/dragon.txt create mode 100755 5-ShellP3/dsh create mode 100644 5-ShellP3/questions.md diff --git a/5-ShellP3/.dshlib.c.swp b/5-ShellP3/.dshlib.c.swp new file mode 100644 index 0000000000000000000000000000000000000000..42a51fa50c4d5b89873c2b580b7a2bace6f2ac48 GIT binary patch literal 16384 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 P#N;WY73Jr`XSx^wht}P7 literal 0 HcmV?d00001 diff --git a/5-ShellP3/bats/student_test.sh b/5-ShellP3/bats/student_test.sh index 638bc34..248994b 100755 --- a/5-ShellP3/bats/student_test.sh +++ b/5-ShellP3/bats/student_test.sh @@ -4,11 +4,68 @@ # # Create your unit tests suit in this file -@test "Example: check ls runs without errors" { +@test "ls | grep .c " { run ./dsh <<EOF -ls +ls | grep ".c" EOF # Assertions [ "$status" -eq 0 ] } + +@test "ls | wc" { + run "./dsh" << EOF +ls | wc +EOF + + stripped_output=$(echo "$output" | tr -d '[:space:]\t\n\r\f\v') + + expected_output="8870dsh3>dsh3>cmdloopreturned0" + + echo "Captured stdout:" + echo "Output: $output" + echo "Exit Status: $status" + echo "${stripped_output} -> ${expected_output}" + + [ "$stripped_output" = "$expected_output" ] + + [ "$status" -eq 0 ] +} + +@test "properly exits" { + run "./dsh" << EOF +exit +EOF + + stripped_output=$(echo "$output" | tr -d '[:space:]\t\n\r\f\v') + + expected_output="dsh3>exiting...cmdloopreturned0" + + echo "Captured stdout:" + echo "Output: $output" + echo "Exit Status: $status" + echo "${stripped_output} -> ${expected_output}" + + [ "$stripped_output" = "$expected_output" ] + + [ "$status" -eq 0 ] +} + +@test "echo hello world | wc & exit" { + run "./dsh" << EOF +echo hello world | wc +exit +EOF + stripped_output=$(echo "$output" | tr -d '[:space:]\t\n\r\f\v') + + expected_output="1212dsh3>dsh3>exiting...cmdloopreturned0" + + echo "Captured stdout:" + echo "Output: $output" + echo "Exit Status: $status" + echo "${stripped_output} -> ${expected_output}" + + [ "$stripped_output" = "$expected_output" ] + + [ "$status" -eq 0] +} diff --git a/5-ShellP3/dragon.txt b/5-ShellP3/dragon.txt new file mode 100644 index 0000000..a9177fd --- /dev/null +++ b/5-ShellP3/dragon.txt @@ -0,0 +1,38 @@ + @%%%% + %%%%%% + %%%%%% + % %%%%%%% @ + %%%%%%%%%% %%%%%%% + %%%%%%% %%%%@ %%%%%%%%%%%%@ %%%%%% @%%%% + %%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%% %%%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%% %%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%@ @%%%%%%%%%%%%%%%%%% %% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@%%%%%%@ + %%%%%%%%@ %%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%% %% + %%%%%%%%%%%%% %%@%%%%%%%%%%%% %%%%%%%%%%% %%%%%%%%%%%% @% + %%%%%%%%%% %%% %%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%% + %%%%%%%%% % %%%%%%%%%%%%% %%%%%%%%%%%%@%%%%%%%%%%% +%%%%%%%%%@ % %%%%%%%%%%%%% @%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%@ %%@%%%%%%%%%%%% @%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%@ %%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% +%%%%%%%%%@ @%%%%%%%%%%%%%% %%%%%%%%%%%%@ %%%% %%%%%%%%%%%%%%%%% %%%%%%%% +%%%%%%%%%% %%%%%%%%%%%%%%%%% %%%%%%%%%%%%% %%%%%%%%%%%%%%%%%% %%%%%%%%% +%%%%%%%%%@%%@ %%%%%%%%%%%%%%%%@ %%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%% %% + %%%%%%%%%% % %%%%%%%%%%%%%%@ %%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%% %% + %%%%%%%%%%%% @ %%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% + %%%%%%%%%%%%% %% % %@ %%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% + %%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%% @%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% + @%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%% %%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%% @%%%%%%%%% + %%%%%%%%%%%%%%%%%%%% @%@% @%%%%%%%%%%%%%%%%%% %%% + %%%%%%%%%%%%%%% %%%%%%%%%% %%%%%%%%%%%%%%% % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%% + %%%%%%%%%%%%%%%%%%%%%%%%%% %%%% %%% %%%%%%%%%% %%%@ + %%%%%%%%%%%%%%%%%%% %%%%%% %% %%%%%%%%%%%%%@ + %%%%%%%@ diff --git a/5-ShellP3/dsh b/5-ShellP3/dsh new file mode 100755 index 0000000000000000000000000000000000000000..97964bae366d2d39c9679ddcb6f5bc27f7b68a81 GIT binary patch literal 30528 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 literal 0 HcmV?d00001 diff --git a/5-ShellP3/dshlib.c b/5-ShellP3/dshlib.c index 0e6738e..4db5396 100644 --- a/5-ShellP3/dshlib.c +++ b/5-ShellP3/dshlib.c @@ -6,9 +6,356 @@ #include <unistd.h> #include <fcntl.h> #include <sys/wait.h> - +#include <errno.h> #include "dshlib.h" +int numInstanceOf(char *str, const char c) { + int count = 0; + while (*str != '\0') { + if (*str == c) count++; + str++; + } + return count; +} + +void print_dragon(){ + // TODO implement + FILE *dragon = fopen("dragon.txt", "r"); + if (dragon == NULL) { + return; + } + + char *s = NULL; + size_t nbyte; + ssize_t nchar; + + while (1) { + nchar = getline(&s, &nbyte, dragon); + if (nchar == -1) { // end of file reached + break; + } + if (nchar == 0) { + continue; + } + if (s == NULL) { // out of memory + exit(1); + } + if (s[nchar - 1] == '\n') { + s[nchar - 1] = '\0'; // remove newline + nchar--; // newline removed + } + + printf("%s\n", s); + } + free(s); + fclose(dragon); +} + +char* trim_whitespace(char *str) { + int start = 0; + while (isspace((unsigned char)str[start])) { + start++; + } + + int end = strlen(str) - 1; + while (end > start && isspace((unsigned char)str[end])) { + end--; + } + + int j = 0; + for (int i = start; i <= end; i++) { + str[j++] = str[i]; + } + str[j] = '\0'; + + return str; +} + +int alloc_cmd_buff(cmd_buff_t *cmd_buff) { + if (cmd_buff == NULL) return ERR_MEMORY; + + cmd_buff->argc = 0; + + cmd_buff->argv = (char**)malloc(CMD_ARGV_MAX * sizeof(char *)); + if (cmd_buff->argv == NULL) return ERR_MEMORY; + + for (int i = 0; i < CMD_ARGV_MAX; i++) { + cmd_buff->argv[i] = (char *)malloc(ARG_MAX * sizeof(char)); + if (cmd_buff->argv[i] == NULL) { + for (int j = 0; j < i; j++) free(cmd_buff->argv[j]); + free(cmd_buff->argv); + return ERR_MEMORY; + } + } + + cmd_buff->_cmd_buffer = (char *)malloc(SH_CMD_MAX * sizeof(char)); + if (cmd_buff->_cmd_buffer == NULL) { + for (int i = 0; i < CMD_ARGV_MAX; i++) free(cmd_buff->argv[i]); + free(cmd_buff->argv); + return ERR_MEMORY; + } + + return OK; +} + +void free_cmd_buff(cmd_buff_t *cmd_buff) { + if (cmd_buff != NULL) { + if (cmd_buff->_cmd_buffer != NULL) { + free(cmd_buff->_cmd_buffer); + cmd_buff->_cmd_buffer = NULL; + } + + if (cmd_buff->argv != NULL) { + for (int i = 0; i < CMD_ARGV_MAX; i++) { + if (cmd_buff->argv[i] != NULL) { + free(cmd_buff->argv[i]); + cmd_buff->argv[i] = NULL; + } + } + free(cmd_buff->argv); + cmd_buff->argv = NULL; + } + memset(cmd_buff, 0, sizeof(cmd_buff_t)); + } +} + +void clear_cmd_buff(cmd_buff_t *cmd_buff) { + if (cmd_buff != NULL) { + cmd_buff->argc = 0; + if (cmd_buff->_cmd_buffer) memset(cmd_buff->_cmd_buffer, 0, strlen(cmd_buff->_cmd_buffer)); + for (int i = 0; i < CMD_ARGV_MAX; i++) cmd_buff->argv[i] = NULL; + } +} + +int build_cmd_buff(char *cmd_line, cmd_buff_t *cmd_buff) { + if ((int)strlen(cmd_line) > SH_CMD_MAX) return ERR_CMD_OR_ARGS_TOO_BIG; + + if ((int)strlen(cmd_line) == 0) return WARN_NO_CMDS; + + if (cmd_buff->_cmd_buffer != NULL) { + free(cmd_buff->_cmd_buffer); + cmd_buff->_cmd_buffer = strdup(trim_whitespace(cmd_line)); + } else return ERR_MEMORY; + + char *token = cmd_buff->_cmd_buffer; + bool quotes = false; + char *p = NULL; + + while (*token) { + if (*token == DOUBLE_QUOTE_CHAR) { + quotes = !quotes; + if (quotes) p = token + 1; + else *token = '\0'; + } else if (!quotes && (*token == SPACE_CHAR || *token == '\t')) { + *token = '\0'; + + if (p != NULL) { + cmd_buff->argv[cmd_buff->argc++] = p; + p = NULL; + } + } else if (p == NULL) { + p = token; + } + token++; + } + + if (p != NULL) { + if (cmd_buff->argc >= CMD_ARGV_MAX - 1) return ERR_CMD_OR_ARGS_TOO_BIG; + cmd_buff->argv[cmd_buff->argc++] = p; + } + + cmd_buff->argv[cmd_buff->argc] = NULL; + return OK; +} + +int alloc_cmd_list(command_list_t *clist, int rc) { + if (clist == NULL) return ERR_MEMORY; + clist->num = 0; + clist->commands = (cmd_buff_t **)calloc(CMD_MAX, sizeof(cmd_buff_t *)); + if (clist->commands == NULL) return ERR_MEMORY; + + for (int i = 0; i < CMD_MAX; i++) { + cmd_buff_t *cmd = (cmd_buff_t *)malloc(sizeof(cmd_buff_t)); + if (cmd == NULL) { + rc = ERR_MEMORY; + break; + } + + memset(cmd, 0, sizeof(cmd_buff_t)); + + if ((rc = alloc_cmd_buff(cmd)) != OK_EXIT) { + free(cmd); + break; + } + clist->commands[i] = cmd; + } + + return rc; +} + +int build_cmd_list(char *cmd_line, command_list_t *clist, int rc) { + if (numInstanceOf(cmd_line, PIPE_CHAR) > CMD_MAX-1) return ERR_TOO_MANY_COMMANDS; + + if ((int)strlen(cmd_line) > SH_CMD_MAX) return ERR_CMD_OR_ARGS_TOO_BIG; + + char *outer_saveptr = NULL; + + char *outer_token = strtok_r(cmd_line, PIPE_STRING, &outer_saveptr); + + while (outer_token != NULL) { + if (clist->num > CMD_MAX) return ERR_TOO_MANY_COMMANDS; + + cmd_buff_t *cmd = malloc(sizeof(cmd_buff_t)); + + if ((rc = alloc_cmd_buff(cmd)) != OK) { + free(cmd); + return rc; + } + + if ((rc = build_cmd_buff(outer_token, cmd)) != OK) { + free(cmd); + return rc; + } + + clist->commands[clist->num] = cmd; + clist->num++; + + outer_token = strtok_r(NULL, PIPE_STRING, &outer_saveptr); + } + + return OK; +} + +void free_cmd_list(command_list_t *clist) { + if (clist != NULL) { + if (clist->commands != NULL) { + for (int i = 0; i < CMD_MAX; i++) { + if (clist->commands[i] != NULL) { + free_cmd_buff(clist->commands[i]); + free(clist->commands[i]); + clist->commands[i] = NULL; + } + } + free(clist->commands); + clist->commands = NULL; + } + } +} + +void clear_cmd_list(command_list_t *clist) { + if (clist != NULL) { + clist->num = 0; + for (int i = 0; i < CMD_MAX; i++) clear_cmd_buff(clist->commands[i]); + } +} + +int exec_pipeline(command_list_t *clist) { + int pipes[clist->num - 1][2]; + pid_t pids[clist->num]; + + for (int i = 0; i < clist->num - 1; i++) { + if (pipe(pipes[i]) == -1) { + perror("pipe"); + exit(EXIT_FAILURE); + } + } + + for (int i = 0; i < clist->num; i++) { + pids[i] = fork(); + if (pids[i] == -1) { + perror("fork"); + exit(EXIT_FAILURE); + } + + if (pids[i] == 0) { + if (i > 0) dup2(pipes[i-1][0], STDIN_FILENO); + + if (i < clist->num - 1) dup2(pipes[i][1], STDOUT_FILENO); + + for (int j = 0; j < clist->num - 1; j++) { + close(pipes[j][0]); + close(pipes[j][1]); + } + + execvp(clist->commands[i]->argv[0], clist->commands[i]->argv); + perror("execvp"); + exit(EXIT_FAILURE); + } + } + + for (int i = 0; i < clist->num - 1; i++) { + close(pipes[i][0]); + close(pipes[i][1]); + } + + for (int i = 0; i < clist->num; i++) waitpid(pids[i], NULL, 0); + + return OK; +} + +int exec_one_cmd(command_list_t *clist, int rc) { + cmd_buff_t *cmd = clist->commands[0]; + if (strcmp(cmd->argv[0], "dragon") == 0) { + print_dragon(); + return OK; + } + + if (strcmp(cmd->argv[0], "rc") == 0) { + printf("%d\n", rc); + return OK; + } + + if (strcmp(cmd->argv[0], EXIT_CMD) == 0) { + printf("exiting...\n"); + return(OK_EXIT); + } + + cmd->argv[cmd->argc] = 0; + + if (strcmp(cmd->argv[0], "cd") == 0) chdir(cmd->argv[1]); + else { + int f_result, c_result; + f_result = fork(); + + if (f_result < 0) perror("fork failed"); + else if (f_result == 0) { + rc = execvp(cmd->argv[0], cmd->argv); + perror("execvp failed"); + exit(EXIT_FAILURE); + } else { + wait(&c_result); + } + } + return OK; +} + +int exec_cmd(command_list_t *clist, int rc) { + if (clist == NULL) return ERR_MEMORY; + + if (rc == ERR_TOO_MANY_COMMANDS) { + printf(CMD_ERR_PIPE_LIMIT, CMD_MAX); + return rc; + } + + char *cmd = clist->commands[0]->argv[0]; + if (!cmd) return ERR_MEMORY; + + if (clist->num == 1) { + if ((rc = exec_one_cmd(clist, rc)) != OK) { + if (rc == OK_EXIT) { + clear_cmd_list(clist); + return rc; + } else return ERR_EXEC_CMD; + } + } + + if (clist->num > 1) { + if ((rc = exec_pipeline(clist)) != OK) return ERR_EXEC_CMD; + } + + return OK; +} + /* * Implement your exec_local_cmd_loop function by building a loop that prompts the * user for input. Use the SH_PROMPT constant from dshlib.h and then @@ -54,6 +401,42 @@ */ int exec_local_cmd_loop() { - - return OK; + char *cmd_line = (char *)malloc(ARG_MAX * sizeof(char)); + int rc = OK; + command_list_t *clist = (command_list_t *)malloc(sizeof(command_list_t)); + + if ((rc = alloc_cmd_list(clist, rc)) != OK) { + free(cmd_line); + return rc; + } + + while(1){ + printf("%s", SH_PROMPT); + if (fgets(cmd_line, ARG_MAX, stdin) == NULL){ + printf("\n"); + break; + } + //remove the trailing \n from cmd_buff + cmd_line[strcspn(cmd_line,"\n")] = '\0'; + + //IMPLEMENT THE REST OF THE REQUIREMENTS + if (strlen(cmd_line) == 0) { + printf(CMD_WARN_NO_CMD); + continue; + } + + if ((rc = build_cmd_list(cmd_line, clist, rc)) != OK) break; + + if ((rc = exec_cmd(clist, rc)) != OK) { + if (rc == OK_EXIT) rc = OK; + break; + } + + clear_cmd_list(clist); + } + + free(cmd_line); + free_cmd_list(clist); + free(clist); + return rc; } diff --git a/5-ShellP3/dshlib.h b/5-ShellP3/dshlib.h index 0f949dc..25aec28 100644 --- a/5-ShellP3/dshlib.h +++ b/5-ShellP3/dshlib.h @@ -1,7 +1,6 @@ #ifndef __DSHLIB_H__ #define __DSHLIB_H__ - //Constants for command structure sizes #define EXE_MAX 64 #define ARG_MAX 256 @@ -18,11 +17,16 @@ typedef struct command typedef struct cmd_buff { - int argc; - char *argv[CMD_ARGV_MAX]; - char *_cmd_buffer; + int argc; // up to CMD_MAX + char **argv; // CMD_ARG_MAX + char *_cmd_buffer; // SCH_CMD_MAX } cmd_buff_t; +typedef struct command_list{ + int num; + cmd_buff_t **commands; // CMD_MAX +} command_list_t; + /* WIP - Move to next assignment #define N_ARG_MAX 15 //MAX number of args for a command typedef struct command{ @@ -33,15 +37,12 @@ typedef struct command{ }command_t; */ -typedef struct command_list{ - int num; - cmd_buff_t commands[CMD_MAX]; -}command_list_t; - //Special character #defines #define SPACE_CHAR ' ' +#define SPACE_STRING " " #define PIPE_CHAR '|' #define PIPE_STRING "|" +#define DOUBLE_QUOTE_CHAR '"' #define SH_PROMPT "dsh3> " #define EXIT_CMD "exit" @@ -58,13 +59,27 @@ typedef struct command_list{ #define OK_EXIT -7 //prototypes +int numInstanceOf(char *, const char); +char *trim_whitespace(char *str); +extern void print_dragon(); + +//cmd_buff int alloc_cmd_buff(cmd_buff_t *cmd_buff); -int free_cmd_buff(cmd_buff_t *cmd_buff); -int clear_cmd_buff(cmd_buff_t *cmd_buff); +void free_cmd_buff(cmd_buff_t *cmd_buff); +void clear_cmd_buff(cmd_buff_t *cmd_buff); int build_cmd_buff(char *cmd_line, cmd_buff_t *cmd_buff); -int close_cmd_buff(cmd_buff_t *cmd_buff); -int build_cmd_list(char *cmd_line, command_list_t *clist); -int free_cmd_list(command_list_t *cmd_lst); + +//command_list_t +int alloc_cmd_list(command_list_t *clist, int rc); +int build_cmd_list(char *cmd_line, command_list_t *clist, int rc); +void free_cmd_list(command_list_t *clist); +void clear_cmd_list(command_list_t *clist); + +//main execution context +int exec_local_cmd_loop(); +int exec_pipeline(command_list_t *clist); +int exec_cd(cmd_buff_t *cmd_buff, int rc); +int exec_cmd(command_list_t *clist, int rc); //built in command stuff typedef enum { @@ -77,13 +92,6 @@ typedef enum { Built_In_Cmds match_command(const char *input); Built_In_Cmds exec_built_in_cmd(cmd_buff_t *cmd); -//main execution context -int exec_local_cmd_loop(); -int exec_cmd(cmd_buff_t *cmd); -int execute_pipeline(command_list_t *clist); - - - //output constants #define CMD_OK_HEADER "PARSED COMMAND LINE - TOTAL COMMANDS %d\n" diff --git a/5-ShellP3/questions.md b/5-ShellP3/questions.md new file mode 100644 index 0000000..23623ac --- /dev/null +++ b/5-ShellP3/questions.md @@ -0,0 +1,38 @@ +### Questions on Fork, Exec, and Linux Signals + +1. **Can you think of why we use `fork()`/`execvp()` instead of just calling `execvp()` directly? What value do you think the `fork()` provides?** + +Since fork creates a separate child process, it allows the command given as input to run separately from the shell without it replacing the previous process that was running. It allows the parents process to "wait" for the child process to finish or continuing allowing for user inputs. + +2. **What happens if the `fork()` system call fails? How does your implementation handle this scenario?** + +If 'fork()' fails, i.e returning -1, is exits with 'EXIT_FAILURE' meaning it didn't execute correctly. + +3. **How does `execvp()` find the command to execute? What system environment variable plays a role in this process?** + +Since the first argument for 'execvp()' is the name of a file, I woudl assume that the function looks for the executable in each directory in the path to the executable and attempts to execute it. If it doesn't exist in the path, then (at least in my code) it exits. + +4. **What is the purpose of calling `wait()` in the parent process after forking? What would happen if we didn’t call it?** + +5. **In the referenced demo code, we used `WEXITSTATUS()`. What information does this provide, and why is it important?** + +It gives you the exit status of a child process, which is important if we wanted to know whether a child process exited properly or with error. + +6. **Describe how your implementation of `build_cmd_buff()` handles quoted arguments. Why is this necessary?** + +Since 'build_cmd_list()' splits the stdin into tokens by the pipe character, i can call 'build_cmd_buff()' on each token. When I do, it goes through the token character by character until it comes across a double quote. If it does, it keeps everything between the first quote and second quote as one token, rather than splitting it by space or tab as would be handled normally. This is important for commands like 'echo' or 'grep' where text included inbetween quotes is supposed to be kept together and handled as one argument. + +7. **What changes did you make to your parsing logic compared to the previous assignment? Were there any unexpected challenges in refactoring your old code?** + +Barely any changes. The only real refactoring I did from the previous assignments was to merge 'build_cmd_buff()' and the code to parse by pipe together, which required more removing code than adding code. + +8. **For this question, you need to do some research on Linux signals. You can use this Google search to get started.** + + - **What is the purpose of signals in a Linux system, and how do they differ from other forms of interprocess communication (IPC)?** + Unlike other IPCs, signals can be received by the system at any point in time. Their purpose is to "notify" processes about events, such as process termination or execution. + - **Find and describe three commonly used signals (e.g., `SIGKILL`, `SIGTERM`, `SIGINT`). What are their typical use cases?** + SIGKILL - kills a process immediately, forcefully terminating it without clean up: example: kill -9 <pid> + SIGTERM - requests for a process to be terminated, allowing clean up; example: 'kill <pid>' + SIGINT - interupts a currently running process; example: 'CTRL + C' + - **What happens when a process receives `SIGSTOP`? Can it be caught or ignored like `SIGINT`? Why or why not?** + Both causes a process to pause however SIGSTOP (CTRL + Z) is forceful and must be adhered to whereas SIGINT can be handled by the process and subsequently ignored. -- GitLab