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