0283ffd2c8ecdbd21733a506625c32234cf6009f
[gpgme.git] / src / gpgme-tool.c
1 /* gpgme-tool.c - GnuPG Made Easy.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003, 2004, 2005, 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
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <getopt.h>
31 #include <ctype.h>
32 #include <stdarg.h>
33 #include <locale.h>
34 #ifdef HAVE_ARGP_H
35 #include <argp.h>
36 #endif
37
38 #include <assuan.h>
39
40 #include "gpgme.h"
41
42 \f
43 #ifndef HAVE_ARGP_H
44 /* Minimal argp implementation.  */
45
46 /* Differences to ARGP:
47    argp_program_version: Required.
48    argp_program_bug_address: Required.
49    argp_program_version_hook: Not supported.
50    argp_err_exit_status: Required.
51    struct argp: Children and help_filter not supported.
52    argp_domain: Not supported.
53    struct argp_option: Group not supported.  Options are printed in
54    order given.  Flags OPTION_ALIAS, OPTION_DOC and OPTION_NO_USAGE
55    are not supported.
56    argp_parse: No flags are supported (ARGP_PARSE_ARGV0, ARGP_NO_ERRS,
57    ARGP_NO_ARGS, ARGP_IN_ORDER, ARGP_NO_HELP, ARGP_NO_EXIT,
58    ARGP_LONG_ONLY, ARGP_SILENT).  ARGP must not be NULL.
59    argp_help: Flag ARGP_HELP_LONG_ONLY not supported.
60    argp_state: argc, argv, next may not be modified and should not be used.  */
61
62 extern const char *argp_program_version;
63 extern const char *argp_program_bug_address;
64 extern error_t argp_err_exit_status;
65
66 struct argp_option
67 {
68   const char *name;
69   int key;
70   const char *arg;
71 #define OPTION_ARG_OPTIONAL 0x1
72 #define OPTION_HIDDEN 0x2
73   int flags;
74   const char *doc;
75   int group;
76 };
77
78 struct argp;
79 struct argp_state
80 {
81   const struct argp *const root_argp;
82   int argc;
83   char **argv;
84   int next;
85   unsigned flags;
86   unsigned arg_num;
87   int quoted;
88   void *input;
89   void **child_inputs;
90   void *hook;
91   char *name;
92   FILE *err_stream;
93   FILE *out_stream;
94   void *pstate;
95 };
96
97 #define ARGP_ERR_UNKNOWN E2BIG
98 #define ARGP_KEY_ARG 0
99 #define ARGP_KEY_ARGS 0x1000006
100 #define ARGP_KEY_END 0x1000001
101 #define ARGP_KEY_NO_ARGS 0x1000002
102 #define ARGP_KEY_INIT 0x1000003
103 #define ARGP_KEY_FINI 0x1000007
104 #define ARGP_KEY_SUCCESS 0x1000004
105 #define ARGP_KEY_ERROR 0x1000005
106 typedef error_t (*argp_parser_t) (int key, char *arg, struct argp_state *state);
107
108 struct argp
109 {
110   const struct argp_option *options;
111   argp_parser_t parser;
112   const char *args_doc;
113   const char *doc;
114
115   const struct argp_child *children;
116   char *(*help_filter) (int key, const char *text, void *input);
117   const char *argp_domain;
118 };
119
120 #define ARGP_HELP_USAGE ARGP_HELP_SHORT_USAGE
121 #define ARGP_HELP_SHORT_USAGE 0x02
122 #define ARGP_HELP_SEE 0x04
123 #define ARGP_HELP_LONG 0x08
124 #define ARGP_HELP_PRE_DOC 0x10
125 #define ARGP_HELP_POST_DOC 0x20
126 #define ARGP_HELP_DOC (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC)
127 #define ARGP_HELP_BUG_ADDR 0x40
128 #define ARGP_HELP_EXIT_ERR 0x100
129 #define ARGP_HELP_EXIT_OK 0x200
130 #define ARGP_HELP_STD_ERR (ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
131 #define ARGP_HELP_STD_USAGE \
132   (ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
133 #define ARGP_HELP_STD_HELP \
134   (ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK   \
135    | ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR)
136
137
138 char *
139 _argp_pname (char *name)
140 {
141   char *pname = name;
142   char *bname = strrchr (pname, '/');
143   if (! bname)
144     bname = strrchr (pname, '\\');
145   if (bname)
146     pname = bname + 1;
147   return pname;
148 }
149
150
151 void
152 _argp_state_help (const struct argp *argp, const struct argp_state *state,
153                   FILE *stream, unsigned flags, char *name)
154 {
155   if (state)
156     name = state->name;
157
158   if (flags & ARGP_HELP_SHORT_USAGE)
159     fprintf (stream, "Usage: %s [OPTIONS...] %s\n", name, argp->args_doc);
160   if (flags & ARGP_HELP_SEE)
161     fprintf (stream, "Try `%s --help' or `%s --usage' for more information.\n",
162              name, name);
163   if (flags & ARGP_HELP_PRE_DOC)
164     {
165       char buf[1024];
166       char *end;
167       strncpy (buf, argp->doc, sizeof (buf));
168       buf[sizeof (buf) - 1] = '\0';
169       end = strchr (buf, '\v');
170       if (end)
171         *end = '\0';
172       fprintf (stream, "%s\n%s", buf, buf[0] ? "\n" : "");
173     }
174   if (flags & ARGP_HELP_LONG)
175     {
176       const struct argp_option *opt = argp->options;
177       while (opt->key)
178         {
179           #define NSPACES 29
180           char spaces[NSPACES + 1] = "                              ";
181           int len = 0;
182           fprintf (stream, "  ");
183           len += 2;
184           if (isascii (opt->key))
185             {
186               fprintf (stream, "-%c", opt->key);
187               len += 2;
188               if (opt->name)
189                 {
190                   fprintf (stream, ", ");
191                   len += 2;
192                 }
193             }
194           if (opt->name)
195             {
196               fprintf (stream, "--%s", opt->name);
197               len += 2 + strlen (opt->name);
198             }
199           if (opt->arg && (opt->flags & OPTION_ARG_OPTIONAL))
200             {
201               fprintf (stream, "[=%s]", opt->arg);
202               len += 3 + strlen (opt->arg);
203             }
204           else if (opt->arg)
205             {
206               fprintf (stream, "=%s", opt->arg);
207               len += 1 + strlen (opt->arg);
208             }
209           if (len >= NSPACES)
210             len = NSPACES - 1;
211           spaces[NSPACES - len] = '\0';
212           fprintf (stream, "%s%s\n", spaces, opt->doc);
213           opt++;
214         }
215       fprintf (stream, "  -?, --help                 Give this help list\n");
216       fprintf (stream, "      --usage                Give a short usage "
217                "message\n");
218     }
219   if (flags & ARGP_HELP_POST_DOC)
220     {
221       char buf[1024];
222       char *end;
223       strncpy (buf, argp->doc, sizeof (buf));
224       buf[sizeof (buf) - 1] = '\0';
225       end = strchr (buf, '\v');
226       if (end)
227         {
228           end++;
229           if (*end)
230             fprintf (stream, "\n%s\n", end);
231         }
232       fprintf (stream, "\nMandatory or optional arguments to long options are also mandatory or optional\n");
233       fprintf (stream, "for any corresponding short options.\n");
234     }
235   if (flags & ARGP_HELP_BUG_ADDR)
236     fprintf (stream, "\nReport bugs to %s.\n", argp_program_bug_address);
237
238   if (flags & ARGP_HELP_EXIT_ERR)
239     exit (argp_err_exit_status);
240   if (flags & ARGP_HELP_EXIT_OK)
241     exit (0);
242 }
243
244
245 void
246 argp_usage (const struct argp_state *state)
247 {
248   _argp_state_help (state->root_argp, state, state->err_stream,
249                     ARGP_HELP_STD_USAGE, state->name);
250 }
251
252
253 void
254 argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags)
255 {
256   _argp_state_help (state->root_argp, state, stream, flags, state->name);
257 }
258
259
260 void
261 argp_error (const struct argp_state *state, const char *fmt, ...)
262 {
263   va_list ap;
264
265   fprintf (state->err_stream, "%s: ", state->name);
266   va_start (ap, fmt);
267   vfprintf (state->err_stream, fmt, ap);
268   va_end (ap);
269   fprintf (state->err_stream, "\n");
270   argp_state_help (state, state->err_stream, ARGP_HELP_STD_ERR);
271   exit (argp_err_exit_status);
272 }
273
274
275 void
276 argp_help (const struct argp *argp, FILE *stream, unsigned flags, char *name)
277 {
278   _argp_state_help (argp, NULL, stream, flags, name);
279 }
280
281
282 error_t
283 argp_parse (const struct argp *argp, int argc,
284             char **argv, unsigned flags, int *arg_index, void *input)
285 {
286   int rc = 0;
287   struct argp_state state = { argp, argc, argv, 1, flags, 0, 0, input,
288                               NULL, NULL, _argp_pname (argv[0]),
289                               stderr, stdout, NULL };
290   /* All non-option arguments are collected at the beginning of
291      &argv[1] during processing.  This is a counter for their number.  */
292   int non_opt_args = 0;
293
294   rc = argp->parser (ARGP_KEY_INIT, NULL, &state);
295   if (rc && rc != ARGP_ERR_UNKNOWN)
296     goto argperror;
297
298   while (state.next < state.argc - non_opt_args)
299     {
300       int idx = state.next;
301       state.next++;
302
303       if (! strcasecmp (state.argv[idx], "--"))
304         {
305           state.quoted = idx;
306           continue;
307         }
308
309       if (state.quoted || state.argv[idx][0] != '-')
310         {
311           char *arg_saved = state.argv[idx];
312           non_opt_args++;
313           memmove (&state.argv[idx], &state.argv[idx + 1],
314                    (state.argc - 1 - idx) * sizeof (char *));
315           state.argv[argc - 1] = arg_saved;
316           state.next--;
317         }
318       else if (! strcasecmp (state.argv[idx], "--help")
319                || !strcmp (state.argv[idx], "-?"))
320         {
321           argp_state_help (&state, state.out_stream, ARGP_HELP_STD_HELP);
322         }
323       else if (! strcasecmp (state.argv[idx], "--usage"))
324         {
325           argp_state_help (&state, state.out_stream,
326                            ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
327         }
328       else if (! strcasecmp (state.argv[idx], "--version")
329                || !strcmp (state.argv[idx], "-V"))
330         {
331           fprintf (state.out_stream, "%s\n", argp_program_version);
332           exit (0);
333         }
334       else
335         {
336           /* Search for option and call parser with its KEY.  */
337           int key = ARGP_KEY_ARG; /* Just some dummy value.  */
338           const struct argp_option *opt = argp->options;
339           char *arg = NULL;
340           int found = 0;
341
342           /* Check for --opt=value syntax.  */
343           arg = strchr (state.argv[idx], '=');
344           if (arg)
345             {
346               *arg = '\0';
347               arg++;
348             }
349             
350           if (state.argv[idx][1] != '-')
351             key = state.argv[idx][1];
352           
353           while (! found && opt->key)
354             {
355               if (key == opt->key
356                   || (key == ARGP_KEY_ARG
357                       && ! strcasecmp (&state.argv[idx][2], opt->name)))
358                 {
359                   if (arg && !opt->arg)
360                     argp_error (&state, "Option %s does not take an argument",
361                                 state.argv[idx]);
362                   if (opt->arg && state.next < state.argc
363                       && state.argv[idx + 1][0] != '-')
364                     {
365                       arg = state.argv[idx + 1];
366                       state.next++;
367                     }
368                   if (opt->arg && !(opt->flags & OPTION_ARG_OPTIONAL))
369                     argp_error (&state, "Option %s requires an argument",
370                                 state.argv[idx]);
371
372                   rc = argp->parser (opt->key, arg, &state);
373                   if (rc == ARGP_ERR_UNKNOWN)
374                     break;
375                   else if (rc)
376                     goto argperror;
377                   found = 1;
378                 }
379               opt++;
380             }
381           if (! found)
382             argp_error (&state, "Unknown option %s", state.argv[idx]);
383         }
384     }
385
386   while (state.next < state.argc)
387     {
388       /* Call parser for all non-option args.  */
389       int idx = state.next;
390       state.next++;
391       rc = argp->parser (ARGP_KEY_ARG, state.argv[idx], &state);
392       if (rc && rc != ARGP_ERR_UNKNOWN)
393         goto argperror;
394       if (rc == ARGP_ERR_UNKNOWN)
395         {
396           int old_next = state.next;
397           rc = argp->parser (ARGP_KEY_ARGS, NULL, &state);
398           if (rc == ARGP_ERR_UNKNOWN)
399             {
400               argp_error (&state, "Too many arguments", state.argv[idx]);
401               goto argperror;
402             }
403           if (! rc && state.next == old_next)
404             {
405               state.arg_num += state.argc - state.next;
406               state.next = state.argc;
407             }
408         }
409       else
410         state.arg_num++;
411     }
412
413   if (state.arg_num == 0)
414     {
415       rc = argp->parser (ARGP_KEY_NO_ARGS, NULL, &state);
416       if (rc && rc != ARGP_ERR_UNKNOWN)
417         goto argperror;
418     }
419   if (state.next == state.argc)
420     {
421       rc = argp->parser (ARGP_KEY_END, NULL, &state);
422       if (rc && rc != ARGP_ERR_UNKNOWN)
423         goto argperror;
424     }
425   rc = argp->parser (ARGP_KEY_FINI, NULL, &state);
426   if (rc && rc != ARGP_ERR_UNKNOWN)
427     goto argperror;
428   
429   rc = 0;
430   argp->parser (ARGP_KEY_SUCCESS, NULL, &state);
431
432  argperror:
433   if (rc)
434     {
435       argp_error (&state, "unexpected error: %s", strerror (rc));
436       argp->parser (ARGP_KEY_ERROR, NULL, &state);
437     }
438
439   argp->parser (ARGP_KEY_FINI, NULL, &state);
440
441   if (arg_index)
442     *arg_index = state.next - 1;
443
444   return 0;
445 }
446 #endif
447
448 \f
449 /* SUPPORT.  */
450 FILE *log_stream;
451 char *program_name = "gpgme-tool";
452
453 void
454 log_init (void)
455 {
456   log_stream = stderr;
457 }
458
459
460 void
461 log_error (int status, gpg_error_t errnum, const char *fmt, ...)
462 {
463   va_list ap;
464
465   fprintf (log_stream, "%s: ", program_name);
466   va_start (ap, fmt);
467   vfprintf (log_stream, fmt, ap);
468   va_end (ap);
469   if (errnum)
470     fprintf (log_stream, ": %s <%s>", gpg_strerror (errnum),
471              gpg_strsource (errnum));
472   fprintf (log_stream, "\n");
473   if (status)
474     exit (status);
475 }
476
477
478 \f
479 typedef enum status
480   {
481     STATUS_PROTOCOL,
482     STATUS_PROGRESS,
483     STATUS_ENGINE,
484     STATUS_ARMOR,
485     STATUS_TEXTMODE,
486     STATUS_INCLUDE_CERTS,
487     STATUS_KEYLIST_MODE,
488     STATUS_RECIPIENT,
489     STATUS_ENCRYPT_RESULT
490   } status_t;
491
492 const char *status_string[] =
493   {
494     "PROTOCOL",
495     "PROGRESS",
496     "ENGINE",
497     "ARMOR",
498     "TEXTMODE",
499     "INCLUDE_CERTS",
500     "KEYLIST_MODE",
501     "RECIPIENT",
502     "ENCRYPT_RESULT"
503   };
504
505 struct gpgme_tool
506 {
507   gpgme_ctx_t ctx;
508 #define MAX_RECIPIENTS 10
509   gpgme_key_t recipients[MAX_RECIPIENTS + 1];
510   int recipients_nr;
511
512   gpg_error_t (*write_status) (void *hook, const char *status, const char *msg);
513   void *write_status_hook;
514   gpg_error_t (*write_data) (void *hook, const void *buf, size_t len);
515   void *write_data_hook;
516 };
517 typedef struct gpgme_tool *gpgme_tool_t;
518
519
520 /* Forward declaration.  */
521 void gt_write_status (gpgme_tool_t gt, status_t status, ...);
522
523 void
524 _gt_progress_cb (void *opaque, const char *what,
525                  int type, int current, int total)
526 {
527   gpgme_tool_t gt = opaque;
528   char buf[100];
529
530   snprintf (buf, sizeof (buf), "0x%02x %i %i", type, current, total);
531   gt_write_status (gt, STATUS_PROGRESS, what, buf);
532 }
533
534
535 gpg_error_t
536 _gt_gpgme_new (gpgme_tool_t gt, gpgme_ctx_t *ctx)
537 {
538   gpg_error_t err;
539
540   err = gpgme_new (ctx);
541   if (err)
542     return err;
543    gpgme_set_progress_cb (*ctx, _gt_progress_cb, gt);
544    return 0;
545 }
546
547
548 void
549 gt_init (gpgme_tool_t gt)
550 {
551   memset (gt, '\0', sizeof (*gt));
552   gpg_error_t err;
553
554   err = _gt_gpgme_new (gt, &gt->ctx);
555   if (err)
556     log_error (1, err, "can't create gpgme context");
557 }
558
559
560 gpg_error_t
561 gt_signers_add (gpgme_tool_t gt, const char *fpr)
562 {
563   gpg_error_t err;
564   gpgme_key_t key;
565
566   err = gpgme_get_key (gt->ctx, fpr, &key, 0);
567   if (err)
568     return err;
569
570   return gpgme_signers_add (gt->ctx, key);
571 }
572
573
574 gpg_error_t
575 gt_signers_clear (gpgme_tool_t gt)
576 {
577   gpgme_signers_clear (gt->ctx);
578   return 0;
579 }
580
581
582 gpg_error_t
583 gt_get_key (gpgme_tool_t gt, const char *pattern, gpgme_key_t *r_key)
584 {
585   gpgme_ctx_t ctx;
586   gpgme_ctx_t listctx;
587   gpgme_error_t err;
588   gpgme_key_t key;
589
590   if (!gt || !r_key || !pattern)
591     return gpg_error (GPG_ERR_INV_VALUE);
592   
593   ctx = gt->ctx;
594
595   err = gpgme_new (&listctx);
596   if (err)
597     return err;
598
599   {
600     gpgme_protocol_t proto;
601     gpgme_engine_info_t info;
602
603     /* Clone the relevant state.  */
604     proto = gpgme_get_protocol (ctx);
605     /* The g13 protocol does not allow keylisting, we need to choose
606        something else.  */
607     if (proto == GPGME_PROTOCOL_G13)
608       proto = GPGME_PROTOCOL_OpenPGP;
609
610     gpgme_set_protocol (listctx, proto);
611     gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
612     info = gpgme_ctx_get_engine_info (ctx);
613     while (info && info->protocol != proto)
614       info = info->next;
615     if (info)
616       gpgme_ctx_set_engine_info (listctx, proto,
617                                  info->file_name, info->home_dir);
618   }
619
620   err = gpgme_op_keylist_start (listctx, pattern, 0);
621   if (!err)
622     err = gpgme_op_keylist_next (listctx, r_key);
623   if (!err)
624     {
625     try_next_key:
626       err = gpgme_op_keylist_next (listctx, &key);
627       if (gpgme_err_code (err) == GPG_ERR_EOF)
628         err = 0;
629       else
630         {
631           if (!err
632               && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr
633               && key && key->subkeys && key->subkeys->fpr
634               && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr))
635             {
636               /* The fingerprint is identical.  We assume that this is
637                  the same key and don't mark it as an ambiguous.  This
638                  problem may occur with corrupted keyrings and has
639                  been noticed often with gpgsm.  In fact gpgsm uses a
640                  similar hack to sort out such duplicates but it can't
641                  do that while listing keys.  */
642               gpgme_key_unref (key);
643               goto try_next_key;
644             }
645           if (!err)
646             {
647               gpgme_key_unref (key);
648               err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
649             }
650           gpgme_key_unref (*r_key);
651         }
652     }
653   gpgme_release (listctx);
654   
655   if (! err)
656     gt_write_status (gt, STATUS_RECIPIENT, 
657                      ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ? 
658                      (*r_key)->subkeys->fpr : "invalid", NULL);
659   return err;
660 }
661
662
663 gpg_error_t
664 gt_recipients_add (gpgme_tool_t gt, const char *pattern)
665 {
666   gpg_error_t err;
667   gpgme_key_t key;
668
669   if (gt->recipients_nr >= MAX_RECIPIENTS)
670     return gpg_error_from_errno (ENOMEM);
671
672   if (gpgme_get_protocol (gt->ctx) == GPGME_PROTOCOL_UISERVER)
673     err = gpgme_key_from_uid (&key, pattern);
674   else
675     err = gt_get_key (gt, pattern, &key);
676   if (err)
677     return err;
678
679   gt->recipients[gt->recipients_nr++] = key;
680   return 0;
681 }
682
683
684 void
685 gt_recipients_clear (gpgme_tool_t gt)
686 {
687   int idx;
688
689   for (idx = 0; idx < gt->recipients_nr; idx++)
690     gpgme_key_unref (gt->recipients[idx]);
691   memset (gt->recipients, '\0', gt->recipients_nr * sizeof (gpgme_key_t));
692   gt->recipients_nr = 0;
693 }
694
695
696 gpg_error_t
697 gt_reset (gpgme_tool_t gt)
698 {
699   gpg_error_t err;
700   gpgme_ctx_t ctx;
701   
702   err = _gt_gpgme_new (gt, &ctx);
703   if (err)
704     return err;
705
706   gpgme_release (gt->ctx);
707   gt->ctx = ctx;
708   gt_recipients_clear (gt);
709   return 0;
710 }
711
712
713 void
714 gt_write_status (gpgme_tool_t gt, status_t status, ...)
715 {
716   va_list ap;
717   const char *text;
718   char buf[950];
719   char *p;
720   size_t n;
721   gpg_error_t err;
722
723   va_start (ap, status);
724   p = buf;
725   n = 0;
726   while ((text = va_arg (ap, const char *)))
727     {
728       if (n)
729         {
730           *p++ = ' ';
731           n++;
732         }
733       while (*text && n < sizeof (buf) - 2)
734         {
735           *p++ = *text++;
736           n++;
737         }
738     }
739   *p = 0;
740   va_end (ap);
741
742   err = gt->write_status (gt->write_status_hook, status_string[status], buf);
743   if (err)
744     log_error (1, err, "can't write status line");
745 }
746
747
748 gpg_error_t
749 gt_write_data (gpgme_tool_t gt, void *buf, size_t len)
750 {
751   return gt->write_data (gt->write_data_hook, buf, len);
752 }
753
754
755 gpg_error_t
756 gt_get_engine_info (gpgme_tool_t gt, gpgme_protocol_t proto)
757 {
758   gpgme_engine_info_t info;
759   info = gpgme_ctx_get_engine_info (gt->ctx);
760   while (info)
761     {
762       if (proto == GPGME_PROTOCOL_UNKNOWN || proto == info->protocol)
763         gt_write_status (gt, STATUS_ENGINE,
764                          gpgme_get_protocol_name (info->protocol),
765                          info->file_name, info->version,
766                          info->req_version, info->home_dir);
767       info = info->next;
768     }
769   return 0;
770 }
771
772
773 gpgme_protocol_t
774 gt_protocol_from_name (const char *name)
775 {
776   if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_OpenPGP)))
777     return GPGME_PROTOCOL_OpenPGP;
778   if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_CMS)))
779     return GPGME_PROTOCOL_CMS;
780   if (! strcasecmp (name,gpgme_get_protocol_name (GPGME_PROTOCOL_GPGCONF)))
781     return GPGME_PROTOCOL_GPGCONF;
782   if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_ASSUAN)))
783     return GPGME_PROTOCOL_ASSUAN;
784   if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_G13)))
785     return GPGME_PROTOCOL_G13;
786   if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_UISERVER)))
787     return GPGME_PROTOCOL_UISERVER;
788   if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_DEFAULT)))
789     return GPGME_PROTOCOL_DEFAULT;
790   return GPGME_PROTOCOL_UNKNOWN;
791 }
792
793   
794 gpg_error_t
795 gt_set_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
796 {
797   return gpgme_set_protocol (gt->ctx, proto);
798 }
799
800
801 gpg_error_t
802 gt_set_sub_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
803 {
804   return gpgme_set_sub_protocol (gt->ctx, proto);
805 }
806
807
808 gpg_error_t
809 gt_get_protocol (gpgme_tool_t gt)
810 {
811   gpgme_protocol_t proto = gpgme_get_protocol (gt->ctx);
812
813   gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
814                    NULL);
815
816   return 0;
817 }
818
819
820 gpg_error_t
821 gt_set_armor (gpgme_tool_t gt, int armor)
822 {
823   gpgme_set_armor (gt->ctx, armor);
824   return 0;
825 }
826
827
828 gpg_error_t
829 gt_get_armor (gpgme_tool_t gt)
830 {
831   gt_write_status (gt, STATUS_ARMOR,
832                    gpgme_get_armor (gt->ctx) ? "true" : "false", NULL);
833
834   return 0;
835 }
836
837
838 gpg_error_t
839 gt_set_textmode (gpgme_tool_t gt, int textmode)
840 {
841   gpgme_set_textmode (gt->ctx, textmode);
842   return 0;
843 }
844
845
846 gpg_error_t
847 gt_get_textmode (gpgme_tool_t gt)
848 {
849   gt_write_status (gt, STATUS_TEXTMODE,
850                    gpgme_get_textmode (gt->ctx) ? "true" : "false", NULL);
851
852   return 0;
853 }
854
855
856 gpg_error_t
857 gt_set_keylist_mode (gpgme_tool_t gt, gpgme_keylist_mode_t keylist_mode)
858 {
859   gpgme_set_keylist_mode (gt->ctx, keylist_mode);
860   return 0;
861 }
862
863
864 gpg_error_t
865 gt_get_keylist_mode (gpgme_tool_t gt)
866 {
867 #define NR_KEYLIST_MODES 6
868   const char *modes[NR_KEYLIST_MODES + 1];
869   int idx = 0;
870   gpgme_keylist_mode_t mode = gpgme_get_keylist_mode (gt->ctx);
871   
872   if (mode & GPGME_KEYLIST_MODE_LOCAL)
873     modes[idx++] = "local";
874   if (mode & GPGME_KEYLIST_MODE_EXTERN)
875     modes[idx++] = "extern";
876   if (mode & GPGME_KEYLIST_MODE_SIGS)
877     modes[idx++] = "sigs";
878   if (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS)
879     modes[idx++] = "sig_notations";
880   if (mode & GPGME_KEYLIST_MODE_EPHEMERAL)
881     modes[idx++] = "ephemeral";
882   if (mode & GPGME_KEYLIST_MODE_VALIDATE)
883     modes[idx++] = "validate";
884   modes[idx++] = NULL;
885
886   gt_write_status (gt, STATUS_KEYLIST_MODE, modes[0], modes[1], modes[2],
887                    modes[3], modes[4], modes[5], modes[6]);
888
889   return 0;
890 }
891
892
893 gpg_error_t
894 gt_set_include_certs (gpgme_tool_t gt, int include_certs)
895 {
896   gpgme_set_include_certs (gt->ctx, include_certs);
897   return 0;
898 }
899
900
901 gpg_error_t
902 gt_get_include_certs (gpgme_tool_t gt)
903 {
904   int include_certs = gpgme_get_include_certs (gt->ctx);
905   char buf[100];
906
907   if (include_certs == GPGME_INCLUDE_CERTS_DEFAULT)
908     strcpy (buf, "default");
909   else
910     snprintf (buf, sizeof (buf), "%i", include_certs);
911
912   gt_write_status (gt, STATUS_INCLUDE_CERTS, buf, NULL);
913
914   return 0;
915 }
916
917
918 gpg_error_t
919 gt_decrypt_verify (gpgme_tool_t gt, gpgme_data_t cipher, gpgme_data_t plain,
920                    int verify)
921 {
922   if (verify)
923     return gpgme_op_decrypt_verify (gt->ctx, cipher, plain);
924   else
925     return gpgme_op_decrypt (gt->ctx, cipher, plain);
926 }
927
928
929 gpg_error_t
930 gt_sign_encrypt (gpgme_tool_t gt, gpgme_encrypt_flags_t flags,
931                  gpgme_data_t plain, gpgme_data_t cipher, int sign)
932 {
933   gpg_error_t err;
934
935   if (sign)
936     err = gpgme_op_encrypt (gt->ctx, gt->recipients, flags, plain, cipher);
937   else
938     err = gpgme_op_encrypt_sign (gt->ctx, gt->recipients, flags, plain, cipher);
939
940   gt_recipients_clear (gt);
941
942   return err;
943 }
944
945
946 gpg_error_t
947 gt_sign (gpgme_tool_t gt, gpgme_data_t plain, gpgme_data_t sig,
948          gpgme_sig_mode_t mode)
949 {
950   return gpgme_op_sign (gt->ctx, plain, sig, mode);
951 }
952
953
954 gpg_error_t
955 gt_verify (gpgme_tool_t gt, gpgme_data_t sig, gpgme_data_t sig_text,
956            gpgme_data_t plain)
957 {
958   return gpgme_op_verify (gt->ctx, sig, sig_text, plain);
959 }
960
961
962 gpg_error_t
963 gt_import (gpgme_tool_t gt, gpgme_data_t data)
964 {
965   return gpgme_op_import (gt->ctx, data);
966 }
967
968
969 gpg_error_t
970 gt_export (gpgme_tool_t gt, const char *pattern[], gpgme_export_mode_t mode,
971            gpgme_data_t data)
972 {
973   return gpgme_op_export_ext (gt->ctx, pattern, mode, data);
974 }
975
976
977 gpg_error_t
978 gt_genkey (gpgme_tool_t gt, const char *parms, gpgme_data_t public,
979            gpgme_data_t secret)
980 {
981   return gpgme_op_genkey (gt->ctx, parms, public, secret);
982 }
983
984
985 gpg_error_t
986 gt_import_keys (gpgme_tool_t gt, char *fpr[])
987 {
988   gpg_error_t err;
989   int cnt;
990   int idx;
991   gpgme_key_t *keys;
992   
993   cnt = 0;
994   while (fpr[cnt])
995     cnt++;
996   
997   if (! cnt)
998     return gpg_error (GPG_ERR_INV_VALUE);
999
1000   keys = malloc ((cnt + 1) * sizeof (gpgme_key_t));
1001   if (! keys)
1002     return gpg_error_from_syserror ();
1003   
1004   for (idx = 0; idx < cnt; idx++)
1005     {
1006       err = gpgme_get_key (gt->ctx, fpr[idx], &keys[idx], 0);
1007       if (err)
1008         break;
1009     }
1010   if (! err)
1011     {
1012       keys[cnt] = NULL;
1013       err = gpgme_op_import_keys (gt->ctx, keys);
1014     }
1015   
1016   /* Rollback.  */
1017   while (--idx >= 0)
1018     gpgme_key_unref (keys[idx]);
1019   free (keys);
1020
1021   return err;
1022 }
1023
1024
1025 gpg_error_t
1026 gt_delete (gpgme_tool_t gt, char *fpr, int allow_secret)
1027 {
1028   gpg_error_t err;
1029   gpgme_key_t key;
1030
1031   err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1032   if (err)
1033     return err;
1034
1035   err = gpgme_op_delete (gt->ctx, key, allow_secret);
1036   gpgme_key_unref (key);
1037   return err;
1038 }
1039
1040
1041 gpg_error_t
1042 gt_keylist_start (gpgme_tool_t gt, const char *pattern[], int secret_only)
1043 {
1044   return gpgme_op_keylist_ext_start (gt->ctx, pattern, secret_only, 0);
1045 }
1046
1047
1048 gpg_error_t
1049 gt_keylist_next (gpgme_tool_t gt, gpgme_key_t *key)
1050 {
1051   return gpgme_op_keylist_next (gt->ctx, key);
1052 }
1053
1054
1055 gpg_error_t
1056 gt_getauditlog (gpgme_tool_t gt, gpgme_data_t output, unsigned int flags)
1057 {
1058   return gpgme_op_getauditlog (gt->ctx, output, flags);
1059 }
1060
1061
1062 gpg_error_t
1063 gt_vfs_mount (gpgme_tool_t gt, const char *container_file,
1064               const char *mount_dir, int flags)
1065 {
1066   gpg_error_t err;
1067   gpg_error_t op_err;
1068   err = gpgme_op_vfs_mount (gt->ctx, container_file, mount_dir, flags, &op_err);
1069   return err ? err : op_err;
1070 }
1071
1072
1073 gpg_error_t
1074 gt_vfs_create (gpgme_tool_t gt, const char *container_file, int flags)
1075 {
1076   gpg_error_t err;
1077   gpg_error_t op_err;
1078   err = gpgme_op_vfs_create (gt->ctx, gt->recipients, container_file,
1079                              flags, &op_err);
1080   gt_recipients_clear (gt);
1081   return err ? err : op_err;
1082 }
1083
1084
1085 // TODO
1086 #define GT_RESULT_ENCRYPT 0x1
1087 #define GT_RESULT_DECRYPT 0x2
1088 #define GT_RESULT_SIGN 0x4
1089 #define GT_RESULT_VERIFY 0x8
1090 #define GT_RESULT_IMPORT 0x10
1091 #define GT_RESULT_GENKEY 0x20
1092 #define GT_RESULT_KEYLIST 0x40
1093 #define GT_RESULT_VFS_MOUNT 0x80
1094 #define GT_RESULT_ALL (~0U)
1095
1096 gpg_error_t
1097 gt_result (gpgme_tool_t gt, unsigned int flags)
1098 {
1099   if (flags & GT_RESULT_ENCRYPT)
1100     {
1101       gpgme_encrypt_result_t res = gpgme_op_encrypt_result (gt->ctx);
1102       if (res)
1103         {
1104           gpgme_invalid_key_t invrec = res->invalid_recipients;
1105           while (invrec)
1106             {
1107               gt_write_status (gt, STATUS_ENCRYPT_RESULT, "invalid_recipient",
1108                                invrec->fpr, invrec->reason);
1109               invrec = invrec->next;
1110             }
1111         }
1112     }
1113   if (flags & GT_RESULT_VFS_MOUNT)
1114     {
1115       gpgme_vfs_mount_result_t res = gpgme_op_vfs_mount_result (gt->ctx);
1116       if (res)
1117         {
1118           gt_write_data (gt, "vfs_mount\n", 10);
1119           gt_write_data (gt, "mount_dir:", 10);
1120           gt_write_data (gt, res->mount_dir, strlen (res->mount_dir));
1121           gt_write_data (gt, "\n", 1);
1122         }
1123     }
1124
1125   return 0;
1126 }
1127
1128 \f
1129 /* GPGME SERVER.  */
1130
1131 #include <assuan.h>
1132
1133 struct server
1134 {
1135   gpgme_tool_t gt;
1136   assuan_context_t assuan_ctx;
1137
1138   gpgme_data_encoding_t input_enc;
1139   gpgme_data_encoding_t output_enc;
1140   assuan_fd_t message_fd;
1141   gpgme_data_encoding_t message_enc;
1142 };
1143
1144
1145 gpg_error_t
1146 server_write_status (void *hook, const char *status, const char *msg)
1147 {
1148   struct server *server = hook;
1149   return assuan_write_status (server->assuan_ctx, status, msg);
1150 }
1151
1152
1153 gpg_error_t
1154 server_write_data (void *hook, const void *buf, size_t len)
1155 {
1156   struct server *server = hook;
1157   return assuan_send_data (server->assuan_ctx, buf, len);
1158 }
1159
1160
1161 static gpgme_data_encoding_t
1162 server_data_encoding (const char *line)
1163 {
1164   if (strstr (line, "--binary"))
1165     return GPGME_DATA_ENCODING_BINARY;
1166   if (strstr (line, "--base64"))
1167     return GPGME_DATA_ENCODING_BASE64;
1168   if (strstr (line, "--armor"))
1169     return GPGME_DATA_ENCODING_ARMOR;
1170   if (strstr (line, "--url"))
1171     return GPGME_DATA_ENCODING_URL;
1172   if (strstr (line, "--urlesc"))
1173     return GPGME_DATA_ENCODING_URLESC;
1174   if (strstr (line, "--url0"))
1175     return GPGME_DATA_ENCODING_URL0;
1176   return GPGME_DATA_ENCODING_NONE;
1177 }
1178
1179
1180 static gpgme_error_t
1181 server_data_obj (assuan_fd_t fd, gpgme_data_encoding_t encoding,
1182                  gpgme_data_t *data)
1183 {
1184   gpgme_error_t err;
1185
1186   err = gpgme_data_new_from_fd (data, fd);
1187   if (err)
1188     return err;
1189   return gpgme_data_set_encoding (*data, encoding);
1190 }
1191
1192
1193 void
1194 server_reset_fds (struct server *server)
1195 {
1196   /* assuan closes the input and output FDs for us when doing a RESET,
1197      but we use this same function after commands, so repeat it
1198      here.  */
1199   assuan_close_input_fd (server->assuan_ctx);
1200   assuan_close_output_fd (server->assuan_ctx);
1201   if (server->message_fd != -1)
1202     {
1203       /* FIXME: Assuan should provide a close function.  */
1204       close (server->message_fd);
1205       server->message_fd = -1;
1206     }
1207   server->input_enc = GPGME_DATA_ENCODING_NONE;
1208   server->output_enc = GPGME_DATA_ENCODING_NONE;
1209   server->message_enc = GPGME_DATA_ENCODING_NONE;
1210 }
1211
1212
1213 static gpg_error_t
1214 reset_notify (assuan_context_t ctx, char *line)
1215 {
1216   struct server *server = assuan_get_pointer (ctx);
1217   server_reset_fds (server);
1218   gt_reset (server->gt);
1219   return 0;
1220 }
1221
1222 static const char hlp_version[] = 
1223   "VERSION [<string>]\n"
1224   "\n"
1225   "Call the function gpgme_check_version.";
1226 static gpg_error_t
1227 cmd_version (assuan_context_t ctx, char *line)
1228 {
1229   if (line && *line)
1230     {
1231       const char *version = gpgme_check_version (line);
1232       return version ? 0 : gpg_error (GPG_ERR_SELFTEST_FAILED);
1233     }
1234   else
1235     {
1236       const char *version = gpgme_check_version (NULL);
1237       return assuan_send_data (ctx, version, strlen (version));
1238     }
1239 }
1240
1241
1242 static gpg_error_t
1243 cmd_engine (assuan_context_t ctx, char *line)
1244 {
1245   struct server *server = assuan_get_pointer (ctx);
1246   return gt_get_engine_info (server->gt, gt_protocol_from_name (line));
1247 }
1248
1249
1250 static const char hlp_protocol[] = 
1251   "PROTOCOL [<name>]\n"
1252   "\n"
1253   "With NAME, set the protocol.  Without return the current protocol.";
1254 static gpg_error_t
1255 cmd_protocol (assuan_context_t ctx, char *line)
1256 {
1257   struct server *server = assuan_get_pointer (ctx);
1258   if (line && *line)
1259     return gt_set_protocol (server->gt, gt_protocol_from_name (line));
1260   else
1261     return gt_get_protocol (server->gt);
1262 }
1263
1264
1265 static gpg_error_t
1266 cmd_sub_protocol (assuan_context_t ctx, char *line)
1267 {
1268   struct server *server = assuan_get_pointer (ctx);
1269   if (line && *line)
1270     return gt_set_sub_protocol (server->gt, gt_protocol_from_name (line));
1271   /* FIXME.  */
1272   return 0;
1273 }
1274
1275
1276 static gpg_error_t
1277 cmd_armor (assuan_context_t ctx, char *line)
1278 {
1279   struct server *server = assuan_get_pointer (ctx);
1280   if (line && *line)
1281     {
1282       int flag = 0;
1283       
1284       if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
1285           || line[0] == '1')
1286         flag = 1;
1287       
1288       return gt_set_armor (server->gt, flag);
1289     }
1290   else
1291     return gt_get_armor (server->gt);
1292 }
1293
1294
1295 static gpg_error_t
1296 cmd_textmode (assuan_context_t ctx, char *line)
1297 {
1298   struct server *server = assuan_get_pointer (ctx);
1299   if (line && *line)
1300     {
1301       int flag = 0;
1302
1303       if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
1304           || line[0] == '1')
1305         flag = 1;
1306       
1307       return gt_set_textmode (server->gt, flag);
1308     }
1309   else
1310     return gt_get_textmode (server->gt);
1311 }
1312
1313
1314 static gpg_error_t
1315 cmd_include_certs (assuan_context_t ctx, char *line)
1316 {
1317   struct server *server = assuan_get_pointer (ctx);
1318
1319   if (line && *line)
1320     {
1321       int include_certs = 0;
1322       
1323       if (! strcasecmp (line, "default"))
1324         include_certs = GPGME_INCLUDE_CERTS_DEFAULT;
1325       else
1326         include_certs = atoi (line);
1327       
1328       return gt_set_include_certs (server->gt, include_certs);
1329     }
1330   else
1331     return gt_get_include_certs (server->gt);
1332 }
1333
1334
1335 static gpg_error_t
1336 cmd_keylist_mode (assuan_context_t ctx, char *line)
1337 {
1338   struct server *server = assuan_get_pointer (ctx);
1339
1340   if (line && *line)
1341     {
1342       gpgme_keylist_mode_t mode = 0;
1343       
1344       if (strstr (line, "local"))
1345         mode |= GPGME_KEYLIST_MODE_LOCAL;
1346       if (strstr (line, "extern"))
1347         mode |= GPGME_KEYLIST_MODE_EXTERN;
1348       if (strstr (line, "sigs"))
1349         mode |= GPGME_KEYLIST_MODE_SIGS;
1350       if (strstr (line, "sig_notations"))
1351         mode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS;
1352       if (strstr (line, "ephemeral"))
1353         mode |= GPGME_KEYLIST_MODE_EPHEMERAL;
1354       if (strstr (line, "validate"))
1355         mode |= GPGME_KEYLIST_MODE_VALIDATE;
1356       
1357       return gt_set_keylist_mode (server->gt, mode);
1358     }
1359   else
1360     return gt_get_keylist_mode (server->gt);
1361 }
1362
1363
1364 static gpg_error_t
1365 input_notify (assuan_context_t ctx, char *line)
1366 {
1367   struct server *server = assuan_get_pointer (ctx);
1368   server->input_enc = server_data_encoding (line);
1369   return 0;
1370 }
1371
1372
1373 static gpg_error_t
1374 output_notify (assuan_context_t ctx, char *line)
1375 {
1376   struct server *server = assuan_get_pointer (ctx);
1377   server->output_enc = server_data_encoding (line);
1378   return 0;
1379 }
1380
1381
1382 static gpg_error_t
1383 cmd_message (assuan_context_t ctx, char *line)
1384 {
1385   struct server *server = assuan_get_pointer (ctx);
1386   gpg_error_t err;
1387   assuan_fd_t sysfd;
1388
1389   err = assuan_command_parse_fd (ctx, line, &sysfd);
1390   if (err)
1391     return err;
1392   server->message_fd = sysfd;
1393   server->message_enc = server_data_encoding (line);
1394   return 0;
1395 }
1396
1397
1398 static gpg_error_t
1399 cmd_recipient (assuan_context_t ctx, char *line)
1400 {
1401   struct server *server = assuan_get_pointer (ctx);
1402
1403   return gt_recipients_add (server->gt, line);
1404 }
1405
1406
1407 static gpg_error_t
1408 cmd_signer (assuan_context_t ctx, char *line)
1409 {
1410   struct server *server = assuan_get_pointer (ctx);
1411
1412   return gt_signers_add (server->gt, line);
1413 }
1414
1415
1416 static gpg_error_t
1417 cmd_signers_clear (assuan_context_t ctx, char *line)
1418 {
1419   struct server *server = assuan_get_pointer (ctx);
1420
1421   return gt_signers_clear (server->gt);
1422 }
1423
1424
1425 static gpg_error_t
1426 _cmd_decrypt_verify (assuan_context_t ctx, char *line, int verify)
1427 {
1428   struct server *server = assuan_get_pointer (ctx);
1429   gpg_error_t err;
1430   assuan_fd_t inp_fd;
1431   assuan_fd_t out_fd;
1432   gpgme_data_t inp_data;
1433   gpgme_data_t out_data;
1434
1435   inp_fd = assuan_get_input_fd (ctx);
1436   if (inp_fd == ASSUAN_INVALID_FD)
1437     return GPG_ERR_ASS_NO_INPUT;
1438   out_fd = assuan_get_output_fd (ctx);
1439   if (out_fd == ASSUAN_INVALID_FD)
1440     return GPG_ERR_ASS_NO_OUTPUT;
1441   
1442   err = server_data_obj (inp_fd, server->input_enc, &inp_data);
1443   if (err)
1444     return err;
1445   err = server_data_obj (out_fd, server->output_enc, &out_data);
1446   if (err)
1447     {
1448       gpgme_data_release (inp_data);
1449       return err;
1450     }
1451
1452   err = gt_decrypt_verify (server->gt, inp_data, out_data, verify); 
1453
1454   gpgme_data_release (inp_data);
1455   gpgme_data_release (out_data);
1456
1457   server_reset_fds (server);
1458
1459   return err;
1460 }
1461
1462
1463 static gpg_error_t
1464 cmd_decrypt (assuan_context_t ctx, char *line)
1465 {
1466   return _cmd_decrypt_verify (ctx, line, 0);
1467 }
1468
1469
1470 static gpg_error_t
1471 cmd_decrypt_verify (assuan_context_t ctx, char *line)
1472 {
1473   return _cmd_decrypt_verify (ctx, line, 1);
1474 }
1475
1476
1477 static gpg_error_t
1478 _cmd_sign_encrypt (assuan_context_t ctx, char *line, int sign)
1479 {
1480   struct server *server = assuan_get_pointer (ctx);
1481   gpg_error_t err;
1482   assuan_fd_t inp_fd;
1483   assuan_fd_t out_fd;
1484   gpgme_data_t inp_data = NULL;
1485   gpgme_data_t out_data = NULL;
1486   gpgme_encrypt_flags_t flags = 0;
1487
1488   if (strstr (line, "--always-trust"))
1489     flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
1490   if (strstr (line, "--no-encrypt-to"))
1491     flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
1492   if (strstr (line, "--prepare"))
1493     flags |= GPGME_ENCRYPT_PREPARE;
1494   if (strstr (line, "--expect-sign"))
1495     flags |= GPGME_ENCRYPT_EXPECT_SIGN;
1496   
1497   inp_fd = assuan_get_input_fd (ctx);
1498   out_fd = assuan_get_output_fd (ctx);
1499   if (inp_fd != ASSUAN_INVALID_FD)
1500     {
1501       err = server_data_obj (inp_fd, server->input_enc, &inp_data);
1502       if (err)
1503         return err;
1504     }
1505   if (out_fd != ASSUAN_INVALID_FD)
1506     {
1507       err = server_data_obj (out_fd, server->output_enc, &out_data);
1508       if (err)
1509         {
1510           gpgme_data_release (inp_data);
1511           return err;
1512         }
1513     }
1514
1515   err = gt_sign_encrypt (server->gt, flags, inp_data, out_data, sign); 
1516
1517   gpgme_data_release (inp_data);
1518   gpgme_data_release (out_data);
1519
1520   server_reset_fds (server);
1521
1522   return err;
1523 }
1524
1525
1526 static gpg_error_t
1527 cmd_encrypt (assuan_context_t ctx, char *line)
1528 {
1529   return _cmd_sign_encrypt (ctx, line, 0);
1530 }
1531
1532
1533 static gpg_error_t
1534 cmd_sign_encrypt (assuan_context_t ctx, char *line)
1535 {
1536   return _cmd_sign_encrypt (ctx, line, 1);
1537 }
1538
1539
1540 static gpg_error_t
1541 cmd_sign (assuan_context_t ctx, char *line)
1542 {
1543   struct server *server = assuan_get_pointer (ctx);
1544   gpg_error_t err;
1545   assuan_fd_t inp_fd;
1546   assuan_fd_t out_fd;
1547   gpgme_data_t inp_data;
1548   gpgme_data_t out_data;
1549   gpgme_sig_mode_t mode = GPGME_SIG_MODE_NORMAL;
1550
1551   if (strstr (line, "--clear"))
1552     mode = GPGME_SIG_MODE_CLEAR;
1553   if (strstr (line, "--detach"))
1554     mode = GPGME_SIG_MODE_DETACH;
1555
1556   inp_fd = assuan_get_input_fd (ctx);
1557   if (inp_fd == ASSUAN_INVALID_FD)
1558     return GPG_ERR_ASS_NO_INPUT;
1559   out_fd = assuan_get_output_fd (ctx);
1560   if (out_fd == ASSUAN_INVALID_FD)
1561     return GPG_ERR_ASS_NO_OUTPUT;
1562   
1563   err = server_data_obj (inp_fd, server->input_enc, &inp_data);
1564   if (err)
1565     return err;
1566   err = server_data_obj (out_fd, server->output_enc, &out_data);
1567   if (err)
1568     {
1569       gpgme_data_release (inp_data);
1570       return err;
1571     }
1572
1573   err = gt_sign (server->gt, inp_data, out_data, mode);
1574
1575   gpgme_data_release (inp_data);
1576   gpgme_data_release (out_data);
1577   server_reset_fds (server);
1578
1579   return err;
1580 }
1581
1582
1583 static gpg_error_t
1584 cmd_verify (assuan_context_t ctx, char *line)
1585 {
1586   struct server *server = assuan_get_pointer (ctx);
1587   gpg_error_t err;
1588   assuan_fd_t inp_fd;
1589   assuan_fd_t msg_fd;
1590   assuan_fd_t out_fd;
1591   gpgme_data_t inp_data;
1592   gpgme_data_t msg_data = NULL;
1593   gpgme_data_t out_data = NULL;
1594
1595   inp_fd = assuan_get_input_fd (ctx);
1596   if (inp_fd == ASSUAN_INVALID_FD)
1597     return GPG_ERR_ASS_NO_INPUT;
1598   msg_fd = server->message_fd;
1599   out_fd = assuan_get_output_fd (ctx);
1600   
1601   err = server_data_obj (inp_fd, server->input_enc, &inp_data);
1602   if (err)
1603     return err;
1604   if (msg_fd != ASSUAN_INVALID_FD)
1605     {
1606       err = server_data_obj (msg_fd, server->message_enc, &msg_data);
1607       if (err)
1608         {
1609           gpgme_data_release (inp_data);
1610           return err;
1611         }
1612     }
1613   if (out_fd != ASSUAN_INVALID_FD)
1614     {
1615       err = server_data_obj (out_fd, server->output_enc, &out_data);
1616       if (err)
1617         {
1618           gpgme_data_release (inp_data);
1619           gpgme_data_release (msg_data);
1620           return err;
1621         }
1622     }
1623
1624   err = gt_verify (server->gt, inp_data, msg_data, out_data);
1625
1626   gpgme_data_release (inp_data);
1627   if (msg_data)
1628     gpgme_data_release (msg_data);
1629   if (out_data)
1630     gpgme_data_release (out_data);
1631
1632   server_reset_fds (server);
1633
1634   return err;
1635 }
1636
1637
1638 static gpg_error_t
1639 cmd_import (assuan_context_t ctx, char *line)
1640 {
1641   struct server *server = assuan_get_pointer (ctx);
1642   
1643   if (line && *line)
1644     {
1645       char *fprs[2] = { line, NULL };
1646
1647       return gt_import_keys (server->gt, fprs);
1648     }
1649   else
1650     {
1651       gpg_error_t err;
1652       assuan_fd_t inp_fd;
1653       gpgme_data_t inp_data;
1654       
1655       inp_fd = assuan_get_input_fd (ctx);
1656       if (inp_fd == ASSUAN_INVALID_FD)
1657         return GPG_ERR_ASS_NO_INPUT;
1658
1659       err = server_data_obj (inp_fd, server->input_enc, &inp_data);
1660       if (err)
1661         return err;
1662       
1663       err = gt_import (server->gt, inp_data); 
1664       
1665       gpgme_data_release (inp_data);
1666       server_reset_fds (server);
1667
1668       return err;
1669     }
1670 }
1671
1672
1673 static gpg_error_t
1674 cmd_export (assuan_context_t ctx, char *line)
1675 {
1676   struct server *server = assuan_get_pointer (ctx);
1677   gpg_error_t err;
1678   assuan_fd_t out_fd;
1679   gpgme_data_t out_data;
1680   gpgme_export_mode_t mode = 0;
1681   const char *pattern[2];
1682   const char optstr[] = "--extern ";
1683
1684   out_fd = assuan_get_output_fd (ctx);
1685   if (out_fd == ASSUAN_INVALID_FD)
1686     return GPG_ERR_ASS_NO_OUTPUT;
1687   err = server_data_obj (out_fd, server->output_enc, &out_data);
1688   if (err)
1689     return err;
1690
1691   if (strncasecmp (line, optstr, strlen (optstr)))
1692     {
1693       mode |= GPGME_EXPORT_MODE_EXTERN;
1694       line += strlen (optstr);
1695     }
1696   pattern[0] = line;
1697   pattern[1] = NULL;
1698
1699   err = gt_export (server->gt, pattern, mode, out_data);
1700
1701   gpgme_data_release (out_data);
1702   server_reset_fds (server);
1703
1704   return err;
1705 }
1706
1707
1708 static gpg_error_t
1709 _cmd_genkey_write (gpgme_data_t data, const void *buf, size_t size)
1710 {
1711   while (size > 0)
1712     {
1713       ssize_t writen = gpgme_data_write (data, buf, size);
1714       if (writen < 0 && errno != EAGAIN)
1715         return gpg_error_from_syserror ();
1716       else if (writen > 0)
1717         {
1718           buf = (void *) (((char *) buf) + writen);
1719           size -= writen;
1720         }
1721     }
1722   return 0;
1723 }
1724
1725
1726 static gpg_error_t
1727 cmd_genkey (assuan_context_t ctx, char *line)
1728 {
1729   struct server *server = assuan_get_pointer (ctx);
1730   gpg_error_t err;
1731   assuan_fd_t inp_fd;
1732   assuan_fd_t out_fd;
1733   gpgme_data_t inp_data;
1734   gpgme_data_t out_data = NULL;
1735   gpgme_data_t parms_data = NULL;
1736   const char *parms;
1737
1738   inp_fd = assuan_get_input_fd (ctx);
1739   if (inp_fd == ASSUAN_INVALID_FD)
1740     return GPG_ERR_ASS_NO_INPUT;
1741   out_fd = assuan_get_output_fd (ctx);
1742   
1743   err = server_data_obj (inp_fd, server->input_enc, &inp_data);
1744   if (err)
1745     return err;
1746   if (out_fd != ASSUAN_INVALID_FD)
1747     {
1748       err = server_data_obj (out_fd, server->output_enc, &out_data);
1749       if (err)
1750         {
1751           gpgme_data_release (inp_data);
1752           return err;
1753         }
1754     }
1755
1756   /* Convert input data.  */
1757   err = gpgme_data_new (&parms_data);
1758   if (err)
1759     goto out;
1760   do
1761     {
1762       char buf[512];
1763       ssize_t readn = gpgme_data_read (inp_data, buf, sizeof (buf));
1764       if (readn < 0)
1765         {
1766           err = gpg_error_from_syserror ();
1767           goto out;
1768         }
1769       else if (readn == 0)
1770         break;
1771
1772       err = _cmd_genkey_write (parms_data, buf, readn);
1773       if (err)
1774         goto out;
1775     }
1776   while (1);
1777   err = _cmd_genkey_write (parms_data, "", 1);
1778   if (err)
1779     goto out;
1780   parms = gpgme_data_release_and_get_mem (parms_data, NULL);
1781   parms_data = NULL;
1782   if (! parms)
1783     {
1784       err = gpg_error (GPG_ERR_GENERAL);
1785       goto out;
1786     }
1787
1788   err = gt_genkey (server->gt, parms, out_data, NULL);
1789
1790   server_reset_fds (server);
1791
1792  out:
1793   gpgme_data_release (inp_data);
1794   if (out_data)
1795     gpgme_data_release (out_data);
1796   if (parms_data)
1797     gpgme_data_release (parms_data);
1798
1799   return err; 
1800 }
1801
1802
1803 static gpg_error_t
1804 cmd_delete (assuan_context_t ctx, char *line)
1805 {
1806   struct server *server = assuan_get_pointer (ctx);
1807   int allow_secret = 0;
1808   const char optstr[] = "--allow-secret ";
1809
1810   if (strncasecmp (line, optstr, strlen (optstr)))
1811     {
1812       allow_secret = 1;
1813       line += strlen (optstr);
1814     }
1815   return gt_delete (server->gt, line, allow_secret);
1816 }
1817
1818
1819 static gpg_error_t
1820 cmd_keylist (assuan_context_t ctx, char *line)
1821 {
1822   struct server *server = assuan_get_pointer (ctx);
1823   gpg_error_t err;
1824   int secret_only = 0;
1825   const char *pattern[2];
1826   const char optstr[] = "--secret-only ";
1827
1828   if (strncasecmp (line, optstr, strlen (optstr)))
1829     {
1830       secret_only = 1;
1831       line += strlen (optstr);
1832     }
1833   pattern[0] = line;
1834   pattern[1] = NULL;
1835
1836   err = gt_keylist_start (server->gt, pattern, secret_only);
1837   while (! err)
1838     {
1839       gpgme_key_t key;
1840
1841       err = gt_keylist_next (server->gt, &key);
1842       if (gpg_err_code (err) == GPG_ERR_EOF)
1843         {
1844           err = 0;
1845           break;
1846         }
1847       else if (! err)
1848         {
1849           char buf[100];
1850           /* FIXME: More data.  */
1851           snprintf (buf, sizeof (buf), "key:%s\n", key->subkeys->fpr);
1852           assuan_send_data (ctx, buf, strlen (buf));
1853           gpgme_key_unref (key);
1854         }
1855     }
1856   
1857   server_reset_fds (server);
1858
1859   return err;
1860 }
1861
1862
1863 static gpg_error_t
1864 cmd_getauditlog (assuan_context_t ctx, char *line)
1865 {
1866   struct server *server = assuan_get_pointer (ctx);
1867   gpg_error_t err;
1868   assuan_fd_t out_fd;
1869   gpgme_data_t out_data;
1870
1871   out_fd = assuan_get_output_fd (ctx);
1872   if (out_fd == ASSUAN_INVALID_FD)
1873     return GPG_ERR_ASS_NO_OUTPUT;
1874   err = server_data_obj (out_fd, server->output_enc, &out_data);
1875   if (err)
1876     return err;
1877
1878   err = gt_getauditlog (server->gt, out_data, 0);
1879
1880   gpgme_data_release (out_data);
1881   server_reset_fds (server);
1882
1883   return err;
1884 }
1885
1886
1887 static gpg_error_t
1888 cmd_vfs_mount (assuan_context_t ctx, char *line)
1889 {
1890   struct server *server = assuan_get_pointer (ctx);
1891   char *mount_dir;
1892   gpg_error_t err;
1893
1894   mount_dir = strchr (line, ' ');
1895   if (mount_dir)
1896     {
1897       *(mount_dir++) = '\0';
1898       while (*mount_dir == ' ')
1899         mount_dir++;
1900     }
1901
1902   err = gt_vfs_mount (server->gt, line, mount_dir, 0);
1903
1904   return err;
1905 }
1906
1907
1908 static gpg_error_t
1909 cmd_vfs_create (assuan_context_t ctx, char *line)
1910 {
1911   struct server *server = assuan_get_pointer (ctx);
1912   gpg_error_t err;
1913   char *end;
1914
1915   end = strchr (line, ' ');
1916   if (end)
1917     {
1918       *(end++) = '\0';
1919       while (*end == ' ')
1920         end++;
1921     }
1922
1923   err = gt_vfs_create (server->gt, line, 0);
1924
1925   return err;
1926 }
1927
1928
1929 static gpg_error_t
1930 cmd_result (assuan_context_t ctx, char *line)
1931 {
1932   struct server *server = assuan_get_pointer (ctx);
1933   return gt_result (server->gt, GT_RESULT_ALL);
1934 }
1935
1936
1937 /* STRERROR <err>  */
1938 static gpg_error_t
1939 cmd_strerror (assuan_context_t ctx, char *line)
1940 {
1941   gpg_error_t err;
1942   char buf[100];
1943
1944   err = atoi (line);
1945   snprintf (buf, sizeof (buf), "%s <%s>", gpgme_strerror (err),
1946             gpgme_strsource (err));
1947   return assuan_send_data (ctx, buf, strlen (buf));
1948 }
1949
1950
1951 static gpg_error_t
1952 cmd_pubkey_algo_name (assuan_context_t ctx, char *line)
1953 {
1954   gpgme_pubkey_algo_t algo;
1955   char buf[100];
1956
1957   algo = atoi (line);
1958   snprintf (buf, sizeof (buf), "%s", gpgme_pubkey_algo_name (algo));
1959   return assuan_send_data (ctx, buf, strlen (buf));
1960 }
1961
1962
1963 static gpg_error_t
1964 cmd_hash_algo_name (assuan_context_t ctx, char *line)
1965 {
1966   gpgme_hash_algo_t algo;
1967   char buf[100];
1968
1969   algo = atoi (line);
1970   snprintf (buf, sizeof (buf), "%s", gpgme_hash_algo_name (algo));
1971   return assuan_send_data (ctx, buf, strlen (buf));
1972 }
1973
1974
1975 /* Tell the assuan library about our commands.  */
1976 static gpg_error_t
1977 register_commands (assuan_context_t ctx)
1978 {
1979   gpg_error_t err;
1980   static struct {
1981     const char *name;
1982     assuan_handler_t handler;
1983     const char * const help;
1984   } table[] = {
1985     // RESET, BYE are implicit.
1986     { "VERSION", cmd_version, hlp_version },
1987     // TODO: Set engine info.
1988     { "ENGINE", cmd_engine },
1989     { "PROTOCOL", cmd_protocol, hlp_protocol },
1990     { "SUB_PROTOCOL", cmd_sub_protocol },
1991     { "ARMOR", cmd_armor },
1992     { "TEXTMODE", cmd_textmode },
1993     { "INCLUDE_CERTS", cmd_include_certs },
1994     { "KEYLIST_MODE", cmd_keylist_mode },
1995     { "INPUT", NULL }, 
1996     { "OUTPUT", NULL }, 
1997     { "MESSAGE", cmd_message },
1998     { "RECIPIENT", cmd_recipient },
1999     { "SIGNER", cmd_signer },
2000     { "SIGNERS_CLEAR", cmd_signers_clear },
2001     // TODO: SIGNOTATION missing.
2002     // TODO: Could add wait interface if we allow more than one context
2003     // and add _START variants.
2004     // TODO: Could add data interfaces if we allow multiple data objects.
2005     { "DECRYPT", cmd_decrypt },
2006     { "DECRYPT_VERIFY", cmd_decrypt_verify },
2007     { "ENCRYPT", cmd_encrypt },
2008     { "ENCRYPT_SIGN", cmd_sign_encrypt },
2009     { "SIGN_ENCRYPT", cmd_sign_encrypt },
2010     { "SIGN", cmd_sign },
2011     { "VERIFY", cmd_verify },
2012     { "IMPORT", cmd_import },
2013     { "EXPORT", cmd_export },
2014     { "GENKEY", cmd_genkey },
2015     { "DELETE", cmd_delete },
2016     // TODO: EDIT, CARD_EDIT (with INQUIRE)
2017     { "KEYLIST", cmd_keylist },
2018     { "LISTKEYS", cmd_keylist },
2019     // TODO: TRUSTLIST, TRUSTLIST_EXT
2020     { "GETAUDITLOG", cmd_getauditlog },
2021     // TODO: ASSUAN
2022     { "VFS_MOUNT", cmd_vfs_mount },
2023     { "MOUNT", cmd_vfs_mount },
2024     { "VFS_CREATE", cmd_vfs_create },
2025     { "CREATE", cmd_vfs_create },
2026     // TODO: GPGCONF
2027     { "RESULT", cmd_result },
2028     { "STRERROR", cmd_strerror },
2029     { "PUBKEY_ALGO_NAME", cmd_pubkey_algo_name },
2030     { "HASH_ALGO_NAME", cmd_hash_algo_name },
2031     { NULL }
2032   };
2033   int idx;
2034
2035   for (idx = 0; table[idx].name; idx++)
2036     {
2037       err = assuan_register_command (ctx, table[idx].name, table[idx].handler,
2038                                      table[idx].help);
2039       if (err)
2040         return err;
2041     } 
2042   return 0;
2043 }
2044
2045
2046 /* TODO: password callback can do INQUIRE.  */
2047 void
2048 gpgme_server (gpgme_tool_t gt)
2049 {
2050   gpg_error_t err;
2051   int filedes[2];
2052   struct server server;
2053   static const char hello[] = ("GPGME-Tool " VERSION " ready");
2054
2055   memset (&server, 0, sizeof (server));
2056   server.message_fd = -1;
2057   server.input_enc = GPGME_DATA_ENCODING_NONE;
2058   server.output_enc = GPGME_DATA_ENCODING_NONE;
2059   server.message_enc = GPGME_DATA_ENCODING_NONE;
2060
2061   server.gt = gt;
2062   gt->write_status = server_write_status;
2063   gt->write_status_hook = &server;
2064   gt->write_data = server_write_data;
2065   gt->write_data_hook = &server;
2066
2067   /* We use a pipe based server so that we can work from scripts.
2068      assuan_init_pipe_server will automagically detect when we are
2069      called with a socketpair and ignore FIELDES in this case. */
2070   filedes[0] = 0;
2071   filedes[1] = 1;
2072   err = assuan_new (&server.assuan_ctx);
2073   if (err)
2074     log_error (1, err, "can't create assuan context");
2075
2076   assuan_set_pointer (server.assuan_ctx, &server);
2077
2078   err = assuan_init_pipe_server (server.assuan_ctx, filedes);
2079   if (err)
2080     log_error (1, err, "can't initialize assuan server");
2081   err = register_commands (server.assuan_ctx);
2082   if (err)
2083     log_error (1, err, "can't register assuan commands");
2084   assuan_set_hello_line (server.assuan_ctx, hello);
2085
2086   assuan_register_reset_notify (server.assuan_ctx, reset_notify);
2087   assuan_register_input_notify (server.assuan_ctx, input_notify);
2088   assuan_register_output_notify (server.assuan_ctx, output_notify);
2089
2090 #define DBG_ASSUAN 0
2091   if (DBG_ASSUAN)
2092     assuan_set_log_stream (server.assuan_ctx, log_stream);
2093
2094   for (;;)
2095     {
2096       err = assuan_accept (server.assuan_ctx);
2097       if (err == -1)
2098         break;
2099       else if (err)
2100         {
2101           log_error (0, err, "assuan accept problem");
2102           break;
2103         }
2104       
2105       err = assuan_process (server.assuan_ctx);
2106       if (err)
2107         log_error (0, err, "assuan processing failed");
2108     }
2109
2110   assuan_release (server.assuan_ctx);
2111 }
2112
2113
2114 \f
2115 /* MAIN PROGRAM STARTS HERE.  */
2116
2117 const char *argp_program_version = VERSION;
2118 const char *argp_program_bug_address = "bug-gpgme@gnupg.org";
2119 error_t argp_err_exit_status = 1;
2120
2121 static char doc[] = "GPGME Tool -- invoke GPGME operations";
2122 static char args_doc[] = "COMMAND [OPTIONS...]";
2123
2124 static struct argp_option options[] = {
2125   { "server", 's', 0, 0, "Server mode" },
2126   { 0 }
2127 };
2128
2129 static error_t parse_options (int key, char *arg, struct argp_state *state);
2130 static struct argp argp = { options, parse_options, args_doc, doc };
2131
2132 struct args
2133 {
2134   enum { CMD_DEFAULT, CMD_SERVER } cmd;
2135 };
2136
2137 void
2138 args_init (struct args *args)
2139 {
2140   memset (args, '\0', sizeof (*args));
2141   args->cmd = CMD_DEFAULT;
2142 }
2143
2144
2145 static error_t
2146 parse_options (int key, char *arg, struct argp_state *state)
2147 {
2148   struct args *args = state->input;
2149
2150   switch (key)
2151     {
2152     case 's':
2153       args->cmd = CMD_SERVER;
2154       break;
2155 #if 0
2156     case ARGP_KEY_ARG:
2157       if (state->arg_num >= 2)
2158         argp_usage (state);
2159       printf ("Arg[%i] = %s\n", state->arg_num, arg);
2160       break;
2161     case ARGP_KEY_END:
2162       if (state->arg_num < 2)
2163         argp_usage (state);
2164       break;
2165 #endif
2166
2167     default:
2168       return ARGP_ERR_UNKNOWN;
2169     }
2170   return 0;
2171 }
2172
2173 \f
2174 int
2175 main (int argc, char *argv[])
2176 {
2177   struct args args;
2178   struct gpgme_tool gt;
2179
2180   setlocale (LC_ALL, "");
2181   gpgme_check_version (NULL);
2182   gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
2183 #ifdef LC_MESSAGES
2184   gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
2185 #endif
2186   args_init (&args);
2187
2188   argp_parse (&argp, argc, argv, 0, 0, &args);
2189   log_init ();
2190
2191   gt_init (&gt);
2192
2193   switch (args.cmd)
2194     {
2195     case CMD_DEFAULT:
2196     case CMD_SERVER:
2197       gpgme_server (&gt);
2198       break;
2199     }
2200
2201   gpgme_release (gt.ctx);
2202
2203   return 0;
2204 }
2205