Release 1.9.0
[gpgme.git] / src / opassuan.c
1 /* opassuan.c - Low-level Assuan operations.
2    Copyright (C) 2009 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, see <https://www.gnu.org/licenses/>.
18  */
19
20 #if HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 /* Suppress warning for accessing deprecated member "err".  */
25 #define _GPGME_IN_GPGME 1
26 #include "gpgme.h"
27 #include "context.h"
28 #include "ops.h"
29 #include "util.h"
30 #include "debug.h"
31
32 /* LEGACY: Remove this when removing the deprecated result
33    structure.  */
34 typedef struct
35 {
36   struct _gpgme_op_assuan_result result;
37 } *op_data_t;
38
39
40 static gpgme_error_t
41 opassuan_start (gpgme_ctx_t ctx, int synchronous,
42                 const char *command,
43                 gpgme_assuan_data_cb_t data_cb,
44                 void *data_cb_value,
45                 gpgme_assuan_inquire_cb_t inq_cb,
46                 void *inq_cb_value,
47                 gpgme_assuan_status_cb_t status_cb,
48                 void *status_cb_value)
49 {
50   gpgme_error_t err;
51
52   if (!command || !*command)
53     return gpg_error (GPG_ERR_INV_VALUE);
54
55   /* The flag value 256 is used to suppress an engine reset.  This is
56      required to keep the connection running.  */
57   err = _gpgme_op_reset (ctx, ((synchronous&255) | 256));
58   if (err)
59     return err;
60
61   {
62     /* LEGACY: Remove this when removing the deprecated result
63        structure.  */
64     void *hook;
65     op_data_t opd;
66     err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook,
67                                  sizeof (*opd), NULL);
68     if (err)
69       return err;
70   }
71
72   return _gpgme_engine_op_assuan_transact (ctx->engine, command,
73                                            data_cb, data_cb_value,
74                                            inq_cb, inq_cb_value,
75                                            status_cb, status_cb_value);
76 }
77
78
79
80 /* XXXX.  This is the asynchronous variant. */
81 gpgme_error_t
82 gpgme_op_assuan_transact_start (gpgme_ctx_t ctx,
83                                 const char *command,
84                                 gpgme_assuan_data_cb_t data_cb,
85                                 void *data_cb_value,
86                                 gpgme_assuan_inquire_cb_t inq_cb,
87                                 void *inq_cb_value,
88                                 gpgme_assuan_status_cb_t status_cb,
89                                 void *status_cb_value)
90 {
91   gpg_error_t err;
92
93   TRACE_BEG7 (DEBUG_CTX, "gpgme_op_assuan_transact_start", ctx,
94               "command=%s, data_cb=%p/%p, inq_cb=%p/%p, status_cb=%p/%p",
95               command, data_cb, data_cb_value, inq_cb, inq_cb_value,
96               status_cb, status_cb_value);
97
98   if (!ctx)
99     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
100
101   err = opassuan_start (ctx, 0, command, data_cb, data_cb_value,
102                         inq_cb, inq_cb_value, status_cb, status_cb_value);
103   return TRACE_ERR (err);
104 }
105
106
107 /* XXXX.  This is the synchronous variant. */
108 gpgme_error_t
109 gpgme_op_assuan_transact_ext (gpgme_ctx_t ctx,
110                               const char *command,
111                               gpgme_assuan_data_cb_t data_cb,
112                               void *data_cb_value,
113                               gpgme_assuan_inquire_cb_t inq_cb,
114                               void *inq_cb_value,
115                               gpgme_assuan_status_cb_t status_cb,
116                               void *status_cb_value,
117                               gpgme_error_t *op_err_p)
118 {
119   gpgme_error_t err;
120   gpgme_error_t op_err;
121
122   TRACE_BEG8 (DEBUG_CTX, "gpgme_op_assuan_transact", ctx,
123               "command=%s, data_cb=%p/%p, inq_cb=%p/%p, status_cb=%p/%p, "
124               "op_err=%p",
125               command, data_cb, data_cb_value, inq_cb, inq_cb_value,
126               status_cb, status_cb_value, op_err_p);
127
128   if (!ctx)
129     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
130
131   err = opassuan_start (ctx, 1, command,
132                         data_cb, data_cb_value,
133                         inq_cb, inq_cb_value,
134                         status_cb, status_cb_value);
135   if (err)
136     goto out;
137
138   err = _gpgme_wait_one_ext (ctx, &op_err);
139   if (op_err)
140     {
141       TRACE_LOG2 ("op_err = %s <%s>", gpgme_strerror (op_err),
142                   gpgme_strsource (op_err));
143       if (! op_err_p)
144         {
145           TRACE_LOG ("warning: operational error ignored by user");
146         }
147     }
148   if (op_err_p)
149     *op_err_p = op_err;
150
151  out:
152   return TRACE_ERR (err);
153 }
154
155
156
157 \f
158 /* Compatibility code for old interface.  */
159
160 /* Evil hack breaking abstractions for the purpose of localizing our
161    other hack.  This is copied from engine.c.  */
162 struct engine
163 {
164   struct engine_ops *ops;
165   void *engine;
166 };
167
168 gpg_error_t _gpgme_engine_assuan_last_op_err (void *engine);
169
170 gpgme_assuan_result_t
171 gpgme_op_assuan_result (gpgme_ctx_t ctx)
172 {
173   gpgme_error_t err;
174   void *hook;
175   op_data_t opd;
176
177   TRACE_BEG (DEBUG_CTX, "gpgme_op_assuan_result", ctx);
178
179   err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, -1, NULL);
180   opd = hook;
181   /* Check in case this function is used without having run a command
182      before.  */
183   if (err || !opd)
184     {
185       TRACE_SUC0 ("result=(null)");
186       return NULL;
187     }
188
189   /* All of this is a hack for the old style interface.  The new style
190      interface returns op errors directly.  */
191   opd->result.err = _gpgme_engine_assuan_last_op_err (ctx->engine->engine);
192   if (opd->result.err)
193     {
194       TRACE_LOG1 ("err = %s", gpg_strerror (0));
195     }
196   else
197     {
198       TRACE_LOG2 ("err = %s <%s>", gpg_strerror (opd->result.err),
199                   gpg_strsource (opd->result.err));
200     }
201
202   TRACE_SUC1 ("result=%p", &opd->result);
203   return &opd->result;
204 }
205
206
207 gpgme_error_t
208 gpgme_op_assuan_transact (gpgme_ctx_t ctx,
209                           const char *command,
210                           gpgme_assuan_data_cb_t data_cb,
211                           void *data_cb_value,
212                           gpgme_assuan_inquire_cb_t inq_cb,
213                           void *inq_cb_value,
214                           gpgme_assuan_status_cb_t status_cb,
215                           void *status_cb_value)
216 {
217   gpgme_error_t err;
218
219   TRACE (DEBUG_CTX, "gpgme_op_assuan_transact", ctx);
220
221   if (!ctx)
222     return gpg_error (GPG_ERR_INV_VALUE);
223
224   /* Users of the old-style session based interfaces need to look at
225      the result structure.  */
226   err = gpgme_op_assuan_transact_ext (ctx, command, data_cb, data_cb_value,
227                                       inq_cb, inq_cb_value,
228                                       status_cb, status_cb_value, NULL);
229   return err;
230 }