Skip to content
Snippets Groups Projects
Commit 475cbb53 authored by cxb23's avatar cxb23
Browse files

completed assignment 5-ShellP3

parent 754f024e
No related branches found
No related tags found
No related merge requests found
File added
...@@ -4,11 +4,68 @@ ...@@ -4,11 +4,68 @@
# #
# Create your unit tests suit in this file # Create your unit tests suit in this file
@test "Example: check ls runs without errors" { @test "ls | grep .c " {
run ./dsh <<EOF run ./dsh <<EOF
ls ls | grep ".c"
EOF EOF
# Assertions # Assertions
[ "$status" -eq 0 ] [ "$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]
}
@%%%%
%%%%%%
%%%%%%
% %%%%%%% @
%%%%%%%%%% %%%%%%%
%%%%%%% %%%%@ %%%%%%%%%%%%@ %%%%%% @%%%%
%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%% %%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%% %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%@ @%%%%%%%%%%%%%%%%%% %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@%%%%%%@
%%%%%%%%@ %%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%% %%
%%%%%%%%%%%%% %%@%%%%%%%%%%%% %%%%%%%%%%% %%%%%%%%%%%% @%
%%%%%%%%%% %%% %%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%% % %%%%%%%%%%%%% %%%%%%%%%%%%@%%%%%%%%%%%
%%%%%%%%%@ % %%%%%%%%%%%%% @%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%@ %%@%%%%%%%%%%%% @%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%@ %%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%
%%%%%%%%%@ @%%%%%%%%%%%%%% %%%%%%%%%%%%@ %%%% %%%%%%%%%%%%%%%%% %%%%%%%%
%%%%%%%%%% %%%%%%%%%%%%%%%%% %%%%%%%%%%%%% %%%%%%%%%%%%%%%%%% %%%%%%%%%
%%%%%%%%%@%%@ %%%%%%%%%%%%%%%%@ %%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%% %%
%%%%%%%%%% % %%%%%%%%%%%%%%@ %%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%% %%
%%%%%%%%%%%% @ %%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%
%%%%%%%%%%%%% %% % %@ %%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%
%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%% @%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%
@%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%% %%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%% @%%%%%%%%%
%%%%%%%%%%%%%%%%%%%% @%@% @%%%%%%%%%%%%%%%%%% %%%
%%%%%%%%%%%%%%% %%%%%%%%%% %%%%%%%%%%%%%%% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% %%% %%%%%%%%%% %%%@
%%%%%%%%%%%%%%%%%%% %%%%%% %% %%%%%%%%%%%%%@
%%%%%%%@
File added
...@@ -6,9 +6,356 @@ ...@@ -6,9 +6,356 @@
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <errno.h>
#include "dshlib.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 * 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 * user for input. Use the SH_PROMPT constant from dshlib.h and then
...@@ -54,6 +401,42 @@ ...@@ -54,6 +401,42 @@
*/ */
int exec_local_cmd_loop() int exec_local_cmd_loop()
{ {
char *cmd_line = (char *)malloc(ARG_MAX * sizeof(char));
int rc = OK;
command_list_t *clist = (command_list_t *)malloc(sizeof(command_list_t));
return OK; 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;
} }
#ifndef __DSHLIB_H__ #ifndef __DSHLIB_H__
#define __DSHLIB_H__ #define __DSHLIB_H__
//Constants for command structure sizes //Constants for command structure sizes
#define EXE_MAX 64 #define EXE_MAX 64
#define ARG_MAX 256 #define ARG_MAX 256
...@@ -18,11 +17,16 @@ typedef struct command ...@@ -18,11 +17,16 @@ typedef struct command
typedef struct cmd_buff typedef struct cmd_buff
{ {
int argc; int argc; // up to CMD_MAX
char *argv[CMD_ARGV_MAX]; char **argv; // CMD_ARG_MAX
char *_cmd_buffer; char *_cmd_buffer; // SCH_CMD_MAX
} cmd_buff_t; } cmd_buff_t;
typedef struct command_list{
int num;
cmd_buff_t **commands; // CMD_MAX
} command_list_t;
/* WIP - Move to next assignment /* WIP - Move to next assignment
#define N_ARG_MAX 15 //MAX number of args for a command #define N_ARG_MAX 15 //MAX number of args for a command
typedef struct command{ typedef struct command{
...@@ -33,15 +37,12 @@ typedef struct command{ ...@@ -33,15 +37,12 @@ typedef struct command{
}command_t; }command_t;
*/ */
typedef struct command_list{
int num;
cmd_buff_t commands[CMD_MAX];
}command_list_t;
//Special character #defines //Special character #defines
#define SPACE_CHAR ' ' #define SPACE_CHAR ' '
#define SPACE_STRING " "
#define PIPE_CHAR '|' #define PIPE_CHAR '|'
#define PIPE_STRING "|" #define PIPE_STRING "|"
#define DOUBLE_QUOTE_CHAR '"'
#define SH_PROMPT "dsh3> " #define SH_PROMPT "dsh3> "
#define EXIT_CMD "exit" #define EXIT_CMD "exit"
...@@ -58,13 +59,27 @@ typedef struct command_list{ ...@@ -58,13 +59,27 @@ typedef struct command_list{
#define OK_EXIT -7 #define OK_EXIT -7
//prototypes //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 alloc_cmd_buff(cmd_buff_t *cmd_buff);
int free_cmd_buff(cmd_buff_t *cmd_buff); void free_cmd_buff(cmd_buff_t *cmd_buff);
int clear_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 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); //command_list_t
int free_cmd_list(command_list_t *cmd_lst); 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 //built in command stuff
typedef enum { typedef enum {
...@@ -77,13 +92,6 @@ typedef enum { ...@@ -77,13 +92,6 @@ typedef enum {
Built_In_Cmds match_command(const char *input); Built_In_Cmds match_command(const char *input);
Built_In_Cmds exec_built_in_cmd(cmd_buff_t *cmd); 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 //output constants
#define CMD_OK_HEADER "PARSED COMMAND LINE - TOTAL COMMANDS %d\n" #define CMD_OK_HEADER "PARSED COMMAND LINE - TOTAL COMMANDS %d\n"
......
### 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.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment