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;
112 #define ARGP_ERR_UNKNOWN EDEADLOCK
113 #define ARGP_KEY_ARG 0
114 #define ARGP_KEY_ARGS 0x1000006
115 #define ARGP_KEY_END 0x1000001
116 #define ARGP_KEY_NO_ARGS 0x1000002
117 #define ARGP_KEY_INIT 0x1000003
118 #define ARGP_KEY_FINI 0x1000007
119 #define ARGP_KEY_SUCCESS 0x1000004
120 #define ARGP_KEY_ERROR 0x1000005
121 typedef error_t (*argp_parser_t) (int key, char *arg, struct argp_state *state);
125 const struct argp_option *options;
126 argp_parser_t parser;
127 const char *args_doc;
130 const struct argp_child *children;
131 char *(*help_filter) (int key, const char *text, void *input);
132 const char *argp_domain;
135 #define ARGP_HELP_USAGE ARGP_HELP_SHORT_USAGE
136 #define ARGP_HELP_SHORT_USAGE 0x02
137 #define ARGP_HELP_SEE 0x04
138 #define ARGP_HELP_LONG 0x08
139 #define ARGP_HELP_PRE_DOC 0x10
140 #define ARGP_HELP_POST_DOC 0x20
141 #define ARGP_HELP_DOC (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC)
142 #define ARGP_HELP_BUG_ADDR 0x40
143 #define ARGP_HELP_EXIT_ERR 0x100
144 #define ARGP_HELP_EXIT_OK 0x200
145 #define ARGP_HELP_STD_ERR (ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
146 #define ARGP_HELP_STD_USAGE \
147 (ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
148 #define ARGP_HELP_STD_HELP \
149 (ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK \
150 | ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR)
153 void argp_error (const struct argp_state *state,
154 const char *fmt, ...) GT_GCC_A_PRINTF(2, 3);
159 _argp_pname (char *name)
162 char *bname = strrchr (pname, '/');
164 bname = strrchr (pname, '\\');
172 _argp_state_help (const struct argp *argp, const struct argp_state *state,
173 FILE *stream, unsigned flags, char *name)
178 if (flags & ARGP_HELP_SHORT_USAGE)
179 fprintf (stream, "Usage: %s [OPTIONS...] %s\n", name, argp->args_doc);
180 if (flags & ARGP_HELP_SEE)
181 fprintf (stream, "Try `%s --help' or `%s --usage' for more information.\n",
183 if (flags & ARGP_HELP_PRE_DOC)
187 strncpy (buf, argp->doc, sizeof (buf));
188 buf[sizeof (buf) - 1] = '\0';
189 end = strchr (buf, '\v');
192 fprintf (stream, "%s\n%s", buf, buf[0] ? "\n" : "");
194 if (flags & ARGP_HELP_LONG)
196 const struct argp_option *opt = argp->options;
200 char spaces[NSPACES + 1] = " ";
202 fprintf (stream, " ");
204 if (isascii (opt->key))
206 fprintf (stream, "-%c", opt->key);
210 fprintf (stream, ", ");
216 fprintf (stream, "--%s", opt->name);
217 len += 2 + strlen (opt->name);
219 if (opt->arg && (opt->flags & OPTION_ARG_OPTIONAL))
221 fprintf (stream, "[=%s]", opt->arg);
222 len += 3 + strlen (opt->arg);
226 fprintf (stream, "=%s", opt->arg);
227 len += 1 + strlen (opt->arg);
231 spaces[NSPACES - len] = '\0';
232 fprintf (stream, "%s%s\n", spaces, opt->doc);
235 fprintf (stream, " -?, --help Give this help list\n");
236 fprintf (stream, " --usage Give a short usage "
239 if (flags & ARGP_HELP_POST_DOC)
243 strncpy (buf, argp->doc, sizeof (buf));
244 buf[sizeof (buf) - 1] = '\0';
245 end = strchr (buf, '\v');
250 fprintf (stream, "\n%s\n", end);
252 fprintf (stream, "\nMandatory or optional arguments to long options are also mandatory or optional\n");
253 fprintf (stream, "for any corresponding short options.\n");
255 if (flags & ARGP_HELP_BUG_ADDR)
256 fprintf (stream, "\nReport bugs to %s.\n", argp_program_bug_address);
258 if (flags & ARGP_HELP_EXIT_ERR)
259 exit (argp_err_exit_status);
260 if (flags & ARGP_HELP_EXIT_OK)
266 argp_usage (const struct argp_state *state)
268 _argp_state_help (state->root_argp, state, state->err_stream,
269 ARGP_HELP_STD_USAGE, state->name);
274 argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags)
276 _argp_state_help (state->root_argp, state, stream, flags, state->name);
281 argp_error (const struct argp_state *state, const char *fmt, ...)
285 fprintf (state->err_stream, "%s: ", state->name);
287 vfprintf (state->err_stream, fmt, ap);
289 fprintf (state->err_stream, "\n");
290 argp_state_help (state, state->err_stream, ARGP_HELP_STD_ERR);
291 exit (argp_err_exit_status);
296 argp_help (const struct argp *argp, FILE *stream, unsigned flags, char *name)
298 _argp_state_help (argp, NULL, stream, flags, name);
303 argp_parse (const struct argp *argp, int argc,
304 char **argv, unsigned flags, int *arg_index, void *input)
307 struct argp_state state = { argp, argc, argv, 1, flags, 0, 0, input,
308 NULL, NULL, _argp_pname (argv[0]),
309 stderr, stdout, NULL };
310 /* All non-option arguments are collected at the beginning of
311 &argv[1] during processing. This is a counter for their number. */
312 int non_opt_args = 0;
314 rc = argp->parser (ARGP_KEY_INIT, NULL, &state);
315 if (rc && rc != ARGP_ERR_UNKNOWN)
318 while (state.next < state.argc - non_opt_args)
320 int idx = state.next;
323 if (! strcasecmp (state.argv[idx], "--"))
329 if (state.quoted || state.argv[idx][0] != '-')
331 char *arg_saved = state.argv[idx];
333 memmove (&state.argv[idx], &state.argv[idx + 1],
334 (state.argc - 1 - idx) * sizeof (char *));
335 state.argv[argc - 1] = arg_saved;
338 else if (! strcasecmp (state.argv[idx], "--help")
339 || !strcmp (state.argv[idx], "-?"))
341 argp_state_help (&state, state.out_stream, ARGP_HELP_STD_HELP);
343 else if (! strcasecmp (state.argv[idx], "--usage"))
345 argp_state_help (&state, state.out_stream,
346 ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
348 else if (! strcasecmp (state.argv[idx], "--version")
349 || !strcmp (state.argv[idx], "-V"))
351 fprintf (state.out_stream, "%s\n", argp_program_version);
356 /* Search for option and call parser with its KEY. */
357 int key = ARGP_KEY_ARG; /* Just some dummy value. */
358 const struct argp_option *opt = argp->options;
362 /* Check for --opt=value syntax. */
363 arg = strchr (state.argv[idx], '=');
370 if (state.argv[idx][1] != '-')
371 key = state.argv[idx][1];
373 while (! found && opt->key)
376 || (key == ARGP_KEY_ARG
377 && ! strcasecmp (&state.argv[idx][2], opt->name)))
379 if (arg && !opt->arg)
380 argp_error (&state, "Option %s does not take an argument",
382 if (opt->arg && state.next < state.argc
383 && state.argv[idx + 1][0] != '-')
385 arg = state.argv[idx + 1];
388 if (opt->arg && !(opt->flags & OPTION_ARG_OPTIONAL))
389 argp_error (&state, "Option %s requires an argument",
392 rc = argp->parser (opt->key, arg, &state);
393 if (rc == ARGP_ERR_UNKNOWN)
402 argp_error (&state, "Unknown option %s", state.argv[idx]);
406 while (state.next < state.argc)
408 /* Call parser for all non-option args. */
409 int idx = state.next;
411 rc = argp->parser (ARGP_KEY_ARG, state.argv[idx], &state);
412 if (rc && rc != ARGP_ERR_UNKNOWN)
414 if (rc == ARGP_ERR_UNKNOWN)
416 int old_next = state.next;
417 rc = argp->parser (ARGP_KEY_ARGS, NULL, &state);
418 if (rc == ARGP_ERR_UNKNOWN)
420 argp_error (&state, "Too many arguments");
423 if (! rc && state.next == old_next)
425 state.arg_num += state.argc - state.next;
426 state.next = state.argc;
433 if (state.arg_num == 0)
435 rc = argp->parser (ARGP_KEY_NO_ARGS, NULL, &state);
436 if (rc && rc != ARGP_ERR_UNKNOWN)
439 if (state.next == state.argc)
441 rc = argp->parser (ARGP_KEY_END, NULL, &state);
442 if (rc && rc != ARGP_ERR_UNKNOWN)
445 rc = argp->parser (ARGP_KEY_FINI, NULL, &state);
446 if (rc && rc != ARGP_ERR_UNKNOWN)
450 argp->parser (ARGP_KEY_SUCCESS, NULL, &state);
455 argp_error (&state, "unexpected error: %s", strerror (rc));
456 argp->parser (ARGP_KEY_ERROR, NULL, &state);
459 argp->parser (ARGP_KEY_FINI, NULL, &state);
462 *arg_index = state.next - 1;
471 char *program_name = "gpgme-tool";
473 #define spacep(p) (*(p) == ' ' || *(p) == '\t')
476 void log_error (int status, gpg_error_t errnum,
477 const char *fmt, ...) GT_GCC_A_PRINTF(3,4);
488 log_error (int status, gpg_error_t errnum, const char *fmt, ...)
492 fprintf (log_stream, "%s: ", program_name);
494 vfprintf (log_stream, fmt, ap);
497 fprintf (log_stream, ": %s <%s>", gpg_strerror (errnum),
498 gpg_strsource (errnum));
499 fprintf (log_stream, "\n");
505 /* Check whether the option NAME appears in LINE. */
507 has_option (const char *line, const char *name)
510 int n = strlen (name);
512 s = strstr (line, name);
513 return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
516 /* Skip over options. It is assumed that leading spaces have been
517 removed (this is the case for lines passed to a handler from
518 assuan). Blanks after the options are also removed. */
520 skip_options (char *line)
522 while ( *line == '-' && line[1] == '-' )
524 while (*line && !spacep (line))
526 while (spacep (line))
535 typedef gpg_error_t (*result_xml_write_cb_t) (void *hook, const void *buf,
538 struct result_xml_state
541 result_xml_write_cb_t cb;
547 int had_data[MAX_TAGS];
552 result_init (struct result_xml_state *state, int indent,
553 result_xml_write_cb_t cb, void *hook)
555 memset (state, '\0', sizeof (*state));
556 state->indent = indent;
563 result_xml_indent (struct result_xml_state *state)
565 char spaces[state->indent + 1];
567 for (i = 0; i < state->indent; i++)
570 return (*state->cb) (state->hook, spaces, i);
575 result_xml_tag_start (struct result_xml_state *state, char *name, ...)
577 result_xml_write_cb_t cb = state->cb;
578 void *hook = state->hook;
585 if (state->next_tag > 0)
587 if (! state->had_data[state->next_tag - 1])
589 (*cb) (hook, ">\n", 2);
590 (*cb) (hook, NULL, 0);
592 state->had_data[state->next_tag - 1] = 1;
595 result_xml_indent (state);
596 (*cb) (hook, "<", 1);
597 (*cb) (hook, name, strlen (name));
599 state->tag[state->next_tag] = name;
600 state->had_data[state->next_tag] = 0;
606 attr = va_arg (ap, char *);
610 attr_val = va_arg (ap, char *);
611 if (attr_val == NULL)
614 (*cb) (hook, " ", 1);
615 (*cb) (hook, attr, strlen (attr));
616 (*cb) (hook, "=\"", 2);
617 (*cb) (hook, attr_val, strlen (attr_val));
618 (*cb) (hook, "\"", 1);
626 result_xml_tag_data (struct result_xml_state *state, char *data)
628 result_xml_write_cb_t cb = state->cb;
629 void *hook = state->hook;
631 if (state->had_data[state->next_tag - 1])
633 (*cb) (hook, "\n", 2);
634 (*cb) (hook, NULL, 0);
635 result_xml_indent (state);
638 (*cb) (hook, ">", 1);
639 state->had_data[state->next_tag - 1] = 2;
641 (*cb) (hook, data, strlen (data));
648 result_xml_tag_end (struct result_xml_state *state)
650 result_xml_write_cb_t cb = state->cb;
651 void *hook = state->hook;
656 if (state->had_data[state->next_tag])
658 if (state->had_data[state->next_tag] == 1)
659 result_xml_indent (state);
660 (*cb) (hook, "</", 2);
661 (*cb) (hook, state->tag[state->next_tag],
662 strlen (state->tag[state->next_tag]));
663 (*cb) (hook, ">\n", 2);
664 (*cb) (hook, NULL, 0);
668 (*cb) (hook, " />\n", 4);
669 (*cb) (hook, NULL, 0);
676 result_add_error (struct result_xml_state *state, char *name, gpg_error_t err)
680 snprintf (code, sizeof (code) - 1, "0x%x", err);
681 snprintf (msg, sizeof (msg) - 1, "%s <%s>",
682 gpg_strerror (err), gpg_strsource (err));
683 result_xml_tag_start (state, name, "value", code, NULL);
684 result_xml_tag_data (state, msg);
685 result_xml_tag_end (state);
691 result_add_pubkey_algo (struct result_xml_state *state,
692 char *name, gpgme_pubkey_algo_t algo)
696 snprintf (code, sizeof (code) - 1, "0x%x", algo);
697 snprintf (msg, sizeof (msg) - 1, "%s",
698 gpgme_pubkey_algo_name (algo));
699 result_xml_tag_start (state, name, "value", code, NULL);
700 result_xml_tag_data (state, msg);
701 result_xml_tag_end (state);
707 result_add_hash_algo (struct result_xml_state *state,
708 char *name, gpgme_hash_algo_t algo)
712 snprintf (code, sizeof (code) - 1, "0x%x", algo);
713 snprintf (msg, sizeof (msg) - 1, "%s",
714 gpgme_hash_algo_name (algo));
715 result_xml_tag_start (state, name, "value", code, NULL);
716 result_xml_tag_data (state, msg);
717 result_xml_tag_end (state);
723 result_add_keyid (struct result_xml_state *state, char *name, char *keyid)
725 result_xml_tag_start (state, name, NULL);
726 result_xml_tag_data (state, keyid);
727 result_xml_tag_end (state);
733 result_add_fpr (struct result_xml_state *state, char *name, char *fpr)
735 result_xml_tag_start (state, name, NULL);
736 result_xml_tag_data (state, fpr);
737 result_xml_tag_end (state);
743 result_add_timestamp (struct result_xml_state *state, char *name,
744 unsigned int timestamp)
748 snprintf (code, sizeof (code) - 1, "%ui", timestamp);
749 result_xml_tag_start (state, name, "unix", code, NULL);
750 result_xml_tag_end (state);
756 result_add_sig_mode (struct result_xml_state *state, char *name,
757 gpgme_sig_mode_t sig_mode)
762 snprintf (code, sizeof (code) - 1, "%i", sig_mode);
765 case GPGME_SIG_MODE_NORMAL:
768 case GPGME_SIG_MODE_DETACH:
771 case GPGME_SIG_MODE_CLEAR:
778 result_xml_tag_start (state, name, "type", mode, "value", code, NULL);
779 result_xml_tag_data (state, mode);
780 result_xml_tag_end (state);
786 result_add_value (struct result_xml_state *state,
787 char *name, unsigned int val)
791 snprintf (code, sizeof (code) - 1, "0x%x", val);
792 result_xml_tag_start (state, name, "value", code, NULL);
793 result_xml_tag_end (state);
799 result_add_string (struct result_xml_state *state,
800 char *name, char *str)
802 result_xml_tag_start (state, name, NULL);
803 result_xml_tag_data (state, str);
804 result_xml_tag_end (state);
810 result_encrypt_to_xml (gpgme_ctx_t ctx, int indent,
811 result_xml_write_cb_t cb, void *hook)
813 struct result_xml_state state;
814 gpgme_encrypt_result_t res = gpgme_op_encrypt_result (ctx);
815 gpgme_invalid_key_t inv_recp;
820 result_init (&state, indent, cb, hook);
821 result_xml_tag_start (&state, "encrypt-result", NULL);
823 inv_recp = res->invalid_recipients;
826 result_xml_tag_start (&state, "invalid-recipients", NULL);
830 result_xml_tag_start (&state, "invalid-key", NULL);
832 result_add_fpr (&state, "fpr", inv_recp->fpr);
833 result_add_error (&state, "reason", inv_recp->reason);
834 result_xml_tag_end (&state);
835 inv_recp = inv_recp->next;
837 result_xml_tag_end (&state);
839 result_xml_tag_end (&state);
846 result_decrypt_to_xml (gpgme_ctx_t ctx, int indent,
847 result_xml_write_cb_t cb, void *hook)
849 struct result_xml_state state;
850 gpgme_decrypt_result_t res = gpgme_op_decrypt_result (ctx);
851 gpgme_recipient_t recp;
856 result_init (&state, indent, cb, hook);
857 result_xml_tag_start (&state, "decrypt-result", NULL);
861 result_xml_tag_start (&state, "file-name", NULL);
862 result_xml_tag_data (&state, res->file_name);
863 result_xml_tag_end (&state);
865 if (res->unsupported_algorithm)
867 result_xml_tag_start (&state, "unsupported-alogorithm", NULL);
868 result_xml_tag_data (&state, res->unsupported_algorithm);
869 result_xml_tag_end (&state);
871 if (res->wrong_key_usage)
873 result_xml_tag_start (&state, "wrong-key-usage", NULL);
874 result_xml_tag_end (&state);
877 recp = res->recipients;
880 result_xml_tag_start (&state, "recipients", NULL);
883 result_xml_tag_start (&state, "recipient", NULL);
884 result_add_keyid (&state, "keyid", recp->keyid);
885 result_add_pubkey_algo (&state, "pubkey-algo", recp->pubkey_algo);
886 result_add_error (&state, "status", recp->status);
887 result_xml_tag_end (&state);
890 result_xml_tag_end (&state);
892 result_xml_tag_end (&state);
899 result_sign_to_xml (gpgme_ctx_t ctx, int indent,
900 result_xml_write_cb_t cb, void *hook)
902 struct result_xml_state state;
903 gpgme_sign_result_t res = gpgme_op_sign_result (ctx);
904 gpgme_invalid_key_t inv_key;
905 gpgme_new_signature_t new_sig;
910 result_init (&state, indent, cb, hook);
911 result_xml_tag_start (&state, "sign-result", NULL);
913 inv_key = res->invalid_signers;
916 result_xml_tag_start (&state, "invalid-signers", NULL);
920 result_xml_tag_start (&state, "invalid-key", NULL);
922 result_add_fpr (&state, "fpr", inv_key->fpr);
923 result_add_error (&state, "reason", inv_key->reason);
924 result_xml_tag_end (&state);
925 inv_key = inv_key->next;
927 result_xml_tag_end (&state);
930 new_sig = res->signatures;
933 result_xml_tag_start (&state, "signatures", NULL);
937 result_xml_tag_start (&state, "new-signature", NULL);
938 result_add_sig_mode (&state, "type", new_sig->type);
939 result_add_pubkey_algo (&state, "pubkey-algo", new_sig->pubkey_algo);
940 result_add_hash_algo (&state, "hash-algo", new_sig->hash_algo);
941 result_add_timestamp (&state, "timestamp", new_sig->timestamp);
943 result_add_fpr (&state, "fpr", new_sig->fpr);
944 result_add_value (&state, "sig-class", new_sig->sig_class);
946 result_xml_tag_end (&state);
947 new_sig = new_sig->next;
949 result_xml_tag_end (&state);
952 result_xml_tag_end (&state);
959 result_verify_to_xml (gpgme_ctx_t ctx, int indent,
960 result_xml_write_cb_t cb, void *hook)
962 struct result_xml_state state;
963 gpgme_verify_result_t res = gpgme_op_verify_result (ctx);
964 gpgme_signature_t sig;
969 result_init (&state, indent, cb, hook);
970 result_xml_tag_start (&state, "verify-result", NULL);
974 result_xml_tag_start (&state, "file-name", NULL);
975 result_xml_tag_data (&state, res->file_name);
976 result_xml_tag_end (&state);
979 sig = res->signatures;
982 result_xml_tag_start (&state, "signatures", NULL);
986 result_xml_tag_start (&state, "signature", NULL);
988 /* FIXME: Could be done better. */
989 result_add_value (&state, "summary", sig->summary);
991 result_add_fpr (&state, "fpr", sig->fpr);
992 result_add_error (&state, "status", sig->status);
993 /* FIXME: notations */
994 result_add_timestamp (&state, "timestamp", sig->timestamp);
995 result_add_timestamp (&state, "exp-timestamp", sig->exp_timestamp);
996 result_add_value (&state, "wrong-key-usage", sig->wrong_key_usage);
997 result_add_value (&state, "pka-trust", sig->pka_trust);
998 result_add_value (&state, "chain-model", sig->chain_model);
999 result_add_value (&state, "validity", sig->validity);
1000 result_add_error (&state, "validity-reason", sig->validity_reason);
1001 result_add_pubkey_algo (&state, "pubkey-algo", sig->pubkey_algo);
1002 result_add_hash_algo (&state, "hash-algo", sig->hash_algo);
1003 if (sig->pka_address)
1004 result_add_string (&state, "pka_address", sig->pka_address);
1006 result_xml_tag_end (&state);
1009 result_xml_tag_end (&state);
1012 result_xml_tag_end (&state);
1019 result_import_to_xml (gpgme_ctx_t ctx, int indent,
1020 result_xml_write_cb_t cb, void *hook)
1022 struct result_xml_state state;
1023 gpgme_import_result_t res = gpgme_op_import_result (ctx);
1024 gpgme_import_status_t stat;
1029 result_init (&state, indent, cb, hook);
1030 result_xml_tag_start (&state, "import-result", NULL);
1032 result_add_value (&state, "considered", res->considered);
1033 result_add_value (&state, "no-user-id", res->no_user_id);
1034 result_add_value (&state, "imported", res->imported);
1035 result_add_value (&state, "imported-rsa", res->imported_rsa);
1036 result_add_value (&state, "unchanged", res->unchanged);
1037 result_add_value (&state, "new-user-ids", res->new_user_ids);
1038 result_add_value (&state, "new-sub-keys", res->new_sub_keys);
1039 result_add_value (&state, "new-signatures", res->new_signatures);
1040 result_add_value (&state, "new-revocations", res->new_revocations);
1041 result_add_value (&state, "secret-read", res->secret_read);
1042 result_add_value (&state, "secret-imported", res->secret_imported);
1043 result_add_value (&state, "secret-unchanged", res->secret_unchanged);
1044 result_add_value (&state, "skipped-new-keys", res->skipped_new_keys);
1045 result_add_value (&state, "not-imported", res->not_imported);
1047 stat = res->imports;
1050 result_xml_tag_start (&state, "imports", NULL);
1054 result_xml_tag_start (&state, "import-status", NULL);
1057 result_add_fpr (&state, "fpr", stat->fpr);
1058 result_add_error (&state, "result", stat->result);
1059 /* FIXME: Could be done better. */
1060 result_add_value (&state, "status", stat->status);
1062 result_xml_tag_end (&state);
1065 result_xml_tag_end (&state);
1068 result_xml_tag_end (&state);
1075 result_genkey_to_xml (gpgme_ctx_t ctx, int indent,
1076 result_xml_write_cb_t cb, void *hook)
1078 struct result_xml_state state;
1079 gpgme_genkey_result_t res = gpgme_op_genkey_result (ctx);
1084 result_init (&state, indent, cb, hook);
1085 result_xml_tag_start (&state, "genkey-result", NULL);
1087 result_add_value (&state, "primary", res->primary);
1088 result_add_value (&state, "sub", res->sub);
1090 result_add_fpr (&state, "fpr", res->fpr);
1092 result_xml_tag_end (&state);
1099 result_keylist_to_xml (gpgme_ctx_t ctx, int indent,
1100 result_xml_write_cb_t cb, void *hook)
1102 struct result_xml_state state;
1103 gpgme_keylist_result_t res = gpgme_op_keylist_result (ctx);
1108 result_init (&state, indent, cb, hook);
1109 result_xml_tag_start (&state, "keylist-result", NULL);
1111 result_add_value (&state, "truncated", res->truncated);
1113 result_xml_tag_end (&state);
1120 result_vfs_mount_to_xml (gpgme_ctx_t ctx, int indent,
1121 result_xml_write_cb_t cb, void *hook)
1123 struct result_xml_state state;
1124 gpgme_vfs_mount_result_t res = gpgme_op_vfs_mount_result (ctx);
1129 result_init (&state, indent, cb, hook);
1130 result_xml_tag_start (&state, "vfs-mount-result", NULL);
1132 result_add_string (&state, "mount-dir", res->mount_dir);
1134 result_xml_tag_end (&state);
1147 STATUS_INCLUDE_CERTS,
1148 STATUS_KEYLIST_MODE,
1150 STATUS_ENCRYPT_RESULT
1153 const char *status_string[] =
1169 #define MAX_RECIPIENTS 10
1170 gpgme_key_t recipients[MAX_RECIPIENTS + 1];
1173 gpg_error_t (*write_status) (void *hook, const char *status, const char *msg);
1174 void *write_status_hook;
1175 gpg_error_t (*write_data) (void *hook, const void *buf, size_t len);
1176 void *write_data_hook;
1178 typedef struct gpgme_tool *gpgme_tool_t;
1181 /* Forward declaration. */
1182 void gt_write_status (gpgme_tool_t gt,
1183 status_t status, ...) GT_GCC_A_SENTINEL(0);
1186 _gt_progress_cb (void *opaque, const char *what,
1187 int type, int current, int total)
1189 gpgme_tool_t gt = opaque;
1192 snprintf (buf, sizeof (buf), "0x%02x %i %i", type, current, total);
1193 gt_write_status (gt, STATUS_PROGRESS, what, buf, NULL);
1198 _gt_gpgme_new (gpgme_tool_t gt, gpgme_ctx_t *ctx)
1202 err = gpgme_new (ctx);
1205 gpgme_set_progress_cb (*ctx, _gt_progress_cb, gt);
1211 gt_init (gpgme_tool_t gt)
1213 memset (gt, '\0', sizeof (*gt));
1216 err = _gt_gpgme_new (gt, >->ctx);
1218 log_error (1, err, "can't create gpgme context");
1223 gt_signers_add (gpgme_tool_t gt, const char *fpr)
1228 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1232 return gpgme_signers_add (gt->ctx, key);
1237 gt_signers_clear (gpgme_tool_t gt)
1239 gpgme_signers_clear (gt->ctx);
1245 gt_get_key (gpgme_tool_t gt, const char *pattern, gpgme_key_t *r_key)
1248 gpgme_ctx_t listctx;
1252 if (!gt || !r_key || !pattern)
1253 return gpg_error (GPG_ERR_INV_VALUE);
1257 err = gpgme_new (&listctx);
1262 gpgme_protocol_t proto;
1263 gpgme_engine_info_t info;
1265 /* Clone the relevant state. */
1266 proto = gpgme_get_protocol (ctx);
1267 /* The g13 protocol does not allow keylisting, we need to choose
1269 if (proto == GPGME_PROTOCOL_G13)
1270 proto = GPGME_PROTOCOL_OpenPGP;
1272 gpgme_set_protocol (listctx, proto);
1273 gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
1274 info = gpgme_ctx_get_engine_info (ctx);
1275 while (info && info->protocol != proto)
1278 gpgme_ctx_set_engine_info (listctx, proto,
1279 info->file_name, info->home_dir);
1282 err = gpgme_op_keylist_start (listctx, pattern, 0);
1284 err = gpgme_op_keylist_next (listctx, r_key);
1288 err = gpgme_op_keylist_next (listctx, &key);
1289 if (gpgme_err_code (err) == GPG_ERR_EOF)
1294 && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr
1295 && key && key->subkeys && key->subkeys->fpr
1296 && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr))
1298 /* The fingerprint is identical. We assume that this is
1299 the same key and don't mark it as an ambiguous. This
1300 problem may occur with corrupted keyrings and has
1301 been noticed often with gpgsm. In fact gpgsm uses a
1302 similar hack to sort out such duplicates but it can't
1303 do that while listing keys. */
1304 gpgme_key_unref (key);
1309 gpgme_key_unref (key);
1310 err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
1312 gpgme_key_unref (*r_key);
1315 gpgme_release (listctx);
1318 gt_write_status (gt, STATUS_RECIPIENT,
1319 ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
1320 (*r_key)->subkeys->fpr : "invalid", NULL);
1326 gt_recipients_add (gpgme_tool_t gt, const char *pattern)
1331 if (gt->recipients_nr >= MAX_RECIPIENTS)
1332 return gpg_error_from_errno (ENOMEM);
1334 if (gpgme_get_protocol (gt->ctx) == GPGME_PROTOCOL_UISERVER)
1335 err = gpgme_key_from_uid (&key, pattern);
1337 err = gt_get_key (gt, pattern, &key);
1341 gt->recipients[gt->recipients_nr++] = key;
1347 gt_recipients_clear (gpgme_tool_t gt)
1351 for (idx = 0; idx < gt->recipients_nr; idx++)
1352 gpgme_key_unref (gt->recipients[idx]);
1353 memset (gt->recipients, '\0', gt->recipients_nr * sizeof (gpgme_key_t));
1354 gt->recipients_nr = 0;
1359 gt_reset (gpgme_tool_t gt)
1364 err = _gt_gpgme_new (gt, &ctx);
1368 gpgme_release (gt->ctx);
1370 gt_recipients_clear (gt);
1376 gt_write_status (gpgme_tool_t gt, status_t status, ...)
1385 va_start (ap, status);
1388 while ((text = va_arg (ap, const char *)))
1395 while (*text && n < sizeof (buf) - 2)
1404 err = gt->write_status (gt->write_status_hook, status_string[status], buf);
1406 log_error (1, err, "can't write status line");
1411 gt_write_data (gpgme_tool_t gt, const void *buf, size_t len)
1413 return gt->write_data (gt->write_data_hook, buf, len);
1418 gt_get_engine_info (gpgme_tool_t gt, gpgme_protocol_t proto)
1420 gpgme_engine_info_t info;
1421 info = gpgme_ctx_get_engine_info (gt->ctx);
1424 if (proto == GPGME_PROTOCOL_UNKNOWN || proto == info->protocol)
1425 gt_write_status (gt, STATUS_ENGINE,
1426 gpgme_get_protocol_name (info->protocol),
1427 info->file_name, info->version,
1428 info->req_version, info->home_dir, NULL);
1436 gt_protocol_from_name (const char *name)
1438 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_OpenPGP)))
1439 return GPGME_PROTOCOL_OpenPGP;
1440 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_CMS)))
1441 return GPGME_PROTOCOL_CMS;
1442 if (! strcasecmp (name,gpgme_get_protocol_name (GPGME_PROTOCOL_GPGCONF)))
1443 return GPGME_PROTOCOL_GPGCONF;
1444 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_ASSUAN)))
1445 return GPGME_PROTOCOL_ASSUAN;
1446 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_G13)))
1447 return GPGME_PROTOCOL_G13;
1448 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_UISERVER)))
1449 return GPGME_PROTOCOL_UISERVER;
1450 if (! strcasecmp (name, gpgme_get_protocol_name (GPGME_PROTOCOL_DEFAULT)))
1451 return GPGME_PROTOCOL_DEFAULT;
1452 return GPGME_PROTOCOL_UNKNOWN;
1457 gt_set_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
1459 return gpgme_set_protocol (gt->ctx, proto);
1464 gt_get_protocol (gpgme_tool_t gt)
1466 gpgme_protocol_t proto = gpgme_get_protocol (gt->ctx);
1468 gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
1476 gt_set_sub_protocol (gpgme_tool_t gt, gpgme_protocol_t proto)
1478 return gpgme_set_sub_protocol (gt->ctx, proto);
1483 gt_get_sub_protocol (gpgme_tool_t gt)
1485 gpgme_protocol_t proto = gpgme_get_sub_protocol (gt->ctx);
1487 gt_write_status (gt, STATUS_PROTOCOL, gpgme_get_protocol_name (proto),
1495 gt_set_armor (gpgme_tool_t gt, int armor)
1497 gpgme_set_armor (gt->ctx, armor);
1503 gt_get_armor (gpgme_tool_t gt)
1505 gt_write_status (gt, STATUS_ARMOR,
1506 gpgme_get_armor (gt->ctx) ? "true" : "false", NULL);
1513 gt_set_textmode (gpgme_tool_t gt, int textmode)
1515 gpgme_set_textmode (gt->ctx, textmode);
1521 gt_get_textmode (gpgme_tool_t gt)
1523 gt_write_status (gt, STATUS_TEXTMODE,
1524 gpgme_get_textmode (gt->ctx) ? "true" : "false", NULL);
1531 gt_set_keylist_mode (gpgme_tool_t gt, gpgme_keylist_mode_t keylist_mode)
1533 gpgme_set_keylist_mode (gt->ctx, keylist_mode);
1539 gt_get_keylist_mode (gpgme_tool_t gt)
1541 #define NR_KEYLIST_MODES 6
1542 const char *modes[NR_KEYLIST_MODES + 1];
1544 gpgme_keylist_mode_t mode = gpgme_get_keylist_mode (gt->ctx);
1546 if (mode & GPGME_KEYLIST_MODE_LOCAL)
1547 modes[idx++] = "local";
1548 if (mode & GPGME_KEYLIST_MODE_EXTERN)
1549 modes[idx++] = "extern";
1550 if (mode & GPGME_KEYLIST_MODE_SIGS)
1551 modes[idx++] = "sigs";
1552 if (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS)
1553 modes[idx++] = "sig_notations";
1554 if (mode & GPGME_KEYLIST_MODE_EPHEMERAL)
1555 modes[idx++] = "ephemeral";
1556 if (mode & GPGME_KEYLIST_MODE_VALIDATE)
1557 modes[idx++] = "validate";
1558 modes[idx++] = NULL;
1560 gt_write_status (gt, STATUS_KEYLIST_MODE, modes[0], modes[1], modes[2],
1561 modes[3], modes[4], modes[5], modes[6], NULL);
1568 gt_set_include_certs (gpgme_tool_t gt, int include_certs)
1570 gpgme_set_include_certs (gt->ctx, include_certs);
1576 gt_get_include_certs (gpgme_tool_t gt)
1578 int include_certs = gpgme_get_include_certs (gt->ctx);
1581 if (include_certs == GPGME_INCLUDE_CERTS_DEFAULT)
1582 strcpy (buf, "default");
1584 snprintf (buf, sizeof (buf), "%i", include_certs);
1586 gt_write_status (gt, STATUS_INCLUDE_CERTS, buf, NULL);
1593 gt_decrypt_verify (gpgme_tool_t gt, gpgme_data_t cipher, gpgme_data_t plain,
1597 return gpgme_op_decrypt_verify (gt->ctx, cipher, plain);
1599 return gpgme_op_decrypt (gt->ctx, cipher, plain);
1604 gt_sign_encrypt (gpgme_tool_t gt, gpgme_encrypt_flags_t flags,
1605 gpgme_data_t plain, gpgme_data_t cipher, int sign)
1610 err = gpgme_op_encrypt_sign (gt->ctx, gt->recipients, flags, plain, cipher);
1612 err = gpgme_op_encrypt (gt->ctx, gt->recipients, flags, plain, cipher);
1614 gt_recipients_clear (gt);
1621 gt_sign (gpgme_tool_t gt, gpgme_data_t plain, gpgme_data_t sig,
1622 gpgme_sig_mode_t mode)
1624 return gpgme_op_sign (gt->ctx, plain, sig, mode);
1629 gt_verify (gpgme_tool_t gt, gpgme_data_t sig, gpgme_data_t sig_text,
1632 return gpgme_op_verify (gt->ctx, sig, sig_text, plain);
1637 gt_import (gpgme_tool_t gt, gpgme_data_t data)
1639 return gpgme_op_import (gt->ctx, data);
1644 gt_export (gpgme_tool_t gt, const char *pattern[], gpgme_export_mode_t mode,
1647 return gpgme_op_export_ext (gt->ctx, pattern, mode, data);
1652 gt_genkey (gpgme_tool_t gt, const char *parms, gpgme_data_t public,
1653 gpgme_data_t secret)
1655 return gpgme_op_genkey (gt->ctx, parms, public, secret);
1660 gt_import_keys (gpgme_tool_t gt, char *fpr[])
1662 gpg_error_t err = 0;
1672 return gpg_error (GPG_ERR_INV_VALUE);
1674 keys = malloc ((cnt + 1) * sizeof (gpgme_key_t));
1676 return gpg_error_from_syserror ();
1678 for (idx = 0; idx < cnt; idx++)
1680 err = gpgme_get_key (gt->ctx, fpr[idx], &keys[idx], 0);
1687 err = gpgme_op_import_keys (gt->ctx, keys);
1692 gpgme_key_unref (keys[idx]);
1700 gt_delete (gpgme_tool_t gt, char *fpr, int allow_secret)
1705 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1709 err = gpgme_op_delete (gt->ctx, key, allow_secret);
1710 gpgme_key_unref (key);
1716 gt_keylist_start (gpgme_tool_t gt, const char *pattern[], int secret_only)
1718 return gpgme_op_keylist_ext_start (gt->ctx, pattern, secret_only, 0);
1723 gt_keylist_next (gpgme_tool_t gt, gpgme_key_t *key)
1725 return gpgme_op_keylist_next (gt->ctx, key);
1730 gt_getauditlog (gpgme_tool_t gt, gpgme_data_t output, unsigned int flags)
1732 return gpgme_op_getauditlog (gt->ctx, output, flags);
1737 gt_vfs_mount (gpgme_tool_t gt, const char *container_file,
1738 const char *mount_dir, int flags)
1742 err = gpgme_op_vfs_mount (gt->ctx, container_file, mount_dir, flags, &op_err);
1743 return err ? err : op_err;
1748 gt_vfs_create (gpgme_tool_t gt, const char *container_file, int flags)
1752 err = gpgme_op_vfs_create (gt->ctx, gt->recipients, container_file,
1754 gt_recipients_clear (gt);
1755 return err ? err : op_err;
1759 static const char hlp_passwd[] =
1760 "PASSWD <user-id>\n"
1762 "Ask the backend to change the passphrase for the key\n"
1763 "specified by USER-ID.";
1765 gt_passwd (gpgme_tool_t gt, char *fpr)
1770 err = gpgme_get_key (gt->ctx, fpr, &key, 0);
1772 return gpg_err_code (err) == GPG_ERR_EOF? gpg_error (GPG_ERR_NO_PUBKEY):err;
1774 err = gpgme_op_passwd (gt->ctx, key, 0);
1775 gpgme_key_unref (key);
1780 #define GT_RESULT_ENCRYPT 0x1
1781 #define GT_RESULT_DECRYPT 0x2
1782 #define GT_RESULT_SIGN 0x4
1783 #define GT_RESULT_VERIFY 0x8
1784 #define GT_RESULT_IMPORT 0x10
1785 #define GT_RESULT_GENKEY 0x20
1786 #define GT_RESULT_KEYLIST 0x40
1787 #define GT_RESULT_VFS_MOUNT 0x80
1788 #define GT_RESULT_ALL (~0U)
1791 gt_result (gpgme_tool_t gt, unsigned int flags)
1793 static const char xml_preamble1[] = "<?xml version=\"1.0\" "
1794 "encoding=\"UTF-8\" standalone=\"yes\"?>\n";
1795 static const char xml_preamble2[] = "<gpgme>\n";
1796 static const char xml_end[] = "</gpgme>\n";
1799 gt_write_data (gt, xml_preamble1, sizeof (xml_preamble1));
1800 gt_write_data (gt, NULL, 0);
1801 gt_write_data (gt, xml_preamble2, sizeof (xml_preamble2));
1802 gt_write_data (gt, NULL, 0);
1803 if (flags & GT_RESULT_ENCRYPT)
1804 result_encrypt_to_xml (gt->ctx, indent,
1805 (result_xml_write_cb_t) gt_write_data, gt);
1806 if (flags & GT_RESULT_DECRYPT)
1807 result_decrypt_to_xml (gt->ctx, indent,
1808 (result_xml_write_cb_t) gt_write_data, gt);
1809 if (flags & GT_RESULT_SIGN)
1810 result_sign_to_xml (gt->ctx, indent,
1811 (result_xml_write_cb_t) gt_write_data, gt);
1812 if (flags & GT_RESULT_VERIFY)
1813 result_verify_to_xml (gt->ctx, indent,
1814 (result_xml_write_cb_t) gt_write_data, gt);
1815 if (flags & GT_RESULT_IMPORT)
1816 result_import_to_xml (gt->ctx, indent,
1817 (result_xml_write_cb_t) gt_write_data, gt);
1818 if (flags & GT_RESULT_GENKEY)
1819 result_genkey_to_xml (gt->ctx, indent,
1820 (result_xml_write_cb_t) gt_write_data, gt);
1821 if (flags & GT_RESULT_KEYLIST)
1822 result_keylist_to_xml (gt->ctx, indent,
1823 (result_xml_write_cb_t) gt_write_data, gt);
1824 if (flags & GT_RESULT_VFS_MOUNT)
1825 result_vfs_mount_to_xml (gt->ctx, indent,
1826 (result_xml_write_cb_t) gt_write_data, gt);
1827 gt_write_data (gt, xml_end, sizeof (xml_end));
1840 assuan_context_t assuan_ctx;
1842 gpgme_data_encoding_t input_enc;
1843 gpgme_data_encoding_t output_enc;
1844 assuan_fd_t input_fd;
1845 char *input_filename;
1847 assuan_fd_t output_fd;
1848 char *output_filename;
1849 FILE *output_stream;
1850 assuan_fd_t message_fd;
1851 char *message_filename;
1852 FILE *message_stream;
1853 gpgme_data_encoding_t message_enc;
1858 server_write_status (void *hook, const char *status, const char *msg)
1860 struct server *server = hook;
1861 return assuan_write_status (server->assuan_ctx, status, msg);
1866 server_write_data (void *hook, const void *buf, size_t len)
1868 struct server *server = hook;
1869 return assuan_send_data (server->assuan_ctx, buf, len);
1875 server_parse_fd (assuan_context_t ctx, char *line, assuan_fd_t *rfd,
1878 *rfd = ASSUAN_INVALID_FD;
1881 if (! strncasecmp (line, "file=", 5))
1884 *filename = strdup (line + 5);
1886 return gpg_error_from_syserror();
1887 term = strchr (*filename, ' ');
1893 return assuan_command_parse_fd (ctx, line, rfd);
1897 static gpgme_data_encoding_t
1898 server_data_encoding (const char *line)
1900 if (strstr (line, "--binary"))
1901 return GPGME_DATA_ENCODING_BINARY;
1902 if (strstr (line, "--base64"))
1903 return GPGME_DATA_ENCODING_BASE64;
1904 if (strstr (line, "--armor"))
1905 return GPGME_DATA_ENCODING_ARMOR;
1906 if (strstr (line, "--url"))
1907 return GPGME_DATA_ENCODING_URL;
1908 if (strstr (line, "--urlesc"))
1909 return GPGME_DATA_ENCODING_URLESC;
1910 if (strstr (line, "--url0"))
1911 return GPGME_DATA_ENCODING_URL0;
1912 return GPGME_DATA_ENCODING_NONE;
1916 static gpgme_error_t
1917 server_data_obj (assuan_fd_t fd, char *fn, int out,
1918 gpgme_data_encoding_t encoding,
1919 gpgme_data_t *data, FILE **fs)
1926 *fs = fopen (fn, out ? "wb" : "rb");
1928 return gpg_error_from_syserror ();
1930 err = gpgme_data_new_from_stream (data, *fs);
1933 err = gpgme_data_new_from_fd (data, (int) fd);
1937 return gpgme_data_set_encoding (*data, encoding);
1942 server_reset_fds (struct server *server)
1944 /* assuan closes the input and output FDs for us when doing a RESET,
1945 but we use this same function after commands, so repeat it
1947 assuan_close_input_fd (server->assuan_ctx);
1948 assuan_close_output_fd (server->assuan_ctx);
1949 if (server->message_fd != ASSUAN_INVALID_FD)
1951 /* FIXME: Assuan should provide a close function. */
1953 CloseHandle (server->message_fd);
1955 close (server->message_fd);
1957 server->message_fd = ASSUAN_INVALID_FD;
1959 if (server->input_filename)
1961 free (server->input_filename);
1962 server->input_filename = NULL;
1964 if (server->output_filename)
1966 free (server->output_filename);
1967 server->output_filename = NULL;
1969 if (server->message_filename)
1971 free (server->message_filename);
1972 server->message_filename = NULL;
1974 if (server->input_stream)
1976 fclose (server->input_stream);
1977 server->input_stream = NULL;
1979 if (server->output_stream)
1981 fclose (server->output_stream);
1982 server->output_stream = NULL;
1984 if (server->message_stream)
1986 fclose (server->message_stream);
1987 server->message_stream = NULL;
1990 server->input_enc = GPGME_DATA_ENCODING_NONE;
1991 server->output_enc = GPGME_DATA_ENCODING_NONE;
1992 server->message_enc = GPGME_DATA_ENCODING_NONE;
1997 reset_notify (assuan_context_t ctx, char *line)
1999 struct server *server = assuan_get_pointer (ctx);
2000 server_reset_fds (server);
2001 gt_reset (server->gt);
2006 static const char hlp_version[] =
2007 "VERSION [<string>]\n"
2009 "Call the function gpgme_check_version.";
2011 cmd_version (assuan_context_t ctx, char *line)
2015 const char *version = gpgme_check_version (line);
2016 return version ? 0 : gpg_error (GPG_ERR_SELFTEST_FAILED);
2020 const char *version = gpgme_check_version (NULL);
2021 return assuan_send_data (ctx, version, strlen (version));
2027 cmd_engine (assuan_context_t ctx, char *line)
2029 struct server *server = assuan_get_pointer (ctx);
2030 return gt_get_engine_info (server->gt, gt_protocol_from_name (line));
2034 static const char hlp_protocol[] =
2035 "PROTOCOL [<name>]\n"
2037 "With NAME, set the protocol. Without return the current protocol.";
2039 cmd_protocol (assuan_context_t ctx, char *line)
2041 struct server *server = assuan_get_pointer (ctx);
2043 return gt_set_protocol (server->gt, gt_protocol_from_name (line));
2045 return gt_get_protocol (server->gt);
2050 cmd_sub_protocol (assuan_context_t ctx, char *line)
2052 struct server *server = assuan_get_pointer (ctx);
2054 return gt_set_sub_protocol (server->gt, gt_protocol_from_name (line));
2056 return gt_get_sub_protocol (server->gt);
2061 cmd_armor (assuan_context_t ctx, char *line)
2063 struct server *server = assuan_get_pointer (ctx);
2068 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2072 return gt_set_armor (server->gt, flag);
2075 return gt_get_armor (server->gt);
2080 cmd_textmode (assuan_context_t ctx, char *line)
2082 struct server *server = assuan_get_pointer (ctx);
2087 if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes")
2091 return gt_set_textmode (server->gt, flag);
2094 return gt_get_textmode (server->gt);
2099 cmd_include_certs (assuan_context_t ctx, char *line)
2101 struct server *server = assuan_get_pointer (ctx);
2105 int include_certs = 0;
2107 if (! strcasecmp (line, "default"))
2108 include_certs = GPGME_INCLUDE_CERTS_DEFAULT;
2110 include_certs = atoi (line);
2112 return gt_set_include_certs (server->gt, include_certs);
2115 return gt_get_include_certs (server->gt);
2120 cmd_keylist_mode (assuan_context_t ctx, char *line)
2122 struct server *server = assuan_get_pointer (ctx);
2126 gpgme_keylist_mode_t mode = 0;
2128 if (strstr (line, "local"))
2129 mode |= GPGME_KEYLIST_MODE_LOCAL;
2130 if (strstr (line, "extern"))
2131 mode |= GPGME_KEYLIST_MODE_EXTERN;
2132 if (strstr (line, "sigs"))
2133 mode |= GPGME_KEYLIST_MODE_SIGS;
2134 if (strstr (line, "sig_notations"))
2135 mode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS;
2136 if (strstr (line, "ephemeral"))
2137 mode |= GPGME_KEYLIST_MODE_EPHEMERAL;
2138 if (strstr (line, "validate"))
2139 mode |= GPGME_KEYLIST_MODE_VALIDATE;
2141 return gt_set_keylist_mode (server->gt, mode);
2144 return gt_get_keylist_mode (server->gt);
2149 cmd_input (assuan_context_t ctx, char *line)
2151 struct server *server = assuan_get_pointer (ctx);
2156 err = server_parse_fd (ctx, line, &sysfd, &filename);
2159 server->input_fd = sysfd;
2160 server->input_filename = filename;
2161 server->input_enc = server_data_encoding (line);
2167 cmd_output (assuan_context_t ctx, char *line)
2169 struct server *server = assuan_get_pointer (ctx);
2174 err = server_parse_fd (ctx, line, &sysfd, &filename);
2177 server->output_fd = sysfd;
2178 server->output_filename = filename;
2179 server->output_enc = server_data_encoding (line);
2185 cmd_message (assuan_context_t ctx, char *line)
2187 struct server *server = assuan_get_pointer (ctx);
2192 err = server_parse_fd (ctx, line, &sysfd, &filename);
2195 server->message_fd = sysfd;
2196 server->message_filename = filename;
2197 server->message_enc = server_data_encoding (line);
2203 cmd_recipient (assuan_context_t ctx, char *line)
2205 struct server *server = assuan_get_pointer (ctx);
2207 return gt_recipients_add (server->gt, line);
2212 cmd_signer (assuan_context_t ctx, char *line)
2214 struct server *server = assuan_get_pointer (ctx);
2216 return gt_signers_add (server->gt, line);
2221 cmd_signers_clear (assuan_context_t ctx, char *line)
2223 struct server *server = assuan_get_pointer (ctx);
2225 return gt_signers_clear (server->gt);
2230 _cmd_decrypt_verify (assuan_context_t ctx, char *line, int verify)
2232 struct server *server = assuan_get_pointer (ctx);
2238 gpgme_data_t inp_data;
2239 gpgme_data_t out_data;
2241 inp_fd = assuan_get_input_fd (ctx);
2242 inp_fn = server->input_filename;
2243 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2244 return GPG_ERR_ASS_NO_INPUT;
2245 out_fd = assuan_get_output_fd (ctx);
2246 out_fn = server->output_filename;
2247 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2248 return GPG_ERR_ASS_NO_OUTPUT;
2250 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2251 &server->input_stream);
2254 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2255 &server->output_stream);
2258 gpgme_data_release (inp_data);
2262 err = gt_decrypt_verify (server->gt, inp_data, out_data, verify);
2264 gpgme_data_release (inp_data);
2265 gpgme_data_release (out_data);
2267 server_reset_fds (server);
2274 cmd_decrypt (assuan_context_t ctx, char *line)
2276 return _cmd_decrypt_verify (ctx, line, 0);
2281 cmd_decrypt_verify (assuan_context_t ctx, char *line)
2283 return _cmd_decrypt_verify (ctx, line, 1);
2288 _cmd_sign_encrypt (assuan_context_t ctx, char *line, int sign)
2290 struct server *server = assuan_get_pointer (ctx);
2296 gpgme_data_t inp_data = NULL;
2297 gpgme_data_t out_data = NULL;
2298 gpgme_encrypt_flags_t flags = 0;
2300 if (strstr (line, "--always-trust"))
2301 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
2302 if (strstr (line, "--no-encrypt-to"))
2303 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
2304 if (strstr (line, "--prepare"))
2305 flags |= GPGME_ENCRYPT_PREPARE;
2306 if (strstr (line, "--expect-sign"))
2307 flags |= GPGME_ENCRYPT_EXPECT_SIGN;
2309 inp_fd = assuan_get_input_fd (ctx);
2310 inp_fn = server->input_filename;
2311 out_fd = assuan_get_output_fd (ctx);
2312 out_fn = server->output_filename;
2313 if (inp_fd != ASSUAN_INVALID_FD || inp_fn)
2315 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2316 &server->input_stream);
2320 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2322 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2323 &server->output_stream);
2326 gpgme_data_release (inp_data);
2331 err = gt_sign_encrypt (server->gt, flags, inp_data, out_data, sign);
2333 gpgme_data_release (inp_data);
2334 gpgme_data_release (out_data);
2336 server_reset_fds (server);
2343 cmd_encrypt (assuan_context_t ctx, char *line)
2345 return _cmd_sign_encrypt (ctx, line, 0);
2350 cmd_sign_encrypt (assuan_context_t ctx, char *line)
2352 return _cmd_sign_encrypt (ctx, line, 1);
2357 cmd_sign (assuan_context_t ctx, char *line)
2359 struct server *server = assuan_get_pointer (ctx);
2365 gpgme_data_t inp_data;
2366 gpgme_data_t out_data;
2367 gpgme_sig_mode_t mode = GPGME_SIG_MODE_NORMAL;
2369 if (strstr (line, "--clear"))
2370 mode = GPGME_SIG_MODE_CLEAR;
2371 if (strstr (line, "--detach"))
2372 mode = GPGME_SIG_MODE_DETACH;
2374 inp_fd = assuan_get_input_fd (ctx);
2375 inp_fn = server->input_filename;
2376 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2377 return GPG_ERR_ASS_NO_INPUT;
2378 out_fd = assuan_get_output_fd (ctx);
2379 out_fn = server->output_filename;
2380 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2381 return GPG_ERR_ASS_NO_OUTPUT;
2383 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2384 &server->input_stream);
2387 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2388 &server->output_stream);
2391 gpgme_data_release (inp_data);
2395 err = gt_sign (server->gt, inp_data, out_data, mode);
2397 gpgme_data_release (inp_data);
2398 gpgme_data_release (out_data);
2399 server_reset_fds (server);
2406 cmd_verify (assuan_context_t ctx, char *line)
2408 struct server *server = assuan_get_pointer (ctx);
2416 gpgme_data_t inp_data;
2417 gpgme_data_t msg_data = NULL;
2418 gpgme_data_t out_data = NULL;
2420 inp_fd = assuan_get_input_fd (ctx);
2421 inp_fn = server->input_filename;
2422 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2423 return GPG_ERR_ASS_NO_INPUT;
2424 msg_fd = server->message_fd;
2425 msg_fn = server->message_filename;
2426 out_fd = assuan_get_output_fd (ctx);
2427 out_fn = server->output_filename;
2429 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2430 &server->input_stream);
2433 if (msg_fd != ASSUAN_INVALID_FD || msg_fn)
2435 err = server_data_obj (msg_fd, msg_fn, 0, server->message_enc, &msg_data,
2436 &server->message_stream);
2439 gpgme_data_release (inp_data);
2443 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2445 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2446 &server->output_stream);
2449 gpgme_data_release (inp_data);
2450 gpgme_data_release (msg_data);
2455 err = gt_verify (server->gt, inp_data, msg_data, out_data);
2457 gpgme_data_release (inp_data);
2459 gpgme_data_release (msg_data);
2461 gpgme_data_release (out_data);
2463 server_reset_fds (server);
2470 cmd_import (assuan_context_t ctx, char *line)
2472 struct server *server = assuan_get_pointer (ctx);
2476 char *fprs[2] = { line, NULL };
2478 return gt_import_keys (server->gt, fprs);
2485 gpgme_data_t inp_data;
2487 inp_fd = assuan_get_input_fd (ctx);
2488 inp_fn = server->input_filename;
2489 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2490 return GPG_ERR_ASS_NO_INPUT;
2492 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2493 &server->input_stream);
2497 err = gt_import (server->gt, inp_data);
2499 gpgme_data_release (inp_data);
2500 server_reset_fds (server);
2507 static const char hlp_export[] =
2508 "EXPORT [--extern] [--minimal] [<pattern>]\n"
2510 "Export the keys described by PATTERN. Write the\n"
2511 "the output to the object set by the last OUTPUT command.";
2513 cmd_export (assuan_context_t ctx, char *line)
2515 struct server *server = assuan_get_pointer (ctx);
2519 gpgme_data_t out_data;
2520 gpgme_export_mode_t mode = 0;
2521 const char *pattern[2];
2523 out_fd = assuan_get_output_fd (ctx);
2524 out_fn = server->output_filename;
2525 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2526 return GPG_ERR_ASS_NO_OUTPUT;
2527 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2528 &server->output_stream);
2532 if (has_option (line, "--extern"))
2533 mode |= GPGME_EXPORT_MODE_EXTERN;
2534 if (has_option (line, "--minimal"))
2535 mode |= GPGME_EXPORT_MODE_MINIMAL;
2537 line = skip_options (line);
2542 err = gt_export (server->gt, pattern, mode, out_data);
2544 gpgme_data_release (out_data);
2545 server_reset_fds (server);
2552 _cmd_genkey_write (gpgme_data_t data, const void *buf, size_t size)
2556 ssize_t writen = gpgme_data_write (data, buf, size);
2557 if (writen < 0 && errno != EAGAIN)
2558 return gpg_error_from_syserror ();
2559 else if (writen > 0)
2561 buf = (void *) (((char *) buf) + writen);
2570 cmd_genkey (assuan_context_t ctx, char *line)
2572 struct server *server = assuan_get_pointer (ctx);
2578 gpgme_data_t inp_data;
2579 gpgme_data_t out_data = NULL;
2580 gpgme_data_t parms_data = NULL;
2583 inp_fd = assuan_get_input_fd (ctx);
2584 inp_fn = server->input_filename;
2585 if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
2586 return GPG_ERR_ASS_NO_INPUT;
2587 out_fd = assuan_get_output_fd (ctx);
2588 out_fn = server->output_filename;
2590 err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data,
2591 &server->input_stream);
2594 if (out_fd != ASSUAN_INVALID_FD || out_fn)
2596 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2597 &server->output_stream);
2600 gpgme_data_release (inp_data);
2605 /* Convert input data. */
2606 err = gpgme_data_new (&parms_data);
2612 ssize_t readn = gpgme_data_read (inp_data, buf, sizeof (buf));
2615 err = gpg_error_from_syserror ();
2618 else if (readn == 0)
2621 err = _cmd_genkey_write (parms_data, buf, readn);
2626 err = _cmd_genkey_write (parms_data, "", 1);
2629 parms = gpgme_data_release_and_get_mem (parms_data, NULL);
2633 err = gpg_error (GPG_ERR_GENERAL);
2637 err = gt_genkey (server->gt, parms, out_data, NULL);
2639 server_reset_fds (server);
2642 gpgme_data_release (inp_data);
2644 gpgme_data_release (out_data);
2646 gpgme_data_release (parms_data);
2653 cmd_delete (assuan_context_t ctx, char *line)
2655 struct server *server = assuan_get_pointer (ctx);
2656 int allow_secret = 0;
2657 const char optstr[] = "--allow-secret";
2659 if (!strncasecmp (line, optstr, strlen (optstr)))
2662 line += strlen (optstr);
2663 while (*line && !spacep (line))
2666 return gt_delete (server->gt, line, allow_secret);
2671 cmd_keylist (assuan_context_t ctx, char *line)
2673 struct server *server = assuan_get_pointer (ctx);
2675 int secret_only = 0;
2676 const char *pattern[2];
2677 const char optstr[] = "--secret-only";
2679 if (!strncasecmp (line, optstr, strlen (optstr)))
2682 line += strlen (optstr);
2683 while (*line && !spacep (line))
2689 err = gt_keylist_start (server->gt, pattern, secret_only);
2694 err = gt_keylist_next (server->gt, &key);
2695 if (gpg_err_code (err) == GPG_ERR_EOF)
2703 /* FIXME: More data. */
2704 snprintf (buf, sizeof (buf), "key:%s\n", key->subkeys->fpr);
2705 assuan_send_data (ctx, buf, strlen (buf));
2706 gpgme_key_unref (key);
2710 server_reset_fds (server);
2716 static const char hlp_getauditlog[] =
2717 "GETAUDITLOG [--html] [--with-help]\n"
2719 "Call the function gpgme_op_getauditlog with the given flags. Write\n"
2720 "the output to the object set by the last OUTPUT command.";
2722 cmd_getauditlog (assuan_context_t ctx, char *line)
2724 struct server *server = assuan_get_pointer (ctx);
2728 gpgme_data_t out_data;
2729 unsigned int flags = 0;
2731 out_fd = assuan_get_output_fd (ctx);
2732 out_fn = server->output_filename;
2733 if (out_fd == ASSUAN_INVALID_FD && !out_fn)
2734 return GPG_ERR_ASS_NO_OUTPUT;
2735 err = server_data_obj (out_fd, out_fn, 1, server->output_enc, &out_data,
2736 &server->output_stream);
2740 if (strstr (line, "--html"))
2741 flags |= GPGME_AUDITLOG_HTML;
2742 if (strstr (line, "--with-help"))
2743 flags |= GPGME_AUDITLOG_WITH_HELP;
2745 err = gt_getauditlog (server->gt, out_data, flags);
2747 gpgme_data_release (out_data);
2748 server_reset_fds (server);
2755 cmd_vfs_mount (assuan_context_t ctx, char *line)
2757 struct server *server = assuan_get_pointer (ctx);
2761 mount_dir = strchr (line, ' ');
2764 *(mount_dir++) = '\0';
2765 while (*mount_dir == ' ')
2769 err = gt_vfs_mount (server->gt, line, mount_dir, 0);
2776 cmd_vfs_create (assuan_context_t ctx, char *line)
2778 struct server *server = assuan_get_pointer (ctx);
2782 end = strchr (line, ' ');
2790 err = gt_vfs_create (server->gt, line, 0);
2797 cmd_passwd (assuan_context_t ctx, char *line)
2799 struct server *server = assuan_get_pointer (ctx);
2801 return gt_passwd (server->gt, line);
2807 cmd_result (assuan_context_t ctx, char *line)
2809 struct server *server = assuan_get_pointer (ctx);
2810 return gt_result (server->gt, GT_RESULT_ALL);
2814 /* STRERROR <err> */
2816 cmd_strerror (assuan_context_t ctx, char *line)
2822 snprintf (buf, sizeof (buf), "%s <%s>", gpgme_strerror (err),
2823 gpgme_strsource (err));
2824 return assuan_send_data (ctx, buf, strlen (buf));
2829 cmd_pubkey_algo_name (assuan_context_t ctx, char *line)
2831 gpgme_pubkey_algo_t algo;
2835 snprintf (buf, sizeof (buf), "%s", gpgme_pubkey_algo_name (algo));
2836 return assuan_send_data (ctx, buf, strlen (buf));
2841 cmd_hash_algo_name (assuan_context_t ctx, char *line)
2843 gpgme_hash_algo_t algo;
2847 snprintf (buf, sizeof (buf), "%s", gpgme_hash_algo_name (algo));
2848 return assuan_send_data (ctx, buf, strlen (buf));
2852 /* Tell the assuan library about our commands. */
2854 register_commands (assuan_context_t ctx)
2859 assuan_handler_t handler;
2860 const char * const help;
2862 /* RESET, BYE are implicit. */
2863 { "VERSION", cmd_version, hlp_version },
2864 /* TODO: Set engine info. */
2865 { "ENGINE", cmd_engine },
2866 { "PROTOCOL", cmd_protocol, hlp_protocol },
2867 { "SUB_PROTOCOL", cmd_sub_protocol },
2868 { "ARMOR", cmd_armor },
2869 { "TEXTMODE", cmd_textmode },
2870 { "INCLUDE_CERTS", cmd_include_certs },
2871 { "KEYLIST_MODE", cmd_keylist_mode },
2872 { "INPUT", cmd_input },
2873 { "OUTPUT", cmd_output },
2874 { "MESSAGE", cmd_message },
2875 { "RECIPIENT", cmd_recipient },
2876 { "SIGNER", cmd_signer },
2877 { "SIGNERS_CLEAR", cmd_signers_clear },
2878 /* TODO: SIGNOTATION missing. */
2879 /* TODO: Could add wait interface if we allow more than one context */
2880 /* and add _START variants. */
2881 /* TODO: Could add data interfaces if we allow multiple data objects. */
2882 { "DECRYPT", cmd_decrypt },
2883 { "DECRYPT_VERIFY", cmd_decrypt_verify },
2884 { "ENCRYPT", cmd_encrypt },
2885 { "ENCRYPT_SIGN", cmd_sign_encrypt },
2886 { "SIGN_ENCRYPT", cmd_sign_encrypt },
2887 { "SIGN", cmd_sign },
2888 { "VERIFY", cmd_verify },
2889 { "IMPORT", cmd_import },
2890 { "EXPORT", cmd_export, hlp_export },
2891 { "GENKEY", cmd_genkey },
2892 { "DELETE", cmd_delete },
2893 /* TODO: EDIT, CARD_EDIT (with INQUIRE) */
2894 { "KEYLIST", cmd_keylist },
2895 { "LISTKEYS", cmd_keylist },
2896 /* TODO: TRUSTLIST, TRUSTLIST_EXT */
2897 { "GETAUDITLOG", cmd_getauditlog, hlp_getauditlog },
2899 { "VFS_MOUNT", cmd_vfs_mount },
2900 { "MOUNT", cmd_vfs_mount },
2901 { "VFS_CREATE", cmd_vfs_create },
2902 { "CREATE", cmd_vfs_create },
2904 { "RESULT", cmd_result },
2905 { "STRERROR", cmd_strerror },
2906 { "PUBKEY_ALGO_NAME", cmd_pubkey_algo_name },
2907 { "HASH_ALGO_NAME", cmd_hash_algo_name },
2908 { "PASSWD", cmd_passwd, hlp_passwd },
2913 for (idx = 0; table[idx].name; idx++)
2915 err = assuan_register_command (ctx, table[idx].name, table[idx].handler,
2924 /* TODO: password callback can do INQUIRE. */
2926 gpgme_server (gpgme_tool_t gt)
2929 assuan_fd_t filedes[2];
2930 struct server server;
2931 static const char hello[] = ("GPGME-Tool " VERSION " ready");
2933 memset (&server, 0, sizeof (server));
2934 server.message_fd = ASSUAN_INVALID_FD;
2935 server.input_enc = GPGME_DATA_ENCODING_NONE;
2936 server.output_enc = GPGME_DATA_ENCODING_NONE;
2937 server.message_enc = GPGME_DATA_ENCODING_NONE;
2940 gt->write_status = server_write_status;
2941 gt->write_status_hook = &server;
2942 gt->write_data = server_write_data;
2943 gt->write_data_hook = &server;
2945 /* We use a pipe based server so that we can work from scripts.
2946 assuan_init_pipe_server will automagically detect when we are
2947 called with a socketpair and ignore FIELDES in this case. */
2948 #ifdef HAVE_W32CE_SYSTEM
2949 filedes[0] = ASSUAN_STDIN;
2950 filedes[1] = ASSUAN_STDOUT;
2952 filedes[0] = assuan_fdopen (0);
2953 filedes[1] = assuan_fdopen (1);
2955 err = assuan_new (&server.assuan_ctx);
2957 log_error (1, err, "can't create assuan context");
2959 assuan_set_pointer (server.assuan_ctx, &server);
2961 err = assuan_init_pipe_server (server.assuan_ctx, filedes);
2963 log_error (1, err, "can't initialize assuan server");
2964 err = register_commands (server.assuan_ctx);
2966 log_error (1, err, "can't register assuan commands");
2967 assuan_set_hello_line (server.assuan_ctx, hello);
2969 assuan_register_reset_notify (server.assuan_ctx, reset_notify);
2971 #define DBG_ASSUAN 0
2973 assuan_set_log_stream (server.assuan_ctx, log_stream);
2977 err = assuan_accept (server.assuan_ctx);
2982 log_error (0, err, "assuan accept problem");
2986 err = assuan_process (server.assuan_ctx);
2988 log_error (0, err, "assuan processing failed");
2991 assuan_release (server.assuan_ctx);
2996 /* MAIN PROGRAM STARTS HERE. */
2998 const char *argp_program_version = VERSION;
2999 const char *argp_program_bug_address = "bug-gpgme@gnupg.org";
3000 error_t argp_err_exit_status = 1;
3002 static char doc[] = "GPGME Tool -- invoke GPGME operations";
3003 static char args_doc[] = "COMMAND [OPTIONS...]";
3005 static struct argp_option options[] = {
3006 { "server", 's', 0, 0, "Server mode" },
3010 static error_t parse_options (int key, char *arg, struct argp_state *state);
3011 static struct argp argp = { options, parse_options, args_doc, doc };
3015 enum { CMD_DEFAULT, CMD_SERVER } cmd;
3019 args_init (struct args *args)
3021 memset (args, '\0', sizeof (*args));
3022 args->cmd = CMD_DEFAULT;
3027 parse_options (int key, char *arg, struct argp_state *state)
3029 struct args *args = state->input;
3034 args->cmd = CMD_SERVER;
3038 if (state->arg_num >= 2)
3040 printf ("Arg[%i] = %s\n", state->arg_num, arg);
3043 if (state->arg_num < 2)
3049 return ARGP_ERR_UNKNOWN;
3056 main (int argc, char *argv[])
3059 struct gpgme_tool gt;
3061 #ifdef HAVE_SETLOCALE
3062 setlocale (LC_ALL, "");
3064 gpgme_check_version (NULL);
3066 gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
3069 gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
3074 argp_parse (&argp, argc, argv, 0, 0, &args);
3087 gpgme_release (gt.ctx);
3089 #ifdef HAVE_W32CE_SYSTEM
3090 /* Give the buggy ssh server time to flush the output buffers. */