コード例 #1
0
ファイル: exechelp-w32ce.c プロジェクト: Domikk/gnupg
/* Simplified version of gnupg_spawn_process.  This function forks and
   then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
   and ERRFD to stderr (any of them may be -1 to connect them to
   /dev/null).  The arguments for the process are expected in the NULL
   terminated array ARGV.  The program name itself should not be
   included there.  Calling gnupg_wait_process is required.

   Returns 0 on success or an error code. */
gpg_error_t
gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
                        int infd, int outfd, int errfd, pid_t *pid)
{
  gpg_error_t err;
  PROCESS_INFORMATION pi = {NULL};
  char *cmdline;

  /* Setup return values.  */
  *pid = (pid_t)(-1);

  if (infd != -1 || outfd != -1 || errfd != -1)
    return gpg_error (GPG_ERR_NOT_SUPPORTED);

  /* Build the command line.  */
  err = build_w32_commandline (argv, 0, 0, 0, &cmdline);
  if (err)
    return err;

  log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline);
  if (!create_process (pgmname, cmdline, &pi))
    {
      log_error ("CreateProcess(fd) failed: %s\n", w32_strerror (-1));
      xfree (cmdline);
      return gpg_error (GPG_ERR_GENERAL);
    }
  xfree (cmdline);
  cmdline = NULL;

  log_debug ("CreateProcess(fd) ready: hProcess=%p hThread=%p"
             " dwProcessID=%d dwThreadId=%d\n",
             pi.hProcess, pi.hThread,
             (int) pi.dwProcessId, (int) pi.dwThreadId);

  /* Process has been created suspended; resume it now. */
  ResumeThread (pi.hThread);
  CloseHandle (pi.hThread);

  *pid = handle_to_pid (pi.hProcess);
  return 0;
}
コード例 #2
0
ファイル: exechelp-w32ce.c プロジェクト: Domikk/gnupg
/* Spawn a new process and immediatley detach from it.  The name of
   the program to exec is PGMNAME and its arguments are in ARGV (the
   programname is automatically passed as first argument).
   Environment strings in ENVP are set.  An error is returned if
   pgmname is not executable; to make this work it is necessary to
   provide an absolute file name.  All standard file descriptors are
   connected to /dev/null. */
gpg_error_t
gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
                              const char *envp[] )
{
  gpg_error_t err;
  char *cmdline;
  PROCESS_INFORMATION pi = {NULL };

  (void)envp;

  /* Build the command line.  */
  err = build_w32_commandline (argv, 0, 0, 0, &cmdline);
  if (err)
    return err;

  /* Note: There is no detached flag under CE.  */
  log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline);
  if (!create_process (pgmname, cmdline, &pi))
    {
      log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1));
      xfree (cmdline);
      return gpg_error (GPG_ERR_GENERAL);
    }
  xfree (cmdline);
  cmdline = NULL;

  log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p"
             " dwProcessID=%d dwThreadId=%d\n",
             pi.hProcess, pi.hThread,
             (int) pi.dwProcessId, (int) pi.dwThreadId);

  /* Process has been created suspended; resume it now. */
  ResumeThread (pi.hThread);
  CloseHandle (pi.hThread);

  return 0;
}
コード例 #3
0
/* Spawn a new process and immediatley detach from it.  The name of
   the program to exec is PGMNAME and its arguments are in ARGV (the
   programname is automatically passed as first argument).
   Environment strings in ENVP are set.  An error is returned if
   pgmname is not executable; to make this work it is necessary to
   provide an absolute file name.  All standard file descriptors are
   connected to /dev/null. */
gpg_error_t
gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
                              const char *envp[] )
{
  gpg_error_t err;
  SECURITY_ATTRIBUTES sec_attr;
  PROCESS_INFORMATION pi =
    {
      NULL,      /* Returns process handle.  */
      0,         /* Returns primary thread handle.  */
      0,         /* Returns pid.  */
      0          /* Returns tid.  */
    };
  STARTUPINFO si;
  int cr_flags;
  char *cmdline;


  /* FIXME: We don't make use of ENVP yet.  It is currently only used
     to pass the GPG_AGENT_INFO variable to gpg-agent.  As the default
     on windows is to use a standard socket, this does not really
     matter.  */
  (void)envp;

  if (access (pgmname, X_OK))
    return gpg_error_from_syserror ();

  /* Prepare security attributes.  */
  memset (&sec_attr, 0, sizeof sec_attr );
  sec_attr.nLength = sizeof sec_attr;
  sec_attr.bInheritHandle = FALSE;

  /* Build the command line.  */
  err = build_w32_commandline (pgmname, argv, &cmdline);
  if (err)
    return err;

  /* Start the process.  */
  memset (&si, 0, sizeof si);
  si.cb = sizeof (si);
  si.dwFlags = STARTF_USESHOWWINDOW;
  si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;

  cr_flags = (CREATE_DEFAULT_ERROR_MODE
              | GetPriorityClass (GetCurrentProcess ())
              | CREATE_NEW_PROCESS_GROUP
              | DETACHED_PROCESS);
/*   log_debug ("CreateProcess(detached), path=`%s' cmdline=`%s'\n", */
/*              pgmname, cmdline); */
  if (!CreateProcess (pgmname,       /* Program to start.  */
                      cmdline,       /* Command line arguments.  */
                      &sec_attr,     /* Process security attributes.  */
                      &sec_attr,     /* Thread security attributes.  */
                      FALSE,         /* Inherit handles.  */
                      cr_flags,      /* Creation flags.  */
                      NULL,          /* Environment.  */
                      NULL,          /* Use current drive/directory.  */
                      &si,           /* Startup information. */
                      &pi            /* Returns process information.  */
                      ))
    {
      log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1));
      xfree (cmdline);
      return gpg_error (GPG_ERR_GENERAL);
    }
  xfree (cmdline);
  cmdline = NULL;

/*   log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p" */
/*              " dwProcessID=%d dwThreadId=%d\n", */
/*              pi.hProcess, pi.hThread, */
/*              (int) pi.dwProcessId, (int) pi.dwThreadId); */

  CloseHandle (pi.hThread);

  return 0;
}
コード例 #4
0
/* Simplified version of gnupg_spawn_process.  This function forks and
   then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
   and ERRFD to stderr (any of them may be -1 to connect them to
   /dev/null).  The arguments for the process are expected in the NULL
   terminated array ARGV.  The program name itself should not be
   included there.  Calling gnupg_wait_process is required.

   Returns 0 on success or an error code. */
gpg_error_t
gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
                        int infd, int outfd, int errfd, pid_t *pid)
{
  gpg_error_t err;
  SECURITY_ATTRIBUTES sec_attr;
  PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
  STARTUPINFO si;
  char *cmdline;
  int i;
  HANDLE stdhd[3];

  /* Setup return values.  */
  *pid = (pid_t)(-1);

  /* Prepare security attributes.  */
  memset (&sec_attr, 0, sizeof sec_attr );
  sec_attr.nLength = sizeof sec_attr;
  sec_attr.bInheritHandle = FALSE;

  /* Build the command line.  */
  err = build_w32_commandline (pgmname, argv, &cmdline);
  if (err)
    return err;

  memset (&si, 0, sizeof si);
  si.cb = sizeof (si);
  si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
  si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
  stdhd[0] = infd  == -1? w32_open_null (0) : INVALID_HANDLE_VALUE;
  stdhd[1] = outfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
  stdhd[2] = errfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
  si.hStdInput  = infd  == -1? stdhd[0] : (void*)_get_osfhandle (infd);
  si.hStdOutput = outfd == -1? stdhd[1] : (void*)_get_osfhandle (outfd);
  si.hStdError  = errfd == -1? stdhd[2] : (void*)_get_osfhandle (errfd);

/*   log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); */
  if (!CreateProcess (pgmname,       /* Program to start.  */
                      cmdline,       /* Command line arguments.  */
                      &sec_attr,     /* Process security attributes.  */
                      &sec_attr,     /* Thread security attributes.  */
                      TRUE,          /* Inherit handles.  */
                      (CREATE_DEFAULT_ERROR_MODE
                       | GetPriorityClass (GetCurrentProcess ())
                       | CREATE_SUSPENDED | DETACHED_PROCESS),
                      NULL,          /* Environment.  */
                      NULL,          /* Use current drive/directory.  */
                      &si,           /* Startup information. */
                      &pi            /* Returns process information.  */
                      ))
    {
      log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
      err = gpg_error (GPG_ERR_GENERAL);
    }
  else
    err = 0;
  xfree (cmdline);
  for (i=0; i < 3; i++)
    if (stdhd[i] != INVALID_HANDLE_VALUE)
      CloseHandle (stdhd[i]);
  if (err)
    return err;

/*   log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
/*              " dwProcessID=%d dwThreadId=%d\n", */
/*              pi.hProcess, pi.hThread, */
/*              (int) pi.dwProcessId, (int) pi.dwThreadId); */

  /* Process has been created suspended; resume it now. */
  ResumeThread (pi.hThread);
  CloseHandle (pi.hThread);

  *pid = handle_to_pid (pi.hProcess);
  return 0;

}
コード例 #5
0
/* Fork and exec the PGMNAME, see exechelp.h for details.  */
gpg_error_t
gnupg_spawn_process (const char *pgmname, const char *argv[],
                     gpg_err_source_t errsource,
                     void (*preexec)(void), unsigned int flags,
                     estream_t infp,
                     estream_t *r_outfp,
                     estream_t *r_errfp,
                     pid_t *pid)
{
  gpg_error_t err;
  SECURITY_ATTRIBUTES sec_attr;
  PROCESS_INFORMATION pi =
    {
      NULL,      /* Returns process handle.  */
      0,         /* Returns primary thread handle.  */
      0,         /* Returns pid.  */
      0          /* Returns tid.  */
    };
  STARTUPINFO si;
  int cr_flags;
  char *cmdline;
  HANDLE inhandle = INVALID_HANDLE_VALUE;
  HANDLE outpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
  HANDLE errpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
  estream_t outfp = NULL;
  estream_t errfp = NULL;
  HANDLE nullhd[3] = {INVALID_HANDLE_VALUE,
                      INVALID_HANDLE_VALUE,
                      INVALID_HANDLE_VALUE};
  int i;
  es_syshd_t syshd;

  if (r_outfp)
    *r_outfp = NULL;
  if (r_errfp)
    *r_errfp = NULL;
  *pid = (pid_t)(-1); /* Always required.  */

  if (infp)
    {
      es_fflush (infp);
      es_rewind (infp);
      es_syshd (infp, &syshd);
      switch (syshd.type)
        {
        case ES_SYSHD_FD:
          inhandle = (HANDLE)_get_osfhandle (syshd.u.fd);
          break;
        case ES_SYSHD_SOCK:
          inhandle = (HANDLE)_get_osfhandle (syshd.u.sock);
          break;
        case ES_SYSHD_HANDLE:
          inhandle = syshd.u.handle;
          break;
        default:
          inhandle = INVALID_HANDLE_VALUE;
          break;
        }
      if (inhandle == INVALID_HANDLE_VALUE)
        return gpg_err_make (errsource, GPG_ERR_INV_VALUE);
      /* FIXME: In case we can't get a system handle (e.g. due to
         es_fopencookie we should create a piper and a feeder
         thread.  */
    }

  if (r_outfp)
    {
      if (create_inheritable_pipe (outpipe, 1))
        {
          err = gpg_err_make (errsource, GPG_ERR_GENERAL);
          log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
          return err;
        }

      syshd.type = ES_SYSHD_HANDLE;
      syshd.u.handle = outpipe[0];
      outfp = es_sysopen (&syshd, "r");
      if (!outfp)
        {
          err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
          log_error (_("error creating a stream for a pipe: %s\n"),
                     gpg_strerror (err));
          CloseHandle (outpipe[0]);
          CloseHandle (outpipe[1]);
          outpipe[0] = outpipe[1] = INVALID_HANDLE_VALUE;
          return err;
        }
    }

  if (r_errfp)
    {
      if (create_inheritable_pipe (errpipe, 1))
        {
          err = gpg_err_make (errsource, GPG_ERR_GENERAL);
          log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
          return err;
        }

      syshd.type = ES_SYSHD_HANDLE;
      syshd.u.handle = errpipe[0];
      errfp = es_sysopen (&syshd, "r");
      if (!errfp)
        {
          err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
          log_error (_("error creating a stream for a pipe: %s\n"),
                     gpg_strerror (err));
          CloseHandle (errpipe[0]);
          CloseHandle (errpipe[1]);
          errpipe[0] = errpipe[1] = INVALID_HANDLE_VALUE;
          if (outfp)
            es_fclose (outfp);
          else if (outpipe[0] != INVALID_HANDLE_VALUE)
            CloseHandle (outpipe[0]);
          if (outpipe[1] != INVALID_HANDLE_VALUE)
            CloseHandle (outpipe[1]);
          return err;
        }
    }

  /* Prepare security attributes.  */
  memset (&sec_attr, 0, sizeof sec_attr );
  sec_attr.nLength = sizeof sec_attr;
  sec_attr.bInheritHandle = FALSE;

  /* Build the command line.  */
  err = build_w32_commandline (pgmname, argv, &cmdline);
  if (err)
    return err;

  if (inhandle != INVALID_HANDLE_VALUE)
    nullhd[0] = w32_open_null (0);
  if (outpipe[1] != INVALID_HANDLE_VALUE)
    nullhd[1] = w32_open_null (0);
  if (errpipe[1] != INVALID_HANDLE_VALUE)
    nullhd[2] = w32_open_null (0);

  /* Start the process.  Note that we can't run the PREEXEC function
     because this might change our own environment. */
  (void)preexec;

  memset (&si, 0, sizeof si);
  si.cb = sizeof (si);
  si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
  si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
  si.hStdInput  =   inhandle == INVALID_HANDLE_VALUE? nullhd[0] : inhandle;
  si.hStdOutput = outpipe[1] == INVALID_HANDLE_VALUE? nullhd[1] : outpipe[1];
  si.hStdError  = errpipe[1] == INVALID_HANDLE_VALUE? nullhd[2] : errpipe[1];

  cr_flags = (CREATE_DEFAULT_ERROR_MODE
              | ((flags & 128)? DETACHED_PROCESS : 0)
              | GetPriorityClass (GetCurrentProcess ())
              | CREATE_SUSPENDED);
/*   log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); */
  if (!CreateProcess (pgmname,       /* Program to start.  */
                      cmdline,       /* Command line arguments.  */
                      &sec_attr,     /* Process security attributes.  */
                      &sec_attr,     /* Thread security attributes.  */
                      TRUE,          /* Inherit handles.  */
                      cr_flags,      /* Creation flags.  */
                      NULL,          /* Environment.  */
                      NULL,          /* Use current drive/directory.  */
                      &si,           /* Startup information. */
                      &pi            /* Returns process information.  */
                      ))
    {
      log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
      xfree (cmdline);
      if (outfp)
        es_fclose (outfp);
      else if (outpipe[0] != INVALID_HANDLE_VALUE)
        CloseHandle (outpipe[0]);
      if (outpipe[1] != INVALID_HANDLE_VALUE)
        CloseHandle (outpipe[1]);
      if (errfp)
        es_fclose (errfp);
      else if (errpipe[0] != INVALID_HANDLE_VALUE)
        CloseHandle (errpipe[0]);
      if (errpipe[1] != INVALID_HANDLE_VALUE)
        CloseHandle (errpipe[1]);
      return gpg_err_make (errsource, GPG_ERR_GENERAL);
    }
  xfree (cmdline);
  cmdline = NULL;

  /* Close the inherited handles to /dev/null.  */
  for (i=0; i < DIM (nullhd); i++)
    if (nullhd[i] != INVALID_HANDLE_VALUE)
      CloseHandle (nullhd[i]);

  /* Close the inherited ends of the pipes.  */
  if (outpipe[1] != INVALID_HANDLE_VALUE)
    CloseHandle (outpipe[1]);
  if (errpipe[1] != INVALID_HANDLE_VALUE)
    CloseHandle (errpipe[1]);

  /* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
  /*            " dwProcessID=%d dwThreadId=%d\n", */
  /*            pi.hProcess, pi.hThread, */
  /*            (int) pi.dwProcessId, (int) pi.dwThreadId); */
  /* log_debug ("                     outfp=%p errfp=%p\n", outfp, errfp); */

  /* Fixme: For unknown reasons AllowSetForegroundWindow returns an
     invalid argument error if we pass it the correct processID.  As a
     workaround we use -1 (ASFW_ANY).  */
  if ( (flags & 64) )
    gnupg_allow_set_foregound_window ((pid_t)(-1)/*pi.dwProcessId*/);

  /* Process has been created suspended; resume it now. */
  ResumeThread (pi.hThread);
  CloseHandle (pi.hThread);

  if (r_outfp)
    *r_outfp = outfp;
  if (r_errfp)
    *r_errfp = errfp;

  *pid = handle_to_pid (pi.hProcess);
  return 0;

}
コード例 #6
0
ファイル: system-w32.c プロジェクト: gpg/libassuan
int
__assuan_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
                const char **argv,
                assuan_fd_t fd_in, assuan_fd_t fd_out,
                assuan_fd_t *fd_child_list,
                void (*atfork) (void *opaque, int reserved),
                void *atforkvalue, unsigned int flags)
{
    SECURITY_ATTRIBUTES sec_attr;
    PROCESS_INFORMATION pi =
    {
        NULL,      /* Returns process handle.  */
        0,         /* Returns primary thread handle.  */
        0,         /* Returns pid.  */
        0          /* Returns tid.  */
    };
    STARTUPINFO si;
    assuan_fd_t fd;
    assuan_fd_t *fdp;
    char *cmdline;
    HANDLE nullfd = INVALID_HANDLE_VALUE;

    /* fixme: Actually we should set the "_assuan_pipe_connect_pid" env
       variable.  However this requires us to write a full environment
       handler, because the strings are expected in sorted order.  The
       suggestion given in the MS Reference Library, to save the old
       value, change it, create process and restore it, is not thread
       safe.  */

    /* Build the command line.  */
    if (build_w32_commandline (ctx, argv, &cmdline))
        return -1;

    /* Start the process.  */
    memset (&sec_attr, 0, sizeof sec_attr);
    sec_attr.nLength = sizeof sec_attr;
    sec_attr.bInheritHandle = FALSE;

    memset (&si, 0, sizeof si);
    si.cb = sizeof (si);
    si.dwFlags = STARTF_USESTDHANDLES;
    /* FIXME: Dup to nul if ASSUAN_INVALID_FD.  */
    si.hStdInput  = fd_in;
    si.hStdOutput = fd_out;

    /* Dup stderr to /dev/null unless it is in the list of FDs to be
       passed to the child. */
    fd = assuan_fd_from_posix_fd (fileno (stderr));
    fdp = fd_child_list;
    if (fdp)
    {
        for (; *fdp != ASSUAN_INVALID_FD && *fdp != fd; fdp++)
            ;
    }
    if (!fdp || *fdp == ASSUAN_INVALID_FD)
    {
        nullfd = CreateFileW (L"nul", GENERIC_WRITE,
                              FILE_SHARE_READ | FILE_SHARE_WRITE,
                              NULL, OPEN_EXISTING, 0, NULL);
        if (nullfd == INVALID_HANDLE_VALUE)
        {
            TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
                    "can't open `nul': %s", _assuan_w32_strerror (ctx, -1));
            _assuan_free (ctx, cmdline);
            gpg_err_set_errno (EIO);
            return -1;
        }
        si.hStdError = nullfd;
    }
    else
        si.hStdError = fd;

    /* Note: We inherit all handles flagged as inheritable.  This seems
       to be a security flaw but there seems to be no way of selecting
       handles to inherit.  A fix for this would be to use a helper
       process like we have in gpgme.  */
    /*   _assuan_log_printf ("CreateProcess, path=`%s' cmdline=`%s'\n", */
    /*                       name, cmdline); */
    if (!CreateProcess (name,                 /* Program to start.  */
                        cmdline,              /* Command line arguments.  */
                        &sec_attr,            /* Process security attributes.  */
                        &sec_attr,            /* Thread security attributes.  */
                        TRUE,                 /* Inherit handles.  */
                        (CREATE_DEFAULT_ERROR_MODE
                         | ((flags & 128)? DETACHED_PROCESS : 0)
                         | GetPriorityClass (GetCurrentProcess ())
                         | CREATE_SUSPENDED), /* Creation flags.  */
                        NULL,                 /* Environment.  */
                        NULL,                 /* Use current drive/directory.  */
                        &si,                  /* Startup information. */
                        &pi                   /* Returns process information.  */
                       ))
    {
        TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_w32", ctx,
                "CreateProcess failed: %s", _assuan_w32_strerror (ctx, -1));
        _assuan_free (ctx, cmdline);
        if (nullfd != INVALID_HANDLE_VALUE)
            CloseHandle (nullfd);

        gpg_err_set_errno (EIO);
        return -1;
    }

    _assuan_free (ctx, cmdline);
    if (nullfd != INVALID_HANDLE_VALUE)
        CloseHandle (nullfd);

    ResumeThread (pi.hThread);
    CloseHandle (pi.hThread);

    /*   _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" */
    /*                       " dwProcessID=%d dwThreadId=%d\n", */
    /*                       pi.hProcess, pi.hThread, */
    /*                       (int) pi.dwProcessId, (int) pi.dwThreadId); */

    *r_pid = (pid_t) pi.hProcess;

    /* No need to modify peer process, as we don't change the handle
       names.  However this also means we are not safe, as we inherit
       too many handles.  Should use approach similar to gpgme and glib
       using a helper process.  */

    return 0;
}
コード例 #7
0
ファイル: exechelp-w32ce.c プロジェクト: Domikk/gnupg
/* Fork and exec the PGMNAME, see exechelp.h for details.  */
gpg_error_t
gnupg_spawn_process (const char *pgmname, const char *argv[],
                     gpg_err_source_t errsource,
                     void (*preexec)(void), unsigned int flags,
                     estream_t infp,
                     estream_t *r_outfp,
                     estream_t *r_errfp,
                     pid_t *pid)
{
  gpg_error_t err;
  PROCESS_INFORMATION pi = {NULL };
  char *cmdline;
  es_syshd_t syshd;
  struct {
    HANDLE hd;
    int rvid;
  } inpipe = {INVALID_HANDLE_VALUE, 0};
  struct {
    HANDLE hd;
    int rvid;
  } outpipe = {INVALID_HANDLE_VALUE, 0};
  struct {
    HANDLE hd;
    int rvid;
  } errpipe = {INVALID_HANDLE_VALUE, 0};
  estream_t outfp = NULL;
  estream_t errfp = NULL;

  (void)preexec;
  (void)flags;

  /* Setup return values.  */
  if (r_outfp)
    *r_outfp = NULL;
  if (r_errfp)
    *r_errfp = NULL;
  *pid = (pid_t)(-1); /* Always required.  */

  log_debug ("%s: enter\n", __func__);
  if (infp)
    {
      es_fflush (infp);
      es_rewind (infp);

      /* Create a pipe to copy our infile to the stdin of the child
         process.  On success inpipe.hd is owned by the feeder.  */
      inpipe.hd = _assuan_w32ce_prepare_pipe (&inpipe.rvid, 1);
      if (inpipe.hd == INVALID_HANDLE_VALUE)
        {
          log_error ("_assuan_w32ce_prepare_pipe failed: %s\n",
                     w32_strerror (-1));
          gpg_err_set_errno (EIO);
          return gpg_error_from_syserror ();
        }
      log_debug ("%s: inpipe %p created; hd=%p rvid=%d\n", __func__,
                 infp, inpipe.hd, inpipe.rvid);
      err = start_feeder (infp, inpipe.hd, 1);
      if (err)
        {
          log_error ("error spawning feeder: %s\n", gpg_strerror (err));
          CloseHandle (inpipe.hd);
          return err;
        }
      inpipe.hd = INVALID_HANDLE_VALUE; /* Now owned by the feeder.  */
      log_debug ("%s: inpipe %p created; feeder started\n", __func__,
                 infp);
    }

  if (r_outfp)
    {
      /* Create a pipe to make the stdout of the child process
         available as a stream.  */
      outpipe.hd = _assuan_w32ce_prepare_pipe (&outpipe.rvid, 0);
      if (outpipe.hd == INVALID_HANDLE_VALUE)
        {
          log_error ("_assuan_w32ce_prepare_pipe failed: %s\n",
                     w32_strerror (-1));
          gpg_err_set_errno (EIO);
          /* Fixme release other stuff/kill feeder.  */
          return gpg_error_from_syserror ();
        }
      syshd.type = ES_SYSHD_HANDLE;
      syshd.u.handle = outpipe.hd;
      err = 0;
      outfp = es_sysopen (&syshd, "r");
      if (!outfp)
        {
          err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
          log_error ("error opening pipe stream: %s\n", gpg_strerror (err));
          CloseHandle (outpipe.hd);
          return err;
        }
      log_debug ("%s: outpipe %p created; hd=%p rvid=%d\n", __func__,
                 outfp, outpipe.hd, outpipe.rvid);
      outpipe.hd = INVALID_HANDLE_VALUE; /* Now owned by the OUTFP.  */
    }

  if (r_errfp)
    {
      /* Create a pipe to make the stderr of the child process
         available as a stream.  */
      errpipe.hd = _assuan_w32ce_prepare_pipe (&errpipe.rvid, 0);
      if (errpipe.hd == INVALID_HANDLE_VALUE)
        {
          log_error ("_assuan_w32ce_prepare_pipe failed: %s\n",
                     w32_strerror (-1));
          gpg_err_set_errno (EIO);
          /* Fixme release other stuff/kill feeder.  */
          return gpg_error_from_syserror ();
        }
      syshd.type = ES_SYSHD_HANDLE;
      syshd.u.handle = errpipe.hd;
      err = 0;
      errfp = es_sysopen (&syshd, "r");
      if (!errfp)
        {
          err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
          log_error ("error opening pipe stream: %s\n", gpg_strerror (err));
          CloseHandle (errpipe.hd);
          return err;
        }
      log_debug ("%s: errpipe %p created; hd=%p rvid=%d\n", __func__,
                 errfp, errpipe.hd, errpipe.rvid);
      errpipe.hd = INVALID_HANDLE_VALUE; /* Now owned by the ERRFP.  */
    }



  /* Build the command line.  */
  err = build_w32_commandline (argv, inpipe.rvid, outpipe.rvid, errpipe.rvid,
                               &cmdline);
  if (err)
    {
      /* Fixme release other stuff/kill feeder.  */
      CloseHandle (errpipe.hd);
      return err;
    }

  log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline);
  if (!create_process (pgmname, cmdline, &pi))
    {
      log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
      xfree (cmdline);
      /* Fixme release other stuff/kill feeder.  */
      CloseHandle (errpipe.hd);
      return gpg_error (GPG_ERR_GENERAL);
    }
  xfree (cmdline);
  cmdline = NULL;

  /* Note: The other end of the pipe is a rendezvous id and thus there
     is no need for a close.  */

  log_debug ("CreateProcess ready: hProcess=%p hThread=%p"
             " dwProcessID=%d dwThreadId=%d\n",
             pi.hProcess, pi.hThread,
             (int) pi.dwProcessId, (int) pi.dwThreadId);


  /* Process has been created suspended; resume it now. */
  ResumeThread (pi.hThread);
  CloseHandle (pi.hThread);

  if (r_outfp)
    *r_outfp = outfp;
  if (r_errfp)
    *r_errfp = errfp;
  *pid = handle_to_pid (pi.hProcess);
  return 0;
}
コード例 #8
0
ファイル: system-w32ce.c プロジェクト: GroovIM/transport
int
__assuan_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
		const char **argv,
		assuan_fd_t fd_in, assuan_fd_t fd_out,
		assuan_fd_t *fd_child_list,
		void (*atfork) (void *opaque, int reserved),
		void *atforkvalue, unsigned int flags)
{
  PROCESS_INFORMATION pi = 
    {
      NULL,      /* Returns process handle.  */
      0,         /* Returns primary thread handle.  */
      0,         /* Returns pid.  */
      0          /* Returns tid.  */
    };
  assuan_fd_t fd;
  assuan_fd_t *fdp;
  assuan_fd_t fd_err;
  int fd_err_isnull = 0;
  char *cmdline;

  /* Dup stderr to /dev/null unless it is in the list of FDs to be
     passed to the child.  Well we don't actually open nul because
     that is not available on Windows, but use our hack for it.
     Because an RVID of 0 is an invalid value and HANDLES will never
     have this value either, we test for this as well.  */

  /* FIXME: As long as we can't decide whether a handle is a real
     handler or an rendezvous id we can't do anything with the
     FD_CHILD_LIST.  We can't do much with stderr either, thus we
     better don't pass stderr to the child at all.  If we would do so
     and it is not a rendezvous id the client would run into
     problems.  */
  fd = assuan_fd_from_posix_fd (fileno (stderr));
  fdp = fd_child_list;
  if (fdp)
    {
      for (; *fdp != ASSUAN_INVALID_FD && *fdp != 0 && *fdp != fd; fdp++)
        ;
    }
  if (!fdp || *fdp == ASSUAN_INVALID_FD)
    fd_err_isnull = 1;
  fd_err = ASSUAN_INVALID_FD;

  if (build_w32_commandline (ctx, argv, fd_in, fd_out, fd_err, fd_err_isnull,
                             &cmdline))
    {
      return -1;
    }

  TRACE2 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
          "path=`%s' cmdline=`%s'", name, cmdline);

  {
    wchar_t *wcmdline, *wname;

    wcmdline = utf8_to_wchar (cmdline);
    _assuan_free (ctx, cmdline);
    if (!wcmdline)
      return -1;

    wname = utf8_to_wchar (name);
    if (!wname)
      {
        free_wchar (wcmdline);
        return -1;
      }
    
    if (!CreateProcess (wname,                /* Program to start.  */
                        wcmdline,             /* Command line arguments.  */
                        NULL,                 /* (not supported)  */
                        NULL,                 /* (not supported)  */
                        FALSE,                /* (not supported)  */
                        (CREATE_SUSPENDED),   /* Creation flags.  */
                        NULL,                 /* (not supported)  */
                        NULL,                 /* (not supported)  */
                        NULL,                 /* (not supported) */
                        &pi                   /* Returns process information.*/
                        ))
      {
        TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
                "CreateProcess failed: %s", _assuan_w32_strerror (ctx, -1));
        free_wchar (wname);
        free_wchar (wcmdline);
        gpg_err_set_errno (EIO);
        return -1;
      }
    free_wchar (wname);
    free_wchar (wcmdline);
  }

  ResumeThread (pi.hThread);

  TRACE4 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
          "CreateProcess ready: hProcess=%p hThread=%p"
          " dwProcessID=%d dwThreadId=%d\n",
          pi.hProcess, pi.hThread, (int) pi.dwProcessId, (int) pi.dwThreadId);

  CloseHandle (pi.hThread); 
  
  *r_pid = (pid_t) pi.hProcess;
  return 0;
}
コード例 #9
0
ファイル: kleowrap.c プロジェクト: tuvell/gpg4win
int
spawn_process_and_wait (const char *pgmname, const char * const *argv)
{
  int err;
  SECURITY_ATTRIBUTES sec_attr;
  PROCESS_INFORMATION pi = 
    {
      NULL,      /* Returns process handle.  */
      0,         /* Returns primary thread handle.  */
      0,         /* Returns pid.  */
      0          /* Returns tid.  */
    };
  STARTUPINFO si;
  int cr_flags;
  char *cmdline;
  HANDLE proc;
  int code;
  DWORD exc;

  /* Prepare security attributes.  */
  memset (&sec_attr, 0, sizeof sec_attr);
  sec_attr.nLength = sizeof sec_attr;
  sec_attr.bInheritHandle = FALSE;
  
  /* Build the command line.  */
  cmdline = build_w32_commandline (pgmname, argv);
  if (! cmdline)
    return -1; 

  /* Start the process.  Note that we can't run the PREEXEC function
     because this would change our own environment. */
  memset (&si, 0, sizeof si);
  si.cb = sizeof (si);
  si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
  si.wShowWindow = DEBUG_W32_SPAWN ? SW_SHOW : SW_MINIMIZE;
  si.hStdInput = w32_open_null (0);
  si.hStdOutput = w32_open_null (1);
  si.hStdError = w32_open_null (1);

  cr_flags = (CREATE_DEFAULT_ERROR_MODE
              | DETACHED_PROCESS
              | GetPriorityClass (GetCurrentProcess ())
              | CREATE_SUSPENDED); 
  if (!CreateProcess (pgmname,       /* Program to start.  */
                      cmdline,       /* Command line arguments.  */
                      &sec_attr,     /* Process security attributes.  */
                      &sec_attr,     /* Thread security attributes.  */
                      TRUE,          /* Inherit handles.  */
                      cr_flags,      /* Creation flags.  */
                      NULL,          /* Environment.  */
                      NULL,          /* Use current drive/directory.  */
                      &si,           /* Startup information. */
                      &pi            /* Returns process information.  */
                      ))
    {
      free (cmdline);
      CloseHandle (si.hStdInput);
      CloseHandle (si.hStdOutput);
      CloseHandle (si.hStdError);
      return -1;
    }
  free (cmdline);
  cmdline = NULL;

  /* Process has been created suspended; resume it now. */
  ResumeThread (pi.hThread);
  CloseHandle (pi.hThread); 

  /* Wait for it to finish.  */

  proc = pi.hProcess;
  err = 0;

  code = WaitForSingleObject (proc, INFINITE);
  switch (code) 
    {
      case WAIT_OBJECT_0:
        if (! GetExitCodeProcess (proc, &exc))
	  err = -1;
	else
	  err = exc;
	break;

      default:
	err = -1;
        break;
    }

  CloseHandle (proc);

  return err;
}