Line data Source code
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 28 : 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 28 : if (!command || !*command)
53 0 : 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 28 : err = _gpgme_op_reset (ctx, ((synchronous&255) | 256));
58 28 : if (err)
59 12 : return err;
60 :
61 : {
62 : /* LEGACY: Remove this when removing the deprecated result
63 : structure. */
64 : void *hook;
65 : op_data_t opd;
66 16 : err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook,
67 : sizeof (*opd), NULL);
68 16 : if (err)
69 0 : return err;
70 : }
71 :
72 16 : 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 0 : 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 0 : 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 0 : if (!ctx)
99 0 : return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
100 :
101 0 : err = opassuan_start (ctx, 0, command, data_cb, data_cb_value,
102 : inq_cb, inq_cb_value, status_cb, status_cb_value);
103 0 : return TRACE_ERR (err);
104 : }
105 :
106 :
107 : /* XXXX. This is the synchronous variant. */
108 : gpgme_error_t
109 28 : 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 28 : 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 28 : if (!ctx)
129 0 : return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
130 :
131 28 : 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 28 : if (err)
136 12 : goto out;
137 :
138 16 : err = _gpgme_wait_one_ext (ctx, &op_err);
139 16 : if (op_err)
140 : {
141 2 : TRACE_LOG2 ("op_err = %s <%s>", gpgme_strerror (op_err),
142 : gpgme_strsource (op_err));
143 2 : if (! op_err_p)
144 : {
145 0 : TRACE_LOG ("warning: operational error ignored by user");
146 : }
147 : }
148 16 : if (op_err_p)
149 16 : *op_err_p = op_err;
150 :
151 : out:
152 28 : return TRACE_ERR (err);
153 : }
154 :
155 :
156 :
157 :
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 0 : gpgme_op_assuan_result (gpgme_ctx_t ctx)
172 : {
173 : gpgme_error_t err;
174 : void *hook;
175 : op_data_t opd;
176 :
177 0 : TRACE_BEG (DEBUG_CTX, "gpgme_op_assuan_result", ctx);
178 :
179 0 : err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, -1, NULL);
180 0 : opd = hook;
181 : /* Check in case this function is used without having run a command
182 : before. */
183 0 : if (err || !opd)
184 : {
185 0 : TRACE_SUC0 ("result=(null)");
186 0 : 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 0 : opd->result.err = _gpgme_engine_assuan_last_op_err (ctx->engine->engine);
192 0 : if (opd->result.err)
193 : {
194 0 : TRACE_LOG1 ("err = %s", gpg_strerror (0));
195 : }
196 : else
197 : {
198 0 : TRACE_LOG2 ("err = %s <%s>", gpg_strerror (opd->result.err),
199 : gpg_strsource (opd->result.err));
200 : }
201 :
202 0 : TRACE_SUC1 ("result=%p", &opd->result);
203 0 : return &opd->result;
204 : }
205 :
206 :
207 : gpgme_error_t
208 0 : 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 0 : TRACE (DEBUG_CTX, "gpgme_op_assuan_transact", ctx);
220 :
221 0 : if (!ctx)
222 0 : 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 0 : 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 0 : return err;
230 : }
|