2003-10-02 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   gpgme_error_t err;
43   void *hook;
44   op_data_t opd;
45
46   err = _gpgme_passphrase_status_handler (priv, status, args);
47   if (err)
48     return err;
49
50   err = _gpgme_progress_status_handler (priv, status, args);
51   if (err)
52     return err;
53
54   err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, -1, NULL);
55   opd = hook;
56   if (err)
57     return err;
58
59   return (*opd->fnc) (opd->fnc_value, status, args, -1);
60 }
61
62
63 static gpgme_error_t
64 command_handler (void *priv, gpgme_status_code_t status, const char *args,
65                  int fd)
66 {
67   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
68   gpgme_error_t err;
69   int processed = 0;
70
71   if (ctx->passphrase_cb)
72     {
73       err = _gpgme_passphrase_command_handler_internal (ctx, status, args,
74                                                         fd, &processed);
75       if (err)
76         return err;
77     }
78
79   if (!processed)
80     {
81       void *hook;
82       op_data_t opd;
83
84       err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, -1, NULL);
85       opd = hook;
86       if (err)
87         return err;
88
89       return (*opd->fnc) (opd->fnc_value, status, args, fd);
90     }
91   return 0;
92 }
93
94
95 static gpgme_error_t
96 edit_start (gpgme_ctx_t ctx, int synchronous, int type, gpgme_key_t key,
97             gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
98 {
99   gpgme_error_t err;
100   void *hook;
101   op_data_t opd;
102
103   err = _gpgme_op_reset (ctx, synchronous);
104   if (err)
105     return err;
106
107   if (!fnc || !out)
108     return gpg_error (GPG_ERR_INV_VALUE);
109
110   err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, sizeof (*opd), NULL);
111   opd = hook;
112   if (err)
113     return err;
114
115   opd->fnc = fnc;
116   opd->fnc_value = fnc_value;
117
118   err = _gpgme_engine_set_command_handler (ctx->engine, command_handler,
119                                            ctx, out);
120   if (err)
121     return err;
122
123   _gpgme_engine_set_status_handler (ctx->engine, edit_status_handler, ctx);
124
125   return _gpgme_engine_op_edit (ctx->engine, type, key, out, ctx);
126 }
127
128
129 gpgme_error_t
130 gpgme_op_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
131                      gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
132 {
133   return edit_start (ctx, 0, 0, key, fnc, fnc_value, out);
134 }
135
136
137 /* Edit the key KEY.  Send status and command requests to FNC and
138    output of edit commands to OUT.  */
139 gpgme_error_t
140 gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key,
141                gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
142 {
143   gpgme_error_t err = edit_start (ctx, 1, 0, key, fnc, fnc_value, out);
144   if (!err)
145     err = _gpgme_wait_one (ctx);
146   return err;
147 }
148
149 \f
150 gpgme_error_t
151 gpgme_op_card_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
152                           gpgme_edit_cb_t fnc, void *fnc_value,
153                           gpgme_data_t out)
154 {
155   return edit_start (ctx, 0, 1, key, fnc, fnc_value, out);
156 }
157
158
159 /* Edit the card for the key KEY.  Send status and command requests to
160    FNC and output of edit commands to OUT.  */
161 gpgme_error_t
162 gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key,
163                     gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
164 {
165   gpgme_error_t err = edit_start (ctx, 1, 1, key, fnc, fnc_value, out);
166   if (!err)
167     err = _gpgme_wait_one (ctx);
168   return err;
169 }