gpgme_error_t _gpgme_data_inbound_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; char buffer[BUFFER_SIZE]; char *bufp = buffer; gpgme_ssize_t buflen; TRACE_BEG1 (DEBUG_CTX, "_gpgme_data_inbound_handler", dh, "fd=0x%x", fd); buflen = _gpgme_io_read (fd, buffer, BUFFER_SIZE); if (buflen < 0) return gpg_error_from_syserror (); if (buflen == 0) { _gpgme_io_close (fd); return TRACE_ERR (0); } do { gpgme_ssize_t amt = gpgme_data_write (dh, bufp, buflen); if (amt == 0 || (amt < 0 && errno != EINTR)) return TRACE_ERR (gpg_error_from_syserror ()); bufp += amt; buflen -= amt; } while (buflen > 0); return TRACE_ERR (0); }
gpgme_error_t _gpgme_data_inbound_handler(void *opaque, int fd) { gpgme_data_t dh = (gpgme_data_t) opaque; char buffer[BUFFER_SIZE]; char *bufp = buffer; ssize_t buflen; buflen = _gpgme_io_read(fd, buffer, BUFFER_SIZE); if(buflen < 0) return gpg_error_from_errno(errno); if(buflen == 0) { _gpgme_io_close(fd); return 0; } do { ssize_t amt = gpgme_data_write(dh, bufp, buflen); if(amt == 0 || (amt < 0 && errno != EINTR)) return gpg_error_from_errno(errno); bufp += amt; buflen -= amt; } while(buflen > 0); return 0; }
/* This function provides access to the internal read function; it is normally not used. */ gpgme_ssize_t gpgme_io_read (int fd, void *buffer, size_t count) { int ret; TRACE_BEG2 (DEBUG_GLOBAL, "gpgme_io_read", fd, "buffer=%p, count=%u", buffer, count); ret = _gpgme_io_read (fd, buffer, count); return TRACE_SYSRES (ret); }
static gpgme_ssize_t my_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size) { return _gpgme_io_read ((int) fd, buffer, size); }
/* Read from gpgconf and pass line after line to the hook function. We put a limit of 64 k on the maximum size for a line. This should allow for quite a long "group" line, which is usually the longest line (mine is currently ~3k). */ static gpgme_error_t gpgconf_read (void *engine, char *arg1, char *arg2, gpgme_error_t (*cb) (void *hook, char *line), void *hook) { struct engine_gpgconf *gpgconf = engine; gpgme_error_t err = 0; char *linebuf; size_t linebufsize; int linelen; char *argv[4] = { NULL /* file_name */, NULL, NULL, NULL }; int rp[2]; struct spawn_fd_item_s cfd[] = { {-1, 1 /* STDOUT_FILENO */, -1, 0}, {-1, -1} }; int status; int nread; char *mark = NULL; argv[1] = arg1; argv[2] = arg2; /* 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, 1) < 0) return gpg_error_from_syserror (); cfd[0].fd = rp[1]; 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 (); } linebufsize = 1024; /* Usually enough for conf lines. */ linebuf = malloc (linebufsize); if (!linebuf) { err = gpg_error_from_syserror (); goto leave; } linelen = 0; while ((nread = _gpgme_io_read (rp[0], linebuf + linelen, linebufsize - linelen - 1))) { char *line; const char *lastmark = NULL; size_t nused; if (nread < 0) { err = gpg_error_from_syserror (); goto leave; } linelen += nread; linebuf[linelen] = '\0'; for (line=linebuf; (mark = strchr (line, '\n')); line = mark+1 ) { lastmark = mark; if (mark > line && mark[-1] == '\r') mark[-1] = '\0'; else mark[0] = '\0'; /* Got a full line. Due to the CR removal code (which occurs only on Windows) we might be one-off and thus would see empty lines. Don't pass them to the callback. */ err = *line? (*cb) (hook, line) : 0; if (err) goto leave; } nused = lastmark? (lastmark + 1 - linebuf) : 0; memmove (linebuf, linebuf + nused, linelen - nused); linelen -= nused; if (!(linelen < linebufsize - 1)) { char *newlinebuf; if (linelen < 8 * 1024 - 1) linebufsize = 8 * 1024; else if (linelen < 64 * 1024 - 1) linebufsize = 64 * 1024; else { /* We reached our limit - give up. */ err = gpg_error (GPG_ERR_LINE_TOO_LONG); goto leave; } newlinebuf = realloc (linebuf, linebufsize); if (!newlinebuf) { err = gpg_error_from_syserror (); goto leave; } linebuf = newlinebuf; } } leave: free (linebuf); _gpgme_io_close (rp[0]); return err; }
static gpgme_error_t gpgconf_read (void *engine, char *arg1, char *arg2, gpgme_error_t (*cb) (void *hook, char *line), void *hook) { struct engine_gpgconf *gpgconf = engine; gpgme_error_t err = 0; #define LINELENGTH 1024 char linebuf[LINELENGTH] = ""; int linelen = 0; char *argv[4] = { NULL /* file_name */, NULL, NULL, NULL }; int rp[2]; struct spawn_fd_item_s cfd[] = { {-1, 1 /* STDOUT_FILENO */, -1, 0}, {-1, -1} }; int status; int nread; char *mark = NULL; argv[1] = arg1; argv[2] = arg2; /* 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, 1) < 0) return gpg_error_from_syserror (); cfd[0].fd = rp[1]; 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 (); } do { nread = _gpgme_io_read (rp[0], linebuf + linelen, LINELENGTH - linelen - 1); if (nread > 0) { char *line; const char *lastmark = NULL; size_t nused; linelen += nread; linebuf[linelen] = '\0'; for (line=linebuf; (mark = strchr (line, '\n')); line = mark+1 ) { lastmark = mark; if (mark > line && mark[-1] == '\r') mark[-1] = '\0'; else mark[0] = '\0'; /* Got a full line. Due to the CR removal code (which occurs only on Windows) we might be one-off and thus would see empty lines. Don't pass them to the callback. */ err = *line? (*cb) (hook, line) : 0; if (err) goto leave; } nused = lastmark? (lastmark + 1 - linebuf) : 0; memmove (linebuf, linebuf + nused, linelen - nused); linelen -= nused; } } while (nread > 0 && linelen < LINELENGTH - 1); if (!err && nread < 0) err = gpg_error_from_syserror (); if (!err && nread > 0) err = gpg_error (GPG_ERR_LINE_TOO_LONG); leave: _gpgme_io_close (rp[0]); return err; }