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