|
Packit |
d7e8d0 |
/* w32-glib-io.c - W32 Glib I/O functions
|
|
Packit Service |
30b792 |
* Copyright (C) 2000 Werner Koch (dd9jn)
|
|
Packit Service |
30b792 |
* Copyright (C) 2001, 2002, 2004, 2005 g10 Code GmbH
|
|
Packit Service |
30b792 |
*
|
|
Packit Service |
30b792 |
* This file is part of GPGME.
|
|
Packit Service |
30b792 |
*
|
|
Packit Service |
30b792 |
* GPGME is free software; you can redistribute it and/or modify it
|
|
Packit Service |
30b792 |
* under the terms of the GNU Lesser General Public License as
|
|
Packit Service |
30b792 |
* published by the Free Software Foundation; either version 2.1 of
|
|
Packit Service |
30b792 |
* the License, or (at your option) any later version.
|
|
Packit Service |
30b792 |
*
|
|
Packit Service |
30b792 |
* GPGME is distributed in the hope that it will be useful, but
|
|
Packit Service |
30b792 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
30b792 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
30b792 |
* Lesser General Public License for more details.
|
|
Packit Service |
30b792 |
*
|
|
Packit Service |
30b792 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit Service |
30b792 |
* License along with this program; if not, see <https://gnu.org/licenses/>.
|
|
Packit Service |
30b792 |
* SPDX-License-Identifier: LGPL-2.1-or-later
|
|
Packit Service |
30b792 |
*/
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
d7e8d0 |
#include <config.h>
|
|
Packit |
d7e8d0 |
#endif
|
|
Packit |
d7e8d0 |
#include <stdio.h>
|
|
Packit |
d7e8d0 |
#include <stdlib.h>
|
|
Packit |
d7e8d0 |
#include <string.h>
|
|
Packit |
d7e8d0 |
#include <assert.h>
|
|
Packit |
d7e8d0 |
#include <errno.h>
|
|
Packit |
d7e8d0 |
#include <fcntl.h>
|
|
Packit |
d7e8d0 |
#ifdef HAVE_UNISTD_H
|
|
Packit |
d7e8d0 |
# include <unistd.h>
|
|
Packit |
d7e8d0 |
#endif
|
|
Packit |
d7e8d0 |
#ifdef HAVE_SYS_TIME_H
|
|
Packit |
d7e8d0 |
# include <sys/time.h>
|
|
Packit |
d7e8d0 |
#endif
|
|
Packit |
d7e8d0 |
#ifdef HAVE_SYS_TYPES_H
|
|
Packit |
d7e8d0 |
# include <sys/types.h>
|
|
Packit |
d7e8d0 |
#endif
|
|
Packit |
d7e8d0 |
#include <glib.h>
|
|
Packit |
d7e8d0 |
#include <windows.h>
|
|
Packit |
d7e8d0 |
#include <io.h>
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
#include "util.h"
|
|
Packit |
d7e8d0 |
#include "priv-io.h"
|
|
Packit |
d7e8d0 |
#include "sema.h"
|
|
Packit |
d7e8d0 |
#include "debug.h"
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
#ifndef O_BINARY
|
|
Packit |
d7e8d0 |
#ifdef _O_BINARY
|
|
Packit |
d7e8d0 |
#define O_BINARY _O_BINARY
|
|
Packit |
d7e8d0 |
#else
|
|
Packit |
d7e8d0 |
#define O_BINARY 0
|
|
Packit |
d7e8d0 |
#endif
|
|
Packit |
d7e8d0 |
#endif
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* This file is an ugly hack to get GPGME working with glib on Windows
|
|
Packit |
d7e8d0 |
targets. On Windows, you can not select() on file descriptors.
|
|
Packit |
d7e8d0 |
The only way to check if there is something to read is to read
|
|
Packit |
d7e8d0 |
something. This means that GPGME can not let glib check for data
|
|
Packit |
d7e8d0 |
without letting glib also handle the data on Windows targets.
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
The ugly consequence is that we need to work on GIOChannels in
|
|
Packit |
d7e8d0 |
GPGME, creating a glib dependency. Also, we need to export an
|
|
Packit |
d7e8d0 |
interface for the application to get at GPGME's GIOChannel. There
|
|
Packit |
d7e8d0 |
is no good way to abstract all this with callbacks, because the
|
|
Packit |
d7e8d0 |
whole thing is also interconnected with the creation of pipes and
|
|
Packit |
d7e8d0 |
child processes.
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
The following rule applies only to this I/O backend:
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
* ALL operations must use the user defined event loop. GPGME can
|
|
Packit |
d7e8d0 |
not anymore provide its own event loop. This is mostly a sanity
|
|
Packit |
d7e8d0 |
requirement: Although we have in theory all information we need to
|
|
Packit |
d7e8d0 |
make the GPGME W32 code for select still work, it would be a big
|
|
Packit |
d7e8d0 |
complication and require changes throughout GPGME.
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
Eventually, we probably have to bite the bullet and make some
|
|
Packit |
d7e8d0 |
really nice callback interfaces to let the user control all this at
|
|
Packit |
d7e8d0 |
a per-context level. */
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
#define MAX_SLAFD 256
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
static struct
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
int used;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* If this is not -1, then it's a libc file descriptor. */
|
|
Packit |
d7e8d0 |
int fd;
|
|
Packit |
d7e8d0 |
/* If fd is -1, this is the Windows socket handle. */
|
|
Packit |
d7e8d0 |
int socket;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
GIOChannel *chan;
|
|
Packit |
d7e8d0 |
/* The boolean PRIMARY is true if this file descriptor caused the
|
|
Packit |
d7e8d0 |
allocation of CHAN. Only then should CHAN be destroyed when this
|
|
Packit |
d7e8d0 |
FD is closed. This, together with the fact that dup'ed file
|
|
Packit |
d7e8d0 |
descriptors are closed before the file descriptors from which
|
|
Packit |
d7e8d0 |
they are dup'ed are closed, ensures that CHAN is always valid,
|
|
Packit |
d7e8d0 |
and shared among all file descriptors referring to the same
|
|
Packit |
d7e8d0 |
underlying object.
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
The logic behind this is that there is only one reason for us to
|
|
Packit |
d7e8d0 |
dup file descriptors anyway: to allow simpler book-keeping of
|
|
Packit |
d7e8d0 |
file descriptors shared between GPGME and libassuan, which both
|
|
Packit |
d7e8d0 |
want to close something. Using the same channel for these
|
|
Packit |
d7e8d0 |
duplicates works just fine (and in fact, using different channels
|
|
Packit |
d7e8d0 |
does not work because the W32 backend in glib does not support
|
|
Packit |
d7e8d0 |
that: One would end up with several competing reader/writer
|
|
Packit |
d7e8d0 |
threads. */
|
|
Packit |
d7e8d0 |
int primary;
|
|
Packit |
d7e8d0 |
} giochannel_table[MAX_SLAFD];
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
static GIOChannel *
|
|
Packit |
d7e8d0 |
find_channel (int fd)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
if (fd < 0 || fd >= MAX_SLAFD || !giochannel_table[fd].used)
|
|
Packit |
d7e8d0 |
return NULL;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
return giochannel_table[fd].chan;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* Returns the FD or -1 on resource limit. */
|
|
Packit |
d7e8d0 |
int
|
|
Packit |
d7e8d0 |
new_dummy_channel_from_fd (int cfd)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
int idx;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
for (idx = 0; idx < MAX_SLAFD; idx++)
|
|
Packit |
d7e8d0 |
if (! giochannel_table[idx].used)
|
|
Packit |
d7e8d0 |
break;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (idx == MAX_SLAFD)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
errno = EIO;
|
|
Packit |
d7e8d0 |
return -1;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
giochannel_table[idx].used = 1;
|
|
Packit |
d7e8d0 |
giochannel_table[idx].chan = NULL;
|
|
Packit |
d7e8d0 |
giochannel_table[idx].fd = cfd;
|
|
Packit |
d7e8d0 |
giochannel_table[idx].socket = INVALID_SOCKET;
|
|
Packit |
d7e8d0 |
giochannel_table[idx].primary = 1;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
return idx;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* Returns the FD or -1 on resource limit. */
|
|
Packit |
d7e8d0 |
int
|
|
Packit |
d7e8d0 |
new_channel_from_fd (int cfd)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
int idx;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
for (idx = 0; idx < MAX_SLAFD; idx++)
|
|
Packit |
d7e8d0 |
if (! giochannel_table[idx].used)
|
|
Packit |
d7e8d0 |
break;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (idx == MAX_SLAFD)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
errno = EIO;
|
|
Packit |
d7e8d0 |
return -1;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
giochannel_table[idx].used = 1;
|
|
Packit |
d7e8d0 |
giochannel_table[idx].chan = g_io_channel_win32_new_fd (cfd);
|
|
Packit |
d7e8d0 |
giochannel_table[idx].fd = cfd;
|
|
Packit |
d7e8d0 |
giochannel_table[idx].socket = INVALID_SOCKET;
|
|
Packit |
d7e8d0 |
giochannel_table[idx].primary = 1;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
g_io_channel_set_encoding (giochannel_table[idx].chan, NULL, NULL);
|
|
Packit |
d7e8d0 |
g_io_channel_set_buffered (giochannel_table[idx].chan, FALSE);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
return idx;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* Returns the FD or -1 on resource limit. */
|
|
Packit |
d7e8d0 |
int
|
|
Packit |
d7e8d0 |
new_channel_from_socket (int sock)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
int idx;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
for (idx = 0; idx < MAX_SLAFD; idx++)
|
|
Packit |
d7e8d0 |
if (! giochannel_table[idx].used)
|
|
Packit |
d7e8d0 |
break;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (idx == MAX_SLAFD)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
errno = EIO;
|
|
Packit |
d7e8d0 |
return -1;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
giochannel_table[idx].used = 1;
|
|
Packit |
d7e8d0 |
giochannel_table[idx].chan = g_io_channel_win32_new_socket (sock);
|
|
Packit |
d7e8d0 |
giochannel_table[idx].fd = -1;
|
|
Packit |
d7e8d0 |
giochannel_table[idx].socket = sock;
|
|
Packit |
d7e8d0 |
giochannel_table[idx].primary = 1;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
g_io_channel_set_encoding (giochannel_table[idx].chan, NULL, NULL);
|
|
Packit |
d7e8d0 |
g_io_channel_set_buffered (giochannel_table[idx].chan, FALSE);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
return idx;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* Compatibility interface. Obsolete. */
|
|
Packit |
d7e8d0 |
void *
|
|
Packit |
d7e8d0 |
gpgme_get_giochannel (int fd)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
return find_channel (fd);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* Look up the giochannel for "file descriptor" FD. */
|
|
Packit |
d7e8d0 |
void *
|
|
Packit |
d7e8d0 |
gpgme_get_fdptr (int fd)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
return find_channel (fd);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* Write the printable version of FD to the buffer BUF of length
|
|
Packit |
d7e8d0 |
BUFLEN. The printable version is the representation on the command
|
|
Packit |
d7e8d0 |
line that the child process expects. */
|
|
Packit |
d7e8d0 |
int
|
|
Packit |
d7e8d0 |
_gpgme_io_fd2str (char *buf, int buflen, int fd)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
HANDLE hndl;
|
|
Packit |
d7e8d0 |
|
|
Packit Service |
30b792 |
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_fd2str", fd, "fd=%d", fd);
|
|
Packit |
d7e8d0 |
if (giochannel_table[fd].fd != -1)
|
|
Packit |
d7e8d0 |
hndl = (HANDLE) _get_osfhandle (giochannel_table[fd].fd);
|
|
Packit |
d7e8d0 |
else
|
|
Packit |
d7e8d0 |
hndl = (HANDLE) giochannel_table[fd].socket;
|
|
Packit |
d7e8d0 |
|
|
Packit Service |
30b792 |
TRACE_SUC ("syshd=%p", hndl);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
return snprintf (buf, buflen, "%d", (int) hndl);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
void
|
|
Packit |
d7e8d0 |
_gpgme_io_subsystem_init (void)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
static struct
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
_gpgme_close_notify_handler_t handler;
|
|
Packit |
d7e8d0 |
void *value;
|
|
Packit |
d7e8d0 |
} notify_table[MAX_SLAFD];
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
int
|
|
Packit |
d7e8d0 |
_gpgme_io_read (int fd, void *buffer, size_t count)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
int saved_errno = 0;
|
|
Packit |
d7e8d0 |
gsize nread;
|
|
Packit |
d7e8d0 |
GIOChannel *chan;
|
|
Packit |
d7e8d0 |
GIOStatus status;
|
|
Packit Service |
30b792 |
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_read", fd,
|
|
Packit |
d7e8d0 |
"buffer=%p, count=%u", buffer, count);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
chan = find_channel (fd);
|
|
Packit |
d7e8d0 |
if (!chan)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
TRACE_LOG ("no channel registered");
|
|
Packit |
d7e8d0 |
errno = EINVAL;
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit Service |
30b792 |
TRACE_LOG ("channel %p", chan);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
GError *err = NULL;
|
|
Packit |
d7e8d0 |
status = g_io_channel_read_chars (chan, (gchar *) buffer,
|
|
Packit |
d7e8d0 |
count, &nread, &err;;
|
|
Packit |
d7e8d0 |
if (err)
|
|
Packit |
d7e8d0 |
{
|
|
Packit Service |
30b792 |
TRACE_LOG ("status %i, err %s", status, err->message);
|
|
Packit |
d7e8d0 |
g_error_free (err);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (status == G_IO_STATUS_EOF)
|
|
Packit |
d7e8d0 |
nread = 0;
|
|
Packit |
d7e8d0 |
else if (status == G_IO_STATUS_AGAIN)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
nread = -1;
|
|
Packit |
d7e8d0 |
saved_errno = EAGAIN;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
else if (status != G_IO_STATUS_NORMAL)
|
|
Packit |
d7e8d0 |
{
|
|
Packit Service |
30b792 |
TRACE_LOG ("status %d", status);
|
|
Packit |
d7e8d0 |
nread = -1;
|
|
Packit |
d7e8d0 |
saved_errno = EIO;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (nread != 0 && nread != -1)
|
|
Packit Service |
30b792 |
TRACE_LOGBUFX (buffer, nread);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
errno = saved_errno;
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (nread);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
int
|
|
Packit |
d7e8d0 |
_gpgme_io_write (int fd, const void *buffer, size_t count)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
int saved_errno = 0;
|
|
Packit |
d7e8d0 |
gsize nwritten;
|
|
Packit |
d7e8d0 |
GIOChannel *chan;
|
|
Packit |
d7e8d0 |
GIOStatus status;
|
|
Packit |
d7e8d0 |
GError *err = NULL;
|
|
Packit |
d7e8d0 |
|
|
Packit Service |
30b792 |
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_write", fd,
|
|
Packit |
d7e8d0 |
"buffer=%p, count=%u", buffer, count);
|
|
Packit Service |
30b792 |
TRACE_LOGBUFX (buffer, count);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
chan = find_channel (fd);
|
|
Packit |
d7e8d0 |
if (!chan)
|
|
Packit |
d7e8d0 |
{
|
|
Packit Service |
30b792 |
TRACE_LOG ("fd=%d: no channel registered");
|
|
Packit |
d7e8d0 |
errno = EINVAL;
|
|
Packit |
d7e8d0 |
return -1;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
status = g_io_channel_write_chars (chan, (gchar *) buffer, count,
|
|
Packit |
d7e8d0 |
&nwritten, &err;;
|
|
Packit |
d7e8d0 |
if (err)
|
|
Packit |
d7e8d0 |
{
|
|
Packit Service |
30b792 |
TRACE_LOG ("write error: %s", err->message);
|
|
Packit |
d7e8d0 |
g_error_free (err);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (status == G_IO_STATUS_AGAIN)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
nwritten = -1;
|
|
Packit |
d7e8d0 |
saved_errno = EAGAIN;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
else if (status != G_IO_STATUS_NORMAL)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
nwritten = -1;
|
|
Packit |
d7e8d0 |
saved_errno = EIO;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
errno = saved_errno;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (nwritten);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
int
|
|
Packit |
d7e8d0 |
_gpgme_io_pipe (int filedes[2], int inherit_idx)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
int fds[2];
|
|
Packit |
d7e8d0 |
|
|
Packit Service |
30b792 |
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_pipe", filedes,
|
|
Packit |
d7e8d0 |
"inherit_idx=%i (GPGME uses it for %s)",
|
|
Packit |
d7e8d0 |
inherit_idx, inherit_idx ? "reading" : "writing");
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
#define PIPEBUF_SIZE 4096
|
|
Packit |
d7e8d0 |
if (_pipe (fds, PIPEBUF_SIZE, O_NOINHERIT | O_BINARY) == -1)
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* Make one end inheritable. */
|
|
Packit |
d7e8d0 |
if (inherit_idx == 0)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
int new_read;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
new_read = _dup (fds[0]);
|
|
Packit |
d7e8d0 |
_close (fds[0]);
|
|
Packit |
d7e8d0 |
fds[0] = new_read;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (new_read < 0)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
_close (fds[1]);
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
else if (inherit_idx == 1)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
int new_write;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
new_write = _dup (fds[1]);
|
|
Packit |
d7e8d0 |
_close (fds[1]);
|
|
Packit |
d7e8d0 |
fds[1] = new_write;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (new_write < 0)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
_close (fds[0]);
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* For _gpgme_io_close. */
|
|
Packit |
d7e8d0 |
filedes[inherit_idx] = new_dummy_channel_from_fd (fds[inherit_idx]);
|
|
Packit |
d7e8d0 |
if (filedes[inherit_idx] < 0)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
int saved_errno = errno;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
_close (fds[0]);
|
|
Packit |
d7e8d0 |
_close (fds[1]);
|
|
Packit |
d7e8d0 |
errno = saved_errno;
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* Now we have a pipe with the correct end inheritable. The other end
|
|
Packit |
d7e8d0 |
should have a giochannel. */
|
|
Packit |
d7e8d0 |
filedes[1 - inherit_idx] = new_channel_from_fd (fds[1 - inherit_idx]);
|
|
Packit |
d7e8d0 |
if (filedes[1 - inherit_idx] < 0)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
int saved_errno = errno;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
_gpgme_io_close (fds[inherit_idx]);
|
|
Packit |
d7e8d0 |
_close (fds[1 - inherit_idx]);
|
|
Packit |
d7e8d0 |
errno = saved_errno;
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit Service |
30b792 |
TRACE_SUC ("read=0x%x/%p, write=0x%x/%p, channel=%p",
|
|
Packit Service |
30b792 |
filedes[0],
|
|
Packit Service |
30b792 |
(HANDLE) _get_osfhandle (giochannel_table[filedes[0]].fd),
|
|
Packit Service |
30b792 |
filedes[1],
|
|
Packit Service |
30b792 |
(HANDLE) _get_osfhandle (giochannel_table[filedes[1]].fd),
|
|
Packit Service |
30b792 |
giochannel_table[1 - inherit_idx].chan);
|
|
Packit Service |
30b792 |
return 0;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
int
|
|
Packit |
d7e8d0 |
_gpgme_io_close (int fd)
|
|
Packit |
d7e8d0 |
{
|
|
Packit Service |
30b792 |
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_close", fd, "");
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (fd < 0 || fd >= MAX_SLAFD)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
errno = EBADF;
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
assert (giochannel_table[fd].used);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* First call the notify handler. */
|
|
Packit |
d7e8d0 |
if (notify_table[fd].handler)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
notify_table[fd].handler (fd, notify_table[fd].value);
|
|
Packit |
d7e8d0 |
notify_table[fd].handler = NULL;
|
|
Packit |
d7e8d0 |
notify_table[fd].value = NULL;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* Then do the close. */
|
|
Packit |
d7e8d0 |
if (giochannel_table[fd].chan)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
if (giochannel_table[fd].primary)
|
|
Packit |
d7e8d0 |
g_io_channel_shutdown (giochannel_table[fd].chan, 1, NULL);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
g_io_channel_unref (giochannel_table[fd].chan);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
else
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
/* Dummy entry, just close. */
|
|
Packit |
d7e8d0 |
assert (giochannel_table[fd].fd != -1);
|
|
Packit |
d7e8d0 |
_close (giochannel_table[fd].fd);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
giochannel_table[fd].used = 0;
|
|
Packit |
d7e8d0 |
giochannel_table[fd].fd = -1;
|
|
Packit |
d7e8d0 |
giochannel_table[fd].socket = INVALID_SOCKET;
|
|
Packit |
d7e8d0 |
giochannel_table[fd].chan = NULL;
|
|
Packit |
d7e8d0 |
giochannel_table[fd].primary = 0;
|
|
Packit |
d7e8d0 |
|
|
Packit Service |
30b792 |
TRACE_SUC ("");
|
|
Packit |
d7e8d0 |
return 0;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
int
|
|
Packit |
d7e8d0 |
_gpgme_io_set_close_notify (int fd, _gpgme_close_notify_handler_t handler,
|
|
Packit |
d7e8d0 |
void *value)
|
|
Packit |
d7e8d0 |
{
|
|
Packit Service |
30b792 |
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_set_close_notify", fd,
|
|
Packit |
d7e8d0 |
"close_handler=%p/%p", handler, value);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
assert (fd != -1);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (fd < 0 || fd >= (int) DIM (notify_table))
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
errno = EINVAL;
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
notify_table[fd].handler = handler;
|
|
Packit |
d7e8d0 |
notify_table[fd].value = value;
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (0);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
int
|
|
Packit |
d7e8d0 |
_gpgme_io_set_nonblocking (int fd)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
GIOChannel *chan;
|
|
Packit |
d7e8d0 |
GIOStatus status;
|
|
Packit |
d7e8d0 |
|
|
Packit Service |
30b792 |
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_set_nonblocking", fd, "");
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
chan = find_channel (fd);
|
|
Packit |
d7e8d0 |
if (!chan)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
errno = EIO;
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
status = g_io_channel_set_flags (chan,
|
|
Packit |
d7e8d0 |
g_io_channel_get_flags (chan) |
|
|
Packit |
d7e8d0 |
G_IO_FLAG_NONBLOCK, NULL);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (status != G_IO_STATUS_NORMAL)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
#if 0
|
|
Packit |
d7e8d0 |
/* glib 1.9.2 does not implement set_flags and returns an
|
|
Packit |
d7e8d0 |
error. */
|
|
Packit |
d7e8d0 |
errno = EIO;
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
#else
|
|
Packit Service |
30b792 |
TRACE_LOG ("g_io_channel_set_flags failed: status=%d (ignored)",
|
|
Packit |
d7e8d0 |
status);
|
|
Packit |
d7e8d0 |
#endif
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (0);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
static char *
|
|
Packit |
d7e8d0 |
build_commandline (char **argv)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
int i;
|
|
Packit |
d7e8d0 |
int n = 0;
|
|
Packit |
d7e8d0 |
char *buf;
|
|
Packit |
d7e8d0 |
char *p;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* We have to quote some things because under Windows the program
|
|
Packit |
d7e8d0 |
parses the commandline and does some unquoting. We enclose the
|
|
Packit |
d7e8d0 |
whole argument in double-quotes, and escape literal double-quotes
|
|
Packit |
d7e8d0 |
as well as backslashes with a backslash. We end up with a
|
|
Packit |
d7e8d0 |
trailing space at the end of the line, but that is harmless. */
|
|
Packit |
d7e8d0 |
for (i = 0; argv[i]; i++)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
p = argv[i];
|
|
Packit |
d7e8d0 |
/* The leading double-quote. */
|
|
Packit |
d7e8d0 |
n++;
|
|
Packit |
d7e8d0 |
while (*p)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
/* An extra one for each literal that must be escaped. */
|
|
Packit |
d7e8d0 |
if (*p == '\\' || *p == '"')
|
|
Packit |
d7e8d0 |
n++;
|
|
Packit |
d7e8d0 |
n++;
|
|
Packit |
d7e8d0 |
p++;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
/* The trailing double-quote and the delimiter. */
|
|
Packit |
d7e8d0 |
n += 2;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
/* And a trailing zero. */
|
|
Packit |
d7e8d0 |
n++;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
buf = p = malloc (n);
|
|
Packit |
d7e8d0 |
if (!buf)
|
|
Packit |
d7e8d0 |
return NULL;
|
|
Packit |
d7e8d0 |
for (i = 0; argv[i]; i++)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
char *argvp = argv[i];
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
*(p++) = '"';
|
|
Packit |
d7e8d0 |
while (*argvp)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
if (*argvp == '\\' || *argvp == '"')
|
|
Packit |
d7e8d0 |
*(p++) = '\\';
|
|
Packit |
d7e8d0 |
*(p++) = *(argvp++);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
*(p++) = '"';
|
|
Packit |
d7e8d0 |
*(p++) = ' ';
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
*(p++) = 0;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
return buf;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
int
|
|
Packit |
d7e8d0 |
_gpgme_io_spawn (const char *path, char * const argv[], unsigned int flags,
|
|
Packit |
d7e8d0 |
struct spawn_fd_item_s *fd_list,
|
|
Packit |
d7e8d0 |
void (*atfork) (void *opaque, int reserved),
|
|
Packit |
d7e8d0 |
void *atforkvalue, pid_t *r_pid)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
SECURITY_ATTRIBUTES sec_attr;
|
|
Packit |
d7e8d0 |
PROCESS_INFORMATION pi =
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
NULL, /* returns process handle */
|
|
Packit |
d7e8d0 |
0, /* returns primary thread handle */
|
|
Packit |
d7e8d0 |
0, /* returns pid */
|
|
Packit |
d7e8d0 |
0 /* returns tid */
|
|
Packit |
d7e8d0 |
};
|
|
Packit |
d7e8d0 |
STARTUPINFO si;
|
|
Packit |
d7e8d0 |
int cr_flags = (CREATE_DEFAULT_ERROR_MODE
|
|
Packit |
d7e8d0 |
| GetPriorityClass (GetCurrentProcess ()));
|
|
Packit |
d7e8d0 |
int i;
|
|
Packit |
d7e8d0 |
char **args;
|
|
Packit |
d7e8d0 |
char *arg_string;
|
|
Packit |
d7e8d0 |
/* FIXME. */
|
|
Packit |
d7e8d0 |
int debug_me = 0;
|
|
Packit |
d7e8d0 |
int tmp_fd;
|
|
Packit |
d7e8d0 |
char *tmp_name;
|
|
Packit |
d7e8d0 |
|
|
Packit Service |
30b792 |
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_spawn", path,
|
|
Packit |
d7e8d0 |
"path=%s", path);
|
|
Packit |
d7e8d0 |
i = 0;
|
|
Packit |
d7e8d0 |
while (argv[i])
|
|
Packit |
d7e8d0 |
{
|
|
Packit Service |
30b792 |
TRACE_LOG ("argv[%2i] = %s", i, argv[i]);
|
|
Packit |
d7e8d0 |
i++;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* We do not inherit any handles by default, and just insert those
|
|
Packit |
d7e8d0 |
handles we want the child to have afterwards. But some handle
|
|
Packit |
d7e8d0 |
values occur on the command line, and we need to move
|
|
Packit |
d7e8d0 |
stdin/out/err to the right location. So we use a wrapper program
|
|
Packit |
d7e8d0 |
which gets the information from a temporary file. */
|
|
Packit |
d7e8d0 |
if (_gpgme_mkstemp (&tmp_fd, &tmp_name) < 0)
|
|
Packit |
d7e8d0 |
{
|
|
Packit Service |
30b792 |
TRACE_LOG ("_gpgme_mkstemp failed: %s", strerror (errno));
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit Service |
30b792 |
TRACE_LOG ("tmp_name = %s", tmp_name);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
args = calloc (2 + i + 1, sizeof (*args));
|
|
Packit |
d7e8d0 |
args[0] = (char *) _gpgme_get_w32spawn_path ();
|
|
Packit |
d7e8d0 |
args[1] = tmp_name;
|
|
Packit |
d7e8d0 |
args[2] = path;
|
|
Packit |
d7e8d0 |
memcpy (&args[3], &argv[1], i * sizeof (*args));
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
memset (&sec_attr, 0, sizeof sec_attr);
|
|
Packit |
d7e8d0 |
sec_attr.nLength = sizeof sec_attr;
|
|
Packit |
d7e8d0 |
sec_attr.bInheritHandle = FALSE;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
arg_string = build_commandline (args);
|
|
Packit |
d7e8d0 |
free (args);
|
|
Packit |
d7e8d0 |
if (!arg_string)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
close (tmp_fd);
|
|
Packit |
d7e8d0 |
DeleteFile (tmp_name);
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
memset (&si, 0, sizeof si);
|
|
Packit |
d7e8d0 |
si.cb = sizeof (si);
|
|
Packit |
d7e8d0 |
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
|
Packit |
d7e8d0 |
si.wShowWindow = debug_me ? SW_SHOW : SW_HIDE;
|
|
Packit |
d7e8d0 |
si.hStdInput = INVALID_HANDLE_VALUE;
|
|
Packit |
d7e8d0 |
si.hStdOutput = INVALID_HANDLE_VALUE;
|
|
Packit |
d7e8d0 |
si.hStdError = INVALID_HANDLE_VALUE;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
cr_flags |= CREATE_SUSPENDED;
|
|
Packit |
d7e8d0 |
if ((flags & IOSPAWN_FLAG_DETACHED))
|
|
Packit |
d7e8d0 |
cr_flags |= DETACHED_PROCESS;
|
|
Packit |
d7e8d0 |
if (!CreateProcessA (_gpgme_get_w32spawn_path (),
|
|
Packit |
d7e8d0 |
arg_string,
|
|
Packit |
d7e8d0 |
&sec_attr, /* process security attributes */
|
|
Packit |
d7e8d0 |
&sec_attr, /* thread security attributes */
|
|
Packit |
d7e8d0 |
FALSE, /* inherit handles */
|
|
Packit |
d7e8d0 |
cr_flags, /* creation flags */
|
|
Packit |
d7e8d0 |
NULL, /* environment */
|
|
Packit |
d7e8d0 |
NULL, /* use current drive/directory */
|
|
Packit |
d7e8d0 |
&si, /* startup information */
|
|
Packit |
d7e8d0 |
&pi)) /* returns process information */
|
|
Packit |
d7e8d0 |
{
|
|
Packit Service |
30b792 |
TRACE_LOG ("CreateProcess failed: ec=%d", (int) GetLastError ());
|
|
Packit |
d7e8d0 |
free (arg_string);
|
|
Packit |
d7e8d0 |
close (tmp_fd);
|
|
Packit |
d7e8d0 |
DeleteFile (tmp_name);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* FIXME: Should translate the error code. */
|
|
Packit |
d7e8d0 |
errno = EIO;
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
free (arg_string);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (flags & IOSPAWN_FLAG_ALLOW_SET_FG)
|
|
Packit |
d7e8d0 |
_gpgme_allow_set_foreground_window ((pid_t)pi.dwProcessId);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* Insert the inherited handles. */
|
|
Packit |
d7e8d0 |
for (i = 0; fd_list[i].fd != -1; i++)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
HANDLE hd;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* Make it inheritable for the wrapper process. */
|
|
Packit |
d7e8d0 |
if (!DuplicateHandle (GetCurrentProcess(),
|
|
Packit |
d7e8d0 |
_get_osfhandle (giochannel_table[fd_list[i].fd].fd),
|
|
Packit |
d7e8d0 |
pi.hProcess, &hd, 0, TRUE, DUPLICATE_SAME_ACCESS))
|
|
Packit |
d7e8d0 |
{
|
|
Packit Service |
30b792 |
TRACE_LOG ("DuplicateHandle failed: ec=%d", (int) GetLastError ());
|
|
Packit |
d7e8d0 |
TerminateProcess (pi.hProcess, 0);
|
|
Packit |
d7e8d0 |
/* Just in case TerminateProcess didn't work, let the
|
|
Packit |
d7e8d0 |
process fail on its own. */
|
|
Packit |
d7e8d0 |
ResumeThread (pi.hThread);
|
|
Packit |
d7e8d0 |
CloseHandle (pi.hThread);
|
|
Packit |
d7e8d0 |
CloseHandle (pi.hProcess);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
close (tmp_fd);
|
|
Packit |
d7e8d0 |
DeleteFile (tmp_name);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* FIXME: Should translate the error code. */
|
|
Packit |
d7e8d0 |
errno = EIO;
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
/* Return the child name of this handle. */
|
|
Packit |
d7e8d0 |
fd_list[i].peer_name = (int) hd;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* Write the handle translation information to the temporary
|
|
Packit |
d7e8d0 |
file. */
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
/* Hold roughly MAX_TRANS quadruplets of 64 bit numbers in hex
|
|
Packit |
d7e8d0 |
notation: "0xFEDCBA9876543210" with an extra white space after
|
|
Packit |
d7e8d0 |
every quadruplet. 10*(19*4 + 1) - 1 = 769. This plans ahead
|
|
Packit |
d7e8d0 |
for a time when a HANDLE is 64 bit. */
|
|
Packit |
d7e8d0 |
#define BUFFER_MAX 800
|
|
Packit |
d7e8d0 |
char line[BUFFER_MAX + 1];
|
|
Packit |
d7e8d0 |
int res;
|
|
Packit |
d7e8d0 |
int written;
|
|
Packit |
d7e8d0 |
size_t len;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if ((flags & IOSPAWN_FLAG_ALLOW_SET_FG))
|
|
Packit |
d7e8d0 |
strcpy (line, "~1 \n");
|
|
Packit |
d7e8d0 |
else
|
|
Packit |
d7e8d0 |
strcpy (line, "\n");
|
|
Packit |
d7e8d0 |
for (i = 0; fd_list[i].fd != -1; i++)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
/* Strip the newline. */
|
|
Packit |
d7e8d0 |
len = strlen (line) - 1;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* Format is: Local name, stdin/stdout/stderr, peer name, argv idx. */
|
|
Packit |
d7e8d0 |
snprintf (&line[len], BUFFER_MAX - len, "0x%x %d 0x%x %d \n",
|
|
Packit |
d7e8d0 |
fd_list[i].fd, fd_list[i].dup_to,
|
|
Packit |
d7e8d0 |
fd_list[i].peer_name, fd_list[i].arg_loc);
|
|
Packit |
d7e8d0 |
/* Rather safe than sorry. */
|
|
Packit |
d7e8d0 |
line[BUFFER_MAX - 1] = '\n';
|
|
Packit |
d7e8d0 |
line[BUFFER_MAX] = '\0';
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
len = strlen (line);
|
|
Packit |
d7e8d0 |
written = 0;
|
|
Packit |
d7e8d0 |
do
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
res = write (tmp_fd, &line[written], len - written);
|
|
Packit |
d7e8d0 |
if (res > 0)
|
|
Packit |
d7e8d0 |
written += res;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
while (res > 0 || (res < 0 && errno == EAGAIN));
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
close (tmp_fd);
|
|
Packit |
d7e8d0 |
/* The temporary file is deleted by the gpgme-w32spawn process
|
|
Packit |
d7e8d0 |
(hopefully). */
|
|
Packit |
d7e8d0 |
|
|
Packit Service |
30b792 |
TRACE_LOG ("CreateProcess ready: hProcess=%p, hThread=%p, "
|
|
Packit |
d7e8d0 |
"dwProcessID=%d, dwThreadId=%d",
|
|
Packit |
d7e8d0 |
pi.hProcess, pi.hThread,
|
|
Packit |
d7e8d0 |
(int) pi.dwProcessId, (int) pi.dwThreadId);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (r_pid)
|
|
Packit |
d7e8d0 |
*r_pid = (pid_t)pi.dwProcessId;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (ResumeThread (pi.hThread) < 0)
|
|
Packit Service |
30b792 |
TRACE_LOG ("ResumeThread failed: ec=%d", (int) GetLastError ());
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (!CloseHandle (pi.hThread))
|
|
Packit Service |
30b792 |
TRACE_LOG ("CloseHandle of thread failed: ec=%d",
|
|
Packit |
d7e8d0 |
(int) GetLastError ());
|
|
Packit |
d7e8d0 |
|
|
Packit Service |
30b792 |
TRACE_LOG ("process=%p", pi.hProcess);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* We don't need to wait for the process. */
|
|
Packit |
d7e8d0 |
if (!CloseHandle (pi.hProcess))
|
|
Packit Service |
30b792 |
TRACE_LOG ("CloseHandle of process failed: ec=%d",
|
|
Packit |
d7e8d0 |
(int) GetLastError ());
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (! (flags & IOSPAWN_FLAG_NOCLOSE))
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
for (i = 0; fd_list[i].fd != -1; i++)
|
|
Packit |
d7e8d0 |
_gpgme_io_close (fd_list[i].fd);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
for (i = 0; fd_list[i].fd != -1; i++)
|
|
Packit |
d7e8d0 |
if (fd_list[i].dup_to == -1)
|
|
Packit Service |
30b792 |
TRACE_LOG ("fd[%i] = 0x%x -> 0x%x", i, fd_list[i].fd,
|
|
Packit |
d7e8d0 |
fd_list[i].peer_name);
|
|
Packit |
d7e8d0 |
else
|
|
Packit Service |
30b792 |
TRACE_LOG ("fd[%i] = 0x%x -> 0x%x (std%s)", i, fd_list[i].fd,
|
|
Packit |
d7e8d0 |
fd_list[i].peer_name, (fd_list[i].dup_to == 0) ? "in" :
|
|
Packit |
d7e8d0 |
((fd_list[i].dup_to == 1) ? "out" : "err"));
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (0);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* Select on the list of fds. Returns: -1 = error, 0 = timeout or
|
|
Packit |
d7e8d0 |
nothing to select, > 0 = number of signaled fds. */
|
|
Packit |
d7e8d0 |
int
|
|
Packit |
d7e8d0 |
_gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
int npollfds;
|
|
Packit |
d7e8d0 |
GPollFD *pollfds;
|
|
Packit |
d7e8d0 |
int *pollfds_map;
|
|
Packit |
d7e8d0 |
int i;
|
|
Packit |
d7e8d0 |
int j;
|
|
Packit |
d7e8d0 |
int any;
|
|
Packit |
d7e8d0 |
int n;
|
|
Packit |
d7e8d0 |
int count;
|
|
Packit |
d7e8d0 |
/* Use a 1s timeout. */
|
|
Packit |
d7e8d0 |
int timeout = 1000;
|
|
Packit |
d7e8d0 |
void *dbg_help = NULL;
|
|
Packit Service |
30b792 |
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_select", fds,
|
|
Packit |
d7e8d0 |
"nfds=%u, nonblock=%u", nfds, nonblock);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (nonblock)
|
|
Packit |
d7e8d0 |
timeout = 0;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
pollfds = calloc (nfds, sizeof *pollfds);
|
|
Packit |
d7e8d0 |
if (!pollfds)
|
|
Packit |
d7e8d0 |
return -1;
|
|
Packit |
d7e8d0 |
pollfds_map = calloc (nfds, sizeof *pollfds_map);
|
|
Packit |
d7e8d0 |
if (!pollfds_map)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
free (pollfds);
|
|
Packit |
d7e8d0 |
return -1;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
npollfds = 0;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
TRACE_SEQ (dbg_help, "select on [ ");
|
|
Packit |
d7e8d0 |
any = 0;
|
|
Packit |
d7e8d0 |
for (i = 0; i < nfds; i++)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
GIOChannel *chan = NULL;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (fds[i].fd == -1)
|
|
Packit |
d7e8d0 |
continue;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if ((fds[i].for_read || fds[i].for_write)
|
|
Packit |
d7e8d0 |
&& !(chan = find_channel (fds[i].fd)))
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
TRACE_ADD1 (dbg_help, "[BAD0x%x ", fds[i].fd);
|
|
Packit |
d7e8d0 |
TRACE_END (dbg_help, "]");
|
|
Packit |
d7e8d0 |
assert (!"see log file");
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
else if (fds[i].for_read )
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
assert(chan);
|
|
Packit |
d7e8d0 |
g_io_channel_win32_make_pollfd (chan, G_IO_IN, pollfds + npollfds);
|
|
Packit |
d7e8d0 |
pollfds_map[npollfds] = i;
|
|
Packit |
d7e8d0 |
TRACE_ADD2 (dbg_help, "r0x%x<%d> ", fds[i].fd, pollfds[npollfds].fd);
|
|
Packit |
d7e8d0 |
npollfds++;
|
|
Packit |
d7e8d0 |
any = 1;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
else if (fds[i].for_write)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
assert(chan);
|
|
Packit |
d7e8d0 |
g_io_channel_win32_make_pollfd (chan, G_IO_OUT, pollfds + npollfds);
|
|
Packit |
d7e8d0 |
pollfds_map[npollfds] = i;
|
|
Packit |
d7e8d0 |
TRACE_ADD2 (dbg_help, "w0x%x<%d> ", fds[i].fd, pollfds[npollfds].fd);
|
|
Packit |
d7e8d0 |
npollfds++;
|
|
Packit |
d7e8d0 |
any = 1;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
fds[i].signaled = 0;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
TRACE_END (dbg_help, "]");
|
|
Packit |
d7e8d0 |
if (!any)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
count = 0;
|
|
Packit |
d7e8d0 |
goto leave;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
count = g_io_channel_win32_poll (pollfds, npollfds, timeout);
|
|
Packit |
d7e8d0 |
if (count < 0)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
int saved_errno = errno;
|
|
Packit |
d7e8d0 |
errno = saved_errno;
|
|
Packit |
d7e8d0 |
goto leave;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
TRACE_SEQ (dbg_help, "select OK [ ");
|
|
Packit |
d7e8d0 |
if (TRACE_ENABLED (dbg_help))
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
for (i = 0; i < npollfds; i++)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
if ((pollfds[i].revents & G_IO_IN))
|
|
Packit |
d7e8d0 |
TRACE_ADD1 (dbg_help, "r0x%x ", fds[pollfds_map[i]].fd);
|
|
Packit |
d7e8d0 |
if ((pollfds[i].revents & G_IO_OUT))
|
|
Packit |
d7e8d0 |
TRACE_ADD1 (dbg_help, "w0x%x ", fds[pollfds_map[i]].fd);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
TRACE_END (dbg_help, "]");
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* COUNT is used to stop the lop as soon as possible. */
|
|
Packit |
d7e8d0 |
for (n = count, i = 0; i < npollfds && n; i++)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
j = pollfds_map[i];
|
|
Packit |
d7e8d0 |
assert (j >= 0 && j < nfds);
|
|
Packit |
d7e8d0 |
if (fds[j].fd == -1)
|
|
Packit |
d7e8d0 |
;
|
|
Packit |
d7e8d0 |
else if (fds[j].for_read)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
if ((pollfds[i].revents & G_IO_IN))
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
fds[j].signaled = 1;
|
|
Packit |
d7e8d0 |
n--;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
else if (fds[j].for_write)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
if ((pollfds[i].revents & G_IO_OUT))
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
fds[j].signaled = 1;
|
|
Packit |
d7e8d0 |
n--;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
leave:
|
|
Packit |
d7e8d0 |
free (pollfds);
|
|
Packit |
d7e8d0 |
free (pollfds_map);
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (count);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
int
|
|
Packit |
d7e8d0 |
_gpgme_io_dup (int fd)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
int newfd;
|
|
Packit |
d7e8d0 |
GIOChannel *chan;
|
|
Packit |
d7e8d0 |
|
|
Packit Service |
30b792 |
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_dup", fd, "");
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (fd < 0 || fd >= MAX_SLAFD || !giochannel_table[fd].used)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
errno = EINVAL;
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
for (newfd = 0; newfd < MAX_SLAFD; newfd++)
|
|
Packit |
d7e8d0 |
if (! giochannel_table[newfd].used)
|
|
Packit |
d7e8d0 |
break;
|
|
Packit |
d7e8d0 |
if (newfd == MAX_SLAFD)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
errno = EIO;
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
chan = giochannel_table[fd].chan;
|
|
Packit |
d7e8d0 |
g_io_channel_ref (chan);
|
|
Packit |
d7e8d0 |
giochannel_table[newfd].used = 1;
|
|
Packit |
d7e8d0 |
giochannel_table[newfd].chan = chan;
|
|
Packit |
d7e8d0 |
giochannel_table[newfd].fd = -1;
|
|
Packit |
d7e8d0 |
giochannel_table[newfd].socket = INVALID_SOCKET;
|
|
Packit |
d7e8d0 |
giochannel_table[newfd].primary = 0;
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (newfd);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
static int
|
|
Packit |
d7e8d0 |
wsa2errno (int err)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
switch (err)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
case WSAENOTSOCK:
|
|
Packit |
d7e8d0 |
return EINVAL;
|
|
Packit |
d7e8d0 |
case WSAEWOULDBLOCK:
|
|
Packit |
d7e8d0 |
return EAGAIN;
|
|
Packit |
d7e8d0 |
case ERROR_BROKEN_PIPE:
|
|
Packit |
d7e8d0 |
return EPIPE;
|
|
Packit |
d7e8d0 |
case WSANOTINITIALISED:
|
|
Packit |
d7e8d0 |
return ENOSYS;
|
|
Packit |
d7e8d0 |
default:
|
|
Packit |
d7e8d0 |
return EIO;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
int
|
|
Packit |
d7e8d0 |
_gpgme_io_socket (int domain, int type, int proto)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
int res;
|
|
Packit |
d7e8d0 |
int fd;
|
|
Packit |
d7e8d0 |
|
|
Packit Service |
30b792 |
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_socket", domain,
|
|
Packit |
d7e8d0 |
"type=%i, protp=%i", type, proto);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
res = socket (domain, type, proto);
|
|
Packit |
d7e8d0 |
if (res == INVALID_SOCKET)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
errno = wsa2errno (WSAGetLastError ());
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
fd = new_channel_from_socket (res);
|
|
Packit |
d7e8d0 |
if (fd < 0)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
int saved_errno = errno;
|
|
Packit |
d7e8d0 |
closesocket (res);
|
|
Packit |
d7e8d0 |
errno = saved_errno;
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit Service |
30b792 |
TRACE_SUC ("fd=%i, socket=0x%x", fd, res);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
return fd;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
int
|
|
Packit |
d7e8d0 |
_gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
GIOChannel *chan;
|
|
Packit |
d7e8d0 |
int sockfd;
|
|
Packit |
d7e8d0 |
int res;
|
|
Packit |
d7e8d0 |
GIOFlags flags;
|
|
Packit |
d7e8d0 |
GIOStatus status;
|
|
Packit |
d7e8d0 |
GError *err = NULL;
|
|
Packit |
d7e8d0 |
|
|
Packit Service |
30b792 |
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_connect", fd,
|
|
Packit |
d7e8d0 |
"addr=%p, addrlen=%i", addr, addrlen);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
chan = find_channel (fd);
|
|
Packit |
d7e8d0 |
if (! chan)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
errno = EINVAL;
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
flags = g_io_channel_get_flags (chan);
|
|
Packit |
d7e8d0 |
if (flags & G_IO_FLAG_NONBLOCK)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
status = g_io_channel_set_flags (chan, flags & ~G_IO_FLAG_NONBLOCK, &err;;
|
|
Packit |
d7e8d0 |
if (err)
|
|
Packit |
d7e8d0 |
{
|
|
Packit Service |
30b792 |
TRACE_LOG ("setting flags error: %s", err->message);
|
|
Packit |
d7e8d0 |
g_error_free (err);
|
|
Packit |
d7e8d0 |
err = NULL;
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
if (status != G_IO_STATUS_NORMAL)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
errno = EIO;
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
sockfd = giochannel_table[fd].socket;
|
|
Packit |
d7e8d0 |
if (sockfd == INVALID_SOCKET)
|
|
Packit |
d7e8d0 |
{
|
|
Packit |
d7e8d0 |
errno = EINVAL;
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit Service |
30b792 |
TRACE_LOG ("connect socket fd=%d", sockfd);
|
|
Packit |
d7e8d0 |
res = connect (sockfd, addr, addrlen);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
/* FIXME: Error ignored here. */
|
|
Packit |
d7e8d0 |
if (! (flags & G_IO_FLAG_NONBLOCK))
|
|
Packit |
d7e8d0 |
g_io_channel_set_flags (chan, flags, NULL);
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
if (res)
|
|
Packit |
d7e8d0 |
{
|
|
Packit Service |
30b792 |
TRACE_LOG ("connect failed: %i %i", res, WSAGetLastError ());
|
|
Packit |
d7e8d0 |
|
|
Packit |
d7e8d0 |
errno = wsa2errno (WSAGetLastError ());
|
|
Packit |
d7e8d0 |
return TRACE_SYSRES (-1);
|
|
Packit |
d7e8d0 |
}
|
|
Packit |
d7e8d0 |
|
|
Packit Service |
30b792 |
TRACE_SUC ("");
|
|
Packit Service |
30b792 |
|
|
Packit Service |
30b792 |
return 0;
|
|
Packit |
d7e8d0 |
}
|