2009-10-27 Marcus Brinkmann <marcus@g10code.de>
[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 <http://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 static gpgme_error_t
33 opassuan_start (gpgme_ctx_t ctx, int synchronous,
34                 const char *command,
35                 gpgme_assuan_data_cb_t data_cb,
36                 void *data_cb_value,
37                 gpgme_assuan_inquire_cb_t inq_cb,
38                 void *inq_cb_value,
39                 gpgme_assuan_status_cb_t status_cb,
40                 void *status_cb_value)
41 {
42   gpgme_error_t err;
43
44   if (!command || !*command)
45     return gpg_error (GPG_ERR_INV_VALUE);
46
47   /* The flag value 256 is used to suppress an engine reset.  This is
48      required to keep the connection running.  */
49   err = _gpgme_op_reset (ctx, ((synchronous&255) | 256));
50   if (err)
51     return err;
52
53   return _gpgme_engine_op_assuan_transact (ctx->engine, command,
54                                            data_cb, data_cb_value,
55                                            inq_cb, inq_cb_value,
56                                            status_cb, status_cb_value);
57 }
58
59
60
61 /* XXXX.  This is the asynchronous variant. */
62 gpgme_error_t
63 gpgme_op_assuan_transact_start (gpgme_ctx_t ctx, 
64                                 const char *command,
65                                 gpgme_assuan_data_cb_t data_cb,
66                                 void *data_cb_value,
67                                 gpgme_assuan_inquire_cb_t inq_cb,
68                                 void *inq_cb_value,
69                                 gpgme_assuan_status_cb_t status_cb,
70                                 void *status_cb_value)
71 {
72   TRACE_BEG7 (DEBUG_CTX, "gpgme_op_assuan_transact_start", ctx,
73               "command=%s, data_cb=%p/%p, inq_cb=%p/%p, status_cb=%p/%p",
74               command, data_cb, data_cb_value, inq_cb, inq_cb_value,
75               status_cb, status_cb_value);
76
77   return TRACE_ERR (opassuan_start (ctx, 0, command, 
78                                     data_cb, data_cb_value,
79                                     inq_cb, inq_cb_value,
80                                     status_cb, status_cb_value));
81 }
82
83
84 /* XXXX.  This is the synchronous variant. */
85 gpgme_error_t
86 gpgme_op_assuan_transact_ext (gpgme_ctx_t ctx,
87                               const char *command,
88                               gpgme_assuan_data_cb_t data_cb,
89                               void *data_cb_value,
90                               gpgme_assuan_inquire_cb_t inq_cb,
91                               void *inq_cb_value,
92                               gpgme_assuan_status_cb_t status_cb,
93                               void *status_cb_value,
94                               gpgme_error_t *op_err_p)
95 {
96   gpgme_error_t err;
97   gpgme_error_t op_err;
98
99   TRACE_BEG8 (DEBUG_CTX, "gpgme_op_assuan_transact", ctx,
100               "command=%s, data_cb=%p/%p, inq_cb=%p/%p, status_cb=%p/%p, "
101               "op_err=%p",
102               command, data_cb, data_cb_value, inq_cb, inq_cb_value,
103               status_cb, status_cb_value, op_err_p);
104
105   err = opassuan_start (ctx, 1, command, 
106                         data_cb, data_cb_value,
107                         inq_cb, inq_cb_value,
108                         status_cb, status_cb_value);
109   if (!err)
110     err = _gpgme_wait_one_ext (ctx, &op_err);
111
112   if (op_err)
113     {
114       TRACE_LOG2 ("op_err = %s <%s>", gpgme_strerror (op_err),
115                   gpgme_strsource (op_err));
116       if (! op_err_p)
117         {
118           TRACE_LOG ("warning: operational error ignored by user");
119         }
120     }
121   if (op_err_p)
122     *op_err_p = op_err;
123
124   return TRACE_ERR (err);
125 }
126
127
128
129 \f
130 /* Compatibility code for old interface.  */
131
132 /* Evil hack breaking abstractions for the purpose of localizing our
133    other hack.  This is copied from engine.c.  */
134 struct engine
135 {
136   struct engine_ops *ops;
137   void *engine;
138 };
139
140 typedef struct
141 {
142   struct _gpgme_op_assuan_result result;
143 } *op_data_t;
144
145 gpg_error_t _gpgme_engine_assuan_last_op_err (void *engine);
146
147 gpgme_assuan_result_t
148 gpgme_op_assuan_result (gpgme_ctx_t ctx)
149 {
150   gpgme_error_t err;
151   void *hook;
152   op_data_t opd;
153
154   TRACE_BEG (DEBUG_CTX, "gpgme_op_assuan_result", ctx);
155
156   err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, -1, NULL);
157   opd = hook;
158   /* Check in case this function is used without having run a command
159      before.  */
160   if (err || !opd)
161     {
162       TRACE_SUC0 ("result=(null)");
163       return NULL;
164     }
165
166   /* All of this is a hack for the old style interface.  The new style
167      interface returns op errors directly.  */
168   opd->result.err = _gpgme_engine_assuan_last_op_err (ctx->engine->engine);
169   if (opd->result.err)
170     {
171       TRACE_LOG1 ("err = %s", gpg_strerror (0));
172     }
173   else
174     {
175       TRACE_LOG2 ("err = %s <%s>", gpg_strerror (opd->result.err),
176                   gpg_strsource (opd->result.err));
177     }
178
179   TRACE_SUC1 ("result=%p", &opd->result);
180   return &opd->result;
181 }
182
183
184 gpgme_error_t
185 gpgme_op_assuan_transact (gpgme_ctx_t ctx,
186                           const char *command,
187                           gpgme_assuan_data_cb_t data_cb,
188                           void *data_cb_value,
189                           gpgme_assuan_inquire_cb_t inq_cb,
190                           void *inq_cb_value,
191                           gpgme_assuan_status_cb_t status_cb,
192                           void *status_cb_value)
193 {
194   gpgme_error_t err;
195
196   TRACE (DEBUG_CTX, "gpgme_op_assuan_transact", ctx);
197
198   /* Users of the old-style session based interfaces need to look at
199      the result structure.  */
200   gpgme_op_assuan_transact_ext (ctx, command, data_cb, data_cb_value,
201                                 inq_cb, inq_cb_value,
202                                 status_cb, status_cb_value, NULL);
203
204   return err;
205 }