1 /* rungpg.c - Gpg Engine.
2 Copyright (C) 2000 Werner Koch (dd9jn)
3 Copyright (C) 2001, 2002, 2003 g10 Code GmbH
5 This file is part of GPGME.
7 GPGME is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GPGME is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GPGME; if not, write to the Free Software Foundation,
19 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
31 #include <sys/types.h>
40 #include "context.h" /*temp hack until we have GpmeData methods to do I/O */
45 #include "status-table.h"
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 char arg[1]; /* Used if data above is not used. */
65 int inbound; /* true if this is used for reading from gpg */
67 int fd; /* the fd to use */
68 int peer_fd; /* the outher side of the pipe */
75 struct arg_and_data_s *arglist;
76 struct arg_and_data_s **argtail;
85 engine_status_handler_t fnc;
90 /* This is a kludge - see the comment at colon_line_handler. */
98 engine_colon_line_handler_t fnc; /* this indicate use of this structrue */
104 struct fd_data_map_s *fd_data_map;
106 /* stuff needed for interactive (command) mode */
112 int idx; /* Index in fd_data_map */
113 gpgme_status_code_t code; /* last code */
114 char *keyword; /* what has been requested (malloced) */
115 engine_command_handler_t fnc;
117 /* The kludges never end. This is used to couple command handlers
118 with output data in edit key mode. */
119 gpgme_data_t linked_data;
123 struct gpgme_io_cbs io_cbs;
126 typedef struct engine_gpg *engine_gpg_t;
130 gpg_io_event (void *engine, gpgme_event_io_t type, void *type_data)
132 engine_gpg_t gpg = engine;
134 if (gpg->io_cbs.event)
135 (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, type, type_data);
140 close_notify_handler (int fd, void *opaque)
142 engine_gpg_t gpg = opaque;
145 if (gpg->status.fd[0] == fd)
148 (*gpg->io_cbs.remove) (gpg->status.tag);
149 gpg->status.fd[0] = -1;
151 else if (gpg->status.fd[1] == fd)
152 gpg->status.fd[1] = -1;
153 else if (gpg->colon.fd[0] == fd)
156 (*gpg->io_cbs.remove) (gpg->colon.tag);
157 gpg->colon.fd[0] = -1;
159 else if (gpg->colon.fd[1] == fd)
160 gpg->colon.fd[1] = -1;
161 else if (gpg->fd_data_map)
165 for (i = 0; gpg->fd_data_map[i].data; i++)
167 if (gpg->fd_data_map[i].fd == fd)
169 if (gpg->fd_data_map[i].tag)
170 (*gpg->io_cbs.remove) (gpg->fd_data_map[i].tag);
171 gpg->fd_data_map[i].fd = -1;
174 if (gpg->fd_data_map[i].peer_fd == fd)
176 gpg->fd_data_map[i].peer_fd = -1;
184 add_arg (engine_gpg_t gpg, const char *arg)
186 struct arg_and_data_s *a;
191 a = malloc (sizeof *a + strlen (arg));
193 return gpg_error_from_errno (errno);
197 strcpy (a->arg, arg);
199 gpg->argtail = &a->next;
204 add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound)
206 struct arg_and_data_s *a;
211 a = malloc (sizeof *a - 1);
213 return gpg_error_from_errno (errno);
216 a->inbound = inbound;
228 gpg->argtail = &a->next;
234 gpg_get_version (void)
236 static const char *gpg_version;
237 DEFINE_STATIC_LOCK (gpg_version_lock);
239 LOCK (gpg_version_lock);
241 gpg_version = _gpgme_get_program_version (_gpgme_get_gpg_path ());
242 UNLOCK (gpg_version_lock);
248 gpg_get_req_version (void)
250 return NEED_GPG_VERSION;
255 free_argv (char **argv)
259 for (i = 0; argv[i]; i++)
266 free_fd_data_map (struct fd_data_map_s *fd_data_map)
273 for (i = 0; fd_data_map[i].data; i++)
275 if (fd_data_map[i].fd != -1)
276 _gpgme_io_close (fd_data_map[i].fd);
277 if (fd_data_map[i].peer_fd != -1)
278 _gpgme_io_close (fd_data_map[i].peer_fd);
279 /* Don't release data because this is only a reference. */
286 gpg_release (void *engine)
288 engine_gpg_t gpg = engine;
295 struct arg_and_data_s *next = gpg->arglist->next;
302 if (gpg->status.buffer)
303 free (gpg->status.buffer);
304 if (gpg->colon.buffer)
305 free (gpg->colon.buffer);
307 free_argv (gpg->argv);
308 if (gpg->cmd.keyword)
309 free (gpg->cmd.keyword);
311 if (gpg->status.fd[0] != -1)
312 _gpgme_io_close (gpg->status.fd[0]);
313 if (gpg->status.fd[1] != -1)
314 _gpgme_io_close (gpg->status.fd[1]);
315 if (gpg->colon.fd[0] != -1)
316 _gpgme_io_close (gpg->colon.fd[0]);
317 if (gpg->colon.fd[1] != -1)
318 _gpgme_io_close (gpg->colon.fd[1]);
319 if (gpg->fd_data_map)
320 free_fd_data_map (gpg->fd_data_map);
321 if (gpg->cmd.fd != -1)
322 _gpgme_io_close (gpg->cmd.fd);
328 gpg_new (void **engine, const char *lc_ctype, const char *lc_messages)
331 gpgme_error_t rc = 0;
333 gpg = calloc (1, sizeof *gpg);
335 return gpg_error_from_errno (errno);
337 gpg->argtail = &gpg->arglist;
338 gpg->status.fd[0] = -1;
339 gpg->status.fd[1] = -1;
340 gpg->colon.fd[0] = -1;
341 gpg->colon.fd[1] = -1;
344 gpg->cmd.linked_data = NULL;
345 gpg->cmd.linked_idx = -1;
347 /* Allocate the read buffer for the status pipe. */
348 gpg->status.bufsize = 1024;
349 gpg->status.readpos = 0;
350 gpg->status.buffer = malloc (gpg->status.bufsize);
351 if (!gpg->status.buffer)
353 rc = gpg_error_from_errno (errno);
356 /* In any case we need a status pipe - create it right here and
357 don't handle it with our generic gpgme_data_t mechanism. */
358 if (_gpgme_io_pipe (gpg->status.fd, 1) == -1)
360 rc = gpg_error_from_errno (errno);
363 if (_gpgme_io_set_close_notify (gpg->status.fd[0],
364 close_notify_handler, gpg)
365 || _gpgme_io_set_close_notify (gpg->status.fd[1],
366 close_notify_handler, gpg))
368 rc = gpg_error (GPG_ERR_GENERAL);
372 rc = add_arg (gpg, "--status-fd");
378 sprintf (buf, "%d", gpg->status.fd[1]);
379 rc = add_arg (gpg, buf);
384 rc = add_arg (gpg, "--no-tty");
386 rc = add_arg (gpg, "--charset");
388 rc = add_arg (gpg, "utf8");
390 rc = add_arg (gpg, "--enable-progress-filter");
401 /* Note, that the status_handler is allowed to modifiy the args
404 gpg_set_status_handler (void *engine, engine_status_handler_t fnc,
407 engine_gpg_t gpg = engine;
409 gpg->status.fnc = fnc;
410 gpg->status.fnc_value = fnc_value;
413 /* Kludge to process --with-colon output. */
415 gpg_set_colon_line_handler (void *engine, engine_colon_line_handler_t fnc,
418 engine_gpg_t gpg = engine;
420 gpg->colon.bufsize = 1024;
421 gpg->colon.readpos = 0;
422 gpg->colon.buffer = malloc (gpg->colon.bufsize);
423 if (!gpg->colon.buffer)
424 return gpg_error_from_errno (errno);
426 if (_gpgme_io_pipe (gpg->colon.fd, 1) == -1)
428 int saved_errno = errno;
429 free (gpg->colon.buffer);
430 gpg->colon.buffer = NULL;
431 return gpg_error_from_errno (saved_errno);
433 if (_gpgme_io_set_close_notify (gpg->colon.fd[0], close_notify_handler, gpg)
434 || _gpgme_io_set_close_notify (gpg->colon.fd[1],
435 close_notify_handler, gpg))
436 return gpg_error (GPG_ERR_GENERAL);
438 gpg->colon.fnc = fnc;
439 gpg->colon.fnc_value = fnc_value;
445 command_handler (void *opaque, int fd)
448 engine_gpg_t gpg = (engine_gpg_t) opaque;
450 assert (gpg->cmd.used);
451 assert (gpg->cmd.code);
452 assert (gpg->cmd.fnc);
454 err = gpg->cmd.fnc (gpg->cmd.fnc_value, gpg->cmd.code, gpg->cmd.keyword, fd);
459 /* And sleep again until read_status will wake us up again. */
460 /* XXX We must check if there are any more fds active after removing
462 (*gpg->io_cbs.remove) (gpg->fd_data_map[gpg->cmd.idx].tag);
463 gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
464 gpg->fd_data_map[gpg->cmd.idx].fd = -1;
471 /* The Fnc will be called to get a value for one of the commands with
472 a key KEY. If the Code pssed to FNC is 0, the function may release
473 resources associated with the returned value from another call. To
474 match such a second call to a first call, the returned value from
475 the first call is passed as keyword. */
477 gpg_set_command_handler (void *engine, engine_command_handler_t fnc,
478 void *fnc_value, gpgme_data_t linked_data)
480 engine_gpg_t gpg = engine;
483 rc = add_arg (gpg, "--command-fd");
487 /* This is a hack. We don't have a real data object. The only
488 thing that matters is that we use something unique, so we use the
489 address of the cmd structure in the gpg object. */
490 rc = add_data (gpg, (void *) &gpg->cmd, -2, 0);
495 gpg->cmd.cb_data = (void *) &gpg->cmd;
496 gpg->cmd.fnc_value = fnc_value;
497 gpg->cmd.linked_data = linked_data;
504 build_argv (engine_gpg_t gpg)
507 struct arg_and_data_s *a;
508 struct fd_data_map_s *fd_data_map;
509 size_t datac=0, argc=0;
511 int need_special = 0;
515 /* We don't want to use the agent with a malformed environment
516 variable. This is only a very basic test but sufficient to make
517 our life in the regression tests easier. */
518 err = _gpgme_getenv ("GPG_AGENT_INFO", &p);
521 use_agent = (p && strchr (p, ':'));
527 free_argv (gpg->argv);
530 if (gpg->fd_data_map)
532 free_fd_data_map (gpg->fd_data_map);
533 gpg->fd_data_map = NULL;
536 argc++; /* For argv[0]. */
537 for (a = gpg->arglist; a; a = a->next)
542 /*fprintf (stderr, "build_argv: data\n" );*/
544 if (a->dup_to == -1 && !a->print_fd)
549 /* fprintf (stderr, "build_argv: arg=`%s'\n", a->arg );*/
557 argc++; /* --batch */
558 argc += 2; /* --comment */
560 argv = calloc (argc + 1, sizeof *argv);
562 return gpg_error_from_errno (errno);
563 fd_data_map = calloc (datac + 1, sizeof *fd_data_map);
566 int saved_errno = errno;
568 return gpg_error_from_errno (saved_errno);
572 argv[argc] = strdup ("gpg"); /* argv[0] */
575 int saved_errno = errno;
578 return gpg_error_from_errno (saved_errno);
583 argv[argc] = strdup ("--enable-special-filenames");
586 int saved_errno = errno;
589 return gpg_error_from_errno (saved_errno);
595 argv[argc] = strdup ("--use-agent");
598 int saved_errno = errno;
601 return gpg_error_from_errno (saved_errno);
607 argv[argc] = strdup ("--batch");
610 int saved_errno = errno;
613 return gpg_error_from_errno (saved_errno);
617 argv[argc] = strdup ("--comment");
620 int saved_errno = errno;
623 return gpg_error_from_errno (saved_errno);
626 argv[argc] = strdup ("");
629 int saved_errno = errno;
632 return gpg_error_from_errno (saved_errno);
635 for (a = gpg->arglist; a; a = a->next)
639 /* Create a pipe to pass it down to gpg. */
640 fd_data_map[datac].inbound = a->inbound;
646 if (_gpgme_io_pipe (fds, fd_data_map[datac].inbound ? 1 : 0)
649 int saved_errno = errno;
652 return gpg_error (saved_errno);
654 if (_gpgme_io_set_close_notify (fds[0],
655 close_notify_handler, gpg)
656 || _gpgme_io_set_close_notify (fds[1],
657 close_notify_handler,
660 return gpg_error (GPG_ERR_GENERAL);
662 /* If the data_type is FD, we have to do a dup2 here. */
663 if (fd_data_map[datac].inbound)
665 fd_data_map[datac].fd = fds[0];
666 fd_data_map[datac].peer_fd = fds[1];
670 fd_data_map[datac].fd = fds[1];
671 fd_data_map[datac].peer_fd = fds[0];
675 /* Hack to get hands on the fd later. */
678 if (gpg->cmd.cb_data == a->data)
680 assert (gpg->cmd.idx == -1);
681 gpg->cmd.idx = datac;
683 else if (gpg->cmd.linked_data == a->data)
685 assert (gpg->cmd.linked_idx == -1);
686 gpg->cmd.linked_idx = datac;
690 fd_data_map[datac].data = a->data;
691 fd_data_map[datac].dup_to = a->dup_to;
694 argv[argc] = malloc (25);
697 int saved_errno = errno;
700 return gpg_error_from_errno (saved_errno);
703 a->print_fd ? "%d" : "-&%d",
704 fd_data_map[datac].peer_fd);
711 argv[argc] = strdup (a->arg);
714 int saved_errno = errno;
717 return gpg_error_from_errno (saved_errno);
724 gpg->fd_data_map = fd_data_map;
730 add_io_cb (engine_gpg_t gpg, int fd, int dir, gpgme_io_cb_t handler, void *data,
735 err = (*gpg->io_cbs.add) (gpg->io_cbs.add_priv, fd, dir, handler, data, tag);
739 /* FIXME Kludge around poll() problem. */
740 err = _gpgme_io_set_nonblocking (fd);
746 status_cmp (const void *ap, const void *bp)
748 const struct status_table_s *a = ap;
749 const struct status_table_s *b = bp;
751 return strcmp (a->name, b->name);
755 /* Handle the status output of GnuPG. This function does read entire
756 lines and passes them as C strings to the callback function (we can
757 use C Strings because the status output is always UTF-8 encoded).
758 Of course we have to buffer the lines to cope with long lines
759 e.g. with a large user ID. Note: We can optimize this to only cope
760 with status line code we know about and skip all other stuff
761 without buffering (i.e. without extending the buffer). */
763 read_status (engine_gpg_t gpg)
767 size_t bufsize = gpg->status.bufsize;
768 char *buffer = gpg->status.buffer;
769 size_t readpos = gpg->status.readpos;
772 if (bufsize - readpos < 256)
774 /* Need more room for the read. */
776 buffer = realloc (buffer, bufsize);
778 return gpg_error_from_errno (errno);
781 nread = _gpgme_io_read (gpg->status.fd[0],
782 buffer + readpos, bufsize-readpos);
784 return gpg_error_from_errno (errno);
792 err = gpg->status.fnc (gpg->status.fnc_value, GPGME_STATUS_EOF, "");
801 for (p = buffer + readpos; nread; nread--, p++)
805 /* (we require that the last line is terminated by a LF) */
807 if (!strncmp (buffer, "[GNUPG:] ", 9)
808 && buffer[9] >= 'A' && buffer[9] <= 'Z')
810 struct status_table_s t, *r;
813 rest = strchr (buffer + 9, ' ');
815 rest = p; /* Set to an empty string. */
820 /* (the status table has one extra element) */
821 r = bsearch (&t, status_table, DIM(status_table) - 1,
822 sizeof t, status_cmp);
826 && (r->code == GPGME_STATUS_GET_BOOL
827 || r->code == GPGME_STATUS_GET_LINE
828 || r->code == GPGME_STATUS_GET_HIDDEN))
830 gpg->cmd.code = r->code;
831 if (gpg->cmd.keyword)
832 free (gpg->cmd.keyword);
833 gpg->cmd.keyword = strdup (rest);
834 if (!gpg->cmd.keyword)
835 return gpg_error_from_errno (errno);
836 /* This should be the last thing we have
837 received and the next thing will be that
838 the command handler does its action. */
840 DEBUG0 ("ERROR, unexpected data in read_status");
842 /* Before we can actually add the command
843 fd, we might have to flush the linked
845 if (gpg->cmd.linked_idx != -1
846 && gpg->fd_data_map[gpg->cmd.linked_idx].fd != -1)
848 struct io_select_fd_s fds;
849 fds.fd = gpg->fd_data_map[gpg->cmd.linked_idx].fd;
857 _gpgme_io_select (&fds, 1, 1);
859 _gpgme_data_inbound_handler
860 (gpg->cmd.linked_data, fds.fd);
862 while (fds.signaled);
865 add_io_cb (gpg, gpg->cmd.fd, 0,
866 command_handler, gpg,
867 &gpg->fd_data_map[gpg->cmd.idx].tag);
868 gpg->fd_data_map[gpg->cmd.idx].fd = gpg->cmd.fd;
871 else if (gpg->status.fnc)
874 err = gpg->status.fnc (gpg->status.fnc_value,
880 if (r->code == GPGME_STATUS_END_STREAM)
884 /* XXX We must check if there are any
885 more fds active after removing this
887 (*gpg->io_cbs.remove)
888 (gpg->fd_data_map[gpg->cmd.idx].tag);
889 gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
890 gpg->fd_data_map[gpg->cmd.idx].fd = -1;
895 /* To reuse the buffer for the next line we have to
896 shift the remaining data to the buffer start and
897 restart the loop Hmmm: We can optimize this function
898 by looking forward in the buffer to see whether a
899 second complete line is available and in this case
900 avoid the memmove for this line. */
903 memmove (buffer, p, nread);
905 break; /* the for loop */
912 /* Update the gpg object. */
913 gpg->status.bufsize = bufsize;
914 gpg->status.buffer = buffer;
915 gpg->status.readpos = readpos;
921 status_handler (void *opaque, int fd)
923 engine_gpg_t gpg = opaque;
926 assert (fd == gpg->status.fd[0]);
927 err = read_status (gpg);
931 _gpgme_io_close (fd);
937 read_colon_line (engine_gpg_t gpg)
941 size_t bufsize = gpg->colon.bufsize;
942 char *buffer = gpg->colon.buffer;
943 size_t readpos = gpg->colon.readpos;
946 if (bufsize - readpos < 256)
948 /* Need more room for the read. */
950 buffer = realloc (buffer, bufsize);
952 return gpg_error_from_errno (errno);
955 nread = _gpgme_io_read (gpg->colon.fd[0], buffer+readpos, bufsize-readpos);
957 return gpg_error_from_errno (errno);
962 assert (gpg->colon.fnc);
963 gpg->colon.fnc (gpg->colon.fnc_value, NULL);
969 for (p = buffer + readpos; nread; nread--, p++)
973 /* (we require that the last line is terminated by a LF)
974 and we skip empty lines. Note: we use UTF8 encoding
975 and escaping of special characters We require at
976 least one colon to cope with some other printed
979 if (*buffer && strchr (buffer, ':'))
981 assert (gpg->colon.fnc);
982 gpg->colon.fnc (gpg->colon.fnc_value, buffer);
985 /* To reuse the buffer for the next line we have to
986 shift the remaining data to the buffer start and
987 restart the loop Hmmm: We can optimize this function
988 by looking forward in the buffer to see whether a
989 second complete line is available and in this case
990 avoid the memmove for this line. */
993 memmove (buffer, p, nread);
995 break; /* The for loop. */
1002 /* Update the gpg object. */
1003 gpg->colon.bufsize = bufsize;
1004 gpg->colon.buffer = buffer;
1005 gpg->colon.readpos = readpos;
1010 /* This colonline handler thing is not the clean way to do it. It
1011 might be better to enhance the gpgme_data_t object to act as a wrapper
1012 for a callback. Same goes for the status thing. For now we use
1013 this thing here because it is easier to implement. */
1014 static gpgme_error_t
1015 colon_line_handler (void *opaque, int fd)
1017 engine_gpg_t gpg = opaque;
1018 gpgme_error_t rc = 0;
1020 assert (fd == gpg->colon.fd[0]);
1021 rc = read_colon_line (gpg);
1025 _gpgme_io_close (fd);
1030 static gpgme_error_t
1031 start (engine_gpg_t gpg)
1037 struct spawn_fd_item_s *fd_child_list, *fd_parent_list;
1040 return gpg_error (GPG_ERR_INV_VALUE);
1042 if (! _gpgme_get_gpg_path ())
1043 return gpg_error (GPG_ERR_INV_ENGINE);
1045 rc = build_argv (gpg);
1049 n = 3; /* status_fd, colon_fd and end of list */
1050 for (i = 0; gpg->fd_data_map[i].data; i++)
1052 fd_child_list = calloc (n + n, sizeof *fd_child_list);
1054 return gpg_error_from_errno (errno);
1055 fd_parent_list = fd_child_list + n;
1057 /* build the fd list for the child */
1061 fd_child_list[n].fd = gpg->colon.fd[1];
1062 fd_child_list[n].dup_to = 1; /* dup to stdout */
1065 for (i = 0; gpg->fd_data_map[i].data; i++)
1067 if (gpg->fd_data_map[i].dup_to != -1)
1069 fd_child_list[n].fd = gpg->fd_data_map[i].peer_fd;
1070 fd_child_list[n].dup_to = gpg->fd_data_map[i].dup_to;
1074 fd_child_list[n].fd = -1;
1075 fd_child_list[n].dup_to = -1;
1077 /* Build the fd list for the parent. */
1079 if (gpg->status.fd[1] != -1)
1081 fd_parent_list[n].fd = gpg->status.fd[1];
1082 fd_parent_list[n].dup_to = -1;
1085 if (gpg->colon.fd[1] != -1)
1087 fd_parent_list[n].fd = gpg->colon.fd[1];
1088 fd_parent_list[n].dup_to = -1;
1091 for (i = 0; gpg->fd_data_map[i].data; i++)
1093 fd_parent_list[n].fd = gpg->fd_data_map[i].peer_fd;
1094 fd_parent_list[n].dup_to = -1;
1097 fd_parent_list[n].fd = -1;
1098 fd_parent_list[n].dup_to = -1;
1100 status = _gpgme_io_spawn (_gpgme_get_gpg_path (),
1101 gpg->argv, fd_child_list, fd_parent_list);
1102 saved_errno = errno;
1103 free (fd_child_list);
1105 return gpg_error_from_errno (saved_errno);
1107 /*_gpgme_register_term_handler ( closure, closure_value, pid );*/
1109 rc = add_io_cb (gpg, gpg->status.fd[0], 1, status_handler, gpg,
1112 /* FIXME: kill the child */
1117 assert (gpg->colon.fd[0] != -1);
1118 rc = add_io_cb (gpg, gpg->colon.fd[0], 1, colon_line_handler, gpg,
1121 /* FIXME: kill the child */
1125 for (i = 0; gpg->fd_data_map[i].data; i++)
1127 if (gpg->cmd.used && i == gpg->cmd.idx)
1129 /* Park the cmd fd. */
1130 gpg->cmd.fd = gpg->fd_data_map[i].fd;
1131 gpg->fd_data_map[i].fd = -1;
1135 rc = add_io_cb (gpg, gpg->fd_data_map[i].fd,
1136 gpg->fd_data_map[i].inbound,
1137 gpg->fd_data_map[i].inbound
1138 ? _gpgme_data_inbound_handler
1139 : _gpgme_data_outbound_handler,
1140 gpg->fd_data_map[i].data, &gpg->fd_data_map[i].tag);
1143 /* FIXME: kill the child */
1148 (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, GPGME_EVENT_START, NULL);
1150 /* fixme: check what data we can release here */
1155 static gpgme_error_t
1156 gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
1158 engine_gpg_t gpg = engine;
1161 err = add_arg (gpg, "--decrypt");
1163 /* Tell the gpg object about the data. */
1165 err = add_arg (gpg, "--output");
1167 err = add_arg (gpg, "-");
1169 err = add_data (gpg, plain, 1, 1);
1171 err = add_data (gpg, ciph, 0, 0);
1178 static gpgme_error_t
1179 gpg_delete (void *engine, gpgme_key_t key, int allow_secret)
1181 engine_gpg_t gpg = engine;
1184 err = add_arg (gpg, allow_secret ? "--delete-secret-and-public-key"
1187 err = add_arg (gpg, "--");
1190 if (!key->subkeys || !key->subkeys->fpr)
1191 return gpg_error (GPG_ERR_INV_VALUE);
1193 err = add_arg (gpg, key->subkeys->fpr);
1202 static gpgme_error_t
1203 append_args_from_signers (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1205 gpgme_error_t err = 0;
1209 for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++)
1211 const char *s = key->subkeys ? key->subkeys->keyid : NULL;
1215 err = add_arg (gpg, "-u");
1217 err = add_arg (gpg, s);
1219 gpgme_key_unref (key);
1226 static gpgme_error_t
1227 gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out,
1228 gpgme_ctx_t ctx /* FIXME */)
1230 engine_gpg_t gpg = engine;
1233 err = add_arg (gpg, "--with-colons");
1235 err = append_args_from_signers (gpg, ctx);
1237 err = add_arg (gpg, type == 0 ? "--edit-key" : "--card-edit");
1239 err = add_data (gpg, out, 1, 1);
1241 err = add_arg (gpg, "--");
1244 const char *s = key->subkeys ? key->subkeys->fpr : NULL;
1246 err = gpg_error (GPG_ERR_INV_VALUE);
1248 err = add_arg (gpg, s);
1257 static gpgme_error_t
1258 append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[])
1260 gpgme_error_t err = 0;
1265 if (!recp[i]->subkeys || !recp[i]->subkeys->fpr)
1266 err = gpg_error (GPG_ERR_INV_VALUE);
1268 err = add_arg (gpg, "-r");
1270 err = add_arg (gpg, recp[i]->subkeys->fpr);
1279 static gpgme_error_t
1280 gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
1281 gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
1283 engine_gpg_t gpg = engine;
1285 int symmetric = !recp;
1287 err = add_arg (gpg, symmetric ? "--symmetric" : "--encrypt");
1289 if (!err && use_armor)
1290 err = add_arg (gpg, "--armor");
1294 /* If we know that all recipients are valid (full or ultimate trust)
1295 we can suppress further checks. */
1296 if (!err && !symmetric && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1297 err = add_arg (gpg, "--always-trust");
1300 err = append_args_from_recipients (gpg, recp);
1303 /* Tell the gpg object about the data. */
1305 err = add_arg (gpg, "--output");
1307 err = add_arg (gpg, "-");
1309 err = add_data (gpg, ciph, 1, 1);
1311 err = add_arg (gpg, "--");
1313 err = add_data (gpg, plain, 0, 0);
1322 static gpgme_error_t
1323 gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
1324 gpgme_encrypt_flags_t flags, gpgme_data_t plain,
1325 gpgme_data_t ciph, int use_armor,
1326 gpgme_ctx_t ctx /* FIXME */)
1328 engine_gpg_t gpg = engine;
1331 err = add_arg (gpg, "--encrypt");
1333 err = add_arg (gpg, "--sign");
1334 if (!err && use_armor)
1335 err = add_arg (gpg, "--armor");
1337 /* If we know that all recipients are valid (full or ultimate trust)
1338 we can suppress further checks. */
1339 if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1340 err = add_arg (gpg, "--always-trust");
1343 err = append_args_from_recipients (gpg, recp);
1346 err = append_args_from_signers (gpg, ctx);
1348 /* Tell the gpg object about the data. */
1350 err = add_arg (gpg, "--output");
1352 err = add_arg (gpg, "-");
1354 err = add_data (gpg, ciph, 1, 1);
1356 err = add_arg (gpg, "--");
1358 err = add_data (gpg, plain, 0, 0);
1367 static gpgme_error_t
1368 gpg_export (void *engine, const char *pattern, unsigned int reserved,
1369 gpgme_data_t keydata, int use_armor)
1371 engine_gpg_t gpg = engine;
1375 return gpg_error (GPG_ERR_INV_VALUE);
1377 err = add_arg (gpg, "--export");
1378 if (!err && use_armor)
1379 err = add_arg (gpg, "--armor");
1381 err = add_data (gpg, keydata, 1, 1);
1383 err = add_arg (gpg, "--");
1385 if (!err && pattern && *pattern)
1386 err = add_arg (gpg, pattern);
1395 static gpgme_error_t
1396 gpg_export_ext (void *engine, const char *pattern[], unsigned int reserved,
1397 gpgme_data_t keydata, int use_armor)
1399 engine_gpg_t gpg = engine;
1403 return gpg_error (GPG_ERR_INV_VALUE);
1405 err = add_arg (gpg, "--export");
1406 if (!err && use_armor)
1407 err = add_arg (gpg, "--armor");
1409 err = add_data (gpg, keydata, 1, 1);
1411 err = add_arg (gpg, "--");
1415 while (!err && *pattern && **pattern)
1416 err = add_arg (gpg, *(pattern++));
1426 static gpgme_error_t
1427 gpg_genkey (void *engine, gpgme_data_t help_data, int use_armor,
1428 gpgme_data_t pubkey, gpgme_data_t seckey)
1430 engine_gpg_t gpg = engine;
1434 return gpg_error (GPG_ERR_INV_VALUE);
1436 /* We need a special mechanism to get the fd of a pipe here, so that
1437 we can use this for the %pubring and %secring parameters. We
1438 don't have this yet, so we implement only the adding to the
1439 standard keyrings. */
1440 if (pubkey || seckey)
1441 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1443 err = add_arg (gpg, "--gen-key");
1444 if (!err && use_armor)
1445 err = add_arg (gpg, "--armor");
1447 err = add_data (gpg, help_data, 0, 0);
1456 static gpgme_error_t
1457 gpg_import (void *engine, gpgme_data_t keydata)
1459 engine_gpg_t gpg = engine;
1462 err = add_arg (gpg, "--import");
1464 err = add_data (gpg, keydata, 0, 0);
1473 static gpgme_error_t
1474 gpg_keylist (void *engine, const char *pattern, int secret_only,
1475 gpgme_keylist_mode_t mode)
1477 engine_gpg_t gpg = engine;
1480 err = add_arg (gpg, "--with-colons");
1482 err = add_arg (gpg, "--fixed-list-mode");
1484 err = add_arg (gpg, "--with-fingerprint");
1486 err = add_arg (gpg, "--with-fingerprint");
1488 err = add_arg (gpg, secret_only ? "--list-secret-keys"
1489 : ((mode & GPGME_KEYLIST_MODE_SIGS)
1490 ? "--check-sigs" : "--list-keys"));
1492 /* Tell the gpg object about the data. */
1494 err = add_arg (gpg, "--");
1495 if (!err && pattern && *pattern)
1496 err = add_arg (gpg, pattern);
1505 static gpgme_error_t
1506 gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
1507 int reserved, gpgme_keylist_mode_t mode)
1509 engine_gpg_t gpg = engine;
1513 return gpg_error (GPG_ERR_INV_VALUE);
1515 err = add_arg (gpg, "--with-colons");
1517 err = add_arg (gpg, "--fixed-list-mode");
1519 err = add_arg (gpg, "--with-fingerprint");
1521 err = add_arg (gpg, "--with-fingerprint");
1523 err = add_arg (gpg, secret_only ? "--list-secret-keys"
1524 : ((mode & GPGME_KEYLIST_MODE_SIGS)
1525 ? "--check-sigs" : "--list-keys"));
1527 err = add_arg (gpg, "--");
1531 while (!err && *pattern && **pattern)
1532 err = add_arg (gpg, *(pattern++));
1542 static gpgme_error_t
1543 gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
1544 gpgme_sig_mode_t mode, int use_armor, int use_textmode,
1545 int include_certs, gpgme_ctx_t ctx /* FIXME */)
1547 engine_gpg_t gpg = engine;
1550 if (mode == GPGME_SIG_MODE_CLEAR)
1551 err = add_arg (gpg, "--clearsign");
1554 err = add_arg (gpg, "--sign");
1555 if (!err && mode == GPGME_SIG_MODE_DETACH)
1556 err = add_arg (gpg, "--detach");
1557 if (!err && use_armor)
1558 err = add_arg (gpg, "--armor");
1559 if (!err && use_textmode)
1560 err = add_arg (gpg, "--textmode");
1564 err = append_args_from_signers (gpg, ctx);
1566 /* Tell the gpg object about the data. */
1568 err = add_data (gpg, in, 0, 0);
1570 err = add_data (gpg, out, 1, 1);
1578 static gpgme_error_t
1579 gpg_trustlist (void *engine, const char *pattern)
1581 engine_gpg_t gpg = engine;
1584 err = add_arg (gpg, "--with-colons");
1586 err = add_arg (gpg, "--list-trust-path");
1588 /* Tell the gpg object about the data. */
1590 err = add_arg (gpg, "--");
1592 err = add_arg (gpg, pattern);
1601 static gpgme_error_t
1602 gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
1603 gpgme_data_t plaintext)
1605 engine_gpg_t gpg = engine;
1606 gpgme_error_t err = 0;
1610 /* Normal or cleartext signature. */
1612 err = add_arg (gpg, "--output");
1614 err = add_arg (gpg, "-");
1616 err = add_arg (gpg, "--");
1618 err = add_data (gpg, sig, 0, 0);
1620 err = add_data (gpg, plaintext, 1, 1);
1624 err = add_arg (gpg, "--verify");
1626 err = add_arg (gpg, "--");
1628 err = add_data (gpg, sig, -1, 0);
1632 err = add_arg (gpg, "-");
1634 err = add_data (gpg, signed_text, 0, 0);
1646 gpg_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
1648 engine_gpg_t gpg = engine;
1650 gpg->io_cbs = *io_cbs;
1654 struct engine_ops _gpgme_engine_ops_gpg =
1656 /* Static functions. */
1657 _gpgme_get_gpg_path,
1659 gpg_get_req_version,
1662 /* Member functions. */
1664 gpg_set_status_handler,
1665 gpg_set_command_handler,
1666 gpg_set_colon_line_handler,