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