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