1 /* rungpg.c - Gpg Engine.
2 Copyright (C) 2000 Werner Koch (dd9jn)
3 Copyright (C) 2001, 2002, 2003, 2004, 2005 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 Lesser General Public License as
9 published by the Free Software Foundation; either version 2.1 of
10 the License, or (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 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
35 #include "context.h" /*temp hack until we have GpmeData methods to do I/O */
40 #include "status-table.h"
41 #include "engine-backend.h"
44 /* This type is used to build a list of gpg arguments and data
48 struct arg_and_data_s *next;
49 gpgme_data_t data; /* If this is not NULL, use arg below. */
50 int inbound; /* True if this is used for reading from gpg. */
52 int print_fd; /* Print the fd number and not the special form of it. */
53 char arg[1]; /* Used if data above is not used. */
60 int inbound; /* true if this is used for reading from gpg */
62 int fd; /* the fd to use */
63 int peer_fd; /* the outher side of the pipe */
72 struct arg_and_data_s *arglist;
73 struct arg_and_data_s **argtail;
82 engine_status_handler_t fnc;
87 /* This is a kludge - see the comment at colon_line_handler. */
95 engine_colon_line_handler_t fnc; /* this indicate use of this structrue */
101 struct fd_data_map_s *fd_data_map;
103 /* stuff needed for interactive (command) mode */
109 int idx; /* Index in fd_data_map */
110 gpgme_status_code_t code; /* last code */
111 char *keyword; /* what has been requested (malloced) */
112 engine_command_handler_t fnc;
114 /* The kludges never end. This is used to couple command handlers
115 with output data in edit key mode. */
116 gpgme_data_t linked_data;
120 struct gpgme_io_cbs io_cbs;
123 typedef struct engine_gpg *engine_gpg_t;
127 gpg_io_event (void *engine, gpgme_event_io_t type, void *type_data)
129 engine_gpg_t gpg = engine;
131 if (gpg->io_cbs.event)
132 (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, type, type_data);
137 close_notify_handler (int fd, void *opaque)
139 engine_gpg_t gpg = opaque;
142 if (gpg->status.fd[0] == fd)
145 (*gpg->io_cbs.remove) (gpg->status.tag);
146 gpg->status.fd[0] = -1;
148 else if (gpg->status.fd[1] == fd)
149 gpg->status.fd[1] = -1;
150 else if (gpg->colon.fd[0] == fd)
153 (*gpg->io_cbs.remove) (gpg->colon.tag);
154 gpg->colon.fd[0] = -1;
156 else if (gpg->colon.fd[1] == fd)
157 gpg->colon.fd[1] = -1;
158 else if (gpg->fd_data_map)
162 for (i = 0; gpg->fd_data_map[i].data; i++)
164 if (gpg->fd_data_map[i].fd == fd)
166 if (gpg->fd_data_map[i].tag)
167 (*gpg->io_cbs.remove) (gpg->fd_data_map[i].tag);
168 gpg->fd_data_map[i].fd = -1;
171 if (gpg->fd_data_map[i].peer_fd == fd)
173 gpg->fd_data_map[i].peer_fd = -1;
181 add_arg (engine_gpg_t gpg, const char *arg)
183 struct arg_and_data_s *a;
188 a = malloc (sizeof *a + strlen (arg));
190 return gpg_error_from_errno (errno);
194 strcpy (a->arg, arg);
196 gpg->argtail = &a->next;
201 add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound)
203 struct arg_and_data_s *a;
208 a = malloc (sizeof *a - 1);
210 return gpg_error_from_errno (errno);
213 a->inbound = inbound;
225 gpg->argtail = &a->next;
231 gpg_get_version (const char *file_name)
233 return _gpgme_get_program_version (file_name ? file_name
234 : _gpgme_get_gpg_path ());
239 gpg_get_req_version (void)
241 return NEED_GPG_VERSION;
246 free_argv (char **argv)
250 for (i = 0; argv[i]; i++)
257 free_fd_data_map (struct fd_data_map_s *fd_data_map)
264 for (i = 0; fd_data_map[i].data; i++)
266 if (fd_data_map[i].fd != -1)
267 _gpgme_io_close (fd_data_map[i].fd);
268 if (fd_data_map[i].peer_fd != -1)
269 _gpgme_io_close (fd_data_map[i].peer_fd);
270 /* Don't release data because this is only a reference. */
277 gpg_cancel (void *engine)
279 engine_gpg_t gpg = engine;
282 return gpg_error (GPG_ERR_INV_VALUE);
284 if (gpg->status.fd[0] != -1)
285 _gpgme_io_close (gpg->status.fd[0]);
286 if (gpg->status.fd[1] != -1)
287 _gpgme_io_close (gpg->status.fd[1]);
288 if (gpg->colon.fd[0] != -1)
289 _gpgme_io_close (gpg->colon.fd[0]);
290 if (gpg->colon.fd[1] != -1)
291 _gpgme_io_close (gpg->colon.fd[1]);
292 if (gpg->fd_data_map)
294 free_fd_data_map (gpg->fd_data_map);
295 gpg->fd_data_map = NULL;
297 if (gpg->cmd.fd != -1)
298 _gpgme_io_close (gpg->cmd.fd);
304 gpg_release (void *engine)
306 engine_gpg_t gpg = engine;
314 free (gpg->file_name);
318 struct arg_and_data_s *next = gpg->arglist->next;
325 if (gpg->status.buffer)
326 free (gpg->status.buffer);
327 if (gpg->colon.buffer)
328 free (gpg->colon.buffer);
330 free_argv (gpg->argv);
331 if (gpg->cmd.keyword)
332 free (gpg->cmd.keyword);
339 gpg_new (void **engine, const char *file_name, const char *home_dir,
340 const char *lc_ctype, const char *lc_messages)
343 gpgme_error_t rc = 0;
345 gpg = calloc (1, sizeof *gpg);
347 return gpg_error_from_errno (errno);
351 gpg->file_name = strdup (file_name);
354 rc = gpg_error_from_errno (errno);
359 gpg->argtail = &gpg->arglist;
360 gpg->status.fd[0] = -1;
361 gpg->status.fd[1] = -1;
362 gpg->colon.fd[0] = -1;
363 gpg->colon.fd[1] = -1;
366 gpg->cmd.linked_data = NULL;
367 gpg->cmd.linked_idx = -1;
369 /* Allocate the read buffer for the status pipe. */
370 gpg->status.bufsize = 1024;
371 gpg->status.readpos = 0;
372 gpg->status.buffer = malloc (gpg->status.bufsize);
373 if (!gpg->status.buffer)
375 rc = gpg_error_from_errno (errno);
378 /* In any case we need a status pipe - create it right here and
379 don't handle it with our generic gpgme_data_t mechanism. */
380 if (_gpgme_io_pipe (gpg->status.fd, 1) == -1)
382 rc = gpg_error_from_errno (errno);
385 if (_gpgme_io_set_close_notify (gpg->status.fd[0],
386 close_notify_handler, gpg)
387 || _gpgme_io_set_close_notify (gpg->status.fd[1],
388 close_notify_handler, gpg))
390 rc = gpg_error (GPG_ERR_GENERAL);
397 rc = add_arg (gpg, "--homedir");
399 rc = add_arg (gpg, home_dir);
404 rc = add_arg (gpg, "--status-fd");
410 _gpgme_io_fd2str (buf, sizeof (buf), gpg->status.fd[1]);
411 rc = add_arg (gpg, buf);
416 rc = add_arg (gpg, "--no-tty");
418 rc = add_arg (gpg, "--charset");
420 rc = add_arg (gpg, "utf8");
422 rc = add_arg (gpg, "--enable-progress-filter");
433 /* Note, that the status_handler is allowed to modifiy the args
436 gpg_set_status_handler (void *engine, engine_status_handler_t fnc,
439 engine_gpg_t gpg = engine;
441 gpg->status.fnc = fnc;
442 gpg->status.fnc_value = fnc_value;
445 /* Kludge to process --with-colon output. */
447 gpg_set_colon_line_handler (void *engine, engine_colon_line_handler_t fnc,
450 engine_gpg_t gpg = engine;
452 gpg->colon.bufsize = 1024;
453 gpg->colon.readpos = 0;
454 gpg->colon.buffer = malloc (gpg->colon.bufsize);
455 if (!gpg->colon.buffer)
456 return gpg_error_from_errno (errno);
458 if (_gpgme_io_pipe (gpg->colon.fd, 1) == -1)
460 int saved_errno = errno;
461 free (gpg->colon.buffer);
462 gpg->colon.buffer = NULL;
463 return gpg_error_from_errno (saved_errno);
465 if (_gpgme_io_set_close_notify (gpg->colon.fd[0], close_notify_handler, gpg)
466 || _gpgme_io_set_close_notify (gpg->colon.fd[1],
467 close_notify_handler, gpg))
468 return gpg_error (GPG_ERR_GENERAL);
470 gpg->colon.fnc = fnc;
471 gpg->colon.fnc_value = fnc_value;
477 command_handler (void *opaque, int fd)
480 engine_gpg_t gpg = (engine_gpg_t) opaque;
483 assert (gpg->cmd.used);
484 assert (gpg->cmd.code);
485 assert (gpg->cmd.fnc);
487 err = gpg->cmd.fnc (gpg->cmd.fnc_value, gpg->cmd.code, gpg->cmd.keyword, fd,
492 /* We always need to send at least a newline character. */
494 _gpgme_io_write (fd, "\n", 1);
497 /* And sleep again until read_status will wake us up again. */
498 /* XXX We must check if there are any more fds active after removing
500 (*gpg->io_cbs.remove) (gpg->fd_data_map[gpg->cmd.idx].tag);
501 gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
502 gpg->fd_data_map[gpg->cmd.idx].fd = -1;
509 /* The Fnc will be called to get a value for one of the commands with
510 a key KEY. If the Code pssed to FNC is 0, the function may release
511 resources associated with the returned value from another call. To
512 match such a second call to a first call, the returned value from
513 the first call is passed as keyword. */
515 gpg_set_command_handler (void *engine, engine_command_handler_t fnc,
516 void *fnc_value, gpgme_data_t linked_data)
518 engine_gpg_t gpg = engine;
521 rc = add_arg (gpg, "--command-fd");
525 /* This is a hack. We don't have a real data object. The only
526 thing that matters is that we use something unique, so we use the
527 address of the cmd structure in the gpg object. */
528 rc = add_data (gpg, (void *) &gpg->cmd, -2, 0);
533 gpg->cmd.cb_data = (void *) &gpg->cmd;
534 gpg->cmd.fnc_value = fnc_value;
535 gpg->cmd.linked_data = linked_data;
542 build_argv (engine_gpg_t gpg)
545 struct arg_and_data_s *a;
546 struct fd_data_map_s *fd_data_map;
547 size_t datac=0, argc=0;
549 int need_special = 0;
553 /* We don't want to use the agent with a malformed environment
554 variable. This is only a very basic test but sufficient to make
555 our life in the regression tests easier. */
556 err = _gpgme_getenv ("GPG_AGENT_INFO", &p);
559 use_agent = (p && strchr (p, ':'));
565 free_argv (gpg->argv);
568 if (gpg->fd_data_map)
570 free_fd_data_map (gpg->fd_data_map);
571 gpg->fd_data_map = NULL;
574 argc++; /* For argv[0]. */
575 for (a = gpg->arglist; a; a = a->next)
580 /*fprintf (stderr, "build_argv: data\n" );*/
582 if (a->dup_to == -1 && !a->print_fd)
587 /* fprintf (stderr, "build_argv: arg=`%s'\n", a->arg );*/
595 argc++; /* --batch */
596 argc += 1; /* --no-sk-comment */
598 argv = calloc (argc + 1, sizeof *argv);
600 return gpg_error_from_errno (errno);
601 fd_data_map = calloc (datac + 1, sizeof *fd_data_map);
604 int saved_errno = errno;
606 return gpg_error_from_errno (saved_errno);
610 argv[argc] = strdup ("gpg"); /* argv[0] */
613 int saved_errno = errno;
616 return gpg_error_from_errno (saved_errno);
621 argv[argc] = strdup ("--enable-special-filenames");
624 int saved_errno = errno;
627 return gpg_error_from_errno (saved_errno);
633 argv[argc] = strdup ("--use-agent");
636 int saved_errno = errno;
639 return gpg_error_from_errno (saved_errno);
645 argv[argc] = strdup ("--batch");
648 int saved_errno = errno;
651 return gpg_error_from_errno (saved_errno);
655 argv[argc] = strdup ("--no-sk-comment");
658 int saved_errno = errno;
661 return gpg_error_from_errno (saved_errno);
664 for (a = gpg->arglist; a; a = a->next)
668 /* Create a pipe to pass it down to gpg. */
669 fd_data_map[datac].inbound = a->inbound;
675 if (_gpgme_io_pipe (fds, fd_data_map[datac].inbound ? 1 : 0)
678 int saved_errno = errno;
681 return gpg_error (saved_errno);
683 if (_gpgme_io_set_close_notify (fds[0],
684 close_notify_handler, gpg)
685 || _gpgme_io_set_close_notify (fds[1],
686 close_notify_handler,
689 return gpg_error (GPG_ERR_GENERAL);
691 /* If the data_type is FD, we have to do a dup2 here. */
692 if (fd_data_map[datac].inbound)
694 fd_data_map[datac].fd = fds[0];
695 fd_data_map[datac].peer_fd = fds[1];
699 fd_data_map[datac].fd = fds[1];
700 fd_data_map[datac].peer_fd = fds[0];
704 /* Hack to get hands on the fd later. */
707 if (gpg->cmd.cb_data == a->data)
709 assert (gpg->cmd.idx == -1);
710 gpg->cmd.idx = datac;
712 else if (gpg->cmd.linked_data == a->data)
714 assert (gpg->cmd.linked_idx == -1);
715 gpg->cmd.linked_idx = datac;
719 fd_data_map[datac].data = a->data;
720 fd_data_map[datac].dup_to = a->dup_to;
726 argv[argc] = malloc (buflen);
729 int saved_errno = errno;
732 return gpg_error_from_errno (saved_errno);
743 _gpgme_io_fd2str (ptr, buflen, fd_data_map[datac].peer_fd);
750 argv[argc] = strdup (a->arg);
753 int saved_errno = errno;
756 return gpg_error_from_errno (saved_errno);
763 gpg->fd_data_map = fd_data_map;
769 add_io_cb (engine_gpg_t gpg, int fd, int dir, gpgme_io_cb_t handler, void *data,
774 err = (*gpg->io_cbs.add) (gpg->io_cbs.add_priv, fd, dir, handler, data, tag);
778 /* FIXME Kludge around poll() problem. */
779 err = _gpgme_io_set_nonblocking (fd);
785 status_cmp (const void *ap, const void *bp)
787 const struct status_table_s *a = ap;
788 const struct status_table_s *b = bp;
790 return strcmp (a->name, b->name);
794 /* Handle the status output of GnuPG. This function does read entire
795 lines and passes them as C strings to the callback function (we can
796 use C Strings because the status output is always UTF-8 encoded).
797 Of course we have to buffer the lines to cope with long lines
798 e.g. with a large user ID. Note: We can optimize this to only cope
799 with status line code we know about and skip all other stuff
800 without buffering (i.e. without extending the buffer). */
802 read_status (engine_gpg_t gpg)
806 size_t bufsize = gpg->status.bufsize;
807 char *buffer = gpg->status.buffer;
808 size_t readpos = gpg->status.readpos;
811 if (bufsize - readpos < 256)
813 /* Need more room for the read. */
815 buffer = realloc (buffer, bufsize);
817 return gpg_error_from_errno (errno);
820 nread = _gpgme_io_read (gpg->status.fd[0],
821 buffer + readpos, bufsize-readpos);
823 return gpg_error_from_errno (errno);
831 err = gpg->status.fnc (gpg->status.fnc_value, GPGME_STATUS_EOF, "");
840 for (p = buffer + readpos; nread; nread--, p++)
844 /* (we require that the last line is terminated by a LF) */
846 if (!strncmp (buffer, "[GNUPG:] ", 9)
847 && buffer[9] >= 'A' && buffer[9] <= 'Z')
849 struct status_table_s t, *r;
852 rest = strchr (buffer + 9, ' ');
854 rest = p; /* Set to an empty string. */
859 /* (the status table has one extra element) */
860 r = bsearch (&t, status_table, DIM(status_table) - 1,
861 sizeof t, status_cmp);
865 && (r->code == GPGME_STATUS_GET_BOOL
866 || r->code == GPGME_STATUS_GET_LINE
867 || r->code == GPGME_STATUS_GET_HIDDEN))
869 gpg->cmd.code = r->code;
870 if (gpg->cmd.keyword)
871 free (gpg->cmd.keyword);
872 gpg->cmd.keyword = strdup (rest);
873 if (!gpg->cmd.keyword)
874 return gpg_error_from_errno (errno);
875 /* This should be the last thing we have
876 received and the next thing will be that
877 the command handler does its action. */
879 DEBUG0 ("ERROR, unexpected data in read_status");
881 add_io_cb (gpg, gpg->cmd.fd, 0,
882 command_handler, gpg,
883 &gpg->fd_data_map[gpg->cmd.idx].tag);
884 gpg->fd_data_map[gpg->cmd.idx].fd = gpg->cmd.fd;
887 else if (gpg->status.fnc)
890 err = gpg->status.fnc (gpg->status.fnc_value,
896 if (r->code == GPGME_STATUS_END_STREAM)
900 /* Before we can actually add the
901 command fd, we might have to flush
902 the linked output data pipe. */
903 if (gpg->cmd.linked_idx != -1
904 && gpg->fd_data_map[gpg->cmd.linked_idx].fd
907 struct io_select_fd_s fds;
909 gpg->fd_data_map[gpg->cmd.linked_idx].fd;
917 _gpgme_io_select (&fds, 1, 1);
919 _gpgme_data_inbound_handler
920 (gpg->cmd.linked_data, fds.fd);
922 while (fds.signaled);
925 /* XXX We must check if there are any
926 more fds active after removing this
928 (*gpg->io_cbs.remove)
929 (gpg->fd_data_map[gpg->cmd.idx].tag);
930 gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
931 gpg->fd_data_map[gpg->cmd.idx].fd = -1;
936 /* To reuse the buffer for the next line we have to
937 shift the remaining data to the buffer start and
938 restart the loop Hmmm: We can optimize this function
939 by looking forward in the buffer to see whether a
940 second complete line is available and in this case
941 avoid the memmove for this line. */
944 memmove (buffer, p, nread);
946 break; /* the for loop */
953 /* Update the gpg object. */
954 gpg->status.bufsize = bufsize;
955 gpg->status.buffer = buffer;
956 gpg->status.readpos = readpos;
962 status_handler (void *opaque, int fd)
964 engine_gpg_t gpg = opaque;
967 assert (fd == gpg->status.fd[0]);
968 err = read_status (gpg);
972 _gpgme_io_close (fd);
978 read_colon_line (engine_gpg_t gpg)
982 size_t bufsize = gpg->colon.bufsize;
983 char *buffer = gpg->colon.buffer;
984 size_t readpos = gpg->colon.readpos;
987 if (bufsize - readpos < 256)
989 /* Need more room for the read. */
991 buffer = realloc (buffer, bufsize);
993 return gpg_error_from_errno (errno);
996 nread = _gpgme_io_read (gpg->colon.fd[0], buffer+readpos, bufsize-readpos);
998 return gpg_error_from_errno (errno);
1003 assert (gpg->colon.fnc);
1004 gpg->colon.fnc (gpg->colon.fnc_value, NULL);
1010 for (p = buffer + readpos; nread; nread--, p++)
1014 /* (we require that the last line is terminated by a LF)
1015 and we skip empty lines. Note: we use UTF8 encoding
1016 and escaping of special characters We require at
1017 least one colon to cope with some other printed
1020 if (*buffer && strchr (buffer, ':'))
1022 assert (gpg->colon.fnc);
1023 gpg->colon.fnc (gpg->colon.fnc_value, buffer);
1026 /* To reuse the buffer for the next line we have to
1027 shift the remaining data to the buffer start and
1028 restart the loop Hmmm: We can optimize this function
1029 by looking forward in the buffer to see whether a
1030 second complete line is available and in this case
1031 avoid the memmove for this line. */
1034 memmove (buffer, p, nread);
1036 break; /* The for loop. */
1043 /* Update the gpg object. */
1044 gpg->colon.bufsize = bufsize;
1045 gpg->colon.buffer = buffer;
1046 gpg->colon.readpos = readpos;
1051 /* This colonline handler thing is not the clean way to do it. It
1052 might be better to enhance the gpgme_data_t object to act as a wrapper
1053 for a callback. Same goes for the status thing. For now we use
1054 this thing here because it is easier to implement. */
1055 static gpgme_error_t
1056 colon_line_handler (void *opaque, int fd)
1058 engine_gpg_t gpg = opaque;
1059 gpgme_error_t rc = 0;
1061 assert (fd == gpg->colon.fd[0]);
1062 rc = read_colon_line (gpg);
1066 _gpgme_io_close (fd);
1071 static gpgme_error_t
1072 start (engine_gpg_t gpg)
1078 struct spawn_fd_item_s *fd_child_list, *fd_parent_list;
1081 return gpg_error (GPG_ERR_INV_VALUE);
1083 if (!gpg->file_name && !_gpgme_get_gpg_path ())
1084 return gpg_error (GPG_ERR_INV_ENGINE);
1086 rc = build_argv (gpg);
1090 n = 3; /* status_fd, colon_fd and end of list */
1091 for (i = 0; gpg->fd_data_map[i].data; i++)
1093 fd_child_list = calloc (n + n, sizeof *fd_child_list);
1095 return gpg_error_from_errno (errno);
1096 fd_parent_list = fd_child_list + n;
1098 /* build the fd list for the child */
1102 fd_child_list[n].fd = gpg->colon.fd[1];
1103 fd_child_list[n].dup_to = 1; /* dup to stdout */
1106 for (i = 0; gpg->fd_data_map[i].data; i++)
1108 if (gpg->fd_data_map[i].dup_to != -1)
1110 fd_child_list[n].fd = gpg->fd_data_map[i].peer_fd;
1111 fd_child_list[n].dup_to = gpg->fd_data_map[i].dup_to;
1115 fd_child_list[n].fd = -1;
1116 fd_child_list[n].dup_to = -1;
1118 /* Build the fd list for the parent. */
1120 if (gpg->status.fd[1] != -1)
1122 fd_parent_list[n].fd = gpg->status.fd[1];
1123 fd_parent_list[n].dup_to = -1;
1126 if (gpg->colon.fd[1] != -1)
1128 fd_parent_list[n].fd = gpg->colon.fd[1];
1129 fd_parent_list[n].dup_to = -1;
1132 for (i = 0; gpg->fd_data_map[i].data; i++)
1134 fd_parent_list[n].fd = gpg->fd_data_map[i].peer_fd;
1135 fd_parent_list[n].dup_to = -1;
1138 fd_parent_list[n].fd = -1;
1139 fd_parent_list[n].dup_to = -1;
1141 status = _gpgme_io_spawn (gpg->file_name ? gpg->file_name :
1142 _gpgme_get_gpg_path (),
1143 gpg->argv, fd_child_list, fd_parent_list);
1144 saved_errno = errno;
1145 free (fd_child_list);
1147 return gpg_error_from_errno (saved_errno);
1149 /*_gpgme_register_term_handler ( closure, closure_value, pid );*/
1151 rc = add_io_cb (gpg, gpg->status.fd[0], 1, status_handler, gpg,
1154 /* FIXME: kill the child */
1159 assert (gpg->colon.fd[0] != -1);
1160 rc = add_io_cb (gpg, gpg->colon.fd[0], 1, colon_line_handler, gpg,
1163 /* FIXME: kill the child */
1167 for (i = 0; gpg->fd_data_map[i].data; i++)
1169 if (gpg->cmd.used && i == gpg->cmd.idx)
1171 /* Park the cmd fd. */
1172 gpg->cmd.fd = gpg->fd_data_map[i].fd;
1173 gpg->fd_data_map[i].fd = -1;
1177 rc = add_io_cb (gpg, gpg->fd_data_map[i].fd,
1178 gpg->fd_data_map[i].inbound,
1179 gpg->fd_data_map[i].inbound
1180 ? _gpgme_data_inbound_handler
1181 : _gpgme_data_outbound_handler,
1182 gpg->fd_data_map[i].data, &gpg->fd_data_map[i].tag);
1185 /* FIXME: kill the child */
1190 (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, GPGME_EVENT_START, NULL);
1192 /* fixme: check what data we can release here */
1197 static gpgme_error_t
1198 gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
1200 engine_gpg_t gpg = engine;
1203 err = add_arg (gpg, "--decrypt");
1205 /* Tell the gpg object about the data. */
1207 err = add_arg (gpg, "--output");
1209 err = add_arg (gpg, "-");
1211 err = add_data (gpg, plain, 1, 1);
1213 err = add_data (gpg, ciph, 0, 0);
1220 static gpgme_error_t
1221 gpg_delete (void *engine, gpgme_key_t key, int allow_secret)
1223 engine_gpg_t gpg = engine;
1226 err = add_arg (gpg, allow_secret ? "--delete-secret-and-public-key"
1229 err = add_arg (gpg, "--");
1232 if (!key->subkeys || !key->subkeys->fpr)
1233 return gpg_error (GPG_ERR_INV_VALUE);
1235 err = add_arg (gpg, key->subkeys->fpr);
1244 static gpgme_error_t
1245 append_args_from_signers (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1247 gpgme_error_t err = 0;
1251 for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++)
1253 const char *s = key->subkeys ? key->subkeys->keyid : NULL;
1257 err = add_arg (gpg, "-u");
1259 err = add_arg (gpg, s);
1261 gpgme_key_unref (key);
1268 static gpgme_error_t
1269 append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1271 gpgme_error_t err = 0;
1272 gpgme_sig_notation_t notation;
1274 notation = gpgme_sig_notation_get (ctx);
1276 while (!err && notation)
1279 && !(notation->flags & GPGME_SIG_NOTATION_HUMAN_READABLE))
1280 err = gpg_error (GPG_ERR_INV_VALUE);
1281 else if (notation->name)
1285 /* Maximum space needed is one byte for the "critical" flag,
1286 the name, one byte for '=', the value, and a terminating
1289 arg = malloc (1 + notation->name_len + 1 + notation->value_len + 1);
1291 err = gpg_error_from_errno (errno);
1297 if (notation->critical)
1300 memcpy (argp, notation->name, notation->name_len);
1301 argp += notation->name_len;
1305 /* We know that notation->name is '\0' terminated. */
1306 strcpy (argp, notation->value);
1310 err = add_arg (gpg, "--sig-notation");
1312 err = add_arg (gpg, arg);
1319 /* This is a policy URL. */
1323 if (notation->critical)
1325 value = malloc (1 + notation->value_len + 1);
1327 err = gpg_error_from_errno (errno);
1331 /* We know that notation->value is '\0' terminated. */
1332 strcpy (&value[1], notation->value);
1336 value = notation->value;
1339 err = add_arg (gpg, "--sig-policy-url");
1341 err = add_arg (gpg, value);
1343 if (value != notation->value)
1347 notation = notation->next;
1353 static gpgme_error_t
1354 gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out,
1355 gpgme_ctx_t ctx /* FIXME */)
1357 engine_gpg_t gpg = engine;
1360 err = add_arg (gpg, "--with-colons");
1362 err = append_args_from_signers (gpg, ctx);
1364 err = add_arg (gpg, type == 0 ? "--edit-key" : "--card-edit");
1366 err = add_data (gpg, out, 1, 1);
1368 err = add_arg (gpg, "--");
1369 if (!err && type == 0)
1371 const char *s = key->subkeys ? key->subkeys->fpr : NULL;
1373 err = gpg_error (GPG_ERR_INV_VALUE);
1375 err = add_arg (gpg, s);
1384 static gpgme_error_t
1385 append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[])
1387 gpgme_error_t err = 0;
1392 if (!recp[i]->subkeys || !recp[i]->subkeys->fpr)
1393 err = gpg_error (GPG_ERR_INV_VALUE);
1395 err = add_arg (gpg, "-r");
1397 err = add_arg (gpg, recp[i]->subkeys->fpr);
1406 static gpgme_error_t
1407 gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
1408 gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
1410 engine_gpg_t gpg = engine;
1412 int symmetric = !recp;
1414 err = add_arg (gpg, symmetric ? "--symmetric" : "--encrypt");
1416 if (!err && use_armor)
1417 err = add_arg (gpg, "--armor");
1421 /* If we know that all recipients are valid (full or ultimate trust)
1422 we can suppress further checks. */
1423 if (!err && !symmetric && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1424 err = add_arg (gpg, "--always-trust");
1427 err = append_args_from_recipients (gpg, recp);
1430 /* Tell the gpg object about the data. */
1432 err = add_arg (gpg, "--output");
1434 err = add_arg (gpg, "-");
1436 err = add_data (gpg, ciph, 1, 1);
1437 if (gpgme_data_get_file_name (plain))
1440 err = add_arg (gpg, "--set-filename");
1442 err = add_arg (gpg, gpgme_data_get_file_name (plain));
1445 err = add_arg (gpg, "--");
1447 err = add_data (gpg, plain, 0, 0);
1456 static gpgme_error_t
1457 gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
1458 gpgme_encrypt_flags_t flags, gpgme_data_t plain,
1459 gpgme_data_t ciph, int use_armor,
1460 gpgme_ctx_t ctx /* FIXME */)
1462 engine_gpg_t gpg = engine;
1465 err = add_arg (gpg, "--encrypt");
1467 err = add_arg (gpg, "--sign");
1468 if (!err && use_armor)
1469 err = add_arg (gpg, "--armor");
1471 /* If we know that all recipients are valid (full or ultimate trust)
1472 we can suppress further checks. */
1473 if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1474 err = add_arg (gpg, "--always-trust");
1477 err = append_args_from_recipients (gpg, recp);
1480 err = append_args_from_signers (gpg, ctx);
1482 err = append_args_from_sig_notations (gpg, ctx);
1484 /* Tell the gpg object about the data. */
1486 err = add_arg (gpg, "--output");
1488 err = add_arg (gpg, "-");
1490 err = add_data (gpg, ciph, 1, 1);
1491 if (gpgme_data_get_file_name (plain))
1494 err = add_arg (gpg, "--set-filename");
1496 err = add_arg (gpg, gpgme_data_get_file_name (plain));
1499 err = add_arg (gpg, "--");
1501 err = add_data (gpg, plain, 0, 0);
1510 static gpgme_error_t
1511 gpg_export (void *engine, const char *pattern, unsigned int reserved,
1512 gpgme_data_t keydata, int use_armor)
1514 engine_gpg_t gpg = engine;
1518 return gpg_error (GPG_ERR_INV_VALUE);
1520 err = add_arg (gpg, "--export");
1521 if (!err && use_armor)
1522 err = add_arg (gpg, "--armor");
1524 err = add_data (gpg, keydata, 1, 1);
1526 err = add_arg (gpg, "--");
1528 if (!err && pattern && *pattern)
1529 err = add_arg (gpg, pattern);
1538 static gpgme_error_t
1539 gpg_export_ext (void *engine, const char *pattern[], unsigned int reserved,
1540 gpgme_data_t keydata, int use_armor)
1542 engine_gpg_t gpg = engine;
1546 return gpg_error (GPG_ERR_INV_VALUE);
1548 err = add_arg (gpg, "--export");
1549 if (!err && use_armor)
1550 err = add_arg (gpg, "--armor");
1552 err = add_data (gpg, keydata, 1, 1);
1554 err = add_arg (gpg, "--");
1558 while (!err && *pattern && **pattern)
1559 err = add_arg (gpg, *(pattern++));
1569 static gpgme_error_t
1570 gpg_genkey (void *engine, gpgme_data_t help_data, int use_armor,
1571 gpgme_data_t pubkey, gpgme_data_t seckey)
1573 engine_gpg_t gpg = engine;
1577 return gpg_error (GPG_ERR_INV_VALUE);
1579 /* We need a special mechanism to get the fd of a pipe here, so that
1580 we can use this for the %pubring and %secring parameters. We
1581 don't have this yet, so we implement only the adding to the
1582 standard keyrings. */
1583 if (pubkey || seckey)
1584 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1586 err = add_arg (gpg, "--gen-key");
1587 if (!err && use_armor)
1588 err = add_arg (gpg, "--armor");
1590 err = add_data (gpg, help_data, 0, 0);
1599 static gpgme_error_t
1600 gpg_import (void *engine, gpgme_data_t keydata)
1602 engine_gpg_t gpg = engine;
1605 err = add_arg (gpg, "--import");
1607 err = add_data (gpg, keydata, 0, 0);
1616 static gpgme_error_t
1617 gpg_keylist (void *engine, const char *pattern, int secret_only,
1618 gpgme_keylist_mode_t mode)
1620 engine_gpg_t gpg = engine;
1623 err = add_arg (gpg, "--with-colons");
1625 err = add_arg (gpg, "--fixed-list-mode");
1627 err = add_arg (gpg, "--with-fingerprint");
1629 err = add_arg (gpg, "--with-fingerprint");
1630 if (!err && (mode & GPGME_KEYLIST_MODE_SIGS)
1631 && (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS))
1633 err = add_arg (gpg, "--list-options");
1635 err = add_arg (gpg, "show-sig-subpackets=\"20,26\"");
1638 err = add_arg (gpg, secret_only ? "--list-secret-keys"
1639 : ((mode & GPGME_KEYLIST_MODE_SIGS)
1640 ? "--check-sigs" : "--list-keys"));
1642 /* Tell the gpg object about the data. */
1644 err = add_arg (gpg, "--");
1645 if (!err && pattern && *pattern)
1646 err = add_arg (gpg, pattern);
1655 static gpgme_error_t
1656 gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
1657 int reserved, gpgme_keylist_mode_t mode)
1659 engine_gpg_t gpg = engine;
1663 return gpg_error (GPG_ERR_INV_VALUE);
1665 err = add_arg (gpg, "--with-colons");
1667 err = add_arg (gpg, "--fixed-list-mode");
1669 err = add_arg (gpg, "--with-fingerprint");
1671 err = add_arg (gpg, "--with-fingerprint");
1672 if (!err && (mode & GPGME_KEYLIST_MODE_SIGS)
1673 && (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS))
1675 err = add_arg (gpg, "--list-options");
1677 err = add_arg (gpg, "show-sig-subpackets=\"20,26\"");
1680 err = add_arg (gpg, secret_only ? "--list-secret-keys"
1681 : ((mode & GPGME_KEYLIST_MODE_SIGS)
1682 ? "--check-sigs" : "--list-keys"));
1684 err = add_arg (gpg, "--");
1688 while (!err && *pattern && **pattern)
1689 err = add_arg (gpg, *(pattern++));
1699 static gpgme_error_t
1700 gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
1701 gpgme_sig_mode_t mode, int use_armor, int use_textmode,
1702 int include_certs, gpgme_ctx_t ctx /* FIXME */)
1704 engine_gpg_t gpg = engine;
1707 if (mode == GPGME_SIG_MODE_CLEAR)
1708 err = add_arg (gpg, "--clearsign");
1711 err = add_arg (gpg, "--sign");
1712 if (!err && mode == GPGME_SIG_MODE_DETACH)
1713 err = add_arg (gpg, "--detach");
1714 if (!err && use_armor)
1715 err = add_arg (gpg, "--armor");
1716 if (!err && use_textmode)
1717 err = add_arg (gpg, "--textmode");
1721 err = append_args_from_signers (gpg, ctx);
1723 err = append_args_from_sig_notations (gpg, ctx);
1725 if (gpgme_data_get_file_name (in))
1728 err = add_arg (gpg, "--set-filename");
1730 err = add_arg (gpg, gpgme_data_get_file_name (in));
1733 /* Tell the gpg object about the data. */
1735 err = add_data (gpg, in, 0, 0);
1737 err = add_data (gpg, out, 1, 1);
1745 static gpgme_error_t
1746 gpg_trustlist (void *engine, const char *pattern)
1748 engine_gpg_t gpg = engine;
1751 err = add_arg (gpg, "--with-colons");
1753 err = add_arg (gpg, "--list-trust-path");
1755 /* Tell the gpg object about the data. */
1757 err = add_arg (gpg, "--");
1759 err = add_arg (gpg, pattern);
1768 static gpgme_error_t
1769 gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
1770 gpgme_data_t plaintext)
1772 engine_gpg_t gpg = engine;
1773 gpgme_error_t err = 0;
1777 /* Normal or cleartext signature. */
1779 err = add_arg (gpg, "--output");
1781 err = add_arg (gpg, "-");
1783 err = add_arg (gpg, "--");
1785 err = add_data (gpg, sig, 0, 0);
1787 err = add_data (gpg, plaintext, 1, 1);
1791 err = add_arg (gpg, "--verify");
1793 err = add_arg (gpg, "--");
1795 err = add_data (gpg, sig, -1, 0);
1799 err = add_arg (gpg, "-");
1801 err = add_data (gpg, signed_text, 0, 0);
1813 gpg_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
1815 engine_gpg_t gpg = engine;
1817 gpg->io_cbs = *io_cbs;
1821 struct engine_ops _gpgme_engine_ops_gpg =
1823 /* Static functions. */
1824 _gpgme_get_gpg_path,
1826 gpg_get_req_version,
1829 /* Member functions. */
1831 gpg_set_status_handler,
1832 gpg_set_command_handler,
1833 gpg_set_colon_line_handler,