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 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 "status-table.h"
47 #include "engine-backend.h"
50 /* This type is used to build a list of gpg arguments and data
54 struct arg_and_data_s *next;
55 gpgme_data_t data; /* If this is not NULL, use arg below. */
56 int inbound; /* True if this is used for reading from gpg. */
58 int print_fd; /* Print the fd number and not the special form of it. */
59 int *arg_locp; /* Write back the argv idx of this argument when
60 building command line to this location. */
61 char arg[1]; /* Used if data above is not used. */
68 int inbound; /* true if this is used for reading from gpg */
70 int fd; /* the fd to use */
71 int peer_fd; /* the other side of the pipe */
72 int arg_loc; /* The index into the argv for translation purposes. */
77 typedef gpgme_error_t (*colon_preprocessor_t) (char *line, char **rline);
86 struct arg_and_data_s *arglist;
87 struct arg_and_data_s **argtail;
97 engine_status_handler_t fnc;
102 /* This is a kludge - see the comment at colon_line_handler. */
111 engine_colon_line_handler_t fnc; /* this indicate use of this structrue */
114 colon_preprocessor_t preprocess_fnc;
118 struct fd_data_map_s *fd_data_map;
120 /* stuff needed for interactive (command) mode */
126 int idx; /* Index in fd_data_map */
127 gpgme_status_code_t code; /* last code */
128 char *keyword; /* what has been requested (malloced) */
129 engine_command_handler_t fnc;
131 /* The kludges never end. This is used to couple command handlers
132 with output data in edit key mode. */
133 gpgme_data_t linked_data;
137 struct gpgme_io_cbs io_cbs;
140 typedef struct engine_gpg *engine_gpg_t;
144 gpg_io_event (void *engine, gpgme_event_io_t type, void *type_data)
146 engine_gpg_t gpg = engine;
148 TRACE3 (DEBUG_ENGINE, "gpgme:gpg_io_event", gpg,
149 "event %p, type %d, type_data %p",
150 gpg->io_cbs.event, type, type_data);
151 if (gpg->io_cbs.event)
152 (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, type, type_data);
157 close_notify_handler (int fd, void *opaque)
159 engine_gpg_t gpg = opaque;
162 if (gpg->status.fd[0] == fd)
165 (*gpg->io_cbs.remove) (gpg->status.tag);
166 gpg->status.fd[0] = -1;
168 else if (gpg->status.fd[1] == fd)
169 gpg->status.fd[1] = -1;
170 else if (gpg->colon.fd[0] == fd)
173 (*gpg->io_cbs.remove) (gpg->colon.tag);
174 gpg->colon.fd[0] = -1;
176 else if (gpg->colon.fd[1] == fd)
177 gpg->colon.fd[1] = -1;
178 else if (gpg->cmd.fd == fd)
180 else if (gpg->fd_data_map)
184 for (i = 0; gpg->fd_data_map[i].data; i++)
186 if (gpg->fd_data_map[i].fd == fd)
188 if (gpg->fd_data_map[i].tag)
189 (*gpg->io_cbs.remove) (gpg->fd_data_map[i].tag);
190 gpg->fd_data_map[i].fd = -1;
193 if (gpg->fd_data_map[i].peer_fd == fd)
195 gpg->fd_data_map[i].peer_fd = -1;
202 /* If FRONT is true, push at the front of the list. Use this for
203 options added late in the process. */
205 _add_arg (engine_gpg_t gpg, const char *arg, int front, int *arg_locp)
207 struct arg_and_data_s *a;
212 a = malloc (sizeof *a + strlen (arg));
214 return gpg_error_from_errno (errno);
218 a->arg_locp = arg_locp;
220 strcpy (a->arg, arg);
223 a->next = gpg->arglist;
226 /* If this is the first argument, we need to update the tail
228 gpg->argtail = &a->next;
236 gpg->argtail = &a->next;
243 add_arg_ext (engine_gpg_t gpg, const char *arg, int front)
245 return _add_arg (gpg, arg, front, NULL);
250 add_arg_with_locp (engine_gpg_t gpg, const char *arg, int *locp)
252 return _add_arg (gpg, arg, 0, locp);
257 add_arg (engine_gpg_t gpg, const char *arg)
259 return add_arg_ext (gpg, arg, 0);
264 add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound)
266 struct arg_and_data_s *a;
271 a = malloc (sizeof *a - 1);
273 return gpg_error_from_errno (errno);
276 a->inbound = inbound;
290 gpg->argtail = &a->next;
296 gpg_get_version (const char *file_name)
298 return _gpgme_get_program_version (file_name ? file_name
299 : _gpgme_get_gpg_path ());
304 gpg_get_req_version (void)
306 return NEED_GPG_VERSION;
311 free_argv (char **argv)
315 for (i = 0; argv[i]; i++)
322 free_fd_data_map (struct fd_data_map_s *fd_data_map)
329 for (i = 0; fd_data_map[i].data; i++)
331 if (fd_data_map[i].fd != -1)
332 _gpgme_io_close (fd_data_map[i].fd);
333 if (fd_data_map[i].peer_fd != -1)
334 _gpgme_io_close (fd_data_map[i].peer_fd);
335 /* Don't release data because this is only a reference. */
342 gpg_cancel (void *engine)
344 engine_gpg_t gpg = engine;
347 return gpg_error (GPG_ERR_INV_VALUE);
349 /* If gpg may be waiting for a cmd, close the cmd fd first. On
350 Windows, close operations block on the reader/writer thread. */
353 if (gpg->cmd.fd != -1)
354 _gpgme_io_close (gpg->cmd.fd);
355 else if (gpg->fd_data_map
356 && gpg->fd_data_map[gpg->cmd.idx].fd != -1)
357 _gpgme_io_close (gpg->fd_data_map[gpg->cmd.idx].fd);
360 if (gpg->status.fd[0] != -1)
361 _gpgme_io_close (gpg->status.fd[0]);
362 if (gpg->status.fd[1] != -1)
363 _gpgme_io_close (gpg->status.fd[1]);
364 if (gpg->colon.fd[0] != -1)
365 _gpgme_io_close (gpg->colon.fd[0]);
366 if (gpg->colon.fd[1] != -1)
367 _gpgme_io_close (gpg->colon.fd[1]);
368 if (gpg->fd_data_map)
370 free_fd_data_map (gpg->fd_data_map);
371 gpg->fd_data_map = NULL;
378 gpg_release (void *engine)
380 engine_gpg_t gpg = engine;
388 free (gpg->file_name);
390 if (gpg->lc_messages)
391 free (gpg->lc_messages);
393 free (gpg->lc_ctype);
397 struct arg_and_data_s *next = gpg->arglist->next;
404 if (gpg->status.buffer)
405 free (gpg->status.buffer);
406 if (gpg->colon.buffer)
407 free (gpg->colon.buffer);
409 free_argv (gpg->argv);
410 if (gpg->cmd.keyword)
411 free (gpg->cmd.keyword);
418 gpg_new (void **engine, const char *file_name, const char *home_dir)
421 gpgme_error_t rc = 0;
422 char *dft_display = NULL;
423 char dft_ttyname[64];
424 char *dft_ttytype = NULL;
426 gpg = calloc (1, sizeof *gpg);
428 return gpg_error_from_errno (errno);
432 gpg->file_name = strdup (file_name);
435 rc = gpg_error_from_errno (errno);
440 gpg->argtail = &gpg->arglist;
441 gpg->status.fd[0] = -1;
442 gpg->status.fd[1] = -1;
443 gpg->colon.fd[0] = -1;
444 gpg->colon.fd[1] = -1;
447 gpg->cmd.linked_data = NULL;
448 gpg->cmd.linked_idx = -1;
450 /* Allocate the read buffer for the status pipe. */
451 gpg->status.bufsize = 1024;
452 gpg->status.readpos = 0;
453 gpg->status.buffer = malloc (gpg->status.bufsize);
454 if (!gpg->status.buffer)
456 rc = gpg_error_from_errno (errno);
459 /* In any case we need a status pipe - create it right here and
460 don't handle it with our generic gpgme_data_t mechanism. */
461 if (_gpgme_io_pipe (gpg->status.fd, 1) == -1)
463 rc = gpg_error_from_errno (errno);
466 if (_gpgme_io_set_close_notify (gpg->status.fd[0],
467 close_notify_handler, gpg)
468 || _gpgme_io_set_close_notify (gpg->status.fd[1],
469 close_notify_handler, gpg))
471 rc = gpg_error (GPG_ERR_GENERAL);
478 rc = add_arg (gpg, "--homedir");
480 rc = add_arg (gpg, home_dir);
485 rc = add_arg (gpg, "--status-fd");
491 _gpgme_io_fd2str (buf, sizeof (buf), gpg->status.fd[1]);
492 rc = add_arg_with_locp (gpg, buf, &gpg->status.arg_loc);
497 rc = add_arg (gpg, "--no-tty");
499 rc = add_arg (gpg, "--charset");
501 rc = add_arg (gpg, "utf8");
503 rc = add_arg (gpg, "--enable-progress-filter");
507 rc = _gpgme_getenv ("DISPLAY", &dft_display);
512 rc = add_arg (gpg, "--display");
514 rc = add_arg (gpg, dft_display);
523 err = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
525 rc = gpg_error_from_errno (err);
530 rc = add_arg (gpg, "--ttyname");
532 rc = add_arg (gpg, dft_ttyname);
538 rc = _gpgme_getenv ("TERM", &dft_ttytype);
544 rc = add_arg (gpg, "--ttytype");
546 rc = add_arg (gpg, dft_ttytype);
566 gpg_set_locale (void *engine, int category, const char *value)
568 engine_gpg_t gpg = engine;
573 else if (category == LC_CTYPE)
577 free (gpg->lc_ctype);
578 gpg->lc_ctype = NULL;
582 gpg->lc_ctype = strdup (value);
584 return gpg_error_from_syserror ();
589 else if (category == LC_MESSAGES)
591 if (gpg->lc_messages)
593 free (gpg->lc_messages);
594 gpg->lc_messages = NULL;
598 gpg->lc_messages = strdup (value);
599 if (!gpg->lc_messages)
600 return gpg_error_from_syserror ();
603 #endif /* LC_MESSAGES */
605 return gpg_error (GPG_ERR_INV_VALUE);
611 /* Note, that the status_handler is allowed to modifiy the args
614 gpg_set_status_handler (void *engine, engine_status_handler_t fnc,
617 engine_gpg_t gpg = engine;
619 gpg->status.fnc = fnc;
620 gpg->status.fnc_value = fnc_value;
623 /* Kludge to process --with-colon output. */
625 gpg_set_colon_line_handler (void *engine, engine_colon_line_handler_t fnc,
628 engine_gpg_t gpg = engine;
630 gpg->colon.bufsize = 1024;
631 gpg->colon.readpos = 0;
632 gpg->colon.buffer = malloc (gpg->colon.bufsize);
633 if (!gpg->colon.buffer)
634 return gpg_error_from_errno (errno);
636 if (_gpgme_io_pipe (gpg->colon.fd, 1) == -1)
638 int saved_errno = errno;
639 free (gpg->colon.buffer);
640 gpg->colon.buffer = NULL;
641 return gpg_error_from_errno (saved_errno);
643 if (_gpgme_io_set_close_notify (gpg->colon.fd[0], close_notify_handler, gpg)
644 || _gpgme_io_set_close_notify (gpg->colon.fd[1],
645 close_notify_handler, gpg))
646 return gpg_error (GPG_ERR_GENERAL);
648 gpg->colon.fnc = fnc;
649 gpg->colon.fnc_value = fnc_value;
655 command_handler (void *opaque, int fd)
657 struct io_cb_data *data = (struct io_cb_data *) opaque;
658 engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
661 assert (gpg->cmd.used);
662 assert (gpg->cmd.code);
663 assert (gpg->cmd.fnc);
665 err = gpg->cmd.fnc (gpg->cmd.fnc_value, gpg->cmd.code, gpg->cmd.keyword, fd,
669 /* And sleep again until read_status will wake us up again. */
670 /* XXX We must check if there are any more fds active after removing
672 (*gpg->io_cbs.remove) (gpg->fd_data_map[gpg->cmd.idx].tag);
673 gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
674 gpg->fd_data_map[gpg->cmd.idx].fd = -1;
679 /* We always need to send at least a newline character. */
681 _gpgme_io_write (fd, "\n", 1);
688 /* The Fnc will be called to get a value for one of the commands with
689 a key KEY. If the Code passed to FNC is 0, the function may release
690 resources associated with the returned value from another call. To
691 match such a second call to a first call, the returned value from
692 the first call is passed as keyword. */
694 gpg_set_command_handler (void *engine, engine_command_handler_t fnc,
695 void *fnc_value, gpgme_data_t linked_data)
697 engine_gpg_t gpg = engine;
700 rc = add_arg (gpg, "--command-fd");
704 /* This is a hack. We don't have a real data object. The only
705 thing that matters is that we use something unique, so we use the
706 address of the cmd structure in the gpg object. */
707 rc = add_data (gpg, (void *) &gpg->cmd, -2, 0);
712 gpg->cmd.cb_data = (void *) &gpg->cmd;
713 gpg->cmd.fnc_value = fnc_value;
714 gpg->cmd.linked_data = linked_data;
721 build_argv (engine_gpg_t gpg)
724 struct arg_and_data_s *a;
725 struct fd_data_map_s *fd_data_map;
726 size_t datac=0, argc=0;
728 int need_special = 0;
732 /* We don't want to use the agent with a malformed environment
733 variable. This is only a very basic test but sufficient to make
734 our life in the regression tests easier. */
735 err = _gpgme_getenv ("GPG_AGENT_INFO", &p);
738 use_agent = (p && strchr (p, ':'));
744 free_argv (gpg->argv);
747 if (gpg->fd_data_map)
749 free_fd_data_map (gpg->fd_data_map);
750 gpg->fd_data_map = NULL;
753 argc++; /* For argv[0]. */
754 for (a = gpg->arglist; a; a = a->next)
759 /*fprintf (stderr, "build_argv: data\n" );*/
761 if (a->dup_to == -1 && !a->print_fd)
766 /* fprintf (stderr, "build_argv: arg=`%s'\n", a->arg );*/
774 argc++; /* --batch */
775 argc += 1; /* --no-sk-comment */
777 argv = calloc (argc + 1, sizeof *argv);
779 return gpg_error_from_errno (errno);
780 fd_data_map = calloc (datac + 1, sizeof *fd_data_map);
783 int saved_errno = errno;
785 return gpg_error_from_errno (saved_errno);
789 argv[argc] = strdup ("gpg"); /* argv[0] */
792 int saved_errno = errno;
795 return gpg_error_from_errno (saved_errno);
800 argv[argc] = strdup ("--enable-special-filenames");
803 int saved_errno = errno;
806 return gpg_error_from_errno (saved_errno);
812 argv[argc] = strdup ("--use-agent");
815 int saved_errno = errno;
818 return gpg_error_from_errno (saved_errno);
824 argv[argc] = strdup ("--batch");
827 int saved_errno = errno;
830 return gpg_error_from_errno (saved_errno);
834 argv[argc] = strdup ("--no-sk-comment");
837 int saved_errno = errno;
840 return gpg_error_from_errno (saved_errno);
843 for (a = gpg->arglist; a; a = a->next)
846 *(a->arg_locp) = argc;
850 /* Create a pipe to pass it down to gpg. */
851 fd_data_map[datac].inbound = a->inbound;
857 if (_gpgme_io_pipe (fds, fd_data_map[datac].inbound ? 1 : 0)
860 int saved_errno = errno;
863 return gpg_error (saved_errno);
865 if (_gpgme_io_set_close_notify (fds[0],
866 close_notify_handler, gpg)
867 || _gpgme_io_set_close_notify (fds[1],
868 close_notify_handler,
871 return gpg_error (GPG_ERR_GENERAL);
873 /* If the data_type is FD, we have to do a dup2 here. */
874 if (fd_data_map[datac].inbound)
876 fd_data_map[datac].fd = fds[0];
877 fd_data_map[datac].peer_fd = fds[1];
881 fd_data_map[datac].fd = fds[1];
882 fd_data_map[datac].peer_fd = fds[0];
886 /* Hack to get hands on the fd later. */
889 if (gpg->cmd.cb_data == a->data)
891 assert (gpg->cmd.idx == -1);
892 gpg->cmd.idx = datac;
894 else if (gpg->cmd.linked_data == a->data)
896 assert (gpg->cmd.linked_idx == -1);
897 gpg->cmd.linked_idx = datac;
901 fd_data_map[datac].data = a->data;
902 fd_data_map[datac].dup_to = a->dup_to;
909 argv[argc] = malloc (buflen);
912 int saved_errno = errno;
915 return gpg_error_from_errno (saved_errno);
926 _gpgme_io_fd2str (ptr, buflen, fd_data_map[datac].peer_fd);
927 fd_data_map[datac].arg_loc = argc;
934 argv[argc] = strdup (a->arg);
937 int saved_errno = errno;
940 return gpg_error_from_errno (saved_errno);
947 gpg->fd_data_map = fd_data_map;
953 add_io_cb (engine_gpg_t gpg, int fd, int dir, gpgme_io_cb_t handler, void *data,
958 err = (*gpg->io_cbs.add) (gpg->io_cbs.add_priv, fd, dir, handler, data, tag);
962 /* FIXME Kludge around poll() problem. */
963 err = _gpgme_io_set_nonblocking (fd);
969 status_cmp (const void *ap, const void *bp)
971 const struct status_table_s *a = ap;
972 const struct status_table_s *b = bp;
974 return strcmp (a->name, b->name);
978 /* Handle the status output of GnuPG. This function does read entire
979 lines and passes them as C strings to the callback function (we can
980 use C Strings because the status output is always UTF-8 encoded).
981 Of course we have to buffer the lines to cope with long lines
982 e.g. with a large user ID. Note: We can optimize this to only cope
983 with status line code we know about and skip all other stuff
984 without buffering (i.e. without extending the buffer). */
986 read_status (engine_gpg_t gpg)
990 size_t bufsize = gpg->status.bufsize;
991 char *buffer = gpg->status.buffer;
992 size_t readpos = gpg->status.readpos;
995 if (bufsize - readpos < 256)
997 /* Need more room for the read. */
999 buffer = realloc (buffer, bufsize);
1001 return gpg_error_from_errno (errno);
1004 nread = _gpgme_io_read (gpg->status.fd[0],
1005 buffer + readpos, bufsize-readpos);
1007 return gpg_error_from_errno (errno);
1011 gpg->status.eof = 1;
1012 if (gpg->status.fnc)
1015 err = gpg->status.fnc (gpg->status.fnc_value, GPGME_STATUS_EOF, "");
1024 for (p = buffer + readpos; nread; nread--, p++)
1028 /* (we require that the last line is terminated by a LF) */
1029 if (p > buffer && p[-1] == '\r')
1032 if (!strncmp (buffer, "[GNUPG:] ", 9)
1033 && buffer[9] >= 'A' && buffer[9] <= 'Z')
1035 struct status_table_s t, *r;
1038 rest = strchr (buffer + 9, ' ');
1040 rest = p; /* Set to an empty string. */
1045 /* (the status table has one extra element) */
1046 r = bsearch (&t, status_table, DIM(status_table) - 1,
1047 sizeof t, status_cmp);
1051 && (r->code == GPGME_STATUS_GET_BOOL
1052 || r->code == GPGME_STATUS_GET_LINE
1053 || r->code == GPGME_STATUS_GET_HIDDEN))
1055 gpg->cmd.code = r->code;
1056 if (gpg->cmd.keyword)
1057 free (gpg->cmd.keyword);
1058 gpg->cmd.keyword = strdup (rest);
1059 if (!gpg->cmd.keyword)
1060 return gpg_error_from_errno (errno);
1061 /* This should be the last thing we have
1062 received and the next thing will be that
1063 the command handler does its action. */
1065 TRACE0 (DEBUG_CTX, "gpgme:read_status", 0,
1066 "error: unexpected data");
1068 add_io_cb (gpg, gpg->cmd.fd, 0,
1069 command_handler, gpg,
1070 &gpg->fd_data_map[gpg->cmd.idx].tag);
1071 gpg->fd_data_map[gpg->cmd.idx].fd = gpg->cmd.fd;
1074 else if (gpg->status.fnc)
1077 err = gpg->status.fnc (gpg->status.fnc_value,
1083 if (r->code == GPGME_STATUS_END_STREAM)
1087 /* Before we can actually add the
1088 command fd, we might have to flush
1089 the linked output data pipe. */
1090 if (gpg->cmd.linked_idx != -1
1091 && gpg->fd_data_map[gpg->cmd.linked_idx].fd
1094 struct io_select_fd_s fds;
1096 gpg->fd_data_map[gpg->cmd.linked_idx].fd;
1103 _gpgme_io_select (&fds, 1, 1);
1105 _gpgme_data_inbound_handler
1106 (gpg->cmd.linked_data, fds.fd);
1108 while (fds.signaled);
1111 /* XXX We must check if there are any
1112 more fds active after removing this
1114 (*gpg->io_cbs.remove)
1115 (gpg->fd_data_map[gpg->cmd.idx].tag);
1116 gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
1117 gpg->fd_data_map[gpg->cmd.idx].fd = -1;
1122 /* To reuse the buffer for the next line we have to
1123 shift the remaining data to the buffer start and
1124 restart the loop Hmmm: We can optimize this function
1125 by looking forward in the buffer to see whether a
1126 second complete line is available and in this case
1127 avoid the memmove for this line. */
1130 memmove (buffer, p, nread);
1132 break; /* the for loop */
1139 /* Update the gpg object. */
1140 gpg->status.bufsize = bufsize;
1141 gpg->status.buffer = buffer;
1142 gpg->status.readpos = readpos;
1147 static gpgme_error_t
1148 status_handler (void *opaque, int fd)
1150 struct io_cb_data *data = (struct io_cb_data *) opaque;
1151 engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
1154 assert (fd == gpg->status.fd[0]);
1155 err = read_status (gpg);
1158 if (gpg->status.eof)
1159 _gpgme_io_close (fd);
1164 static gpgme_error_t
1165 read_colon_line (engine_gpg_t gpg)
1169 size_t bufsize = gpg->colon.bufsize;
1170 char *buffer = gpg->colon.buffer;
1171 size_t readpos = gpg->colon.readpos;
1174 if (bufsize - readpos < 256)
1176 /* Need more room for the read. */
1178 buffer = realloc (buffer, bufsize);
1180 return gpg_error_from_errno (errno);
1183 nread = _gpgme_io_read (gpg->colon.fd[0], buffer+readpos, bufsize-readpos);
1185 return gpg_error_from_errno (errno);
1190 assert (gpg->colon.fnc);
1191 gpg->colon.fnc (gpg->colon.fnc_value, NULL);
1197 for (p = buffer + readpos; nread; nread--, p++)
1201 /* (we require that the last line is terminated by a LF)
1202 and we skip empty lines. Note: we use UTF8 encoding
1203 and escaping of special characters. We require at
1204 least one colon to cope with some other printed
1207 if (*buffer && strchr (buffer, ':'))
1211 if (gpg->colon.preprocess_fnc)
1215 err = gpg->colon.preprocess_fnc (buffer, &line);
1220 assert (gpg->colon.fnc);
1221 gpg->colon.fnc (gpg->colon.fnc_value, line ? line : buffer);
1226 /* To reuse the buffer for the next line we have to
1227 shift the remaining data to the buffer start and
1228 restart the loop Hmmm: We can optimize this function
1229 by looking forward in the buffer to see whether a
1230 second complete line is available and in this case
1231 avoid the memmove for this line. */
1234 memmove (buffer, p, nread);
1236 break; /* The for loop. */
1243 /* Update the gpg object. */
1244 gpg->colon.bufsize = bufsize;
1245 gpg->colon.buffer = buffer;
1246 gpg->colon.readpos = readpos;
1251 /* This colonline handler thing is not the clean way to do it. It
1252 might be better to enhance the gpgme_data_t object to act as a wrapper
1253 for a callback. Same goes for the status thing. For now we use
1254 this thing here because it is easier to implement. */
1255 static gpgme_error_t
1256 colon_line_handler (void *opaque, int fd)
1258 struct io_cb_data *data = (struct io_cb_data *) opaque;
1259 engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
1260 gpgme_error_t rc = 0;
1262 assert (fd == gpg->colon.fd[0]);
1263 rc = read_colon_line (gpg);
1267 _gpgme_io_close (fd);
1272 static gpgme_error_t
1273 start (engine_gpg_t gpg)
1279 struct spawn_fd_item_s *fd_list;
1283 return gpg_error (GPG_ERR_INV_VALUE);
1285 if (!gpg->file_name && !_gpgme_get_gpg_path ())
1286 return gpg_error (GPG_ERR_INV_ENGINE);
1290 rc = add_arg_ext (gpg, gpg->lc_ctype, 1);
1292 rc = add_arg_ext (gpg, "--lc-ctype", 1);
1297 if (gpg->lc_messages)
1299 rc = add_arg_ext (gpg, gpg->lc_messages, 1);
1301 rc = add_arg_ext (gpg, "--lc-messages", 1);
1306 rc = build_argv (gpg);
1310 /* status_fd, colon_fd and end of list. */
1312 for (i = 0; gpg->fd_data_map[i].data; i++)
1314 fd_list = calloc (n, sizeof *fd_list);
1316 return gpg_error_from_errno (errno);
1318 /* Build the fd list for the child. */
1320 fd_list[n].fd = gpg->status.fd[1];
1321 fd_list[n].dup_to = -1;
1322 fd_list[n].arg_loc = gpg->status.arg_loc;
1326 fd_list[n].fd = gpg->colon.fd[1];
1327 fd_list[n].dup_to = 1;
1330 for (i = 0; gpg->fd_data_map[i].data; i++)
1332 fd_list[n].fd = gpg->fd_data_map[i].peer_fd;
1333 fd_list[n].dup_to = gpg->fd_data_map[i].dup_to;
1334 fd_list[n].arg_loc = gpg->fd_data_map[i].arg_loc;
1338 fd_list[n].dup_to = -1;
1340 status = _gpgme_io_spawn (gpg->file_name ? gpg->file_name :
1341 _gpgme_get_gpg_path (), gpg->argv,
1342 IOSPAWN_FLAG_ALLOW_SET_FG,
1343 fd_list, NULL, NULL, &pid);
1344 saved_errno = errno;
1348 return gpg_error_from_errno (saved_errno);
1350 /*_gpgme_register_term_handler ( closure, closure_value, pid );*/
1352 rc = add_io_cb (gpg, gpg->status.fd[0], 1, status_handler, gpg,
1355 /* FIXME: kill the child */
1360 assert (gpg->colon.fd[0] != -1);
1361 rc = add_io_cb (gpg, gpg->colon.fd[0], 1, colon_line_handler, gpg,
1364 /* FIXME: kill the child */
1368 for (i = 0; gpg->fd_data_map[i].data; i++)
1370 if (gpg->cmd.used && i == gpg->cmd.idx)
1372 /* Park the cmd fd. */
1373 gpg->cmd.fd = gpg->fd_data_map[i].fd;
1374 gpg->fd_data_map[i].fd = -1;
1378 rc = add_io_cb (gpg, gpg->fd_data_map[i].fd,
1379 gpg->fd_data_map[i].inbound,
1380 gpg->fd_data_map[i].inbound
1381 ? _gpgme_data_inbound_handler
1382 : _gpgme_data_outbound_handler,
1383 gpg->fd_data_map[i].data, &gpg->fd_data_map[i].tag);
1386 /* FIXME: kill the child */
1391 gpg_io_event (gpg, GPGME_EVENT_START, NULL);
1393 /* fixme: check what data we can release here */
1398 static gpgme_error_t
1399 gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
1401 engine_gpg_t gpg = engine;
1404 err = add_arg (gpg, "--decrypt");
1406 /* Tell the gpg object about the data. */
1408 err = add_arg (gpg, "--output");
1410 err = add_arg (gpg, "-");
1412 err = add_data (gpg, plain, 1, 1);
1414 err = add_arg (gpg, "--");
1416 err = add_data (gpg, ciph, -1, 0);
1423 static gpgme_error_t
1424 gpg_delete (void *engine, gpgme_key_t key, int allow_secret)
1426 engine_gpg_t gpg = engine;
1429 err = add_arg (gpg, allow_secret ? "--delete-secret-and-public-key"
1432 err = add_arg (gpg, "--");
1435 if (!key->subkeys || !key->subkeys->fpr)
1436 return gpg_error (GPG_ERR_INV_VALUE);
1438 err = add_arg (gpg, key->subkeys->fpr);
1447 static gpgme_error_t
1448 gpg_passwd (void *engine, gpgme_key_t key, unsigned int flags)
1450 engine_gpg_t gpg = engine;
1453 if (!key || !key->subkeys || !key->subkeys->fpr)
1454 return gpg_error (GPG_ERR_INV_CERT_OBJ);
1456 err = add_arg (gpg, "--passwd");
1458 err = add_arg (gpg, key->subkeys->fpr);
1465 static gpgme_error_t
1466 append_args_from_signers (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1468 gpgme_error_t err = 0;
1472 for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++)
1474 const char *s = key->subkeys ? key->subkeys->keyid : NULL;
1478 err = add_arg (gpg, "-u");
1480 err = add_arg (gpg, s);
1482 gpgme_key_unref (key);
1489 static gpgme_error_t
1490 append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1492 gpgme_error_t err = 0;
1493 gpgme_sig_notation_t notation;
1495 notation = gpgme_sig_notation_get (ctx);
1497 while (!err && notation)
1500 && !(notation->flags & GPGME_SIG_NOTATION_HUMAN_READABLE))
1501 err = gpg_error (GPG_ERR_INV_VALUE);
1502 else if (notation->name)
1506 /* Maximum space needed is one byte for the "critical" flag,
1507 the name, one byte for '=', the value, and a terminating
1510 arg = malloc (1 + notation->name_len + 1 + notation->value_len + 1);
1512 err = gpg_error_from_errno (errno);
1518 if (notation->critical)
1521 memcpy (argp, notation->name, notation->name_len);
1522 argp += notation->name_len;
1526 /* We know that notation->name is '\0' terminated. */
1527 strcpy (argp, notation->value);
1531 err = add_arg (gpg, "--sig-notation");
1533 err = add_arg (gpg, arg);
1540 /* This is a policy URL. */
1544 if (notation->critical)
1546 value = malloc (1 + notation->value_len + 1);
1548 err = gpg_error_from_errno (errno);
1552 /* We know that notation->value is '\0' terminated. */
1553 strcpy (&value[1], notation->value);
1557 value = notation->value;
1560 err = add_arg (gpg, "--sig-policy-url");
1562 err = add_arg (gpg, value);
1564 if (value != notation->value)
1568 notation = notation->next;
1574 static gpgme_error_t
1575 gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out,
1576 gpgme_ctx_t ctx /* FIXME */)
1578 engine_gpg_t gpg = engine;
1581 err = add_arg (gpg, "--with-colons");
1583 err = append_args_from_signers (gpg, ctx);
1585 err = add_arg (gpg, type == 0 ? "--edit-key" : "--card-edit");
1587 err = add_data (gpg, out, 1, 1);
1589 err = add_arg (gpg, "--");
1590 if (!err && type == 0)
1592 const char *s = key->subkeys ? key->subkeys->fpr : NULL;
1594 err = gpg_error (GPG_ERR_INV_VALUE);
1596 err = add_arg (gpg, s);
1605 static gpgme_error_t
1606 append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[])
1608 gpgme_error_t err = 0;
1613 if (!recp[i]->subkeys || !recp[i]->subkeys->fpr)
1614 err = gpg_error (GPG_ERR_INV_VALUE);
1616 err = add_arg (gpg, "-r");
1618 err = add_arg (gpg, recp[i]->subkeys->fpr);
1627 static gpgme_error_t
1628 gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
1629 gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
1631 engine_gpg_t gpg = engine;
1633 int symmetric = !recp;
1635 err = add_arg (gpg, symmetric ? "--symmetric" : "--encrypt");
1637 if (!err && use_armor)
1638 err = add_arg (gpg, "--armor");
1642 /* If we know that all recipients are valid (full or ultimate trust)
1643 we can suppress further checks. */
1644 if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1645 err = add_arg (gpg, "--always-trust");
1647 if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
1648 err = add_arg (gpg, "--no-encrypt-to");
1651 err = append_args_from_recipients (gpg, recp);
1654 /* Tell the gpg object about the data. */
1656 err = add_arg (gpg, "--output");
1658 err = add_arg (gpg, "-");
1660 err = add_data (gpg, ciph, 1, 1);
1661 if (gpgme_data_get_file_name (plain))
1664 err = add_arg (gpg, "--set-filename");
1666 err = add_arg (gpg, gpgme_data_get_file_name (plain));
1669 err = add_arg (gpg, "--");
1671 err = add_data (gpg, plain, -1, 0);
1680 static gpgme_error_t
1681 gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
1682 gpgme_encrypt_flags_t flags, gpgme_data_t plain,
1683 gpgme_data_t ciph, int use_armor,
1684 gpgme_ctx_t ctx /* FIXME */)
1686 engine_gpg_t gpg = engine;
1689 err = add_arg (gpg, "--encrypt");
1691 err = add_arg (gpg, "--sign");
1692 if (!err && use_armor)
1693 err = add_arg (gpg, "--armor");
1695 /* If we know that all recipients are valid (full or ultimate trust)
1696 we can suppress further checks. */
1697 if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1698 err = add_arg (gpg, "--always-trust");
1701 err = append_args_from_recipients (gpg, recp);
1704 err = append_args_from_signers (gpg, ctx);
1706 err = append_args_from_sig_notations (gpg, ctx);
1708 /* Tell the gpg object about the data. */
1710 err = add_arg (gpg, "--output");
1712 err = add_arg (gpg, "-");
1714 err = add_data (gpg, ciph, 1, 1);
1715 if (gpgme_data_get_file_name (plain))
1718 err = add_arg (gpg, "--set-filename");
1720 err = add_arg (gpg, gpgme_data_get_file_name (plain));
1723 err = add_arg (gpg, "--");
1725 err = add_data (gpg, plain, -1, 0);
1734 static gpgme_error_t
1735 export_common (engine_gpg_t gpg, gpgme_export_mode_t mode,
1736 gpgme_data_t keydata, int use_armor)
1738 gpgme_error_t err = 0;
1740 if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
1741 |GPGME_EXPORT_MODE_MINIMAL)))
1742 return gpg_error (GPG_ERR_NOT_SUPPORTED);
1744 if ((mode & GPGME_EXPORT_MODE_MINIMAL))
1745 err = add_arg (gpg, "--export-options=export-minimal");
1749 else if ((mode & GPGME_EXPORT_MODE_EXTERN))
1751 err = add_arg (gpg, "--send-keys");
1755 err = add_arg (gpg, "--export");
1756 if (!err && use_armor)
1757 err = add_arg (gpg, "--armor");
1759 err = add_data (gpg, keydata, 1, 1);
1762 err = add_arg (gpg, "--");
1768 static gpgme_error_t
1769 gpg_export (void *engine, const char *pattern, gpgme_export_mode_t mode,
1770 gpgme_data_t keydata, int use_armor)
1772 engine_gpg_t gpg = engine;
1775 err = export_common (gpg, mode, keydata, use_armor);
1777 if (!err && pattern && *pattern)
1778 err = add_arg (gpg, pattern);
1787 static gpgme_error_t
1788 gpg_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
1789 gpgme_data_t keydata, int use_armor)
1791 engine_gpg_t gpg = engine;
1794 err = export_common (gpg, mode, keydata, use_armor);
1798 while (!err && *pattern && **pattern)
1799 err = add_arg (gpg, *(pattern++));
1809 static gpgme_error_t
1810 gpg_genkey (void *engine, gpgme_data_t help_data, int use_armor,
1811 gpgme_data_t pubkey, gpgme_data_t seckey)
1813 engine_gpg_t gpg = engine;
1817 return gpg_error (GPG_ERR_INV_VALUE);
1819 /* We need a special mechanism to get the fd of a pipe here, so that
1820 we can use this for the %pubring and %secring parameters. We
1821 don't have this yet, so we implement only the adding to the
1822 standard keyrings. */
1823 if (pubkey || seckey)
1824 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1826 err = add_arg (gpg, "--gen-key");
1827 if (!err && use_armor)
1828 err = add_arg (gpg, "--armor");
1830 err = add_arg (gpg, "--");
1832 err = add_data (gpg, help_data, -1, 0);
1840 /* Return the next DELIM delimited string from DATA as a C-string.
1841 The caller needs to provide the address of a pointer variable which
1842 he has to set to NULL before the first call. After the last call
1843 to this function, this function needs to be called once more with
1844 DATA set to NULL so that the function can release its internal
1845 state. After that the pointer variable is free for use again.
1846 Note that we use a delimiter and thus a trailing delimiter is not
1847 required. DELIM may not be changed after the first call. */
1849 string_from_data (gpgme_data_t data, int delim,
1850 void **helpptr, gpgme_error_t *r_err)
1852 #define MYBUFLEN 2000 /* Fixme: We don't support URLs longer than that. */
1855 int nbytes; /* Length of the last returned string including
1857 int buflen; /* Valid length of BUF. */
1858 char buf[MYBUFLEN+1]; /* Buffer with one byte extra space. */
1878 self = malloc (sizeof *self);
1881 *r_err = gpg_error_from_syserror ();
1893 assert (self->nbytes <= self->buflen);
1894 memmove (self->buf, self->buf + self->nbytes, self->buflen - self->nbytes);
1895 self->buflen -= self->nbytes;
1900 /* Fixme: This is fairly infective scanning because we may scan
1901 the buffer several times. */
1902 p = memchr (self->buf, delim, self->buflen);
1906 self->nbytes = p - self->buf + 1;
1910 if ( !(MYBUFLEN - self->buflen) )
1912 /* Not enough space - URL too long. */
1913 *r_err = gpg_error (GPG_ERR_TOO_LARGE);
1917 nread = gpgme_data_read (data, self->buf + self->buflen,
1918 MYBUFLEN - self->buflen);
1921 *r_err = gpg_error_from_syserror ();
1924 self->buflen += nread;
1928 /* EOF reached. If we have anything in the buffer, append a Nul and
1933 self->buf[self->buflen] = 0; /* (we allocated one extra byte) */
1942 static gpgme_error_t
1943 gpg_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray)
1945 engine_gpg_t gpg = engine;
1948 gpgme_data_encoding_t dataenc;
1950 if (keydata && keyarray)
1951 return gpg_error (GPG_ERR_INV_VALUE); /* Only one is allowed. */
1953 dataenc = gpgme_data_get_encoding (keydata);
1957 err = add_arg (gpg, "--recv-keys");
1959 err = add_arg (gpg, "--");
1960 for (idx=0; !err && keyarray[idx]; idx++)
1962 if (keyarray[idx]->protocol != GPGME_PROTOCOL_OpenPGP)
1964 else if (!keyarray[idx]->subkeys)
1966 else if (keyarray[idx]->subkeys->fpr && *keyarray[idx]->subkeys->fpr)
1967 err = add_arg (gpg, keyarray[idx]->subkeys->fpr);
1968 else if (*keyarray[idx]->subkeys->keyid)
1969 err = add_arg (gpg, keyarray[idx]->subkeys->keyid);
1972 else if (dataenc == GPGME_DATA_ENCODING_URL
1973 || dataenc == GPGME_DATA_ENCODING_URL0)
1978 int delim = (dataenc == GPGME_DATA_ENCODING_URL)? '\n': 0;
1980 /* FIXME: --fetch-keys is probably not correct because it can't
1981 grok all kinds of URLs. On Unix it should just work but on
1982 Windows we will build the command line and that may fail for
1983 some embedded control characters. It is anyway limited to
1984 the maximum size of the command line. We need another
1985 command which can take its input from a file. Maybe we
1986 should use an option to gpg to modify such commands (ala
1988 err = add_arg (gpg, "--fetch-keys");
1990 err = add_arg (gpg, "--");
1993 && (string = string_from_data (keydata, delim, &helpptr, &xerr)))
1994 err = add_arg (gpg, string);
1997 string_from_data (NULL, delim, &helpptr, &xerr);
1999 else if (dataenc == GPGME_DATA_ENCODING_URLESC)
2001 /* Already escaped URLs are not yet supported. */
2002 err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2006 err = add_arg (gpg, "--import");
2008 err = add_arg (gpg, "--");
2010 err = add_data (gpg, keydata, -1, 0);
2020 /* The output for external keylistings in GnuPG is different from all
2021 the other key listings. We catch this here with a special
2022 preprocessor that reformats the colon handler lines. */
2023 static gpgme_error_t
2024 gpg_keylist_preprocess (char *line, char **r_line)
2028 RT_NONE, RT_INFO, RT_PUB, RT_UID
2031 #define NR_FIELDS 16
2032 char *field[NR_FIELDS];
2037 while (line && fields < NR_FIELDS)
2039 field[fields++] = line;
2040 line = strchr (line, ':');
2045 if (!strcmp (field[0], "info"))
2047 else if (!strcmp (field[0], "pub"))
2049 else if (!strcmp (field[0], "uid"))
2057 /* FIXME: Eventually, check the version number at least. */
2066 pub:<keyid>:<algo>:<keylen>:<creationdate>:<expirationdate>:<flags>
2068 as defined in 5.2. Machine Readable Indexes of the OpenPGP
2069 HTTP Keyserver Protocol (draft).
2072 pub:o<flags>:<keylen>:<algo>:<keyid>:<creatdate>:<expdate>::::::::
2075 if (asprintf (r_line, "pub:o%s:%s:%s:%s:%s:%s::::::::",
2076 field[6], field[3], field[2], field[1],
2077 field[4], field[5]) < 0)
2078 return gpg_error_from_errno (errno);
2084 uid:<escaped uid string>:<creationdate>:<expirationdate>:<flags>
2086 as defined in 5.2. Machine Readable Indexes of the OpenPGP
2087 HTTP Keyserver Protocol (draft).
2090 uid:o<flags>::::<creatdate>:<expdate>:::<c-coded uid>:
2094 /* The user ID is percent escaped, but we want c-coded.
2095 Because we have to replace each '%HL' by '\xHL', we need at
2096 most 4/3 th the number of bytes. But because we also need
2097 to escape the backslashes we allocate twice as much. */
2098 char *uid = malloc (2 * strlen (field[1]) + 1);
2103 return gpg_error_from_errno (errno);
2113 /* Copy the next two bytes unconditionally. */
2115 *(dst++) = *(src++);
2117 *(dst++) = *(src++);
2119 else if (*src == '\\')
2125 *(dst++) = *(src++);
2129 if (asprintf (r_line, "uid:o%s::::%s:%s:::%s:",
2130 field[4], field[2], field[3], uid) < 0)
2131 return gpg_error_from_errno (errno);
2136 /* Unknown record. */
2145 gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
2146 gpgme_keylist_mode_t mode)
2150 err = add_arg (gpg, "--with-colons");
2152 err = add_arg (gpg, "--fixed-list-mode");
2154 err = add_arg (gpg, "--with-fingerprint");
2156 err = add_arg (gpg, "--with-fingerprint");
2158 && (mode & GPGME_KEYLIST_MODE_SIGS)
2159 && (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS))
2161 err = add_arg (gpg, "--list-options");
2163 err = add_arg (gpg, "show-sig-subpackets=\"20,26\"");
2167 if ( (mode & GPGME_KEYLIST_MODE_EXTERN) )
2170 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
2171 else if ( (mode & GPGME_KEYLIST_MODE_LOCAL))
2173 /* The local+extern mode is special. It works only with
2174 gpg >= 2.0.10. FIXME: We should check that we have
2175 such a version to that we can return a proper error
2176 code. The problem is that we don't know the context
2177 here and thus can't access the cached version number
2178 for the engine info structure. */
2179 err = add_arg (gpg, "--locate-keys");
2180 if ((mode & GPGME_KEYLIST_MODE_SIGS))
2181 err = add_arg (gpg, "--with-sig-check");
2185 err = add_arg (gpg, "--search-keys");
2186 gpg->colon.preprocess_fnc = gpg_keylist_preprocess;
2191 err = add_arg (gpg, secret_only ? "--list-secret-keys"
2192 : ((mode & GPGME_KEYLIST_MODE_SIGS)
2193 ? "--check-sigs" : "--list-keys"));
2197 err = add_arg (gpg, "--");
2203 static gpgme_error_t
2204 gpg_keylist (void *engine, const char *pattern, int secret_only,
2205 gpgme_keylist_mode_t mode)
2207 engine_gpg_t gpg = engine;
2210 err = gpg_keylist_build_options (gpg, secret_only, mode);
2212 if (!err && pattern && *pattern)
2213 err = add_arg (gpg, pattern);
2222 static gpgme_error_t
2223 gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
2224 int reserved, gpgme_keylist_mode_t mode)
2226 engine_gpg_t gpg = engine;
2230 return gpg_error (GPG_ERR_INV_VALUE);
2232 err = gpg_keylist_build_options (gpg, secret_only, mode);
2236 while (!err && *pattern && **pattern)
2237 err = add_arg (gpg, *(pattern++));
2247 static gpgme_error_t
2248 gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
2249 gpgme_sig_mode_t mode, int use_armor, int use_textmode,
2250 int include_certs, gpgme_ctx_t ctx /* FIXME */)
2252 engine_gpg_t gpg = engine;
2255 if (mode == GPGME_SIG_MODE_CLEAR)
2256 err = add_arg (gpg, "--clearsign");
2259 err = add_arg (gpg, "--sign");
2260 if (!err && mode == GPGME_SIG_MODE_DETACH)
2261 err = add_arg (gpg, "--detach");
2262 if (!err && use_armor)
2263 err = add_arg (gpg, "--armor");
2264 if (!err && use_textmode)
2265 err = add_arg (gpg, "--textmode");
2269 err = append_args_from_signers (gpg, ctx);
2271 err = append_args_from_sig_notations (gpg, ctx);
2273 if (gpgme_data_get_file_name (in))
2276 err = add_arg (gpg, "--set-filename");
2278 err = add_arg (gpg, gpgme_data_get_file_name (in));
2281 /* Tell the gpg object about the data. */
2283 err = add_arg (gpg, "--");
2285 err = add_data (gpg, in, -1, 0);
2287 err = add_data (gpg, out, 1, 1);
2295 static gpgme_error_t
2296 gpg_trustlist (void *engine, const char *pattern)
2298 engine_gpg_t gpg = engine;
2301 err = add_arg (gpg, "--with-colons");
2303 err = add_arg (gpg, "--list-trust-path");
2305 /* Tell the gpg object about the data. */
2307 err = add_arg (gpg, "--");
2309 err = add_arg (gpg, pattern);
2318 static gpgme_error_t
2319 gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
2320 gpgme_data_t plaintext)
2322 engine_gpg_t gpg = engine;
2323 gpgme_error_t err = 0;
2327 /* Normal or cleartext signature. */
2329 err = add_arg (gpg, "--output");
2331 err = add_arg (gpg, "-");
2333 err = add_arg (gpg, "--");
2335 err = add_data (gpg, sig, -1, 0);
2337 err = add_data (gpg, plaintext, 1, 1);
2341 err = add_arg (gpg, "--verify");
2343 err = add_arg (gpg, "--");
2345 err = add_data (gpg, sig, -1, 0);
2346 if (!err && signed_text)
2347 err = add_data (gpg, signed_text, -1, 0);
2358 gpg_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
2360 engine_gpg_t gpg = engine;
2362 gpg->io_cbs = *io_cbs;
2366 struct engine_ops _gpgme_engine_ops_gpg =
2368 /* Static functions. */
2369 _gpgme_get_gpg_path,
2372 gpg_get_req_version,
2375 /* Member functions. */
2378 gpg_set_status_handler,
2379 gpg_set_command_handler,
2380 gpg_set_colon_line_handler,
2382 NULL, /* set_protocol */
2384 gpg_decrypt, /* decrypt_verify */
2398 NULL, /* getauditlog */
2399 NULL, /* opassuan_transact */
2400 NULL, /* conf_load */
2401 NULL, /* conf_save */
2405 NULL, /* cancel_op */