1 /* engine-gpg.c - Gpg Engine.
2 Copyright (C) 2000 Werner Koch (dd9jn)
3 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007,
4 2009, 2010, 2012 g10 Code GmbH
6 This file is part of GPGME.
8 GPGME is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 GPGME is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with this program; if not, see <http://www.gnu.org/licenses/>.
41 #include "context.h" /*temp hack until we have GpmeData methods to do I/O */
46 #include "engine-backend.h"
49 /* This type is used to build a list of gpg arguments and data
53 struct arg_and_data_s *next;
54 gpgme_data_t data; /* If this is not NULL, use arg below. */
55 int inbound; /* True if this is used for reading from gpg. */
57 int print_fd; /* Print the fd number and not the special form of it. */
58 int *arg_locp; /* Write back the argv idx of this argument when
59 building command line to this location. */
60 char arg[1]; /* Used if data above is not used. */
67 int inbound; /* true if this is used for reading from gpg */
69 int fd; /* the fd to use */
70 int peer_fd; /* the other side of the pipe */
71 int arg_loc; /* The index into the argv for translation purposes. */
76 typedef gpgme_error_t (*colon_preprocessor_t) (char *line, char **rline);
85 struct arg_and_data_s *arglist;
86 struct arg_and_data_s **argtail;
96 engine_status_handler_t fnc;
101 /* This is a kludge - see the comment at colon_line_handler. */
110 engine_colon_line_handler_t fnc; /* this indicate use of this structrue */
113 colon_preprocessor_t preprocess_fnc;
117 struct fd_data_map_s *fd_data_map;
119 /* stuff needed for interactive (command) mode */
125 int idx; /* Index in fd_data_map */
126 gpgme_status_code_t code; /* last code */
127 char *keyword; /* what has been requested (malloced) */
128 engine_command_handler_t fnc;
130 /* The kludges never end. This is used to couple command handlers
131 with output data in edit key mode. */
132 gpgme_data_t linked_data;
136 struct gpgme_io_cbs io_cbs;
139 typedef struct engine_gpg *engine_gpg_t;
143 gpg_io_event (void *engine, gpgme_event_io_t type, void *type_data)
145 engine_gpg_t gpg = engine;
147 TRACE3 (DEBUG_ENGINE, "gpgme:gpg_io_event", gpg,
148 "event %p, type %d, type_data %p",
149 gpg->io_cbs.event, type, type_data);
150 if (gpg->io_cbs.event)
151 (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, type, type_data);
156 close_notify_handler (int fd, void *opaque)
158 engine_gpg_t gpg = opaque;
161 if (gpg->status.fd[0] == fd)
164 (*gpg->io_cbs.remove) (gpg->status.tag);
165 gpg->status.fd[0] = -1;
167 else if (gpg->status.fd[1] == fd)
168 gpg->status.fd[1] = -1;
169 else if (gpg->colon.fd[0] == fd)
172 (*gpg->io_cbs.remove) (gpg->colon.tag);
173 gpg->colon.fd[0] = -1;
175 else if (gpg->colon.fd[1] == fd)
176 gpg->colon.fd[1] = -1;
177 else if (gpg->cmd.fd == fd)
179 else if (gpg->fd_data_map)
183 for (i = 0; gpg->fd_data_map[i].data; i++)
185 if (gpg->fd_data_map[i].fd == fd)
187 if (gpg->fd_data_map[i].tag)
188 (*gpg->io_cbs.remove) (gpg->fd_data_map[i].tag);
189 gpg->fd_data_map[i].fd = -1;
192 if (gpg->fd_data_map[i].peer_fd == fd)
194 gpg->fd_data_map[i].peer_fd = -1;
201 /* If FRONT is true, push at the front of the list. Use this for
202 options added late in the process. */
204 _add_arg (engine_gpg_t gpg, const char *arg, int front, int *arg_locp)
206 struct arg_and_data_s *a;
211 a = malloc (sizeof *a + strlen (arg));
213 return gpg_error_from_errno (errno);
217 a->arg_locp = arg_locp;
219 strcpy (a->arg, arg);
222 a->next = gpg->arglist;
225 /* If this is the first argument, we need to update the tail
227 gpg->argtail = &a->next;
235 gpg->argtail = &a->next;
242 add_arg_ext (engine_gpg_t gpg, const char *arg, int front)
244 return _add_arg (gpg, arg, front, NULL);
249 add_arg_with_locp (engine_gpg_t gpg, const char *arg, int *locp)
251 return _add_arg (gpg, arg, 0, locp);
256 add_arg (engine_gpg_t gpg, const char *arg)
258 return add_arg_ext (gpg, arg, 0);
263 add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound)
265 struct arg_and_data_s *a;
270 a = malloc (sizeof *a - 1);
272 return gpg_error_from_errno (errno);
275 a->inbound = inbound;
289 gpg->argtail = &a->next;
295 gpg_get_version (const char *file_name)
297 return _gpgme_get_program_version (file_name ? file_name
298 : _gpgme_get_gpg_path ());
303 gpg_get_req_version (void)
305 return NEED_GPG_VERSION;
310 free_argv (char **argv)
314 for (i = 0; argv[i]; i++)
321 free_fd_data_map (struct fd_data_map_s *fd_data_map)
328 for (i = 0; fd_data_map[i].data; i++)
330 if (fd_data_map[i].fd != -1)
331 _gpgme_io_close (fd_data_map[i].fd);
332 if (fd_data_map[i].peer_fd != -1)
333 _gpgme_io_close (fd_data_map[i].peer_fd);
334 /* Don't release data because this is only a reference. */
341 gpg_cancel (void *engine)
343 engine_gpg_t gpg = engine;
346 return gpg_error (GPG_ERR_INV_VALUE);
348 /* If gpg may be waiting for a cmd, close the cmd fd first. On
349 Windows, close operations block on the reader/writer thread. */
352 if (gpg->cmd.fd != -1)
353 _gpgme_io_close (gpg->cmd.fd);
354 else if (gpg->fd_data_map
355 && gpg->fd_data_map[gpg->cmd.idx].fd != -1)
356 _gpgme_io_close (gpg->fd_data_map[gpg->cmd.idx].fd);
359 if (gpg->status.fd[0] != -1)
360 _gpgme_io_close (gpg->status.fd[0]);
361 if (gpg->status.fd[1] != -1)
362 _gpgme_io_close (gpg->status.fd[1]);
363 if (gpg->colon.fd[0] != -1)
364 _gpgme_io_close (gpg->colon.fd[0]);
365 if (gpg->colon.fd[1] != -1)
366 _gpgme_io_close (gpg->colon.fd[1]);
367 if (gpg->fd_data_map)
369 free_fd_data_map (gpg->fd_data_map);
370 gpg->fd_data_map = NULL;
377 gpg_release (void *engine)
379 engine_gpg_t gpg = engine;
387 free (gpg->file_name);
389 if (gpg->lc_messages)
390 free (gpg->lc_messages);
392 free (gpg->lc_ctype);
396 struct arg_and_data_s *next = gpg->arglist->next;
403 if (gpg->status.buffer)
404 free (gpg->status.buffer);
405 if (gpg->colon.buffer)
406 free (gpg->colon.buffer);
408 free_argv (gpg->argv);
409 if (gpg->cmd.keyword)
410 free (gpg->cmd.keyword);
417 gpg_new (void **engine, const char *file_name, const char *home_dir)
420 gpgme_error_t rc = 0;
421 char *dft_display = NULL;
422 char dft_ttyname[64];
423 char *dft_ttytype = NULL;
425 gpg = calloc (1, sizeof *gpg);
427 return gpg_error_from_errno (errno);
431 gpg->file_name = strdup (file_name);
434 rc = gpg_error_from_errno (errno);
439 gpg->argtail = &gpg->arglist;
440 gpg->status.fd[0] = -1;
441 gpg->status.fd[1] = -1;
442 gpg->colon.fd[0] = -1;
443 gpg->colon.fd[1] = -1;
446 gpg->cmd.linked_data = NULL;
447 gpg->cmd.linked_idx = -1;
449 /* Allocate the read buffer for the status pipe. */
450 gpg->status.bufsize = 1024;
451 gpg->status.readpos = 0;
452 gpg->status.buffer = malloc (gpg->status.bufsize);
453 if (!gpg->status.buffer)
455 rc = gpg_error_from_errno (errno);
458 /* In any case we need a status pipe - create it right here and
459 don't handle it with our generic gpgme_data_t mechanism. */
460 if (_gpgme_io_pipe (gpg->status.fd, 1) == -1)
462 rc = gpg_error_from_errno (errno);
465 if (_gpgme_io_set_close_notify (gpg->status.fd[0],
466 close_notify_handler, gpg)
467 || _gpgme_io_set_close_notify (gpg->status.fd[1],
468 close_notify_handler, gpg))
470 rc = gpg_error (GPG_ERR_GENERAL);
477 rc = add_arg (gpg, "--homedir");
479 rc = add_arg (gpg, home_dir);
484 rc = add_arg (gpg, "--status-fd");
490 _gpgme_io_fd2str (buf, sizeof (buf), gpg->status.fd[1]);
491 rc = add_arg_with_locp (gpg, buf, &gpg->status.arg_loc);
496 rc = add_arg (gpg, "--no-tty");
498 rc = add_arg (gpg, "--charset");
500 rc = add_arg (gpg, "utf8");
502 rc = add_arg (gpg, "--enable-progress-filter");
506 rc = _gpgme_getenv ("DISPLAY", &dft_display);
511 rc = add_arg (gpg, "--display");
513 rc = add_arg (gpg, dft_display);
522 err = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
524 rc = gpg_error_from_errno (err);
529 rc = add_arg (gpg, "--ttyname");
531 rc = add_arg (gpg, dft_ttyname);
537 rc = _gpgme_getenv ("TERM", &dft_ttytype);
543 rc = add_arg (gpg, "--ttytype");
545 rc = add_arg (gpg, dft_ttytype);
565 gpg_set_locale (void *engine, int category, const char *value)
567 engine_gpg_t gpg = engine;
572 else if (category == LC_CTYPE)
576 free (gpg->lc_ctype);
577 gpg->lc_ctype = NULL;
581 gpg->lc_ctype = strdup (value);
583 return gpg_error_from_syserror ();
588 else if (category == LC_MESSAGES)
590 if (gpg->lc_messages)
592 free (gpg->lc_messages);
593 gpg->lc_messages = NULL;
597 gpg->lc_messages = strdup (value);
598 if (!gpg->lc_messages)
599 return gpg_error_from_syserror ();
602 #endif /* LC_MESSAGES */
604 return gpg_error (GPG_ERR_INV_VALUE);
610 /* Note, that the status_handler is allowed to modifiy the args
613 gpg_set_status_handler (void *engine, engine_status_handler_t fnc,
616 engine_gpg_t gpg = engine;
618 gpg->status.fnc = fnc;
619 gpg->status.fnc_value = fnc_value;
622 /* Kludge to process --with-colon output. */
624 gpg_set_colon_line_handler (void *engine, engine_colon_line_handler_t fnc,
627 engine_gpg_t gpg = engine;
629 gpg->colon.bufsize = 1024;
630 gpg->colon.readpos = 0;
631 gpg->colon.buffer = malloc (gpg->colon.bufsize);
632 if (!gpg->colon.buffer)
633 return gpg_error_from_errno (errno);
635 if (_gpgme_io_pipe (gpg->colon.fd, 1) == -1)
637 int saved_errno = errno;
638 free (gpg->colon.buffer);
639 gpg->colon.buffer = NULL;
640 return gpg_error_from_errno (saved_errno);
642 if (_gpgme_io_set_close_notify (gpg->colon.fd[0], close_notify_handler, gpg)
643 || _gpgme_io_set_close_notify (gpg->colon.fd[1],
644 close_notify_handler, gpg))
645 return gpg_error (GPG_ERR_GENERAL);
647 gpg->colon.fnc = fnc;
648 gpg->colon.fnc_value = fnc_value;
654 command_handler (void *opaque, int fd)
656 struct io_cb_data *data = (struct io_cb_data *) opaque;
657 engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
660 assert (gpg->cmd.used);
661 assert (gpg->cmd.code);
662 assert (gpg->cmd.fnc);
664 err = gpg->cmd.fnc (gpg->cmd.fnc_value, gpg->cmd.code, gpg->cmd.keyword, fd,
668 /* And sleep again until read_status will wake us up again. */
669 /* XXX We must check if there are any more fds active after removing
671 (*gpg->io_cbs.remove) (gpg->fd_data_map[gpg->cmd.idx].tag);
672 gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
673 gpg->fd_data_map[gpg->cmd.idx].fd = -1;
678 /* We always need to send at least a newline character. */
680 _gpgme_io_write (fd, "\n", 1);
687 /* The Fnc will be called to get a value for one of the commands with
688 a key KEY. If the Code passed to FNC is 0, the function may release
689 resources associated with the returned value from another call. To
690 match such a second call to a first call, the returned value from
691 the first call is passed as keyword. */
693 gpg_set_command_handler (void *engine, engine_command_handler_t fnc,
694 void *fnc_value, gpgme_data_t linked_data)
696 engine_gpg_t gpg = engine;
699 rc = add_arg (gpg, "--command-fd");
703 /* This is a hack. We don't have a real data object. The only
704 thing that matters is that we use something unique, so we use the
705 address of the cmd structure in the gpg object. */
706 rc = add_data (gpg, (void *) &gpg->cmd, -2, 0);
711 gpg->cmd.cb_data = (void *) &gpg->cmd;
712 gpg->cmd.fnc_value = fnc_value;
713 gpg->cmd.linked_data = linked_data;
720 build_argv (engine_gpg_t gpg)
723 struct arg_and_data_s *a;
724 struct fd_data_map_s *fd_data_map;
725 size_t datac=0, argc=0;
727 int need_special = 0;
731 /* We don't want to use the agent with a malformed environment
732 variable. This is only a very basic test but sufficient to make
733 our life in the regression tests easier. */
734 err = _gpgme_getenv ("GPG_AGENT_INFO", &p);
737 use_agent = (p && strchr (p, ':'));
743 free_argv (gpg->argv);
746 if (gpg->fd_data_map)
748 free_fd_data_map (gpg->fd_data_map);
749 gpg->fd_data_map = NULL;
752 argc++; /* For argv[0]. */
753 for (a = gpg->arglist; a; a = a->next)
758 /*fprintf (stderr, "build_argv: data\n" );*/
760 if (a->dup_to == -1 && !a->print_fd)
765 /* fprintf (stderr, "build_argv: arg=`%s'\n", a->arg );*/
773 argc++; /* --batch */
774 argc += 1; /* --no-sk-comment */
776 argv = calloc (argc + 1, sizeof *argv);
778 return gpg_error_from_errno (errno);
779 fd_data_map = calloc (datac + 1, sizeof *fd_data_map);
782 int saved_errno = errno;
784 return gpg_error_from_errno (saved_errno);
788 argv[argc] = strdup ("gpg"); /* argv[0] */
791 int saved_errno = errno;
794 return gpg_error_from_errno (saved_errno);
799 argv[argc] = strdup ("--enable-special-filenames");
802 int saved_errno = errno;
805 return gpg_error_from_errno (saved_errno);
811 argv[argc] = strdup ("--use-agent");
814 int saved_errno = errno;
817 return gpg_error_from_errno (saved_errno);
823 argv[argc] = strdup ("--batch");
826 int saved_errno = errno;
829 return gpg_error_from_errno (saved_errno);
833 argv[argc] = strdup ("--no-sk-comment");
836 int saved_errno = errno;
839 return gpg_error_from_errno (saved_errno);
842 for (a = gpg->arglist; a; a = a->next)
845 *(a->arg_locp) = argc;
849 /* Create a pipe to pass it down to gpg. */
850 fd_data_map[datac].inbound = a->inbound;
856 if (_gpgme_io_pipe (fds, fd_data_map[datac].inbound ? 1 : 0)
859 int saved_errno = errno;
862 return gpg_error (saved_errno);
864 if (_gpgme_io_set_close_notify (fds[0],
865 close_notify_handler, gpg)
866 || _gpgme_io_set_close_notify (fds[1],
867 close_notify_handler,
870 return gpg_error (GPG_ERR_GENERAL);
872 /* If the data_type is FD, we have to do a dup2 here. */
873 if (fd_data_map[datac].inbound)
875 fd_data_map[datac].fd = fds[0];
876 fd_data_map[datac].peer_fd = fds[1];
880 fd_data_map[datac].fd = fds[1];
881 fd_data_map[datac].peer_fd = fds[0];
885 /* Hack to get hands on the fd later. */
888 if (gpg->cmd.cb_data == a->data)
890 assert (gpg->cmd.idx == -1);
891 gpg->cmd.idx = datac;
893 else if (gpg->cmd.linked_data == a->data)
895 assert (gpg->cmd.linked_idx == -1);
896 gpg->cmd.linked_idx = datac;
900 fd_data_map[datac].data = a->data;
901 fd_data_map[datac].dup_to = a->dup_to;
908 argv[argc] = malloc (buflen);
911 int saved_errno = errno;
914 return gpg_error_from_errno (saved_errno);
925 _gpgme_io_fd2str (ptr, buflen, fd_data_map[datac].peer_fd);
926 fd_data_map[datac].arg_loc = argc;
933 argv[argc] = strdup (a->arg);
936 int saved_errno = errno;
939 return gpg_error_from_errno (saved_errno);
946 gpg->fd_data_map = fd_data_map;
952 add_io_cb (engine_gpg_t gpg, int fd, int dir, gpgme_io_cb_t handler, void *data,
957 err = (*gpg->io_cbs.add) (gpg->io_cbs.add_priv, fd, dir, handler, data, tag);
961 /* FIXME Kludge around poll() problem. */
962 err = _gpgme_io_set_nonblocking (fd);
967 /* Handle the status output of GnuPG. This function does read entire
968 lines and passes them as C strings to the callback function (we can
969 use C Strings because the status output is always UTF-8 encoded).
970 Of course we have to buffer the lines to cope with long lines
971 e.g. with a large user ID. Note: We can optimize this to only cope
972 with status line code we know about and skip all other stuff
973 without buffering (i.e. without extending the buffer). */
975 read_status (engine_gpg_t gpg)
979 size_t bufsize = gpg->status.bufsize;
980 char *buffer = gpg->status.buffer;
981 size_t readpos = gpg->status.readpos;
984 if (bufsize - readpos < 256)
986 /* Need more room for the read. */
988 buffer = realloc (buffer, bufsize);
990 return gpg_error_from_errno (errno);
993 nread = _gpgme_io_read (gpg->status.fd[0],
994 buffer + readpos, bufsize-readpos);
996 return gpg_error_from_errno (errno);
1000 gpg->status.eof = 1;
1001 if (gpg->status.fnc)
1004 err = gpg->status.fnc (gpg->status.fnc_value, GPGME_STATUS_EOF, "");
1013 for (p = buffer + readpos; nread; nread--, p++)
1017 /* (we require that the last line is terminated by a LF) */
1018 if (p > buffer && p[-1] == '\r')
1021 if (!strncmp (buffer, "[GNUPG:] ", 9)
1022 && buffer[9] >= 'A' && buffer[9] <= 'Z')
1025 gpgme_status_code_t r;
1027 rest = strchr (buffer + 9, ' ');
1029 rest = p; /* Set to an empty string. */
1033 r = _gpgme_parse_status (buffer + 9);
1037 && (r == GPGME_STATUS_GET_BOOL
1038 || r == GPGME_STATUS_GET_LINE
1039 || r == GPGME_STATUS_GET_HIDDEN))
1042 if (gpg->cmd.keyword)
1043 free (gpg->cmd.keyword);
1044 gpg->cmd.keyword = strdup (rest);
1045 if (!gpg->cmd.keyword)
1046 return gpg_error_from_errno (errno);
1047 /* This should be the last thing we have
1048 received and the next thing will be that
1049 the command handler does its action. */
1051 TRACE0 (DEBUG_CTX, "gpgme:read_status", 0,
1052 "error: unexpected data");
1054 add_io_cb (gpg, gpg->cmd.fd, 0,
1055 command_handler, gpg,
1056 &gpg->fd_data_map[gpg->cmd.idx].tag);
1057 gpg->fd_data_map[gpg->cmd.idx].fd = gpg->cmd.fd;
1060 else if (gpg->status.fnc)
1063 err = gpg->status.fnc (gpg->status.fnc_value,
1069 if (r == GPGME_STATUS_END_STREAM)
1073 /* Before we can actually add the
1074 command fd, we might have to flush
1075 the linked output data pipe. */
1076 if (gpg->cmd.linked_idx != -1
1077 && gpg->fd_data_map[gpg->cmd.linked_idx].fd
1080 struct io_select_fd_s fds;
1082 gpg->fd_data_map[gpg->cmd.linked_idx].fd;
1089 _gpgme_io_select (&fds, 1, 1);
1091 _gpgme_data_inbound_handler
1092 (gpg->cmd.linked_data, fds.fd);
1094 while (fds.signaled);
1097 /* XXX We must check if there are any
1098 more fds active after removing this
1100 (*gpg->io_cbs.remove)
1101 (gpg->fd_data_map[gpg->cmd.idx].tag);
1102 gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
1103 gpg->fd_data_map[gpg->cmd.idx].fd = -1;
1108 /* To reuse the buffer for the next line we have to
1109 shift the remaining data to the buffer start and
1110 restart the loop Hmmm: We can optimize this function
1111 by looking forward in the buffer to see whether a
1112 second complete line is available and in this case
1113 avoid the memmove for this line. */
1116 memmove (buffer, p, nread);
1118 break; /* the for loop */
1125 /* Update the gpg object. */
1126 gpg->status.bufsize = bufsize;
1127 gpg->status.buffer = buffer;
1128 gpg->status.readpos = readpos;
1133 static gpgme_error_t
1134 status_handler (void *opaque, int fd)
1136 struct io_cb_data *data = (struct io_cb_data *) opaque;
1137 engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
1140 assert (fd == gpg->status.fd[0]);
1141 err = read_status (gpg);
1144 if (gpg->status.eof)
1145 _gpgme_io_close (fd);
1150 static gpgme_error_t
1151 read_colon_line (engine_gpg_t gpg)
1155 size_t bufsize = gpg->colon.bufsize;
1156 char *buffer = gpg->colon.buffer;
1157 size_t readpos = gpg->colon.readpos;
1160 if (bufsize - readpos < 256)
1162 /* Need more room for the read. */
1164 buffer = realloc (buffer, bufsize);
1166 return gpg_error_from_errno (errno);
1169 nread = _gpgme_io_read (gpg->colon.fd[0], buffer+readpos, bufsize-readpos);
1171 return gpg_error_from_errno (errno);
1176 assert (gpg->colon.fnc);
1177 gpg->colon.fnc (gpg->colon.fnc_value, NULL);
1183 for (p = buffer + readpos; nread; nread--, p++)
1187 /* (we require that the last line is terminated by a LF)
1188 and we skip empty lines. Note: we use UTF8 encoding
1189 and escaping of special characters. We require at
1190 least one colon to cope with some other printed
1193 if (*buffer && strchr (buffer, ':'))
1197 if (gpg->colon.preprocess_fnc)
1201 err = gpg->colon.preprocess_fnc (buffer, &line);
1206 assert (gpg->colon.fnc);
1207 gpg->colon.fnc (gpg->colon.fnc_value, line ? line : buffer);
1212 /* To reuse the buffer for the next line we have to
1213 shift the remaining data to the buffer start and
1214 restart the loop Hmmm: We can optimize this function
1215 by looking forward in the buffer to see whether a
1216 second complete line is available and in this case
1217 avoid the memmove for this line. */
1220 memmove (buffer, p, nread);
1222 break; /* The for loop. */
1229 /* Update the gpg object. */
1230 gpg->colon.bufsize = bufsize;
1231 gpg->colon.buffer = buffer;
1232 gpg->colon.readpos = readpos;
1237 /* This colonline handler thing is not the clean way to do it. It
1238 might be better to enhance the gpgme_data_t object to act as a wrapper
1239 for a callback. Same goes for the status thing. For now we use
1240 this thing here because it is easier to implement. */
1241 static gpgme_error_t
1242 colon_line_handler (void *opaque, int fd)
1244 struct io_cb_data *data = (struct io_cb_data *) opaque;
1245 engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
1246 gpgme_error_t rc = 0;
1248 assert (fd == gpg->colon.fd[0]);
1249 rc = read_colon_line (gpg);
1253 _gpgme_io_close (fd);
1258 static gpgme_error_t
1259 start (engine_gpg_t gpg)
1265 struct spawn_fd_item_s *fd_list;
1269 return gpg_error (GPG_ERR_INV_VALUE);
1271 if (!gpg->file_name && !_gpgme_get_gpg_path ())
1272 return gpg_error (GPG_ERR_INV_ENGINE);
1276 rc = add_arg_ext (gpg, gpg->lc_ctype, 1);
1278 rc = add_arg_ext (gpg, "--lc-ctype", 1);
1283 if (gpg->lc_messages)
1285 rc = add_arg_ext (gpg, gpg->lc_messages, 1);
1287 rc = add_arg_ext (gpg, "--lc-messages", 1);
1292 rc = build_argv (gpg);
1296 /* status_fd, colon_fd and end of list. */
1298 for (i = 0; gpg->fd_data_map[i].data; i++)
1300 fd_list = calloc (n, sizeof *fd_list);
1302 return gpg_error_from_errno (errno);
1304 /* Build the fd list for the child. */
1306 fd_list[n].fd = gpg->status.fd[1];
1307 fd_list[n].dup_to = -1;
1308 fd_list[n].arg_loc = gpg->status.arg_loc;
1312 fd_list[n].fd = gpg->colon.fd[1];
1313 fd_list[n].dup_to = 1;
1316 for (i = 0; gpg->fd_data_map[i].data; i++)
1318 fd_list[n].fd = gpg->fd_data_map[i].peer_fd;
1319 fd_list[n].dup_to = gpg->fd_data_map[i].dup_to;
1320 fd_list[n].arg_loc = gpg->fd_data_map[i].arg_loc;
1324 fd_list[n].dup_to = -1;
1326 status = _gpgme_io_spawn (gpg->file_name ? gpg->file_name :
1327 _gpgme_get_gpg_path (), gpg->argv,
1328 IOSPAWN_FLAG_ALLOW_SET_FG,
1329 fd_list, NULL, NULL, &pid);
1330 saved_errno = errno;
1334 return gpg_error_from_errno (saved_errno);
1336 /*_gpgme_register_term_handler ( closure, closure_value, pid );*/
1338 rc = add_io_cb (gpg, gpg->status.fd[0], 1, status_handler, gpg,
1341 /* FIXME: kill the child */
1346 assert (gpg->colon.fd[0] != -1);
1347 rc = add_io_cb (gpg, gpg->colon.fd[0], 1, colon_line_handler, gpg,
1350 /* FIXME: kill the child */
1354 for (i = 0; gpg->fd_data_map[i].data; i++)
1356 if (gpg->cmd.used && i == gpg->cmd.idx)
1358 /* Park the cmd fd. */
1359 gpg->cmd.fd = gpg->fd_data_map[i].fd;
1360 gpg->fd_data_map[i].fd = -1;
1364 rc = add_io_cb (gpg, gpg->fd_data_map[i].fd,
1365 gpg->fd_data_map[i].inbound,
1366 gpg->fd_data_map[i].inbound
1367 ? _gpgme_data_inbound_handler
1368 : _gpgme_data_outbound_handler,
1369 gpg->fd_data_map[i].data, &gpg->fd_data_map[i].tag);
1372 /* FIXME: kill the child */
1377 gpg_io_event (gpg, GPGME_EVENT_START, NULL);
1379 /* fixme: check what data we can release here */
1384 static gpgme_error_t
1385 gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
1387 engine_gpg_t gpg = engine;
1390 err = add_arg (gpg, "--decrypt");
1392 /* Tell the gpg object about the data. */
1394 err = add_arg (gpg, "--output");
1396 err = add_arg (gpg, "-");
1398 err = add_data (gpg, plain, 1, 1);
1400 err = add_arg (gpg, "--");
1402 err = add_data (gpg, ciph, -1, 0);
1409 static gpgme_error_t
1410 gpg_delete (void *engine, gpgme_key_t key, int allow_secret)
1412 engine_gpg_t gpg = engine;
1415 err = add_arg (gpg, allow_secret ? "--delete-secret-and-public-key"
1418 err = add_arg (gpg, "--");
1421 if (!key->subkeys || !key->subkeys->fpr)
1422 return gpg_error (GPG_ERR_INV_VALUE);
1424 err = add_arg (gpg, key->subkeys->fpr);
1433 static gpgme_error_t
1434 gpg_passwd (void *engine, gpgme_key_t key, unsigned int flags)
1436 engine_gpg_t gpg = engine;
1439 if (!key || !key->subkeys || !key->subkeys->fpr)
1440 return gpg_error (GPG_ERR_INV_CERT_OBJ);
1442 err = add_arg (gpg, "--passwd");
1444 err = add_arg (gpg, key->subkeys->fpr);
1451 static gpgme_error_t
1452 append_args_from_signers (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1454 gpgme_error_t err = 0;
1458 for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++)
1460 const char *s = key->subkeys ? key->subkeys->keyid : NULL;
1464 err = add_arg (gpg, "-u");
1466 err = add_arg (gpg, s);
1468 gpgme_key_unref (key);
1475 static gpgme_error_t
1476 append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1478 gpgme_error_t err = 0;
1479 gpgme_sig_notation_t notation;
1481 notation = gpgme_sig_notation_get (ctx);
1483 while (!err && notation)
1486 && !(notation->flags & GPGME_SIG_NOTATION_HUMAN_READABLE))
1487 err = gpg_error (GPG_ERR_INV_VALUE);
1488 else if (notation->name)
1492 /* Maximum space needed is one byte for the "critical" flag,
1493 the name, one byte for '=', the value, and a terminating
1496 arg = malloc (1 + notation->name_len + 1 + notation->value_len + 1);
1498 err = gpg_error_from_errno (errno);
1504 if (notation->critical)
1507 memcpy (argp, notation->name, notation->name_len);
1508 argp += notation->name_len;
1512 /* We know that notation->name is '\0' terminated. */
1513 strcpy (argp, notation->value);
1517 err = add_arg (gpg, "--sig-notation");
1519 err = add_arg (gpg, arg);
1526 /* This is a policy URL. */
1530 if (notation->critical)
1532 value = malloc (1 + notation->value_len + 1);
1534 err = gpg_error_from_errno (errno);
1538 /* We know that notation->value is '\0' terminated. */
1539 strcpy (&value[1], notation->value);
1543 value = notation->value;
1546 err = add_arg (gpg, "--sig-policy-url");
1548 err = add_arg (gpg, value);
1550 if (value != notation->value)
1554 notation = notation->next;
1560 static gpgme_error_t
1561 gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out,
1562 gpgme_ctx_t ctx /* FIXME */)
1564 engine_gpg_t gpg = engine;
1567 err = add_arg (gpg, "--with-colons");
1569 err = append_args_from_signers (gpg, ctx);
1571 err = add_arg (gpg, type == 0 ? "--edit-key" : "--card-edit");
1573 err = add_data (gpg, out, 1, 1);
1575 err = add_arg (gpg, "--");
1576 if (!err && type == 0)
1578 const char *s = key->subkeys ? key->subkeys->fpr : NULL;
1580 err = gpg_error (GPG_ERR_INV_VALUE);
1582 err = add_arg (gpg, s);
1591 static gpgme_error_t
1592 append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[])
1594 gpgme_error_t err = 0;
1599 if (!recp[i]->subkeys || !recp[i]->subkeys->fpr)
1600 err = gpg_error (GPG_ERR_INV_VALUE);
1602 err = add_arg (gpg, "-r");
1604 err = add_arg (gpg, recp[i]->subkeys->fpr);
1613 static gpgme_error_t
1614 gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
1615 gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
1617 engine_gpg_t gpg = engine;
1619 int symmetric = !recp;
1621 err = add_arg (gpg, symmetric ? "--symmetric" : "--encrypt");
1623 if (!err && use_armor)
1624 err = add_arg (gpg, "--armor");
1628 /* If we know that all recipients are valid (full or ultimate trust)
1629 we can suppress further checks. */
1630 if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1631 err = add_arg (gpg, "--always-trust");
1633 if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
1634 err = add_arg (gpg, "--no-encrypt-to");
1637 err = append_args_from_recipients (gpg, recp);
1640 /* Tell the gpg object about the data. */
1642 err = add_arg (gpg, "--output");
1644 err = add_arg (gpg, "-");
1646 err = add_data (gpg, ciph, 1, 1);
1647 if (gpgme_data_get_file_name (plain))
1650 err = add_arg (gpg, "--set-filename");
1652 err = add_arg (gpg, gpgme_data_get_file_name (plain));
1655 err = add_arg (gpg, "--");
1657 err = add_data (gpg, plain, -1, 0);
1666 static gpgme_error_t
1667 gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
1668 gpgme_encrypt_flags_t flags, gpgme_data_t plain,
1669 gpgme_data_t ciph, int use_armor,
1670 gpgme_ctx_t ctx /* FIXME */)
1672 engine_gpg_t gpg = engine;
1675 err = add_arg (gpg, "--encrypt");
1677 err = add_arg (gpg, "--sign");
1678 if (!err && use_armor)
1679 err = add_arg (gpg, "--armor");
1681 /* If we know that all recipients are valid (full or ultimate trust)
1682 we can suppress further checks. */
1683 if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1684 err = add_arg (gpg, "--always-trust");
1687 err = append_args_from_recipients (gpg, recp);
1690 err = append_args_from_signers (gpg, ctx);
1692 err = append_args_from_sig_notations (gpg, ctx);
1694 /* Tell the gpg object about the data. */
1696 err = add_arg (gpg, "--output");
1698 err = add_arg (gpg, "-");
1700 err = add_data (gpg, ciph, 1, 1);
1701 if (gpgme_data_get_file_name (plain))
1704 err = add_arg (gpg, "--set-filename");
1706 err = add_arg (gpg, gpgme_data_get_file_name (plain));
1709 err = add_arg (gpg, "--");
1711 err = add_data (gpg, plain, -1, 0);
1720 static gpgme_error_t
1721 export_common (engine_gpg_t gpg, gpgme_export_mode_t mode,
1722 gpgme_data_t keydata, int use_armor)
1724 gpgme_error_t err = 0;
1726 if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
1727 |GPGME_EXPORT_MODE_MINIMAL)))
1728 return gpg_error (GPG_ERR_NOT_SUPPORTED);
1730 if ((mode & GPGME_EXPORT_MODE_MINIMAL))
1731 err = add_arg (gpg, "--export-options=export-minimal");
1735 else if ((mode & GPGME_EXPORT_MODE_EXTERN))
1737 err = add_arg (gpg, "--send-keys");
1741 err = add_arg (gpg, "--export");
1742 if (!err && use_armor)
1743 err = add_arg (gpg, "--armor");
1745 err = add_data (gpg, keydata, 1, 1);
1748 err = add_arg (gpg, "--");
1754 static gpgme_error_t
1755 gpg_export (void *engine, const char *pattern, gpgme_export_mode_t mode,
1756 gpgme_data_t keydata, int use_armor)
1758 engine_gpg_t gpg = engine;
1761 err = export_common (gpg, mode, keydata, use_armor);
1763 if (!err && pattern && *pattern)
1764 err = add_arg (gpg, pattern);
1773 static gpgme_error_t
1774 gpg_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
1775 gpgme_data_t keydata, int use_armor)
1777 engine_gpg_t gpg = engine;
1780 err = export_common (gpg, mode, keydata, use_armor);
1784 while (!err && *pattern && **pattern)
1785 err = add_arg (gpg, *(pattern++));
1795 static gpgme_error_t
1796 gpg_genkey (void *engine, gpgme_data_t help_data, int use_armor,
1797 gpgme_data_t pubkey, gpgme_data_t seckey)
1799 engine_gpg_t gpg = engine;
1803 return gpg_error (GPG_ERR_INV_VALUE);
1805 /* We need a special mechanism to get the fd of a pipe here, so that
1806 we can use this for the %pubring and %secring parameters. We
1807 don't have this yet, so we implement only the adding to the
1808 standard keyrings. */
1809 if (pubkey || seckey)
1810 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1812 err = add_arg (gpg, "--gen-key");
1813 if (!err && use_armor)
1814 err = add_arg (gpg, "--armor");
1816 err = add_arg (gpg, "--");
1818 err = add_data (gpg, help_data, -1, 0);
1826 /* Return the next DELIM delimited string from DATA as a C-string.
1827 The caller needs to provide the address of a pointer variable which
1828 he has to set to NULL before the first call. After the last call
1829 to this function, this function needs to be called once more with
1830 DATA set to NULL so that the function can release its internal
1831 state. After that the pointer variable is free for use again.
1832 Note that we use a delimiter and thus a trailing delimiter is not
1833 required. DELIM may not be changed after the first call. */
1835 string_from_data (gpgme_data_t data, int delim,
1836 void **helpptr, gpgme_error_t *r_err)
1838 #define MYBUFLEN 2000 /* Fixme: We don't support URLs longer than that. */
1841 int nbytes; /* Length of the last returned string including
1843 int buflen; /* Valid length of BUF. */
1844 char buf[MYBUFLEN+1]; /* Buffer with one byte extra space. */
1864 self = malloc (sizeof *self);
1867 *r_err = gpg_error_from_syserror ();
1879 assert (self->nbytes <= self->buflen);
1880 memmove (self->buf, self->buf + self->nbytes, self->buflen - self->nbytes);
1881 self->buflen -= self->nbytes;
1886 /* Fixme: This is fairly infective scanning because we may scan
1887 the buffer several times. */
1888 p = memchr (self->buf, delim, self->buflen);
1892 self->nbytes = p - self->buf + 1;
1896 if ( !(MYBUFLEN - self->buflen) )
1898 /* Not enough space - URL too long. */
1899 *r_err = gpg_error (GPG_ERR_TOO_LARGE);
1903 nread = gpgme_data_read (data, self->buf + self->buflen,
1904 MYBUFLEN - self->buflen);
1907 *r_err = gpg_error_from_syserror ();
1910 self->buflen += nread;
1914 /* EOF reached. If we have anything in the buffer, append a Nul and
1919 self->buf[self->buflen] = 0; /* (we allocated one extra byte) */
1928 static gpgme_error_t
1929 gpg_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray)
1931 engine_gpg_t gpg = engine;
1934 gpgme_data_encoding_t dataenc;
1936 if (keydata && keyarray)
1937 return gpg_error (GPG_ERR_INV_VALUE); /* Only one is allowed. */
1939 dataenc = gpgme_data_get_encoding (keydata);
1943 err = add_arg (gpg, "--recv-keys");
1945 err = add_arg (gpg, "--");
1946 for (idx=0; !err && keyarray[idx]; idx++)
1948 if (keyarray[idx]->protocol != GPGME_PROTOCOL_OpenPGP)
1950 else if (!keyarray[idx]->subkeys)
1952 else if (keyarray[idx]->subkeys->fpr && *keyarray[idx]->subkeys->fpr)
1953 err = add_arg (gpg, keyarray[idx]->subkeys->fpr);
1954 else if (*keyarray[idx]->subkeys->keyid)
1955 err = add_arg (gpg, keyarray[idx]->subkeys->keyid);
1958 else if (dataenc == GPGME_DATA_ENCODING_URL
1959 || dataenc == GPGME_DATA_ENCODING_URL0)
1964 int delim = (dataenc == GPGME_DATA_ENCODING_URL)? '\n': 0;
1966 /* FIXME: --fetch-keys is probably not correct because it can't
1967 grok all kinds of URLs. On Unix it should just work but on
1968 Windows we will build the command line and that may fail for
1969 some embedded control characters. It is anyway limited to
1970 the maximum size of the command line. We need another
1971 command which can take its input from a file. Maybe we
1972 should use an option to gpg to modify such commands (ala
1974 err = add_arg (gpg, "--fetch-keys");
1976 err = add_arg (gpg, "--");
1979 && (string = string_from_data (keydata, delim, &helpptr, &xerr)))
1980 err = add_arg (gpg, string);
1983 string_from_data (NULL, delim, &helpptr, &xerr);
1985 else if (dataenc == GPGME_DATA_ENCODING_URLESC)
1987 /* Already escaped URLs are not yet supported. */
1988 err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1992 err = add_arg (gpg, "--import");
1994 err = add_arg (gpg, "--");
1996 err = add_data (gpg, keydata, -1, 0);
2006 /* The output for external keylistings in GnuPG is different from all
2007 the other key listings. We catch this here with a special
2008 preprocessor that reformats the colon handler lines. */
2009 static gpgme_error_t
2010 gpg_keylist_preprocess (char *line, char **r_line)
2014 RT_NONE, RT_INFO, RT_PUB, RT_UID
2017 #define NR_FIELDS 16
2018 char *field[NR_FIELDS];
2023 while (line && fields < NR_FIELDS)
2025 field[fields++] = line;
2026 line = strchr (line, ':');
2031 if (!strcmp (field[0], "info"))
2033 else if (!strcmp (field[0], "pub"))
2035 else if (!strcmp (field[0], "uid"))
2043 /* FIXME: Eventually, check the version number at least. */
2052 pub:<keyid>:<algo>:<keylen>:<creationdate>:<expirationdate>:<flags>
2054 as defined in 5.2. Machine Readable Indexes of the OpenPGP
2055 HTTP Keyserver Protocol (draft).
2058 pub:o<flags>:<keylen>:<algo>:<keyid>:<creatdate>:<expdate>::::::::
2061 if (asprintf (r_line, "pub:o%s:%s:%s:%s:%s:%s::::::::",
2062 field[6], field[3], field[2], field[1],
2063 field[4], field[5]) < 0)
2064 return gpg_error_from_errno (errno);
2070 uid:<escaped uid string>:<creationdate>:<expirationdate>:<flags>
2072 as defined in 5.2. Machine Readable Indexes of the OpenPGP
2073 HTTP Keyserver Protocol (draft).
2076 uid:o<flags>::::<creatdate>:<expdate>:::<c-coded uid>:
2080 /* The user ID is percent escaped, but we want c-coded.
2081 Because we have to replace each '%HL' by '\xHL', we need at
2082 most 4/3 th the number of bytes. But because we also need
2083 to escape the backslashes we allocate twice as much. */
2084 char *uid = malloc (2 * strlen (field[1]) + 1);
2089 return gpg_error_from_errno (errno);
2099 /* Copy the next two bytes unconditionally. */
2101 *(dst++) = *(src++);
2103 *(dst++) = *(src++);
2105 else if (*src == '\\')
2111 *(dst++) = *(src++);
2115 if (asprintf (r_line, "uid:o%s::::%s:%s:::%s:",
2116 field[4], field[2], field[3], uid) < 0)
2117 return gpg_error_from_errno (errno);
2122 /* Unknown record. */
2131 gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
2132 gpgme_keylist_mode_t mode)
2136 err = add_arg (gpg, "--with-colons");
2138 err = add_arg (gpg, "--fixed-list-mode");
2140 err = add_arg (gpg, "--with-fingerprint");
2142 err = add_arg (gpg, "--with-fingerprint");
2144 && (mode & GPGME_KEYLIST_MODE_SIGS)
2145 && (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS))
2147 err = add_arg (gpg, "--list-options");
2149 err = add_arg (gpg, "show-sig-subpackets=\"20,26\"");
2153 if ( (mode & GPGME_KEYLIST_MODE_EXTERN) )
2156 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
2157 else if ( (mode & GPGME_KEYLIST_MODE_LOCAL))
2159 /* The local+extern mode is special. It works only with
2160 gpg >= 2.0.10. FIXME: We should check that we have
2161 such a version to that we can return a proper error
2162 code. The problem is that we don't know the context
2163 here and thus can't access the cached version number
2164 for the engine info structure. */
2165 err = add_arg (gpg, "--locate-keys");
2166 if ((mode & GPGME_KEYLIST_MODE_SIGS))
2167 err = add_arg (gpg, "--with-sig-check");
2171 err = add_arg (gpg, "--search-keys");
2172 gpg->colon.preprocess_fnc = gpg_keylist_preprocess;
2177 err = add_arg (gpg, secret_only ? "--list-secret-keys"
2178 : ((mode & GPGME_KEYLIST_MODE_SIGS)
2179 ? "--check-sigs" : "--list-keys"));
2183 err = add_arg (gpg, "--");
2189 static gpgme_error_t
2190 gpg_keylist (void *engine, const char *pattern, int secret_only,
2191 gpgme_keylist_mode_t mode)
2193 engine_gpg_t gpg = engine;
2196 err = gpg_keylist_build_options (gpg, secret_only, mode);
2198 if (!err && pattern && *pattern)
2199 err = add_arg (gpg, pattern);
2208 static gpgme_error_t
2209 gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
2210 int reserved, gpgme_keylist_mode_t mode)
2212 engine_gpg_t gpg = engine;
2216 return gpg_error (GPG_ERR_INV_VALUE);
2218 err = gpg_keylist_build_options (gpg, secret_only, mode);
2222 while (!err && *pattern && **pattern)
2223 err = add_arg (gpg, *(pattern++));
2233 static gpgme_error_t
2234 gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
2235 gpgme_sig_mode_t mode, int use_armor, int use_textmode,
2236 int include_certs, gpgme_ctx_t ctx /* FIXME */)
2238 engine_gpg_t gpg = engine;
2241 if (mode == GPGME_SIG_MODE_CLEAR)
2242 err = add_arg (gpg, "--clearsign");
2245 err = add_arg (gpg, "--sign");
2246 if (!err && mode == GPGME_SIG_MODE_DETACH)
2247 err = add_arg (gpg, "--detach");
2248 if (!err && use_armor)
2249 err = add_arg (gpg, "--armor");
2250 if (!err && use_textmode)
2251 err = add_arg (gpg, "--textmode");
2255 err = append_args_from_signers (gpg, ctx);
2257 err = append_args_from_sig_notations (gpg, ctx);
2259 if (gpgme_data_get_file_name (in))
2262 err = add_arg (gpg, "--set-filename");
2264 err = add_arg (gpg, gpgme_data_get_file_name (in));
2267 /* Tell the gpg object about the data. */
2269 err = add_arg (gpg, "--");
2271 err = add_data (gpg, in, -1, 0);
2273 err = add_data (gpg, out, 1, 1);
2281 static gpgme_error_t
2282 gpg_trustlist (void *engine, const char *pattern)
2284 engine_gpg_t gpg = engine;
2287 err = add_arg (gpg, "--with-colons");
2289 err = add_arg (gpg, "--list-trust-path");
2291 /* Tell the gpg object about the data. */
2293 err = add_arg (gpg, "--");
2295 err = add_arg (gpg, pattern);
2304 static gpgme_error_t
2305 gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
2306 gpgme_data_t plaintext)
2308 engine_gpg_t gpg = engine;
2309 gpgme_error_t err = 0;
2313 /* Normal or cleartext signature. */
2315 err = add_arg (gpg, "--output");
2317 err = add_arg (gpg, "-");
2319 err = add_arg (gpg, "--");
2321 err = add_data (gpg, sig, -1, 0);
2323 err = add_data (gpg, plaintext, 1, 1);
2327 err = add_arg (gpg, "--verify");
2329 err = add_arg (gpg, "--");
2331 err = add_data (gpg, sig, -1, 0);
2332 if (!err && signed_text)
2333 err = add_data (gpg, signed_text, -1, 0);
2344 gpg_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
2346 engine_gpg_t gpg = engine;
2348 gpg->io_cbs = *io_cbs;
2352 struct engine_ops _gpgme_engine_ops_gpg =
2354 /* Static functions. */
2355 _gpgme_get_gpg_path,
2358 gpg_get_req_version,
2361 /* Member functions. */
2364 gpg_set_status_handler,
2365 gpg_set_command_handler,
2366 gpg_set_colon_line_handler,
2368 NULL, /* set_protocol */
2370 gpg_decrypt, /* decrypt_verify */
2384 NULL, /* getauditlog */
2385 NULL, /* opassuan_transact */
2386 NULL, /* conf_load */
2387 NULL, /* conf_save */
2391 NULL, /* cancel_op */