11.8 Job Control for ushThis section describes an implementation of job control for ush. Start by testing ush7 in the following cases to make sure that it correctly handles the SIGINT and SIGQUIT.
11.8.1 A job list objectTo do job control, ush must keep track of its children. Use a list object similar to the one used in Program 2.9 to keep a program history. The nodes in the list should have the following structure.
Place the list structure in a separate file along with the following functions to manipulate the job list.
Add the specified job to the list. The pgid is the process group ID, and cmd is the command string for the job. The status value can be either FOREGROUND or BACKGROUND. If successful, add returns the job number. If unsuccessful, add returns 1 and sets errno. It uses getlargest to determine the largest job number and uses a job number that is one greater than this.
Remove the node corresponding to the specified job from the list. If successful, delete returns the job number. If unsuccessful, delete returns 1 and sets errno. Be sure to free all space associated with the deleted node.
Output a list of jobs and each one's status. Use the following format.
Set the status value of the node of the corresponding job. If successful, setstatus returns 0. If unsuccessful, setstatus returns 1 and sets errno.
Return the status value associated with the specified job in *pstatus. If successful, getstatus returns 0. If unsuccessful, getstatus returns 1 and sets errno.
Return the process group ID of the specified job. If job doesn't exist, getprocess returns 0.
Scan the job list for the largest job number currently in the list. The getlargest function returns the largest job number if any nodes are on the list or 0 if the list is empty. Write a driver program to thoroughly test the list functions independently of ush. 11.8.2 The job list in ushAfter the job list functions are working, add the job list object to ush as follows.
Test ush with the job list. Do not add job control in this step. Execute the jobs command frequently to see the status of the background processes. Carefully experiment with an existing shell that has job control. Make sure that ush handles background and foreground processes similarly. 11.8.3 Job control in ushIncorporate job control into ush by adding the following commands to ush in addition to the jobs command of the previous section.
11.8.4 Process behavior in waiting for a pipelineWhat happens when a shell starts a pipeline in the foreground and one of the processes in the pipeline terminates? The result depends on which process in the pipeline is the child of the shell. Exercise 11.36Make a new version of showid from Exercise 11.28 on page 395 that sleeps for one minute after displaying the IDs. Call the new program showidsleep. Run ush7 with each of the following command lines. What happens?
Answer:For the first command line, the shell displays the prompt after one minute since the first command in the pipeline is the child of the shell. For the second command line, the shell displays the prompt immediately since it waits only for the first command in the pipeline. This is probably not the desired behavior. Typically, a pipeline consists of a sequence of filters, and the last one in the sequence is the last to finish. Exercise 11.37How would you solve the problem described in Exercise 11.36?Answer:One solution would be to rewrite executecmdpipe so that the last command of the pipeline was executed by the first process created. A better solution would be to have all of the processes in the pipeline be children of the shell and have the shell wait for all of them. |