1 /* gpgme-tool.c - GnuPG Made Easy.
2 Copyright (C) 2009, 2010 g10 Code GmbH
4 This file is part of GPGME.
6 GPGME is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of
9 the License, or (at your option) any later version.
11 GPGME is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with this program; if not, see <http://www.gnu.org/licenses/>.
44 # define GT_GCC_A_SENTINEL(a) __attribute__ ((sentinel(a)))
46 # define GT_GCC_A_SENTINEL(a)
49 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
50 # define GT_GCC_A_PRINTF(f, a) __attribute__ ((format (printf,f,a)))
52 # define GT_GCC_A_PRINTF(f, a)
55 #define DIM(v) (sizeof(v)/sizeof((v)[0]))
56 #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
57 *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
58 #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
63 /* Minimal argp implementation. */
65 /* Differences to ARGP:
66 argp_program_version: Required.
67 argp_program_bug_address: Required.
68 argp_program_version_hook: Not supported.
69 argp_err_exit_status: Required.
70 struct argp: Children and help_filter not supported.
71 argp_domain: Not supported.
72 struct argp_option: Group not supported. Options are printed in
73 order given. Flags OPTION_ALIAS, OPTION_DOC and OPTION_NO_USAGE
75 argp_parse: No flags are supported (ARGP_PARSE_ARGV0, ARGP_NO_ERRS,
76 ARGP_NO_ARGS, ARGP_IN_ORDER, ARGP_NO_HELP, ARGP_NO_EXIT,
77 ARGP_LONG_ONLY, ARGP_SILENT). ARGP must not be NULL.
78 argp_help: Flag ARGP_HELP_LONG_ONLY not supported.
79 argp_state: argc, argv, next may not be modified and should not be used. */
81 extern const char *argp_program_version;
82 extern const char *argp_program_bug_address;
83 extern error_t argp_err_exit_status;
90 #define OPTION_ARG_OPTIONAL 0x1
91 #define OPTION_HIDDEN 0x2
100 const struct argp *const root_argp;
117 # define ARGP_ERR_UNKNOWN EDEADLK /* POSIX */
119 # define ARGP_ERR_UNKNOWN EDEADLOCK /* *GNU/kFreebsd does not define this) */
121 #define ARGP_KEY_ARG 0
122 #define ARGP_KEY_ARGS 0x1000006
123 #define ARGP_KEY_END 0x1000001
124 #define ARGP_KEY_NO_ARGS 0x1000002
125 #define ARGP_KEY_INIT 0x1000003
126 #define ARGP_KEY_FINI 0x1000007
127 #define ARGP_KEY_SUCCESS 0x1000004
128 #define ARGP_KEY_ERROR 0x1000005
129 typedef error_t (*argp_parser_t) (int key, char *arg, struct argp_state *state);
133 const struct argp_option *options;
134 argp_parser_t parser;
135 const char *args_doc;
138 const struct argp_child *children;
139 char *(*help_filter) (int key, const char *text, void *input);
140 const char *argp_domain;
143 #define ARGP_HELP_USAGE ARGP_HELP_SHORT_USAGE
144 #define ARGP_HELP_SHORT_USAGE 0x02
145 #define ARGP_HELP_SEE 0x04
146 #define ARGP_HELP_LONG 0x08
147 #define ARGP_HELP_PRE_DOC 0x10
148 #define ARGP_HELP_POST_DOC 0x20
149 #define ARGP_HELP_DOC (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC)
150 #define ARGP_HELP_BUG_ADDR 0x40
151 #define ARGP_HELP_EXIT_ERR 0x100
152 #define ARGP_HELP_EXIT_OK 0x200
153 #define ARGP_HELP_STD_ERR (ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
154 #define ARGP_HELP_STD_USAGE \
155 (ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
156 #define ARGP_HELP_STD_HELP \
157 (ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK \
158 | ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR)
161 void argp_error (const struct argp_state *state,
162 const char *fmt, ...) GT_GCC_A_PRINTF(2, 3);
167 _argp_pname (char *name)
170 char *bname = strrchr (pname, '/');
172 bname = strrchr (pname, '\\');
180 _argp_state_help (const struct argp *argp, const struct argp_state *state,
181 FILE *stream, unsigned flags, char *name)
186 if (flags & ARGP_HELP_SHORT_USAGE)
187 fprintf (stream, "Usage: %s [OPTIONS...] %s\n", name, argp->args_doc);
188 if (flags & ARGP_HELP_SEE)
189 fprintf (stream, "Try `%s --help' or `%s --usage' for more information.\n",
191 if (flags & ARGP_HELP_PRE_DOC)
195 strncpy (buf, argp->doc, sizeof (buf));
196 buf[sizeof (buf) - 1] = '\0';
197 end = strchr (buf, '\v');
200 fprintf (stream, "%s\n%s", buf, buf[0] ? "\n" : "");
202 if (flags & ARGP_HELP_LONG)
204 const struct argp_option *opt = argp->options;
208 char spaces[NSPACES + 1] = " ";
210 fprintf (stream, " ");
212 if (isascii (opt->key))
214 fprintf (stream, "-%c", opt->key);
218 fprintf (stream, ", ");
224 fprintf (stream, "--%s", opt->name);
225 len += 2 + strlen (opt->name);
227 if (opt->arg && (opt->flags & OPTION_ARG_OPTIONAL))
229 fprintf (stream, "[=%s]", opt->arg);
230 len += 3 + strlen (opt->arg);
234 fprintf (stream, "=%s", opt->arg);
235 len += 1 + strlen (opt->arg);
239 spaces[NSPACES - len] = '\0';
240 fprintf (stream, "%s%s\n", spaces, opt->doc);
243 fprintf (stream, " -?, --help Give this help list\n");
244 fprintf (stream, " --usage Give a short usage "
247 if (flags & ARGP_HELP_POST_DOC)
251 strncpy (buf, argp->doc, sizeof (buf));
252 buf[sizeof (buf) - 1] = '\0';
253 end = strchr (buf, '\v');
258 fprintf (stream, "\n%s\n", end);
260 fprintf (stream, "\nMandatory or optional arguments to long options are also mandatory or optional\n");
261 fprintf (stream, "for any corresponding short options.\n");
263 if (flags & ARGP_HELP_BUG_ADDR)
264 fprintf (stream, "\nReport bugs to %s.\n", argp_program_bug_address);
266 if (flags & ARGP_HELP_EXIT_ERR)
267 exit (argp_err_exit_status);
268 if (flags & ARGP_HELP_EXIT_OK)
274 argp_usage (const struct argp_state *state)
276 _argp_state_help (state->root_argp, state, state->err_stream,
277 ARGP_HELP_STD_USAGE, state->name);
282 argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags)
284 _argp_state_help (state->root_argp, state, stream, flags, state->name);
289 argp_error (const struct argp_state *state, const char *fmt, ...)
293 fprintf (state->err_stream, "%s: ", state->name);
295 vfprintf (state->err_stream, fmt, ap);
297 fprintf (state->err_stream, "\n");
298 argp_state_help (state, state->err_stream, ARGP_HELP_STD_ERR);
299 exit (argp_err_exit_status);
304 argp_help (const struct argp *argp, FILE *stream, unsigned flags, char *name)
306 _argp_state_help (argp, NULL, stream, flags, name);
311 argp_parse (const struct argp *argp, int argc,
312 char **argv, unsigned flags, int *arg_index, void *input)
315 struct argp_state state = { argp, argc, argv, 1, flags, 0, 0, input,
316 NULL, NULL, _argp_pname (argv[0]),
317 stderr, stdout, NULL };
318 /* All non-option arguments are collected at the beginning of
319 &argv[1] during processing. This is a counter for their number. */
320 int non_opt_args = 0;
322 rc = argp->parser (ARGP_KEY_INIT, NULL, &state);
323 if (rc && rc != ARGP_ERR_UNKNOWN)
326 while (state.next < state.argc - non_opt_args)
328 int idx = state.next;
331 if (! strcasecmp (state.argv[idx], "--"))
337 if (state.quoted || state.argv[idx][0] != '-')
339 char *arg_saved = state.argv[idx];
341 memmove (&state.argv[idx], &state.argv[idx + 1],
342 (state.argc - 1 - idx) * sizeof (char *));
343 state.argv[argc - 1] = arg_saved;
346 else if (! strcasecmp (state.argv[idx], "--help")
347 || !strcmp (state.argv[idx], "-?"))
349 argp_state_help (&state, state.out_stream, ARGP_HELP_STD_HELP);
351 else if (! strcasecmp (state.argv[idx], "--usage"))
353 argp_state_help (&state, state.out_stream,
354 ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
356 else if (! strcasecmp (state.argv[idx], "--version")
357 || !strcmp (state.argv[idx], "-V"))
359 fprintf (state.out_stream, "%s\n", argp_program_version);
364 /* Search for option and call parser with its KEY. */
365 int key = ARGP_KEY_ARG; /* Just some dummy value. */
366 const struct argp_option *opt = argp->options;
370 /* Check for --opt=value syntax. */
371 arg = strchr (state.argv[idx], '=');
378 if (state.argv[idx][1] != '-')
379 key = state.argv[idx][1];
381 while (! found && opt->key)
384 || (key == ARGP_KEY_ARG
385 && ! strcasecmp (&state.argv[idx][2], opt->name)))
387 if (arg && !opt->arg)
388 argp_error (&state, "Option %s does not take an argument",
390 if (opt->arg && state.next < state.argc
391 && state.argv[idx + 1][0] != '-')
393 arg = state.argv[idx + 1];
396 if (opt->arg && !(opt->flags & OPTION_ARG_OPTIONAL))
397 argp_error (&state, "Option %s requires an argument",
400 rc = argp->parser (opt->key, arg, &state);
401 if (rc == ARGP_ERR_UNKNOWN)
410 argp_error (&state, "Unknown option %s", state.argv[idx]);
414 while (state.next < state.argc)
416 /* Call parser for all non-option args. */
417 int idx = state.next;
419 rc = argp->parser (ARGP_KEY_ARG, state.argv[idx], &state);
420 if (rc && rc != ARGP_ERR_UNKNOWN)
422 if (rc == ARGP_ERR_UNKNOWN)
424 int old_next = state.next;
425 rc = argp->parser (ARGP_KEY_ARGS, NULL, &state);
426 if (rc == ARGP_ERR_UNKNOWN)
428 argp_error (&state, "Too many arguments");
431 if (! rc && state.next == old_next)
433 state.arg_num += state.argc - state.next;
434 state.next = state.argc;
441 if (state.arg_num == 0)
443 rc = argp->parser (ARGP_KEY_NO_ARGS, NULL, &state);
444 if (rc && rc != ARGP_ERR_UNKNOWN)
447 if (state.next == state.argc)
449 rc = argp->parser (ARGP_KEY_END, NULL, &state);
450 if (rc && rc != ARGP_ERR_UNKNOWN)
453 rc = argp->parser (ARGP_KEY_FINI, NULL, &state);
454 if (rc && rc != ARGP_ERR_UNKNOWN)
458 argp->parser (ARGP_KEY_SUCCESS, NULL, &state);
463 argp_error (&state, "unexpected error: %s", strerror (rc));
464 argp->parser (ARGP_KEY_ERROR, NULL, &state);
467 argp->parser (ARGP_KEY_FINI, NULL, &state);
470 *arg_index = state.next - 1;
479 char *program_name = "gpgme-tool";
481 #define spacep(p) (*(p) == ' ' || *(p) == '\t')
484 void log_error (int status, gpg_error_t errnum,
485 const char *fmt, ...) GT_GCC_A_PRINTF(3,4);
496 log_error (int status, gpg_error_t errnum, const char *fmt, ...)
500 fprintf (log_stream, "%s: ", program_name);
502 vfprintf (log_stream, fmt, ap);
505 fprintf (log_stream, ": %s <%s>", gpg_strerror (errnum),
506 gpg_strsource (errnum));
507 fprintf (log_stream, "\n");
513 /* Note that it is sufficient to allocate the target string D as long
514 as the source string S, i.e.: strlen(s)+1;. D == S is allowed. */
516 strcpy_escaped_plus (char *d, const char *s)
520 if (*s == '%' && s[1] && s[2])
535 /* Check whether the option NAME appears in LINE. */
537 has_option (const char *line, const char *name)
540 int n = strlen (name);
542 s = strstr (line, name);
543 return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
546 /* Skip over options. It is assumed that leading spaces have been
547 removed (this is the case for lines passed to a handler from
548 assuan). Blanks after the options are also removed. */
550 skip_options (char *line)
552 while ( *line == '-' && line[1] == '-' )
554 while (*line && !spacep (line))
556 while (spacep (line))
565 typedef gpg_error_t (*result_xml_write_cb_t) (void *hook, const void *buf,
568 struct result_xml_state
571 result_xml_write_cb_t cb;
577 int had_data[MAX_TAGS];
582 result_init (struct result_xml_state *state, int indent,
583 result_xml_write_cb_t cb, void *hook)
585 memset (state, '\0', sizeof (*state));
586 state->indent = indent;
593 result_xml_indent (struct result_xml_state *state)
595 char spaces[state->indent + 1];
597 for (i = 0; i < state->indent; i++)
600 return (*state->cb) (state->hook, spaces, i);
605 result_xml_tag_start (struct result_xml_state *state, char *name, ...)
607 result_xml_write_cb_t cb = state->cb;
608 void *hook = state->hook;
615 if (state->next_tag > 0)
617 if (! state->had_data[state->next_tag - 1])
619 (*cb) (hook, ">\n", 2);
620 (*cb) (hook, NULL, 0);
622 state->had_data[state->next_tag - 1] = 1;
625 result_xml_indent (state);
626 (*cb) (hook, "<", 1);
627 (*cb) (hook, name, strlen (name));
629 state->tag[state->next_tag] = name;
630 state->had_data[state->next_tag] = 0;
636 attr = va_arg (ap, char *);
640 attr_val = va_arg (ap, char *);
641 if (attr_val == NULL)
644 (*cb) (hook, " ", 1);
645 (*cb) (hook, attr, strlen (attr));
646 (*cb) (hook, "=\"", 2);
647 (*cb) (hook, attr_val, strlen (attr_val));
648 (*cb) (hook, "\"", 1);
656 result_xml_tag_data (struct result_xml_state *state, char *data)
658 result_xml_write_cb_t cb = state->cb;
659 void *hook = state->hook;
661 if (state->had_data[state->next_tag - 1])
663 (*cb) (hook, "\n", 2);
664 (*cb) (hook, NULL, 0);
665 result_xml_indent (state);
668 (*cb) (hook, ">", 1);
669 state->had_data[state->next_tag - 1] = 2;
671 (*cb) (hook, data, strlen (data));
678 result_xml_tag_end (struct result_xml_state *state)
680 result_xml_write_cb_t cb = state->cb;
681 void *hook = state->hook;
686 if (state->had_data[state->next_tag])
688 if (state->had_data[state->next_tag] == 1)
689 result_xml_indent (state);
690 (*cb) (hook, "</", 2);
691 (*cb) (hook, state->tag[state->next_tag],
692 strlen (state->tag[state->next_tag]));
693 (*cb) (hook, ">\n", 2);
694 (*cb) (hook, NULL, 0);
698 (*cb) (hook, " />\n", 4);
699 (*cb) (hook, NULL, 0);
706 result_add_error (struct result_xml_state *state, char *name, gpg_error_t err)
710 snprintf (code, sizeof (code) - 1, "0x%x", err);
711 snprintf (msg, sizeof (msg) - 1, "%s <%s>",
712 gpg_strerror (err), gpg_strsource (err));
713 result_xml_tag_start (state, name, "value", code, NULL);
714 result_xml_tag_data (state, msg);
715 result_xml_tag_end (state);
721 result_add_pubkey_algo (struct result_xml_state *state,
722 char *name, gpgme_pubkey_algo_t algo)
726 snprintf (code, sizeof (code) - 1, "0x%x", algo);
727 snprintf (msg, sizeof (msg) - 1, "%s",
728 gpgme_pubkey_algo_name (algo));
729 result_xml_tag_start (state, name, "value", code, NULL);
730 result_xml_tag_data (state, msg);
731 result_xml_tag_end (state);
737 result_add_hash_algo (struct result_xml_state *state,
738 char *name, gpgme_hash_algo_t algo)
742 snprintf (code, sizeof (code) - 1, "0x%x", algo);
743 snprintf (msg, sizeof (msg) - 1, "%s",
744 gpgme_hash_algo_name (algo));
745 result_xml_tag_start (state, name, "value", code, NULL);
746 result_xml_tag_data (state, msg);
747 result_xml_tag_end (state);
753 result_add_keyid (struct result_xml_state *state, char *name, char *keyid)
755 result_xml_tag_start (state, name, NULL);
756 result_xml_tag_data (state, keyid);
757 result_xml_tag_end (state);
763 result_add_fpr (struct result_xml_state *state, char *name, char *fpr)
765 result_xml_tag_start (state, name, NULL);
766 result_xml_tag_data (state, fpr);
767 result_xml_tag_end (state);
773 result_add_timestamp (struct result_xml_state *state, char *name,
774 unsigned int timestamp)
778 snprintf (code, sizeof (code) - 1, "%ui", timestamp);
779 result_xml_tag_start (state, name, "unix", code, NULL);
780 result_xml_tag_end (state);
786 result_add_sig_mode (struct result_xml_state *state, char *name,
787 gpgme_sig_mode_t sig_mode)
792 snprintf (code, sizeof (code) - 1, "%i", sig_mode);
795 case GPGME_SIG_MODE_NORMAL:
798 case GPGME_SIG_MODE_DETACH:
801 case GPGME_SIG_MODE_CLEAR:
808 result_xml_tag_start (state, name, "type", mode, "value", code, NULL);
809 result_xml_tag_data (state, mode);
810 result_xml_tag_end (state);
816 result_add_value (struct result_xml_state *state,
817 char *name, unsigned int val)
821 snprintf (code, sizeof (code) - 1, "0x%x", val);
822 result_xml_tag_start (state, name, "value", code, NULL);
823 result_xml_tag_end (state);
829 result_add_string (struct result_xml_state *state,
830 char *name, char *str)
832 result_xml_tag_start (state, name, NULL);
833 result_xml_tag_data (state, str);
834 result_xml_tag_end (state);
840 result_encrypt_to_xml (gpgme_ctx_t ctx, int indent,
841 result_xml_write_cb_t cb, void *hook)
843 struct result_xml_state state;
844 gpgme_encrypt_result_t res = gpgme_op_encrypt_result (ctx);
845 gpgme_invalid_key_t inv_recp;
850 result_init (&state, indent, cb, hook);
851 result_xml_tag_start (&state, "encrypt-result", NULL);
853 inv_recp = res->invalid_recipients;
856 result_xml_tag_start (&state, "invalid-recipients", NULL);
860 result_xml_tag_start (&state, "invalid-key", NULL);
862 result_add_fpr (&state, "fpr", inv_recp->fpr);
863 result_add_error (&state, "reason", inv_recp->reason);
864 result_xml_tag_end (&state);
865 inv_recp = inv_recp->next;
867 result_xml_tag_end (&state);
869 result_xml_tag_end (&state);
876 result_decrypt_to_xml (gpgme_ctx_t ctx, int indent,
877 result_xml_write_cb_t cb, void *hook)
879 struct result_xml_state state;
880 gpgme_decrypt_result_t res = gpgme_op_decrypt_result (ctx);
881 gpgme_recipient_t recp;
886 result_init (&state, indent, cb, hook);
887 result_xml_tag_start (&state, "decrypt-result", NULL);
891 result_xml_tag_start (&state, "file-name", NULL);
892 result_xml_tag_data (&state, res->file_name);
893 result_xml_tag_end (&state);
895 if (res->unsupported_algorithm)
897 result_xml_tag_start (&state, "unsupported-alogorithm", NULL);
898 result_xml_tag_data (&state, res->unsupported_algorithm);
899 result_xml_tag_end (&state);
901 if (res->wrong_key_usage)
903 result_xml_tag_start (&state, "wrong-key-usage", NULL);
904 result_xml_tag_end (&state);
907 recp = res->recipients;
910 result_xml_tag_start (&state, "recipients", NULL);
913 result_xml_tag_start (&state, "recipient", NULL);
914 result_add_keyid (&state, "keyid", recp->keyid);
915 result_add_pubkey_algo (&state, "pubkey-algo", recp->pubkey_algo);
916 result_add_error (&state, "status", recp->status);
917 result_xml_tag_end (&state);
920 result_xml_tag_end (&state);
922 result_xml_tag_end (&state);
929 result_sign_to_xml (gpgme_ctx_t ctx, int indent,
930 result_xml_write_cb_t cb, void *hook)
932 struct result_xml_state state;
933 gpgme_sign_result_t res = gpgme_op_sign_result (ctx);
934 gpgme_invalid_key_t inv_key;
935 gpgme_new_signature_t new_sig;
940 result_init (&state, indent, cb, hook);
941 result_xml_tag_start (&state, "sign-result", NULL);
943 inv_key = res->invalid_signers;
946 result_xml_tag_start (&state, "invalid-signers", NULL);
950 result_xml_tag_start (&state, "invalid-key", NULL);
952 result_add_fpr (&state, "fpr", inv_key->fpr);
953 result_add_error (&state, "reason", inv_key->reason);
954 result_xml_tag_end (&state);
955 inv_key = inv_key->next;
957 result_xml_tag_end (&state);
960 new_sig = res->signatures;
963 result_xml_tag_start (&state, "signatures", NULL);
967 result_xml_tag_start (&state, "new-signature", NULL);
968 result_add_sig_mode (&state, "type", new_sig->type);
969 result_add_pubkey_algo (&state, "pubkey-algo", new_sig->pubkey_algo);
970 result_add_hash_algo (&state, "hash-algo", new_sig->hash_algo);
971 result_add_timestamp (&state, "timestamp", new_sig->timestamp);
973 result_add_fpr (&state, "fpr", new_sig->fpr);
974 result_add_value (&state, "sig-class", new_sig->sig_class);
976 result_xml_tag_end (&state);
977 new_sig = new_sig->next;
979 result_xml_tag_end (&state);
982 result_xml_tag_end (&state);
989 result_verify_to_xml (gpgme_ctx_t ctx, int indent,
990 result_xml_write_cb_t cb, void *hook)
992 struct result_xml_state state;
993 gpgme_verify_result_t res = gpgme_op_verify_result (ctx);
994 gpgme_signature_t sig;
999 result_init (&state, indent, cb, hook);
1000 result_xml_tag_start (&state, "verify-result", NULL);
1004 result_xml_tag_start (&state, "file-name", NULL);
1005 result_xml_tag_data (&state, res->file_name);
1006 result_xml_tag_end (&state);
1009 sig = res->signatures;
1012 result_xml_tag_start (&state, "signatures", NULL);
1016 result_xml_tag_start (&state, "signature", NULL);
1018 /* FIXME: Could be done better. */
1019 result_add_value (&state, "summary", sig->summary);
1021 result_add_fpr (&state, "fpr", sig->fpr);
1022 result_add_error (&state, "status", sig->status);
1023 /* FIXME: notations */
1024 result_add_timestamp (&state, "timestamp", sig->timestamp);
1025 result_add_timestamp (&state, "exp-timestamp", sig->exp_timestamp);
1026 result_add_value (&state, "wrong-key-usage", sig->wrong_key_usage);
1027 result_add_value (&state, "pka-trust", sig->pka_trust);
1028 result_add_value (&state, "chain-model", sig->chain_model);
1029 result_add_value (&state, "validity", sig->validity);
1030 result_add_error (&state, "validity-reason", sig->validity_reason);
1031 result_add_pubkey_algo (&state, "pubkey-algo", sig->pubkey_algo);
1032 result_add_hash_algo (&state, "hash-algo", sig->hash_algo);
1033 if (sig->pka_address)
1034 result_add_string (&state, "pka_address", sig->pka_address);
1036 result_xml_tag_end (&state);
1039 result_xml_tag_end (&state);
1042 result_xml_tag_end (&state);
1049 result_import_to_xml (gpgme_ctx_t ctx, int indent,
1050 result_xml_write_cb_t cb, void *hook)
1052 struct result_xml_state state;
1053 gpgme_import_result_t res = gpgme_op_import_result (ctx);
1054 gpgme_import_status_t stat;
1059 result_init (&state, indent, cb, hook);
1060 result_xml_tag_start (&state, "import-result", NULL);
1062 result_add_value (&state, "considered", res->considered);
1063 result_add_value (&state, "no-user-id", res->no_user_id);
1064 result_add_value (&state, "imported", res->imported);
1065 result_add_value (&state, "imported-rsa", res->imported_rsa);
1066 result_add_value (&state, "unchanged", res->unchanged);
1067 result_add_value (&state, "new-user-ids", res->new_user_ids);
1068 result_add_value (&state, "new-sub-keys", res->new_sub_keys);
1069 result_add_value (&state, "new-signatures", res->new_signatures);
1070 result_add_value (&state, "new-revocations", res->new_revocations);
1071 result_add_value (&state, "secret-read", res->secret_read);
1072 result_add_value (&state, "secret-imported", res->secret_imported);
1073 result_add_value (&state, "secret-unchanged", res->secret_unchanged);
1074 result_add_value (&state, "skipped-new-keys", res->skipped_new_keys);
1075 result_add_value (&state, "not-imported", res->not_imported);
1077 stat = res->imports;
1080 result_xml_tag_start (&state, "imports", NULL);
1084 result_xml_tag_start (&state, "import-status", NULL);
1087 result_add_fpr (&state, "fpr", stat->fpr);
1088 result_add_error (&state, "result", stat->result);
1089 /* FIXME: Could be done better. */
1090 result_add_value (&state, "status", stat->status);
1092 result_xml_tag_end (&state);
1095 result_xml_tag_end (&state);
1098 result_xml_tag_end (&state);
1105 result_genkey_to_xml (gpgme_ctx_t ctx, int indent,
1106 result_xml_write_cb_t cb, void *hook)
1108 struct result_xml_state state;
1109 gpgme_genkey_result_t res = gpgme_op_genkey_result (ctx);
1114 result_init (&state, indent, cb, hook);
1115 result_xml_tag_start (&state, "genkey-result", NULL);
1117 result_add_value (&state, "primary", res->primary);
1118 result_add_value (&state, "sub", res->sub);
1120 result_add_fpr (&state, "fpr", res->fpr);
1122 result_xml_tag_end (&state);
1129 result_keylist_to_xml (gpgme_ctx_t ctx, int indent,
1130 result_xml_write_cb_t cb, void *hook)
1132 struct result_xml_state state;
1133 gpgme_keylist_result_t res = gpgme_op_keylist_result (ctx);
1138 result_init (&state, indent, cb, hook);
1139 result_xml_tag_start (&state, "keylist-result", NULL);
1141 result_add_value (&state, "truncated", res->truncated);
1143 result_xml_tag_end (&state);
1150 result_vfs_mount_to_xml (gpgme_ctx_t ctx, int indent,
1151 result_xml_write_cb_t cb, void *hook)
1153 struct result_xml_state state;
1154 gpgme_vfs_mount_result_t res = gpgme_op_vfs_mount_result (ctx);
1159 result_init (&state, indent, cb, hook);
1160 result_xml_tag_start (&state, "vfs-mount-result", NULL);
1162 result_add_string (&state, "mount-dir", res->mount_dir);
1164 result_xml_tag_end (&state);
1177 STATUS_INCLUDE_CERTS,
1178 STATUS_KEYLIST_MODE,
1180 STATUS_ENCRYPT_RESULT
1183 const char *status_string[] =
1199 #define MAX_RECIPIENTS 10
1200 gpgme_key_t recipients[MAX_RECIPIENTS + 1];
1203 gpg_error_t (*write_status) (void *hook, const char *status, const char *msg);
1204 void *write_status_hook;
1205 gpg_error_t (*write_data) (void *hook, const void *buf, size_t len);
1206 void *write_data_hook;
1208 typedef struct gpgme_tool *gpgme_tool_t;
1211 /* Forward declaration. */
1212 void gt_write_status (gpgme_tool_t gt,
1213 status_t status, ...) GT_GCC_A_SENTINEL(0);
1216 _gt_progress_cb (void *opaque, const char *what,
1217 int type, int current, int total)
1219 gpgme_tool_t gt = opaque;
1222 snprintf (buf, sizeof (buf), "0x%02x %i %i", type, current, total);
1223 gt_write_status (gt, STATUS_PROGRESS, what, buf, NULL);
1228 _gt_gpgme_new (gpgme_tool_t gt, gpgme_ctx_t *ctx)
1232 err = gpgme_new (ctx);
1235 gpgme_set_progress_cb (*ctx, _gt_progress_cb, gt);
1241 gt_init (gpgme_tool_t gt)
1243 memset (gt, '\0', sizeof (*gt));
1246 err = _gt_gpgme_new (gt, >->ctx);
1248 log_error (1, err, "can't create gpgme context");
1253 gt_signers_add (gpgme_tool_t gt, const char *fpr)
1258 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1262 return gpgme_signers_add (gt->ctx, key);
1267 gt_signers_clear (gpgme_tool_t gt)
1269 gpgme_signers_clear (gt->ctx);
1275 gt_get_key (gpgme_tool_t gt, const char *pattern, gpgme_key_t *r_key)
1278 gpgme_ctx_t listctx;
1282 if (!gt || !r_key || !pattern)
1283 return gpg_error (GPG_ERR_INV_VALUE);
1287 err = gpgme_new (&listctx);
1292 gpgme_protocol_t proto;
1293 gpgme_engine_info_t info;
1295 /* Clone the relevant state. */
1296 proto = gpgme_get_protocol (ctx);
1297 /* The g13 protocol does not allow keylisting, we need to choose
1299 if (proto == GPGME_PROTOCOL_G13)
1300 proto = GPGME_PROTOCOL_OpenPGP;
1302 gpgme_set_protocol (listctx, proto);
1303 gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
1304 info = gpgme_ctx_get_engine_info (ctx);
1305 while (info && info->protocol != proto)
1308 gpgme_ctx_set_engine_info (listctx, proto,
1309 info->file_name, info->home_dir);
1312 err = gpgme_op_keylist_start (listctx, pattern, 0);
1314 err = gpgme_op_keylist_next (listctx, r_key);
1318 err = gpgme_op_keylist_next (listctx, &key);
1319 if (gpgme_err_code (err) == GPG_ERR_EOF)
1324 && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr
1325 && key && key->subkeys && key->subkeys->fpr
1326 && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr))
1328 /* The fingerprint is identical. We assume that this is
1329 the same key and don't mark it as an ambiguous. This
1330 problem may occur with corrupted keyrings and has
1331 been noticed often with gpgsm. In fact gpgsm uses a
1332 similar hack to sort out such duplicates but it can't
1333 do that while listing keys. */
1334 gpgme_key_unref (key);
1339 gpgme_key_unref (key);
1340 err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
1342 gpgme_key_unref (*r_key);
1345 gpgme_release (listctx);
1348 gt_write_status (gt, STATUS_RECIPIENT,
1349 ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
1350 (*r_key)->subkeys->fpr : "invalid", NULL);
1356 gt_recipients_add (gpgme_tool_t gt, const char *pattern)
1361 if (gt->recipients_nr >= MAX_RECIPIENTS)
1362 return gpg_error_from_errno (ENOMEM);
1364 if (gpgme_get_protocol (gt->ctx) == GPGME_PROTOCOL_UISERVER)
1365 err = gpgme_key_from_uid (&key, pattern);
1367 err = gt_get_key (gt, pattern, &key);
1371 gt->recipients[gt->recipients_nr++] = key;
1377 gt_recipients_clear (gpgme_tool_t gt)
1381 for (idx = 0; idx < gt->recipients_nr; idx++)
1382 gpgme_key_unref (gt->recipients[idx]);
1383 memset (gt->recipients, '\0', gt->recipients_nr * sizeof (gpgme_key_t));
1384 gt->recipients_nr = 0;
1389 gt_reset (gpgme_tool_t gt)
1394 err = _gt_gpgme_new (gt, &ctx);
1398 gpgme_release (gt->ctx);
1400 gt_recipients_clear (gt);
1406 gt_write_status (gpgme_tool_t gt, status_t status, ...)
1415 va_start (ap, status);
1418 while ((text = va_arg (ap, const char *)))
1425 while (*text && n < sizeof (buf) - 2)
1434 err = gt->write_status (gt->write_status_hook, status_string[status], buf);
1436 log_error (1, err, "can't write status line");
1441 gt_write_data (gpgme_tool_t gt, const void *buf, size_t len)
1443 return gt->write_data (gt->write_data_hook, buf, len);
1448 gt_get_engine_info (gpgme_tool_t gt, gpgme_protocol_t proto)
1450 gpgme_engine_info_t info;
1451 info = gpgme_ctx_get_engine_info (gt->ctx);
1454 if (proto == GPGME_PROTOCOL_UNKNOWN || proto == info->protocol)
1455 gt_write_status (gt, STATUS_ENGINE,
1456 gpgme_get_protocol_name (info->protocol),
1457 info->file_name, info->version,
1458 info->req_version, info->home_dir, NULL);
1466 gt_protocol_from_name (const char *name)
1468 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_OpenPGP)))
1469 return GPGME_PROTOCOL_OpenPGP;
1470 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_CMS)))
1471 return GPGME_PROTOCOL_CMS;
1472 if (! strcasecmp (name,gpgme_get_protocol_name (GPGME_PROTOCOL_GPGCONF)))
1473 return GPGME_PROTOCOL_GPGCONF;
1474 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_ASSUAN)))
1475 return GPGME_PROTOCOL_ASSUAN;
1476 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_G13)))
1477 return GPGME_PROTOCOL_G13;
1478 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_UISERVER)))
1479 return GPGME_PROTOCOL_UISERVER;
1480 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_DEFAULT)))
1481 return GPGME_PROTOCOL_DEFAULT;
1482 return GPGME_PROTOCOL_UNKNOWN;
1487 gt_set_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
1489 return gpgme_set_protocol (gt->ctx, proto);
1494 gt_get_protocol (gpgme_tool_t gt)
1496 gpgme_protocol_t proto = gpgme_get_protocol (gt->ctx);
1498 gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
1506 gt_set_sub_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
1508 return gpgme_set_sub_protocol (gt->ctx, proto);
1513 gt_get_sub_protocol (gpgme_tool_t gt)
1515 gpgme_protocol_t proto = gpgme_get_sub_protocol (gt->ctx);
1517 gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
1525 gt_set_armor (gpgme_tool_t gt, int armor)
1527 gpgme_set_armor (gt->ctx, armor);
1533 gt_get_armor (gpgme_tool_t gt)
1535 gt_write_status (gt, STATUS_ARMOR,
1536 gpgme_get_armor (gt->ctx) ? "true" : "false", NULL);
1543 gt_set_textmode (gpgme_tool_t gt, int textmode)
1545 gpgme_set_textmode (gt->ctx, textmode);
1551 gt_get_textmode (gpgme_tool_t gt)
1553 gt_write_status (gt, STATUS_TEXTMODE,
1554 gpgme_get_textmode (gt->ctx) ? "true" : "false", NULL);
1561 gt_set_keylist_mode (gpgme_tool_t gt, gpgme_keylist_mode_t keylist_mode)
1563 gpgme_set_keylist_mode (gt->ctx, keylist_mode);
1569 gt_get_keylist_mode (gpgme_tool_t gt)
1571 #define NR_KEYLIST_MODES 6
1572 const char *modes[NR_KEYLIST_MODES + 1];
1574 gpgme_keylist_mode_t mode = gpgme_get_keylist_mode (gt->ctx);
1576 if (mode & GPGME_KEYLIST_MODE_LOCAL)
1577 modes[idx++] = "local";
1578 if (mode & GPGME_KEYLIST_MODE_EXTERN)
1579 modes[idx++] = "extern";
1580 if (mode & GPGME_KEYLIST_MODE_SIGS)
1581 modes[idx++] = "sigs";
1582 if (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS)
1583 modes[idx++] = "sig_notations";
1584 if (mode & GPGME_KEYLIST_MODE_EPHEMERAL)
1585 modes[idx++] = "ephemeral";
1586 if (mode & GPGME_KEYLIST_MODE_VALIDATE)
1587 modes[idx++] = "validate";
1588 modes[idx++] = NULL;
1590 gt_write_status (gt, STATUS_KEYLIST_MODE, modes[0], modes[1], modes[2],
1591 modes[3], modes[4], modes[5], modes[6], NULL);
1598 gt_set_include_certs (gpgme_tool_t gt, int include_certs)
1600 gpgme_set_include_certs (gt->ctx, include_certs);
1606 gt_get_include_certs (gpgme_tool_t gt)
1608 int include_certs = gpgme_get_include_certs (gt->ctx);
1611 if (include_certs == GPGME_INCLUDE_CERTS_DEFAULT)
1612 strcpy (buf, "default");
1614 snprintf (buf, sizeof (buf), "%i", include_certs);
1616 gt_write_status (gt, STATUS_INCLUDE_CERTS, buf, NULL);
1623 gt_decrypt_verify (gpgme_tool_t gt, gpgme_data_t cipher, gpgme_data_t plain,
1627 return gpgme_op_decrypt_verify (gt->ctx, cipher, plain);
1629 return gpgme_op_decrypt (gt->ctx, cipher, plain);
1634 gt_sign_encrypt (gpgme_tool_t gt, gpgme_encrypt_flags_t flags,
1635 gpgme_data_t plain, gpgme_data_t cipher, int sign)
1640 err = gpgme_op_encrypt_sign (gt->ctx, gt->recipients, flags, plain, cipher);
1642 err = gpgme_op_encrypt (gt->ctx, gt->recipients, flags, plain, cipher);
1644 gt_recipients_clear (gt);
1651 gt_sign (gpgme_tool_t gt, gpgme_data_t plain, gpgme_data_t sig,
1652 gpgme_sig_mode_t mode)
1654 return gpgme_op_sign (gt->ctx, plain, sig, mode);
1659 gt_verify (gpgme_tool_t gt, gpgme_data_t sig, gpgme_data_t sig_text,
1662 return gpgme_op_verify (gt->ctx, sig, sig_text, plain);
1667 gt_import (gpgme_tool_t gt, gpgme_data_t data)
1669 return gpgme_op_import (gt->ctx, data);
1674 gt_export (gpgme_tool_t gt, const char *pattern[], gpgme_export_mode_t mode,
1677 return gpgme_op_export_ext (gt->ctx, pattern, mode, data);
1682 gt_genkey (gpgme_tool_t gt, const char *parms, gpgme_data_t public,
1683 gpgme_data_t secret)
1685 return gpgme_op_genkey (gt->ctx, parms, public, secret);
1690 gt_import_keys (gpgme_tool_t gt, char *fpr[])
1692 gpg_error_t err = 0;
1702 return gpg_error (GPG_ERR_INV_VALUE);
1704 keys = malloc ((cnt + 1) * sizeof (gpgme_key_t));
1706 return gpg_error_from_syserror ();
1708 for (idx = 0; idx < cnt; idx++)
1710 err = gpgme_get_key (gt->ctx, fpr[idx], &keys[idx], 0);
1717 err = gpgme_op_import_keys (gt->ctx, keys);
1722 gpgme_key_unref (keys[idx]);
1730 gt_delete (gpgme_tool_t gt, char *fpr, int allow_secret)
1735 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1739 err = gpgme_op_delete (gt->ctx, key, allow_secret);
1740 gpgme_key_unref (key);
1746 gt_keylist_start (gpgme_tool_t gt, const char *pattern[], int secret_only)
1748 return gpgme_op_keylist_ext_start (gt->ctx, pattern, secret_only, 0);
1753 gt_keylist_next (gpgme_tool_t gt, gpgme_key_t *key)
1755 return gpgme_op_keylist_next (gt->ctx, key);
1760 gt_getauditlog (gpgme_tool_t gt, gpgme_data_t output, unsigned int flags)
1762 return gpgme_op_getauditlog (gt->ctx, output, flags);
1767 gt_vfs_mount (gpgme_tool_t gt, const char *container_file,
1768 const char *mount_dir, int flags)
1772 err = gpgme_op_vfs_mount (gt->ctx, container_file, mount_dir, flags, &op_err);
1773 return err ? err : op_err;
1778 gt_vfs_create (gpgme_tool_t gt, const char *container_file, int flags)
1782 err = gpgme_op_vfs_create (gt->ctx, gt->recipients, container_file,
1784 gt_recipients_clear (gt);
1785 return err ? err : op_err;
1789 static const char hlp_passwd[] =
1790 "PASSWD <user-id>\n"
1792 "Ask the backend to change the passphrase for the key\n"
1793 "specified by USER-ID.";
1795 gt_passwd (gpgme_tool_t gt, char *fpr)
1800 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1802 return gpg_err_code (err) == GPG_ERR_EOF? gpg_error (GPG_ERR_NO_PUBKEY):err;
1804 err = gpgme_op_passwd (gt->ctx, key, 0);
1805 gpgme_key_unref (key);
1810 #define GT_RESULT_ENCRYPT 0x1
1811 #define GT_RESULT_DECRYPT 0x2
1812 #define GT_RESULT_SIGN 0x4
1813 #define GT_RESULT_VERIFY 0x8
1814 #define GT_RESULT_IMPORT 0x10
1815 #define GT_RESULT_GENKEY 0x20
1816 #define GT_RESULT_KEYLIST 0x40
1817 #define GT_RESULT_VFS_MOUNT 0x80
1818 #define GT_RESULT_ALL (~0U)
1821 gt_result (gpgme_tool_t gt, unsigned int flags)
1823 static const char xml_preamble1[] = "<?xml version=\"1.0\" "
1824 "encoding=\"UTF-8\" standalone=\"yes\"?>\n";
1825 static const char xml_preamble2[] = "<gpgme>\n";
1826 static const char xml_end[] = "</gpgme>\n";
1829 gt_write_data (gt, xml_preamble1, sizeof (xml_preamble1));
1830 gt_write_data (gt, NULL, 0);
1831 gt_write_data (gt, xml_preamble2, sizeof (xml_preamble2));
1832 gt_write_data (gt, NULL, 0);
1833 if (flags & GT_RESULT_ENCRYPT)
1834 result_encrypt_to_xml (gt->ctx, indent,
1835 (result_xml_write_cb_t) gt_write_data, gt);
1836 if (flags & GT_RESULT_DECRYPT)
1837 result_decrypt_to_xml (gt->ctx, indent,
1838 (result_xml_write_cb_t) gt_write_data, gt);
1839 if (flags & GT_RESULT_SIGN)
1840 result_sign_to_xml (gt->ctx, indent,
1841 (result_xml_write_cb_t) gt_write_data, gt);
1842 if (flags & GT_RESULT_VERIFY)
1843 result_verify_to_xml (gt->ctx, indent,
1844 (result_xml_write_cb_t) gt_write_data, gt);
1845 if (flags & GT_RESULT_IMPORT)
1846 result_import_to_xml (gt->ctx, indent,
1847 (result_xml_write_cb_t) gt_write_data, gt);
1848 if (flags & GT_RESULT_GENKEY)
1849 result_genkey_to_xml (gt->ctx, indent,
1850 (result_xml_write_cb_t) gt_write_data, gt);
1851 if (flags & GT_RESULT_KEYLIST)
1852 result_keylist_to_xml (gt->ctx, indent,
1853 (result_xml_write_cb_t) gt_write_data, gt);
1854 if (flags & GT_RESULT_VFS_MOUNT)
1855 result_vfs_mount_to_xml (gt->ctx, indent,
1856 (result_xml_write_cb_t) gt_write_data, gt);
1857 gt_write_data (gt, xml_end, sizeof (xml_end));
1870 assuan_context_t assuan_ctx;
1872 gpgme_data_encoding_t input_enc;
1873 gpgme_data_encoding_t output_enc;
1874 assuan_fd_t input_fd;
1875 char *input_filename;
1877 assuan_fd_t output_fd;
1878 char *output_filename;
1879 FILE *output_stream;
1880 assuan_fd_t message_fd;
1881 char *message_filename;
1882 FILE *message_stream;
1883 gpgme_data_encoding_t message_enc;
1888 server_write_status (void *hook, const char *status, const char *msg)
1890 struct server *server = hook;
1891 return assuan_write_status (server->assuan_ctx, status, msg);
1896 server_write_data (void *hook, const void *buf, size_t len)
1898 struct server *server = hook;
1899 return assuan_send_data (server->assuan_ctx, buf, len);
1905 server_parse_fd (assuan_context_t ctx, char *line, assuan_fd_t *rfd,
1908 *rfd = ASSUAN_INVALID_FD;
1911 if (! strncasecmp (line, "file=", 5))
1914 *filename = strdup (line + 5);
1916 return gpg_error_from_syserror();
1917 term = strchr (*filename, ' ');
1923 return assuan_command_parse_fd (ctx, line, rfd);
1927 static gpgme_data_encoding_t
1928 server_data_encoding (const char *line)
1930 if (strstr (line, "--binary"))
1931 return GPGME_DATA_ENCODING_BINARY;
1932 if (strstr (line, "--base64"))
1933 return GPGME_DATA_ENCODING_BASE64;
1934 if (strstr (line, "--armor"))
1935 return GPGME_DATA_ENCODING_ARMOR;
1936 if (strstr (line, "--url"))
1937 return GPGME_DATA_ENCODING_URL;
1938 if (strstr (line, "--urlesc"))
1939 return GPGME_DATA_ENCODING_URLESC;
1940 if (strstr (line, "--url0"))
1941 return GPGME_DATA_ENCODING_URL0;
1942 return GPGME_DATA_ENCODING_NONE;
1946 static gpgme_error_t
1947 server_data_obj (assuan_fd_t fd, char *fn, int out,
1948 gpgme_data_encoding_t encoding,
1949 gpgme_data_t *data, FILE **fs)
1956 *fs = fopen (fn, out ? "wb" : "rb");
1958 return gpg_error_from_syserror ();
1960 err = gpgme_data_new_from_stream (data, *fs);
1963 err = gpgme_data_new_from_fd (data, (int) fd);
1967 return gpgme_data_set_encoding (*data, encoding);
1972 server_reset_fds (struct server *server)
1974 /* assuan closes the input and output FDs for us when doing a RESET,
1975 but we use this same function after commands, so repeat it
1977 assuan_close_input_fd (server->assuan_ctx);
1978 assuan_close_output_fd (server->assuan_ctx);
1979 if (server->message_fd != ASSUAN_INVALID_FD)
1981 /* FIXME: Assuan should provide a close function. */
1983 CloseHandle (server->message_fd);
1985 close (server->message_fd);
1987 server->message_fd = ASSUAN_INVALID_FD;
1989 if (server->input_filename)
1991 free (server->input_filename);
1992 server->input_filename = NULL;
1994 if (server->output_filename)
1996 free (server->output_filename);
1997 server->output_filename = NULL;
1999 if (server->message_filename)
2001 free (server->message_filename);
2002 server->message_filename = NULL;
2004 if (server->input_stream)
2006 fclose (server->input_stream);
2007 server->input_stream = NULL;
2009 if (server->output_stream)
2011 fclose (server->output_stream);
2012 server->output_stream = NULL;
2014 if (server->message_stream)
2016 fclose (server->message_stream);
2017 server->message_stream = NULL;
2020 server->input_enc = GPGME_DATA_ENCODING_NONE;
2021 server->output_enc = GPGME_DATA_ENCODING_NONE;
2022 server->message_enc = GPGME_DATA_ENCODING_NONE;
2027 reset_notify (assuan_context_t ctx, char *line)
2029 struct server *server = assuan_get_pointer (ctx);
2030 server_reset_fds (server);
2031 gt_reset (server->gt);
2036 static const char hlp_version[] =
2037 "VERSION [<string>]\n"
2039 "Call the function gpgme_check_version.";
2041 cmd_version (assuan_context_t ctx, char *line)
2045 const char *version = gpgme_check_version (line);
2046 return version ? 0 : gpg_error (GPG_ERR_SELFTEST_FAILED);
2050 const char *version = gpgme_check_version (NULL);
2051 return assuan_send_data (ctx, version, strlen (version));
2057 cmd_engine (assuan_context_t ctx, char *line)
2059 struct server *server = assuan_get_pointer (ctx);
2060 return gt_get_engine_info (server->gt, gt_protocol_from_name (line));
2064 static const char hlp_protocol[] =
2065 "PROTOCOL [<name>]\n"
2067 "With NAME, set the protocol. Without return the current protocol.";
2069 cmd_protocol (assuan_context_t ctx, char *line)
2071 struct server *server = assuan_get_pointer (ctx);
2073 return gt_set_protocol (server->gt, gt_protocol_from_name (line));
2075 return gt_get_protocol (server->gt);
2080 cmd_sub_protocol (assuan_context_t ctx, char *line)
2082 struct server *server = assuan_get_pointer (ctx);
2084 return gt_set_sub_protocol (server->gt, gt_protocol_from_name (line));
2086 return gt_get_sub_protocol (server->gt);
2091 cmd_armor (assuan_context_t ctx, char *line)
2093 struct server *server = assuan_get_pointer (ctx);
2098 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2102 return gt_set_armor (server->gt, flag);
2105 return gt_get_armor (server->gt);
2110 cmd_textmode (assuan_context_t ctx, char *line)
2112 struct server *server = assuan_get_pointer (ctx);
2117 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2121 return gt_set_textmode (server->gt, flag);
2124 return gt_get_textmode (server->gt);
2129 cmd_include_certs (assuan_context_t ctx, char *line)
2131 struct server *server = assuan_get_pointer (ctx);
2135 int include_certs = 0;
2137 if (! strcasecmp (line, "default"))
2138 include_certs = GPGME_INCLUDE_CERTS_DEFAULT;
2140 include_certs = atoi (line);
2142 return gt_set_include_certs (server->gt, include_certs);
2145 return gt_get_include_certs (server->gt);
2150 cmd_keylist_mode (assuan_context_t ctx, char *line)
2152 struct server *server = assuan_get_pointer (ctx);
2156 gpgme_keylist_mode_t mode = 0;
2158 if (strstr (line, "local"))
2159 mode |= GPGME_KEYLIST_MODE_LOCAL;
2160 if (strstr (line, "extern"))
2161 mode |= GPGME_KEYLIST_MODE_EXTERN;
2162 if (strstr (line, "sigs"))
2163 mode |= GPGME_KEYLIST_MODE_SIGS;
2164 if (strstr (line, "sig_notations"))
2165 mode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS;
2166 if (strstr (line, "ephemeral"))
2167 mode |= GPGME_KEYLIST_MODE_EPHEMERAL;
2168 if (strstr (line, "validate"))
2169 mode |= GPGME_KEYLIST_MODE_VALIDATE;
2171 return gt_set_keylist_mode (server->gt, mode);
2174 return gt_get_keylist_mode (server->gt);
2179 cmd_input (assuan_context_t ctx, char *line)
2181 struct server *server = assuan_get_pointer (ctx);
2186 err = server_parse_fd (ctx, line, &sysfd, &filename);
2189 server->input_fd = sysfd;
2190 server->input_filename = filename;
2191 server->input_enc = server_data_encoding (line);
2197 cmd_output (assuan_context_t ctx, char *line)
2199 struct server *server = assuan_get_pointer (ctx);
2204 err = server_parse_fd (ctx, line, &sysfd, &filename);
2207 server->output_fd = sysfd;
2208 server->output_filename = filename;
2209 server->output_enc = server_data_encoding (line);
2215 cmd_message (assuan_context_t ctx, char *line)
2217 struct server *server = assuan_get_pointer (ctx);
2222 err = server_parse_fd (ctx, line, &sysfd, &filename);
2225 server->message_fd = sysfd;
2226 server->message_filename = filename;
2227 server->message_enc = server_data_encoding (line);
2233 cmd_recipient (assuan_context_t ctx, char *line)
2235 struct server *server = assuan_get_pointer (ctx);
2237 return gt_recipients_add (server->gt, line);
2242 cmd_signer (assuan_context_t ctx, char *line)
2244 struct server *server = assuan_get_pointer (ctx);
2246 return gt_signers_add (server->gt, line);
2251 cmd_signers_clear (assuan_context_t ctx, char *line)
2253 struct server *server = assuan_get_pointer (ctx);
2255 return gt_signers_clear (server->gt);
2260 _cmd_decrypt_verify (assuan_context_t ctx, char *line, int verify)
2262 struct server *server = assuan_get_pointer (ctx);
2268 gpgme_data_t inp_data;
2269 gpgme_data_t out_data;
2271 inp_fd = assuan_get_input_fd (ctx);
2272 inp_fn = server->input_filename;
2273 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2274 return GPG_ERR_ASS_NO_INPUT;
2275 out_fd = assuan_get_output_fd (ctx);
2276 out_fn = server->output_filename;
2277 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2278 return GPG_ERR_ASS_NO_OUTPUT;
2280 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2281 &server->input_stream);
2284 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2285 &server->output_stream);
2288 gpgme_data_release (inp_data);
2292 err = gt_decrypt_verify (server->gt, inp_data, out_data, verify);
2294 gpgme_data_release (inp_data);
2295 gpgme_data_release (out_data);
2297 server_reset_fds (server);
2304 cmd_decrypt (assuan_context_t ctx, char *line)
2306 return _cmd_decrypt_verify (ctx, line, 0);
2311 cmd_decrypt_verify (assuan_context_t ctx, char *line)
2313 return _cmd_decrypt_verify (ctx, line, 1);
2318 _cmd_sign_encrypt (assuan_context_t ctx, char *line, int sign)
2320 struct server *server = assuan_get_pointer (ctx);
2326 gpgme_data_t inp_data = NULL;
2327 gpgme_data_t out_data = NULL;
2328 gpgme_encrypt_flags_t flags = 0;
2330 if (strstr (line, "--always-trust"))
2331 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
2332 if (strstr (line, "--no-encrypt-to"))
2333 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
2334 if (strstr (line, "--prepare"))
2335 flags |= GPGME_ENCRYPT_PREPARE;
2336 if (strstr (line, "--expect-sign"))
2337 flags |= GPGME_ENCRYPT_EXPECT_SIGN;
2339 inp_fd = assuan_get_input_fd (ctx);
2340 inp_fn = server->input_filename;
2341 out_fd = assuan_get_output_fd (ctx);
2342 out_fn = server->output_filename;
2343 if (inp_fd != ASSUAN_INVALID_FD || inp_fn)
2345 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2346 &server->input_stream);
2350 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2352 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2353 &server->output_stream);
2356 gpgme_data_release (inp_data);
2361 err = gt_sign_encrypt (server->gt, flags, inp_data, out_data, sign);
2363 gpgme_data_release (inp_data);
2364 gpgme_data_release (out_data);
2366 server_reset_fds (server);
2373 cmd_encrypt (assuan_context_t ctx, char *line)
2375 return _cmd_sign_encrypt (ctx, line, 0);
2380 cmd_sign_encrypt (assuan_context_t ctx, char *line)
2382 return _cmd_sign_encrypt (ctx, line, 1);
2387 cmd_sign (assuan_context_t ctx, char *line)
2389 struct server *server = assuan_get_pointer (ctx);
2395 gpgme_data_t inp_data;
2396 gpgme_data_t out_data;
2397 gpgme_sig_mode_t mode = GPGME_SIG_MODE_NORMAL;
2399 if (strstr (line, "--clear"))
2400 mode = GPGME_SIG_MODE_CLEAR;
2401 if (strstr (line, "--detach"))
2402 mode = GPGME_SIG_MODE_DETACH;
2404 inp_fd = assuan_get_input_fd (ctx);
2405 inp_fn = server->input_filename;
2406 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2407 return GPG_ERR_ASS_NO_INPUT;
2408 out_fd = assuan_get_output_fd (ctx);
2409 out_fn = server->output_filename;
2410 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2411 return GPG_ERR_ASS_NO_OUTPUT;
2413 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2414 &server->input_stream);
2417 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2418 &server->output_stream);
2421 gpgme_data_release (inp_data);
2425 err = gt_sign (server->gt, inp_data, out_data, mode);
2427 gpgme_data_release (inp_data);
2428 gpgme_data_release (out_data);
2429 server_reset_fds (server);
2436 cmd_verify (assuan_context_t ctx, char *line)
2438 struct server *server = assuan_get_pointer (ctx);
2446 gpgme_data_t inp_data;
2447 gpgme_data_t msg_data = NULL;
2448 gpgme_data_t out_data = NULL;
2450 inp_fd = assuan_get_input_fd (ctx);
2451 inp_fn = server->input_filename;
2452 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2453 return GPG_ERR_ASS_NO_INPUT;
2454 msg_fd = server->message_fd;
2455 msg_fn = server->message_filename;
2456 out_fd = assuan_get_output_fd (ctx);
2457 out_fn = server->output_filename;
2459 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2460 &server->input_stream);
2463 if (msg_fd != ASSUAN_INVALID_FD || msg_fn)
2465 err = server_data_obj (msg_fd, msg_fn, 0, server->message_enc, &msg_data,
2466 &server->message_stream);
2469 gpgme_data_release (inp_data);
2473 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2475 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2476 &server->output_stream);
2479 gpgme_data_release (inp_data);
2480 gpgme_data_release (msg_data);
2485 err = gt_verify (server->gt, inp_data, msg_data, out_data);
2487 gpgme_data_release (inp_data);
2489 gpgme_data_release (msg_data);
2491 gpgme_data_release (out_data);
2493 server_reset_fds (server);
2500 cmd_import (assuan_context_t ctx, char *line)
2502 struct server *server = assuan_get_pointer (ctx);
2506 char *fprs[2] = { line, NULL };
2508 return gt_import_keys (server->gt, fprs);
2515 gpgme_data_t inp_data;
2517 inp_fd = assuan_get_input_fd (ctx);
2518 inp_fn = server->input_filename;
2519 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2520 return GPG_ERR_ASS_NO_INPUT;
2522 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2523 &server->input_stream);
2527 err = gt_import (server->gt, inp_data);
2529 gpgme_data_release (inp_data);
2530 server_reset_fds (server);
2537 static const char hlp_export[] =
2538 "EXPORT [--extern] [--minimal] [<pattern>]\n"
2540 "Export the keys described by PATTERN. Write the\n"
2541 "the output to the object set by the last OUTPUT command.";
2543 cmd_export (assuan_context_t ctx, char *line)
2545 struct server *server = assuan_get_pointer (ctx);
2549 gpgme_data_t out_data;
2550 gpgme_export_mode_t mode = 0;
2551 const char *pattern[2];
2553 out_fd = assuan_get_output_fd (ctx);
2554 out_fn = server->output_filename;
2555 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2556 return GPG_ERR_ASS_NO_OUTPUT;
2557 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2558 &server->output_stream);
2562 if (has_option (line, "--extern"))
2563 mode |= GPGME_EXPORT_MODE_EXTERN;
2564 if (has_option (line, "--minimal"))
2565 mode |= GPGME_EXPORT_MODE_MINIMAL;
2567 line = skip_options (line);
2572 err = gt_export (server->gt, pattern, mode, out_data);
2574 gpgme_data_release (out_data);
2575 server_reset_fds (server);
2582 _cmd_genkey_write (gpgme_data_t data, const void *buf, size_t size)
2586 ssize_t writen = gpgme_data_write (data, buf, size);
2587 if (writen < 0 && errno != EAGAIN)
2588 return gpg_error_from_syserror ();
2589 else if (writen > 0)
2591 buf = (void *) (((char *) buf) + writen);
2600 cmd_genkey (assuan_context_t ctx, char *line)
2602 struct server *server = assuan_get_pointer (ctx);
2608 gpgme_data_t inp_data;
2609 gpgme_data_t out_data = NULL;
2610 gpgme_data_t parms_data = NULL;
2613 inp_fd = assuan_get_input_fd (ctx);
2614 inp_fn = server->input_filename;
2615 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2616 return GPG_ERR_ASS_NO_INPUT;
2617 out_fd = assuan_get_output_fd (ctx);
2618 out_fn = server->output_filename;
2620 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2621 &server->input_stream);
2624 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2626 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2627 &server->output_stream);
2630 gpgme_data_release (inp_data);
2635 /* Convert input data. */
2636 err = gpgme_data_new (&parms_data);
2642 ssize_t readn = gpgme_data_read (inp_data, buf, sizeof (buf));
2645 err = gpg_error_from_syserror ();
2648 else if (readn == 0)
2651 err = _cmd_genkey_write (parms_data, buf, readn);
2656 err = _cmd_genkey_write (parms_data, "", 1);
2659 parms = gpgme_data_release_and_get_mem (parms_data, NULL);
2663 err = gpg_error (GPG_ERR_GENERAL);
2667 err = gt_genkey (server->gt, parms, out_data, NULL);
2669 server_reset_fds (server);
2672 gpgme_data_release (inp_data);
2674 gpgme_data_release (out_data);
2676 gpgme_data_release (parms_data);
2683 cmd_delete (assuan_context_t ctx, char *line)
2685 struct server *server = assuan_get_pointer (ctx);
2686 int allow_secret = 0;
2687 const char optstr[] = "--allow-secret";
2689 if (!strncasecmp (line, optstr, strlen (optstr)))
2692 line += strlen (optstr);
2693 while (*line && !spacep (line))
2696 return gt_delete (server->gt, line, allow_secret);
2700 static const char hlp_keylist[] =
2701 "KEYLIST [--secret-only] [<patterns>]\n"
2703 "List all certificates or only those specified by PATTERNS. Each\n"
2704 "pattern shall be a percent-plus escaped certificate specification.";
2706 cmd_keylist (assuan_context_t ctx, char *line)
2708 #define MAX_CMD_KEYLIST_PATTERN 20
2709 struct server *server = assuan_get_pointer (ctx);
2711 int secret_only = 0;
2713 const char *pattern[MAX_CMD_KEYLIST_PATTERN+1];
2714 const char optstr[] = "--secret-only";
2717 if (!strncasecmp (line, optstr, strlen (optstr)))
2720 line += strlen (optstr);
2721 while (*line && !spacep (line))
2726 for (p=line; *p; line = p)
2728 while (*p && *p != ' ')
2734 if (idx+1 == DIM (pattern))
2735 return gpg_error (GPG_ERR_TOO_MANY);
2736 strcpy_escaped_plus (line, line);
2737 pattern[idx++] = line;
2740 pattern[idx] = NULL;
2742 err = gt_keylist_start (server->gt, pattern, secret_only);
2747 err = gt_keylist_next (server->gt, &key);
2748 if (gpg_err_code (err) == GPG_ERR_EOF)
2756 /* FIXME: More data. */
2757 snprintf (buf, sizeof (buf), "key:%s\n", key->subkeys->fpr);
2758 /* Write data and flush so that we see one D line for each
2759 key. This does not change the semantics but is easier to
2760 read by organic eyes. */
2761 if (!assuan_send_data (ctx, buf, strlen (buf)))
2762 assuan_send_data (ctx, NULL, 0);
2763 gpgme_key_unref (key);
2767 server_reset_fds (server);
2773 static const char hlp_getauditlog[] =
2774 "GETAUDITLOG [--html] [--with-help]\n"
2776 "Call the function gpgme_op_getauditlog with the given flags. Write\n"
2777 "the output to the object set by the last OUTPUT command.";
2779 cmd_getauditlog (assuan_context_t ctx, char *line)
2781 struct server *server = assuan_get_pointer (ctx);
2785 gpgme_data_t out_data;
2786 unsigned int flags = 0;
2788 out_fd = assuan_get_output_fd (ctx);
2789 out_fn = server->output_filename;
2790 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2791 return GPG_ERR_ASS_NO_OUTPUT;
2792 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2793 &server->output_stream);
2797 if (strstr (line, "--html"))
2798 flags |= GPGME_AUDITLOG_HTML;
2799 if (strstr (line, "--with-help"))
2800 flags |= GPGME_AUDITLOG_WITH_HELP;
2802 err = gt_getauditlog (server->gt, out_data, flags);
2804 gpgme_data_release (out_data);
2805 server_reset_fds (server);
2812 cmd_vfs_mount (assuan_context_t ctx, char *line)
2814 struct server *server = assuan_get_pointer (ctx);
2818 mount_dir = strchr (line, ' ');
2821 *(mount_dir++) = '\0';
2822 while (*mount_dir == ' ')
2826 err = gt_vfs_mount (server->gt, line, mount_dir, 0);
2833 cmd_vfs_create (assuan_context_t ctx, char *line)
2835 struct server *server = assuan_get_pointer (ctx);
2839 end = strchr (line, ' ');
2847 err = gt_vfs_create (server->gt, line, 0);
2854 cmd_passwd (assuan_context_t ctx, char *line)
2856 struct server *server = assuan_get_pointer (ctx);
2858 return gt_passwd (server->gt, line);
2864 cmd_result (assuan_context_t ctx, char *line)
2866 struct server *server = assuan_get_pointer (ctx);
2867 return gt_result (server->gt, GT_RESULT_ALL);
2871 /* STRERROR <err> */
2873 cmd_strerror (assuan_context_t ctx, char *line)
2879 snprintf (buf, sizeof (buf), "%s <%s>", gpgme_strerror (err),
2880 gpgme_strsource (err));
2881 return assuan_send_data (ctx, buf, strlen (buf));
2886 cmd_pubkey_algo_name (assuan_context_t ctx, char *line)
2888 gpgme_pubkey_algo_t algo;
2892 snprintf (buf, sizeof (buf), "%s", gpgme_pubkey_algo_name (algo));
2893 return assuan_send_data (ctx, buf, strlen (buf));
2898 cmd_hash_algo_name (assuan_context_t ctx, char *line)
2900 gpgme_hash_algo_t algo;
2904 snprintf (buf, sizeof (buf), "%s", gpgme_hash_algo_name (algo));
2905 return assuan_send_data (ctx, buf, strlen (buf));
2909 /* Tell the assuan library about our commands. */
2911 register_commands (assuan_context_t ctx)
2916 assuan_handler_t handler;
2917 const char * const help;
2919 /* RESET, BYE are implicit. */
2920 { "VERSION", cmd_version, hlp_version },
2921 /* TODO: Set engine info. */
2922 { "ENGINE", cmd_engine },
2923 { "PROTOCOL", cmd_protocol, hlp_protocol },
2924 { "SUB_PROTOCOL", cmd_sub_protocol },
2925 { "ARMOR", cmd_armor },
2926 { "TEXTMODE", cmd_textmode },
2927 { "INCLUDE_CERTS", cmd_include_certs },
2928 { "KEYLIST_MODE", cmd_keylist_mode },
2929 { "INPUT", cmd_input },
2930 { "OUTPUT", cmd_output },
2931 { "MESSAGE", cmd_message },
2932 { "RECIPIENT", cmd_recipient },
2933 { "SIGNER", cmd_signer },
2934 { "SIGNERS_CLEAR", cmd_signers_clear },
2935 /* TODO: SIGNOTATION missing. */
2936 /* TODO: Could add wait interface if we allow more than one context */
2937 /* and add _START variants. */
2938 /* TODO: Could add data interfaces if we allow multiple data objects. */
2939 { "DECRYPT", cmd_decrypt },
2940 { "DECRYPT_VERIFY", cmd_decrypt_verify },
2941 { "ENCRYPT", cmd_encrypt },
2942 { "ENCRYPT_SIGN", cmd_sign_encrypt },
2943 { "SIGN_ENCRYPT", cmd_sign_encrypt },
2944 { "SIGN", cmd_sign },
2945 { "VERIFY", cmd_verify },
2946 { "IMPORT", cmd_import },
2947 { "EXPORT", cmd_export, hlp_export },
2948 { "GENKEY", cmd_genkey },
2949 { "DELETE", cmd_delete },
2950 /* TODO: EDIT, CARD_EDIT (with INQUIRE) */
2951 { "KEYLIST", cmd_keylist, hlp_keylist },
2952 { "LISTKEYS", cmd_keylist, hlp_keylist },
2953 /* TODO: TRUSTLIST, TRUSTLIST_EXT */
2954 { "GETAUDITLOG", cmd_getauditlog, hlp_getauditlog },
2956 { "VFS_MOUNT", cmd_vfs_mount },
2957 { "MOUNT", cmd_vfs_mount },
2958 { "VFS_CREATE", cmd_vfs_create },
2959 { "CREATE", cmd_vfs_create },
2961 { "RESULT", cmd_result },
2962 { "STRERROR", cmd_strerror },
2963 { "PUBKEY_ALGO_NAME", cmd_pubkey_algo_name },
2964 { "HASH_ALGO_NAME", cmd_hash_algo_name },
2965 { "PASSWD", cmd_passwd, hlp_passwd },
2970 for (idx = 0; table[idx].name; idx++)
2972 err = assuan_register_command (ctx, table[idx].name, table[idx].handler,
2981 /* TODO: password callback can do INQUIRE. */
2983 gpgme_server (gpgme_tool_t gt)
2986 assuan_fd_t filedes[2];
2987 struct server server;
2988 static const char hello[] = ("GPGME-Tool " VERSION " ready");
2990 memset (&server, 0, sizeof (server));
2991 server.message_fd = ASSUAN_INVALID_FD;
2992 server.input_enc = GPGME_DATA_ENCODING_NONE;
2993 server.output_enc = GPGME_DATA_ENCODING_NONE;
2994 server.message_enc = GPGME_DATA_ENCODING_NONE;
2997 gt->write_status = server_write_status;
2998 gt->write_status_hook = &server;
2999 gt->write_data = server_write_data;
3000 gt->write_data_hook = &server;
3002 /* We use a pipe based server so that we can work from scripts.
3003 assuan_init_pipe_server will automagically detect when we are
3004 called with a socketpair and ignore FIELDES in this case. */
3005 #ifdef HAVE_W32CE_SYSTEM
3006 filedes[0] = ASSUAN_STDIN;
3007 filedes[1] = ASSUAN_STDOUT;
3009 filedes[0] = assuan_fdopen (0);
3010 filedes[1] = assuan_fdopen (1);
3012 err = assuan_new (&server.assuan_ctx);
3014 log_error (1, err, "can't create assuan context");
3016 assuan_set_pointer (server.assuan_ctx, &server);
3018 err = assuan_init_pipe_server (server.assuan_ctx, filedes);
3020 log_error (1, err, "can't initialize assuan server");
3021 err = register_commands (server.assuan_ctx);
3023 log_error (1, err, "can't register assuan commands");
3024 assuan_set_hello_line (server.assuan_ctx, hello);
3026 assuan_register_reset_notify (server.assuan_ctx, reset_notify);
3028 #define DBG_ASSUAN 0
3030 assuan_set_log_stream (server.assuan_ctx, log_stream);
3034 err = assuan_accept (server.assuan_ctx);
3039 log_error (0, err, "assuan accept problem");
3043 err = assuan_process (server.assuan_ctx);
3045 log_error (0, err, "assuan processing failed");
3048 assuan_release (server.assuan_ctx);
3053 /* MAIN PROGRAM STARTS HERE. */
3055 const char *argp_program_version = VERSION;
3056 const char *argp_program_bug_address = "bug-gpgme@gnupg.org";
3057 error_t argp_err_exit_status = 1;
3059 static char doc[] = "GPGME Tool -- invoke GPGME operations";
3060 static char args_doc[] = "COMMAND [OPTIONS...]";
3062 static struct argp_option options[] = {
3063 { "server", 's', 0, 0, "Server mode" },
3067 static error_t parse_options (int key, char *arg, struct argp_state *state);
3068 static struct argp argp = { options, parse_options, args_doc, doc };
3072 enum { CMD_DEFAULT, CMD_SERVER } cmd;
3076 args_init (struct args *args)
3078 memset (args, '\0', sizeof (*args));
3079 args->cmd = CMD_DEFAULT;
3084 parse_options (int key, char *arg, struct argp_state *state)
3086 struct args *args = state->input;
3091 args->cmd = CMD_SERVER;
3095 if (state->arg_num >= 2)
3097 printf ("Arg[%i] = %s\n", state->arg_num, arg);
3100 if (state->arg_num < 2)
3106 return ARGP_ERR_UNKNOWN;
3113 main (int argc, char *argv[])
3116 struct gpgme_tool gt;
3118 #ifdef HAVE_SETLOCALE
3119 setlocale (LC_ALL, "");
3121 gpgme_check_version (NULL);
3123 gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
3126 gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
3131 argp_parse (&argp, argc, argv, 0, 0, &args);
3144 gpgme_release (gt.ctx);
3146 #ifdef HAVE_W32CE_SYSTEM
3147 /* Give the buggy ssh server time to flush the output buffers. */