Blame src/gpgme-w32spawn.c

Packit Service 672cf4
/* gpgme-w32spawn.c - Wrapper to spawn a process under Windows.
Packit Service 0ef63b
 * Copyright (C) 2008 g10 Code GmbH
Packit Service 0ef63b
 *
Packit Service 0ef63b
 * This file is part of GPGME.
Packit Service 0ef63b
 *
Packit Service 0ef63b
 * GPGME is free software; you can redistribute it and/or modify it
Packit Service 0ef63b
 * under the terms of the GNU Lesser General Public License as
Packit Service 0ef63b
 * published by the Free Software Foundation; either version 2.1 of
Packit Service 0ef63b
 * the License, or (at your option) any later version.
Packit Service 0ef63b
 *
Packit Service 0ef63b
 * GPGME is distributed in the hope that it will be useful, but
Packit Service 0ef63b
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 0ef63b
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 0ef63b
 * Lesser General Public License for more details.
Packit Service 0ef63b
 *
Packit Service 0ef63b
 * You should have received a copy of the GNU Lesser General Public
Packit Service 0ef63b
 * License along with this program; if not, see <https://gnu.org/licenses/>.
Packit Service 0ef63b
 * SPDX-License-Identifier: LGPL-2.1-or-later
Packit Service 672cf4
 */
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
#ifdef HAVE_CONFIG_H
Packit Service 672cf4
# include <config.h>
Packit Service 672cf4
#endif
Packit Service 672cf4
Packit Service 672cf4
#include <errno.h>
Packit Service 672cf4
#include <stdio.h>
Packit Service 672cf4
#include <stdlib.h>
Packit Service 672cf4
#include <fcntl.h>
Packit Service 672cf4
#include <ctype.h>
Packit Service 672cf4
#include <string.h>
Packit Service 672cf4
#ifdef HAVE_SYS_TYPES_H
Packit Service 672cf4
# include <sys/types.h>
Packit Service 672cf4
#endif
Packit Service 672cf4
#ifdef HAVE_SYS_STAT_H
Packit Service 672cf4
# include <sys/stat.h>
Packit Service 672cf4
#endif
Packit Service 672cf4
#include <stdint.h>
Packit Service 672cf4
#include <process.h>
Packit Service 672cf4
Packit Service 672cf4
#include "priv-io.h"
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
/* Name of this program.  */
Packit Service 672cf4
#define PGM "gpgme-w32spawn"
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4

Packit Service 672cf4
static char *
Packit Service 672cf4
build_commandline (char **argv)
Packit Service 672cf4
{
Packit Service 672cf4
  int i;
Packit Service 672cf4
  int n = 0;
Packit Service 672cf4
  char *buf;
Packit Service 672cf4
  char *p;
Packit Service 672cf4
Packit Service 672cf4
  /* We have to quote some things because under Windows the program
Packit Service 672cf4
     parses the commandline and does some unquoting.  We enclose the
Packit Service 672cf4
     whole argument in double-quotes, and escape literal double-quotes
Packit Service 672cf4
     as well as backslashes with a backslash.  We end up with a
Packit Service 672cf4
     trailing space at the end of the line, but that is harmless.  */
Packit Service 672cf4
  for (i = 0; argv[i]; i++)
Packit Service 672cf4
    {
Packit Service 672cf4
      p = argv[i];
Packit Service 672cf4
      /* The leading double-quote.  */
Packit Service 672cf4
      n++;
Packit Service 672cf4
      while (*p)
Packit Service 672cf4
	{
Packit Service 672cf4
	  /* An extra one for each literal that must be escaped.  */
Packit Service 672cf4
	  if (*p == '\\' || *p == '"')
Packit Service 672cf4
	    n++;
Packit Service 672cf4
	  n++;
Packit Service 672cf4
	  p++;
Packit Service 672cf4
	}
Packit Service 672cf4
      /* The trailing double-quote and the delimiter.  */
Packit Service 672cf4
      n += 2;
Packit Service 672cf4
    }
Packit Service 672cf4
  /* And a trailing zero.  */
Packit Service 672cf4
  n++;
Packit Service 672cf4
Packit Service 672cf4
  buf = p = malloc (n);
Packit Service 672cf4
  if (!buf)
Packit Service 672cf4
    return NULL;
Packit Service 672cf4
  for (i = 0; argv[i]; i++)
Packit Service 672cf4
    {
Packit Service 672cf4
      char *argvp = argv[i];
Packit Service 672cf4
Packit Service 672cf4
      *(p++) = '"';
Packit Service 672cf4
      while (*argvp)
Packit Service 672cf4
	{
Packit Service 672cf4
	  if (*argvp == '\\' || *argvp == '"')
Packit Service 672cf4
	    *(p++) = '\\';
Packit Service 672cf4
	  *(p++) = *(argvp++);
Packit Service 672cf4
	}
Packit Service 672cf4
      *(p++) = '"';
Packit Service 672cf4
      *(p++) = ' ';
Packit Service 672cf4
    }
Packit Service 672cf4
  *(p++) = 0;
Packit Service 672cf4
Packit Service 672cf4
  return buf;
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
int
Packit Service 672cf4
my_spawn (char **argv, struct spawn_fd_item_s *fd_list, unsigned int flags)
Packit Service 672cf4
{
Packit Service 672cf4
  SECURITY_ATTRIBUTES sec_attr;
Packit Service 672cf4
  PROCESS_INFORMATION pi =
Packit Service 672cf4
    {
Packit Service 672cf4
      NULL,      /* returns process handle */
Packit Service 672cf4
      0,         /* returns primary thread handle */
Packit Service 672cf4
      0,         /* returns pid */
Packit Service 672cf4
      0          /* returns tid */
Packit Service 672cf4
    };
Packit Service 672cf4
  STARTUPINFO si;
Packit Service 672cf4
  char *envblock = NULL;
Packit Service 672cf4
  int cr_flags = CREATE_DEFAULT_ERROR_MODE
Packit Service 672cf4
    | GetPriorityClass (GetCurrentProcess ());
Packit Service 672cf4
  int i;
Packit Service 672cf4
  char *arg_string;
Packit Service 672cf4
  int duped_stdin = 0;
Packit Service 672cf4
  int duped_stdout = 0;
Packit Service 672cf4
  int duped_stderr = 0;
Packit Service 672cf4
  HANDLE hnul = INVALID_HANDLE_VALUE;
Packit Service 672cf4
Packit Service 672cf4
  i = 0;
Packit Service 672cf4
  while (argv[i])
Packit Service 672cf4
    {
Packit Service 672cf4
      fprintf (stderr, PGM": argv[%2i] = %s\n", i, argv[i]);
Packit Service 672cf4
      i++;
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  memset (&sec_attr, 0, sizeof sec_attr);
Packit Service 672cf4
  sec_attr.nLength = sizeof sec_attr;
Packit Service 672cf4
  sec_attr.bInheritHandle = FALSE;
Packit Service 672cf4
Packit Service 672cf4
  arg_string = build_commandline (argv);
Packit Service 672cf4
  if (!arg_string)
Packit Service 672cf4
    return -1;
Packit Service 672cf4
Packit Service 672cf4
  memset (&si, 0, sizeof si);
Packit Service 672cf4
  si.cb = sizeof (si);
Packit Service 672cf4
  si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
Packit Service 0ef63b
  si.wShowWindow = (flags & IOSPAWN_FLAG_SHOW_WINDOW) ? SW_SHOW : SW_HIDE;
Packit Service 672cf4
  si.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
Packit Service 672cf4
  si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
Packit Service 672cf4
  si.hStdError = GetStdHandle (STD_ERROR_HANDLE);
Packit Service 672cf4
Packit Service 672cf4
  fprintf (stderr, PGM": spawning: %s\n", arg_string);
Packit Service 672cf4
Packit Service 672cf4
  for (i = 0; fd_list[i].fd != -1; i++)
Packit Service 672cf4
    {
Packit Service 672cf4
      /* The handle already is inheritable.  */
Packit Service 672cf4
      if (fd_list[i].dup_to == 0)
Packit Service 672cf4
	{
Packit Service 672cf4
	  si.hStdInput = (HANDLE) fd_list[i].peer_name;
Packit Service 672cf4
	  duped_stdin = 1;
Packit Service 672cf4
	  fprintf (stderr, PGM": dup 0x%x to stdin\n", fd_list[i].peer_name);
Packit Service 672cf4
        }
Packit Service 672cf4
      else if (fd_list[i].dup_to == 1)
Packit Service 672cf4
	{
Packit Service 672cf4
	  si.hStdOutput = (HANDLE) fd_list[i].peer_name;
Packit Service 672cf4
	  duped_stdout = 1;
Packit Service 672cf4
	  fprintf (stderr, PGM": dup 0x%x to stdout\n", fd_list[i].peer_name);
Packit Service 672cf4
        }
Packit Service 672cf4
      else if (fd_list[i].dup_to == 2)
Packit Service 672cf4
	{
Packit Service 672cf4
	  si.hStdError = (HANDLE) fd_list[i].peer_name;
Packit Service 672cf4
	  duped_stderr = 1;
Packit Service 672cf4
	  fprintf (stderr, PGM":dup 0x%x to stderr\n", fd_list[i].peer_name);
Packit Service 672cf4
        }
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  if (!duped_stdin || !duped_stdout || !duped_stderr)
Packit Service 672cf4
    {
Packit Service 672cf4
      SECURITY_ATTRIBUTES sa;
Packit Service 672cf4
Packit Service 672cf4
      memset (&sa, 0, sizeof sa);
Packit Service 672cf4
      sa.nLength = sizeof sa;
Packit Service 672cf4
      sa.bInheritHandle = TRUE;
Packit Service 672cf4
      hnul = CreateFile ("nul",
Packit Service 672cf4
			 GENERIC_READ|GENERIC_WRITE,
Packit Service 672cf4
			 FILE_SHARE_READ|FILE_SHARE_WRITE,
Packit Service 672cf4
			 &sa,
Packit Service 672cf4
			 OPEN_EXISTING,
Packit Service 672cf4
			 FILE_ATTRIBUTE_NORMAL,
Packit Service 672cf4
			 NULL);
Packit Service 672cf4
      if (hnul == INVALID_HANDLE_VALUE)
Packit Service 672cf4
	{
Packit Service 672cf4
	  free (arg_string);
Packit Service 672cf4
	  /* FIXME: Should translate the error code.  */
Packit Service 672cf4
	  errno = EIO;
Packit Service 672cf4
	  return -1;
Packit Service 672cf4
        }
Packit Service 672cf4
      /* Make sure that the process has a connected stdin.  */
Packit Service 672cf4
      if (!duped_stdin)
Packit Service 672cf4
	si.hStdInput = hnul;
Packit Service 672cf4
      /* Make sure that the process has a connected stdout.  */
Packit Service 672cf4
      if (!duped_stdout)
Packit Service 672cf4
	si.hStdOutput = hnul;
Packit Service 672cf4
      /* We normally don't want all the normal output.  */
Packit Service 672cf4
      if (!duped_stderr)
Packit Service 672cf4
	si.hStdError = hnul;
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  cr_flags |= CREATE_SUSPENDED;
Packit Service 672cf4
  if (!CreateProcessA (argv[0],
Packit Service 672cf4
		       arg_string,
Packit Service 672cf4
		       &sec_attr,     /* process security attributes */
Packit Service 672cf4
		       &sec_attr,     /* thread security attributes */
Packit Service 672cf4
		       TRUE,          /* inherit handles */
Packit Service 672cf4
		       cr_flags,      /* creation flags */
Packit Service 672cf4
		       envblock,      /* environment */
Packit Service 672cf4
		       NULL,          /* use current drive/directory */
Packit Service 672cf4
		       &si,           /* startup information */
Packit Service 672cf4
		       &pi))          /* returns process information */
Packit Service 672cf4
    {
Packit Service 672cf4
      free (arg_string);
Packit Service 672cf4
      /* FIXME: Should translate the error code.  */
Packit Service 672cf4
      errno = EIO;
Packit Service 672cf4
      return -1;
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  free (arg_string);
Packit Service 672cf4
Packit Service 672cf4
  /* Close the /dev/nul handle if used.  */
Packit Service 672cf4
  if (hnul != INVALID_HANDLE_VALUE)
Packit Service 672cf4
    CloseHandle (hnul);
Packit Service 672cf4
Packit Service 672cf4
  for (i = 0; fd_list[i].fd != -1; i++)
Packit Service 672cf4
    CloseHandle ((HANDLE) fd_list[i].fd);
Packit Service 672cf4
Packit Service 672cf4
  if (flags & IOSPAWN_FLAG_ALLOW_SET_FG)
Packit Service 672cf4
    {
Packit Service 672cf4
      static int initialized;
Packit Service 672cf4
      static BOOL (WINAPI * func)(DWORD);
Packit Service 672cf4
      void *handle;
Packit Service 672cf4
Packit Service 672cf4
      if (!initialized)
Packit Service 672cf4
        {
Packit Service 672cf4
          /* Available since W2000; thus we dynload it.  */
Packit Service 672cf4
          initialized = 1;
Packit Service 672cf4
          handle = LoadLibrary ("user32.dll");
Packit Service 672cf4
          if (handle)
Packit Service 672cf4
            {
Packit Service 672cf4
              func = GetProcAddress (handle, "AllowSetForegroundWindow");
Packit Service 672cf4
              if (!func)
Packit Service 672cf4
                FreeLibrary (handle);
Packit Service 672cf4
            }
Packit Service 672cf4
        }
Packit Service 672cf4
Packit Service 672cf4
      if (func)
Packit Service 672cf4
        {
Packit Service 672cf4
          int rc = func (pi.dwProcessId);
Packit Service 672cf4
          fprintf (stderr, PGM": AllowSetForegroundWindow(%d): rc=%d\n",
Packit Service 672cf4
                   (int)pi.dwProcessId, rc);
Packit Service 672cf4
        }
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  ResumeThread (pi.hThread);
Packit Service 672cf4
  CloseHandle (pi.hThread);
Packit Service 672cf4
  CloseHandle (pi.hProcess);
Packit Service 672cf4
Packit Service 672cf4
  return 0;
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4

Packit Service 672cf4
#define MAX_TRANS 10
Packit Service 672cf4
Packit Service 672cf4
int
Packit Service 672cf4
translate_get_from_file (const char *trans_file,
Packit Service 672cf4
			 struct spawn_fd_item_s *fd_list,
Packit Service 672cf4
                         unsigned int *r_flags)
Packit Service 672cf4
{
Packit Service 672cf4
  /* Hold roughly MAX_TRANS triplets of 64 bit numbers in hex
Packit Service 672cf4
     notation: "0xFEDCBA9876543210".  10*19*4 - 1 = 759.  This plans
Packit Service 672cf4
     ahead for a time when a HANDLE is 64 bit.  */
Packit Service 672cf4
#define BUFFER_MAX 810
Packit Service 672cf4
Packit Service 672cf4
  char line[BUFFER_MAX + 1];
Packit Service 672cf4
  char *linep;
Packit Service 672cf4
  int idx;
Packit Service 672cf4
  int res;
Packit Service 672cf4
  int fd;
Packit Service 672cf4
Packit Service 672cf4
  *r_flags = 0;
Packit Service 672cf4
Packit Service 672cf4
  fd = open (trans_file, O_RDONLY);
Packit Service 672cf4
  if (fd < 0)
Packit Service 672cf4
    return -1;
Packit Service 672cf4
Packit Service 672cf4
  /* We always read one line from stdin.  */
Packit Service 672cf4
  res = read (fd, line, BUFFER_MAX);
Packit Service 672cf4
  close (fd);
Packit Service 672cf4
  if (res < 0)
Packit Service 672cf4
    return -1;
Packit Service 672cf4
Packit Service 672cf4
  line[BUFFER_MAX] = '\0';
Packit Service 672cf4
  linep = strchr (line, '\n');
Packit Service 672cf4
  if (linep)
Packit Service 672cf4
    {
Packit Service 672cf4
      if (linep > line && linep[-1] == '\r')
Packit Service 672cf4
        linep--;
Packit Service 672cf4
      *linep = '\0';
Packit Service 672cf4
    }
Packit Service 672cf4
  linep = line;
Packit Service 672cf4
Packit Service 672cf4
  /* Now start to read mapping pairs.  */
Packit Service 672cf4
  for (idx = 0; idx < MAX_TRANS; idx++)
Packit Service 672cf4
    {
Packit Service 672cf4
      unsigned long from;
Packit Service 672cf4
      long dup_to;
Packit Service 672cf4
      unsigned long to;
Packit Service 672cf4
      unsigned long loc;
Packit Service 672cf4
      char *tail;
Packit Service 672cf4
Packit Service 672cf4
      /* FIXME: Maybe could use scanf.  */
Packit Service 672cf4
      while (isspace (*((unsigned char *)linep)))
Packit Service 672cf4
	linep++;
Packit Service 672cf4
      if (*linep == '\0')
Packit Service 672cf4
	break;
Packit Service 672cf4
      if (!idx && *linep == '~')
Packit Service 672cf4
        {
Packit Service 672cf4
          /* Spawn flags have been passed.  */
Packit Service 672cf4
          linep++;
Packit Service 672cf4
          *r_flags = strtoul (linep, &tail, 0);
Packit Service 672cf4
          if (tail == NULL || ! (*tail == '\0' || isspace (*tail)))
Packit Service 672cf4
            break;
Packit Service 672cf4
          linep = tail;
Packit Service 672cf4
Packit Service 672cf4
          while (isspace (*((unsigned char *)linep)))
Packit Service 672cf4
            linep++;
Packit Service 672cf4
          if (*linep == '\0')
Packit Service 672cf4
            break;
Packit Service 672cf4
        }
Packit Service 672cf4
Packit Service 672cf4
      from = strtoul (linep, &tail, 0);
Packit Service 672cf4
      if (tail == NULL || ! (*tail == '\0' || isspace (*tail)))
Packit Service 672cf4
	break;
Packit Service 672cf4
      linep = tail;
Packit Service 672cf4
Packit Service 672cf4
      while (isspace (*linep))
Packit Service 672cf4
	linep++;
Packit Service 672cf4
      if (*linep == '\0')
Packit Service 672cf4
	break;
Packit Service 672cf4
      dup_to = strtol (linep, &tail, 0);
Packit Service 672cf4
      if (tail == NULL || ! (*tail == '\0' || isspace (*tail)))
Packit Service 672cf4
	break;
Packit Service 672cf4
      linep = tail;
Packit Service 672cf4
Packit Service 672cf4
      while (isspace (*linep))
Packit Service 672cf4
	linep++;
Packit Service 672cf4
      if (*linep == '\0')
Packit Service 672cf4
	break;
Packit Service 672cf4
      to = strtoul (linep, &tail, 0);
Packit Service 672cf4
      if (tail == NULL || ! (*tail == '\0' || isspace (*tail)))
Packit Service 672cf4
	break;
Packit Service 672cf4
      linep = tail;
Packit Service 672cf4
Packit Service 672cf4
      while (isspace (*linep))
Packit Service 672cf4
	linep++;
Packit Service 672cf4
      if (*linep == '\0')
Packit Service 672cf4
	break;
Packit Service 672cf4
      loc = strtoul (linep, &tail, 0);
Packit Service 672cf4
      if (tail == NULL || ! (*tail == '\0' || isspace (*tail)))
Packit Service 672cf4
	break;
Packit Service 672cf4
      linep = tail;
Packit Service 672cf4
Packit Service 672cf4
      fd_list[idx].fd = from;
Packit Service 672cf4
      fd_list[idx].dup_to = dup_to;
Packit Service 672cf4
      fd_list[idx].peer_name = to;
Packit Service 672cf4
      fd_list[idx].arg_loc = loc;
Packit Service 672cf4
    }
Packit Service 672cf4
  fd_list[idx].fd = -1;
Packit Service 672cf4
  fd_list[idx].dup_to = -1;
Packit Service 672cf4
  fd_list[idx].peer_name = -1;
Packit Service 672cf4
  fd_list[idx].arg_loc = 0;
Packit Service 672cf4
  return 0;
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
/* Read the translated handles from TRANS_FILE and do a substitution
Packit Service 672cf4
   in ARGV.  Returns the new argv and the list of substitutions in
Packit Service 672cf4
   FD_LIST (which must be MAX_TRANS+1 large).  */
Packit Service 672cf4
char **
Packit Service 672cf4
translate_handles (const char *trans_file, const char * const *argv,
Packit Service 672cf4
		   struct spawn_fd_item_s *fd_list, unsigned int *r_flags)
Packit Service 672cf4
{
Packit Service 672cf4
  int res;
Packit Service 672cf4
  int idx;
Packit Service 672cf4
  int n_args;
Packit Service 672cf4
  char **args;
Packit Service 672cf4
Packit Service 672cf4
  res = translate_get_from_file (trans_file, fd_list, r_flags);
Packit Service 672cf4
  if (res < 0)
Packit Service 672cf4
    return NULL;
Packit Service 672cf4
Packit Service 672cf4
  for (idx = 0; argv[idx]; idx++)
Packit Service 672cf4
    ;
Packit Service 672cf4
  args = malloc (sizeof (*args) * (idx + 1));
Packit Service 672cf4
  for (idx = 0; argv[idx]; idx++)
Packit Service 672cf4
    {
Packit Service 672cf4
      args[idx] = strdup (argv[idx]);
Packit Service 672cf4
      if (!args[idx])
Packit Service 672cf4
	return NULL;
Packit Service 672cf4
    }
Packit Service 672cf4
  args[idx] = NULL;
Packit Service 672cf4
  n_args = idx;
Packit Service 672cf4
Packit Service 672cf4
  for (idx = 0; fd_list[idx].fd != -1; idx++)
Packit Service 672cf4
    {
Packit Service 672cf4
      char buf[25];
Packit Service 672cf4
      int aidx;
Packit Service 672cf4
Packit Service 672cf4
      aidx = fd_list[idx].arg_loc;
Packit Service 672cf4
      if (aidx == 0)
Packit Service 672cf4
	continue;
Packit Service 672cf4
Packit Service 672cf4
      if (aidx >= n_args)
Packit Service 672cf4
        {
Packit Service 672cf4
	  fprintf (stderr, PGM": translation file does not match args\n");
Packit Service 672cf4
          return NULL;
Packit Service 672cf4
        }
Packit Service 672cf4
Packit Service 672cf4
      args[aidx] = malloc (sizeof (buf));
Packit Service 672cf4
      /* We currently disable translation for stdin/stdout/stderr.  We
Packit Service 672cf4
	 assume that the spawned program handles 0/1/2 specially
Packit Service 672cf4
	 already.  FIXME: Check if this is true.  */
Packit Service 672cf4
      if (!args[idx] || fd_list[idx].dup_to != -1)
Packit Service 672cf4
	return NULL;
Packit Service 672cf4
Packit Service 672cf4
      /* NOTE: Here is the part where application specific knowledge
Packit Service 672cf4
	 comes in.  GPGME/GnuPG uses two forms of descriptor
Packit Service 672cf4
	 specification, a plain number and a "-&" form.  */
Packit Service 672cf4
      if (argv[aidx][0] == '-' && argv[aidx][1] == '&')
Packit Service 672cf4
	snprintf (args[aidx], sizeof (buf), "-&%d", fd_list[idx].peer_name);
Packit Service 672cf4
      else
Packit Service 672cf4
	snprintf (args[aidx], sizeof (buf), "%d", fd_list[idx].peer_name);
Packit Service 672cf4
    }
Packit Service 672cf4
  return args;
Packit Service 672cf4
}
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
int
Packit Service 672cf4
main (int argc, const char * const *argv)
Packit Service 672cf4
{
Packit Service 672cf4
  int rc = 0;
Packit Service 672cf4
  char **argv_spawn;
Packit Service 672cf4
  struct spawn_fd_item_s fd_list[MAX_TRANS + 1];
Packit Service 672cf4
  unsigned int flags;
Packit Service 672cf4
Packit Service 672cf4
  if (argc < 3)
Packit Service 672cf4
    {
Packit Service 672cf4
      rc = 2;
Packit Service 672cf4
      goto leave;
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  argv_spawn = translate_handles (argv[1], &argv[2], fd_list, &flags);
Packit Service 672cf4
  if (!argv_spawn)
Packit Service 672cf4
    {
Packit Service 672cf4
      rc = 2;
Packit Service 672cf4
      goto leave;
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  /* Using execv does not replace the existing program image, but
Packit Service 672cf4
     spawns a new one and daemonizes it, confusing the command line
Packit Service 672cf4
     interpreter.  So we have to use spawnv.  */
Packit Service 672cf4
  rc = my_spawn (argv_spawn, fd_list, flags);
Packit Service 672cf4
  if (rc < 0)
Packit Service 672cf4
    {
Packit Service 672cf4
      fprintf (stderr, PGM": executing `%s' failed: %s\n",
Packit Service 672cf4
	       argv[0], strerror (errno));
Packit Service 672cf4
      rc = 2;
Packit Service 672cf4
      goto leave;
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
 leave:
Packit Service 672cf4
  if (rc)
Packit Service 672cf4
    fprintf (stderr, PGM": internal error\n");
Packit Service 672cf4
  /* Always try to delete the temporary file.  */
Packit Service 672cf4
  if (argc >= 2)
Packit Service 672cf4
    {
Packit Service 672cf4
      if (DeleteFile (argv[1]) == 0)
Packit Service 672cf4
	fprintf (stderr, PGM": failed to delete %s: ec=%ld\n",
Packit Service 672cf4
		 argv[1], GetLastError ());
Packit Service 672cf4
    }
Packit Service 672cf4
  return rc;
Packit Service 672cf4
}