/* Export the keys listed in PATTERN into KEYDATA. */ gpgme_error_t gpgme_op_export_ext (gpgme_ctx_t ctx, const char *pattern[], gpgme_export_mode_t mode, gpgme_data_t keydata) { gpgme_error_t err; TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_ext_start", ctx, "mode=0x%x, keydata=%p", mode, keydata); if (_gpgme_debug_trace () && pattern) { int i = 0; while (pattern[i]) { TRACE_LOG2 ("pattern[%i] = %s", i, pattern[i]); i++; } } err = export_ext_start (ctx, 1, pattern, mode, keydata); if (!err) err = _gpgme_wait_one (ctx); return TRACE_ERR (err); }
int _gpgme_io_set_close_notify (int fd, _gpgme_close_notify_handler_t handler, void *value) { int i; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_set_close_notify", fd, "close_handler=%p/%p", handler, value); assert (fd != -1); LOCK (notify_table_lock); for (i=0; i < DIM (notify_table); i++) if (notify_table[i].inuse && notify_table[i].fd == fd) break; if (i == DIM (notify_table)) for (i = 0; i < DIM (notify_table); i++) if (!notify_table[i].inuse) break; if (i == DIM (notify_table)) { UNLOCK (notify_table_lock); errno = EINVAL; return TRACE_SYSRES (-1); } notify_table[i].fd = fd; notify_table[i].handler = handler; notify_table[i].value = value; notify_table[i].inuse = 1; UNLOCK (notify_table_lock); return TRACE_SYSRES (0); }
int _gpgme_io_socket (int domain, int type, int proto) { int res; int fd; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_socket", domain, "type=%i, protp=%i", type, proto); res = socket (domain, type, proto); if (res == INVALID_SOCKET) { errno = wsa2errno (WSAGetLastError ()); return TRACE_SYSRES (-1); } fd = new_channel_from_socket (res); if (fd < 0) { int saved_errno = errno; closesocket (res); errno = saved_errno; return TRACE_SYSRES (-1); } TRACE_SUC2 ("fd=%i, socket=0x%x", fd, res); return fd; }
gpgme_error_t gpgme_op_export_keys (gpgme_ctx_t ctx, gpgme_key_t keys[], gpgme_export_mode_t mode, gpgme_data_t keydata) { gpgme_error_t err; TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_keys", ctx, "mode=0x%x, keydata=%p", mode, keydata); if (_gpgme_debug_trace () && keys) { int i = 0; while (keys[i]) { TRACE_LOG3 ("keys[%i] = %p (%s)", i, keys[i], (keys[i]->subkeys && keys[i]->subkeys->fpr) ? keys[i]->subkeys->fpr : "invalid"); i++; } } err = export_keys_start (ctx, 1, keys, mode, keydata); if (!err) err = _gpgme_wait_one (ctx); return TRACE_ERR (err); }
gpgme_error_t gpgme_op_trustlist_start (gpgme_ctx_t ctx, const char *pattern, int max_level) { gpgme_error_t err = 0; void *hook; op_data_t opd; TRACE_BEG2 (DEBUG_CTX, "gpgme_op_trustlist_start", ctx, "pattern=%s, max_level=%i", pattern, max_level); if (!pattern || !*pattern) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); err = _gpgme_op_reset (ctx, 2); if (err) return TRACE_ERR (err); err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook, sizeof (*opd), NULL); opd = hook; if (err) return TRACE_ERR (err); _gpgme_engine_set_status_handler (ctx->engine, trustlist_status_handler, ctx); err = _gpgme_engine_set_colon_line_handler (ctx->engine, trustlist_colon_handler, ctx); if (err) return TRACE_ERR (err); err = _gpgme_engine_op_trustlist (ctx->engine, pattern); return TRACE_ERR (err); }
gpgme_error_t gpgme_set_protocol (gpgme_ctx_t ctx, gpgme_protocol_t protocol) { TRACE_BEG2 (DEBUG_CTX, "gpgme_set_protocol", ctx, "protocol=%i (%s)", protocol, gpgme_get_protocol_name (protocol) ? gpgme_get_protocol_name (protocol) : "invalid"); if (protocol != GPGME_PROTOCOL_OpenPGP && protocol != GPGME_PROTOCOL_CMS && protocol != GPGME_PROTOCOL_GPGCONF && protocol != GPGME_PROTOCOL_ASSUAN && protocol != GPGME_PROTOCOL_G13 && protocol != GPGME_PROTOCOL_UISERVER && protocol != GPGME_PROTOCOL_SPAWN) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); if (ctx->protocol != protocol) { /* Shut down the engine when switching protocols. */ if (ctx->engine) { TRACE_LOG1 ("releasing ctx->engine=%p", ctx->engine); _gpgme_engine_release (ctx->engine); ctx->engine = NULL; } ctx->protocol = protocol; } return TRACE_ERR (0); }
gpgme_error_t _gpgme_cancel_with_err (gpgme_ctx_t ctx, gpg_error_t ctx_err, gpg_error_t op_err) { gpgme_error_t err; struct gpgme_io_event_done_data data; TRACE_BEG2 (DEBUG_CTX, "_gpgme_cancel_with_err", ctx, "ctx_err=%i, op_err=%i", ctx_err, op_err); if (ctx_err) { err = _gpgme_engine_cancel (ctx->engine); if (err) return TRACE_ERR (err); } else { err = _gpgme_engine_cancel_op (ctx->engine); if (err) return TRACE_ERR (err); } data.err = ctx_err; data.op_err = op_err; _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &data); return TRACE_ERR (0); }
/* Set the current position from where the next read or write starts in the data object with the handle DH to OFFSET, relativ to WHENCE. */ gpgme_off_t gpgme_data_seek (gpgme_data_t dh, gpgme_off_t offset, int whence) { TRACE_BEG2 (DEBUG_DATA, "gpgme_data_seek", dh, "offset=%lli, whence=%i", offset, whence); if (!dh) { gpg_err_set_errno (EINVAL); return TRACE_SYSRES (-1); } if (!dh->cbs->seek) { gpg_err_set_errno (ENOSYS); return TRACE_SYSRES (-1); } /* For relative movement, we must take into account the actual position of the read counter. */ if (whence == SEEK_CUR) offset -= dh->pending_len; offset = (*dh->cbs->seek) (dh, offset, whence); if (offset >= 0) dh->pending_len = 0; return TRACE_SYSRES (offset); }
/* Add KEY to list of signers in CTX. */ gpgme_error_t gpgme_signers_add (gpgme_ctx_t ctx, const gpgme_key_t key) { TRACE_BEG2 (DEBUG_CTX, "gpgme_signers_add", ctx, "key=%p (%s)", key, (key->subkeys && key->subkeys->fpr) ? key->subkeys->fpr : "invalid"); if (!ctx || !key) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); if (ctx->signers_len == ctx->signers_size) { gpgme_key_t *newarr; int n = ctx->signers_size + 5; int j; newarr = realloc (ctx->signers, n * sizeof (*newarr)); if (!newarr) return TRACE_ERR (gpg_error_from_errno (errno)); for (j = ctx->signers_size; j < n; j++) newarr[j] = NULL; ctx->signers = newarr; ctx->signers_size = n; } gpgme_key_ref (key); ctx->signers[ctx->signers_len++] = key; return TRACE_SUC (); }
gpgme_error_t gpgme_op_decrypt_start (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain) { gpgme_error_t err; TRACE_BEG2 (DEBUG_CTX, "gpgme_op_decrypt_start", ctx, "cipher=%p, plain=%p", cipher, plain); err = decrypt_start (ctx, 0, cipher, plain); return TRACE_ERR (err); }
/* This function provides access to the internal write function. It is to be used by user callbacks to return data to gpgme. See gpgme_passphrase_cb_t and gpgme_edit_cb_t. */ gpgme_ssize_t gpgme_io_write (int fd, const void *buffer, size_t count) { int ret; TRACE_BEG2 (DEBUG_GLOBAL, "gpgme_io_write", fd, "buffer=%p, count=%u", buffer, count); ret = _gpgme_io_write (fd, buffer, count); return TRACE_SYSRES (ret); }
static ssize_t old_user_read (gpgme_data_t dh, void *buffer, size_t size) { gpgme_error_t err; size_t amt; TRACE_BEG2 (DEBUG_DATA, "gpgme:old_user_read", dh, "buffer=%p, size=%u", buffer, size); err = (*dh->data.old_user.cb) (dh->data.old_user.handle, buffer, size, &amt); if (err) return TRACE_SYSRES (gpgme_error_to_errno (err)); return TRACE_SYSRES (amt); }
int _gpgme_io_read (int fd, void *buffer, size_t count) { int saved_errno = 0; gsize nread; GIOChannel *chan; GIOStatus status; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_read", fd, "buffer=%p, count=%u", buffer, count); chan = find_channel (fd); if (!chan) { TRACE_LOG ("no channel registered"); errno = EINVAL; return TRACE_SYSRES (-1); } TRACE_LOG1 ("channel %p", chan); { GError *err = NULL; status = g_io_channel_read_chars (chan, (gchar *) buffer, count, &nread, &err); if (err) { TRACE_LOG2 ("status %i, err %s", status, err->message); g_error_free (err); } } if (status == G_IO_STATUS_EOF) nread = 0; else if (status == G_IO_STATUS_AGAIN) { nread = -1; saved_errno = EAGAIN; } else if (status != G_IO_STATUS_NORMAL) { TRACE_LOG1 ("status %d", status); nread = -1; saved_errno = EIO; } if (nread != 0 && nread != -1) TRACE_LOGBUF (buffer, nread); errno = saved_errno; return TRACE_SYSRES (nread); }
/* Decrypt ciphertext CIPHER within CTX and store the resulting plaintext in PLAIN. */ gpgme_error_t gpgme_op_decrypt (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain) { gpgme_error_t err; TRACE_BEG2 (DEBUG_CTX, "gpgme_op_decrypt", ctx, "cipher=%p, plain=%p", cipher, plain); if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); err = decrypt_start (ctx, 1, cipher, plain); if (!err) err = _gpgme_wait_one (ctx); return TRACE_ERR (err); }
/* Run the command FILE with the arguments in ARGV. Connect stdin to DATAIN, stdout to DATAOUT, and STDERR to DATAERR. If one the data streams is NULL, connect to /dev/null instead. */ gpgme_error_t gpgme_op_spawn_start (gpgme_ctx_t ctx, 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; TRACE_BEG2 (DEBUG_CTX, "gpgme_op_spawn_start", ctx, "file=(%s) flaggs=%x", file, flags); if (!ctx) return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); err = spawn_start (ctx, 0, file, argv, datain, dataout, dataerr, flags); return err; }
int _gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen) { int res; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_connect", fd, "addr=%p, addrlen=%i", addr, addrlen); res = connect (fd, addr, addrlen); if (!res) { errno = wsa2errno (WSAGetLastError ()); return TRACE_SYSRES (-1); } return TRACE_SUC (); }
static gpgme_error_t add_io_cb (engine_gpgsm_t gpgsm, iocb_data_t *iocbd, gpgme_io_cb_t handler) { gpgme_error_t err; TRACE_BEG2 (DEBUG_ENGINE, "engine-gpgsm:add_io_cb", gpgsm, "fd %d, dir %d", iocbd->fd, iocbd->dir); err = (*gpgsm->io_cbs.add) (gpgsm->io_cbs.add_priv, iocbd->fd, iocbd->dir, handler, iocbd->data, &iocbd->tag); if (err) return TRACE_ERR (err); if (!iocbd->dir) /* FIXME Kludge around poll() problem. */ err = _gpgme_io_set_nonblocking (iocbd->fd); return TRACE_ERR (err); }
static off_t old_user_seek (gpgme_data_t dh, off_t offset, int whence) { gpgme_error_t err; TRACE_BEG2 (DEBUG_DATA, "gpgme:old_user_seek", dh, "offset=%llu, whence=%i", offset, whence); if (whence != SEEK_SET || offset) { errno = EINVAL; return TRACE_SYSRES (-1); } err = (*dh->data.old_user.cb) (dh->data.old_user.handle, NULL, 0, NULL); if (err) return TRACE_SYSRES (gpgme_error_to_errno (err)); return TRACE_SYSRES (0); }
/* This function provides access to the internal write function. It is to be used by user callbacks to return data to gpgme. See gpgme_passphrase_cb_t and gpgme_edit_cb_t. Note that this is a variant of gpgme_io_write which guarantees that all COUNT bytes are written or an error is return. Returns: 0 on success or -1 on error and the sets errno. */ int gpgme_io_writen (int fd, const void *buffer_arg, size_t count) { const char *buffer = buffer_arg; int ret = 0; TRACE_BEG2 (DEBUG_GLOBAL, "gpgme_io_writen", fd, "buffer=%p, count=%u", buffer, count); while (count) { ret = _gpgme_io_write (fd, buffer, count); if (ret < 0) break; buffer += ret; count -= ret; ret = 0; } return TRACE_SYSRES (ret); }
/* Create a new data buffer which retrieves the data from the callback function READ_CB. */ gpgme_error_t gpgme_data_new_with_read_cb (gpgme_data_t *r_dh, int (*read_cb) (void *, char *, size_t, size_t *), void *read_cb_value) { gpgme_error_t err; TRACE_BEG2 (DEBUG_DATA, "gpgme_data_new_with_read_cb", r_dh, "read_cb=%p/%p", read_cb, read_cb_value); err = _gpgme_data_new (r_dh, &old_user_cbs); if (err) return TRACE_ERR (err); (*r_dh)->data.old_user.cb = read_cb; (*r_dh)->data.old_user.handle = read_cb_value; return TRACE_ERR (0); }
int _gpgme_io_set_close_notify (int fd, _gpgme_close_notify_handler_t handler, void *value) { TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_set_close_notify", fd, "close_handler=%p/%p", handler, value); assert (fd != -1); if (fd < 0 || fd >= (int) DIM (notify_table)) { errno = EINVAL; return TRACE_SYSRES (-1); } notify_table[fd].handler = handler; notify_table[fd].value = value; return TRACE_SYSRES (0); }
int _gpgme_io_socket (int domain, int type, int proto) { int res; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_socket", domain, "type=%i, protp=%i", type, proto); res = socket (domain, type, proto); if (res == INVALID_SOCKET) { errno = wsa2errno (WSAGetLastError ()); return TRACE_SYSRES (-1); } TRACE_SUC1 ("socket=0x%x", res); return res; }
int _gpgme_io_write (int fd, const void *buffer, size_t count) { int saved_errno = 0; gsize nwritten; GIOChannel *chan; GIOStatus status; GError *err = NULL; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_write", fd, "buffer=%p, count=%u", buffer, count); TRACE_LOGBUF (buffer, count); chan = find_channel (fd); if (!chan) { TRACE_LOG ("fd %d: no channel registered"); errno = EINVAL; return -1; } status = g_io_channel_write_chars (chan, (gchar *) buffer, count, &nwritten, &err); if (err) { TRACE_LOG1 ("write error: %s", err->message); g_error_free (err); } if (status == G_IO_STATUS_AGAIN) { nwritten = -1; saved_errno = EAGAIN; } else if (status != G_IO_STATUS_NORMAL) { nwritten = -1; saved_errno = EIO; } errno = saved_errno; return TRACE_SYSRES (nwritten); }
/* Read up to SIZE bytes into buffer BUFFER from the data object with the handle DH. Return the number of characters read, 0 on EOF and -1 on error. If an error occurs, errno is set. */ gpgme_ssize_t gpgme_data_read (gpgme_data_t dh, void *buffer, size_t size) { gpgme_ssize_t res; TRACE_BEG2 (DEBUG_DATA, "gpgme_data_read", dh, "buffer=%p, size=%u", buffer, size); if (!dh) { gpg_err_set_errno (EINVAL); return TRACE_SYSRES (-1); } if (!dh->cbs->read) { gpg_err_set_errno (ENOSYS); return TRACE_SYSRES (-1); } do res = (*dh->cbs->read) (dh, buffer, size); while (res < 0 && errno == EINTR); return TRACE_SYSRES (res); }
int _gpgme_io_read (int fd, void *buffer, size_t count) { int nread; struct reader_context_s *ctx; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_read", fd, "buffer=%p, count=%u", buffer, count); ctx = find_reader (fd, 1); if (!ctx) { errno = EBADF; return TRACE_SYSRES (-1); } if (ctx->eof_shortcut) return TRACE_SYSRES (0); LOCK (ctx->mutex); if (ctx->readpos == ctx->writepos && !ctx->error) { /* No data available. */ UNLOCK (ctx->mutex); TRACE_LOG1 ("waiting for data from thread %p", ctx->thread_hd); WaitForSingleObject (ctx->have_data_ev, INFINITE); TRACE_LOG1 ("data from thread %p available", ctx->thread_hd); LOCK (ctx->mutex); } if (ctx->readpos == ctx->writepos || ctx->error) { UNLOCK (ctx->mutex); ctx->eof_shortcut = 1; if (ctx->eof) return TRACE_SYSRES (0); if (!ctx->error) { TRACE_LOG ("EOF but ctx->eof flag not set"); return 0; } errno = ctx->error_code; return TRACE_SYSRES (-1); } nread = ctx->readpos < ctx->writepos ? ctx->writepos - ctx->readpos : READBUF_SIZE - ctx->readpos; if (nread > count) nread = count; memcpy (buffer, ctx->buffer + ctx->readpos, nread); ctx->readpos = (ctx->readpos + nread) % READBUF_SIZE; if (ctx->readpos == ctx->writepos && !ctx->eof) { if (!ResetEvent (ctx->have_data_ev)) { TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ()); UNLOCK (ctx->mutex); /* FIXME: Should translate the error code. */ errno = EIO; return TRACE_SYSRES (-1); } } if (!SetEvent (ctx->have_space_ev)) { TRACE_LOG2 ("SetEvent (0x%x) failed: ec=%d", ctx->have_space_ev, (int) GetLastError ()); UNLOCK (ctx->mutex); /* FIXME: Should translate the error code. */ errno = EIO; return TRACE_SYSRES (-1); } UNLOCK (ctx->mutex); TRACE_LOGBUF (buffer, nread); return TRACE_SYSRES (nread); }
int _gpgme_io_write (int fd, const void *buffer, size_t count) { struct writer_context_s *ctx; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_write", fd, "buffer=%p, count=%u", buffer, count); TRACE_LOGBUF (buffer, count); if (count == 0) return TRACE_SYSRES (0); ctx = find_writer (fd, 0); if (!ctx) return TRACE_SYSRES (-1); LOCK (ctx->mutex); if (!ctx->error && ctx->nbytes) { /* Bytes are pending for send. */ /* Reset the is_empty event. Better safe than sorry. */ if (!ResetEvent (ctx->is_empty)) { TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ()); UNLOCK (ctx->mutex); /* FIXME: Should translate the error code. */ errno = EIO; return TRACE_SYSRES (-1); } UNLOCK (ctx->mutex); TRACE_LOG1 ("waiting for empty buffer in thread %p", ctx->thread_hd); WaitForSingleObject (ctx->is_empty, INFINITE); TRACE_LOG1 ("thread %p buffer is empty", ctx->thread_hd); LOCK (ctx->mutex); } if (ctx->error) { UNLOCK (ctx->mutex); if (ctx->error_code == ERROR_NO_DATA) errno = EPIPE; else errno = EIO; return TRACE_SYSRES (-1); } /* If no error occured, the number of bytes in the buffer must be zero. */ assert (!ctx->nbytes); if (count > WRITEBUF_SIZE) count = WRITEBUF_SIZE; memcpy (ctx->buffer, buffer, count); ctx->nbytes = count; /* We have to reset the is_empty event early, because it is also used by the select() implementation to probe the channel. */ if (!ResetEvent (ctx->is_empty)) { TRACE_LOG1 ("ResetEvent failed: ec=%d", (int) GetLastError ()); UNLOCK (ctx->mutex); /* FIXME: Should translate the error code. */ errno = EIO; return TRACE_SYSRES (-1); } if (!SetEvent (ctx->have_data)) { TRACE_LOG1 ("SetEvent failed: ec=%d", (int) GetLastError ()); UNLOCK (ctx->mutex); /* FIXME: Should translate the error code. */ errno = EIO; return TRACE_SYSRES (-1); } UNLOCK (ctx->mutex); return TRACE_SYSRES ((int) count); }
/* Select on the list of fds. Returns: -1 = error, 0 = timeout or nothing to select, > 0 = number of signaled fds. */ int _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock) { int npollfds; GPollFD *pollfds; int *pollfds_map; int i; int j; int any; int n; int count; /* Use a 1s timeout. */ int timeout = 1000; void *dbg_help = NULL; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_select", fds, "nfds=%u, nonblock=%u", nfds, nonblock); if (nonblock) timeout = 0; pollfds = calloc (nfds, sizeof *pollfds); if (!pollfds) return -1; pollfds_map = calloc (nfds, sizeof *pollfds_map); if (!pollfds_map) { free (pollfds); return -1; } npollfds = 0; TRACE_SEQ (dbg_help, "select on [ "); any = 0; for (i = 0; i < nfds; i++) { GIOChannel *chan = NULL; if (fds[i].fd == -1) continue; if ((fds[i].for_read || fds[i].for_write) && !(chan = find_channel (fds[i].fd))) { TRACE_ADD1 (dbg_help, "[BAD0x%x ", fds[i].fd); TRACE_END (dbg_help, "]"); assert (!"see log file"); } else if (fds[i].for_read ) { assert(chan); g_io_channel_win32_make_pollfd (chan, G_IO_IN, pollfds + npollfds); pollfds_map[npollfds] = i; TRACE_ADD2 (dbg_help, "r0x%x<%d> ", fds[i].fd, pollfds[npollfds].fd); npollfds++; any = 1; } else if (fds[i].for_write) { assert(chan); g_io_channel_win32_make_pollfd (chan, G_IO_OUT, pollfds + npollfds); pollfds_map[npollfds] = i; TRACE_ADD2 (dbg_help, "w0x%x<%d> ", fds[i].fd, pollfds[npollfds].fd); npollfds++; any = 1; } fds[i].signaled = 0; } TRACE_END (dbg_help, "]"); if (!any) { count = 0; goto leave; } count = g_io_channel_win32_poll (pollfds, npollfds, timeout); if (count < 0) { int saved_errno = errno; errno = saved_errno; goto leave; } TRACE_SEQ (dbg_help, "select OK [ "); if (TRACE_ENABLED (dbg_help)) { for (i = 0; i < npollfds; i++) { if ((pollfds[i].revents & G_IO_IN)) TRACE_ADD1 (dbg_help, "r0x%x ", fds[pollfds_map[i]].fd); if ((pollfds[i].revents & G_IO_OUT)) TRACE_ADD1 (dbg_help, "w0x%x ", fds[pollfds_map[i]].fd); } TRACE_END (dbg_help, "]"); } /* COUNT is used to stop the lop as soon as possible. */ for (n = count, i = 0; i < npollfds && n; i++) { j = pollfds_map[i]; assert (j >= 0 && j < nfds); if (fds[j].fd == -1) ; else if (fds[j].for_read) { if ((pollfds[i].revents & G_IO_IN)) { fds[j].signaled = 1; n--; } } else if (fds[j].for_write) { if ((pollfds[i].revents & G_IO_OUT)) { fds[j].signaled = 1; n--; } } } leave: free (pollfds); free (pollfds_map); return TRACE_SYSRES (count); }
int _gpgme_io_pipe (int filedes[2], int inherit_idx) { int fds[2]; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes, "inherit_idx=%i (GPGME uses it for %s)", inherit_idx, inherit_idx ? "reading" : "writing"); #define PIPEBUF_SIZE 4096 if (_pipe (fds, PIPEBUF_SIZE, O_NOINHERIT | O_BINARY) == -1) return TRACE_SYSRES (-1); /* Make one end inheritable. */ if (inherit_idx == 0) { int new_read; new_read = _dup (fds[0]); _close (fds[0]); fds[0] = new_read; if (new_read < 0) { _close (fds[1]); return TRACE_SYSRES (-1); } } else if (inherit_idx == 1) { int new_write; new_write = _dup (fds[1]); _close (fds[1]); fds[1] = new_write; if (new_write < 0) { _close (fds[0]); return TRACE_SYSRES (-1); } } /* For _gpgme_io_close. */ filedes[inherit_idx] = new_dummy_channel_from_fd (fds[inherit_idx]); if (filedes[inherit_idx] < 0) { int saved_errno = errno; _close (fds[0]); _close (fds[1]); errno = saved_errno; return TRACE_SYSRES (-1); } /* Now we have a pipe with the correct end inheritable. The other end should have a giochannel. */ filedes[1 - inherit_idx] = new_channel_from_fd (fds[1 - inherit_idx]); if (filedes[1 - inherit_idx] < 0) { int saved_errno = errno; _gpgme_io_close (fds[inherit_idx]); _close (fds[1 - inherit_idx]); errno = saved_errno; return TRACE_SYSRES (-1); } return TRACE_SUC5 ("read=0x%x/%p, write=0x%x/%p, channel=%p", filedes[0], (HANDLE) _get_osfhandle (giochannel_table[filedes[0]].fd), filedes[1], (HANDLE) _get_osfhandle (giochannel_table[filedes[1]].fd), giochannel_table[1 - inherit_idx].chan); }
int _gpgme_io_pipe (int filedes[2], int inherit_idx) { HANDLE rh; HANDLE wh; SECURITY_ATTRIBUTES sec_attr; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes, "inherit_idx=%i (GPGME uses it for %s)", inherit_idx, inherit_idx ? "reading" : "writing"); memset (&sec_attr, 0, sizeof (sec_attr)); sec_attr.nLength = sizeof (sec_attr); sec_attr.bInheritHandle = FALSE; if (!CreatePipe (&rh, &wh, &sec_attr, PIPEBUF_SIZE)) { TRACE_LOG1 ("CreatePipe failed: ec=%d", (int) GetLastError ()); /* FIXME: Should translate the error code. */ errno = EIO; return TRACE_SYSRES (-1); } /* Make one end inheritable. */ if (inherit_idx == 0) { struct writer_context_s *ctx; HANDLE hd; if (!DuplicateHandle (GetCurrentProcess(), rh, GetCurrentProcess(), &hd, 0, TRUE, DUPLICATE_SAME_ACCESS)) { TRACE_LOG1 ("DuplicateHandle failed: ec=%d", (int) GetLastError ()); CloseHandle (rh); CloseHandle (wh); /* FIXME: Should translate the error code. */ errno = EIO; return TRACE_SYSRES (-1); } CloseHandle (rh); rh = hd; ctx = find_writer (handle_to_fd (wh), 0); assert (ctx == NULL); ctx = find_writer (handle_to_fd (wh), 1); if (!ctx) { CloseHandle (rh); CloseHandle (wh); /* FIXME: Should translate the error code. */ errno = EIO; return TRACE_SYSRES (-1); } } else if (inherit_idx == 1) { struct reader_context_s *ctx; HANDLE hd; if (!DuplicateHandle( GetCurrentProcess(), wh, GetCurrentProcess(), &hd, 0, TRUE, DUPLICATE_SAME_ACCESS)) { TRACE_LOG1 ("DuplicateHandle failed: ec=%d", (int) GetLastError ()); CloseHandle (rh); CloseHandle (wh); /* FIXME: Should translate the error code. */ errno = EIO; return TRACE_SYSRES (-1); } CloseHandle (wh); wh = hd; ctx = find_reader (handle_to_fd (rh), 0); assert (ctx == NULL); ctx = find_reader (handle_to_fd (rh), 1); if (!ctx) { CloseHandle (rh); CloseHandle (wh); /* FIXME: Should translate the error code. */ errno = EIO; return TRACE_SYSRES (-1); } } filedes[0] = handle_to_fd (rh); filedes[1] = handle_to_fd (wh); return TRACE_SUC2 ("read=%p, write=%p", rh, wh); }
int _gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen) { GIOChannel *chan; int sockfd; int res; GIOFlags flags; GIOStatus status; GError *err = NULL; TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_connect", fd, "addr=%p, addrlen=%i", addr, addrlen); chan = find_channel (fd); if (! chan) { errno = EINVAL; return TRACE_SYSRES (-1); } flags = g_io_channel_get_flags (chan); if (flags & G_IO_FLAG_NONBLOCK) { status = g_io_channel_set_flags (chan, flags & ~G_IO_FLAG_NONBLOCK, &err); if (err) { TRACE_LOG1 ("setting flags error: %s", err->message); g_error_free (err); err = NULL; } if (status != G_IO_STATUS_NORMAL) { errno = EIO; return TRACE_SYSRES (-1); } } sockfd = giochannel_table[fd].socket; if (sockfd == INVALID_SOCKET) { errno = EINVAL; return TRACE_SYSRES (-1); } TRACE_LOG1 ("connect sockfd=0x%x", sockfd); res = connect (sockfd, addr, addrlen); /* FIXME: Error ignored here. */ if (! (flags & G_IO_FLAG_NONBLOCK)) g_io_channel_set_flags (chan, flags, NULL); if (res) { TRACE_LOG2 ("connect failed: %i %i", res, WSAGetLastError ()); errno = wsa2errno (WSAGetLastError ()); return TRACE_SYSRES (-1); } return TRACE_SUC (); }