Shell Implementation - Suggested Step 3

Contents

  1. Implement sigint_handler and sigtstp_handler
  2. Finish implementing sigchld_handler
  3. Finish eval
  4. Change implementation of waitfg
  5. Finish implementing do_bgfg
  6. Update the quit command

Implement sigint_handler and sigtstp_handler[top]

These signal handlers should forward the signal to the foreground process job if there is one; else do nothing.

  1. Use the fgpid function to get the pid of the foreground job. This function return 0 if there is currently no foreground job.
  2. If there is a foreground job, use the kill system call to send the signal to the process group for the foreground job.

Note 1: The group id of the foreground job is the pid stored in the job table. Why?

Note 2: How do you send the signal to all processes in the foreground job process group?

Finish implementing sigchld_handler [top]

If waitpid returns the pid of a child,

  1. Check if it terminated normally. If so delete it from the job table. This will change all fields of the entry for the job. In particular, it changes the state entry to be UNDEF.
  2. Otherwise, check if the process was terminated by a signal. If so, delete the job from the job table and print a message including the signal number that caused termination. (See the tests or run the reference shell to see the exact format and content of the message.)
  3. Otherwise, check if the process was stopped. In this case, print a message (see the tests for the exact format and content) and change the state to ST, but don't delete the job.

Finish eval[top]

  1. Declare a signal set (type sigset_t) variable and initialize it to be empty (sigemptyset function)
  2. Add the SIGCHLD signal to the signal set
  3. If the command is not builtin, block SIGCHLD before forking a child (sigprocmask function). Why?
  4. Child should create a new process group with itself as the group leader (setpgrp function) before calling execvp.
  5. Parent should add the child to the job list and then unblock the SIGCHLD signal. Why?

Change implementation of waitfg[top]

  1. Get a pointer to the entry in the job table for the pid passed to waitfg.

  2. Loop while the state of this entry is FG. Call sleep to sleep for 1 second between checks.

    When the state is no longer FG, return.

Finish implementing do_bgfg[top]

  1. Get the entry for the job from the job table
  2. If the state is ST and the command is bg, change the state to BG and send SIGCONT signal to the process group. How?
  3. If the state is ST and the command is fg, change the state to FG, send SIGCONT signal to the process group (how?) and wait (by calling waitfg).
  4. If the state is BG and the command is fg, change the state to FG and wait (by calling waitfg)
  5. Print appropriate messages (see the expected output from tests for the exact content of messages).

Update the quit command[top]

Check if there are stopped jobs (how?). If so print a message, but don't exit. Just return 1.