Question: In C Programming: I need help with how to go about this part: -------------------------------------------------------------------------------------------- 2. Word splitting The line of input shall be split into
In C Programming:
I need help with how to go about this part:
--------------------------------------------------------------------------------------------
2. Word splitting
The line of input shall be split into words, delimited by the characters in the IFS environment variable, or " \t " (
A minimum of 512 words shall be supported.
Note: unset (NULL) is not the same as empty (). An empty IFS string is valid, and the entire command line would be interpreted as a single word.
2. Expansion
Each of the following tokens shall be expanded within each word:
Any occurrence of ~/ at the beginning of a word shall be replaced with the value of the HOME environment variable. The "/" shall be retained. (see GETENV(3))
Any occurrence of $$ within a word shall be replaced with the proccess ID of the smallsh process (see GETPID(3)).
Any occurrence of $? within a word shall be replaced with the exit status of the last foreground command (see waiting).
Any occurrence of $! within a word shall be replaced with the process ID of the most recent background process (see waiting).
If an expanded environment variable is unset, it shall be interpreted as an empty string (). This includes the PS1 variable as described above.
The $? parameter shall default to 0 (0).
The $! parameter shall default to an empty string () if no background process ID is available.
Expansion shall occur in the forward direction in a single pass, and expanded text shall not participate in further expansion token recognition (expansion is not recursive).
3. Parsing
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...]]
--------------------------------------------------------------------------------------------------------
Here's what I have so far:
#include
#define MAX_INPUT 2048 #define MAX_ARGS 512 int bg_allowed = 1; int num_background_pids = 0; pid_t num_background_pids[MAX_ARGS];
// Catch CTRL-C // void handle_SIGINT(int signo) { char *message = "terminated by signal 2 "; write(STDOUT_FILENO, message, 23); sleep(10); }
// Catch CTRL-Z // void handle_SIGTSTP(int signo) {
if (bg_allowed == 1) { // bg_allowed gets changed to 0 to enter forground-only mode and displays message
char *message = "Entering foreground-only mode (& is now ignored) "; write(1, message, 49); fflush(stdout); bg_allowed = 0; }
else {
// bg_allowed gets changed to 1 to exit foreground-only mode and displays message char *message = "Exiting foreground-only mode "; write(1, message, 29); fflush(stdout); bg_allowed = 1; } }
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); } // remove pid from list of background processes background_pids[i] = 0;
else { // child process still running, update last_pid last_pid = background_pids[i]; } }
// remove any exited or signaled background processes 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() {
// SIGNAL HANDLERS // // CTRL-C // struct sigaction SIGINT_action = {0}; // Initialize SIGINT_action struct to be empty SIGINT_action.sa_handler = handle_SIGINT; // Register handle_SIGINT as the signal handler sigfillset(&SIGINT_action.sa_mask); // Block all catchable signals while handle_SIGINT is running SIGINT_action.sa_flags = 0; // No flags set
sigaction(SIGINT, &SIGINT_action, NULL); // Install the signal handler
// CTRL-Z // struct sigaction SIGTSTP_action = {0}; // Initialize SIGTSTP_action struct to be empty SIGTSTP_action.sa_handler = handle_SIGTSTP; // Register handle_SIGTSTP as the signal handler sigfillset(&SIGTSTP_action.sa_mask); // Block all catchable signals while handle_SIGTSTP is running SIGTSTP_action.sa_flags = 0; // No flags set
sigaction(SIGTSTP, &SIGTSTP_action, NULL); // Install the signal handler
char *input = NULL; ssize_t inputSize = 0;
while(1) { get_last_background_pid() int newline = 0;
printf("$"); fflush(stdout); ssize_t numChars = getline(&input, &inputSize, stdin)
while (numChars == -1 && errno == EINTR) { printf(" $"); fflush(stdout); clearerr(stdin); numChars = getline(&input, &inputSize, stdin); }
if (numChars == -1) { perror("getline"); exit(EXIT_FAILURE); }
// Removing the new line // for (int i = 0; (i < numChars && newline == 0); ++i) { if (input[i] == ' ') { input[i] = '\0'; newline = 1; } }
// Check if input is blank and do nothing but return // if(!strcmp(input, "")) { return; }
} return 0; }
----------
thank you!!
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
