core: Remove cruft from the engine-gpg code.
[gpgme.git] / src / edit.c
1 /* edit.c - Key edit function.
2    Copyright (C) 2002, 2003, 2004 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 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.
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    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19    02111-1307, USA.  */
20
21 #if HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <stdlib.h>
25
26 #include "gpgme.h"
27 #include "debug.h"
28 #include "context.h"
29 #include "ops.h"
30 #include "util.h"
31
32
33 \f
34 typedef struct
35 {
36   /* The user callback function and its hook value.  */
37   gpgme_interact_cb_t fnc;
38   gpgme_edit_cb_t fnc_old;
39   void *fnc_value;
40 } *op_data_t;
41
42 \f
43 static gpgme_error_t
44 edit_status_handler (void *priv, gpgme_status_code_t status, char *args)
45 {
46   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
47   gpgme_error_t err;
48   void *hook;
49   op_data_t opd;
50
51   err = _gpgme_passphrase_status_handler (priv, status, args);
52   if (err)
53     return err;
54
55   err = _gpgme_progress_status_handler (priv, status, args);
56   if (err)
57     return err;
58
59   err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, -1, NULL);
60   opd = hook;
61   if (err)
62     return err;
63
64   if (opd->fnc_old)
65     return (*opd->fnc_old) (opd->fnc_value, status, args, -1);
66
67   return (*opd->fnc) (opd->fnc_value, _gpgme_status_to_string (status),
68                       args, -1);
69 }
70
71
72 static gpgme_error_t
73 command_handler (void *priv, gpgme_status_code_t status, const char *args,
74                  int fd, int *processed_r)
75 {
76   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
77   gpgme_error_t err;
78   int processed = 0;
79
80   if (ctx->passphrase_cb)
81     {
82       err = _gpgme_passphrase_command_handler (ctx, status, args,
83                                                fd, &processed);
84       if (err)
85         return err;
86     }
87   else
88     err = 0;
89
90   if (!processed)
91     {
92       void *hook;
93       op_data_t opd;
94
95       err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, -1, NULL);
96       opd = hook;
97       if (err)
98         return err;
99
100       if (opd->fnc_old)
101         err = (*opd->fnc_old) (opd->fnc_value, status, args, fd);
102       else
103         err = (*opd->fnc) (opd->fnc_value, _gpgme_status_to_string (status),
104                            args, fd);
105
106       if (gpg_err_code (err) == GPG_ERR_FALSE)
107         err = 0;
108       else
109         processed = 1;
110     }
111
112   *processed_r = processed;
113   return err;
114 }
115
116
117 static gpgme_error_t
118 interact_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t key,
119                 unsigned int flags,
120                 gpgme_interact_cb_t fnc, void *fnc_value, gpgme_data_t out)
121 {
122   gpgme_error_t err;
123   void *hook;
124   op_data_t opd;
125
126   err = _gpgme_op_reset (ctx, synchronous);
127   if (err)
128     return err;
129
130   if (!fnc || !out)
131     return gpg_error (GPG_ERR_INV_VALUE);
132
133   err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, sizeof (*opd), NULL);
134   opd = hook;
135   if (err)
136     return err;
137
138   opd->fnc = fnc;
139   opd->fnc_old = NULL;
140   opd->fnc_value = fnc_value;
141
142   err = _gpgme_engine_set_command_handler (ctx->engine, command_handler, ctx);
143   if (err)
144     return err;
145
146   _gpgme_engine_set_status_handler (ctx->engine, edit_status_handler, ctx);
147
148   return _gpgme_engine_op_edit (ctx->engine,
149                                 (flags & GPGME_INTERACT_CARD)? 1: 0,
150                                 key, out, ctx);
151 }
152
153
154 gpgme_error_t
155 gpgme_op_interact_start (gpgme_ctx_t ctx, gpgme_key_t key, unsigned int flags,
156                          gpgme_interact_cb_t fnc, void *fnc_value,
157                          gpgme_data_t out)
158 {
159   gpgme_error_t err;
160
161   TRACE_BEG5 (DEBUG_CTX, "gpgme_op_interact_start", ctx,
162               "key=%p flags=0x%x fnc=%p fnc_value=%p, out=%p",
163               key, flags,fnc, fnc_value, out);
164
165   if (!ctx)
166     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
167
168   err = interact_start (ctx, 0, key, flags, fnc, fnc_value, out);
169   return err;
170 }
171
172
173 gpgme_error_t
174 gpgme_op_interact (gpgme_ctx_t ctx, gpgme_key_t key, unsigned int flags,
175                    gpgme_interact_cb_t fnc, void *fnc_value,
176                    gpgme_data_t out)
177 {
178   gpgme_error_t err;
179
180   TRACE_BEG5 (DEBUG_CTX, "gpgme_op_interact", ctx,
181               "key=%p flags=0x%x fnc=%p fnc_value=%p, out=%p",
182               key, flags,fnc, fnc_value, out);
183
184   if (!ctx)
185     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
186
187   err = interact_start (ctx, 1, key, flags, fnc, fnc_value, out);
188   if (!err)
189     err = _gpgme_wait_one (ctx);
190   return err;
191 }
192
193
194
195 \f
196 /* The deprecated interface.  */
197 static gpgme_error_t
198 edit_start (gpgme_ctx_t ctx, int synchronous, int type, gpgme_key_t key,
199             gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
200 {
201   gpgme_error_t err;
202   void *hook;
203   op_data_t opd;
204
205   err = _gpgme_op_reset (ctx, synchronous);
206   if (err)
207     return err;
208
209   if (!fnc || !out)
210     return gpg_error (GPG_ERR_INV_VALUE);
211
212   err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, sizeof (*opd), NULL);
213   opd = hook;
214   if (err)
215     return err;
216
217   opd->fnc = NULL;
218   opd->fnc_old = fnc;
219   opd->fnc_value = fnc_value;
220
221   err = _gpgme_engine_set_command_handler (ctx->engine, command_handler, ctx);
222   if (err)
223     return err;
224
225   _gpgme_engine_set_status_handler (ctx->engine, edit_status_handler, ctx);
226
227   return _gpgme_engine_op_edit (ctx->engine, type, key, out, ctx);
228 }
229
230
231 gpgme_error_t
232 gpgme_op_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
233                      gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
234 {
235   gpgme_error_t err;
236
237   TRACE_BEG5 (DEBUG_CTX, "gpgme_op_edit_start", ctx,
238               "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
239               (key && key->subkeys && key->subkeys->fpr) ?
240               key->subkeys->fpr : "invalid", fnc, fnc_value, out);
241
242   if (!ctx)
243     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
244
245   err = edit_start (ctx, 0, 0, key, fnc, fnc_value, out);
246   return err;
247 }
248
249
250 /* Edit the key KEY.  Send status and command requests to FNC and
251    output of edit commands to OUT.  */
252 gpgme_error_t
253 gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key,
254                gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
255 {
256   gpgme_error_t err;
257
258   TRACE_BEG5 (DEBUG_CTX, "gpgme_op_edit", ctx,
259               "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
260               (key && key->subkeys && key->subkeys->fpr) ?
261               key->subkeys->fpr : "invalid", fnc, fnc_value, out);
262
263   if (!ctx)
264     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
265
266   err = edit_start (ctx, 1, 0, key, fnc, fnc_value, out);
267
268   if (!err)
269     err = _gpgme_wait_one (ctx);
270   return TRACE_ERR (err);
271 }
272
273 \f
274 gpgme_error_t
275 gpgme_op_card_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
276                           gpgme_edit_cb_t fnc, void *fnc_value,
277                           gpgme_data_t out)
278 {
279   gpgme_error_t err;
280
281   TRACE_BEG5 (DEBUG_CTX, "gpgme_op_card_edit_start", ctx,
282               "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
283               (key && key->subkeys && key->subkeys->fpr) ?
284               key->subkeys->fpr : "invalid", fnc, fnc_value, out);
285
286   if (!ctx)
287     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
288
289   err = edit_start (ctx, 0, 1, key, fnc, fnc_value, out);
290   return err;
291 }
292
293
294 /* Edit the card for the key KEY.  Send status and command requests to
295    FNC and output of edit commands to OUT.  */
296 gpgme_error_t
297 gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key,
298                     gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
299 {
300   gpgme_error_t err;
301
302   TRACE_BEG5 (DEBUG_CTX, "gpgme_op_card_edit", ctx,
303               "key=%p (%s), fnc=%p fnc_value=%p, out=%p", key,
304               (key && key->subkeys && key->subkeys->fpr) ?
305               key->subkeys->fpr : "invalid", fnc, fnc_value, out);
306
307   if (!ctx)
308     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
309
310   err = edit_start (ctx, 1, 1, key, fnc, fnc_value, out);
311   if (!err)
312     err = _gpgme_wait_one (ctx);
313   return TRACE_ERR (err);
314 }