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