$Id: DESIGN,v 1.6 2003/10/14 14:43:33 ldv Exp $

Here is a hasher-priv (*uid=root,egid=hashman,gid!=egid) control flow:
+ sanitize file descriptors
  + set safe umask
  + ensure 0,1,2 are valid file descriptors
  + close all the rest
  + reopen stdin with /dev/null if stdin is a tty
+ parse command line arguments
  + check for non-zero argument list
  + parse -h, --help and -number options
    + caller_num initialized here
  + parse arguments, abort if wrong
    + chroot_path and chroot_argv are initialized here
    + valid arguments are:
      getugid1
      killuid1
      chrootuid1 <chroot path> <program> [program args]
      getugid2
      killuid2
      chrootuid2 <chroot path> <program> [program args]
      makedev <chroot path>
+ initialize data related to caller
  + caller_user initialized here from SUDO_USER
    + caller_user must be existing user with valid home directory
    + must be true: caller_user == caller_user->pw_name
  + caller_uid initialized here from SUDO_UID
    + caller_uid must be valid uid
    + must be true: caller_uid == caller_user->pw_uid
  + caller_gid initialized here from SUDO_GID
    + caller_gid must be valid gid
    + must be true: caller_gid == caller_user->pw_gid
  + caller_home initialized here
+ drop all environment variables
+ load configuration
  + safe chdir to /etc/hasher-priv
  + safe load "system" file
    + config format is sequence of name=value lines
    + valid names are:
      user1
      user2
      prefix
      umask
      nice
      rlimit_(hard|soft)_*
      wlimit_(time_elapsed|time_idle|bytes_written)
  + safe chdir to "user.d"
  + safe load caller_user file
    + change_user1 and change_user2 should be initialized here
  + if caller_num is defined
    + discard change_user1 and change_user2
    + safe load caller_user:caller_num file
      + change_user1 and change_user2 should be initialized here
  + change_uid1 and change_gid1 initialized from change_user1
  + change_uid2 and change_gid2 initialized from change_user2
+ execute choosen task
  + getugid1: print change_uid1:change_gid1 pair
  + getugid2: print change_uid2:change_gid2 pair
  + killuid1/killuid2
    + check for valid uid specified
    + drop dumpable flag (just in case - not required)
    + setuid to specified uid
    + kill (-1, SIGKILL)
    + purge all SYSV IPC objects
  + makedev
    + safe chdir to chroot_path
    + safe chdir to dev
    + create fixed set of devices
  + chrootuid1/chrootuid2
    + check for valid uid specified
    + safe chdir to chroot_path
    + sanitize file descriptors again
    + create pipe
    + chroot to "."
    + clear supplementary group access list
    + set rlimits
    + fork
      + in child:
        + setgid/setuid to specified user
        + set nice and umask
	+ redirect stdout/stderr to pipe
        + execute specified program
      + in parent:
        + setgid/setuid to caller user
        + handle child output
