core: New function gpgme_op_create_key.
[gpgme.git] / src / engine-gpg.c
1 /* engine-gpg.c - Gpg Engine.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007,
4                  2009, 2010, 2012, 2013 g10 Code GmbH
5
6    This file is part of GPGME.
7
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.
12
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.
17
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/>.
20 */
21
22 #if HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <errno.h>
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33 #ifdef HAVE_LOCALE_H
34 #include <locale.h>
35 #endif
36
37 #include "gpgme.h"
38 #include "util.h"
39 #include "ops.h"
40 #include "wait.h"
41 #include "context.h"  /*temp hack until we have GpmeData methods to do I/O */
42 #include "priv-io.h"
43 #include "sema.h"
44 #include "debug.h"
45 #include "data.h"
46
47 #include "engine-backend.h"
48
49
50 /* This type is used to build a list of gpg arguments and data
51    sources/sinks.  */
52 struct arg_and_data_s
53 {
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.  */
57   int dup_to;
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.  */
62 };
63
64
65 struct fd_data_map_s
66 {
67   gpgme_data_t data;
68   int inbound;  /* true if this is used for reading from gpg */
69   int dup_to;
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.  */
73   void *tag;
74 };
75
76
77 typedef gpgme_error_t (*colon_preprocessor_t) (char *line, char **rline);
78
79 struct engine_gpg
80 {
81   char *file_name;
82   char *version;
83
84   char *lc_messages;
85   char *lc_ctype;
86
87   struct arg_and_data_s *arglist;
88   struct arg_and_data_s **argtail;
89
90   struct
91   {
92     int fd[2];
93     int arg_loc;
94     size_t bufsize;
95     char *buffer;
96     size_t readpos;
97     int eof;
98     engine_status_handler_t fnc;
99     void *fnc_value;
100     gpgme_status_cb_t mon_cb;
101     void *mon_cb_value;
102     void *tag;
103   } status;
104
105   /* This is a kludge - see the comment at colon_line_handler.  */
106   struct
107   {
108     int fd[2];
109     int arg_loc;
110     size_t bufsize;
111     char *buffer;
112     size_t readpos;
113     int eof;
114     engine_colon_line_handler_t fnc;  /* this indicate use of this structrue */
115     void *fnc_value;
116     void *tag;
117     colon_preprocessor_t preprocess_fnc;
118   } colon;
119
120   char **argv;
121   struct fd_data_map_s *fd_data_map;
122
123   /* stuff needed for interactive (command) mode */
124   struct
125   {
126     int used;
127     int fd;
128     void *cb_data;
129     int idx;            /* Index in fd_data_map */
130     gpgme_status_code_t code;  /* last code */
131     char *keyword;       /* what has been requested (malloced) */
132     engine_command_handler_t fnc;
133     void *fnc_value;
134     /* The kludges never end.  This is used to couple command handlers
135        with output data in edit key mode.  */
136     gpgme_data_t linked_data;
137     int linked_idx;
138   } cmd;
139
140   struct gpgme_io_cbs io_cbs;
141   gpgme_pinentry_mode_t pinentry_mode;
142 };
143
144 typedef struct engine_gpg *engine_gpg_t;
145
146 \f
147 static void
148 gpg_io_event (void *engine, gpgme_event_io_t type, void *type_data)
149 {
150   engine_gpg_t gpg = engine;
151
152   TRACE3 (DEBUG_ENGINE, "gpgme:gpg_io_event", gpg,
153           "event %p, type %d, type_data %p",
154           gpg->io_cbs.event, type, type_data);
155   if (gpg->io_cbs.event)
156     (*gpg->io_cbs.event) (gpg->io_cbs.event_priv, type, type_data);
157 }
158
159
160 static void
161 close_notify_handler (int fd, void *opaque)
162 {
163   engine_gpg_t gpg = opaque;
164   assert (fd != -1);
165
166   if (gpg->status.fd[0] == fd)
167     {
168       if (gpg->status.tag)
169         (*gpg->io_cbs.remove) (gpg->status.tag);
170       gpg->status.fd[0] = -1;
171     }
172   else if (gpg->status.fd[1] == fd)
173     gpg->status.fd[1] = -1;
174   else if (gpg->colon.fd[0] == fd)
175     {
176       if (gpg->colon.tag)
177         (*gpg->io_cbs.remove) (gpg->colon.tag);
178       gpg->colon.fd[0] = -1;
179     }
180   else if (gpg->colon.fd[1] == fd)
181     gpg->colon.fd[1] = -1;
182   else if (gpg->cmd.fd == fd)
183     gpg->cmd.fd = -1;
184   else if (gpg->fd_data_map)
185     {
186       int i;
187
188       for (i = 0; gpg->fd_data_map[i].data; i++)
189         {
190           if (gpg->fd_data_map[i].fd == fd)
191             {
192               if (gpg->fd_data_map[i].tag)
193                 (*gpg->io_cbs.remove) (gpg->fd_data_map[i].tag);
194               gpg->fd_data_map[i].fd = -1;
195               break;
196             }
197           if (gpg->fd_data_map[i].peer_fd == fd)
198             {
199               gpg->fd_data_map[i].peer_fd = -1;
200               break;
201             }
202         }
203     }
204 }
205
206 /* If FRONT is true, push at the front of the list.  Use this for
207    options added late in the process.  */
208 static gpgme_error_t
209 _add_arg (engine_gpg_t gpg, const char *arg, int front, int *arg_locp)
210 {
211   struct arg_and_data_s *a;
212
213   assert (gpg);
214   assert (arg);
215
216   a = malloc (sizeof *a + strlen (arg));
217   if (!a)
218     return gpg_error_from_syserror ();
219
220   a->data = NULL;
221   a->dup_to = -1;
222   a->arg_locp = arg_locp;
223
224   strcpy (a->arg, arg);
225   if (front)
226     {
227       a->next = gpg->arglist;
228       if (!gpg->arglist)
229         {
230           /* If this is the first argument, we need to update the tail
231              pointer.  */
232           gpg->argtail = &a->next;
233         }
234       gpg->arglist = a;
235     }
236   else
237     {
238       a->next = NULL;
239       *gpg->argtail = a;
240       gpg->argtail = &a->next;
241     }
242
243   return 0;
244 }
245
246 static gpgme_error_t
247 add_arg_ext (engine_gpg_t gpg, const char *arg, int front)
248 {
249   return _add_arg (gpg, arg, front, NULL);
250 }
251
252
253 static gpgme_error_t
254 add_arg_with_locp (engine_gpg_t gpg, const char *arg, int *locp)
255 {
256   return _add_arg (gpg, arg, 0, locp);
257 }
258
259
260 static gpgme_error_t
261 add_arg (engine_gpg_t gpg, const char *arg)
262 {
263   return add_arg_ext (gpg, arg, 0);
264 }
265
266
267 static gpgme_error_t
268 add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound)
269 {
270   struct arg_and_data_s *a;
271
272   assert (gpg);
273   assert (data);
274
275   a = malloc (sizeof *a - 1);
276   if (!a)
277     return gpg_error_from_syserror ();
278   a->next = NULL;
279   a->data = data;
280   a->inbound = inbound;
281   a->arg_locp = NULL;
282
283   if (dup_to == -2)
284     {
285       a->print_fd = 1;
286       a->dup_to = -1;
287     }
288   else
289     {
290       a->print_fd = 0;
291       a->dup_to = dup_to;
292     }
293   *gpg->argtail = a;
294   gpg->argtail = &a->next;
295   return 0;
296 }
297
298
299 /* Return true if the engine's version is at least VERSION.  */
300 static int
301 have_gpg_version (engine_gpg_t gpg, const char *version)
302 {
303   return _gpgme_compare_versions (gpg->version, version);
304 }
305
306
307 \f
308 static char *
309 gpg_get_version (const char *file_name)
310 {
311   return _gpgme_get_program_version (file_name ? file_name
312                                      : _gpgme_get_default_gpg_name ());
313 }
314
315
316 static const char *
317 gpg_get_req_version (void)
318 {
319   return "1.4.0";
320 }
321
322
323 static void
324 free_argv (char **argv)
325 {
326   int i;
327
328   for (i = 0; argv[i]; i++)
329     free (argv[i]);
330   free (argv);
331 }
332
333
334 static void
335 free_fd_data_map (struct fd_data_map_s *fd_data_map)
336 {
337   int i;
338
339   if (!fd_data_map)
340     return;
341
342   for (i = 0; fd_data_map[i].data; i++)
343     {
344       if (fd_data_map[i].fd != -1)
345         _gpgme_io_close (fd_data_map[i].fd);
346       if (fd_data_map[i].peer_fd != -1)
347         _gpgme_io_close (fd_data_map[i].peer_fd);
348       /* Don't release data because this is only a reference.  */
349     }
350   free (fd_data_map);
351 }
352
353
354 static gpgme_error_t
355 gpg_cancel (void *engine)
356 {
357   engine_gpg_t gpg = engine;
358
359   if (!gpg)
360     return gpg_error (GPG_ERR_INV_VALUE);
361
362   /* If gpg may be waiting for a cmd, close the cmd fd first.  On
363      Windows, close operations block on the reader/writer thread.  */
364   if (gpg->cmd.used)
365     {
366       if (gpg->cmd.fd != -1)
367         _gpgme_io_close (gpg->cmd.fd);
368       else if (gpg->fd_data_map
369                && gpg->fd_data_map[gpg->cmd.idx].fd != -1)
370         _gpgme_io_close (gpg->fd_data_map[gpg->cmd.idx].fd);
371     }
372
373   if (gpg->status.fd[0] != -1)
374     _gpgme_io_close (gpg->status.fd[0]);
375   if (gpg->status.fd[1] != -1)
376     _gpgme_io_close (gpg->status.fd[1]);
377   if (gpg->colon.fd[0] != -1)
378     _gpgme_io_close (gpg->colon.fd[0]);
379   if (gpg->colon.fd[1] != -1)
380     _gpgme_io_close (gpg->colon.fd[1]);
381   if (gpg->fd_data_map)
382     {
383       free_fd_data_map (gpg->fd_data_map);
384       gpg->fd_data_map = NULL;
385     }
386
387   return 0;
388 }
389
390 static void
391 gpg_release (void *engine)
392 {
393   engine_gpg_t gpg = engine;
394
395   if (!gpg)
396     return;
397
398   gpg_cancel (engine);
399
400   if (gpg->file_name)
401     free (gpg->file_name);
402   if (gpg->version)
403     free (gpg->version);
404
405   if (gpg->lc_messages)
406     free (gpg->lc_messages);
407   if (gpg->lc_ctype)
408     free (gpg->lc_ctype);
409
410   while (gpg->arglist)
411     {
412       struct arg_and_data_s *next = gpg->arglist->next;
413
414       free (gpg->arglist);
415       gpg->arglist = next;
416     }
417
418   if (gpg->status.buffer)
419     free (gpg->status.buffer);
420   if (gpg->colon.buffer)
421     free (gpg->colon.buffer);
422   if (gpg->argv)
423     free_argv (gpg->argv);
424   if (gpg->cmd.keyword)
425     free (gpg->cmd.keyword);
426
427   free (gpg);
428 }
429
430
431 static gpgme_error_t
432 gpg_new (void **engine, const char *file_name, const char *home_dir,
433          const char *version)
434 {
435   engine_gpg_t gpg;
436   gpgme_error_t rc = 0;
437   char *dft_display = NULL;
438   char dft_ttyname[64];
439   char *dft_ttytype = NULL;
440
441   gpg = calloc (1, sizeof *gpg);
442   if (!gpg)
443     return gpg_error_from_syserror ();
444
445   if (file_name)
446     {
447       gpg->file_name = strdup (file_name);
448       if (!gpg->file_name)
449         {
450           rc = gpg_error_from_syserror ();
451           goto leave;
452         }
453     }
454
455   if (version)
456     {
457       gpg->version = strdup (version);
458       if (!gpg->version)
459         {
460           rc = gpg_error_from_syserror ();
461           goto leave;
462         }
463     }
464
465   gpg->argtail = &gpg->arglist;
466   gpg->status.fd[0] = -1;
467   gpg->status.fd[1] = -1;
468   gpg->colon.fd[0] = -1;
469   gpg->colon.fd[1] = -1;
470   gpg->cmd.fd = -1;
471   gpg->cmd.idx = -1;
472   gpg->cmd.linked_data = NULL;
473   gpg->cmd.linked_idx = -1;
474
475   /* Allocate the read buffer for the status pipe.  */
476   gpg->status.bufsize = 1024;
477   gpg->status.readpos = 0;
478   gpg->status.buffer = malloc (gpg->status.bufsize);
479   if (!gpg->status.buffer)
480     {
481       rc = gpg_error_from_syserror ();
482       goto leave;
483     }
484   /* In any case we need a status pipe - create it right here and
485      don't handle it with our generic gpgme_data_t mechanism.  */
486   if (_gpgme_io_pipe (gpg->status.fd, 1) == -1)
487     {
488       rc = gpg_error_from_syserror ();
489       goto leave;
490     }
491   if (_gpgme_io_set_close_notify (gpg->status.fd[0],
492                                   close_notify_handler, gpg)
493       || _gpgme_io_set_close_notify (gpg->status.fd[1],
494                                      close_notify_handler, gpg))
495     {
496       rc = gpg_error (GPG_ERR_GENERAL);
497       goto leave;
498     }
499   gpg->status.eof = 0;
500
501   if (home_dir)
502     {
503       rc = add_arg (gpg, "--homedir");
504       if (!rc)
505         rc = add_arg (gpg, home_dir);
506       if (rc)
507         goto leave;
508     }
509
510   rc = add_arg (gpg, "--status-fd");
511   if (rc)
512     goto leave;
513
514   {
515     char buf[25];
516     _gpgme_io_fd2str (buf, sizeof (buf), gpg->status.fd[1]);
517     rc = add_arg_with_locp (gpg, buf, &gpg->status.arg_loc);
518     if (rc)
519       goto leave;
520   }
521
522   rc = add_arg (gpg, "--no-tty");
523   if (!rc)
524     rc = add_arg (gpg, "--charset");
525   if (!rc)
526     rc = add_arg (gpg, "utf8");
527   if (!rc)
528     rc = add_arg (gpg, "--enable-progress-filter");
529   if (rc)
530     goto leave;
531
532   rc = _gpgme_getenv ("DISPLAY", &dft_display);
533   if (rc)
534     goto leave;
535   if (dft_display)
536     {
537       rc = add_arg (gpg, "--display");
538       if (!rc)
539         rc = add_arg (gpg, dft_display);
540
541       free (dft_display);
542       if (rc)
543         goto leave;
544     }
545
546   if (isatty (1))
547     {
548       int err;
549
550       err = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
551
552       /* Even though isatty() returns 1, ttyname_r() may fail in many
553          ways, e.g., when /dev/pts is not accessible under chroot.  */
554       if (!err)
555         {
556           if (*dft_ttyname)
557             {
558               rc = add_arg (gpg, "--ttyname");
559               if (!rc)
560                 rc = add_arg (gpg, dft_ttyname);
561             }
562           else
563             rc = 0;
564           if (!rc)
565             {
566               rc = _gpgme_getenv ("TERM", &dft_ttytype);
567               if (rc)
568                 goto leave;
569
570               if (dft_ttytype)
571                 {
572                   rc = add_arg (gpg, "--ttytype");
573                   if (!rc)
574                     rc = add_arg (gpg, dft_ttytype);
575                 }
576
577               free (dft_ttytype);
578             }
579           if (rc)
580             goto leave;
581         }
582     }
583
584  leave:
585   if (rc)
586     gpg_release (gpg);
587   else
588     *engine = gpg;
589   return rc;
590 }
591
592
593 static gpgme_error_t
594 gpg_set_locale (void *engine, int category, const char *value)
595 {
596   engine_gpg_t gpg = engine;
597
598   if (0)
599     ;
600 #ifdef LC_CTYPE
601   else if (category == LC_CTYPE)
602     {
603       if (gpg->lc_ctype)
604         {
605           free (gpg->lc_ctype);
606           gpg->lc_ctype = NULL;
607         }
608       if (value)
609         {
610           gpg->lc_ctype = strdup (value);
611           if (!gpg->lc_ctype)
612             return gpg_error_from_syserror ();
613         }
614     }
615 #endif
616 #ifdef LC_MESSAGES
617   else if (category == LC_MESSAGES)
618     {
619       if (gpg->lc_messages)
620         {
621           free (gpg->lc_messages);
622           gpg->lc_messages = NULL;
623         }
624       if (value)
625         {
626           gpg->lc_messages = strdup (value);
627           if (!gpg->lc_messages)
628             return gpg_error_from_syserror ();
629         }
630     }
631 #endif /* LC_MESSAGES */
632   else
633     return gpg_error (GPG_ERR_INV_VALUE);
634
635   return 0;
636 }
637
638 /* This sets a status callback for monitoring status lines before they
639  * are passed to a caller set handler.  */
640 static void
641 gpg_set_status_cb (void *engine, gpgme_status_cb_t cb, void *cb_value)
642 {
643   engine_gpg_t gpg = engine;
644
645   gpg->status.mon_cb = cb;
646   gpg->status.mon_cb_value = cb_value;
647 }
648
649
650 /* Note, that the status_handler is allowed to modifiy the args
651    value.  */
652 static void
653 gpg_set_status_handler (void *engine, engine_status_handler_t fnc,
654                         void *fnc_value)
655 {
656   engine_gpg_t gpg = engine;
657
658   gpg->status.fnc = fnc;
659   gpg->status.fnc_value = fnc_value;
660 }
661
662 /* Kludge to process --with-colon output.  */
663 static gpgme_error_t
664 gpg_set_colon_line_handler (void *engine, engine_colon_line_handler_t fnc,
665                             void *fnc_value)
666 {
667   engine_gpg_t gpg = engine;
668
669   gpg->colon.bufsize = 1024;
670   gpg->colon.readpos = 0;
671   gpg->colon.buffer = malloc (gpg->colon.bufsize);
672   if (!gpg->colon.buffer)
673     return gpg_error_from_syserror ();
674
675   if (_gpgme_io_pipe (gpg->colon.fd, 1) == -1)
676     {
677       int saved_err = gpg_error_from_syserror ();
678       free (gpg->colon.buffer);
679       gpg->colon.buffer = NULL;
680       return saved_err;
681     }
682   if (_gpgme_io_set_close_notify (gpg->colon.fd[0], close_notify_handler, gpg)
683       || _gpgme_io_set_close_notify (gpg->colon.fd[1],
684                                      close_notify_handler, gpg))
685     return gpg_error (GPG_ERR_GENERAL);
686   gpg->colon.eof = 0;
687   gpg->colon.fnc = fnc;
688   gpg->colon.fnc_value = fnc_value;
689   return 0;
690 }
691
692
693 static gpgme_error_t
694 command_handler (void *opaque, int fd)
695 {
696   struct io_cb_data *data = (struct io_cb_data *) opaque;
697   engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
698   gpgme_error_t err;
699   int processed = 0;
700   assert (gpg->cmd.used);
701   assert (gpg->cmd.code);
702   assert (gpg->cmd.fnc);
703
704   err = gpg->cmd.fnc (gpg->cmd.fnc_value, gpg->cmd.code, gpg->cmd.keyword, fd,
705                       &processed);
706
707   gpg->cmd.code = 0;
708   /* And sleep again until read_status will wake us up again.  */
709   /* XXX We must check if there are any more fds active after removing
710      this one.  */
711   (*gpg->io_cbs.remove) (gpg->fd_data_map[gpg->cmd.idx].tag);
712   gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
713   gpg->fd_data_map[gpg->cmd.idx].fd = -1;
714
715   if (err)
716     return err;
717
718   /* We always need to send at least a newline character.  */
719   if (!processed)
720     _gpgme_io_write (fd, "\n", 1);
721
722   return 0;
723 }
724
725
726
727 /* The Fnc will be called to get a value for one of the commands with
728    a key KEY.  If the Code passed to FNC is 0, the function may release
729    resources associated with the returned value from another call.  To
730    match such a second call to a first call, the returned value from
731    the first call is passed as keyword.  */
732 static gpgme_error_t
733 gpg_set_command_handler (void *engine, engine_command_handler_t fnc,
734                          void *fnc_value, gpgme_data_t linked_data)
735 {
736   engine_gpg_t gpg = engine;
737   gpgme_error_t rc;
738
739   rc = add_arg (gpg, "--command-fd");
740   if (rc)
741     return rc;
742
743   /* This is a hack.  We don't have a real data object.  The only
744      thing that matters is that we use something unique, so we use the
745      address of the cmd structure in the gpg object.  */
746   rc = add_data (gpg, (void *) &gpg->cmd, -2, 0);
747   if (rc)
748     return rc;
749
750   gpg->cmd.fnc = fnc;
751   gpg->cmd.cb_data = (void *) &gpg->cmd;
752   gpg->cmd.fnc_value = fnc_value;
753   gpg->cmd.linked_data = linked_data;
754   gpg->cmd.used = 1;
755   return 0;
756 }
757
758
759 static gpgme_error_t
760 build_argv (engine_gpg_t gpg, const char *pgmname)
761 {
762   gpgme_error_t err;
763   struct arg_and_data_s *a;
764   struct fd_data_map_s *fd_data_map;
765   size_t datac=0, argc=0;
766   char **argv;
767   int need_special = 0;
768   int use_agent = 0;
769   char *p;
770
771   if (_gpgme_in_gpg_one_mode ())
772     {
773       /* In GnuPG-1 mode we don't want to use the agent with a
774          malformed environment variable.  This is only a very basic
775          test but sufficient to make our life in the regression tests
776          easier.  With GnuPG-2 the agent is anyway required and on
777          modern installations GPG_AGENT_INFO is optional.  */
778       err = _gpgme_getenv ("GPG_AGENT_INFO", &p);
779       if (err)
780         return err;
781       use_agent = (p && strchr (p, ':'));
782       if (p)
783         free (p);
784     }
785
786   if (gpg->argv)
787     {
788       free_argv (gpg->argv);
789       gpg->argv = NULL;
790     }
791   if (gpg->fd_data_map)
792     {
793       free_fd_data_map (gpg->fd_data_map);
794       gpg->fd_data_map = NULL;
795     }
796
797   argc++;       /* For argv[0].  */
798   for (a = gpg->arglist; a; a = a->next)
799     {
800       argc++;
801       if (a->data)
802         {
803           /*fprintf (stderr, "build_argv: data\n" );*/
804           datac++;
805           if (a->dup_to == -1 && !a->print_fd)
806             need_special = 1;
807         }
808       else
809         {
810           /*   fprintf (stderr, "build_argv: arg=`%s'\n", a->arg );*/
811         }
812     }
813   if (need_special)
814     argc++;
815   if (use_agent)
816     argc++;
817   if (gpg->pinentry_mode)
818     argc++;
819   if (!gpg->cmd.used)
820     argc++;     /* --batch */
821   argc += 1;    /* --no-sk-comments */
822
823   argv = calloc (argc + 1, sizeof *argv);
824   if (!argv)
825     return gpg_error_from_syserror ();
826   fd_data_map = calloc (datac + 1, sizeof *fd_data_map);
827   if (!fd_data_map)
828     {
829       int saved_err = gpg_error_from_syserror ();
830       free_argv (argv);
831       return saved_err;
832     }
833
834   argc = datac = 0;
835   argv[argc] = strdup (_gpgme_get_basename (pgmname)); /* argv[0] */
836   if (!argv[argc])
837     {
838       int saved_err = gpg_error_from_syserror ();
839       free (fd_data_map);
840       free_argv (argv);
841       return saved_err;
842     }
843   argc++;
844   if (need_special)
845     {
846       argv[argc] = strdup ("--enable-special-filenames");
847       if (!argv[argc])
848         {
849           int saved_err = gpg_error_from_syserror ();
850           free (fd_data_map);
851           free_argv (argv);
852           return saved_err;
853         }
854       argc++;
855     }
856   if (use_agent)
857     {
858       argv[argc] = strdup ("--use-agent");
859       if (!argv[argc])
860         {
861           int saved_err = gpg_error_from_syserror ();
862           free (fd_data_map);
863           free_argv (argv);
864           return saved_err;
865         }
866       argc++;
867     }
868
869   if (gpg->pinentry_mode && have_gpg_version (gpg, "2.1.0"))
870     {
871       const char *s = NULL;
872       switch (gpg->pinentry_mode)
873         {
874         case GPGME_PINENTRY_MODE_DEFAULT: break;
875         case GPGME_PINENTRY_MODE_ASK:     s = "--pinentry-mode=ask"; break;
876         case GPGME_PINENTRY_MODE_CANCEL:  s = "--pinentry-mode=cancel"; break;
877         case GPGME_PINENTRY_MODE_ERROR:   s = "--pinentry-mode=error"; break;
878         case GPGME_PINENTRY_MODE_LOOPBACK:s = "--pinentry-mode=loopback"; break;
879         }
880       if (s)
881         {
882           argv[argc] = strdup (s);
883           if (!argv[argc])
884             {
885               int saved_err = gpg_error_from_syserror ();
886               free (fd_data_map);
887               free_argv (argv);
888               return saved_err;
889             }
890           argc++;
891         }
892     }
893
894   if (!gpg->cmd.used)
895     {
896       argv[argc] = strdup ("--batch");
897       if (!argv[argc])
898         {
899           int saved_err = gpg_error_from_syserror ();
900           free (fd_data_map);
901           free_argv (argv);
902           return saved_err;
903         }
904       argc++;
905     }
906   argv[argc] = strdup ("--no-sk-comments");
907   if (!argv[argc])
908     {
909       int saved_err = gpg_error_from_syserror ();
910       free (fd_data_map);
911       free_argv (argv);
912       return saved_err;
913     }
914   argc++;
915   for (a = gpg->arglist; a; a = a->next)
916     {
917       if (a->arg_locp)
918         *(a->arg_locp) = argc;
919
920       if (a->data)
921         {
922           /* Create a pipe to pass it down to gpg.  */
923           fd_data_map[datac].inbound = a->inbound;
924
925           /* Create a pipe.  */
926           {
927             int fds[2];
928
929             if (_gpgme_io_pipe (fds, fd_data_map[datac].inbound ? 1 : 0)
930                 == -1)
931               {
932                 int saved_errno = errno;
933                 free (fd_data_map);
934                 free_argv (argv);
935                 return gpg_error (saved_errno);
936               }
937             if (_gpgme_io_set_close_notify (fds[0],
938                                             close_notify_handler, gpg)
939                 || _gpgme_io_set_close_notify (fds[1],
940                                                close_notify_handler,
941                                                gpg))
942               {
943                 /* We leak fd_data_map and the fds.  This is not easy
944                    to avoid and given that we reach this here only
945                    after a malloc failure for a small object, it is
946                    probably better not to do anything.  */
947                 return gpg_error (GPG_ERR_GENERAL);
948               }
949             /* If the data_type is FD, we have to do a dup2 here.  */
950             if (fd_data_map[datac].inbound)
951               {
952                 fd_data_map[datac].fd       = fds[0];
953                 fd_data_map[datac].peer_fd  = fds[1];
954               }
955             else
956               {
957                 fd_data_map[datac].fd       = fds[1];
958                 fd_data_map[datac].peer_fd  = fds[0];
959               }
960           }
961
962           /* Hack to get hands on the fd later.  */
963           if (gpg->cmd.used)
964             {
965               if (gpg->cmd.cb_data == a->data)
966                 {
967                   assert (gpg->cmd.idx == -1);
968                   gpg->cmd.idx = datac;
969                 }
970               else if (gpg->cmd.linked_data == a->data)
971                 {
972                   assert (gpg->cmd.linked_idx == -1);
973                   gpg->cmd.linked_idx = datac;
974                 }
975             }
976
977           fd_data_map[datac].data = a->data;
978           fd_data_map[datac].dup_to = a->dup_to;
979
980           if (a->dup_to == -1)
981             {
982               char *ptr;
983               int buflen = 25;
984
985               argv[argc] = malloc (buflen);
986               if (!argv[argc])
987                 {
988                   int saved_err = gpg_error_from_syserror ();
989                   free (fd_data_map);
990                   free_argv (argv);
991                   return saved_err;
992                 }
993
994               ptr = argv[argc];
995               if (!a->print_fd)
996                 {
997                   *(ptr++) = '-';
998                   *(ptr++) = '&';
999                   buflen -= 2;
1000                 }
1001
1002               _gpgme_io_fd2str (ptr, buflen, fd_data_map[datac].peer_fd);
1003               fd_data_map[datac].arg_loc = argc;
1004               argc++;
1005             }
1006           datac++;
1007         }
1008       else
1009         {
1010           argv[argc] = strdup (a->arg);
1011           if (!argv[argc])
1012             {
1013               int saved_err = gpg_error_from_syserror ();
1014               free (fd_data_map);
1015               free_argv (argv);
1016               return saved_err;
1017             }
1018             argc++;
1019         }
1020     }
1021
1022   gpg->argv = argv;
1023   gpg->fd_data_map = fd_data_map;
1024   return 0;
1025 }
1026
1027
1028 static gpgme_error_t
1029 add_io_cb (engine_gpg_t gpg, int fd, int dir, gpgme_io_cb_t handler, void *data,
1030            void **tag)
1031 {
1032   gpgme_error_t err;
1033
1034   err = (*gpg->io_cbs.add) (gpg->io_cbs.add_priv, fd, dir, handler, data, tag);
1035   if (err)
1036     return err;
1037   if (!dir)
1038     /* FIXME Kludge around poll() problem.  */
1039     err = _gpgme_io_set_nonblocking (fd);
1040   return err;
1041 }
1042
1043
1044 /* Handle the status output of GnuPG.  This function does read entire
1045    lines and passes them as C strings to the callback function (we can
1046    use C Strings because the status output is always UTF-8 encoded).
1047    Of course we have to buffer the lines to cope with long lines
1048    e.g. with a large user ID.  Note: We can optimize this to only cope
1049    with status line code we know about and skip all other stuff
1050    without buffering (i.e. without extending the buffer).  */
1051 static gpgme_error_t
1052 read_status (engine_gpg_t gpg)
1053 {
1054   char *p;
1055   int nread;
1056   size_t bufsize = gpg->status.bufsize;
1057   char *buffer = gpg->status.buffer;
1058   size_t readpos = gpg->status.readpos;
1059   gpgme_error_t err;
1060
1061   assert (buffer);
1062   if (bufsize - readpos < 256)
1063     {
1064       /* Need more room for the read.  */
1065       bufsize += 1024;
1066       buffer = realloc (buffer, bufsize);
1067       if (!buffer)
1068         return gpg_error_from_syserror ();
1069     }
1070
1071   nread = _gpgme_io_read (gpg->status.fd[0],
1072                           buffer + readpos, bufsize-readpos);
1073   if (nread == -1)
1074     return gpg_error_from_syserror ();
1075
1076   if (!nread)
1077     {
1078       err = 0;
1079       gpg->status.eof = 1;
1080       if (gpg->status.mon_cb)
1081         err = gpg->status.mon_cb (gpg->status.mon_cb_value,
1082                                   GPGME_STATUS_EOF, "");
1083       if (gpg->status.fnc)
1084         err = gpg->status.fnc (gpg->status.fnc_value, GPGME_STATUS_EOF, "");
1085
1086       return err;
1087     }
1088
1089   while (nread > 0)
1090     {
1091       for (p = buffer + readpos; nread; nread--, p++)
1092         {
1093           if (*p == '\n')
1094             {
1095               /* (we require that the last line is terminated by a LF) */
1096               if (p > buffer && p[-1] == '\r')
1097                 p[-1] = 0;
1098               *p = 0;
1099               if (!strncmp (buffer, "[GNUPG:] ", 9)
1100                   && buffer[9] >= 'A' && buffer[9] <= 'Z')
1101                 {
1102                   char *rest;
1103                   gpgme_status_code_t r;
1104
1105                   rest = strchr (buffer + 9, ' ');
1106                   if (!rest)
1107                     rest = p; /* Set to an empty string.  */
1108                   else
1109                     *rest++ = 0;
1110
1111                   r = _gpgme_parse_status (buffer + 9);
1112                   if (gpg->status.mon_cb && r != GPGME_STATUS_PROGRESS)
1113                     {
1114                       /* Note that we call the monitor even if we do
1115                        * not know the status code (r < 0).  */
1116                       err = gpg->status.mon_cb (gpg->status.mon_cb_value,
1117                                                 buffer + 9, rest);
1118                       if (err)
1119                         return err;
1120                     }
1121                   if (r >= 0)
1122                     {
1123                       if (gpg->cmd.used
1124                           && (r == GPGME_STATUS_GET_BOOL
1125                               || r == GPGME_STATUS_GET_LINE
1126                               || r == GPGME_STATUS_GET_HIDDEN))
1127                         {
1128                           gpg->cmd.code = r;
1129                           if (gpg->cmd.keyword)
1130                             free (gpg->cmd.keyword);
1131                           gpg->cmd.keyword = strdup (rest);
1132                           if (!gpg->cmd.keyword)
1133                             return gpg_error_from_syserror ();
1134                           /* This should be the last thing we have
1135                              received and the next thing will be that
1136                              the command handler does its action.  */
1137                           if (nread > 1)
1138                             TRACE0 (DEBUG_CTX, "gpgme:read_status", 0,
1139                                     "error: unexpected data");
1140
1141                           add_io_cb (gpg, gpg->cmd.fd, 0,
1142                                      command_handler, gpg,
1143                                      &gpg->fd_data_map[gpg->cmd.idx].tag);
1144                           gpg->fd_data_map[gpg->cmd.idx].fd = gpg->cmd.fd;
1145                           gpg->cmd.fd = -1;
1146                         }
1147                       else if (gpg->status.fnc)
1148                         {
1149                           err = gpg->status.fnc (gpg->status.fnc_value,
1150                                                  r, rest);
1151                           if (err)
1152                             return err;
1153                         }
1154
1155                       if (r == GPGME_STATUS_END_STREAM)
1156                         {
1157                           if (gpg->cmd.used)
1158                             {
1159                               /* Before we can actually add the
1160                                  command fd, we might have to flush
1161                                  the linked output data pipe.  */
1162                               if (gpg->cmd.linked_idx != -1
1163                                   && gpg->fd_data_map[gpg->cmd.linked_idx].fd
1164                                   != -1)
1165                                 {
1166                                   struct io_select_fd_s fds;
1167                                   fds.fd =
1168                                     gpg->fd_data_map[gpg->cmd.linked_idx].fd;
1169                                   fds.for_read = 1;
1170                                   fds.for_write = 0;
1171                                   fds.opaque = NULL;
1172                                   do
1173                                     {
1174                                       fds.signaled = 0;
1175                                       _gpgme_io_select (&fds, 1, 1);
1176                                       if (fds.signaled)
1177                                         _gpgme_data_inbound_handler
1178                                           (gpg->cmd.linked_data, fds.fd);
1179                                     }
1180                                   while (fds.signaled);
1181                                 }
1182
1183                               /* XXX We must check if there are any
1184                                  more fds active after removing this
1185                                  one.  */
1186                               (*gpg->io_cbs.remove)
1187                                 (gpg->fd_data_map[gpg->cmd.idx].tag);
1188                               gpg->cmd.fd = gpg->fd_data_map[gpg->cmd.idx].fd;
1189                               gpg->fd_data_map[gpg->cmd.idx].fd = -1;
1190                             }
1191                         }
1192                     }
1193                 }
1194               /* To reuse the buffer for the next line we have to
1195                  shift the remaining data to the buffer start and
1196                  restart the loop Hmmm: We can optimize this function
1197                  by looking forward in the buffer to see whether a
1198                  second complete line is available and in this case
1199                  avoid the memmove for this line.  */
1200               nread--; p++;
1201               if (nread)
1202                 memmove (buffer, p, nread);
1203               readpos = 0;
1204               break; /* the for loop */
1205             }
1206           else
1207             readpos++;
1208         }
1209     }
1210
1211   /* Update the gpg object.  */
1212   gpg->status.bufsize = bufsize;
1213   gpg->status.buffer = buffer;
1214   gpg->status.readpos = readpos;
1215   return 0;
1216 }
1217
1218
1219 static gpgme_error_t
1220 status_handler (void *opaque, int fd)
1221 {
1222   struct io_cb_data *data = (struct io_cb_data *) opaque;
1223   engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
1224   int err;
1225
1226   assert (fd == gpg->status.fd[0]);
1227   err = read_status (gpg);
1228   if (err)
1229     return err;
1230   if (gpg->status.eof)
1231     _gpgme_io_close (fd);
1232   return 0;
1233 }
1234
1235
1236 static gpgme_error_t
1237 read_colon_line (engine_gpg_t gpg)
1238 {
1239   char *p;
1240   int nread;
1241   size_t bufsize = gpg->colon.bufsize;
1242   char *buffer = gpg->colon.buffer;
1243   size_t readpos = gpg->colon.readpos;
1244
1245   assert (buffer);
1246   if (bufsize - readpos < 256)
1247     {
1248       /* Need more room for the read.  */
1249       bufsize += 1024;
1250       buffer = realloc (buffer, bufsize);
1251       if (!buffer)
1252         return gpg_error_from_syserror ();
1253     }
1254
1255   nread = _gpgme_io_read (gpg->colon.fd[0], buffer+readpos, bufsize-readpos);
1256   if (nread == -1)
1257     return gpg_error_from_syserror ();
1258
1259   if (!nread)
1260     {
1261       gpg->colon.eof = 1;
1262       assert (gpg->colon.fnc);
1263       gpg->colon.fnc (gpg->colon.fnc_value, NULL);
1264       return 0;
1265     }
1266
1267   while (nread > 0)
1268     {
1269       for (p = buffer + readpos; nread; nread--, p++)
1270         {
1271           if ( *p == '\n' )
1272             {
1273               /* (we require that the last line is terminated by a LF)
1274                  and we skip empty lines.  Note: we use UTF8 encoding
1275                  and escaping of special characters.  We require at
1276                  least one colon to cope with some other printed
1277                  information.  */
1278               *p = 0;
1279               if (*buffer && strchr (buffer, ':'))
1280                 {
1281                   char *line = NULL;
1282
1283                   if (gpg->colon.preprocess_fnc)
1284                     {
1285                       gpgme_error_t err;
1286
1287                       err = gpg->colon.preprocess_fnc (buffer, &line);
1288                       if (err)
1289                         return err;
1290                     }
1291
1292                   assert (gpg->colon.fnc);
1293                   if (line)
1294                     {
1295                       char *linep = line;
1296                       char *endp;
1297
1298                       do
1299                         {
1300                           endp = strchr (linep, '\n');
1301                           if (endp)
1302                             *endp++ = 0;
1303                           gpg->colon.fnc (gpg->colon.fnc_value, linep);
1304                           linep = endp;
1305                         }
1306                       while (linep && *linep);
1307
1308                       free (line);
1309                     }
1310                   else
1311                     gpg->colon.fnc (gpg->colon.fnc_value, buffer);
1312                 }
1313
1314               /* To reuse the buffer for the next line we have to
1315                  shift the remaining data to the buffer start and
1316                  restart the loop Hmmm: We can optimize this function
1317                  by looking forward in the buffer to see whether a
1318                  second complete line is available and in this case
1319                  avoid the memmove for this line.  */
1320               nread--; p++;
1321               if (nread)
1322                 memmove (buffer, p, nread);
1323               readpos = 0;
1324               break; /* The for loop.  */
1325             }
1326           else
1327             readpos++;
1328         }
1329     }
1330
1331   /* Update the gpg object.  */
1332   gpg->colon.bufsize = bufsize;
1333   gpg->colon.buffer  = buffer;
1334   gpg->colon.readpos = readpos;
1335   return 0;
1336 }
1337
1338
1339 /* This colonline handler thing is not the clean way to do it.  It
1340    might be better to enhance the gpgme_data_t object to act as a wrapper
1341    for a callback.  Same goes for the status thing.  For now we use
1342    this thing here because it is easier to implement.  */
1343 static gpgme_error_t
1344 colon_line_handler (void *opaque, int fd)
1345 {
1346   struct io_cb_data *data = (struct io_cb_data *) opaque;
1347   engine_gpg_t gpg = (engine_gpg_t) data->handler_value;
1348   gpgme_error_t rc = 0;
1349
1350   assert (fd == gpg->colon.fd[0]);
1351   rc = read_colon_line (gpg);
1352   if (rc)
1353     return rc;
1354   if (gpg->colon.eof)
1355     _gpgme_io_close (fd);
1356   return 0;
1357 }
1358
1359
1360 static gpgme_error_t
1361 start (engine_gpg_t gpg)
1362 {
1363   gpgme_error_t rc;
1364   int i, n;
1365   int status;
1366   struct spawn_fd_item_s *fd_list;
1367   pid_t pid;
1368   const char *pgmname;
1369
1370   if (!gpg)
1371     return gpg_error (GPG_ERR_INV_VALUE);
1372
1373   if (!gpg->file_name && !_gpgme_get_default_gpg_name ())
1374     return trace_gpg_error (GPG_ERR_INV_ENGINE);
1375
1376   if (gpg->lc_ctype)
1377     {
1378       rc = add_arg_ext (gpg, gpg->lc_ctype, 1);
1379       if (!rc)
1380         rc = add_arg_ext (gpg, "--lc-ctype", 1);
1381       if (rc)
1382         return rc;
1383     }
1384
1385   if (gpg->lc_messages)
1386     {
1387       rc = add_arg_ext (gpg, gpg->lc_messages, 1);
1388       if (!rc)
1389         rc = add_arg_ext (gpg, "--lc-messages", 1);
1390       if (rc)
1391         return rc;
1392     }
1393
1394   pgmname = gpg->file_name ? gpg->file_name : _gpgme_get_default_gpg_name ();
1395   rc = build_argv (gpg, pgmname);
1396   if (rc)
1397     return rc;
1398
1399   /* status_fd, colon_fd and end of list.  */
1400   n = 3;
1401   for (i = 0; gpg->fd_data_map[i].data; i++)
1402     n++;
1403   fd_list = calloc (n, sizeof *fd_list);
1404   if (! fd_list)
1405     return gpg_error_from_syserror ();
1406
1407   /* Build the fd list for the child.  */
1408   n = 0;
1409   fd_list[n].fd = gpg->status.fd[1];
1410   fd_list[n].dup_to = -1;
1411   fd_list[n].arg_loc = gpg->status.arg_loc;
1412   n++;
1413   if (gpg->colon.fnc)
1414     {
1415       fd_list[n].fd = gpg->colon.fd[1];
1416       fd_list[n].dup_to = 1;
1417       n++;
1418     }
1419   for (i = 0; gpg->fd_data_map[i].data; i++)
1420     {
1421       fd_list[n].fd = gpg->fd_data_map[i].peer_fd;
1422       fd_list[n].dup_to = gpg->fd_data_map[i].dup_to;
1423       fd_list[n].arg_loc = gpg->fd_data_map[i].arg_loc;
1424       n++;
1425     }
1426   fd_list[n].fd = -1;
1427   fd_list[n].dup_to = -1;
1428
1429   status = _gpgme_io_spawn (pgmname, gpg->argv,
1430                             (IOSPAWN_FLAG_DETACHED |IOSPAWN_FLAG_ALLOW_SET_FG),
1431                             fd_list, NULL, NULL, &pid);
1432   {
1433     int saved_err = gpg_error_from_syserror ();
1434     free (fd_list);
1435     if (status == -1)
1436       return saved_err;
1437   }
1438
1439   /*_gpgme_register_term_handler ( closure, closure_value, pid );*/
1440
1441   rc = add_io_cb (gpg, gpg->status.fd[0], 1, status_handler, gpg,
1442                   &gpg->status.tag);
1443   if (rc)
1444     /* FIXME: kill the child */
1445     return rc;
1446
1447   if (gpg->colon.fnc)
1448     {
1449       assert (gpg->colon.fd[0] != -1);
1450       rc = add_io_cb (gpg, gpg->colon.fd[0], 1, colon_line_handler, gpg,
1451                       &gpg->colon.tag);
1452       if (rc)
1453         /* FIXME: kill the child */
1454         return rc;
1455     }
1456
1457   for (i = 0; gpg->fd_data_map[i].data; i++)
1458     {
1459       if (gpg->cmd.used && i == gpg->cmd.idx)
1460         {
1461           /* Park the cmd fd.  */
1462           gpg->cmd.fd = gpg->fd_data_map[i].fd;
1463           gpg->fd_data_map[i].fd = -1;
1464         }
1465       else
1466         {
1467           rc = add_io_cb (gpg, gpg->fd_data_map[i].fd,
1468                           gpg->fd_data_map[i].inbound,
1469                           gpg->fd_data_map[i].inbound
1470                           ? _gpgme_data_inbound_handler
1471                           : _gpgme_data_outbound_handler,
1472                           gpg->fd_data_map[i].data, &gpg->fd_data_map[i].tag);
1473
1474           if (rc)
1475             /* FIXME: kill the child */
1476             return rc;
1477         }
1478     }
1479
1480   gpg_io_event (gpg, GPGME_EVENT_START, NULL);
1481
1482   /* fixme: check what data we can release here */
1483   return 0;
1484 }
1485
1486
1487 /* Add the --input-size-hint option if requested.  */
1488 static gpgme_error_t
1489 add_input_size_hint (engine_gpg_t gpg, gpgme_data_t data)
1490 {
1491   gpgme_error_t err;
1492   gpgme_off_t value = _gpgme_data_get_size_hint (data);
1493   char numbuf[50];  /* Large enough for even 2^128 in base-10.  */
1494   char *p;
1495
1496   if (!value || !have_gpg_version (gpg, "2.1.15"))
1497     return 0;
1498
1499   err = add_arg (gpg, "--input-size-hint");
1500   if (!err)
1501     {
1502       p = numbuf + sizeof numbuf;
1503       *--p = 0;
1504       do
1505         {
1506           *--p = '0' + (value % 10);
1507           value /= 10;
1508         }
1509       while (value);
1510       err = add_arg (gpg, p);
1511     }
1512   return err;
1513 }
1514
1515
1516 static gpgme_error_t
1517 gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
1518 {
1519   engine_gpg_t gpg = engine;
1520   gpgme_error_t err;
1521
1522   err = add_arg (gpg, "--decrypt");
1523
1524   /* Tell the gpg object about the data.  */
1525   if (!err)
1526     err = add_arg (gpg, "--output");
1527   if (!err)
1528     err = add_arg (gpg, "-");
1529   if (!err)
1530     err = add_data (gpg, plain, 1, 1);
1531   if (!err)
1532     err = add_input_size_hint (gpg, ciph);
1533   if (!err)
1534     err = add_arg (gpg, "--");
1535   if (!err)
1536     err = add_data (gpg, ciph, -1, 0);
1537
1538   if (!err)
1539     err = start (gpg);
1540   return err;
1541 }
1542
1543 static gpgme_error_t
1544 gpg_delete (void *engine, gpgme_key_t key, int allow_secret)
1545 {
1546   engine_gpg_t gpg = engine;
1547   gpgme_error_t err;
1548
1549   err = add_arg (gpg, allow_secret ? "--delete-secret-and-public-key"
1550                  : "--delete-key");
1551   if (!err)
1552     err = add_arg (gpg, "--");
1553   if (!err)
1554     {
1555       if (!key->subkeys || !key->subkeys->fpr)
1556         return gpg_error (GPG_ERR_INV_VALUE);
1557       else
1558         err = add_arg (gpg, key->subkeys->fpr);
1559     }
1560
1561   if (!err)
1562     err = start (gpg);
1563   return err;
1564 }
1565
1566
1567 static gpgme_error_t
1568 gpg_passwd (void *engine, gpgme_key_t key, unsigned int flags)
1569 {
1570   engine_gpg_t gpg = engine;
1571   gpgme_error_t err;
1572
1573   if (!key || !key->subkeys || !key->subkeys->fpr)
1574     return gpg_error (GPG_ERR_INV_CERT_OBJ);
1575
1576   err = add_arg (gpg, "--passwd");
1577   if (!err)
1578     err = add_arg (gpg, key->subkeys->fpr);
1579   if (!err)
1580     err = start (gpg);
1581   return err;
1582 }
1583
1584
1585 static gpgme_error_t
1586 append_args_from_signers (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1587 {
1588   gpgme_error_t err = 0;
1589   int i;
1590   gpgme_key_t key;
1591
1592   for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++)
1593     {
1594       const char *s = key->subkeys ? key->subkeys->keyid : NULL;
1595       if (s)
1596         {
1597           if (!err)
1598             err = add_arg (gpg, "-u");
1599           if (!err)
1600             err = add_arg (gpg, s);
1601         }
1602       gpgme_key_unref (key);
1603       if (err) break;
1604     }
1605   return err;
1606 }
1607
1608
1609 static gpgme_error_t
1610 append_args_from_sig_notations (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
1611 {
1612   gpgme_error_t err = 0;
1613   gpgme_sig_notation_t notation;
1614
1615   notation = gpgme_sig_notation_get (ctx);
1616
1617   while (!err && notation)
1618     {
1619       if (notation->name
1620           && !(notation->flags & GPGME_SIG_NOTATION_HUMAN_READABLE))
1621         err = gpg_error (GPG_ERR_INV_VALUE);
1622       else if (notation->name)
1623         {
1624           char *arg;
1625
1626           /* Maximum space needed is one byte for the "critical" flag,
1627              the name, one byte for '=', the value, and a terminating
1628              '\0'.  */
1629
1630           arg = malloc (1 + notation->name_len + 1 + notation->value_len + 1);
1631           if (!arg)
1632             err = gpg_error_from_syserror ();
1633
1634           if (!err)
1635             {
1636               char *argp = arg;
1637
1638               if (notation->critical)
1639                 *(argp++) = '!';
1640
1641               memcpy (argp, notation->name, notation->name_len);
1642               argp += notation->name_len;
1643
1644               *(argp++) = '=';
1645
1646               /* We know that notation->name is '\0' terminated.  */
1647               strcpy (argp, notation->value);
1648             }
1649
1650           if (!err)
1651             err = add_arg (gpg, "--sig-notation");
1652           if (!err)
1653             err = add_arg (gpg, arg);
1654
1655           if (arg)
1656             free (arg);
1657         }
1658       else
1659         {
1660           /* This is a policy URL.  */
1661
1662           char *value;
1663
1664           if (notation->critical)
1665             {
1666               value = malloc (1 + notation->value_len + 1);
1667               if (!value)
1668                 err = gpg_error_from_syserror ();
1669               else
1670                 {
1671                   value[0] = '!';
1672                   /* We know that notation->value is '\0' terminated.  */
1673                   strcpy (&value[1], notation->value);
1674                 }
1675             }
1676           else
1677             value = notation->value;
1678
1679           if (!err)
1680             err = add_arg (gpg, "--sig-policy-url");
1681           if (!err)
1682             err = add_arg (gpg, value);
1683
1684           if (value != notation->value)
1685             free (value);
1686         }
1687
1688       notation = notation->next;
1689     }
1690   return err;
1691 }
1692
1693
1694 static gpgme_error_t
1695 gpg_edit (void *engine, int type, gpgme_key_t key, gpgme_data_t out,
1696           gpgme_ctx_t ctx /* FIXME */)
1697 {
1698   engine_gpg_t gpg = engine;
1699   gpgme_error_t err;
1700
1701   err = add_arg (gpg, "--with-colons");
1702   if (!err)
1703     err = append_args_from_signers (gpg, ctx);
1704   if (!err)
1705   err = add_arg (gpg, type == 0 ? "--edit-key" : "--card-edit");
1706   if (!err)
1707     err = add_data (gpg, out, 1, 1);
1708   if (!err)
1709     err = add_arg (gpg, "--");
1710   if (!err && type == 0)
1711     {
1712       const char *s = key->subkeys ? key->subkeys->fpr : NULL;
1713       if (!s)
1714         err = gpg_error (GPG_ERR_INV_VALUE);
1715       else
1716         err = add_arg (gpg, s);
1717     }
1718   if (!err)
1719     err = start (gpg);
1720
1721   return err;
1722 }
1723
1724
1725 static gpgme_error_t
1726 append_args_from_recipients (engine_gpg_t gpg, gpgme_key_t recp[])
1727 {
1728   gpgme_error_t err = 0;
1729   int i = 0;
1730
1731   while (recp[i])
1732     {
1733       if (!recp[i]->subkeys || !recp[i]->subkeys->fpr)
1734         err = gpg_error (GPG_ERR_INV_VALUE);
1735       if (!err)
1736         err = add_arg (gpg, "-r");
1737       if (!err)
1738         err = add_arg (gpg, recp[i]->subkeys->fpr);
1739       if (err)
1740         break;
1741       i++;
1742     }
1743   return err;
1744 }
1745
1746
1747 static gpgme_error_t
1748 gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
1749              gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
1750 {
1751   engine_gpg_t gpg = engine;
1752   gpgme_error_t err = 0;
1753
1754   if (recp)
1755     err = add_arg (gpg, "--encrypt");
1756
1757   if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || !recp))
1758     err = add_arg (gpg, "--symmetric");
1759
1760   if (!err && use_armor)
1761     err = add_arg (gpg, "--armor");
1762
1763   if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS))
1764     err = add_arg (gpg, "--compress-algo=none");
1765
1766   if (gpgme_data_get_encoding (plain) == GPGME_DATA_ENCODING_MIME
1767       && have_gpg_version (gpg, "2.1.14"))
1768     err = add_arg (gpg, "--mimemode");
1769
1770   if (recp)
1771     {
1772       /* If we know that all recipients are valid (full or ultimate trust)
1773          we can suppress further checks.  */
1774       if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1775         err = add_arg (gpg, "--always-trust");
1776
1777       if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
1778         err = add_arg (gpg, "--no-encrypt-to");
1779
1780       if (!err)
1781         err = append_args_from_recipients (gpg, recp);
1782     }
1783
1784   /* Tell the gpg object about the data.  */
1785   if (!err)
1786     err = add_arg (gpg, "--output");
1787   if (!err)
1788     err = add_arg (gpg, "-");
1789   if (!err)
1790     err = add_data (gpg, ciph, 1, 1);
1791   if (gpgme_data_get_file_name (plain))
1792     {
1793       if (!err)
1794         err = add_arg (gpg, "--set-filename");
1795       if (!err)
1796         err = add_arg (gpg, gpgme_data_get_file_name (plain));
1797     }
1798   if (!err)
1799     err = add_input_size_hint (gpg, plain);
1800   if (!err)
1801     err = add_arg (gpg, "--");
1802   if (!err)
1803     err = add_data (gpg, plain, -1, 0);
1804
1805   if (!err)
1806     err = start (gpg);
1807
1808   return err;
1809 }
1810
1811
1812 static gpgme_error_t
1813 gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
1814                   gpgme_encrypt_flags_t flags, gpgme_data_t plain,
1815                   gpgme_data_t ciph, int use_armor,
1816                   gpgme_ctx_t ctx /* FIXME */)
1817 {
1818   engine_gpg_t gpg = engine;
1819   gpgme_error_t err = 0;
1820
1821   if (recp)
1822     err = add_arg (gpg, "--encrypt");
1823
1824   if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || !recp))
1825     err = add_arg (gpg, "--symmetric");
1826
1827   if (!err)
1828     err = add_arg (gpg, "--sign");
1829   if (!err && use_armor)
1830     err = add_arg (gpg, "--armor");
1831
1832   if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS))
1833     err = add_arg (gpg, "--compress-algo=none");
1834
1835   if (gpgme_data_get_encoding (plain) == GPGME_DATA_ENCODING_MIME
1836       && have_gpg_version (gpg, "2.1.14"))
1837     err = add_arg (gpg, "--mimemode");
1838
1839   if (recp)
1840     {
1841       /* If we know that all recipients are valid (full or ultimate trust)
1842          we can suppress further checks.  */
1843       if (!err && (flags & GPGME_ENCRYPT_ALWAYS_TRUST))
1844         err = add_arg (gpg, "--always-trust");
1845
1846       if (!err && (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
1847         err = add_arg (gpg, "--no-encrypt-to");
1848
1849       if (!err)
1850         err = append_args_from_recipients (gpg, recp);
1851     }
1852
1853   if (!err)
1854     err = append_args_from_signers (gpg, ctx);
1855
1856   if (!err)
1857     err = append_args_from_sig_notations (gpg, ctx);
1858
1859   /* Tell the gpg object about the data.  */
1860   if (!err)
1861     err = add_arg (gpg, "--output");
1862   if (!err)
1863     err = add_arg (gpg, "-");
1864   if (!err)
1865     err = add_data (gpg, ciph, 1, 1);
1866   if (gpgme_data_get_file_name (plain))
1867     {
1868       if (!err)
1869         err = add_arg (gpg, "--set-filename");
1870       if (!err)
1871         err = add_arg (gpg, gpgme_data_get_file_name (plain));
1872     }
1873   if (!err)
1874     err = add_input_size_hint (gpg, plain);
1875   if (!err)
1876     err = add_arg (gpg, "--");
1877   if (!err)
1878     err = add_data (gpg, plain, -1, 0);
1879
1880   if (!err)
1881     err = start (gpg);
1882
1883   return err;
1884 }
1885
1886
1887 static gpgme_error_t
1888 export_common (engine_gpg_t gpg, gpgme_export_mode_t mode,
1889                gpgme_data_t keydata, int use_armor)
1890 {
1891   gpgme_error_t err = 0;
1892
1893   if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
1894                 |GPGME_EXPORT_MODE_MINIMAL
1895                 |GPGME_EXPORT_MODE_SECRET)))
1896     return gpg_error (GPG_ERR_NOT_SUPPORTED);
1897
1898   if ((mode & GPGME_EXPORT_MODE_MINIMAL))
1899     err = add_arg (gpg, "--export-options=export-minimal");
1900
1901   if (err)
1902     ;
1903   else if ((mode & GPGME_EXPORT_MODE_EXTERN))
1904     {
1905       err = add_arg (gpg, "--send-keys");
1906     }
1907   else
1908     {
1909       if ((mode & GPGME_EXPORT_MODE_SECRET))
1910         err = add_arg (gpg, "--export-secret-keys");
1911       else
1912         err = add_arg (gpg, "--export");
1913       if (!err && use_armor)
1914         err = add_arg (gpg, "--armor");
1915       if (!err)
1916         err = add_data (gpg, keydata, 1, 1);
1917     }
1918   if (!err)
1919     err = add_arg (gpg, "--");
1920
1921   return err;
1922 }
1923
1924
1925 static gpgme_error_t
1926 gpg_export (void *engine, const char *pattern, gpgme_export_mode_t mode,
1927             gpgme_data_t keydata, int use_armor)
1928 {
1929   engine_gpg_t gpg = engine;
1930   gpgme_error_t err;
1931
1932   err = export_common (gpg, mode, keydata, use_armor);
1933
1934   if (!err && pattern && *pattern)
1935     err = add_arg (gpg, pattern);
1936
1937   if (!err)
1938     err = start (gpg);
1939
1940   return err;
1941 }
1942
1943
1944 static gpgme_error_t
1945 gpg_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
1946                 gpgme_data_t keydata, int use_armor)
1947 {
1948   engine_gpg_t gpg = engine;
1949   gpgme_error_t err;
1950
1951   err = export_common (gpg, mode, keydata, use_armor);
1952
1953   if (pattern)
1954     {
1955       while (!err && *pattern && **pattern)
1956         err = add_arg (gpg, *(pattern++));
1957     }
1958
1959   if (!err)
1960     err = start (gpg);
1961
1962   return err;
1963 }
1964
1965
1966 static gpgme_error_t
1967 gpg_createkey_from_param (engine_gpg_t gpg,
1968                           gpgme_data_t help_data, int use_armor)
1969 {
1970   gpgme_error_t err;
1971
1972   err = add_arg (gpg, "--gen-key");
1973   if (!err && use_armor)
1974     err = add_arg (gpg, "--armor");
1975   if (!err)
1976     err = add_arg (gpg, "--");
1977   if (!err)
1978     err = add_data (gpg, help_data, -1, 0);
1979   if (!err)
1980     err = start (gpg);
1981   return err;
1982 }
1983
1984
1985 /* This is used for gpg versions which do not support the quick-genkey
1986  * command to emulate the gpgme_op_createkey API.  */
1987 static gpgme_error_t
1988 gpg_createkey_legacy (engine_gpg_t gpg,
1989                const char *userid, const char *algo,
1990                unsigned long expires,
1991                unsigned int flags,
1992                int use_armor)
1993 {
1994   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1995 }
1996
1997
1998 static gpgme_error_t
1999 gpg_createkey (engine_gpg_t gpg,
2000                const char *userid, const char *algo,
2001                unsigned long expires,
2002                unsigned int flags,
2003                int use_armor)
2004 {
2005   gpgme_error_t err;
2006
2007   err = add_arg (gpg, "--quick-gen-key");
2008   if (!err && use_armor)
2009     err = add_arg (gpg, "--armor");
2010   if (!err && (flags & GPGME_CREATE_NOPASSWD))
2011     {
2012       err = add_arg (gpg, "--passphrase");
2013       if (!err)
2014         err = add_arg (gpg, "");
2015     }
2016   if (!err && (flags & GPGME_CREATE_FORCE))
2017     err = add_arg (gpg, "--yes");
2018   if (!err)
2019     err = add_arg (gpg, "--");
2020   if (!err)
2021     err = add_arg (gpg, userid);
2022
2023   /* This condition is only required to allow the use of gpg < 2.1.16 */
2024   if (algo
2025       || (flags & (GPGME_CREATE_SIGN | GPGME_CREATE_ENCR
2026                    | GPGME_CREATE_CERT | GPGME_CREATE_AUTH))
2027       || expires)
2028     {
2029
2030       if (!err)
2031         err = add_arg (gpg, algo? algo : "default");
2032       if (!err)
2033         {
2034           char tmpbuf[5*4+1];
2035           snprintf (tmpbuf, sizeof tmpbuf, "%s%s%s%s",
2036                     (flags & GPGME_CREATE_SIGN)? " sign":"",
2037                     (flags & GPGME_CREATE_ENCR)? " encr":"",
2038                     (flags & GPGME_CREATE_CERT)? " cert":"",
2039                     (flags & GPGME_CREATE_AUTH)? " auth":"");
2040           err = add_arg (gpg, *tmpbuf? tmpbuf : "default");
2041         }
2042       if (!err && expires)
2043         {
2044           char tmpbuf[8+20];
2045           snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expires);
2046           err = add_arg (gpg, tmpbuf);
2047         }
2048     }
2049
2050   if (!err)
2051     err = start (gpg);
2052   return err;
2053 }
2054
2055
2056 static gpgme_error_t
2057 gpg_addkey (engine_gpg_t gpg,
2058             const char *algo,
2059             unsigned long expires,
2060             gpgme_key_t key,
2061             unsigned int flags,
2062             int use_armor)
2063 {
2064   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2065 }
2066
2067
2068 static gpgme_error_t
2069 gpg_adduid (engine_gpg_t gpg,
2070             const char *userid,
2071             unsigned int flags,
2072             int use_armor)
2073 {
2074   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2075 }
2076
2077
2078 static gpgme_error_t
2079 gpg_genkey (void *engine,
2080             const char *userid, const char *algo,
2081             unsigned long reserved, unsigned long expires,
2082             gpgme_key_t key, unsigned int flags,
2083             gpgme_data_t help_data, int use_armor,
2084             gpgme_data_t pubkey, gpgme_data_t seckey)
2085 {
2086   engine_gpg_t gpg = engine;
2087   gpgme_error_t err;
2088
2089   (void)reserved;
2090
2091   if (!gpg)
2092     return gpg_error (GPG_ERR_INV_VALUE);
2093
2094   /* If HELP_DATA is given the use of the old interface
2095    * (gpgme_op_genkey) has been requested.  The other modes are:
2096    *
2097    *  USERID && !KEY          - Create a new keyblock.
2098    * !USERID &&  KEY          - Add a new subkey to KEY (gpg >= 2.1.14)
2099    *  USERID &&  KEY && !ALGO - Add a new user id to KEY (gpg >= 2.1.14).
2100    *
2101    */
2102   if (help_data)
2103     {
2104       /* We need a special mechanism to get the fd of a pipe here, so
2105          that we can use this for the %pubring and %secring
2106          parameters.  We don't have this yet, so we implement only the
2107          adding to the standard keyrings.  */
2108       if (pubkey || seckey)
2109         err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2110       else
2111         err = gpg_createkey_from_param (gpg, help_data, use_armor);
2112     }
2113   else if (userid && !key)
2114     {
2115       if (!have_gpg_version (gpg, "2.1.13"))
2116         err = gpg_createkey_legacy (gpg, userid, algo, expires, flags,
2117                                     use_armor);
2118       else
2119         err = gpg_createkey (gpg, userid, algo, expires, flags, use_armor);
2120     }
2121   else if (!have_gpg_version (gpg, "2.1.13"))
2122     err = gpg_error (GPG_ERR_NOT_SUPPORTED);
2123   else if (!userid && key)
2124     err = gpg_addkey (gpg, algo, expires, key, flags, use_armor);
2125   else if (userid && key && !algo)
2126     err = gpg_adduid (gpg, userid, flags, use_armor);
2127   else
2128     err = gpg_error (GPG_ERR_INV_VALUE);
2129
2130   return err;
2131 }
2132
2133 /* Return the next DELIM delimited string from DATA as a C-string.
2134    The caller needs to provide the address of a pointer variable which
2135    he has to set to NULL before the first call.  After the last call
2136    to this function, this function needs to be called once more with
2137    DATA set to NULL so that the function can release its internal
2138    state.  After that the pointer variable is free for use again.
2139    Note that we use a delimiter and thus a trailing delimiter is not
2140    required.  DELIM may not be changed after the first call. */
2141 static const char *
2142 string_from_data (gpgme_data_t data, int delim,
2143                   void **helpptr, gpgme_error_t *r_err)
2144 {
2145 #define MYBUFLEN 2000 /* Fixme: We don't support URLs longer than that.  */
2146   struct {
2147     int  eof_seen;
2148     int  nbytes;      /* Length of the last returned string including
2149                          the delimiter. */
2150     int  buflen;      /* Valid length of BUF.  */
2151     char buf[MYBUFLEN+1];  /* Buffer with one byte extra space.  */
2152   } *self;
2153   char *p;
2154   int nread;
2155
2156   *r_err = 0;
2157   if (!data)
2158     {
2159       if (*helpptr)
2160         {
2161           free (*helpptr);
2162           *helpptr = NULL;
2163         }
2164       return NULL;
2165     }
2166
2167   if (*helpptr)
2168     self = *helpptr;
2169   else
2170     {
2171       self = malloc (sizeof *self);
2172       if (!self)
2173         {
2174           *r_err = gpg_error_from_syserror ();
2175           return NULL;
2176         }
2177       *helpptr = self;
2178       self->eof_seen = 0;
2179       self->nbytes = 0;
2180       self->buflen = 0;
2181     }
2182
2183   if (self->eof_seen)
2184     return NULL;
2185
2186   assert (self->nbytes <= self->buflen);
2187   memmove (self->buf, self->buf + self->nbytes, self->buflen - self->nbytes);
2188   self->buflen -= self->nbytes;
2189   self->nbytes = 0;
2190
2191   do
2192     {
2193       /* Fixme: This is fairly infective scanning because we may scan
2194          the buffer several times.  */
2195       p = memchr (self->buf, delim, self->buflen);
2196       if (p)
2197         {
2198           *p = 0;
2199           self->nbytes = p - self->buf + 1;
2200           return self->buf;
2201         }
2202
2203       if ( !(MYBUFLEN - self->buflen) )
2204         {
2205           /* Not enough space - URL too long.  */
2206           *r_err = gpg_error (GPG_ERR_TOO_LARGE);
2207           return NULL;
2208         }
2209
2210       nread = gpgme_data_read (data, self->buf + self->buflen,
2211                                MYBUFLEN - self->buflen);
2212       if (nread < 0)
2213         {
2214           *r_err = gpg_error_from_syserror ();
2215           return NULL;
2216         }
2217       self->buflen += nread;
2218     }
2219   while (nread);
2220
2221   /* EOF reached.  If we have anything in the buffer, append a Nul and
2222      return it. */
2223   self->eof_seen = 1;
2224   if (self->buflen)
2225     {
2226       self->buf[self->buflen] = 0;  /* (we allocated one extra byte)  */
2227       return self->buf;
2228     }
2229   return NULL;
2230 #undef MYBUFLEN
2231 }
2232
2233
2234
2235 static gpgme_error_t
2236 gpg_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray)
2237 {
2238   engine_gpg_t gpg = engine;
2239   gpgme_error_t err;
2240   int idx;
2241   gpgme_data_encoding_t dataenc;
2242
2243   if (keydata && keyarray)
2244     return gpg_error (GPG_ERR_INV_VALUE); /* Only one is allowed.  */
2245
2246   dataenc = gpgme_data_get_encoding (keydata);
2247
2248   if (keyarray)
2249     {
2250       err = add_arg (gpg, "--recv-keys");
2251       if (!err)
2252         err = add_arg (gpg, "--");
2253       for (idx=0; !err && keyarray[idx]; idx++)
2254         {
2255           if (keyarray[idx]->protocol != GPGME_PROTOCOL_OpenPGP)
2256             ;
2257           else if (!keyarray[idx]->subkeys)
2258             ;
2259           else if (keyarray[idx]->subkeys->fpr && *keyarray[idx]->subkeys->fpr)
2260             err = add_arg (gpg, keyarray[idx]->subkeys->fpr);
2261           else if (*keyarray[idx]->subkeys->keyid)
2262             err = add_arg (gpg, keyarray[idx]->subkeys->keyid);
2263         }
2264     }
2265   else if (dataenc == GPGME_DATA_ENCODING_URL
2266            || dataenc == GPGME_DATA_ENCODING_URL0)
2267     {
2268       void *helpptr;
2269       const char *string;
2270       gpgme_error_t xerr;
2271       int delim = (dataenc == GPGME_DATA_ENCODING_URL)? '\n': 0;
2272
2273       /* FIXME: --fetch-keys is probably not correct because it can't
2274          grok all kinds of URLs.  On Unix it should just work but on
2275          Windows we will build the command line and that may fail for
2276          some embedded control characters.  It is anyway limited to
2277          the maximum size of the command line.  We need another
2278          command which can take its input from a file.  Maybe we
2279          should use an option to gpg to modify such commands (ala
2280          --multifile).  */
2281       err = add_arg (gpg, "--fetch-keys");
2282       if (!err)
2283         err = add_arg (gpg, "--");
2284       helpptr = NULL;
2285       while (!err
2286              && (string = string_from_data (keydata, delim, &helpptr, &xerr)))
2287         err = add_arg (gpg, string);
2288       if (!err)
2289         err = xerr;
2290       string_from_data (NULL, delim, &helpptr, &xerr);
2291     }
2292   else if (dataenc == GPGME_DATA_ENCODING_URLESC)
2293     {
2294       /* Already escaped URLs are not yet supported.  */
2295       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
2296     }
2297   else
2298     {
2299       err = add_arg (gpg, "--import");
2300       if (!err)
2301         err = add_arg (gpg, "--");
2302       if (!err)
2303         err = add_data (gpg, keydata, -1, 0);
2304     }
2305
2306   if (!err)
2307     err = start (gpg);
2308
2309   return err;
2310 }
2311
2312
2313 /* The output for external keylistings in GnuPG is different from all
2314    the other key listings.  We catch this here with a special
2315    preprocessor that reformats the colon handler lines.  */
2316 static gpgme_error_t
2317 gpg_keylist_preprocess (char *line, char **r_line)
2318 {
2319   enum
2320     {
2321       RT_NONE, RT_INFO, RT_PUB, RT_UID
2322     }
2323   rectype = RT_NONE;
2324 #define NR_FIELDS 16
2325   char *field[NR_FIELDS];
2326   int fields = 0;
2327   size_t n;
2328
2329   *r_line = NULL;
2330
2331   while (line && fields < NR_FIELDS)
2332     {
2333       field[fields++] = line;
2334       line = strchr (line, ':');
2335       if (line)
2336         *(line++) = '\0';
2337     }
2338
2339   if (!strcmp (field[0], "info"))
2340     rectype = RT_INFO;
2341   else if (!strcmp (field[0], "pub"))
2342     rectype = RT_PUB;
2343   else if (!strcmp (field[0], "uid"))
2344     rectype = RT_UID;
2345   else
2346     rectype = RT_NONE;
2347
2348   switch (rectype)
2349     {
2350     case RT_INFO:
2351       /* FIXME: Eventually, check the version number at least.  */
2352       return 0;
2353
2354     case RT_PUB:
2355       if (fields < 7)
2356         return 0;
2357
2358       /* The format is:
2359
2360          pub:<keyid>:<algo>:<keylen>:<creationdate>:<expirationdate>:<flags>
2361
2362          as defined in 5.2. Machine Readable Indexes of the OpenPGP
2363          HTTP Keyserver Protocol (draft).  Modern versions of the SKS
2364          keyserver return the fingerprint instead of the keyid.  We
2365          detect this here and use the v4 fingerprint format to convert
2366          it to a key id.
2367
2368          We want:
2369          pub:o<flags>:<keylen>:<algo>:<keyid>:<creatdate>:<expdate>::::::::
2370       */
2371
2372       n = strlen (field[1]);
2373       if (n > 16)
2374         {
2375           if (asprintf (r_line,
2376                         "pub:o%s:%s:%s:%s:%s:%s::::::::\n"
2377                         "fpr:::::::::%s:",
2378                         field[6], field[3], field[2], field[1] + n - 16,
2379                         field[4], field[5], field[1]) < 0)
2380             return gpg_error_from_syserror ();
2381         }
2382       else
2383         {
2384           if (asprintf (r_line,
2385                         "pub:o%s:%s:%s:%s:%s:%s::::::::",
2386                         field[6], field[3], field[2], field[1],
2387                         field[4], field[5]) < 0)
2388             return gpg_error_from_syserror ();
2389         }
2390
2391       return 0;
2392
2393     case RT_UID:
2394       /* The format is:
2395
2396          uid:<escaped uid string>:<creationdate>:<expirationdate>:<flags>
2397
2398          as defined in 5.2. Machine Readable Indexes of the OpenPGP
2399          HTTP Keyserver Protocol (draft).
2400
2401          We want:
2402          uid:o<flags>::::<creatdate>:<expdate>:::<c-coded uid>:
2403       */
2404
2405       {
2406         /* The user ID is percent escaped, but we want c-coded.
2407            Because we have to replace each '%HL' by '\xHL', we need at
2408            most 4/3 th the number of bytes.  But because we also need
2409            to escape the backslashes we allocate twice as much.  */
2410         char *uid = malloc (2 * strlen (field[1]) + 1);
2411         char *src;
2412         char *dst;
2413
2414         if (! uid)
2415           return gpg_error_from_syserror ();
2416         src = field[1];
2417         dst = uid;
2418         while (*src)
2419           {
2420             if (*src == '%')
2421               {
2422                 *(dst++) = '\\';
2423                 *(dst++) = 'x';
2424                 src++;
2425                 /* Copy the next two bytes unconditionally.  */
2426                 if (*src)
2427                   *(dst++) = *(src++);
2428                 if (*src)
2429                   *(dst++) = *(src++);
2430               }
2431             else if (*src == '\\')
2432               {
2433                 *dst++ = '\\';
2434                 *dst++ = '\\';
2435                 src++;
2436               }
2437             else
2438               *(dst++) = *(src++);
2439           }
2440         *dst = '\0';
2441
2442         if (asprintf (r_line, "uid:o%s::::%s:%s:::%s:",
2443                       field[4], field[2], field[3], uid) < 0)
2444           return gpg_error_from_syserror ();
2445       }
2446       return 0;
2447
2448     case RT_NONE:
2449       /* Unknown record.  */
2450       break;
2451     }
2452   return 0;
2453
2454 }
2455
2456
2457 static gpg_error_t
2458 gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
2459                            gpgme_keylist_mode_t mode)
2460 {
2461   gpg_error_t err;
2462
2463   err = add_arg (gpg, "--with-colons");
2464
2465   /* Since gpg 2.1.15 fingerprints are always printed, thus there is
2466    * no more need to explictly request them.  */
2467   if (!have_gpg_version (gpg, "2.1.15"))
2468     {
2469       if (!err)
2470         err = add_arg (gpg, "--fixed-list-mode");
2471       if (!err)
2472         err = add_arg (gpg, "--with-fingerprint");
2473       if (!err)
2474         err = add_arg (gpg, "--with-fingerprint");
2475     }
2476
2477   if (!err && (mode & GPGME_KEYLIST_MODE_WITH_TOFU)
2478       && have_gpg_version (gpg, "2.1.16"))
2479     err = add_arg (gpg, "--with-tofu-info");
2480
2481   if (!err && (mode & GPGME_KEYLIST_MODE_WITH_SECRET))
2482     err = add_arg (gpg, "--with-secret");
2483
2484   if (!err
2485       && (mode & GPGME_KEYLIST_MODE_SIGS)
2486       && (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS))
2487     {
2488       err = add_arg (gpg, "--list-options");
2489       if (!err)
2490         err = add_arg (gpg, "show-sig-subpackets=\"20,26\"");
2491     }
2492
2493   if (!err)
2494     {
2495       if ( (mode & GPGME_KEYLIST_MODE_EXTERN) )
2496         {
2497           if (secret_only)
2498             err = gpg_error (GPG_ERR_NOT_SUPPORTED);
2499           else if ( (mode & GPGME_KEYLIST_MODE_LOCAL))
2500             {
2501               /* The local+extern mode is special.  It works only with
2502                  gpg >= 2.0.10.  FIXME: We should check that we have
2503                  such a version to that we can return a proper error
2504                  code.  The problem is that we don't know the context
2505                  here and thus can't access the cached version number
2506                  for the engine info structure.  */
2507               err = add_arg (gpg, "--locate-keys");
2508               if ((mode & GPGME_KEYLIST_MODE_SIGS))
2509                 err = add_arg (gpg, "--with-sig-check");
2510             }
2511           else
2512             {
2513               err = add_arg (gpg, "--search-keys");
2514               gpg->colon.preprocess_fnc = gpg_keylist_preprocess;
2515             }
2516         }
2517       else
2518         {
2519           err = add_arg (gpg, secret_only ? "--list-secret-keys"
2520                          : ((mode & GPGME_KEYLIST_MODE_SIGS)
2521                             ? "--check-sigs" : "--list-keys"));
2522         }
2523     }
2524
2525   if (!err)
2526     err = add_arg (gpg, "--");
2527
2528   return err;
2529 }
2530
2531
2532 static gpgme_error_t
2533 gpg_keylist (void *engine, const char *pattern, int secret_only,
2534              gpgme_keylist_mode_t mode, int engine_flags)
2535 {
2536   engine_gpg_t gpg = engine;
2537   gpgme_error_t err;
2538
2539   err = gpg_keylist_build_options (gpg, secret_only, mode);
2540
2541   if (!err && pattern && *pattern)
2542     err = add_arg (gpg, pattern);
2543
2544   if (!err)
2545     err = start (gpg);
2546
2547   return err;
2548 }
2549
2550
2551 static gpgme_error_t
2552 gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
2553                  int reserved, gpgme_keylist_mode_t mode, int engine_flags)
2554 {
2555   engine_gpg_t gpg = engine;
2556   gpgme_error_t err;
2557
2558   if (reserved)
2559     return gpg_error (GPG_ERR_INV_VALUE);
2560
2561   err = gpg_keylist_build_options (gpg, secret_only, mode);
2562
2563   if (pattern)
2564     {
2565       while (!err && *pattern && **pattern)
2566         err = add_arg (gpg, *(pattern++));
2567     }
2568
2569   if (!err)
2570     err = start (gpg);
2571
2572   return err;
2573 }
2574
2575
2576 static gpgme_error_t
2577 gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
2578           gpgme_sig_mode_t mode, int use_armor, int use_textmode,
2579           int include_certs, gpgme_ctx_t ctx /* FIXME */)
2580 {
2581   engine_gpg_t gpg = engine;
2582   gpgme_error_t err;
2583
2584   if (mode == GPGME_SIG_MODE_CLEAR)
2585     err = add_arg (gpg, "--clearsign");
2586   else
2587     {
2588       err = add_arg (gpg, "--sign");
2589       if (!err && mode == GPGME_SIG_MODE_DETACH)
2590         err = add_arg (gpg, "--detach");
2591       if (!err && use_armor)
2592         err = add_arg (gpg, "--armor");
2593       if (!err)
2594         {
2595           if (gpgme_data_get_encoding (in) == GPGME_DATA_ENCODING_MIME
2596               && have_gpg_version (gpg, "2.1.14"))
2597             err = add_arg (gpg, "--mimemode");
2598           else if (use_textmode)
2599             err = add_arg (gpg, "--textmode");
2600         }
2601     }
2602
2603   if (!err)
2604     err = append_args_from_signers (gpg, ctx);
2605   if (!err)
2606     err = append_args_from_sig_notations (gpg, ctx);
2607
2608   if (gpgme_data_get_file_name (in))
2609     {
2610       if (!err)
2611         err = add_arg (gpg, "--set-filename");
2612       if (!err)
2613         err = add_arg (gpg, gpgme_data_get_file_name (in));
2614     }
2615
2616   /* Tell the gpg object about the data.  */
2617   if (!err)
2618     err = add_input_size_hint (gpg, in);
2619   if (!err)
2620     err = add_arg (gpg, "--");
2621   if (!err)
2622     err = add_data (gpg, in, -1, 0);
2623   if (!err)
2624     err = add_data (gpg, out, 1, 1);
2625
2626   if (!err)
2627     err = start (gpg);
2628
2629   return err;
2630 }
2631
2632 static gpgme_error_t
2633 gpg_trustlist (void *engine, const char *pattern)
2634 {
2635   engine_gpg_t gpg = engine;
2636   gpgme_error_t err;
2637
2638   err = add_arg (gpg, "--with-colons");
2639   if (!err)
2640     err = add_arg (gpg, "--list-trust-path");
2641
2642   /* Tell the gpg object about the data.  */
2643   if (!err)
2644     err = add_arg (gpg, "--");
2645   if (!err)
2646     err = add_arg (gpg, pattern);
2647
2648   if (!err)
2649     err = start (gpg);
2650
2651   return err;
2652 }
2653
2654
2655 static gpgme_error_t
2656 gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
2657             gpgme_data_t plaintext)
2658 {
2659   engine_gpg_t gpg = engine;
2660   gpgme_error_t err = 0;
2661
2662   if (plaintext)
2663     {
2664       /* Normal or cleartext signature.  */
2665       err = add_arg (gpg, "--output");
2666       if (!err)
2667         err = add_arg (gpg, "-");
2668       if (!err)
2669         err = add_input_size_hint (gpg, sig);
2670       if (!err)
2671         err = add_arg (gpg, "--");
2672       if (!err)
2673         err = add_data (gpg, sig, -1, 0);
2674       if (!err)
2675         err = add_data (gpg, plaintext, 1, 1);
2676     }
2677   else
2678     {
2679       err = add_arg (gpg, "--verify");
2680       if (!err)
2681         err = add_input_size_hint (gpg, signed_text);
2682       if (!err)
2683         err = add_arg (gpg, "--");
2684       if (!err)
2685         err = add_data (gpg, sig, -1, 0);
2686       if (!err && signed_text)
2687         err = add_data (gpg, signed_text, -1, 0);
2688     }
2689
2690   if (!err)
2691     err = start (gpg);
2692
2693   return err;
2694 }
2695
2696
2697 static void
2698 gpg_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
2699 {
2700   engine_gpg_t gpg = engine;
2701
2702   gpg->io_cbs = *io_cbs;
2703 }
2704
2705
2706 static gpgme_error_t
2707 gpg_set_pinentry_mode (void *engine, gpgme_pinentry_mode_t mode)
2708 {
2709   engine_gpg_t gpg = engine;
2710
2711   gpg->pinentry_mode = mode;
2712   return 0;
2713 }
2714
2715
2716 \f
2717 struct engine_ops _gpgme_engine_ops_gpg =
2718   {
2719     /* Static functions.  */
2720     _gpgme_get_default_gpg_name,
2721     NULL,
2722     gpg_get_version,
2723     gpg_get_req_version,
2724     gpg_new,
2725
2726     /* Member functions.  */
2727     gpg_release,
2728     NULL,                               /* reset */
2729     gpg_set_status_cb,
2730     gpg_set_status_handler,
2731     gpg_set_command_handler,
2732     gpg_set_colon_line_handler,
2733     gpg_set_locale,
2734     NULL,                               /* set_protocol */
2735     gpg_decrypt,
2736     gpg_decrypt,                        /* decrypt_verify */
2737     gpg_delete,
2738     gpg_edit,
2739     gpg_encrypt,
2740     gpg_encrypt_sign,
2741     gpg_export,
2742     gpg_export_ext,
2743     gpg_genkey,
2744     gpg_import,
2745     gpg_keylist,
2746     gpg_keylist_ext,
2747     gpg_sign,
2748     gpg_trustlist,
2749     gpg_verify,
2750     NULL,               /* getauditlog */
2751     NULL,               /* opassuan_transact */
2752     NULL,               /* conf_load */
2753     NULL,               /* conf_save */
2754     gpg_set_io_cbs,
2755     gpg_io_event,
2756     gpg_cancel,
2757     NULL,               /* cancel_op */
2758     gpg_passwd,
2759     gpg_set_pinentry_mode,
2760     NULL                /* opspawn */
2761   };