예제 #1
0
파일: w32-io.c 프로젝트: nobled/gpgme
/* Find a writer context or create a new one.  Note that the writer
   context will last until a _gpgme_io_close.  */
static struct writer_context_s *
find_writer (int fd, int start_it)
{
  struct writer_context_s *wt = NULL;
  int i;

  LOCK (writer_table_lock);
  for (i = 0; i < writer_table_size; i++)
    if (writer_table[i].used && writer_table[i].fd == fd)
      wt = writer_table[i].context;

  if (wt || !start_it)
    {
      UNLOCK (writer_table_lock);
      return wt;
    }

  for (i = 0; i < writer_table_size; i++)
    if (!writer_table[i].used)
      break;

  if (i != writer_table_size)
    {
      wt = create_writer (fd_to_handle (fd));
      if (wt)
	{
	  writer_table[i].fd = fd;
	  writer_table[i].context = wt; 
	  writer_table[i].used = 1;
	}
    }

  UNLOCK (writer_table_lock);
  return wt;
}
예제 #2
0
static int
xfs_fsal_inode2handle(int fd, ino_t ino, vfs_file_handle_t *fh)
{
	xfs_bstat_t bstat;
	struct xfs_filehandle hdl;
        void *data, *fhdata;
        size_t sz, fhsz;
        int rv;

        if(fh->handle_bytes < sizeof(hdl)) {
                errno = E2BIG;
                return -1;
        }
	if((xfs_fsal_bulkstat_inode(fd, ino, &bstat) < 0) ||
           (fd_to_handle(fd, &data, &sz) < 0))
		return -1;

        if ((rv = handle_to_fshandle(data, sz, &fhdata, &fhsz)) >= 0) {
                memset(&hdl, 0, sizeof(hdl));
                memcpy(&hdl.fh_fshdl, fhdata, fhsz);
                hdl.fh_sz_following = XFS_FILEHANDLE_SZ_FOLLOWING;
                hdl.fh_gen = bstat.bs_gen;
                hdl.fh_ino = bstat.bs_ino;

                memcpy(fh->handle, &hdl, sizeof(hdl));
                fh->handle_bytes = sizeof(hdl);
                free_handle(fhdata, fhsz);
        }

        free_handle(data, sz);
	return rv;
}
예제 #3
0
파일: w32-io.c 프로젝트: nobled/gpgme
/* Find a reader context or create a new one.  Note that the reader
   context will last until a _gpgme_io_close.  */
static struct reader_context_s *
find_reader (int fd, int start_it)
{
  struct reader_context_s *rd = NULL;
  int i;

  LOCK (reader_table_lock);
  for (i = 0; i < reader_table_size; i++)
    if (reader_table[i].used && reader_table[i].fd == fd)
      rd = reader_table[i].context;

  if (rd || !start_it)
    {
      UNLOCK (reader_table_lock);
      return rd;
    }

  for (i = 0; i < reader_table_size; i++)
    if (!reader_table[i].used)
      break;

  if (i != reader_table_size)
    {
      rd = create_reader (fd_to_handle (fd));
      if (rd)
	{
	  reader_table[i].fd = fd;
	  reader_table[i].context = rd;
	  reader_table[i].used = 1;
	}
    }

  UNLOCK (reader_table_lock);
  return rd;
}
예제 #4
0
/* 
 * Find a writer context or create a new one 
 * Note that the writer context will last until a io_close.
 */
static struct writer_context_s *
find_writer (int fd, int start_it)
{
    int i;

    for (i=0; i < writer_table_size ; i++ ) {
        if ( writer_table[i].used && writer_table[i].fd == fd )
            return writer_table[i].context;
    }
    if (!start_it)
        return NULL;

    LOCK (writer_table_lock);
    for (i=0; i < writer_table_size; i++ ) {
        if (!writer_table[i].used) {
            writer_table[i].fd = fd;
            writer_table[i].context = create_writer (fd_to_handle (fd));
            writer_table[i].used = 1;
            UNLOCK (writer_table_lock);
            return writer_table[i].context;
        }
    }
    UNLOCK (writer_table_lock);
    return NULL;
}
예제 #5
0
파일: fsal_internal.c 프로젝트: ic-hep/emi3
fsal_status_t fsal_internal_fd2handle(xfsfsal_op_context_t * p_context,
                                      int fd, xfsfsal_handle_t * phandle)
{
  int rc = 0;
  struct stat ino;

  char *handle_val;
  size_t handle_len;

  if(!phandle)
    ReturnCode(ERR_FSAL_FAULT, 0);

  memset(phandle, 0, sizeof(xfsfsal_handle_t));

  /* retrieve inode */
  rc = fstat(fd, &ino);
  if(rc)
    ReturnCode(posix2fsal_error(errno), errno);
  phandle->data.inode = ino.st_ino;
  phandle->data.type = DT_UNKNOWN;  /** Put here something smarter */

  if((rc = fd_to_handle(fd, (void **)(&handle_val), &handle_len)) < 0)
    ReturnCode(posix2fsal_error(errno), errno);

  memcpy(phandle->data.handle_val, handle_val, handle_len);
  phandle->data.handle_len = handle_len;

  free_handle(handle_val, handle_len);

  ReturnCode(ERR_FSAL_NO_ERROR, 0);
}                               /* fsal_internal_fd2handle */
예제 #6
0
/* 
 * Find a reader context or create a new one 
 * Note that the reader context will last until a io_close.
 */
static struct reader_context_s *
find_reader (int fd, int start_it)
{
    int i;

    for (i=0; i < reader_table_size ; i++ ) {
        if ( reader_table[i].used && reader_table[i].fd == fd )
            return reader_table[i].context;
    }
    if (!start_it)
        return NULL;

    LOCK (reader_table_lock);
    for (i=0; i < reader_table_size; i++ ) {
        if (!reader_table[i].used) {
            reader_table[i].fd = fd;
            reader_table[i].context = create_reader (fd_to_handle (fd));
            reader_table[i].used = 1;
            UNLOCK (reader_table_lock);
            return reader_table[i].context;
        }
    }
    UNLOCK (reader_table_lock);
    return NULL;
}
예제 #7
0
파일: os.c 프로젝트: alemic/couchstore
static couch_file_handle couch_constructor(couchstore_error_info_t *errinfo,
                                           void* cookie)
{
    (void) cookie;
    (void)errinfo;
    /*
    ** We don't have a file descriptor till couch_open runs, so return
    ** an invalid value for now.
    */
    return fd_to_handle(-1);
}
예제 #8
0
파일: w32-io.c 프로젝트: nobled/gpgme
int
_gpgme_io_close (int fd)
{
  int i;
  _gpgme_close_notify_handler_t handler = NULL;
  void *value = NULL;
  TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_close", fd);

  if (fd == -1)
    {
      errno = EBADF;
      return TRACE_SYSRES (-1);
    }

  kill_reader (fd);
  kill_writer (fd);
  LOCK (notify_table_lock);
  for (i = 0; i < DIM (notify_table); i++)
    {
      if (notify_table[i].inuse && notify_table[i].fd == fd)
	{
	  handler = notify_table[i].handler;
	  value   = notify_table[i].value;
	  notify_table[i].handler = NULL;
	  notify_table[i].value = NULL;
	  notify_table[i].inuse = 0;
	  break;
	}
    }
  UNLOCK (notify_table_lock);
  if (handler)
    handler (fd, value);

  if (!CloseHandle (fd_to_handle (fd)))
    { 
      TRACE_LOG1 ("CloseHandle failed: ec=%d", (int) GetLastError ());
      /* FIXME: Should translate the error code.  */
      errno = EIO;
      return TRACE_SYSRES (-1);
    }

  return TRACE_SYSRES (0);
}
예제 #9
0
static int
vfs_xfs_fd_to_handle(int fd, vfs_file_handle_t *fh)
{
        void *data;
        size_t sz;
        int rv = 0;

        if (fd_to_handle(fd, &data, &sz) < 0)
                return -1;

        if (sz >= fh->handle_bytes) {
                errno = E2BIG;
                rv = -1;
        } else {
                memcpy(fh->handle, data, sz);
                fh->handle_bytes = sz;
        }
        free_handle(data, sz);
        return rv;
}
예제 #10
0
파일: os.c 프로젝트: alemic/couchstore
static couchstore_error_t couch_open(couchstore_error_info_t *errinfo,
                                     couch_file_handle* handle,
                                     const char *path,
                                     int oflag)
{
    int fd;
    do {
        fd = open(path, oflag | O_LARGEFILE, 0666);
    } while (fd == -1 && errno == EINTR);

    if (fd < 0) {
        save_errno(errinfo);
        if (errno == ENOENT) {
            return COUCHSTORE_ERROR_NO_SUCH_FILE;
        } else {
            return COUCHSTORE_ERROR_OPEN_FILE;
        }
    }
    /* Tell the caller about the new handle (file descriptor) */
    *handle = fd_to_handle(fd);
    return COUCHSTORE_SUCCESS;
}
예제 #11
0
int vfs_fd_to_handle(int fd, struct fsal_filesystem *fs,
		     vfs_file_handle_t *fh)
{
	void *data;
	size_t sz;
	int rv = 0;

	if (fd_to_handle(fd, &data, &sz) < 0)
		return -1;

	if (sz >= fh->handle_len) {
		errno = E2BIG;
		rv = -1;
	} else {
		memcpy(fh->handle_data, data, sz);
		fh->handle_len = sz;

		LogXFSHandle(fh);
	}
	free_handle(data, sz);
	return rv;
}
예제 #12
0
static int xfs_fsal_inode2handle(int fd, ino_t ino, vfs_file_handle_t *fh)
{
	xfs_bstat_t bstat;
	xfs_handle_t *hdl = (xfs_handle_t *) fh->handle_data;
	void *data;
	size_t sz;

	if (fh->handle_len < sizeof(*hdl)) {
		errno = E2BIG;
		return -1;
	}

	/* Get the information pertinent to this inode, and
	 * the file handle for the reference fd.
	 */
	if ((xfs_fsal_bulkstat_inode(fd, ino, &bstat) < 0) ||
	    (fd_to_handle(fd, &data, &sz) < 0))
		return -1;

	/* Copy the fsid from the reference fd */
	memcpy(&hdl->ha_fsid, data, sizeof(xfs_fsid_t));

	/* Fill in the rest of the handle with the information
	 * pertinent to this inode.
	 */
	hdl->ha_fid.fid_len = sizeof(xfs_handle_t) -
			      sizeof(xfs_fsid_t) -
			      sizeof(hdl->ha_fid.fid_len);
	hdl->ha_fid.fid_pad = 0;
	hdl->ha_fid.fid_gen = bstat.bs_gen;
	hdl->ha_fid.fid_ino = bstat.bs_ino;

	fh->handle_len = sizeof(*hdl);

	free_handle(data, sz);
	return 0;
}
예제 #13
0
int
_gpgme_io_close ( int fd )
{
    int i;
    void (*handler)(int, void*) = NULL;
    void *value = NULL;

    if ( fd == -1 )
        return -1;

    DEBUG1 ("** closing handle for fd %d\n", fd);
    kill_reader (fd);
    kill_writer (fd);
    LOCK (notify_table_lock);
    for ( i=0; i < DIM (notify_table); i++ ) {
        if (notify_table[i].inuse && notify_table[i].fd == fd) {
            handler = notify_table[i].handler;
            value   = notify_table[i].value;
            notify_table[i].handler = NULL;
            notify_table[i].value = NULL;
            notify_table[i].inuse = 0;
            break;
        }
    }
    UNLOCK (notify_table_lock);
    if (handler)
        handler (fd, value);

    if ( !CloseHandle (fd_to_handle (fd)) ) { 
        DEBUG2 ("CloseHandle for fd %d failed: ec=%d\n",
                 fd, (int)GetLastError ());
        return -1;
    }

    return 0;
}
예제 #14
0
/* See exechelp.h for a description.  */
gpg_error_t
gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode)
{
  gpg_err_code_t ec;
  HANDLE proc = fd_to_handle (pid);
  int code;
  DWORD exc;

  if (r_exitcode)
    *r_exitcode = -1;

  if (pid == (pid_t)(-1))
    return gpg_error (GPG_ERR_INV_VALUE);

  /* FIXME: We should do a pth_waitpid here.  However this has not yet
     been implemented.  A special W32 pth system call would even be
     better.  */
  code = WaitForSingleObject (proc, hang? INFINITE : 0);
  switch (code)
    {
    case WAIT_TIMEOUT:
      ec = GPG_ERR_TIMEOUT;
      break;

    case WAIT_FAILED:
      log_error (_("waiting for process %d to terminate failed: %s\n"),
                 (int)pid, w32_strerror (-1));
      ec = GPG_ERR_GENERAL;
      break;

    case WAIT_OBJECT_0:
      if (!GetExitCodeProcess (proc, &exc))
        {
          log_error (_("error getting exit code of process %d: %s\n"),
                     (int)pid, w32_strerror (-1) );
          ec = GPG_ERR_GENERAL;
        }
      else if (exc)
        {
          log_error (_("error running `%s': exit status %d\n"),
                     pgmname, (int)exc );
          if (r_exitcode)
            *r_exitcode = (int)exc;
          ec = GPG_ERR_GENERAL;
        }
      else
        {
          if (r_exitcode)
            *r_exitcode = 0;
          ec = 0;
        }
      break;

    default:
      log_error ("WaitForSingleObject returned unexpected "
                 "code %d for pid %d\n", code, (int)pid );
      ec = GPG_ERR_GENERAL;
      break;
    }

  return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
}
예제 #15
0
/* Log hook */
int _start(int arg0, int arg1, unsigned int arg2, void *addr, int len, int arg5)
{
    /* Kernel functions */
#if VER == 532
    void (*spinlock)(void *lock) = (void (*)(void*))0xFFF075BC;
    void (*spunlock)(void *lock) = (void (*)(void*))0xFFF075E0;
    int (*fd_to_handle)(unsigned int *ipcbuf, int rampid) = (int (*)(unsigned int*,int))0xFFF0C7F8;
    int (*IOS_IoctlvAsync)(int arg0, int fd, int cmd, int cnt_in, int cnt_out, struct iovec *vecs, void *cb, void *usrdata) = (int (*)(int,int,int,int,int,struct iovec*,void*,void*))0xFFF0BAF4;
    int (*IOS_WaitReply)(void *usrdata, int arg1, int arg2) = (int (*)(void*,int,int))0xFFF18150;
    void* (*memmove)(void *dst, void *src, int len) = (void* (*)(void*,void*,int))0xFFF09C7C;
#elif VER == 550
    void (*spinlock)(void *lock) = (void (*)(void*))0x0;
    void (*spunlock)(void *lock) = (void (*)(void*))0x0;
    int (*fd_to_handle)(unsigned int *ipcbuf, int rampid) = (int (*)(unsigned int*,int))0x0;
    int (*IOS_IoctlvAsync)(int arg0, int fd, int cmd, int cnt_in, int cnt_out, struct iovec *vecs, void *cb, void *usrdata) = (int (*)(int,int,int,int,int,struct iovec*,void*,void*))0x0;
    int (*IOS_WaitReply)(void *usrdata, int arg1, int arg2) = (int (*)(void*,int,int))0x0;
    void* (*memmove)(void *dst, void *src, int len) = (void* (*)(void*,void*,int))0x0;
#else
    void (*spinlock)(void *lock) = (void (*)(void*))0x0;
    void (*spunlock)(void *lock) = (void (*)(void*))0x0;
    int (*fd_to_handle)(unsigned int *ipcbuf, int rampid) = (int (*)(unsigned int*,int))0x0;
    int (*IOS_IoctlvAsync)(int arg0, int fd, int cmd, int cnt_in, int cnt_out, struct iovec *vecs, void *cb, void *usrdata) = (int (*)(int,int,int,int,int,struct iovec*,void*,void*))0x0;
    int (*IOS_WaitReply)(void *usrdata, int arg1, int arg2) = (int (*)(void*,int,int))0x0;
    void* (*memmove)(void *dst, void *src, int len) = (void* (*)(void*,void*,int))0x0;
#endif

    /* Only do this if socket open */
    int sockfd = *((int*)0xFFF00B48);
    if (sockfd != -1)
    {
        /* Lock a spinlock */
        spinlock((void*)(0xA0000000 + (0xFFF00B4C - 0xC0000000)));

        /* Get socket FD and convert to handle */
        unsigned int ipcbuf[3] = {0, 0, *((unsigned int*)0xFFF00B44)};
        fd_to_handle(ipcbuf, 4);

        /* Copy socket data to 0x40-aligned buffer */
        memmove((void*)0xDFF01500, addr, len);

        /* Execute send() request and wait for completion */
        unsigned int reqbuf[2] = {(unsigned int)sockfd, 0};
        int sendlen = ((len / 0x40) * 0x40) + ((len % 0x40 == 0) ? 0 : 0x40);
        struct iovec vecs[4];
        vecs[0].buffer = (void*)&reqbuf[0];
        vecs[0].len = 8;
        vecs[0].unknown8[0] = vecs[0].unknown8[1] = vecs[0].unknown8[2] = vecs[0].unknown8[3] = 0;
        vecs[1].buffer = (void*)0xDFF01500;
        vecs[1].len = sendlen;
        vecs[1].unknown8[0] = vecs[1].unknown8[1] = vecs[1].unknown8[2] = vecs[1].unknown8[3] = 0;
        vecs[2].buffer = (void*)0;
        vecs[2].len = 0;
        vecs[2].unknown8[0] = vecs[2].unknown8[1] = vecs[2].unknown8[2] = vecs[2].unknown8[3] = 0;
        vecs[3].buffer = (void*)0;
        vecs[3].len = 0;
        vecs[3].unknown8[0] = vecs[3].unknown8[1] = vecs[3].unknown8[2] = vecs[3].unknown8[3] = 0;
        IOS_IoctlvAsync(0, (int)ipcbuf[2], 0xE, 4, 0, vecs, (void*)0, (void*)0x1234ABC0);
        IOS_WaitReply((void*)0x1234ABC0, 0xF4240, 0);

        /* Release the spinlock */
        spunlock((void*)(0xA0000000 + (0xFFF00B4C - 0xC0000000)));
    }

    /* Pass through to real function */
#if VER == 532
    int (*real_func)(int arg0, int arg1, unsigned int arg2, void *addr, int len, int arg5) = (int (*)(int,int,unsigned int,void*,int,int))0xFFF1AB94;
#elif VER == 550
    int (*real_func)(int arg0, int arg1, unsigned int arg2, void *addr, int len, int arg5) = (int (*)(int,int,unsigned int,void*,int,int))0x0;
#else
    int (*real_func)(int arg0, int arg1, unsigned int arg2, void *addr, int len, int arg5) = (int (*)(int,int,unsigned int,void*,int,int))0x0;
#endif
    return real_func(arg0, arg1, arg2, addr, len, arg5);
}
예제 #16
0
int
_gpgme_io_spawn ( const char *path, char **argv,
                  struct spawn_fd_item_s *fd_child_list,
                  struct spawn_fd_item_s *fd_parent_list )
{
    SECURITY_ATTRIBUTES sec_attr;
    PROCESS_INFORMATION pi = {
        NULL,      /* returns process handle */
        0,         /* returns primary thread handle */
        0,         /* returns pid */
        0         /* returns tid */
    };
    STARTUPINFO si;
    char *envblock = NULL;
    int cr_flags = CREATE_DEFAULT_ERROR_MODE
                 | GetPriorityClass (GetCurrentProcess ());
    int i;
    char *arg_string;
    int duped_stdin = 0;
    int duped_stderr = 0;
    HANDLE hnul = INVALID_HANDLE_VALUE;
    /* FIXME.  */
    int debug_me = 0;

    memset (&sec_attr, 0, sizeof sec_attr );
    sec_attr.nLength = sizeof sec_attr;
    sec_attr.bInheritHandle = FALSE;

    arg_string = build_commandline ( argv );
    if (!arg_string )
        return -1; 

    memset (&si, 0, sizeof si);
    si.cb = sizeof (si);
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.wShowWindow = debug_me? SW_SHOW : SW_HIDE;
    si.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
    si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
    si.hStdError = GetStdHandle (STD_ERROR_HANDLE);

    for (i=0; fd_child_list[i].fd != -1; i++ ) {
        if (fd_child_list[i].dup_to == 0 ) {
            si.hStdInput = fd_to_handle (fd_child_list[i].fd);
            DEBUG1 ("using %d for stdin", fd_child_list[i].fd );
            duped_stdin=1;
        }
        else if (fd_child_list[i].dup_to == 1 ) {
            si.hStdOutput = fd_to_handle (fd_child_list[i].fd);
            DEBUG1 ("using %d for stdout", fd_child_list[i].fd );
        }
        else if (fd_child_list[i].dup_to == 2 ) {
            si.hStdError = fd_to_handle (fd_child_list[i].fd);
            DEBUG1 ("using %d for stderr", fd_child_list[i].fd );
            duped_stderr = 1;
        }
    }

    if( !duped_stdin || !duped_stderr ) {
        SECURITY_ATTRIBUTES sa;

        memset (&sa, 0, sizeof sa );
        sa.nLength = sizeof sa;
        sa.bInheritHandle = TRUE;
        hnul = CreateFile ( "nul",
                            GENERIC_READ|GENERIC_WRITE,
                            FILE_SHARE_READ|FILE_SHARE_WRITE,
                            &sa,
                            OPEN_EXISTING,
                            FILE_ATTRIBUTE_NORMAL,
                            NULL );
        if ( hnul == INVALID_HANDLE_VALUE ) {
            DEBUG1 ("can't open `nul': ec=%d\n", (int)GetLastError ());
            free (arg_string);
            return -1;
        }
        /* Make sure that the process has a connected stdin */
        if ( !duped_stdin ) {
            si.hStdInput = hnul;
            DEBUG1 ("using %d for dummy stdin", (int)hnul );
        }
        /* We normally don't want all the normal output */
        if ( !duped_stderr ) {
            si.hStdError = hnul;
            DEBUG1 ("using %d for dummy stderr", (int)hnul );
        }
    }

    DEBUG2 ("CreateProcess, path=`%s' args=`%s'", path, arg_string);
    cr_flags |= CREATE_SUSPENDED; 
    if ( !CreateProcessA (path,
                          arg_string,
                          &sec_attr,     /* process security attributes */
                          &sec_attr,     /* thread security attributes */
                          TRUE,          /* inherit handles */
                          cr_flags,      /* creation flags */
                          envblock,      /* environment */
                          NULL,          /* use current drive/directory */
                          &si,           /* startup information */
                          &pi            /* returns process information */
        ) ) {
        DEBUG1 ("CreateProcess failed: ec=%d\n", (int) GetLastError ());
        free (arg_string);
        return -1;
    }

    /* Close the /dev/nul handle if used. */
    if (hnul != INVALID_HANDLE_VALUE ) {
        if ( !CloseHandle ( hnul ) )
            DEBUG1 ("CloseHandle(hnul) failed: ec=%d\n", (int)GetLastError());
    }

    /* Close the other ends of the pipes. */
    for (i = 0; fd_parent_list[i].fd != -1; i++)
      _gpgme_io_close (fd_parent_list[i].fd);

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

    if ( ResumeThread ( pi.hThread ) < 0 ) {
        DEBUG1 ("ResumeThread failed: ec=%d\n", (int)GetLastError ());
    }

    if ( !CloseHandle (pi.hThread) ) { 
        DEBUG1 ("CloseHandle of thread failed: ec=%d\n",
                 (int)GetLastError ());
    }

    return handle_to_pid (pi.hProcess);
}
예제 #17
0
파일: w32-io.c 프로젝트: nobled/gpgme
int
_gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
		 struct spawn_fd_item_s *fd_list,
		 void (*atfork) (void *opaque, int reserved),
		 void *atforkvalue, pid_t *r_pid)
{
  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 = (CREATE_DEFAULT_ERROR_MODE
                  | GetPriorityClass (GetCurrentProcess ()));
  int i;
  char **args;
  char *arg_string;
  /* FIXME.  */
  int debug_me = 0;
  int tmp_fd;
  char *tmp_name;

  TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_spawn", path,
	      "path=%s", path);
  i = 0;
  while (argv[i])
    {
      TRACE_LOG2 ("argv[%2i] = %s", i, argv[i]);
      i++;
    }

  /* We do not inherit any handles by default, and just insert those
     handles we want the child to have afterwards.  But some handle
     values occur on the command line, and we need to move
     stdin/out/err to the right location.  So we use a wrapper program
     which gets the information from a temporary file.  */
  if (_gpgme_mkstemp (&tmp_fd, &tmp_name) < 0)
    {
      TRACE_LOG1 ("_gpgme_mkstemp failed: %s", strerror (errno));
      return TRACE_SYSRES (-1);
    }
  TRACE_LOG1 ("tmp_name = %s", tmp_name);

  args = calloc (2 + i + 1, sizeof (*args));
  args[0] = (char *) _gpgme_get_w32spawn_path ();
  args[1] = tmp_name;
  args[2] = path;
  memcpy (&args[3], &argv[1], i * sizeof (*args));

  memset (&sec_attr, 0, sizeof sec_attr);
  sec_attr.nLength = sizeof sec_attr;
  sec_attr.bInheritHandle = FALSE;
 
  arg_string = build_commandline (args);
  free (args);
  if (!arg_string)
    {
      close (tmp_fd);
      DeleteFile (tmp_name);
      return TRACE_SYSRES (-1);
    }

  memset (&si, 0, sizeof si);
  si.cb = sizeof (si);
  si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
  si.wShowWindow = debug_me ? SW_SHOW : SW_HIDE;
  si.hStdInput = INVALID_HANDLE_VALUE;
  si.hStdOutput = INVALID_HANDLE_VALUE;
  si.hStdError = INVALID_HANDLE_VALUE;

  cr_flags |= CREATE_SUSPENDED; 
  cr_flags |= DETACHED_PROCESS;
  if (!CreateProcessA (_gpgme_get_w32spawn_path (),
		       arg_string,
		       &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 */
    {
      TRACE_LOG1 ("CreateProcess failed: ec=%d", (int) GetLastError ());
      free (arg_string);
      close (tmp_fd);
      DeleteFile (tmp_name);

      /* FIXME: Should translate the error code.  */
      errno = EIO;
      return TRACE_SYSRES (-1);
    }

  free (arg_string);

  if (flags & IOSPAWN_FLAG_ALLOW_SET_FG)
    _gpgme_allow_set_foreground_window ((pid_t)pi.dwProcessId);

  /* Insert the inherited handles.  */
  for (i = 0; fd_list[i].fd != -1; i++)
    {
      HANDLE hd;

      /* Make it inheritable for the wrapper process.  */
      if (!DuplicateHandle (GetCurrentProcess(), fd_to_handle (fd_list[i].fd),
			    pi.hProcess, &hd, 0, TRUE, DUPLICATE_SAME_ACCESS))
	{
	  TRACE_LOG1 ("DuplicateHandle failed: ec=%d", (int) GetLastError ());
	  TerminateProcess (pi.hProcess, 0);
	  /* Just in case TerminateProcess didn't work, let the
	     process fail on its own.  */
	  ResumeThread (pi.hThread);
	  CloseHandle (pi.hThread);
	  CloseHandle (pi.hProcess);

	  close (tmp_fd);
	  DeleteFile (tmp_name);

	  /* FIXME: Should translate the error code.  */
	  errno = EIO;
	  return TRACE_SYSRES (-1);
        }
      /* Return the child name of this handle.  */
      fd_list[i].peer_name = handle_to_fd (hd);
    }
  
  /* Write the handle translation information to the temporary
     file.  */
  {
    /* Hold roughly MAX_TRANS quadruplets of 64 bit numbers in hex
       notation: "0xFEDCBA9876543210" with an extra white space after
       every quadruplet.  10*(19*4 + 1) - 1 = 769.  This plans ahead
       for a time when a HANDLE is 64 bit.  */
#define BUFFER_MAX 810
    char line[BUFFER_MAX + 1];
    int res;
    int written;
    size_t len;

    if ((flags & IOSPAWN_FLAG_ALLOW_SET_FG))
      strcpy (line, "~1 \n");
    else
      strcpy (line, "\n");
    for (i = 0; fd_list[i].fd != -1; i++)
      {
	/* Strip the newline.  */
	len = strlen (line) - 1;
	
	/* Format is: Local name, stdin/stdout/stderr, peer name, argv idx.  */
	snprintf (&line[len], BUFFER_MAX - len, "0x%x %d 0x%x %d  \n",
		  fd_list[i].fd, fd_list[i].dup_to,
		  fd_list[i].peer_name, fd_list[i].arg_loc);
	/* Rather safe than sorry.  */
	line[BUFFER_MAX - 1] = '\n';
	line[BUFFER_MAX] = '\0';
      }
    len = strlen (line);
    written = 0;
    do
      {
	res = write (tmp_fd, &line[written], len - written);
	if (res > 0)
	  written += res;
      }
    while (res > 0 || (res < 0 && errno == EAGAIN));
  }
  close (tmp_fd);
  /* The temporary file is deleted by the gpgme-w32spawn process
     (hopefully).  */

  TRACE_LOG4 ("CreateProcess ready: hProcess=%p, hThread=%p, "
	      "dwProcessID=%d, dwThreadId=%d",
	      pi.hProcess, pi.hThread, 
	      (int) pi.dwProcessId, (int) pi.dwThreadId);
  
  if (r_pid)
    *r_pid = (pid_t)pi.dwProcessId;

  
  if (ResumeThread (pi.hThread) < 0)
    TRACE_LOG1 ("ResumeThread failed: ec=%d", (int) GetLastError ());
  
  if (!CloseHandle (pi.hThread))
    TRACE_LOG1 ("CloseHandle of thread failed: ec=%d",
		(int) GetLastError ());

  TRACE_LOG1 ("process=%p", pi.hProcess);

  /* We don't need to wait for the process.  */
  if (!CloseHandle (pi.hProcess))
    TRACE_LOG1 ("CloseHandle of process failed: ec=%d",
		(int) GetLastError ());

  if (! (flags & IOSPAWN_FLAG_NOCLOSE))
    {
      for (i = 0; fd_list[i].fd != -1; i++)
	_gpgme_io_close (fd_list[i].fd);
    }

  for (i = 0; fd_list[i].fd != -1; i++)
    if (fd_list[i].dup_to == -1)
      TRACE_LOG3 ("fd[%i] = 0x%x -> 0x%x", i, fd_list[i].fd,
		  fd_list[i].peer_name);
    else
      TRACE_LOG4 ("fd[%i] = 0x%x -> 0x%x (std%s)", i, fd_list[i].fd,
		  fd_list[i].peer_name, (fd_list[i].dup_to == 0) ? "in" :
		  ((fd_list[i].dup_to == 1) ? "out" : "err"));

  return TRACE_SYSRES (0);
}
예제 #18
0
파일: w32-io.c 프로젝트: nobled/gpgme
int
_gpgme_io_dup (int fd)
{
  HANDLE handle = fd_to_handle (fd);
  HANDLE new_handle = fd_to_handle (fd);
  int i;
  struct reader_context_s *rd_ctx;
  struct writer_context_s *wt_ctx;

  TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_dup", fd);

  if (!DuplicateHandle (GetCurrentProcess(), handle,
			GetCurrentProcess(), &new_handle,
			0, FALSE, DUPLICATE_SAME_ACCESS))
    {
      TRACE_LOG1 ("DuplicateHandle failed: ec=%d\n", (int) GetLastError ());
      /* FIXME: Translate error code.  */
      errno = EIO;
      return TRACE_SYSRES (-1);
    }

  rd_ctx = find_reader (fd, 0);
  if (rd_ctx)
    {
      /* No need for locking, as the only races are against the reader
	 thread itself, which doesn't touch refcount.  */
      rd_ctx->refcount++;

      LOCK (reader_table_lock);
      for (i = 0; i < reader_table_size; i++)
	if (!reader_table[i].used)
	  break;
      /* FIXME.  */
      assert (i != reader_table_size);
      reader_table[i].fd = handle_to_fd (new_handle);
      reader_table[i].context = rd_ctx;
      reader_table[i].used = 1;
      UNLOCK (reader_table_lock);
    }

  wt_ctx = find_writer (fd, 0);
  if (wt_ctx)
    {
      /* No need for locking, as the only races are against the writer
	 thread itself, which doesn't touch refcount.  */
      wt_ctx->refcount++;

      LOCK (writer_table_lock);
      for (i = 0; i < writer_table_size; i++)
	if (!writer_table[i].used)
	  break;
      /* FIXME.  */
      assert (i != writer_table_size);
      writer_table[i].fd = handle_to_fd (new_handle);
      writer_table[i].context = wt_ctx;
      writer_table[i].used = 1;
      UNLOCK (writer_table_lock);
    }

  return TRACE_SYSRES (handle_to_fd (new_handle));
}