Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

In C programming: Smallsh shall perform signal handling of the SIGINT and SIGTSTP signals as follows: The SIGTSTP signal shall be ignored by smallsh. The

In C programming:

Smallsh shall perform signal handling of the SIGINT and SIGTSTP signals as follows:

The SIGTSTP signal shall be ignored by smallsh.

The SIGINT signal shall be ignored (SIG_IGN) at all times except when reading a line of input in Step 1, during which time it shall be registered to a signal handler which does nothing.

Explanation:

SIGTSTP (CTRL-Z) normally causes a process to halt, which is undesirable. The smallsh process should not respond to this signal, so it sets its disposition to SIG_IGN.

The SIGINT (CTRL-C) signal normally causes a process to exit immediately, which is not desired. When delivered by a terminal, the terminal also clears the current line of input; because of this, we want to reprint the prompt for the restarted line of input. This is accomplished by registering a signal handler (which does nothing) to the SIGINT signal; when an interruptible system call (such as read()) is blocked and a signal with a custom handler arrives, the system call will fail with errno=EINTR (interrupted) after the signal handler returns. This allows us to escape the blocked read operation in order to reprint the prompt. If the disposition were set instead to SIG_IGN, the system call would not be interrupted, as with SIGTSTP above.

Here's what I have so far:

#define MAX_ARGS 512

#define MAX_LENGTH 2048

int num_background_pids = 0;

pid_t background_pids[MAX_ARGS];

int status = 0;

bool foreground_only = false;

void error(char* msg) {

fprintf(stderr, "%s ", msg);

status = 1;

}

// CTRL+C

void handle_SIGINT(int signo) {

if (!foreground_only) {

// ignore the signal for background processes

return;

}

// kill the foreground process and set status variable

if (signo == SIGINT) {

fprintf(stderr, "Terminated by signal %d ", signo);

status = 2;

}

}

// CTRL+Z

void handle_SIGTSTP(int signo) {

if (foreground_only) {

// ignore the signal for foreground processes

return;

}

// toggle foreground-only mode and print message

if (signo == SIGTSTP) {

foreground_only = !foreground_only;

if (foreground_only) {

fprintf(stderr, "Entering foreground-only mode (& is now ignored) ");

}

else {

fprintf(stderr, "Exiting foreground-only mode ");

}

}

}

pid_t get_last_background_pid() {

pid_t last_pid = 0;

int i;

for (i = 0; i < num_background_pids; i++) {

int child_status;

pid_t child_pid = waitpid(background_pids[i], &child_status, WNOHANG);

if (child_pid == background_pids[i]) {

if (WIFEXITED(child_status)) {

fprintf(stderr, "Child process %jd done. Exit status %d. ", (intmax_t) child_pid, WEXITSTATUS(child_status));

}

else if (WIFSIGNALED(child_status)) {

fprintf(stderr, "Child process %jd done. Signaled %d. ", (intmax_t) child_pid, WTERMSIG(child_status));

}

else if (WIFSTOPPED(child_status)) {

fprintf(stderr, "Child process %jd stopped. Continuing. ", (intmax_t) child_pid);

kill(child_pid, SIGCONT);

}

background_pids[i] = 0;

}

else {

last_pid = background_pids[i];

}

}

int j = 0;

for (i = 0; i < num_background_pids; i++) {

if (background_pids[i] != 0) {

background_pids[j++] = background_pids[i];

}

}

num_background_pids = j;

return last_pid;

}

int main() {

struct sigaction SIGINT_action = {0};

SIGINT_action.sa_handler = handle_SIGINT;

sigfillset(&SIGINT_action.sa_mask);

SIGINT_action.sa_flags = 0;

sigaction(SIGINT, &SIGINT_action, NULL);

struct sigaction SIGTSTP_action = {0};

SIGTSTP_action.sa_handler = handle_SIGTSTP;

sigfillset(&SIGTSTP_action.sa_mask);

SIGTSTP_action.sa_flags = 0;

sigaction(SIGTSTP, &SIGTSTP_action, NULL);

char *input = NULL;

ssize_t inputSize = 0;

char *delimiters = " \t ";

char *words[MAX_ARGS];

char *prompt = (getenv("PS1") != NULL) ? getenv("PS1") :"";

while(1) {

get_last_background_pid();//before the prompt

printf("%s", prompt);

ssize_t line_length = getline(&input, &inputSize, stdin);

bool input_redir = false, output_redir = false, background = false, comment = false;

int input_pos = -1, output_pos = -1, background_pos = -1, comment_pos = -1;

int i = 0;

words[i] = strtok(input, delimiters);

while (words[i] != NULL) {

if (strcmp(words[i], "<") == 0) {

input_redir = true;

input_pos = i;

}

else if (strcmp(words[i], ">") == 0) {

output_redir = true;

output_pos = i;

}

else if (strcmp(words[i], "&") == 0) {

background = true;

background_pos = i;

}

else if (strcmp(words[i], "#") == 0) {

comment = true;

comment_pos = i;

words[i] = NULL;

break;

}

i++;

words[i] = strtok(NULL, delimiters);

}

if (i > 0) {

if (input_redir && input_pos == i-2) {

freopen(words[i-1], "r", stdin);

words[i-2] = NULL;

}

else if (output_redir && output_pos == i-2) {

freopen(words[i-1], "w", stdout);

words[i-2] = NULL;

}

else if (input_redir && output_redir && (input_pos == i-3 || output_pos == i-3)) {

if (input_pos == i-3) {

freopen(words[i-2], "r", stdin);

words[i-3] = NULL;

}

}

else {

freopen(words[i-2], "w", stdout);

words[i-3] = NULL;

}

}

if (background && background_pos == i-1) {

words[i-1] = NULL;

pid_t pid = fork();

if (pid == 0) {

execvp(words[0], words);

error("Invalid command");

exit(1);

}

else if (pid > 0) {

background_pids[num_background_pids] = pid;

num_background_pids++;

}

else {

error("Fork failed");

}

}

else {

// run in foreground

pid_t pid = fork();

if (pid == 0) {

execvp(words[0], words);

error("Invalid command");

exit(1);

}

else if (pid > 0) {

waitpid(pid, &status, 0);

}

else {

error("Invalid command");

exit(1);

}

}

}

return 0;

}

Thank you!!

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Object Oriented Databases Prentice Hall International Series In Computer Science

Authors: John G. Hughes

1st Edition

0136298745, 978-0136298748

More Books

Students also viewed these Databases questions

Question

8. Managers are not trained to be innovation leaders.

Answered: 1 week ago