Question: In C programming: I'm working on my small shell in c. I think I have the first part: Before printing a prompt message, smallsh shall
In C programming:
I'm working on my small shell in c. I think I have the first part:
Before printing a prompt message, smallsh shall check for any un-waited-for background processes in the same process group ID as smallsh, and print the following informative message to stderr for each:
If exited: Child process %d done. Exit status %d. ,
If signaled: Child process %d done. Signaled %d. ,
If a child process is stopped, smallsh shall send it the SIGCONT signal and print the following message to stderr: Child process %d stopped. Continuing. ,
Any other child state changes (e.g. WIFCONTINUED) shall be ignored.
My code:
#define _POSIX_C_SOURCE 200809L
#include
#define MAX_INPUT 2048 #define MAX_ARGS 512 int bg_allowed = 1; // Is background
// 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
while(1) { get_last_background_pid() // Prompt
} return 0; }
The next part is:
The prompt Smallsh shall print a prompt to stderr by expanding the PS1 parameter (see parameter expansion below).
Explanation:
PS1 stands for Prompt String 1. There are three PSx parameters specified in POSIX:
PS1 (default: $ for users, # for root user): Printed before each new command line
Reading a line of input After printing the command prompt, smallsh shall read a line of input from stdin. (See GETLINE(3))
If reading is interrupted by a signal (see signal handling), a newline shall be printed, then a new command prompt shall be printed (including checking for background processes), and reading a line of input shall resume. (See CLEARERR(3), and dont forget to reset errno).
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.
- I'm not too sure how to get the user input going..
Thank you!!!
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
