2003-05-18 Marcus Brinkmann <marcus@g10code.de>
[gpgme.git] / gpgme / edit.c
1 /* edit.c - Key edit function.
2    Copyright (C) 2002, 2003 g10 Code GmbH
3
4    This file is part of GPGME.
5  
6    GPGME is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10  
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    General Public License for more details.
15  
16    You should have received a copy of the GNU General Public License
17    along with GPGME; if not, write to the Free Software Foundation,
18    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 #if HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 #include <stdlib.h>
24
25 #include "gpgme.h"
26 #include "context.h"
27 #include "ops.h"
28
29 \f
30 typedef struct
31 {
32   /* The user callback function and its hook value.  */
33   gpgme_edit_cb_t fnc;
34   void *fnc_value;
35 } *op_data_t;
36
37 \f
38 static gpgme_error_t
39 edit_status_handler (void *priv, gpgme_status_code_t status, char *args)
40 {
41   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
42   op_data_t opd;
43
44   return _gpgme_passphrase_status_handler (priv, status, args)
45     || _gpgme_progress_status_handler (priv, status, args)
46     || _gpgme_op_data_lookup (ctx, OPDATA_EDIT, (void **) &opd, -1, NULL)
47     || (*opd->fnc) (opd->fnc_value, status, args, NULL);
48 }
49
50
51 static gpgme_error_t
52 command_handler (void *priv, gpgme_status_code_t status, const char *args,
53                  const char **result)
54 {
55   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
56   gpgme_error_t err;
57   op_data_t opd;
58
59   *result = NULL;
60   if (ctx->passphrase_cb)
61     {
62       err = _gpgme_passphrase_command_handler (ctx, status, args, result);
63       if (err)
64         return err;
65     }
66
67   if (!*result)
68     {
69       err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, (void **) &opd, -1, NULL);
70       if (err)
71         return err;
72
73       return (*opd->fnc) (opd->fnc_value, status, args, result);
74     }
75   return 0;
76 }
77
78
79 static gpgme_error_t
80 edit_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t key,
81             gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
82 {
83   gpgme_error_t err;
84   op_data_t opd;
85
86   err = _gpgme_op_reset (ctx, synchronous);
87   if (err)
88     return err;
89
90   if (!fnc || !out)
91     return GPGME_Invalid_Value;
92
93   err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, (void **) &opd,
94                                sizeof (*opd), NULL);
95   if (err)
96     return err;
97
98   opd->fnc = fnc;
99   opd->fnc_value = fnc_value;
100
101   err = _gpgme_engine_set_command_handler (ctx->engine, command_handler,
102                                            ctx, out);
103   if (err)
104     return err;
105
106   _gpgme_engine_set_status_handler (ctx->engine, edit_status_handler, ctx);
107
108   return _gpgme_engine_op_edit (ctx->engine, key, out, ctx);
109 }
110
111
112 gpgme_error_t
113 gpgme_op_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
114                      gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
115 {
116   return edit_start (ctx, 0, key, fnc, fnc_value, out);
117 }
118
119
120 /* Edit the key KEY.  Send status and command requests to FNC and
121    output of edit commands to OUT.  */
122 gpgme_error_t
123 gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key,
124                gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
125 {
126   gpgme_error_t err = edit_start (ctx, 1, key, fnc, fnc_value, out);
127   if (!err)
128     err = _gpgme_wait_one (ctx);
129   return err;
130 }