Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Working on a small shell and I'm stuck on this part: The words are parsed syntactically into tokens in the following order. Tokens recognized in

Working on a small shell and I'm stuck on this part:

The words are parsed syntactically into tokens in the following order. Tokens recognized in a previous step do not take part in further parsing.

The first occurrence of the word # and any additional words following it shall be ignored as a comment.

If the last word is &, it shall indicate that the command is to be run in the background.

If the last word is immediately preceded by the word "<", it shall be interpreted as the filename operand of the input redirection operator.

If the last word is immediately preceded by the word ">", it shall be interpreted as the filename operand of the output redirection operator.

Steps 3 and 4 may occur in either order (output redirection may occur before input redirection).

All words not listed above shall be interpreted as regular words and form the command to be executed and its arguments. The tokens listed above shall not be included as command arguments.

A valid command line may be either:

[command] [arguments...] [> outfile] [< infile] [&] [# [comment...]]

[command] [arguments...] [< infile] [> outfile] [&] [# [comment...]]

If "<", ">", and "&" appear outside of the end-of-line context described above, they are treated as regular arguments:

$ echo test < > & test test < > & test

This is 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);

int i = 0;

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

while (words[i] != NULL) {

i++;

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

}

if (WIFEXITED(status)) {

exit_status = WEXITSTATUS(status);

}

char *home = getenv("HOME");

for (int j = 0; j < i; j++) {

if (strncmp(words[j], "~/", 2) == 0) {

char *temp = NULL;

if (home != NULL) {

temp = malloc(strlen(home) + strlen(words[j] -1));

strcpy(temp, home);

strcat(temp, words[j] + 1);

}

else {

temp = malloc(strlen(words[j]));

strcpy(temp, words[j]);

}

words[j] = temp;

}

}

char pid[16];

snprintf(pid, sizeof(pid), "%d", getpid());

for (int j = 0; j < i; j++) {

char *pos = strstr(words[j], "$$");

if (pos != NULL) {

char *temp = malloc(strlen(words[j]) - 1 + strlen(pid));

strncpy(temp, words[j], pos - words[j]);

temp[pos - words[j]] = '\0';

strcat(temp, pid);

strcat(temp, pos + 2);

words[j] = temp;

}

}

char exit_status[16];

snprintf(exit_status, sizeof(exit_status), "%d", status);

for (int j = 0; j < i; j++) {

char *pos = strstr(words[j], "$?");

if (pos != NULL) {

char *temp = malloc(strlen(words[j]) - 1 + strlen(exit_status));

strncpy(temp, words[j], pos - words[j]);

temp[pos - words[j]] = '\0';

strcat(temp, exit_status);

strcat(temp, pos + 2);

words[j] = temp;

}

}

char *bg_pid = getenv("!");

if (bg_pid == NULL) {

bg_pid = "";

}

char bg_pid_str[16];

snprintf(bg_pid_str, sizeof(bg_pid_str), "%s", bg_pid);

for (int j = 0; j < i; j++) {

char *pos = strstr(words[j], "$!");

if (pos != NULL) {

char *temp = malloc(strlen(words[j]) - 1 + strlen(bg_pid));

strncpy(temp, words[j], pos - words[j]);

temp[pos - words[j]] = '\0';

strcat(temp, bg_pid);

strcat(temp, pos + 2);

words[j] = temp;

}

}

for (int j = 0; j < i; j++) {

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

break;

}

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

break;

}

}

if (words[0]== '\0') {

//

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

exit(0);

}

printf(;

}

}

return 0;

}

Thanks!

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

Learn To Program Databases With Visual Basic 6

Authors: John Smiley

1st Edition

1902745035, 978-1902745039

More Books

Students also viewed these Databases questions

Question

7. List behaviors to improve effective leadership in meetings

Answered: 1 week ago