Example #1
0
File: spawn.c Project: gpg/gpgme
static gpgme_error_t
spawn_start (gpgme_ctx_t ctx, int synchronous,
             const char *file, const char *argv[],
             gpgme_data_t datain,
             gpgme_data_t dataout, gpgme_data_t dataerr,
             unsigned int flags)
{
  gpgme_error_t err;
  const char *tmp_argv[2];

  if (ctx->protocol != GPGME_PROTOCOL_SPAWN)
    return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL);

  err = _gpgme_op_reset (ctx, synchronous);
  if (err)
    return err;

  if (!argv)
    {
      tmp_argv[0] = _gpgme_get_basename (file);
      tmp_argv[1] = NULL;
      argv = tmp_argv;
    }

  return _gpgme_engine_op_spawn (ctx->engine, file, argv,
                                 datain, dataout, dataerr, flags);
}
Example #2
0
static gpgme_error_t
engspawn_start (engine_spawn_t esp, const char *file, const char *argv[],
                unsigned int flags)
{
  gpgme_error_t err;
  int i, n;
  int status;
  struct spawn_fd_item_s *fd_list;
  pid_t pid;
  unsigned int spflags;
  const char *save_argv0 = NULL;

  if (!esp || !file || !argv || !argv[0])
    return gpg_error (GPG_ERR_INV_VALUE);

  spflags = 0;
  if ((flags & GPGME_SPAWN_DETACHED))
    spflags |= IOSPAWN_FLAG_DETACHED;
  if ((flags & GPGME_SPAWN_ALLOW_SET_FG))
    spflags |= IOSPAWN_FLAG_ALLOW_SET_FG;


  err = build_fd_data_map (esp);
  if (err)
    return err;

  n = 0;
  for (i = 0; esp->fd_data_map[i].data; i++)
    n++;
  fd_list = calloc (n+1, sizeof *fd_list);
  if (!fd_list)
    return gpg_error_from_syserror ();

  /* Build the fd list for the child.  */
  n = 0;
  for (i = 0; esp->fd_data_map[i].data; i++)
    {
      fd_list[n].fd = esp->fd_data_map[i].peer_fd;
      fd_list[n].dup_to = esp->fd_data_map[i].dup_to;
      n++;
    }
  fd_list[n].fd = -1;
  fd_list[n].dup_to = -1;

  if (argv[0] && !*argv[0])
    {
      save_argv0 = argv[0];
      argv[0] = _gpgme_get_basename (file);
    }
  status = _gpgme_io_spawn (file, (char * const *)argv, spflags,
                            fd_list, NULL, NULL, &pid);
  if (save_argv0)
    argv[0] = save_argv0;
  free (fd_list);
  if (status == -1)
    return gpg_error_from_syserror ();

  for (i = 0; esp->fd_data_map[i].data; i++)
    {
      err = add_io_cb (esp, esp->fd_data_map[i].fd,
                       esp->fd_data_map[i].inbound,
                       esp->fd_data_map[i].inbound
                       ? _gpgme_data_inbound_handler
                       : _gpgme_data_outbound_handler,
                       esp->fd_data_map[i].data, &esp->fd_data_map[i].tag);
      if (err)
        return err;  /* FIXME: kill the child */
    }

  engspawn_io_event (esp, GPGME_EVENT_START, NULL);

  return 0;
}
Example #3
0
static gpgme_error_t
g13_new (void **engine, const char *file_name, const char *home_dir)
{
  gpgme_error_t err = 0;
  engine_g13_t g13;
  const char *pgmname;
  int argc;
  const char *argv[5];
  char *dft_display = NULL;
  char dft_ttyname[64];
  char *dft_ttytype = NULL;
  char *optstr;

  g13 = calloc (1, sizeof *g13);
  if (!g13)
    return gpg_error_from_syserror ();

  g13->status_cb.fd = -1;
  g13->status_cb.dir = 1;
  g13->status_cb.tag = 0;
  g13->status_cb.data = g13;

  pgmname = file_name ? file_name : _gpgme_get_default_g13_name ();
  argc = 0;
  argv[argc++] = _gpgme_get_basename (pgmname);
  if (home_dir)
    {
      argv[argc++] = "--homedir";
      argv[argc++] = home_dir;
    }
  argv[argc++] = "--server";
  argv[argc++] = NULL;

  err = assuan_new_ext (&g13->assuan_ctx, GPG_ERR_SOURCE_GPGME,
			&_gpgme_assuan_malloc_hooks, _gpgme_assuan_log_cb,
			NULL);
  if (err)
    goto leave;
  assuan_ctx_set_system_hooks (g13->assuan_ctx, &_gpgme_assuan_system_hooks);

#if USE_DESCRIPTOR_PASSING
  err = assuan_pipe_connect (g13->assuan_ctx, pgmname, argv,
                             NULL, NULL, NULL, ASSUAN_PIPE_CONNECT_FDPASSING);
#else
  err = assuan_pipe_connect (g13->assuan_ctx, pgmname, argv,
                             NULL, NULL, NULL, 0);
#endif
  if (err)
    goto leave;

  err = _gpgme_getenv ("DISPLAY", &dft_display);
  if (err)
    goto leave;
  if (dft_display)
    {
      if (asprintf (&optstr, "OPTION display=%s", dft_display) < 0)
        {
	  free (dft_display);
	  err = gpg_error_from_syserror ();
	  goto leave;
	}
      free (dft_display);

      err = assuan_transact (g13->assuan_ctx, optstr, NULL, NULL, NULL,
			     NULL, NULL, NULL);
      free (optstr);
      if (err)
	goto leave;
    }

  if (isatty (1))
    {
      int rc;

      rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));

      /* Even though isatty() returns 1, ttyname_r() may fail in many
	 ways, e.g., when /dev/pts is not accessible under chroot.  */
      if (!rc)
	{
	  if (asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0)
	    {
	      err = gpg_error_from_syserror ();
	      goto leave;
	    }
	  err = assuan_transact (g13->assuan_ctx, optstr, NULL, NULL, NULL,
				 NULL, NULL, NULL);
	  free (optstr);
	  if (err)
	    goto leave;

	  err = _gpgme_getenv ("TERM", &dft_ttytype);
	  if (err)
	    goto leave;
	  if (dft_ttytype)
	    {
	      if (asprintf (&optstr, "OPTION ttytype=%s", dft_ttytype) < 0)
		{
		  free (dft_ttytype);
		  err = gpg_error_from_syserror ();
		  goto leave;
		}
	      free (dft_ttytype);

	      err = assuan_transact (g13->assuan_ctx, optstr, NULL, NULL,
				     NULL, NULL, NULL, NULL);
	      free (optstr);
	      if (err)
		goto leave;
	    }
	}
    }

#ifdef HAVE_W32_SYSTEM
  /* Under Windows we need to use AllowSetForegroundWindow.  Tell
     g13 to tell us when it needs it.  */
  if (!err)
    {
      err = assuan_transact (g13->assuan_ctx, "OPTION allow-pinentry-notify",
                             NULL, NULL, NULL, NULL, NULL, NULL);
      if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
        err = 0; /* This is a new feature of g13.  */
    }
#endif /*HAVE_W32_SYSTEM*/

 leave:

  if (err)
    g13_release (g13);
  else
    *engine = g13;

  return err;
}