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