void
vsf_two_process_start(struct vsf_session* p_sess)
{
  /* Create the comms channel between privileged parent and no-priv child */
  priv_sock_init(p_sess);
  if (tunable_ssl_enable)
  {
    /* Create the comms channel between the no-priv SSL child and the low-priv
     * protocol handling child.
     */
    ssl_comm_channel_init(p_sess);
  }
  vsf_sysutil_install_async_sighandler(kVSFSysUtilSigCHLD, twoproc_handle_sigchld);
  {
    int newpid = vsf_sysutil_fork();
    if (newpid != 0)
    {
      /* Parent - go into pre-login parent process mode */
      while (1)
      {
        process_login_req(p_sess);
      }
    }
  }
  /* Child process - time to lose as much privilege as possible and do the
   * login processing
   */
  vsf_sysutil_close(p_sess->parent_fd);
  if (tunable_ssl_enable)
  {
    vsf_sysutil_close(p_sess->ssl_consumer_fd);
  }
  if (tunable_local_enable && tunable_userlist_enable)
  {
    int retval = str_fileread(&p_sess->userlist_str, tunable_userlist_file,
                              VSFTP_CONF_FILE_MAX);
    if (vsf_sysutil_retval_is_error(retval))
    {
      die2("cannot open user list file:", tunable_userlist_file);
    }
  }
  drop_all_privs();
  init_connection(p_sess);
  /* NOTREACHED */
}
void
vsf_two_process_start(struct vsf_session* p_sess)
{
  vsf_sysutil_install_sighandler(kVSFSysUtilSigTERM, handle_sigterm, 0, 1);
  /* Overrides the SIGKILL setting set by the standalone listener. */
  vsf_set_term_if_parent_dies();
  /* Create the comms channel between privileged parent and no-priv child */
  priv_sock_init(p_sess);
  if (tunable_ssl_enable)
  {
    /* Create the comms channel between the no-priv SSL child and the low-priv
     * protocol handling child.
     */
    ssl_comm_channel_init(p_sess);
  }
  vsf_sysutil_install_sighandler(kVSFSysUtilSigCHLD, handle_sigchld, 0, 1);
  {
    int newpid;
    if (tunable_isolate_network)
    {
      newpid = vsf_sysutil_fork_newnet();
    }
    else
    {
      newpid = vsf_sysutil_fork();
    }
    if (newpid != 0)
    {
      priv_sock_set_parent_context(p_sess);
      if (tunable_ssl_enable)
      {
        ssl_comm_channel_set_consumer_context(p_sess);
      }
      /* Parent - go into pre-login parent process mode */
      while (1)
      {
        process_login_req(p_sess);
      }
    }
  }
  /* Child process - time to lose as much privilege as possible and do the
   * login processing
   */
  vsf_set_die_if_parent_dies();
  priv_sock_set_child_context(p_sess);
  if (tunable_ssl_enable)
  {
    ssl_comm_channel_set_producer_context(p_sess);
  }
  if (tunable_local_enable && tunable_userlist_enable)
  {
    int retval = str_fileread(&p_sess->userlist_str, tunable_userlist_file,
                              VSFTP_CONF_FILE_MAX);
    if (vsf_sysutil_retval_is_error(retval))
    {
      die2("cannot read user list file:", tunable_userlist_file);
    }
  }
  drop_all_privs();
  init_connection(p_sess);
  /* NOTREACHED */
}