X-Git-Url: http://git.tremily.us/?a=blobdiff_plain;f=src%2Fgpgme-tool.c;h=3a02065733d5291330d452afb02c675dc644d5fa;hb=193eb62538b9413e0dfbd04c075f871d5aa9130b;hp=e424c381fb5c42812df2050fcc06c26114ce408b;hpb=de287a7996c85e6c6eb740f110df0f904d4cd867;p=gpgme.git diff --git a/src/gpgme-tool.c b/src/gpgme-tool.c index e424c38..3a02065 100644 --- a/src/gpgme-tool.c +++ b/src/gpgme-tool.c @@ -1,18 +1,18 @@ -/* gpgme-tool.c - GnuPG Made Easy. +/* gpgme-tool.c - Assuan server exposing GnuPG Made Easy operations. Copyright (C) 2009, 2010 g10 Code GmbH This file is part of GPGME. - + GPGME is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + GPGME is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, see . */ @@ -40,10 +40,10 @@ #include "gpgme.h" /* GCC attributes. */ -#if __GNUC__ >= 4 +#if __GNUC__ >= 4 # define GT_GCC_A_SENTINEL(a) __attribute__ ((sentinel(a))) #else -# define GT_GCC_A_SENTINEL(a) +# define GT_GCC_A_SENTINEL(a) #endif #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) @@ -158,9 +158,9 @@ struct argp | ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR) -void argp_error (const struct argp_state *state, +void argp_error (const struct argp_state *state, const char *fmt, ...) GT_GCC_A_PRINTF(2, 3); - + char * @@ -374,10 +374,10 @@ argp_parse (const struct argp *argp, int argc, *arg = '\0'; arg++; } - + if (state.argv[idx][1] != '-') key = state.argv[idx][1]; - + while (! found && opt->key) { if (key == opt->key @@ -453,7 +453,7 @@ argp_parse (const struct argp *argp, int argc, rc = argp->parser (ARGP_KEY_FINI, NULL, &state); if (rc && rc != ARGP_ERR_UNKNOWN) goto argperror; - + rc = 0; argp->parser (ARGP_KEY_SUCCESS, NULL, &state); @@ -481,7 +481,7 @@ char *program_name = "gpgme-tool"; #define spacep(p) (*(p) == ' ' || *(p) == '\t') -void log_error (int status, gpg_error_t errnum, +void log_error (int status, gpg_error_t errnum, const char *fmt, ...) GT_GCC_A_PRINTF(3,4); @@ -518,7 +518,7 @@ strcpy_escaped_plus (char *d, const char *s) while (*s) { if (*s == '%' && s[1] && s[2]) - { + { s++; *d++ = xtoi_2 (s); s += 2; @@ -528,7 +528,7 @@ strcpy_escaped_plus (char *d, const char *s) else *d++ = *s++; } - *d = 0; + *d = 0; } @@ -630,7 +630,7 @@ result_xml_tag_start (struct result_xml_state *state, char *name, ...) state->had_data[state->next_tag] = 0; state->indent += 2; state->next_tag++; - + while (1) { attr = va_arg (ap, char *); @@ -704,7 +704,7 @@ result_xml_tag_end (struct result_xml_state *state) gpg_error_t result_add_error (struct result_xml_state *state, char *name, gpg_error_t err) -{ +{ char code[20]; char msg[1024]; snprintf (code, sizeof (code) - 1, "0x%x", err); @@ -720,7 +720,7 @@ result_add_error (struct result_xml_state *state, char *name, gpg_error_t err) gpg_error_t result_add_pubkey_algo (struct result_xml_state *state, char *name, gpgme_pubkey_algo_t algo) -{ +{ char code[20]; char msg[80]; snprintf (code, sizeof (code) - 1, "0x%x", algo); @@ -736,7 +736,7 @@ result_add_pubkey_algo (struct result_xml_state *state, gpg_error_t result_add_hash_algo (struct result_xml_state *state, char *name, gpgme_hash_algo_t algo) -{ +{ char code[20]; char msg[80]; snprintf (code, sizeof (code) - 1, "0x%x", algo); @@ -751,7 +751,7 @@ result_add_hash_algo (struct result_xml_state *state, gpg_error_t result_add_keyid (struct result_xml_state *state, char *name, char *keyid) -{ +{ result_xml_tag_start (state, name, NULL); result_xml_tag_data (state, keyid); result_xml_tag_end (state); @@ -761,7 +761,7 @@ result_add_keyid (struct result_xml_state *state, char *name, char *keyid) gpg_error_t result_add_fpr (struct result_xml_state *state, char *name, char *fpr) -{ +{ result_xml_tag_start (state, name, NULL); result_xml_tag_data (state, fpr); result_xml_tag_end (state); @@ -785,7 +785,7 @@ result_add_timestamp (struct result_xml_state *state, char *name, gpg_error_t result_add_sig_mode (struct result_xml_state *state, char *name, gpgme_sig_mode_t sig_mode) -{ +{ char *mode; char code[20]; @@ -815,7 +815,7 @@ result_add_sig_mode (struct result_xml_state *state, char *name, gpg_error_t result_add_value (struct result_xml_state *state, char *name, unsigned int val) -{ +{ char code[20]; snprintf (code, sizeof (code) - 1, "0x%x", val); @@ -828,7 +828,7 @@ result_add_value (struct result_xml_state *state, gpg_error_t result_add_string (struct result_xml_state *state, char *name, char *str) -{ +{ result_xml_tag_start (state, name, NULL); result_xml_tag_data (state, str); result_xml_tag_end (state); @@ -854,7 +854,7 @@ result_encrypt_to_xml (gpgme_ctx_t ctx, int indent, if (inv_recp) { result_xml_tag_start (&state, "invalid-recipients", NULL); - + while (inv_recp) { result_xml_tag_start (&state, "invalid-key", NULL); @@ -867,7 +867,7 @@ result_encrypt_to_xml (gpgme_ctx_t ctx, int indent, result_xml_tag_end (&state); } result_xml_tag_end (&state); - + return 0; } @@ -920,7 +920,7 @@ result_decrypt_to_xml (gpgme_ctx_t ctx, int indent, result_xml_tag_end (&state); } result_xml_tag_end (&state); - + return 0; } @@ -944,7 +944,7 @@ result_sign_to_xml (gpgme_ctx_t ctx, int indent, if (inv_key) { result_xml_tag_start (&state, "invalid-signers", NULL); - + while (inv_key) { result_xml_tag_start (&state, "invalid-key", NULL); @@ -980,7 +980,7 @@ result_sign_to_xml (gpgme_ctx_t ctx, int indent, } result_xml_tag_end (&state); - + return 0; } @@ -1014,7 +1014,7 @@ result_verify_to_xml (gpgme_ctx_t ctx, int indent, while (sig) { result_xml_tag_start (&state, "signature", NULL); - + /* FIXME: Could be done better. */ result_add_value (&state, "summary", sig->summary); if (sig->fpr) @@ -1032,7 +1032,7 @@ result_verify_to_xml (gpgme_ctx_t ctx, int indent, result_add_hash_algo (&state, "hash-algo", sig->hash_algo); if (sig->pka_address) result_add_string (&state, "pka_address", sig->pka_address); - + result_xml_tag_end (&state); sig = sig->next; } @@ -1040,7 +1040,7 @@ result_verify_to_xml (gpgme_ctx_t ctx, int indent, } result_xml_tag_end (&state); - + return 0; } @@ -1078,7 +1078,7 @@ result_import_to_xml (gpgme_ctx_t ctx, int indent, if (stat) { result_xml_tag_start (&state, "imports", NULL); - + while (stat) { result_xml_tag_start (&state, "import-status", NULL); @@ -1096,7 +1096,7 @@ result_import_to_xml (gpgme_ctx_t ctx, int indent, } result_xml_tag_end (&state); - + return 0; } @@ -1120,7 +1120,7 @@ result_genkey_to_xml (gpgme_ctx_t ctx, int indent, result_add_fpr (&state, "fpr", res->fpr); result_xml_tag_end (&state); - + return 0; } @@ -1141,7 +1141,7 @@ result_keylist_to_xml (gpgme_ctx_t ctx, int indent, result_add_value (&state, "truncated", res->truncated); result_xml_tag_end (&state); - + return 0; } @@ -1162,7 +1162,7 @@ result_vfs_mount_to_xml (gpgme_ctx_t ctx, int indent, result_add_string (&state, "mount-dir", res->mount_dir); result_xml_tag_end (&state); - + return 0; } @@ -1209,7 +1209,7 @@ typedef struct gpgme_tool *gpgme_tool_t; /* Forward declaration. */ -void gt_write_status (gpgme_tool_t gt, +void gt_write_status (gpgme_tool_t gt, status_t status, ...) GT_GCC_A_SENTINEL(0); void @@ -1281,7 +1281,7 @@ gt_get_key (gpgme_tool_t gt, const char *pattern, gpgme_key_t *r_key) if (!gt || !r_key || !pattern) return gpg_error (GPG_ERR_INV_VALUE); - + ctx = gt->ctx; err = gpgme_new (&listctx); @@ -1343,10 +1343,10 @@ gt_get_key (gpgme_tool_t gt, const char *pattern, gpgme_key_t *r_key) } } gpgme_release (listctx); - + if (! err) - gt_write_status (gt, STATUS_RECIPIENT, - ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ? + gt_write_status (gt, STATUS_RECIPIENT, + ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ? (*r_key)->subkeys->fpr : "invalid", NULL); return err; } @@ -1390,7 +1390,7 @@ gt_reset (gpgme_tool_t gt) { gpg_error_t err; gpgme_ctx_t ctx; - + err = _gt_gpgme_new (gt, &ctx); if (err) return err; @@ -1482,7 +1482,7 @@ gt_protocol_from_name (const char *name) return GPGME_PROTOCOL_UNKNOWN; } - + gpg_error_t gt_set_protocol (gpgme_tool_t gt, gpgme_protocol_t proto) { @@ -1572,7 +1572,7 @@ gt_get_keylist_mode (gpgme_tool_t gt) const char *modes[NR_KEYLIST_MODES + 1]; int idx = 0; gpgme_keylist_mode_t mode = gpgme_get_keylist_mode (gt->ctx); - + if (mode & GPGME_KEYLIST_MODE_LOCAL) modes[idx++] = "local"; if (mode & GPGME_KEYLIST_MODE_EXTERN) @@ -1693,18 +1693,18 @@ gt_import_keys (gpgme_tool_t gt, char *fpr[]) int cnt; int idx; gpgme_key_t *keys; - + cnt = 0; while (fpr[cnt]) cnt++; - + if (! cnt) return gpg_error (GPG_ERR_INV_VALUE); keys = malloc ((cnt + 1) * sizeof (gpgme_key_t)); if (! keys) return gpg_error_from_syserror (); - + for (idx = 0; idx < cnt; idx++) { err = gpgme_get_key (gt->ctx, fpr[idx], &keys[idx], 0); @@ -1716,7 +1716,7 @@ gt_import_keys (gpgme_tool_t gt, char *fpr[]) keys[cnt] = NULL; err = gpgme_op_import_keys (gt->ctx, keys); } - + /* Rollback. */ while (--idx >= 0) gpgme_key_unref (keys[idx]); @@ -1786,7 +1786,7 @@ gt_vfs_create (gpgme_tool_t gt, const char *container_file, int flags) } -static const char hlp_passwd[] = +static const char hlp_passwd[] = "PASSWD \n" "\n" "Ask the backend to change the passphrase for the key\n" @@ -1900,7 +1900,10 @@ server_write_data (void *hook, const void *buf, size_t len) } - +/* Wrapper around assuan_command_parse_fd to also handle a + "file=FILENAME" argument. On success either a filename is returned + at FILENAME or a file descriptor at RFD; the other one is set to + NULL respective ASSUAN_INVALID_FD. */ static gpg_error_t server_parse_fd (assuan_context_t ctx, char *line, assuan_fd_t *rfd, char **filename) @@ -1922,7 +1925,7 @@ server_parse_fd (assuan_context_t ctx, char *line, assuan_fd_t *rfd, else return assuan_command_parse_fd (ctx, line, rfd); } - + static gpgme_data_encoding_t server_data_encoding (const char *line) @@ -1974,8 +1977,24 @@ server_reset_fds (struct server *server) /* assuan closes the input and output FDs for us when doing a RESET, but we use this same function after commands, so repeat it here. */ - assuan_close_input_fd (server->assuan_ctx); - assuan_close_output_fd (server->assuan_ctx); + if (server->input_fd != ASSUAN_INVALID_FD) + { +#if HAVE_W32_SYSTEM + CloseHandle (server->input_fd); +#else + close (server->input_fd); +#endif + server->input_fd = ASSUAN_INVALID_FD; + } + if (server->output_fd != ASSUAN_INVALID_FD) + { +#if HAVE_W32_SYSTEM + CloseHandle (server->output_fd); +#else + close (server->output_fd); +#endif + server->output_fd = ASSUAN_INVALID_FD; + } if (server->message_fd != ASSUAN_INVALID_FD) { /* FIXME: Assuan should provide a close function. */ @@ -2033,7 +2052,7 @@ reset_notify (assuan_context_t ctx, char *line) } -static const char hlp_version[] = +static const char hlp_version[] = "VERSION []\n" "\n" "Call the function gpgme_check_version."; @@ -2053,6 +2072,10 @@ cmd_version (assuan_context_t ctx, char *line) } +static const char hlp_engine[] = + "ENGINE []\n" + "\n" + "Get information about a GPGME engine (a.k.a. protocol)."; static gpg_error_t cmd_engine (assuan_context_t ctx, char *line) { @@ -2061,10 +2084,11 @@ cmd_engine (assuan_context_t ctx, char *line) } -static const char hlp_protocol[] = +static const char hlp_protocol[] = "PROTOCOL []\n" "\n" - "With NAME, set the protocol. Without return the current protocol."; + "With NAME, set the protocol. Without, return the current\n" + "protocol."; static gpg_error_t cmd_protocol (assuan_context_t ctx, char *line) { @@ -2076,6 +2100,11 @@ cmd_protocol (assuan_context_t ctx, char *line) } +static const char hlp_sub_protocol[] = + "SUB_PROTOCOL []\n" + "\n" + "With NAME, set the sub-protocol. Without, return the\n" + "current sub-protocol."; static gpg_error_t cmd_sub_protocol (assuan_context_t ctx, char *line) { @@ -2087,6 +2116,11 @@ cmd_sub_protocol (assuan_context_t ctx, char *line) } +static const char hlp_armor[] = + "ARMOR [true|false]\n" + "\n" + "With 'true' or 'false', turn output ASCII armoring on or\n" + "off. Without, return the current armoring status."; static gpg_error_t cmd_armor (assuan_context_t ctx, char *line) { @@ -2094,11 +2128,11 @@ cmd_armor (assuan_context_t ctx, char *line) if (line && *line) { int flag = 0; - + if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes") || line[0] == '1') flag = 1; - + return gt_set_armor (server->gt, flag); } else @@ -2106,6 +2140,11 @@ cmd_armor (assuan_context_t ctx, char *line) } +static const char hlp_textmode[] = + "TEXTMODE [true|false]\n" + "\n" + "With 'true' or 'false', turn text mode on or off.\n" + "Without, return the current text mode status."; static gpg_error_t cmd_textmode (assuan_context_t ctx, char *line) { @@ -2117,7 +2156,7 @@ cmd_textmode (assuan_context_t ctx, char *line) if (! strcasecmp (line, "true") || ! strcasecmp (line, "yes") || line[0] == '1') flag = 1; - + return gt_set_textmode (server->gt, flag); } else @@ -2125,6 +2164,13 @@ cmd_textmode (assuan_context_t ctx, char *line) } +static const char hlp_include_certs[] = + "INCLUDE_CERTS [default|]\n" + "\n" + "With DEFAULT or N, set how many certificates should be\n" + "included in the next S/MIME signed message. See the\n" + "GPGME documentation for details on the meaning of" + "various N. Without either, return the current setting."; static gpg_error_t cmd_include_certs (assuan_context_t ctx, char *line) { @@ -2133,12 +2179,12 @@ cmd_include_certs (assuan_context_t ctx, char *line) if (line && *line) { int include_certs = 0; - + if (! strcasecmp (line, "default")) include_certs = GPGME_INCLUDE_CERTS_DEFAULT; else include_certs = atoi (line); - + return gt_set_include_certs (server->gt, include_certs); } else @@ -2146,6 +2192,11 @@ cmd_include_certs (assuan_context_t ctx, char *line) } +static const char hlp_keylist_mode[] = + "KEYLIST_MODE [local] [extern] [sigs] [sig_notations]\n" + " [ephemeral] [validate]\n" + "\n" + "Set the mode for the next KEYLIST command."; static gpg_error_t cmd_keylist_mode (assuan_context_t ctx, char *line) { @@ -2154,7 +2205,7 @@ cmd_keylist_mode (assuan_context_t ctx, char *line) if (line && *line) { gpgme_keylist_mode_t mode = 0; - + if (strstr (line, "local")) mode |= GPGME_KEYLIST_MODE_LOCAL; if (strstr (line, "extern")) @@ -2167,7 +2218,7 @@ cmd_keylist_mode (assuan_context_t ctx, char *line) mode |= GPGME_KEYLIST_MODE_EPHEMERAL; if (strstr (line, "validate")) mode |= GPGME_KEYLIST_MODE_VALIDATE; - + return gt_set_keylist_mode (server->gt, mode); } else @@ -2175,6 +2226,11 @@ cmd_keylist_mode (assuan_context_t ctx, char *line) } +static const char hlp_input[] = + "INPUT [|FILE=]\n" + "\n" + "Set the input for the next command. Use either the\n" + "Assuan file descriptor FD or a filesystem PATH."; static gpg_error_t cmd_input (assuan_context_t ctx, char *line) { @@ -2193,6 +2249,11 @@ cmd_input (assuan_context_t ctx, char *line) } +static const char hlp_output[] = + "OUTPUT [|FILE=]\n" + "\n" + "Set the output for the next command. Use either the\n" + "Assuan file descriptor FD or a filesystem PATH."; static gpg_error_t cmd_output (assuan_context_t ctx, char *line) { @@ -2211,6 +2272,12 @@ cmd_output (assuan_context_t ctx, char *line) } +static const char hlp_message[] = + "MESSAGE [|FILE=]\n" + "\n" + "Set the plaintext message for the next VERIFY command\n" + "with a detached signature. Use either the Assuan file\n" + "descriptor FD or a filesystem PATH."; static gpg_error_t cmd_message (assuan_context_t ctx, char *line) { @@ -2229,6 +2296,11 @@ cmd_message (assuan_context_t ctx, char *line) } +static const char hlp_recipient[] = + "RECIPIENT \n" + "\n" + "Add the key matching PATTERN to the list of recipients\n" + "for the next encryption command."; static gpg_error_t cmd_recipient (assuan_context_t ctx, char *line) { @@ -2238,6 +2310,11 @@ cmd_recipient (assuan_context_t ctx, char *line) } +static const char hlp_signer[] = + "SIGNER \n" + "\n" + "Add the key with FINGERPRINT to the list of signers to\n" + "be used for the next signing command."; static gpg_error_t cmd_signer (assuan_context_t ctx, char *line) { @@ -2247,6 +2324,11 @@ cmd_signer (assuan_context_t ctx, char *line) } +static const char hlp_signers_clear[] = + "SIGNERS_CLEAR\n" + "\n" + "Clear the list of signers specified by previous SIGNER\n" + "commands."; static gpg_error_t cmd_signers_clear (assuan_context_t ctx, char *line) { @@ -2268,15 +2350,15 @@ _cmd_decrypt_verify (assuan_context_t ctx, char *line, int verify) gpgme_data_t inp_data; gpgme_data_t out_data; - inp_fd = assuan_get_input_fd (ctx); + inp_fd = server->input_fd; inp_fn = server->input_filename; if (inp_fd == ASSUAN_INVALID_FD && !inp_fn) return GPG_ERR_ASS_NO_INPUT; - out_fd = assuan_get_output_fd (ctx); + out_fd = server->output_fd; out_fn = server->output_filename; if (out_fd == ASSUAN_INVALID_FD && !out_fn) return GPG_ERR_ASS_NO_OUTPUT; - + err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data, &server->input_stream); if (err) @@ -2289,7 +2371,7 @@ _cmd_decrypt_verify (assuan_context_t ctx, char *line, int verify) return err; } - err = gt_decrypt_verify (server->gt, inp_data, out_data, verify); + err = gt_decrypt_verify (server->gt, inp_data, out_data, verify); gpgme_data_release (inp_data); gpgme_data_release (out_data); @@ -2300,6 +2382,12 @@ _cmd_decrypt_verify (assuan_context_t ctx, char *line, int verify) } +static const char hlp_decrypt[] = + "DECRYPT\n" + "\n" + "Decrypt the object set by the last INPUT command and\n" + "write the decrypted message to the object set by the\n" + "last OUTPUT command."; static gpg_error_t cmd_decrypt (assuan_context_t ctx, char *line) { @@ -2307,6 +2395,12 @@ cmd_decrypt (assuan_context_t ctx, char *line) } +static const char hlp_decrypt_verify[] = + "DECRYPT_VERIFY\n" + "\n" + "Decrypt the object set by the last INPUT command and\n" + "verify any embedded signatures. Write the decrypted\n" + "message to the object set by the last OUTPUT command."; static gpg_error_t cmd_decrypt_verify (assuan_context_t ctx, char *line) { @@ -2335,10 +2429,10 @@ _cmd_sign_encrypt (assuan_context_t ctx, char *line, int sign) flags |= GPGME_ENCRYPT_PREPARE; if (strstr (line, "--expect-sign")) flags |= GPGME_ENCRYPT_EXPECT_SIGN; - - inp_fd = assuan_get_input_fd (ctx); + + inp_fd = server->input_fd; inp_fn = server->input_filename; - out_fd = assuan_get_output_fd (ctx); + out_fd = server->output_fd; out_fn = server->output_filename; if (inp_fd != ASSUAN_INVALID_FD || inp_fn) { @@ -2358,7 +2452,7 @@ _cmd_sign_encrypt (assuan_context_t ctx, char *line, int sign) } } - err = gt_sign_encrypt (server->gt, flags, inp_data, out_data, sign); + err = gt_sign_encrypt (server->gt, flags, inp_data, out_data, sign); gpgme_data_release (inp_data); gpgme_data_release (out_data); @@ -2369,6 +2463,14 @@ _cmd_sign_encrypt (assuan_context_t ctx, char *line, int sign) } +static const char hlp_encrypt[] = + "ENCRYPT [--always-trust] [--no-encrypt-to]\n" + " [--prepare] [--expect-sign]\n" + "\n" + "Encrypt the object set by the last INPUT command to\n" + "the keys specified by previous RECIPIENT commands. \n" + "Write the signed and encrypted message to the object\n" + "set by the last OUTPUT command."; static gpg_error_t cmd_encrypt (assuan_context_t ctx, char *line) { @@ -2376,6 +2478,15 @@ cmd_encrypt (assuan_context_t ctx, char *line) } +static const char hlp_sign_encrypt[] = + "SIGN_ENCRYPT [--always-trust] [--no-encrypt-to]\n" + " [--prepare] [--expect-sign]\n" + "\n" + "Sign the object set by the last INPUT command with the\n" + "keys specified by previous SIGNER commands and encrypt\n" + "it to the keys specified by previous RECIPIENT\n" + "commands. Write the signed and encrypted message to\n" + "the object set by the last OUTPUT command."; static gpg_error_t cmd_sign_encrypt (assuan_context_t ctx, char *line) { @@ -2383,6 +2494,15 @@ cmd_sign_encrypt (assuan_context_t ctx, char *line) } +static const char hlp_sign[] = + "SIGN [--clear|--detach]\n" + "\n" + "Sign the object set by the last INPUT command with the\n" + "keys specified by previous SIGNER commands. Write the\n" + "signed message to the object set by the last OUTPUT\n" + "command. With `--clear`, generate a clear text\n" + "signature. With `--detach`, generate a detached\n" + "signature."; static gpg_error_t cmd_sign (assuan_context_t ctx, char *line) { @@ -2401,15 +2521,15 @@ cmd_sign (assuan_context_t ctx, char *line) if (strstr (line, "--detach")) mode = GPGME_SIG_MODE_DETACH; - inp_fd = assuan_get_input_fd (ctx); + inp_fd = server->input_fd; inp_fn = server->input_filename; if (inp_fd == ASSUAN_INVALID_FD && !inp_fn) return GPG_ERR_ASS_NO_INPUT; - out_fd = assuan_get_output_fd (ctx); + out_fd = server->output_fd; out_fn = server->output_filename; if (out_fd == ASSUAN_INVALID_FD && !out_fn) return GPG_ERR_ASS_NO_OUTPUT; - + err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data, &server->input_stream); if (err) @@ -2432,6 +2552,13 @@ cmd_sign (assuan_context_t ctx, char *line) } +static const char hlp_verify[] = + "VERIFY\n" + "\n" + "Verify signatures on the object set by the last INPUT\n" + "and MESSAGE commands. If the message was encrypted,\n" + "write the plaintext to the object set by the last\n" + "OUTPUT command."; static gpg_error_t cmd_verify (assuan_context_t ctx, char *line) { @@ -2447,13 +2574,13 @@ cmd_verify (assuan_context_t ctx, char *line) gpgme_data_t msg_data = NULL; gpgme_data_t out_data = NULL; - inp_fd = assuan_get_input_fd (ctx); + inp_fd = server->input_fd; inp_fn = server->input_filename; if (inp_fd == ASSUAN_INVALID_FD && !inp_fn) return GPG_ERR_ASS_NO_INPUT; msg_fd = server->message_fd; msg_fn = server->message_filename; - out_fd = assuan_get_output_fd (ctx); + out_fd = server->output_fd; out_fn = server->output_filename; err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data, @@ -2496,11 +2623,17 @@ cmd_verify (assuan_context_t ctx, char *line) } +static const char hlp_import[] = + "IMPORT []\n" + "\n" + "With PATTERN, import the keys described by PATTERN.\n" + "Without, read a key (or keys) from the object set by the\n" + "last INPUT command."; static gpg_error_t cmd_import (assuan_context_t ctx, char *line) { struct server *server = assuan_get_pointer (ctx); - + if (line && *line) { char *fprs[2] = { line, NULL }; @@ -2513,8 +2646,8 @@ cmd_import (assuan_context_t ctx, char *line) assuan_fd_t inp_fd; char *inp_fn; gpgme_data_t inp_data; - - inp_fd = assuan_get_input_fd (ctx); + + inp_fd = server->input_fd; inp_fn = server->input_filename; if (inp_fd == ASSUAN_INVALID_FD && !inp_fn) return GPG_ERR_ASS_NO_INPUT; @@ -2523,9 +2656,9 @@ cmd_import (assuan_context_t ctx, char *line) &server->input_stream); if (err) return err; - - err = gt_import (server->gt, inp_data); - + + err = gt_import (server->gt, inp_data); + gpgme_data_release (inp_data); server_reset_fds (server); @@ -2534,7 +2667,7 @@ cmd_import (assuan_context_t ctx, char *line) } -static const char hlp_export[] = +static const char hlp_export[] = "EXPORT [--extern] [--minimal] []\n" "\n" "Export the keys described by PATTERN. Write the\n" @@ -2550,7 +2683,7 @@ cmd_export (assuan_context_t ctx, char *line) gpgme_export_mode_t mode = 0; const char *pattern[2]; - out_fd = assuan_get_output_fd (ctx); + out_fd = server->output_fd; out_fn = server->output_filename; if (out_fd == ASSUAN_INVALID_FD && !out_fn) return GPG_ERR_ASS_NO_OUTPUT; @@ -2610,13 +2743,13 @@ cmd_genkey (assuan_context_t ctx, char *line) gpgme_data_t parms_data = NULL; const char *parms; - inp_fd = assuan_get_input_fd (ctx); + inp_fd = server->input_fd; inp_fn = server->input_filename; if (inp_fd == ASSUAN_INVALID_FD && !inp_fn) return GPG_ERR_ASS_NO_INPUT; - out_fd = assuan_get_output_fd (ctx); + out_fd = server->output_fd; out_fn = server->output_filename; - + err = server_data_obj (inp_fd, inp_fn, 0, server->input_enc, &inp_data, &server->input_stream); if (err) @@ -2675,7 +2808,7 @@ cmd_genkey (assuan_context_t ctx, char *line) if (parms_data) gpgme_data_release (parms_data); - return err; + return err; } @@ -2697,7 +2830,7 @@ cmd_delete (assuan_context_t ctx, char *line) } -static const char hlp_keylist[] = +static const char hlp_keylist[] = "KEYLIST [--secret-only] []\n" "\n" "List all certificates or only those specified by PATTERNS. Each\n" @@ -2763,14 +2896,14 @@ cmd_keylist (assuan_context_t ctx, char *line) gpgme_key_unref (key); } } - + server_reset_fds (server); return err; } -static const char hlp_getauditlog[] = +static const char hlp_getauditlog[] = "GETAUDITLOG [--html] [--with-help]\n" "\n" "Call the function gpgme_op_getauditlog with the given flags. Write\n" @@ -2785,7 +2918,7 @@ cmd_getauditlog (assuan_context_t ctx, char *line) gpgme_data_t out_data; unsigned int flags = 0; - out_fd = assuan_get_output_fd (ctx); + out_fd = server->output_fd; out_fn = server->output_filename; if (out_fd == ASSUAN_INVALID_FD && !out_fn) return GPG_ERR_ASS_NO_OUTPUT; @@ -2919,31 +3052,31 @@ register_commands (assuan_context_t ctx) /* RESET, BYE are implicit. */ { "VERSION", cmd_version, hlp_version }, /* TODO: Set engine info. */ - { "ENGINE", cmd_engine }, + { "ENGINE", cmd_engine, hlp_engine }, { "PROTOCOL", cmd_protocol, hlp_protocol }, - { "SUB_PROTOCOL", cmd_sub_protocol }, - { "ARMOR", cmd_armor }, - { "TEXTMODE", cmd_textmode }, - { "INCLUDE_CERTS", cmd_include_certs }, - { "KEYLIST_MODE", cmd_keylist_mode }, - { "INPUT", cmd_input }, - { "OUTPUT", cmd_output }, - { "MESSAGE", cmd_message }, - { "RECIPIENT", cmd_recipient }, - { "SIGNER", cmd_signer }, - { "SIGNERS_CLEAR", cmd_signers_clear }, + { "SUB_PROTOCOL", cmd_sub_protocol, hlp_sub_protocol }, + { "ARMOR", cmd_armor, hlp_armor }, + { "TEXTMODE", cmd_textmode, hlp_textmode }, + { "INCLUDE_CERTS", cmd_include_certs, hlp_include_certs }, + { "KEYLIST_MODE", cmd_keylist_mode, hlp_keylist_mode }, + { "INPUT", cmd_input, hlp_input }, + { "OUTPUT", cmd_output, hlp_output }, + { "MESSAGE", cmd_message, hlp_message }, + { "RECIPIENT", cmd_recipient, hlp_recipient }, + { "SIGNER", cmd_signer, hlp_signer }, + { "SIGNERS_CLEAR", cmd_signers_clear, hlp_signers_clear }, /* TODO: SIGNOTATION missing. */ /* TODO: Could add wait interface if we allow more than one context */ /* and add _START variants. */ /* TODO: Could add data interfaces if we allow multiple data objects. */ - { "DECRYPT", cmd_decrypt }, - { "DECRYPT_VERIFY", cmd_decrypt_verify }, - { "ENCRYPT", cmd_encrypt }, - { "ENCRYPT_SIGN", cmd_sign_encrypt }, - { "SIGN_ENCRYPT", cmd_sign_encrypt }, - { "SIGN", cmd_sign }, - { "VERIFY", cmd_verify }, - { "IMPORT", cmd_import }, + { "DECRYPT", cmd_decrypt, hlp_decrypt }, + { "DECRYPT_VERIFY", cmd_decrypt_verify, hlp_decrypt_verify }, + { "ENCRYPT", cmd_encrypt, hlp_encrypt }, + { "ENCRYPT_SIGN", cmd_sign_encrypt, hlp_sign_encrypt }, + { "SIGN_ENCRYPT", cmd_sign_encrypt, hlp_sign_encrypt }, + { "SIGN", cmd_sign, hlp_sign }, + { "VERIFY", cmd_verify, hlp_verify }, + { "IMPORT", cmd_import, hlp_import }, { "EXPORT", cmd_export, hlp_export }, { "GENKEY", cmd_genkey }, { "DELETE", cmd_delete }, @@ -2973,7 +3106,7 @@ register_commands (assuan_context_t ctx) table[idx].help); if (err) return err; - } + } return 0; } @@ -3039,7 +3172,7 @@ gpgme_server (gpgme_tool_t gt) log_error (0, err, "assuan accept problem"); break; } - + err = assuan_process (server.assuan_ctx); if (err) log_error (0, err, "assuan processing failed"); @@ -3056,7 +3189,7 @@ const char *argp_program_version = VERSION; const char *argp_program_bug_address = "bug-gpgme@gnupg.org"; error_t argp_err_exit_status = 1; -static char doc[] = "GPGME Tool -- invoke GPGME operations"; +static char doc[] = "GPGME Tool -- Assuan server exposing GPGME operations"; static char args_doc[] = "COMMAND [OPTIONS...]"; static struct argp_option options[] = {