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