   This file documents the GNU C library.

   This is Edition 0.03, last updated 19 May 1993, of
`The GNU C Library Reference Manual', for Version 1.06 Beta.

   Copyright (C) 1993 Free Software Foundation, Inc.

   Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.

   Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided also
that the section entitled "GNU Library General Public License" is
included exactly as in the original, and provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.

   Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions, except that the text of the translations of the section
entitled "GNU Library General Public License" must be approved for
accuracy by the Foundation.

Initializing the Shell
----------------------

   When a shell program that normally performs job control is started,
it has to be careful in case it has been invoked from another shell
that is already doing its own job control.

   A subshell that runs interactively has to ensure that it has been
placed in the foreground by its parent shell before it can enable job
control itself.  It does this by getting its initial process group ID
with the `getpgrp' function, and comparing it to the process group ID
of the current foreground job associated with its controlling terminal
(which can be retrieved using the `tcgetpgrp' function).

   If the subshell is not running as a foreground job, it must stop
itself by sending a `SIGTTIN' signal to its own process group.  It may
not arbitrarily put itself into the foreground; it must wait for the
user to tell the parent shell to do this.  If the subshell is continued
again, it should repeat the check and stop itself again if it is still
not in the foreground.

   Once the subshell has been placed into the foreground by its parent
shell, it can enable its own job control.  It does this by calling
`setpgid' to put itself into its own process group, and then calling
`tcsetpgrp' to place this process group into the foreground.

   When a shell enables job control, it should set itself to ignore all
the job control stop signals so that it doesn't accidentally stop
itself. You can do this by setting the action for all the stop signals
to `SIG_IGN'.

   A subshell that runs non-interactively cannot and should not support
job control.  It must leave all processes it creates in the same process
group as the shell itself; this allows the non-interactive shell and its
child processes to be treated as a single job by the parent shell.  This
is easy to do--just don't use any of the job control primitives--but
you must remember to make the shell do it.

   Here is the initialization code for the sample shell that shows how
to do all of this.

     /* Keep track of attributes of the shell.  */

     #include <sys/types.h>
     #include <termios.h>
     #include <unistd.h>

     pid_t shell_pgid;
     struct termios shell_tmodes;
     int shell_terminal;
     int shell_is_interactive;

     /* Make sure the shell is running interactively as the foreground job
        before proceeding. */

     void
     init_shell ()
     {

       /* See if we are running interactively.  */
       shell_terminal = STDIN_FILENO;
       shell_is_interactive = isatty (shell_terminal);

       if (shell_is_interactive)
         {
           /* Loop until we are in the foreground.  */
           while (tcgetpgrp (shell_terminal) != (shell_pgid = getpgrp ()))
             kill (- shell_pgid, SIGTTIN);

           /* Ignore interactive and job-control signals.  */
           signal (SIGINT, SIG_IGN);
           signal (SIGQUIT, SIG_IGN);
           signal (SIGTSTP, SIG_IGN);
           signal (SIGTTIN, SIG_IGN);
           signal (SIGTTOU, SIG_IGN);
           signal (SIGCHLD, SIG_IGN);

           /* Put ourselves in our own process group.  */
           shell_pgid = getpid ();
           if (setpgid (shell_pgid, shell_pgid) < 0)
             {
               perror ("Couldn't put the shell in its own process group");
               exit (1);
             }

           /* Grab control of the terminal.  */
           tcsetpgrp (shell_terminal, shell_pgid);

           /* Save default terminal attributes for shell.  */
           tcgetattr (shell_terminal, &shell_tmodes);
         }
     }

Launching Jobs
--------------

   Once the shell has taken responsibility for performing job control on
its controlling terminal, it can launch jobs in response to commands
typed by the user.

   To create the processes in a process group, you use the same `fork'
and `exec' functions described in Process Creation Concepts.
Since there are multiple child processes involved, though, things are a
little more complicated and you must be careful to do things in the
right order.  Otherwise, nasty race conditions can result.

   You have two choices for how to structure the tree of parent-child
relationships among the processes.  You can either make all the
processes in the process group be children of the shell process, or you
can make one process in group be the ancestor of all the other processes
in that group.  The sample shell program presented in this chapter uses
the first approach because it makes bookkeeping somewhat simpler.

   As each process is forked, it should put itself in the new process
group by calling `setpgid'; see Process Group Functions.  The
first process in the new group becomes its "process group leader", and
its process ID becomes the "process group ID" for the group.

   The shell should also call `setpgid' to put each of its child
processes into the new process group.  This is because there is a
potential timing problem: each child process must be put in the process
group before it begins executing a new program, and the shell depends on
having all the child processes in the group before it continues
executing.  If both the child processes and the shell call `setpgid',
this ensures that the right things happen no matter which process gets
to it first.

   If the job is being launched as a foreground job, the new process
group also needs to be put into the foreground on the controlling
terminal using `tcsetpgrp'.  Again, this should be done by the shell as
well as by each of its child processes, to avoid race conditions.

   The next thing each child process should do is to reset its signal
actions.

   During initialization, the shell process set itself to ignore job
control signals; see Initializing the Shell.  As a result, any
child processes it creates also ignore these signals by inheritance.
This is definitely undesirable, so each child process should explicitly
set the actions for these signals back to `SIG_DFL' just after it is
forked.

   Since shells follow this convention, applications can assume that
they inherit the correct handling of these signals from the parent
process. But every application has a responsibility not to mess up the
handling of stop signals.  Applications that disable the normal
interpretation of the SUSP character should provide some other
mechanism for the user to stop the job.  When the user invokes this
mechanism, the program should send a `SIGTSTP' signal to the process
group of the process, not just to the process itself.  See Signaling Another Process.

   Finally, each child process should call `exec' in the normal way.
This is also the point at which redirection of the standard input and
output channels should be handled.  See Duplicating Descriptors,
for an explanation of how to do this.

   Here is the function from the sample shell program that is
responsible for launching a program.  The function is executed by each
child process immediately after it has been forked by the shell, and
never returns.

     void
     launch_process (process *p, pid_t pgid,
                     int infile, int outfile, int errfile,
                     int foreground)
     {
       pid_t pid;

       if (shell_is_interactive)
         {
           /* Put the process into the process group and give the process group
              the terminal, if appropriate.
              This has to be done both by the shell and in the individual
              child processes because of potential race conditions.  */
           pid = getpid ();
           if (pgid == 0) pgid = pid;
           setpgid (pid, pgid);
           if (foreground)
             tcsetpgrp (shell_terminal, pgid);

           /* Set the handling for job control signals back to the default.  */
           signal (SIGINT, SIG_DFL);
           signal (SIGQUIT, SIG_DFL);
           signal (SIGTSTP, SIG_DFL);
           signal (SIGTTIN, SIG_DFL);
           signal (SIGTTOU, SIG_DFL);
           signal (SIGCHLD, SIG_DFL);
         }

       /* Set the standard input/output channels of the new process.  */
       if (infile != STDIN_FILENO)
         {
           dup2 (infile, STDIN_FILENO);
           close (infile);
         }
       if (outfile != STDOUT_FILENO)
         {
           dup2 (outfile, STDOUT_FILENO);
           close (outfile);
         }
       if (errfile != STDERR_FILENO)
         {
           dup2 (errfile, STDERR_FILENO);
           close (errfile);
         }

       /* Exec the new process.  Make sure we exit.  */
       execvp (p->argv[0], p->argv);
       perror ("execvp");
       exit (1);
     }

   If the shell is not running interactively, this function does not do
anything with process groups or signals.  Remember that a shell not
performing job control must keep all of its subprocesses in the same
process group as the shell itself.

   Next, here is the function that actually launches a complete job.
After creating the child processes, this function calls some other
functions to put the newly created job into the foreground or
background; these are discussed in Foreground and Background.

     void
     launch_job (job *j, int foreground)
     {
       process *p;
       pid_t pid;
       int mypipe[2], infile, outfile;

       infile = j->stdin;
       for (p = j->first_process; p; p = p->next)
         {
           /* Set up pipes, if necessary.  */
           if (p->next)
             {
               if (pipe (mypipe) < 0)
                 {
                   perror ("pipe");
                   exit (1);
                 }
               outfile = mypipe[1];
             }
           else
             outfile = j->stdout;

           /* Fork the child processes.  */
           pid = fork ();
           if (pid == 0)
             /* This is the child process.  */
             launch_process (p, j->pgid, infile, outfile, j->stderr, foreground);
           else if (pid < 0)
             {
               /* The fork failed.  */
               perror ("fork");
               exit (1);
             }
           else
             {
               /* This is the parent process.  */
               p->pid = pid;
               if (shell_is_interactive)
                 {
                   if (!j->pgid)
                     j->pgid = pid;
                   setpgid (pid, j->pgid);
                 }
             }

           /* Clean up after pipes.  */
           if (infile != j->stdin)
             close (infile);
           if (outfile != j->stdout)
             close (outfile);
           infile = mypipe[0];
         }

       format_job_info (j, "launched");

       if (!shell_is_interactive)
         wait_for_job (j);
       else if (foreground)
         put_job_in_foreground (j, 0);
       else
         put_job_in_background (j, 0);
     }

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 been 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)");
     }

Stopped and Terminated Jobs
---------------------------

   When a foreground process is launched, the shell must block until
all of the processes in that job have either terminated or stopped.  It
can do this by calling the `waitpid' function; see Process Completion.
Use the `WUNTRACED' option so that status is reported
for processes that stop as well as processes that terminate.

   The shell must also check on the status of background jobs so that it
can report terminated and stopped jobs to the user; this can be done by
calling `waitpid' with the `WNOHANG' option.  A good place to put a
such a check for terminated and stopped jobs is just before prompting
for a new command.

   The shell can also receive asynchronous notification that there is
status information available for a child process by establishing a
handler for `SIGCHLD' signals.  See Signal Handling.

   In the sample shell program, the `SIGCHLD' signal is normally
ignored.  This is to avoid reentrancy problems involving the global data
structures the shell manipulates.  But at specific times when the shell
is not using these data structures--such as when it is waiting for
input on the terminal--it makes sense to enable a handler for
`SIGCHLD'.  The same function that is used to do the synchronous status
checks (`do_job_notification', in this case) can also be called from
within this handler.

   Here are the parts of the sample shell program that deal with
checking the status of jobs and reporting the information to the user.

     /* Store the status of the process PID that was returned by waitpid.
        Return 0 if all went well, nonzero otherwise.  */

     int
     mark_process_status (pid_t pid, int status)
     {
       job *j;
       process *p;

       if (pid > 0)
         {
           /* Update the record for the process.  */
           for (j = first_job; j; j = j->next)
             for (p = j->first_process; p; p = p->next)
               if (p->pid == pid)
                 {
                   p->status = status;
                   if (WIFSTOPPED (status))
                     p->stopped = 1;
                   else
                     {
                       p->completed = 1;
                       if (WIFSIGNALED (status))
                         fprintf (stderr, "%d: Terminated by signal %d.\n",
                                  (int) pid, WTERMSIG (p->status));
                     }
                   return 0;
                  }
           fprintf (stderr, "No child process %d.\n", pid);
           return -1;
         }
       else if (pid == 0 || errno == ECHILD)
         /* No processes ready to report.  */
         return -1;
       else {
         /* Other weird errors.  */
         perror ("waitpid");
         return -1;
       }
     }

     /* Check for processes that have status information available,
        without blocking.  */

     void
     update_status (void)
     {
       int status;
       pid_t pid;

       do
         pid = waitpid (WAIT_ANY, &status, WUNTRACED|WNOHANG);
       while (!mark_process_status (pid, status));
     }

     /* Check for processes that have status information available,
        blocking until all processes in the given job have reported.  */

     void
     wait_for_job (job *j)
     {
       int status;
       pid_t pid;

       do
         pid = waitpid (WAIT_ANY, &status, WUNTRACED);
       while (!mark_process_status (pid, status)
              && !job_is_stopped (j)
              && !job_is_completed (j));
     }

     /* Format information about job status for the user to look at.  */

     void
     format_job_info (job *j, const char *status)
     {
       fprintf (stderr, "%ld (%s): %s\n", (long)j->pgid, status, j->command);
     }

     /* Notify the user about stopped or terminated jobs.
        Delete terminated jobs from the active job list.  */

     void
     do_job_notification (void)
     {
       job *j, *jlast, *jnext;
       process *p;

       /* Update status information for child processes.  */
       update_status ();

       jlast = NULL;
       for (j = first_job; j; j = jnext)
         {
           jnext = j->next;

           /* If all processes have completed, tell the user the job has
              completed and delete it from the list of active jobs.  */
           if (job_is_completed (j)) {
             format_job_info (j, "completed");
             if (jlast)
               jlast->next = jnext;
             else
               first_job = jnext;
             free_job (j);
           }

           /* Notify the user about stopped jobs,
              marking them so that we won't do this more than once.  */
           else if (job_is_stopped (j) && !j->notified) {
             format_job_info (j, "stopped");
             j->notified = 1;
             jlast = j;
           }

           /* Don't say anything about jobs that are still running.  */
           else
             jlast = j;
         }
     }

Continuing Stopped Jobs
-----------------------

   The shell can continue a stopped job by sending a `SIGCONT' signal
to its process group.  If the job is being continued in the foreground,
the shell should first invoke `tcsetpgrp' to give the job access to the
terminal, and restore the saved terminal settings.  After continuing a
job in the foreground, the shell should wait for the job to stop or
complete, as if the job had just been launched in the foreground.

   The sample shell program uses the same set of
functions--`put_job_in_foreground' and `put_job_in_background'--to
handle both newly created and continued jobs.  The definitions of these
functions were given in Foreground and Background.  When
continuing a stopped job, a nonzero value is passed as the CONT
argument to ensure that the `SIGCONT' signal is sent and the terminal
modes reset, as appropriate.

   This leaves only a function for updating the shell's internal
bookkeeping about the job being continued:

     /* Mark a stopped job J as being running again.  */

     void
     mark_job_as_running (job *j)
     {
       Process *p;

       for (p = j->first_process; p; p = p->next)
         p->stopped = 0;
       j->notified = 0;
     }

     /* Continue the job J.  */

     void
     continue_job (job *j, int foreground)
     {
       mark_job_as_running (j);
       if (foreground)
         put_job_in_foreground (j, 1);
       else
         put_job_in_background (j, 1);
     }

The Missing Pieces
------------------

   The code extracts for the sample shell included in this chapter are
only a part of the entire shell program.  In particular, nothing at all
has been said about how `job' and `program' data structures are
allocated and initialized.

   Most real shells provide a complex user interface that has support
for a command language; variables; abbreviations, substitutions, and
pattern matching on file names; and the like.  All of this is far too
complicated to explain here!  Instead, we have concentrated on showing
how to implement the core process creation and job control functions
that can be called from such a shell.

   Here is a table summarizing the major entry points we have presented:

`void init_shell (void)'
     Initialize the shell's internal state.  See Initializing the Shell.

`void launch_job (job *J, int FOREGROUND)'
     Launch the job J as either a foreground or background job. See
     Launching Jobs.

`void do_job_notification (void)'
     Check for and report any jobs that have terminated or stopped.
     Can be called synchronously or within a handler for `SIGCHLD'
     signals. See Stopped and Terminated Jobs.

`void continue_job (job *J, int FOREGROUND)'
     Continue the job J.  See Continuing Stopped Jobs.

   Of course, a real shell would also want to provide other functions
for managing jobs.  For example, it would be useful to have commands to
list all active jobs or to send a signal (such as `SIGKILL') to a job.

Functions for Job Control
=========================

   This section contains detailed descriptions of the functions relating
to job control.

Identifying the Controlling Terminal
------------------------------------

   You can use the `ctermid' function to get a file name that you can
use to open the controlling terminal.  In the GNU library, it returns
the same string all the time: `"/dev/tty"'.  That is a special "magic"
file name that refers to the controlling terminal of the current
process (if it has one).  The function `ctermid' is declared in the
header file `stdio.h'.

 -- Function: char * ctermid (char *STRING)
     The `ctermid' function returns a string containing the file name of
     the controlling terminal for the current process.  If STRING is
     not a null pointer, it should be an array that can hold at least
     `L_ctermid' characters; the string is returned in this array.
     Otherwise, a pointer to a string in a static area is returned,
     which might get overwritten on subsequent calls to this function.

     An empty string is returned if the file name cannot be determined
     for any reason.  Even if a file name is returned, access to the
     file it represents is not guaranteed.

 -- Macro: int L_ctermid
     The value of this macro is an integer constant expression that
     represents the size of a string large enough to hold the file name
     returned by `ctermid'.

   See also the `isatty' and `ttyname' functions, in Is It a Terminal.

Process Group Functions
-----------------------

   Here are descriptions of the functions for manipulating process
groups. Your program should include the header files `sys/types.h' and
`unistd.h' to use these functions.

 -- Function: pid_t setsid (void)
     The `setsid' function creates a new session.  The calling process
     becomes the session leader, and is put in a new process group whose
     process group ID is the same as the process ID of that process.
     There are initially no other processes in the new process group,
     and no other process groups in the new session.

     This function also makes the calling process have no controlling
     terminal.

     The `setsid' function returns the new process group ID of the
     calling process if successful.  A return value of `-1' indicates an
     error.  The following `errno' error conditions are defined for this
     function:

    `EPERM'
          The calling process is already a process group leader, or
          there is already another process group around that has the
          same process group ID.

   The `getpgrp' function has two definitions: one derived from BSD
Unix, and one from the POSIX.1 standard.  The feature test macros you
have selected (see Feature Test Macros.) determine which definition
you get.  Specifically, you get the BSD version if you define
`_BSD_SOURCE'; otherwise, you get the POSIX version if you define
`_POSIX_SOURCE' or `_GNU_SOURCE'.  Programs written for old BSD systems
will not include `unistd.h', which defines `getpgrp' specially under
`_BSD_SOURCE'.  You must link such programs with the `-lbsd-compat'
option to get the BSD definition.

 -- POSIX.1 Function: pid_t getpgrp (void)
     The POSIX.1 definition of `getpgrp' returns the process group ID of
     the calling process.

 -- BSD Function: pid_t getpgrp (pid_t PID)
     The BSD definition of `getpgrp' returns the process group ID of the
     process PID.  You can supply a value of `0' for the PID argument
     to get information about the calling process.

 -- Function: int setpgid (pid_t PID, pid_t PGID)
     The `setpgid' function puts the process PID into the process group
     PGID.  As a special case, either PID or PGID can be zero to
     indicate the process ID of the calling process.

     This function fails on a system that does not support job control.
     See Job Control is Optional, for more information.

     If the operation is successful, `setpgid' returns zero.  Otherwise
     it returns `-1'.  The following `errno' error conditions are
     defined for this function:

    `EACCES'
          The child process named by PID has executed an `exec'
          function since it was forked.

    `EINVAL'
          The value of the PGID is not valid.

    `ENOSYS'
          The system doesn't support job control.

    `EPERM'
          The process indicated by the PID argument is a session leader,
          or is not in the same session as the calling process, or the
          value of the PGID argument doesn't match a process group ID
          in the same session as the calling process.

    `ESRCH'
          The process indicated by the PID argument is not the calling
          process or a child of the calling process.

 -- Function: int setpgrp (pid_t PID, pid_t PGID)
     This is the BSD Unix name for `setpgid'.  Both functions do exactly
     the same thing.

Functions for Controlling Terminal Access
-----------------------------------------

   These are the functions for reading or setting the foreground
process group of a terminal.  You should include the header files
`sys/types.h' and `unistd.h' in your application to use these functions.

   Although these functions take a file descriptor argument to specify
the terminal device, the foreground job is associated with the terminal
file itself and not a particular open file descriptor.

 -- Function: pid_t tcgetpgrp (int FILEDES)
     This function returns the process group ID of the foreground
     process group associated with the terminal open on descriptor
     FILEDES.

     If there is no foreground process group, the return value is a
     number greater than `1' that does not match the process group ID
     of any existing process group.  This can happen if all of the
     processes in the job that was formerly the foreground job have
     terminated, and no other job has yet been moved into the
     foreground.

     In case of an error, a value of `-1' is returned.  The following
     `errno' error conditions are defined for this function:

    `EBADF'
          The FILEDES argument is not a valid file descriptor.

    `ENOSYS'
          The system doesn't support job control.

    `ENOTTY'
          The terminal file associated with the FILEDES argument isn't
          the controlling terminal of the calling process.

 -- Function: int tcsetpgrp (int FILEDES, pid_t PGID)
     This function is used to set a terminal's foreground process group
     ID. The argument FILEDES is a descriptor which specifies the
     terminal; PGID specifies the process group.  The calling process
     must be a member of the same session as PGID and must have the same
     controlling terminal.

     For terminal access purposes, this function is treated as output.
     If it is called from a background process on its controlling
     terminal, normally all processes in the process group are sent a
     `SIGTTOU' signal.  The exception is if the calling process itself
     is ignoring or blocking `SIGTTOU' signals, in which case the
     operation is performed and no signal is sent.

     If successful, `tcsetpgrp' returns `0'.  A return value of `-1'
     indicates an error.  The following `errno' error conditions are
     defined for this function:

    `EBADF'
          The FILEDES argument is not a valid file descriptor.

    `EINVAL'
          The PGID argument is not valid.

    `ENOSYS'
          The system doesn't support job control.

    `ENOTTY'
          The FILEDES isn't the controlling terminal of the calling
          process.

    `EPERM'
          The PGID isn't a process group in the same session as the
          calling process.

Users and Groups
****************

   Every user who can log in on the system is identified by a unique
number called the "user ID".  Each process has an effective user ID
which says which user's access permissions it has.

   Users are classified into "groups" for access control purposes.  Each
process has one or more "group ID values" which say which groups the
process can use for access to files.

   The effective user and group IDs of a process collectively form its
"persona".  This determines which files the process can access.
Normally, a process inherits its persona from the parent process, but
under special circumstances a process can change its persona and thus
change its access permissions.

   Each file in the system also has a user ID and a group ID.  Access
control works by comparing the user and group IDs of the file with those
of the running process.

   The system keeps a database of all the registered users, and another
database of all the defined groups.  There are library functions you
can use to examine these databases.

User and Group IDs
==================

   Each user account on a computer system is identified by a "user
name" (or "login name") and "user ID".  Normally, each user name has a
unique user ID, but it is possible for several login names to have the
same user ID.  The user names and corresponding user IDs are stored in
a data base which you can access as described in User Database.

   Users are classified in "groups".  Each user name also belongs to
one or more groups, and has one "default group".  Users who are members
of the same group can share resources (such as files) that are not
accessible to users who are not a member of that group.  Each group has
a "group name" and "group ID".  See Group Database, for how to find
information about a group ID or group name.

The Persona of a Process
========================

   At any time, each process has a single user ID and a group ID which
determine the privileges of the process.  These are collectively called
the "persona" of the process, because they determine "who it is" for
purposes of access control.  These IDs are also called the "effective
user ID" and "effective group ID" of the process.

   Your login shell starts out with a persona which consists of your
user ID and your default group ID. In normal circumstances, all your
other processes inherit these values.

   A process also has a "real user ID" which identifies the user who
created the process, and a "real group ID" which identifies that user's
default group.  These values do not play a role in access control, so
we do not consider them part of the persona.  But they are also
important.

   Both the real and effective user ID can be changed during the
lifetime of a process.  See Why Change Persona.

   In addition, a user can belong to multiple groups, so the persona
includes "supplementary group IDs" that also contribute to access
permission.

   For details on how a process's effective user IDs and group IDs
affect its permission to access files, see Access Permission.

   The user ID of a process also controls permissions for sending
signals using the `kill' function.  See Signaling Another Process.

Why Change the Persona of a Process?
====================================

   The most obvious situation where it is necessary for a process to
change its user and/or group IDs is the `login' program.  When `login'
starts running, its user ID is `root'.  Its job is to start a shell
whose user and group IDs are those of the user who is logging in.  (To
accomplish this fully, `login' must set the real user and group IDs as
well as its persona.  But this is a special case.)

   The more common case of changing persona is when an ordinary user
program needs access to a resource that wouldn't ordinarily be
accessible to the user actually running it.

   For example, you may have a file that is controlled by your program
but that shouldn't be read or modified directly by other users, either
because it implements some kind of locking protocol, or because you want
to preserve the integrity or privacy of the information it contains.
This kind of restricted access can be implemented by having the program
change its effective user or group ID to match that of the resource.

   Thus, imagine a game program that saves scores in a file.  The game
program itself needs to be able to update this file no matter who is
running it, but if users can write the file without going through the
game, they can give themselves any scores they like.  Some people
consider this undesirable, or even reprehensible.  It can be prevented
by creating a new user ID and login name (say, `games') to own the
scores file, and make the file writable only by this user.  Then, when
the game program wants to update this file, it can change its effective
user ID to be that for `games'.  In effect, the program must adopt the
persona of `games' so it can write the scores file.

How an Application Can Change Persona
=====================================

   The ability to change the persona of a process can be a source of
unintentional privacy violations, or even intentional abuse.  Because of
the potential for problems, changing persona is restricted to special
circumstances.

   You can't arbitrarily set your user ID or group ID to anything you
want; only privileged processes can do that.  Instead, the normal way
for a program to change its persona is that it has been set up in
advance to change to a particular user or group.  This is the function
of the setuid and setgid bits of a file's access mode.  See
Permission Bits.

   When the setuid bit of an executable file is set, executing that file
automatically changes the effective user ID to the user that owns the
file.  Likewise, executing a file whose setgid bit is set changes the
effective group ID to the group of the file.  See Executing a File.
Creating a file that changes to a particular user or group ID thus
requires full access to that user or group ID.

   See File Attributes, for a more general discussion of file modes
and accessibility.

   A process can always change its effective user (or group) ID back to
its real ID.  Programs do this so as to turn off their special
privileges when they are not needed, which makes for more robustness.

Reading the Persona of a Process
================================

   Here are detailed descriptions of the functions for reading the user
and group IDs of a process, both real and effective.  To use these
facilities, you must include the header files `sys/types.h' and
`unistd.h'.

 -- Data Type: uid_t
     This is an integer data type used to represent user IDs.  In the
     GNU library, this is an alias for `unsigned int'.

 -- Data Type: gid_t
     This is an integer data type used to represent group IDs.  In the
     GNU library, this is an alias for `unsigned int'.

 -- Function: uid_t getuid (void)
     The `getuid' function returns the real user ID of the process.

 -- Function: gid_t getgid (void)
     The `getgid' function returns the real group ID of the process.

 -- Function: uid_t geteuid (void)
     The `geteuid' function returns the effective user ID of the
     process.

 -- Function: gid_t getegid (void)
     The `getegid' function returns the effective group ID of the
     process.

 -- Function: int getgroups (int COUNT, gid_t *GROUPS)
     The `getgroups' function is used to inquire about the supplementary
     group IDs of the process.  Up to COUNT of these group IDs are
     stored in the array GROUPS; the return value from the function is
     the number of group IDs actually stored.  If COUNT is smaller than
     the total number of supplementary group IDs, then `getgroups'
     returns a value of `-1' and `errno' is set to `EINVAL'.

     If COUNT is zero, then `getgroups' just returns the total number
     of supplementary group IDs.  On systems that do not support
     supplementary groups, this will always be zero.

     Here's how to use `getgroups' to read all the supplementary group
     IDs:

          gid_t *
          read_all_groups (void)
          {
            int ngroups = getgroups (NULL, 0);
            gid_t *groups = (gid_t *) xmalloc (ngroups * sizeof (gid_t));
            int val = getgroups (ngroups, groups);
            if (val < 0)
              {
                free (groups);
                return NULL;
              }
            return groups;
          }

Setting the User ID
===================

   This section describes the functions for altering the user ID (real
and/or effective) of a process.  To use these facilities, you must
include the header files `sys/types.h' and `unistd.h'.

 -- Function: int setuid (uid_t NEWUID)
     This function sets both the real and effective user ID of the
     process to NEWUID, provided that the process has appropriate
     privileges.

     If the process is not privileged, then NEWUID must either be equal
     to the real user ID or the saved user ID (if the system supports
     the `_POSIX_SAVED_IDS' feature).  In this case, `setuid' sets only
     the effective user ID and not the real user ID.

     The `setuid' function returns a value of `0' to indicate
     successful completion, and a value of `-1' to indicate an error.
     The following `errno' error conditions are defined for this
     function:

    `EINVAL'
          The value of the NEWUID argument is invalid.

    `EPERM'
          The process does not have the appropriate privileges; you do
          not have permission to change to the specified ID.

 -- Function: int setreuid (uid_t RUID, uid_t EUID)
     This function sets the real user ID of the process to RUID and the
     effective user ID to EUID.

     The `setreuid' function exists for compatibility with 4.3 BSD Unix,
     which does not support saved IDs.  You can use this function to
     swap the effective and real user IDs of the process.  (Privileged
     processes are not limited to this particular usage.)  If saved IDs
     are supported, you should use that feature instead of this
     function.  See Enable/Disable Setuid.

     The return value is `0' on success and `-1' on failure. The
     following `errno' error conditions are defined for this function:

    `EPERM'
          The process does not have the appropriate privileges; you do
          not have permission to change to the specified ID.

Setting the Group IDs
=====================

   This section describes the functions for altering the group IDs (real
and effective) of a process.  To use these facilities, you must include
the header files `sys/types.h' and `unistd.h'.

 -- Function: int setgid (gid_t NEWGID)
     This function sets both the real and effective group ID of the
     process to NEWGID, provided that the process has appropriate
     privileges.

     If the process is not privileged, then NEWGID must either be equal
     to the real group ID or the saved group ID.  In this case, `setgid'
     sets only the effective group ID and not the real group ID.

     The return values and error conditions for `setgid' are the same
     as those for `setuid'.

 -- Function: int setregid (gid_t RGID, fid_t EGID)
     This function sets the real group ID of the process to RGID and
     the effective group ID to EGID.

     The `setregid' function is provided for compatibility with 4.3 BSD
     Unix, which does not support saved IDs.  You can use this function
     to swap the effective and real group IDs of the process.
     (Privileged processes are not limited to this usage.)  If saved
     IDs are supported, you should use that feature instead of using
     this function. See Enable/Disable Setuid.

     The return values and error conditions for `setregid' are the same
     as those for `setreuid'.

   The GNU system also lets privileged processes change their
supplementary group IDs.  To use `setgroups' or `initgroups', your
programs should include the header file `grp.h'.

 -- Function: int setgroups (size_t COUNT, gid_t *GROUPS)
     This function sets the process's supplementary group IDs.  It can
     only be called from privileged processes.  The COUNT argument
     specifies the number of group IDs in the array GROUPS.

     This function returns `0' if successful and `-1' on error. The
     following `errno' error conditions are defined for this function:

    `EPERM'
          The calling process is not privileged.

 -- Function: int initgroups (const char *USER, gid_t GID)
     The `initgroups' function effectively calls `setgroups' to set the
     process's supplementary group IDs to be the normal default for the
     user name USER.  The group ID GID is also included.

Enabling and Disabling Setuid Access
====================================

   A typical setuid program does not need its special access all of the
time.  It's a good idea to turn off this access when it isn't needed,
so it can't possibly give unintended access.

   If the system supports the saved user ID feature, you can accomplish
this with `setuid'.  When the game program starts, its real user ID is
`jdoe', its effective user ID is `games', and its saved user ID is also
`games'.  The program should record both user ID values once at the
beginning, like this:

     user_user_id = getuid ();
     game_user_id = geteuid ();

   Then it can turn off game file access with

     setuid (user_user_id);

and turn it on with

     setuid (game_user_id);

Throughout this process, the real user ID remains `jdoe' and the saved
user ID remains `games', so the program can always set its effective
user ID to either one.

   On other systems that don't support the saved user ID feature, you
can turn setuid access on and off by using `setreuid' to swap the real
and effective user IDs of the process, as follows:

     setreuid (geteuid (), getuid ());

This special case is always allowed--it cannot fail.

   Why does this have the effect of toggling the setuid access?
Suppose a game program has just started, and its real user ID is `jdoe'
while its effective user ID is `games'.  In this state, the game can
write the scores file.  If it swaps the two uids, the real becomes
`games' and the effective becomes `jdoe'; now the program has only
`jdoe' access.  Another swap brings `games' back to the effective user
ID and restores access to the scores file.

   In order to handle both kinds of systems, test for the saved user ID
feature with a preprocessor conditional, like this:

     #ifdef _POSIX_SAVED_IDS
       setuid (user_user_id);
     #else
       setreuid (geteuid (), getuid ());
     #endif