(libc.info.gz) Foreground and Background

Info Catalog (libc.info.gz) Launching Jobs (libc.info.gz) Implementing a Shell (libc.info.gz) Stopped and Terminated Jobs
 
 28.6.4 Foreground and Background
 --------------------------------
 
 Now let's consider what actions must be taken by the shell when it
 launches a job into the foreground, and how this differs from what must
 be done when a background job is launched.
 
    When a foreground job is launched, the shell must first give it
 access to the controlling terminal by calling 'tcsetpgrp'.  Then, the
 shell should wait for processes in that process group to terminate or
 stop.  This is discussed in more detail in  Stopped and Terminated
 Jobs.
 
    When all of the processes in the group have either completed or
 stopped, the shell should regain control of the terminal for its own
 process group by calling 'tcsetpgrp' again.  Since stop signals caused
 by I/O from a background process or a SUSP character typed by the user
 are sent to the process group, normally all the processes in the job
 stop together.
 
    The foreground job may have left the terminal in a strange state, so
 the shell should restore its own saved terminal modes before continuing.
 In case the job is merely stopped, the shell should first save the
 current terminal modes so that it can restore them later if the job is
 continued.  The functions for dealing with terminal modes are
 'tcgetattr' and 'tcsetattr'; these are described in  Terminal
 Modes.
 
    Here is the sample shell's function for doing all of this.
 
      /* Put job J in the foreground.  If CONT is nonzero,
         restore the saved terminal modes and send the process group a
         'SIGCONT' signal to wake it up before we block.  */
 
      void
      put_job_in_foreground (job *j, int cont)
      {
        /* Put the job into the foreground.  */
        tcsetpgrp (shell_terminal, j->pgid);
 
        /* Send the job a continue signal, if necessary.  */
        if (cont)
          {
            tcsetattr (shell_terminal, TCSADRAIN, &j->tmodes);
            if (kill (- j->pgid, SIGCONT) < 0)
              perror ("kill (SIGCONT)");
          }
 
        /* Wait for it to report.  */
        wait_for_job (j);
 
        /* Put the shell back in the foreground.  */
        tcsetpgrp (shell_terminal, shell_pgid);
 
        /* Restore the shell's terminal modes.  */
        tcgetattr (shell_terminal, &j->tmodes);
        tcsetattr (shell_terminal, TCSADRAIN, &shell_tmodes);
      }
 
    If the process group is launched as a background job, the shell
 should remain in the foreground itself and continue to read commands
 from the terminal.
 
    In the sample shell, there is not much that needs to be done to put a
 job into the background.  Here is the function it uses:
 
      /* Put a job in the background.  If the cont argument is true, send
         the process group a 'SIGCONT' signal to wake it up.  */
 
      void
      put_job_in_background (job *j, int cont)
      {
        /* Send the job a continue signal, if necessary.  */
        if (cont)
          if (kill (-j->pgid, SIGCONT) < 0)
            perror ("kill (SIGCONT)");
      }
 
Info Catalog (libc.info.gz) Launching Jobs (libc.info.gz) Implementing a Shell (libc.info.gz) Stopped and Terminated Jobs
automatically generated by info2html