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)
59 /* Minimal argp implementation. */
61 /* Differences to ARGP:
62 argp_program_version: Required.
63 argp_program_bug_address: Required.
64 argp_program_version_hook: Not supported.
65 argp_err_exit_status: Required.
66 struct argp: Children and help_filter not supported.
67 argp_domain: Not supported.
68 struct argp_option: Group not supported. Options are printed in
69 order given. Flags OPTION_ALIAS, OPTION_DOC and OPTION_NO_USAGE
71 argp_parse: No flags are supported (ARGP_PARSE_ARGV0, ARGP_NO_ERRS,
72 ARGP_NO_ARGS, ARGP_IN_ORDER, ARGP_NO_HELP, ARGP_NO_EXIT,
73 ARGP_LONG_ONLY, ARGP_SILENT). ARGP must not be NULL.
74 argp_help: Flag ARGP_HELP_LONG_ONLY not supported.
75 argp_state: argc, argv, next may not be modified and should not be used. */
77 extern const char *argp_program_version;
78 extern const char *argp_program_bug_address;
79 extern error_t argp_err_exit_status;
86 #define OPTION_ARG_OPTIONAL 0x1
87 #define OPTION_HIDDEN 0x2
96 const struct argp *const root_argp;
113 # define ARGP_ERR_UNKNOWN EDEADLK /* POSIX */
115 # define ARGP_ERR_UNKNOWN EDEADLOCK /* *GNU/kFreebsd does not define this) */
117 #define ARGP_KEY_ARG 0
118 #define ARGP_KEY_ARGS 0x1000006
119 #define ARGP_KEY_END 0x1000001
120 #define ARGP_KEY_NO_ARGS 0x1000002
121 #define ARGP_KEY_INIT 0x1000003
122 #define ARGP_KEY_FINI 0x1000007
123 #define ARGP_KEY_SUCCESS 0x1000004
124 #define ARGP_KEY_ERROR 0x1000005
125 typedef error_t (*argp_parser_t) (int key, char *arg, struct argp_state *state);
129 const struct argp_option *options;
130 argp_parser_t parser;
131 const char *args_doc;
134 const struct argp_child *children;
135 char *(*help_filter) (int key, const char *text, void *input);
136 const char *argp_domain;
139 #define ARGP_HELP_USAGE ARGP_HELP_SHORT_USAGE
140 #define ARGP_HELP_SHORT_USAGE 0x02
141 #define ARGP_HELP_SEE 0x04
142 #define ARGP_HELP_LONG 0x08
143 #define ARGP_HELP_PRE_DOC 0x10
144 #define ARGP_HELP_POST_DOC 0x20
145 #define ARGP_HELP_DOC (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC)
146 #define ARGP_HELP_BUG_ADDR 0x40
147 #define ARGP_HELP_EXIT_ERR 0x100
148 #define ARGP_HELP_EXIT_OK 0x200
149 #define ARGP_HELP_STD_ERR (ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
150 #define ARGP_HELP_STD_USAGE \
151 (ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
152 #define ARGP_HELP_STD_HELP \
153 (ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK \
154 | ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR)
157 void argp_error (const struct argp_state *state,
158 const char *fmt, ...) GT_GCC_A_PRINTF(2, 3);
163 _argp_pname (char *name)
166 char *bname = strrchr (pname, '/');
168 bname = strrchr (pname, '\\');
176 _argp_state_help (const struct argp *argp, const struct argp_state *state,
177 FILE *stream, unsigned flags, char *name)
182 if (flags & ARGP_HELP_SHORT_USAGE)
183 fprintf (stream, "Usage: %s [OPTIONS...] %s\n", name, argp->args_doc);
184 if (flags & ARGP_HELP_SEE)
185 fprintf (stream, "Try `%s --help' or `%s --usage' for more information.\n",
187 if (flags & ARGP_HELP_PRE_DOC)
191 strncpy (buf, argp->doc, sizeof (buf));
192 buf[sizeof (buf) - 1] = '\0';
193 end = strchr (buf, '\v');
196 fprintf (stream, "%s\n%s", buf, buf[0] ? "\n" : "");
198 if (flags & ARGP_HELP_LONG)
200 const struct argp_option *opt = argp->options;
204 char spaces[NSPACES + 1] = " ";
206 fprintf (stream, " ");
208 if (isascii (opt->key))
210 fprintf (stream, "-%c", opt->key);
214 fprintf (stream, ", ");
220 fprintf (stream, "--%s", opt->name);
221 len += 2 + strlen (opt->name);
223 if (opt->arg && (opt->flags & OPTION_ARG_OPTIONAL))
225 fprintf (stream, "[=%s]", opt->arg);
226 len += 3 + strlen (opt->arg);
230 fprintf (stream, "=%s", opt->arg);
231 len += 1 + strlen (opt->arg);
235 spaces[NSPACES - len] = '\0';
236 fprintf (stream, "%s%s\n", spaces, opt->doc);
239 fprintf (stream, " -?, --help Give this help list\n");
240 fprintf (stream, " --usage Give a short usage "
243 if (flags & ARGP_HELP_POST_DOC)
247 strncpy (buf, argp->doc, sizeof (buf));
248 buf[sizeof (buf) - 1] = '\0';
249 end = strchr (buf, '\v');
254 fprintf (stream, "\n%s\n", end);
256 fprintf (stream, "\nMandatory or optional arguments to long options are also mandatory or optional\n");
257 fprintf (stream, "for any corresponding short options.\n");
259 if (flags & ARGP_HELP_BUG_ADDR)
260 fprintf (stream, "\nReport bugs to %s.\n", argp_program_bug_address);
262 if (flags & ARGP_HELP_EXIT_ERR)
263 exit (argp_err_exit_status);
264 if (flags & ARGP_HELP_EXIT_OK)
270 argp_usage (const struct argp_state *state)
272 _argp_state_help (state->root_argp, state, state->err_stream,
273 ARGP_HELP_STD_USAGE, state->name);
278 argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags)
280 _argp_state_help (state->root_argp, state, stream, flags, state->name);
285 argp_error (const struct argp_state *state, const char *fmt, ...)
289 fprintf (state->err_stream, "%s: ", state->name);
291 vfprintf (state->err_stream, fmt, ap);
293 fprintf (state->err_stream, "\n");
294 argp_state_help (state, state->err_stream, ARGP_HELP_STD_ERR);
295 exit (argp_err_exit_status);
300 argp_help (const struct argp *argp, FILE *stream, unsigned flags, char *name)
302 _argp_state_help (argp, NULL, stream, flags, name);
307 argp_parse (const struct argp *argp, int argc,
308 char **argv, unsigned flags, int *arg_index, void *input)
311 struct argp_state state = { argp, argc, argv, 1, flags, 0, 0, input,
312 NULL, NULL, _argp_pname (argv[0]),
313 stderr, stdout, NULL };
314 /* All non-option arguments are collected at the beginning of
315 &argv[1] during processing. This is a counter for their number. */
316 int non_opt_args = 0;
318 rc = argp->parser (ARGP_KEY_INIT, NULL, &state);
319 if (rc && rc != ARGP_ERR_UNKNOWN)
322 while (state.next < state.argc - non_opt_args)
324 int idx = state.next;
327 if (! strcasecmp (state.argv[idx], "--"))
333 if (state.quoted || state.argv[idx][0] != '-')
335 char *arg_saved = state.argv[idx];
337 memmove (&state.argv[idx], &state.argv[idx + 1],
338 (state.argc - 1 - idx) * sizeof (char *));
339 state.argv[argc - 1] = arg_saved;
342 else if (! strcasecmp (state.argv[idx], "--help")
343 || !strcmp (state.argv[idx], "-?"))
345 argp_state_help (&state, state.out_stream, ARGP_HELP_STD_HELP);
347 else if (! strcasecmp (state.argv[idx], "--usage"))
349 argp_state_help (&state, state.out_stream,
350 ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
352 else if (! strcasecmp (state.argv[idx], "--version")
353 || !strcmp (state.argv[idx], "-V"))
355 fprintf (state.out_stream, "%s\n", argp_program_version);
360 /* Search for option and call parser with its KEY. */
361 int key = ARGP_KEY_ARG; /* Just some dummy value. */
362 const struct argp_option *opt = argp->options;
366 /* Check for --opt=value syntax. */
367 arg = strchr (state.argv[idx], '=');
374 if (state.argv[idx][1] != '-')
375 key = state.argv[idx][1];
377 while (! found && opt->key)
380 || (key == ARGP_KEY_ARG
381 && ! strcasecmp (&state.argv[idx][2], opt->name)))
383 if (arg && !opt->arg)
384 argp_error (&state, "Option %s does not take an argument",
386 if (opt->arg && state.next < state.argc
387 && state.argv[idx + 1][0] != '-')
389 arg = state.argv[idx + 1];
392 if (opt->arg && !(opt->flags & OPTION_ARG_OPTIONAL))
393 argp_error (&state, "Option %s requires an argument",
396 rc = argp->parser (opt->key, arg, &state);
397 if (rc == ARGP_ERR_UNKNOWN)
406 argp_error (&state, "Unknown option %s", state.argv[idx]);
410 while (state.next < state.argc)
412 /* Call parser for all non-option args. */
413 int idx = state.next;
415 rc = argp->parser (ARGP_KEY_ARG, state.argv[idx], &state);
416 if (rc && rc != ARGP_ERR_UNKNOWN)
418 if (rc == ARGP_ERR_UNKNOWN)
420 int old_next = state.next;
421 rc = argp->parser (ARGP_KEY_ARGS, NULL, &state);
422 if (rc == ARGP_ERR_UNKNOWN)
424 argp_error (&state, "Too many arguments");
427 if (! rc && state.next == old_next)
429 state.arg_num += state.argc - state.next;
430 state.next = state.argc;
437 if (state.arg_num == 0)
439 rc = argp->parser (ARGP_KEY_NO_ARGS, NULL, &state);
440 if (rc && rc != ARGP_ERR_UNKNOWN)
443 if (state.next == state.argc)
445 rc = argp->parser (ARGP_KEY_END, NULL, &state);
446 if (rc && rc != ARGP_ERR_UNKNOWN)
449 rc = argp->parser (ARGP_KEY_FINI, NULL, &state);
450 if (rc && rc != ARGP_ERR_UNKNOWN)
454 argp->parser (ARGP_KEY_SUCCESS, NULL, &state);
459 argp_error (&state, "unexpected error: %s", strerror (rc));
460 argp->parser (ARGP_KEY_ERROR, NULL, &state);
463 argp->parser (ARGP_KEY_FINI, NULL, &state);
466 *arg_index = state.next - 1;
475 char *program_name = "gpgme-tool";
477 #define spacep(p) (*(p) == ' ' || *(p) == '\t')
480 void log_error (int status, gpg_error_t errnum,
481 const char *fmt, ...) GT_GCC_A_PRINTF(3,4);
492 log_error (int status, gpg_error_t errnum, const char *fmt, ...)
496 fprintf (log_stream, "%s: ", program_name);
498 vfprintf (log_stream, fmt, ap);
501 fprintf (log_stream, ": %s <%s>", gpg_strerror (errnum),
502 gpg_strsource (errnum));
503 fprintf (log_stream, "\n");
509 /* Check whether the option NAME appears in LINE. */
511 has_option (const char *line, const char *name)
514 int n = strlen (name);
516 s = strstr (line, name);
517 return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
520 /* Skip over options. It is assumed that leading spaces have been
521 removed (this is the case for lines passed to a handler from
522 assuan). Blanks after the options are also removed. */
524 skip_options (char *line)
526 while ( *line == '-' && line[1] == '-' )
528 while (*line && !spacep (line))
530 while (spacep (line))
539 typedef gpg_error_t (*result_xml_write_cb_t) (void *hook, const void *buf,
542 struct result_xml_state
545 result_xml_write_cb_t cb;
551 int had_data[MAX_TAGS];
556 result_init (struct result_xml_state *state, int indent,
557 result_xml_write_cb_t cb, void *hook)
559 memset (state, '\0', sizeof (*state));
560 state->indent = indent;
567 result_xml_indent (struct result_xml_state *state)
569 char spaces[state->indent + 1];
571 for (i = 0; i < state->indent; i++)
574 return (*state->cb) (state->hook, spaces, i);
579 result_xml_tag_start (struct result_xml_state *state, char *name, ...)
581 result_xml_write_cb_t cb = state->cb;
582 void *hook = state->hook;
589 if (state->next_tag > 0)
591 if (! state->had_data[state->next_tag - 1])
593 (*cb) (hook, ">\n", 2);
594 (*cb) (hook, NULL, 0);
596 state->had_data[state->next_tag - 1] = 1;
599 result_xml_indent (state);
600 (*cb) (hook, "<", 1);
601 (*cb) (hook, name, strlen (name));
603 state->tag[state->next_tag] = name;
604 state->had_data[state->next_tag] = 0;
610 attr = va_arg (ap, char *);
614 attr_val = va_arg (ap, char *);
615 if (attr_val == NULL)
618 (*cb) (hook, " ", 1);
619 (*cb) (hook, attr, strlen (attr));
620 (*cb) (hook, "=\"", 2);
621 (*cb) (hook, attr_val, strlen (attr_val));
622 (*cb) (hook, "\"", 1);
630 result_xml_tag_data (struct result_xml_state *state, char *data)
632 result_xml_write_cb_t cb = state->cb;
633 void *hook = state->hook;
635 if (state->had_data[state->next_tag - 1])
637 (*cb) (hook, "\n", 2);
638 (*cb) (hook, NULL, 0);
639 result_xml_indent (state);
642 (*cb) (hook, ">", 1);
643 state->had_data[state->next_tag - 1] = 2;
645 (*cb) (hook, data, strlen (data));
652 result_xml_tag_end (struct result_xml_state *state)
654 result_xml_write_cb_t cb = state->cb;
655 void *hook = state->hook;
660 if (state->had_data[state->next_tag])
662 if (state->had_data[state->next_tag] == 1)
663 result_xml_indent (state);
664 (*cb) (hook, "</", 2);
665 (*cb) (hook, state->tag[state->next_tag],
666 strlen (state->tag[state->next_tag]));
667 (*cb) (hook, ">\n", 2);
668 (*cb) (hook, NULL, 0);
672 (*cb) (hook, " />\n", 4);
673 (*cb) (hook, NULL, 0);
680 result_add_error (struct result_xml_state *state, char *name, gpg_error_t err)
684 snprintf (code, sizeof (code) - 1, "0x%x", err);
685 snprintf (msg, sizeof (msg) - 1, "%s <%s>",
686 gpg_strerror (err), gpg_strsource (err));
687 result_xml_tag_start (state, name, "value", code, NULL);
688 result_xml_tag_data (state, msg);
689 result_xml_tag_end (state);
695 result_add_pubkey_algo (struct result_xml_state *state,
696 char *name, gpgme_pubkey_algo_t algo)
700 snprintf (code, sizeof (code) - 1, "0x%x", algo);
701 snprintf (msg, sizeof (msg) - 1, "%s",
702 gpgme_pubkey_algo_name (algo));
703 result_xml_tag_start (state, name, "value", code, NULL);
704 result_xml_tag_data (state, msg);
705 result_xml_tag_end (state);
711 result_add_hash_algo (struct result_xml_state *state,
712 char *name, gpgme_hash_algo_t algo)
716 snprintf (code, sizeof (code) - 1, "0x%x", algo);
717 snprintf (msg, sizeof (msg) - 1, "%s",
718 gpgme_hash_algo_name (algo));
719 result_xml_tag_start (state, name, "value", code, NULL);
720 result_xml_tag_data (state, msg);
721 result_xml_tag_end (state);
727 result_add_keyid (struct result_xml_state *state, char *name, char *keyid)
729 result_xml_tag_start (state, name, NULL);
730 result_xml_tag_data (state, keyid);
731 result_xml_tag_end (state);
737 result_add_fpr (struct result_xml_state *state, char *name, char *fpr)
739 result_xml_tag_start (state, name, NULL);
740 result_xml_tag_data (state, fpr);
741 result_xml_tag_end (state);
747 result_add_timestamp (struct result_xml_state *state, char *name,
748 unsigned int timestamp)
752 snprintf (code, sizeof (code) - 1, "%ui", timestamp);
753 result_xml_tag_start (state, name, "unix", code, NULL);
754 result_xml_tag_end (state);
760 result_add_sig_mode (struct result_xml_state *state, char *name,
761 gpgme_sig_mode_t sig_mode)
766 snprintf (code, sizeof (code) - 1, "%i", sig_mode);
769 case GPGME_SIG_MODE_NORMAL:
772 case GPGME_SIG_MODE_DETACH:
775 case GPGME_SIG_MODE_CLEAR:
782 result_xml_tag_start (state, name, "type", mode, "value", code, NULL);
783 result_xml_tag_data (state, mode);
784 result_xml_tag_end (state);
790 result_add_value (struct result_xml_state *state,
791 char *name, unsigned int val)
795 snprintf (code, sizeof (code) - 1, "0x%x", val);
796 result_xml_tag_start (state, name, "value", code, NULL);
797 result_xml_tag_end (state);
803 result_add_string (struct result_xml_state *state,
804 char *name, char *str)
806 result_xml_tag_start (state, name, NULL);
807 result_xml_tag_data (state, str);
808 result_xml_tag_end (state);
814 result_encrypt_to_xml (gpgme_ctx_t ctx, int indent,
815 result_xml_write_cb_t cb, void *hook)
817 struct result_xml_state state;
818 gpgme_encrypt_result_t res = gpgme_op_encrypt_result (ctx);
819 gpgme_invalid_key_t inv_recp;
824 result_init (&state, indent, cb, hook);
825 result_xml_tag_start (&state, "encrypt-result", NULL);
827 inv_recp = res->invalid_recipients;
830 result_xml_tag_start (&state, "invalid-recipients", NULL);
834 result_xml_tag_start (&state, "invalid-key", NULL);
836 result_add_fpr (&state, "fpr", inv_recp->fpr);
837 result_add_error (&state, "reason", inv_recp->reason);
838 result_xml_tag_end (&state);
839 inv_recp = inv_recp->next;
841 result_xml_tag_end (&state);
843 result_xml_tag_end (&state);
850 result_decrypt_to_xml (gpgme_ctx_t ctx, int indent,
851 result_xml_write_cb_t cb, void *hook)
853 struct result_xml_state state;
854 gpgme_decrypt_result_t res = gpgme_op_decrypt_result (ctx);
855 gpgme_recipient_t recp;
860 result_init (&state, indent, cb, hook);
861 result_xml_tag_start (&state, "decrypt-result", NULL);
865 result_xml_tag_start (&state, "file-name", NULL);
866 result_xml_tag_data (&state, res->file_name);
867 result_xml_tag_end (&state);
869 if (res->unsupported_algorithm)
871 result_xml_tag_start (&state, "unsupported-alogorithm", NULL);
872 result_xml_tag_data (&state, res->unsupported_algorithm);
873 result_xml_tag_end (&state);
875 if (res->wrong_key_usage)
877 result_xml_tag_start (&state, "wrong-key-usage", NULL);
878 result_xml_tag_end (&state);
881 recp = res->recipients;
884 result_xml_tag_start (&state, "recipients", NULL);
887 result_xml_tag_start (&state, "recipient", NULL);
888 result_add_keyid (&state, "keyid", recp->keyid);
889 result_add_pubkey_algo (&state, "pubkey-algo", recp->pubkey_algo);
890 result_add_error (&state, "status", recp->status);
891 result_xml_tag_end (&state);
894 result_xml_tag_end (&state);
896 result_xml_tag_end (&state);
903 result_sign_to_xml (gpgme_ctx_t ctx, int indent,
904 result_xml_write_cb_t cb, void *hook)
906 struct result_xml_state state;
907 gpgme_sign_result_t res = gpgme_op_sign_result (ctx);
908 gpgme_invalid_key_t inv_key;
909 gpgme_new_signature_t new_sig;
914 result_init (&state, indent, cb, hook);
915 result_xml_tag_start (&state, "sign-result", NULL);
917 inv_key = res->invalid_signers;
920 result_xml_tag_start (&state, "invalid-signers", NULL);
924 result_xml_tag_start (&state, "invalid-key", NULL);
926 result_add_fpr (&state, "fpr", inv_key->fpr);
927 result_add_error (&state, "reason", inv_key->reason);
928 result_xml_tag_end (&state);
929 inv_key = inv_key->next;
931 result_xml_tag_end (&state);
934 new_sig = res->signatures;
937 result_xml_tag_start (&state, "signatures", NULL);
941 result_xml_tag_start (&state, "new-signature", NULL);
942 result_add_sig_mode (&state, "type", new_sig->type);
943 result_add_pubkey_algo (&state, "pubkey-algo", new_sig->pubkey_algo);
944 result_add_hash_algo (&state, "hash-algo", new_sig->hash_algo);
945 result_add_timestamp (&state, "timestamp", new_sig->timestamp);
947 result_add_fpr (&state, "fpr", new_sig->fpr);
948 result_add_value (&state, "sig-class", new_sig->sig_class);
950 result_xml_tag_end (&state);
951 new_sig = new_sig->next;
953 result_xml_tag_end (&state);
956 result_xml_tag_end (&state);
963 result_verify_to_xml (gpgme_ctx_t ctx, int indent,
964 result_xml_write_cb_t cb, void *hook)
966 struct result_xml_state state;
967 gpgme_verify_result_t res = gpgme_op_verify_result (ctx);
968 gpgme_signature_t sig;
973 result_init (&state, indent, cb, hook);
974 result_xml_tag_start (&state, "verify-result", NULL);
978 result_xml_tag_start (&state, "file-name", NULL);
979 result_xml_tag_data (&state, res->file_name);
980 result_xml_tag_end (&state);
983 sig = res->signatures;
986 result_xml_tag_start (&state, "signatures", NULL);
990 result_xml_tag_start (&state, "signature", NULL);
992 /* FIXME: Could be done better. */
993 result_add_value (&state, "summary", sig->summary);
995 result_add_fpr (&state, "fpr", sig->fpr);
996 result_add_error (&state, "status", sig->status);
997 /* FIXME: notations */
998 result_add_timestamp (&state, "timestamp", sig->timestamp);
999 result_add_timestamp (&state, "exp-timestamp", sig->exp_timestamp);
1000 result_add_value (&state, "wrong-key-usage", sig->wrong_key_usage);
1001 result_add_value (&state, "pka-trust", sig->pka_trust);
1002 result_add_value (&state, "chain-model", sig->chain_model);
1003 result_add_value (&state, "validity", sig->validity);
1004 result_add_error (&state, "validity-reason", sig->validity_reason);
1005 result_add_pubkey_algo (&state, "pubkey-algo", sig->pubkey_algo);
1006 result_add_hash_algo (&state, "hash-algo", sig->hash_algo);
1007 if (sig->pka_address)
1008 result_add_string (&state, "pka_address", sig->pka_address);
1010 result_xml_tag_end (&state);
1013 result_xml_tag_end (&state);
1016 result_xml_tag_end (&state);
1023 result_import_to_xml (gpgme_ctx_t ctx, int indent,
1024 result_xml_write_cb_t cb, void *hook)
1026 struct result_xml_state state;
1027 gpgme_import_result_t res = gpgme_op_import_result (ctx);
1028 gpgme_import_status_t stat;
1033 result_init (&state, indent, cb, hook);
1034 result_xml_tag_start (&state, "import-result", NULL);
1036 result_add_value (&state, "considered", res->considered);
1037 result_add_value (&state, "no-user-id", res->no_user_id);
1038 result_add_value (&state, "imported", res->imported);
1039 result_add_value (&state, "imported-rsa", res->imported_rsa);
1040 result_add_value (&state, "unchanged", res->unchanged);
1041 result_add_value (&state, "new-user-ids", res->new_user_ids);
1042 result_add_value (&state, "new-sub-keys", res->new_sub_keys);
1043 result_add_value (&state, "new-signatures", res->new_signatures);
1044 result_add_value (&state, "new-revocations", res->new_revocations);
1045 result_add_value (&state, "secret-read", res->secret_read);
1046 result_add_value (&state, "secret-imported", res->secret_imported);
1047 result_add_value (&state, "secret-unchanged", res->secret_unchanged);
1048 result_add_value (&state, "skipped-new-keys", res->skipped_new_keys);
1049 result_add_value (&state, "not-imported", res->not_imported);
1051 stat = res->imports;
1054 result_xml_tag_start (&state, "imports", NULL);
1058 result_xml_tag_start (&state, "import-status", NULL);
1061 result_add_fpr (&state, "fpr", stat->fpr);
1062 result_add_error (&state, "result", stat->result);
1063 /* FIXME: Could be done better. */
1064 result_add_value (&state, "status", stat->status);
1066 result_xml_tag_end (&state);
1069 result_xml_tag_end (&state);
1072 result_xml_tag_end (&state);
1079 result_genkey_to_xml (gpgme_ctx_t ctx, int indent,
1080 result_xml_write_cb_t cb, void *hook)
1082 struct result_xml_state state;
1083 gpgme_genkey_result_t res = gpgme_op_genkey_result (ctx);
1088 result_init (&state, indent, cb, hook);
1089 result_xml_tag_start (&state, "genkey-result", NULL);
1091 result_add_value (&state, "primary", res->primary);
1092 result_add_value (&state, "sub", res->sub);
1094 result_add_fpr (&state, "fpr", res->fpr);
1096 result_xml_tag_end (&state);
1103 result_keylist_to_xml (gpgme_ctx_t ctx, int indent,
1104 result_xml_write_cb_t cb, void *hook)
1106 struct result_xml_state state;
1107 gpgme_keylist_result_t res = gpgme_op_keylist_result (ctx);
1112 result_init (&state, indent, cb, hook);
1113 result_xml_tag_start (&state, "keylist-result", NULL);
1115 result_add_value (&state, "truncated", res->truncated);
1117 result_xml_tag_end (&state);
1124 result_vfs_mount_to_xml (gpgme_ctx_t ctx, int indent,
1125 result_xml_write_cb_t cb, void *hook)
1127 struct result_xml_state state;
1128 gpgme_vfs_mount_result_t res = gpgme_op_vfs_mount_result (ctx);
1133 result_init (&state, indent, cb, hook);
1134 result_xml_tag_start (&state, "vfs-mount-result", NULL);
1136 result_add_string (&state, "mount-dir", res->mount_dir);
1138 result_xml_tag_end (&state);
1151 STATUS_INCLUDE_CERTS,
1152 STATUS_KEYLIST_MODE,
1154 STATUS_ENCRYPT_RESULT
1157 const char *status_string[] =
1173 #define MAX_RECIPIENTS 10
1174 gpgme_key_t recipients[MAX_RECIPIENTS + 1];
1177 gpg_error_t (*write_status) (void *hook, const char *status, const char *msg);
1178 void *write_status_hook;
1179 gpg_error_t (*write_data) (void *hook, const void *buf, size_t len);
1180 void *write_data_hook;
1182 typedef struct gpgme_tool *gpgme_tool_t;
1185 /* Forward declaration. */
1186 void gt_write_status (gpgme_tool_t gt,
1187 status_t status, ...) GT_GCC_A_SENTINEL(0);
1190 _gt_progress_cb (void *opaque, const char *what,
1191 int type, int current, int total)
1193 gpgme_tool_t gt = opaque;
1196 snprintf (buf, sizeof (buf), "0x%02x %i %i", type, current, total);
1197 gt_write_status (gt, STATUS_PROGRESS, what, buf, NULL);
1202 _gt_gpgme_new (gpgme_tool_t gt, gpgme_ctx_t *ctx)
1206 err = gpgme_new (ctx);
1209 gpgme_set_progress_cb (*ctx, _gt_progress_cb, gt);
1215 gt_init (gpgme_tool_t gt)
1217 memset (gt, '\0', sizeof (*gt));
1220 err = _gt_gpgme_new (gt, >->ctx);
1222 log_error (1, err, "can't create gpgme context");
1227 gt_signers_add (gpgme_tool_t gt, const char *fpr)
1232 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1236 return gpgme_signers_add (gt->ctx, key);
1241 gt_signers_clear (gpgme_tool_t gt)
1243 gpgme_signers_clear (gt->ctx);
1249 gt_get_key (gpgme_tool_t gt, const char *pattern, gpgme_key_t *r_key)
1252 gpgme_ctx_t listctx;
1256 if (!gt || !r_key || !pattern)
1257 return gpg_error (GPG_ERR_INV_VALUE);
1261 err = gpgme_new (&listctx);
1266 gpgme_protocol_t proto;
1267 gpgme_engine_info_t info;
1269 /* Clone the relevant state. */
1270 proto = gpgme_get_protocol (ctx);
1271 /* The g13 protocol does not allow keylisting, we need to choose
1273 if (proto == GPGME_PROTOCOL_G13)
1274 proto = GPGME_PROTOCOL_OpenPGP;
1276 gpgme_set_protocol (listctx, proto);
1277 gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
1278 info = gpgme_ctx_get_engine_info (ctx);
1279 while (info && info->protocol != proto)
1282 gpgme_ctx_set_engine_info (listctx, proto,
1283 info->file_name, info->home_dir);
1286 err = gpgme_op_keylist_start (listctx, pattern, 0);
1288 err = gpgme_op_keylist_next (listctx, r_key);
1292 err = gpgme_op_keylist_next (listctx, &key);
1293 if (gpgme_err_code (err) == GPG_ERR_EOF)
1298 && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr
1299 && key && key->subkeys && key->subkeys->fpr
1300 && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr))
1302 /* The fingerprint is identical. We assume that this is
1303 the same key and don't mark it as an ambiguous. This
1304 problem may occur with corrupted keyrings and has
1305 been noticed often with gpgsm. In fact gpgsm uses a
1306 similar hack to sort out such duplicates but it can't
1307 do that while listing keys. */
1308 gpgme_key_unref (key);
1313 gpgme_key_unref (key);
1314 err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
1316 gpgme_key_unref (*r_key);
1319 gpgme_release (listctx);
1322 gt_write_status (gt, STATUS_RECIPIENT,
1323 ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
1324 (*r_key)->subkeys->fpr : "invalid", NULL);
1330 gt_recipients_add (gpgme_tool_t gt, const char *pattern)
1335 if (gt->recipients_nr >= MAX_RECIPIENTS)
1336 return gpg_error_from_errno (ENOMEM);
1338 if (gpgme_get_protocol (gt->ctx) == GPGME_PROTOCOL_UISERVER)
1339 err = gpgme_key_from_uid (&key, pattern);
1341 err = gt_get_key (gt, pattern, &key);
1345 gt->recipients[gt->recipients_nr++] = key;
1351 gt_recipients_clear (gpgme_tool_t gt)
1355 for (idx = 0; idx < gt->recipients_nr; idx++)
1356 gpgme_key_unref (gt->recipients[idx]);
1357 memset (gt->recipients, '\0', gt->recipients_nr * sizeof (gpgme_key_t));
1358 gt->recipients_nr = 0;
1363 gt_reset (gpgme_tool_t gt)
1368 err = _gt_gpgme_new (gt, &ctx);
1372 gpgme_release (gt->ctx);
1374 gt_recipients_clear (gt);
1380 gt_write_status (gpgme_tool_t gt, status_t status, ...)
1389 va_start (ap, status);
1392 while ((text = va_arg (ap, const char *)))
1399 while (*text && n < sizeof (buf) - 2)
1408 err = gt->write_status (gt->write_status_hook, status_string[status], buf);
1410 log_error (1, err, "can't write status line");
1415 gt_write_data (gpgme_tool_t gt, const void *buf, size_t len)
1417 return gt->write_data (gt->write_data_hook, buf, len);
1422 gt_get_engine_info (gpgme_tool_t gt, gpgme_protocol_t proto)
1424 gpgme_engine_info_t info;
1425 info = gpgme_ctx_get_engine_info (gt->ctx);
1428 if (proto == GPGME_PROTOCOL_UNKNOWN || proto == info->protocol)
1429 gt_write_status (gt, STATUS_ENGINE,
1430 gpgme_get_protocol_name (info->protocol),
1431 info->file_name, info->version,
1432 info->req_version, info->home_dir, NULL);
1440 gt_protocol_from_name (const char *name)
1442 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_OpenPGP)))
1443 return GPGME_PROTOCOL_OpenPGP;
1444 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_CMS)))
1445 return GPGME_PROTOCOL_CMS;
1446 if (! strcasecmp (name,gpgme_get_protocol_name (GPGME_PROTOCOL_GPGCONF)))
1447 return GPGME_PROTOCOL_GPGCONF;
1448 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_ASSUAN)))
1449 return GPGME_PROTOCOL_ASSUAN;
1450 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_G13)))
1451 return GPGME_PROTOCOL_G13;
1452 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_UISERVER)))
1453 return GPGME_PROTOCOL_UISERVER;
1454 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_DEFAULT)))
1455 return GPGME_PROTOCOL_DEFAULT;
1456 return GPGME_PROTOCOL_UNKNOWN;
1461 gt_set_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
1463 return gpgme_set_protocol (gt->ctx, proto);
1468 gt_get_protocol (gpgme_tool_t gt)
1470 gpgme_protocol_t proto = gpgme_get_protocol (gt->ctx);
1472 gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
1480 gt_set_sub_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
1482 return gpgme_set_sub_protocol (gt->ctx, proto);
1487 gt_get_sub_protocol (gpgme_tool_t gt)
1489 gpgme_protocol_t proto = gpgme_get_sub_protocol (gt->ctx);
1491 gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
1499 gt_set_armor (gpgme_tool_t gt, int armor)
1501 gpgme_set_armor (gt->ctx, armor);
1507 gt_get_armor (gpgme_tool_t gt)
1509 gt_write_status (gt, STATUS_ARMOR,
1510 gpgme_get_armor (gt->ctx) ? "true" : "false", NULL);
1517 gt_set_textmode (gpgme_tool_t gt, int textmode)
1519 gpgme_set_textmode (gt->ctx, textmode);
1525 gt_get_textmode (gpgme_tool_t gt)
1527 gt_write_status (gt, STATUS_TEXTMODE,
1528 gpgme_get_textmode (gt->ctx) ? "true" : "false", NULL);
1535 gt_set_keylist_mode (gpgme_tool_t gt, gpgme_keylist_mode_t keylist_mode)
1537 gpgme_set_keylist_mode (gt->ctx, keylist_mode);
1543 gt_get_keylist_mode (gpgme_tool_t gt)
1545 #define NR_KEYLIST_MODES 6
1546 const char *modes[NR_KEYLIST_MODES + 1];
1548 gpgme_keylist_mode_t mode = gpgme_get_keylist_mode (gt->ctx);
1550 if (mode & GPGME_KEYLIST_MODE_LOCAL)
1551 modes[idx++] = "local";
1552 if (mode & GPGME_KEYLIST_MODE_EXTERN)
1553 modes[idx++] = "extern";
1554 if (mode & GPGME_KEYLIST_MODE_SIGS)
1555 modes[idx++] = "sigs";
1556 if (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS)
1557 modes[idx++] = "sig_notations";
1558 if (mode & GPGME_KEYLIST_MODE_EPHEMERAL)
1559 modes[idx++] = "ephemeral";
1560 if (mode & GPGME_KEYLIST_MODE_VALIDATE)
1561 modes[idx++] = "validate";
1562 modes[idx++] = NULL;
1564 gt_write_status (gt, STATUS_KEYLIST_MODE, modes[0], modes[1], modes[2],
1565 modes[3], modes[4], modes[5], modes[6], NULL);
1572 gt_set_include_certs (gpgme_tool_t gt, int include_certs)
1574 gpgme_set_include_certs (gt->ctx, include_certs);
1580 gt_get_include_certs (gpgme_tool_t gt)
1582 int include_certs = gpgme_get_include_certs (gt->ctx);
1585 if (include_certs == GPGME_INCLUDE_CERTS_DEFAULT)
1586 strcpy (buf, "default");
1588 snprintf (buf, sizeof (buf), "%i", include_certs);
1590 gt_write_status (gt, STATUS_INCLUDE_CERTS, buf, NULL);
1597 gt_decrypt_verify (gpgme_tool_t gt, gpgme_data_t cipher, gpgme_data_t plain,
1601 return gpgme_op_decrypt_verify (gt->ctx, cipher, plain);
1603 return gpgme_op_decrypt (gt->ctx, cipher, plain);
1608 gt_sign_encrypt (gpgme_tool_t gt, gpgme_encrypt_flags_t flags,
1609 gpgme_data_t plain, gpgme_data_t cipher, int sign)
1614 err = gpgme_op_encrypt_sign (gt->ctx, gt->recipients, flags, plain, cipher);
1616 err = gpgme_op_encrypt (gt->ctx, gt->recipients, flags, plain, cipher);
1618 gt_recipients_clear (gt);
1625 gt_sign (gpgme_tool_t gt, gpgme_data_t plain, gpgme_data_t sig,
1626 gpgme_sig_mode_t mode)
1628 return gpgme_op_sign (gt->ctx, plain, sig, mode);
1633 gt_verify (gpgme_tool_t gt, gpgme_data_t sig, gpgme_data_t sig_text,
1636 return gpgme_op_verify (gt->ctx, sig, sig_text, plain);
1641 gt_import (gpgme_tool_t gt, gpgme_data_t data)
1643 return gpgme_op_import (gt->ctx, data);
1648 gt_export (gpgme_tool_t gt, const char *pattern[], gpgme_export_mode_t mode,
1651 return gpgme_op_export_ext (gt->ctx, pattern, mode, data);
1656 gt_genkey (gpgme_tool_t gt, const char *parms, gpgme_data_t public,
1657 gpgme_data_t secret)
1659 return gpgme_op_genkey (gt->ctx, parms, public, secret);
1664 gt_import_keys (gpgme_tool_t gt, char *fpr[])
1666 gpg_error_t err = 0;
1676 return gpg_error (GPG_ERR_INV_VALUE);
1678 keys = malloc ((cnt + 1) * sizeof (gpgme_key_t));
1680 return gpg_error_from_syserror ();
1682 for (idx = 0; idx < cnt; idx++)
1684 err = gpgme_get_key (gt->ctx, fpr[idx], &keys[idx], 0);
1691 err = gpgme_op_import_keys (gt->ctx, keys);
1696 gpgme_key_unref (keys[idx]);
1704 gt_delete (gpgme_tool_t gt, char *fpr, int allow_secret)
1709 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1713 err = gpgme_op_delete (gt->ctx, key, allow_secret);
1714 gpgme_key_unref (key);
1720 gt_keylist_start (gpgme_tool_t gt, const char *pattern[], int secret_only)
1722 return gpgme_op_keylist_ext_start (gt->ctx, pattern, secret_only, 0);
1727 gt_keylist_next (gpgme_tool_t gt, gpgme_key_t *key)
1729 return gpgme_op_keylist_next (gt->ctx, key);
1734 gt_getauditlog (gpgme_tool_t gt, gpgme_data_t output, unsigned int flags)
1736 return gpgme_op_getauditlog (gt->ctx, output, flags);
1741 gt_vfs_mount (gpgme_tool_t gt, const char *container_file,
1742 const char *mount_dir, int flags)
1746 err = gpgme_op_vfs_mount (gt->ctx, container_file, mount_dir, flags, &op_err);
1747 return err ? err : op_err;
1752 gt_vfs_create (gpgme_tool_t gt, const char *container_file, int flags)
1756 err = gpgme_op_vfs_create (gt->ctx, gt->recipients, container_file,
1758 gt_recipients_clear (gt);
1759 return err ? err : op_err;
1763 static const char hlp_passwd[] =
1764 "PASSWD <user-id>\n"
1766 "Ask the backend to change the passphrase for the key\n"
1767 "specified by USER-ID.";
1769 gt_passwd (gpgme_tool_t gt, char *fpr)
1774 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1776 return gpg_err_code (err) == GPG_ERR_EOF? gpg_error (GPG_ERR_NO_PUBKEY):err;
1778 err = gpgme_op_passwd (gt->ctx, key, 0);
1779 gpgme_key_unref (key);
1784 #define GT_RESULT_ENCRYPT 0x1
1785 #define GT_RESULT_DECRYPT 0x2
1786 #define GT_RESULT_SIGN 0x4
1787 #define GT_RESULT_VERIFY 0x8
1788 #define GT_RESULT_IMPORT 0x10
1789 #define GT_RESULT_GENKEY 0x20
1790 #define GT_RESULT_KEYLIST 0x40
1791 #define GT_RESULT_VFS_MOUNT 0x80
1792 #define GT_RESULT_ALL (~0U)
1795 gt_result (gpgme_tool_t gt, unsigned int flags)
1797 static const char xml_preamble1[] = "<?xml version=\"1.0\" "
1798 "encoding=\"UTF-8\" standalone=\"yes\"?>\n";
1799 static const char xml_preamble2[] = "<gpgme>\n";
1800 static const char xml_end[] = "</gpgme>\n";
1803 gt_write_data (gt, xml_preamble1, sizeof (xml_preamble1));
1804 gt_write_data (gt, NULL, 0);
1805 gt_write_data (gt, xml_preamble2, sizeof (xml_preamble2));
1806 gt_write_data (gt, NULL, 0);
1807 if (flags & GT_RESULT_ENCRYPT)
1808 result_encrypt_to_xml (gt->ctx, indent,
1809 (result_xml_write_cb_t) gt_write_data, gt);
1810 if (flags & GT_RESULT_DECRYPT)
1811 result_decrypt_to_xml (gt->ctx, indent,
1812 (result_xml_write_cb_t) gt_write_data, gt);
1813 if (flags & GT_RESULT_SIGN)
1814 result_sign_to_xml (gt->ctx, indent,
1815 (result_xml_write_cb_t) gt_write_data, gt);
1816 if (flags & GT_RESULT_VERIFY)
1817 result_verify_to_xml (gt->ctx, indent,
1818 (result_xml_write_cb_t) gt_write_data, gt);
1819 if (flags & GT_RESULT_IMPORT)
1820 result_import_to_xml (gt->ctx, indent,
1821 (result_xml_write_cb_t) gt_write_data, gt);
1822 if (flags & GT_RESULT_GENKEY)
1823 result_genkey_to_xml (gt->ctx, indent,
1824 (result_xml_write_cb_t) gt_write_data, gt);
1825 if (flags & GT_RESULT_KEYLIST)
1826 result_keylist_to_xml (gt->ctx, indent,
1827 (result_xml_write_cb_t) gt_write_data, gt);
1828 if (flags & GT_RESULT_VFS_MOUNT)
1829 result_vfs_mount_to_xml (gt->ctx, indent,
1830 (result_xml_write_cb_t) gt_write_data, gt);
1831 gt_write_data (gt, xml_end, sizeof (xml_end));
1844 assuan_context_t assuan_ctx;
1846 gpgme_data_encoding_t input_enc;
1847 gpgme_data_encoding_t output_enc;
1848 assuan_fd_t input_fd;
1849 char *input_filename;
1851 assuan_fd_t output_fd;
1852 char *output_filename;
1853 FILE *output_stream;
1854 assuan_fd_t message_fd;
1855 char *message_filename;
1856 FILE *message_stream;
1857 gpgme_data_encoding_t message_enc;
1862 server_write_status (void *hook, const char *status, const char *msg)
1864 struct server *server = hook;
1865 return assuan_write_status (server->assuan_ctx, status, msg);
1870 server_write_data (void *hook, const void *buf, size_t len)
1872 struct server *server = hook;
1873 return assuan_send_data (server->assuan_ctx, buf, len);
1879 server_parse_fd (assuan_context_t ctx, char *line, assuan_fd_t *rfd,
1882 *rfd = ASSUAN_INVALID_FD;
1885 if (! strncasecmp (line, "file=", 5))
1888 *filename = strdup (line + 5);
1890 return gpg_error_from_syserror();
1891 term = strchr (*filename, ' ');
1897 return assuan_command_parse_fd (ctx, line, rfd);
1901 static gpgme_data_encoding_t
1902 server_data_encoding (const char *line)
1904 if (strstr (line, "--binary"))
1905 return GPGME_DATA_ENCODING_BINARY;
1906 if (strstr (line, "--base64"))
1907 return GPGME_DATA_ENCODING_BASE64;
1908 if (strstr (line, "--armor"))
1909 return GPGME_DATA_ENCODING_ARMOR;
1910 if (strstr (line, "--url"))
1911 return GPGME_DATA_ENCODING_URL;
1912 if (strstr (line, "--urlesc"))
1913 return GPGME_DATA_ENCODING_URLESC;
1914 if (strstr (line, "--url0"))
1915 return GPGME_DATA_ENCODING_URL0;
1916 return GPGME_DATA_ENCODING_NONE;
1920 static gpgme_error_t
1921 server_data_obj (assuan_fd_t fd, char *fn, int out,
1922 gpgme_data_encoding_t encoding,
1923 gpgme_data_t *data, FILE **fs)
1930 *fs = fopen (fn, out ? "wb" : "rb");
1932 return gpg_error_from_syserror ();
1934 err = gpgme_data_new_from_stream (data, *fs);
1937 err = gpgme_data_new_from_fd (data, (int) fd);
1941 return gpgme_data_set_encoding (*data, encoding);
1946 server_reset_fds (struct server *server)
1948 /* assuan closes the input and output FDs for us when doing a RESET,
1949 but we use this same function after commands, so repeat it
1951 assuan_close_input_fd (server->assuan_ctx);
1952 assuan_close_output_fd (server->assuan_ctx);
1953 if (server->message_fd != ASSUAN_INVALID_FD)
1955 /* FIXME: Assuan should provide a close function. */
1957 CloseHandle (server->message_fd);
1959 close (server->message_fd);
1961 server->message_fd = ASSUAN_INVALID_FD;
1963 if (server->input_filename)
1965 free (server->input_filename);
1966 server->input_filename = NULL;
1968 if (server->output_filename)
1970 free (server->output_filename);
1971 server->output_filename = NULL;
1973 if (server->message_filename)
1975 free (server->message_filename);
1976 server->message_filename = NULL;
1978 if (server->input_stream)
1980 fclose (server->input_stream);
1981 server->input_stream = NULL;
1983 if (server->output_stream)
1985 fclose (server->output_stream);
1986 server->output_stream = NULL;
1988 if (server->message_stream)
1990 fclose (server->message_stream);
1991 server->message_stream = NULL;
1994 server->input_enc = GPGME_DATA_ENCODING_NONE;
1995 server->output_enc = GPGME_DATA_ENCODING_NONE;
1996 server->message_enc = GPGME_DATA_ENCODING_NONE;
2001 reset_notify (assuan_context_t ctx, char *line)
2003 struct server *server = assuan_get_pointer (ctx);
2004 server_reset_fds (server);
2005 gt_reset (server->gt);
2010 static const char hlp_version[] =
2011 "VERSION [<string>]\n"
2013 "Call the function gpgme_check_version.";
2015 cmd_version (assuan_context_t ctx, char *line)
2019 const char *version = gpgme_check_version (line);
2020 return version ? 0 : gpg_error (GPG_ERR_SELFTEST_FAILED);
2024 const char *version = gpgme_check_version (NULL);
2025 return assuan_send_data (ctx, version, strlen (version));
2031 cmd_engine (assuan_context_t ctx, char *line)
2033 struct server *server = assuan_get_pointer (ctx);
2034 return gt_get_engine_info (server->gt, gt_protocol_from_name (line));
2038 static const char hlp_protocol[] =
2039 "PROTOCOL [<name>]\n"
2041 "With NAME, set the protocol. Without return the current protocol.";
2043 cmd_protocol (assuan_context_t ctx, char *line)
2045 struct server *server = assuan_get_pointer (ctx);
2047 return gt_set_protocol (server->gt, gt_protocol_from_name (line));
2049 return gt_get_protocol (server->gt);
2054 cmd_sub_protocol (assuan_context_t ctx, char *line)
2056 struct server *server = assuan_get_pointer (ctx);
2058 return gt_set_sub_protocol (server->gt, gt_protocol_from_name (line));
2060 return gt_get_sub_protocol (server->gt);
2065 cmd_armor (assuan_context_t ctx, char *line)
2067 struct server *server = assuan_get_pointer (ctx);
2072 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2076 return gt_set_armor (server->gt, flag);
2079 return gt_get_armor (server->gt);
2084 cmd_textmode (assuan_context_t ctx, char *line)
2086 struct server *server = assuan_get_pointer (ctx);
2091 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2095 return gt_set_textmode (server->gt, flag);
2098 return gt_get_textmode (server->gt);
2103 cmd_include_certs (assuan_context_t ctx, char *line)
2105 struct server *server = assuan_get_pointer (ctx);
2109 int include_certs = 0;
2111 if (! strcasecmp (line, "default"))
2112 include_certs = GPGME_INCLUDE_CERTS_DEFAULT;
2114 include_certs = atoi (line);
2116 return gt_set_include_certs (server->gt, include_certs);
2119 return gt_get_include_certs (server->gt);
2124 cmd_keylist_mode (assuan_context_t ctx, char *line)
2126 struct server *server = assuan_get_pointer (ctx);
2130 gpgme_keylist_mode_t mode = 0;
2132 if (strstr (line, "local"))
2133 mode |= GPGME_KEYLIST_MODE_LOCAL;
2134 if (strstr (line, "extern"))
2135 mode |= GPGME_KEYLIST_MODE_EXTERN;
2136 if (strstr (line, "sigs"))
2137 mode |= GPGME_KEYLIST_MODE_SIGS;
2138 if (strstr (line, "sig_notations"))
2139 mode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS;
2140 if (strstr (line, "ephemeral"))
2141 mode |= GPGME_KEYLIST_MODE_EPHEMERAL;
2142 if (strstr (line, "validate"))
2143 mode |= GPGME_KEYLIST_MODE_VALIDATE;
2145 return gt_set_keylist_mode (server->gt, mode);
2148 return gt_get_keylist_mode (server->gt);
2153 cmd_input (assuan_context_t ctx, char *line)
2155 struct server *server = assuan_get_pointer (ctx);
2160 err = server_parse_fd (ctx, line, &sysfd, &filename);
2163 server->input_fd = sysfd;
2164 server->input_filename = filename;
2165 server->input_enc = server_data_encoding (line);
2171 cmd_output (assuan_context_t ctx, char *line)
2173 struct server *server = assuan_get_pointer (ctx);
2178 err = server_parse_fd (ctx, line, &sysfd, &filename);
2181 server->output_fd = sysfd;
2182 server->output_filename = filename;
2183 server->output_enc = server_data_encoding (line);
2189 cmd_message (assuan_context_t ctx, char *line)
2191 struct server *server = assuan_get_pointer (ctx);
2196 err = server_parse_fd (ctx, line, &sysfd, &filename);
2199 server->message_fd = sysfd;
2200 server->message_filename = filename;
2201 server->message_enc = server_data_encoding (line);
2207 cmd_recipient (assuan_context_t ctx, char *line)
2209 struct server *server = assuan_get_pointer (ctx);
2211 return gt_recipients_add (server->gt, line);
2216 cmd_signer (assuan_context_t ctx, char *line)
2218 struct server *server = assuan_get_pointer (ctx);
2220 return gt_signers_add (server->gt, line);
2225 cmd_signers_clear (assuan_context_t ctx, char *line)
2227 struct server *server = assuan_get_pointer (ctx);
2229 return gt_signers_clear (server->gt);
2234 _cmd_decrypt_verify (assuan_context_t ctx, char *line, int verify)
2236 struct server *server = assuan_get_pointer (ctx);
2242 gpgme_data_t inp_data;
2243 gpgme_data_t out_data;
2245 inp_fd = assuan_get_input_fd (ctx);
2246 inp_fn = server->input_filename;
2247 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2248 return GPG_ERR_ASS_NO_INPUT;
2249 out_fd = assuan_get_output_fd (ctx);
2250 out_fn = server->output_filename;
2251 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2252 return GPG_ERR_ASS_NO_OUTPUT;
2254 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2255 &server->input_stream);
2258 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2259 &server->output_stream);
2262 gpgme_data_release (inp_data);
2266 err = gt_decrypt_verify (server->gt, inp_data, out_data, verify);
2268 gpgme_data_release (inp_data);
2269 gpgme_data_release (out_data);
2271 server_reset_fds (server);
2278 cmd_decrypt (assuan_context_t ctx, char *line)
2280 return _cmd_decrypt_verify (ctx, line, 0);
2285 cmd_decrypt_verify (assuan_context_t ctx, char *line)
2287 return _cmd_decrypt_verify (ctx, line, 1);
2292 _cmd_sign_encrypt (assuan_context_t ctx, char *line, int sign)
2294 struct server *server = assuan_get_pointer (ctx);
2300 gpgme_data_t inp_data = NULL;
2301 gpgme_data_t out_data = NULL;
2302 gpgme_encrypt_flags_t flags = 0;
2304 if (strstr (line, "--always-trust"))
2305 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
2306 if (strstr (line, "--no-encrypt-to"))
2307 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
2308 if (strstr (line, "--prepare"))
2309 flags |= GPGME_ENCRYPT_PREPARE;
2310 if (strstr (line, "--expect-sign"))
2311 flags |= GPGME_ENCRYPT_EXPECT_SIGN;
2313 inp_fd = assuan_get_input_fd (ctx);
2314 inp_fn = server->input_filename;
2315 out_fd = assuan_get_output_fd (ctx);
2316 out_fn = server->output_filename;
2317 if (inp_fd != ASSUAN_INVALID_FD || inp_fn)
2319 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2320 &server->input_stream);
2324 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2326 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2327 &server->output_stream);
2330 gpgme_data_release (inp_data);
2335 err = gt_sign_encrypt (server->gt, flags, inp_data, out_data, sign);
2337 gpgme_data_release (inp_data);
2338 gpgme_data_release (out_data);
2340 server_reset_fds (server);
2347 cmd_encrypt (assuan_context_t ctx, char *line)
2349 return _cmd_sign_encrypt (ctx, line, 0);
2354 cmd_sign_encrypt (assuan_context_t ctx, char *line)
2356 return _cmd_sign_encrypt (ctx, line, 1);
2361 cmd_sign (assuan_context_t ctx, char *line)
2363 struct server *server = assuan_get_pointer (ctx);
2369 gpgme_data_t inp_data;
2370 gpgme_data_t out_data;
2371 gpgme_sig_mode_t mode = GPGME_SIG_MODE_NORMAL;
2373 if (strstr (line, "--clear"))
2374 mode = GPGME_SIG_MODE_CLEAR;
2375 if (strstr (line, "--detach"))
2376 mode = GPGME_SIG_MODE_DETACH;
2378 inp_fd = assuan_get_input_fd (ctx);
2379 inp_fn = server->input_filename;
2380 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2381 return GPG_ERR_ASS_NO_INPUT;
2382 out_fd = assuan_get_output_fd (ctx);
2383 out_fn = server->output_filename;
2384 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2385 return GPG_ERR_ASS_NO_OUTPUT;
2387 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2388 &server->input_stream);
2391 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2392 &server->output_stream);
2395 gpgme_data_release (inp_data);
2399 err = gt_sign (server->gt, inp_data, out_data, mode);
2401 gpgme_data_release (inp_data);
2402 gpgme_data_release (out_data);
2403 server_reset_fds (server);
2410 cmd_verify (assuan_context_t ctx, char *line)
2412 struct server *server = assuan_get_pointer (ctx);
2420 gpgme_data_t inp_data;
2421 gpgme_data_t msg_data = NULL;
2422 gpgme_data_t out_data = NULL;
2424 inp_fd = assuan_get_input_fd (ctx);
2425 inp_fn = server->input_filename;
2426 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2427 return GPG_ERR_ASS_NO_INPUT;
2428 msg_fd = server->message_fd;
2429 msg_fn = server->message_filename;
2430 out_fd = assuan_get_output_fd (ctx);
2431 out_fn = server->output_filename;
2433 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2434 &server->input_stream);
2437 if (msg_fd != ASSUAN_INVALID_FD || msg_fn)
2439 err = server_data_obj (msg_fd, msg_fn, 0, server->message_enc, &msg_data,
2440 &server->message_stream);
2443 gpgme_data_release (inp_data);
2447 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2449 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2450 &server->output_stream);
2453 gpgme_data_release (inp_data);
2454 gpgme_data_release (msg_data);
2459 err = gt_verify (server->gt, inp_data, msg_data, out_data);
2461 gpgme_data_release (inp_data);
2463 gpgme_data_release (msg_data);
2465 gpgme_data_release (out_data);
2467 server_reset_fds (server);
2474 cmd_import (assuan_context_t ctx, char *line)
2476 struct server *server = assuan_get_pointer (ctx);
2480 char *fprs[2] = { line, NULL };
2482 return gt_import_keys (server->gt, fprs);
2489 gpgme_data_t inp_data;
2491 inp_fd = assuan_get_input_fd (ctx);
2492 inp_fn = server->input_filename;
2493 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2494 return GPG_ERR_ASS_NO_INPUT;
2496 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2497 &server->input_stream);
2501 err = gt_import (server->gt, inp_data);
2503 gpgme_data_release (inp_data);
2504 server_reset_fds (server);
2511 static const char hlp_export[] =
2512 "EXPORT [--extern] [--minimal] [<pattern>]\n"
2514 "Export the keys described by PATTERN. Write the\n"
2515 "the output to the object set by the last OUTPUT command.";
2517 cmd_export (assuan_context_t ctx, char *line)
2519 struct server *server = assuan_get_pointer (ctx);
2523 gpgme_data_t out_data;
2524 gpgme_export_mode_t mode = 0;
2525 const char *pattern[2];
2527 out_fd = assuan_get_output_fd (ctx);
2528 out_fn = server->output_filename;
2529 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2530 return GPG_ERR_ASS_NO_OUTPUT;
2531 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2532 &server->output_stream);
2536 if (has_option (line, "--extern"))
2537 mode |= GPGME_EXPORT_MODE_EXTERN;
2538 if (has_option (line, "--minimal"))
2539 mode |= GPGME_EXPORT_MODE_MINIMAL;
2541 line = skip_options (line);
2546 err = gt_export (server->gt, pattern, mode, out_data);
2548 gpgme_data_release (out_data);
2549 server_reset_fds (server);
2556 _cmd_genkey_write (gpgme_data_t data, const void *buf, size_t size)
2560 ssize_t writen = gpgme_data_write (data, buf, size);
2561 if (writen < 0 && errno != EAGAIN)
2562 return gpg_error_from_syserror ();
2563 else if (writen > 0)
2565 buf = (void *) (((char *) buf) + writen);
2574 cmd_genkey (assuan_context_t ctx, char *line)
2576 struct server *server = assuan_get_pointer (ctx);
2582 gpgme_data_t inp_data;
2583 gpgme_data_t out_data = NULL;
2584 gpgme_data_t parms_data = NULL;
2587 inp_fd = assuan_get_input_fd (ctx);
2588 inp_fn = server->input_filename;
2589 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2590 return GPG_ERR_ASS_NO_INPUT;
2591 out_fd = assuan_get_output_fd (ctx);
2592 out_fn = server->output_filename;
2594 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2595 &server->input_stream);
2598 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2600 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2601 &server->output_stream);
2604 gpgme_data_release (inp_data);
2609 /* Convert input data. */
2610 err = gpgme_data_new (&parms_data);
2616 ssize_t readn = gpgme_data_read (inp_data, buf, sizeof (buf));
2619 err = gpg_error_from_syserror ();
2622 else if (readn == 0)
2625 err = _cmd_genkey_write (parms_data, buf, readn);
2630 err = _cmd_genkey_write (parms_data, "", 1);
2633 parms = gpgme_data_release_and_get_mem (parms_data, NULL);
2637 err = gpg_error (GPG_ERR_GENERAL);
2641 err = gt_genkey (server->gt, parms, out_data, NULL);
2643 server_reset_fds (server);
2646 gpgme_data_release (inp_data);
2648 gpgme_data_release (out_data);
2650 gpgme_data_release (parms_data);
2657 cmd_delete (assuan_context_t ctx, char *line)
2659 struct server *server = assuan_get_pointer (ctx);
2660 int allow_secret = 0;
2661 const char optstr[] = "--allow-secret";
2663 if (!strncasecmp (line, optstr, strlen (optstr)))
2666 line += strlen (optstr);
2667 while (*line && !spacep (line))
2670 return gt_delete (server->gt, line, allow_secret);
2675 cmd_keylist (assuan_context_t ctx, char *line)
2677 struct server *server = assuan_get_pointer (ctx);
2679 int secret_only = 0;
2680 const char *pattern[2];
2681 const char optstr[] = "--secret-only";
2683 if (!strncasecmp (line, optstr, strlen (optstr)))
2686 line += strlen (optstr);
2687 while (*line && !spacep (line))
2693 err = gt_keylist_start (server->gt, pattern, secret_only);
2698 err = gt_keylist_next (server->gt, &key);
2699 if (gpg_err_code (err) == GPG_ERR_EOF)
2707 /* FIXME: More data. */
2708 snprintf (buf, sizeof (buf), "key:%s\n", key->subkeys->fpr);
2709 assuan_send_data (ctx, buf, strlen (buf));
2710 gpgme_key_unref (key);
2714 server_reset_fds (server);
2720 static const char hlp_getauditlog[] =
2721 "GETAUDITLOG [--html] [--with-help]\n"
2723 "Call the function gpgme_op_getauditlog with the given flags. Write\n"
2724 "the output to the object set by the last OUTPUT command.";
2726 cmd_getauditlog (assuan_context_t ctx, char *line)
2728 struct server *server = assuan_get_pointer (ctx);
2732 gpgme_data_t out_data;
2733 unsigned int flags = 0;
2735 out_fd = assuan_get_output_fd (ctx);
2736 out_fn = server->output_filename;
2737 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2738 return GPG_ERR_ASS_NO_OUTPUT;
2739 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2740 &server->output_stream);
2744 if (strstr (line, "--html"))
2745 flags |= GPGME_AUDITLOG_HTML;
2746 if (strstr (line, "--with-help"))
2747 flags |= GPGME_AUDITLOG_WITH_HELP;
2749 err = gt_getauditlog (server->gt, out_data, flags);
2751 gpgme_data_release (out_data);
2752 server_reset_fds (server);
2759 cmd_vfs_mount (assuan_context_t ctx, char *line)
2761 struct server *server = assuan_get_pointer (ctx);
2765 mount_dir = strchr (line, ' ');
2768 *(mount_dir++) = '\0';
2769 while (*mount_dir == ' ')
2773 err = gt_vfs_mount (server->gt, line, mount_dir, 0);
2780 cmd_vfs_create (assuan_context_t ctx, char *line)
2782 struct server *server = assuan_get_pointer (ctx);
2786 end = strchr (line, ' ');
2794 err = gt_vfs_create (server->gt, line, 0);
2801 cmd_passwd (assuan_context_t ctx, char *line)
2803 struct server *server = assuan_get_pointer (ctx);
2805 return gt_passwd (server->gt, line);
2811 cmd_result (assuan_context_t ctx, char *line)
2813 struct server *server = assuan_get_pointer (ctx);
2814 return gt_result (server->gt, GT_RESULT_ALL);
2818 /* STRERROR <err> */
2820 cmd_strerror (assuan_context_t ctx, char *line)
2826 snprintf (buf, sizeof (buf), "%s <%s>", gpgme_strerror (err),
2827 gpgme_strsource (err));
2828 return assuan_send_data (ctx, buf, strlen (buf));
2833 cmd_pubkey_algo_name (assuan_context_t ctx, char *line)
2835 gpgme_pubkey_algo_t algo;
2839 snprintf (buf, sizeof (buf), "%s", gpgme_pubkey_algo_name (algo));
2840 return assuan_send_data (ctx, buf, strlen (buf));
2845 cmd_hash_algo_name (assuan_context_t ctx, char *line)
2847 gpgme_hash_algo_t algo;
2851 snprintf (buf, sizeof (buf), "%s", gpgme_hash_algo_name (algo));
2852 return assuan_send_data (ctx, buf, strlen (buf));
2856 /* Tell the assuan library about our commands. */
2858 register_commands (assuan_context_t ctx)
2863 assuan_handler_t handler;
2864 const char * const help;
2866 /* RESET, BYE are implicit. */
2867 { "VERSION", cmd_version, hlp_version },
2868 /* TODO: Set engine info. */
2869 { "ENGINE", cmd_engine },
2870 { "PROTOCOL", cmd_protocol, hlp_protocol },
2871 { "SUB_PROTOCOL", cmd_sub_protocol },
2872 { "ARMOR", cmd_armor },
2873 { "TEXTMODE", cmd_textmode },
2874 { "INCLUDE_CERTS", cmd_include_certs },
2875 { "KEYLIST_MODE", cmd_keylist_mode },
2876 { "INPUT", cmd_input },
2877 { "OUTPUT", cmd_output },
2878 { "MESSAGE", cmd_message },
2879 { "RECIPIENT", cmd_recipient },
2880 { "SIGNER", cmd_signer },
2881 { "SIGNERS_CLEAR", cmd_signers_clear },
2882 /* TODO: SIGNOTATION missing. */
2883 /* TODO: Could add wait interface if we allow more than one context */
2884 /* and add _START variants. */
2885 /* TODO: Could add data interfaces if we allow multiple data objects. */
2886 { "DECRYPT", cmd_decrypt },
2887 { "DECRYPT_VERIFY", cmd_decrypt_verify },
2888 { "ENCRYPT", cmd_encrypt },
2889 { "ENCRYPT_SIGN", cmd_sign_encrypt },
2890 { "SIGN_ENCRYPT", cmd_sign_encrypt },
2891 { "SIGN", cmd_sign },
2892 { "VERIFY", cmd_verify },
2893 { "IMPORT", cmd_import },
2894 { "EXPORT", cmd_export, hlp_export },
2895 { "GENKEY", cmd_genkey },
2896 { "DELETE", cmd_delete },
2897 /* TODO: EDIT, CARD_EDIT (with INQUIRE) */
2898 { "KEYLIST", cmd_keylist },
2899 { "LISTKEYS", cmd_keylist },
2900 /* TODO: TRUSTLIST, TRUSTLIST_EXT */
2901 { "GETAUDITLOG", cmd_getauditlog, hlp_getauditlog },
2903 { "VFS_MOUNT", cmd_vfs_mount },
2904 { "MOUNT", cmd_vfs_mount },
2905 { "VFS_CREATE", cmd_vfs_create },
2906 { "CREATE", cmd_vfs_create },
2908 { "RESULT", cmd_result },
2909 { "STRERROR", cmd_strerror },
2910 { "PUBKEY_ALGO_NAME", cmd_pubkey_algo_name },
2911 { "HASH_ALGO_NAME", cmd_hash_algo_name },
2912 { "PASSWD", cmd_passwd, hlp_passwd },
2917 for (idx = 0; table[idx].name; idx++)
2919 err = assuan_register_command (ctx, table[idx].name, table[idx].handler,
2928 /* TODO: password callback can do INQUIRE. */
2930 gpgme_server (gpgme_tool_t gt)
2933 assuan_fd_t filedes[2];
2934 struct server server;
2935 static const char hello[] = ("GPGME-Tool " VERSION " ready");
2937 memset (&server, 0, sizeof (server));
2938 server.message_fd = ASSUAN_INVALID_FD;
2939 server.input_enc = GPGME_DATA_ENCODING_NONE;
2940 server.output_enc = GPGME_DATA_ENCODING_NONE;
2941 server.message_enc = GPGME_DATA_ENCODING_NONE;
2944 gt->write_status = server_write_status;
2945 gt->write_status_hook = &server;
2946 gt->write_data = server_write_data;
2947 gt->write_data_hook = &server;
2949 /* We use a pipe based server so that we can work from scripts.
2950 assuan_init_pipe_server will automagically detect when we are
2951 called with a socketpair and ignore FIELDES in this case. */
2952 #ifdef HAVE_W32CE_SYSTEM
2953 filedes[0] = ASSUAN_STDIN;
2954 filedes[1] = ASSUAN_STDOUT;
2956 filedes[0] = assuan_fdopen (0);
2957 filedes[1] = assuan_fdopen (1);
2959 err = assuan_new (&server.assuan_ctx);
2961 log_error (1, err, "can't create assuan context");
2963 assuan_set_pointer (server.assuan_ctx, &server);
2965 err = assuan_init_pipe_server (server.assuan_ctx, filedes);
2967 log_error (1, err, "can't initialize assuan server");
2968 err = register_commands (server.assuan_ctx);
2970 log_error (1, err, "can't register assuan commands");
2971 assuan_set_hello_line (server.assuan_ctx, hello);
2973 assuan_register_reset_notify (server.assuan_ctx, reset_notify);
2975 #define DBG_ASSUAN 0
2977 assuan_set_log_stream (server.assuan_ctx, log_stream);
2981 err = assuan_accept (server.assuan_ctx);
2986 log_error (0, err, "assuan accept problem");
2990 err = assuan_process (server.assuan_ctx);
2992 log_error (0, err, "assuan processing failed");
2995 assuan_release (server.assuan_ctx);
3000 /* MAIN PROGRAM STARTS HERE. */
3002 const char *argp_program_version = VERSION;
3003 const char *argp_program_bug_address = "bug-gpgme@gnupg.org";
3004 error_t argp_err_exit_status = 1;
3006 static char doc[] = "GPGME Tool -- invoke GPGME operations";
3007 static char args_doc[] = "COMMAND [OPTIONS...]";
3009 static struct argp_option options[] = {
3010 { "server", 's', 0, 0, "Server mode" },
3014 static error_t parse_options (int key, char *arg, struct argp_state *state);
3015 static struct argp argp = { options, parse_options, args_doc, doc };
3019 enum { CMD_DEFAULT, CMD_SERVER } cmd;
3023 args_init (struct args *args)
3025 memset (args, '\0', sizeof (*args));
3026 args->cmd = CMD_DEFAULT;
3031 parse_options (int key, char *arg, struct argp_state *state)
3033 struct args *args = state->input;
3038 args->cmd = CMD_SERVER;
3042 if (state->arg_num >= 2)
3044 printf ("Arg[%i] = %s\n", state->arg_num, arg);
3047 if (state->arg_num < 2)
3053 return ARGP_ERR_UNKNOWN;
3060 main (int argc, char *argv[])
3063 struct gpgme_tool gt;
3065 #ifdef HAVE_SETLOCALE
3066 setlocale (LC_ALL, "");
3068 gpgme_check_version (NULL);
3070 gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
3073 gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
3078 argp_parse (&argp, argc, argv, 0, 0, &args);
3091 gpgme_release (gt.ctx);
3093 #ifdef HAVE_W32CE_SYSTEM
3094 /* Give the buggy ssh server time to flush the output buffers. */