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