/* 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); }
/* 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); }
gpgme_error_t _gpgme_data_outbound_handler (void *opaque, int fd) { struct io_cb_data *data = (struct io_cb_data *) opaque; gpgme_data_t dh = (gpgme_data_t) data->handler_value; gpgme_ssize_t nwritten; TRACE_BEG1 (DEBUG_CTX, "_gpgme_data_outbound_handler", dh, "fd=0x%x", fd); if (!dh->pending_len) { gpgme_ssize_t amt = gpgme_data_read (dh, dh->pending, BUFFER_SIZE); if (amt < 0) return TRACE_ERR (gpg_error_from_syserror ()); if (amt == 0) { _gpgme_io_close (fd); return TRACE_ERR (0); } dh->pending_len = amt; } nwritten = _gpgme_io_write (fd, dh->pending, dh->pending_len); if (nwritten == -1 && errno == EAGAIN) return TRACE_ERR (0); if (nwritten == -1 && errno == EPIPE) { /* Not much we can do. The other end closed the pipe, but we still have data. This should only ever happen if the other end is going to tell us what happened on some other channel. Silently close our end. */ _gpgme_io_close (fd); return TRACE_ERR (0); } if (nwritten <= 0) return TRACE_ERR (gpg_error_from_syserror ()); if (nwritten < dh->pending_len) memmove (dh->pending, dh->pending + nwritten, dh->pending_len - nwritten); dh->pending_len -= nwritten; return TRACE_ERR (0); }
gpgme_error_t _gpgme_data_outbound_handler(void *opaque, int fd) { gpgme_data_t dh = (gpgme_data_t) opaque; ssize_t nwritten; if(!dh->pending_len) { ssize_t amt = gpgme_data_read(dh, dh->pending, BUFFER_SIZE); if(amt < 0) return gpg_error_from_errno(errno); if(amt == 0) { _gpgme_io_close(fd); return 0; } dh->pending_len = amt; } nwritten = _gpgme_io_write(fd, dh->pending, dh->pending_len); if(nwritten == -1 && errno == EAGAIN) return 0; if(nwritten == -1 && errno == EPIPE) { /* Not much we can do. The other end closed the pipe, but we still have data. This should only ever happen if the other end is going to tell us what happened on some other channel. Silently close our end. */ _gpgme_io_close(fd); return 0; } if(nwritten <= 0) return gpg_error_from_errno(errno); if(nwritten < dh->pending_len) memmove(dh->pending, dh->pending + nwritten, dh->pending_len - nwritten); dh->pending_len -= nwritten; return 0; }
static gpgme_ssize_t my_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer, size_t size) { return _gpgme_io_write ((int) fd, buffer, size); }
static gpgme_error_t gpgconf_write (void *engine, char *arg1, char *arg2, gpgme_data_t conf) { struct engine_gpgconf *gpgconf = engine; gpgme_error_t err = 0; #define BUFLEN 1024 char buf[BUFLEN]; int buflen = 0; char *argv[] = { NULL /* file_name */, arg1, arg2, 0 }; int rp[2]; struct spawn_fd_item_s cfd[] = { {-1, 0 /* STDIN_FILENO */}, {-1, -1} }; int status; int nwrite; /* FIXME: Deal with engine->home_dir. */ /* _gpgme_engine_new guarantees that this is not NULL. */ argv[0] = gpgconf->file_name; if (_gpgme_io_pipe (rp, 0) < 0) return gpg_error_from_syserror (); cfd[0].fd = rp[0]; status = _gpgme_io_spawn (gpgconf->file_name, argv, 0, cfd, NULL, NULL, NULL); if (status < 0) { _gpgme_io_close (rp[0]); _gpgme_io_close (rp[1]); return gpg_error_from_syserror (); } for (;;) { if (buflen == 0) { do { buflen = gpgme_data_read (conf, buf, BUFLEN); } while (buflen < 0 && errno == EAGAIN); if (buflen < 0) { err = gpg_error_from_syserror (); _gpgme_io_close (rp[1]); return err; } else if (buflen == 0) { /* All is written. */ _gpgme_io_close (rp[1]); return 0; } } do { nwrite = _gpgme_io_write (rp[1], buf, buflen); } while (nwrite < 0 && errno == EAGAIN); if (nwrite > 0) { buflen -= nwrite; if (buflen > 0) memmove (&buf[0], &buf[nwrite], buflen); } else if (nwrite < 0) { _gpgme_io_close (rp[1]); return gpg_error_from_syserror (); } } return 0; }