2003-01-06 Marcus Brinkmann <marcus@g10code.de>
[gpgme.git] / gpgme / engine.c
1 /* engine.c - GPGME engine support.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002 g10 Code GmbH
4  
5    This file is part of GPGME.
6  
7    GPGME is free software; you can redistribute it and/or modify it
8    under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11  
12    GPGME is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    General Public License for more details.
16  
17    You should have received a copy of the GNU General Public License
18    along with GPGME; if not, write to the Free Software Foundation,
19    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "gpgme.h"
28 #include "util.h"
29 #include "sema.h"
30
31 #include "engine.h"
32 #include "engine-backend.h"
33
34
35 struct engine_object_s
36 {
37   struct engine_ops *ops;
38   void *engine;
39 };
40
41
42 static struct engine_ops *engine_ops[] =
43   {
44     &_gpgme_engine_ops_gpg,             /* OpenPGP.  */
45 #ifdef ENABLE_GPGSM
46     &_gpgme_engine_ops_gpgsm            /* CMS.  */
47 #else
48     NULL
49 #endif
50   };
51
52
53 /* Get the path of the engine for PROTOCOL.  */
54 const char *
55 _gpgme_engine_get_path (GpgmeProtocol proto)
56 {
57   if (proto > sizeof (engine_ops) / sizeof (engine_ops[0]))
58     return NULL;
59
60   if (engine_ops[proto] && engine_ops[proto]->get_path)
61     return (*engine_ops[proto]->get_path) ();
62   else
63     return NULL;
64 }
65
66
67 /* Get the version number of the engine for PROTOCOL.  */
68 const char *
69 _gpgme_engine_get_version (GpgmeProtocol proto)
70 {
71   if (proto > sizeof (engine_ops) / sizeof (engine_ops[0]))
72     return NULL;
73
74   if (engine_ops[proto] && engine_ops[proto]->get_version)
75     return (*engine_ops[proto]->get_version) ();
76   else
77     return NULL;
78 }
79
80
81 /* Verify the version requirement for the engine for PROTOCOL.  */
82 GpgmeError
83 gpgme_engine_check_version (GpgmeProtocol proto)
84 {
85   if (proto > sizeof (engine_ops) / sizeof (engine_ops[0]))
86     return mk_error (Invalid_Value);
87
88   if (!engine_ops[proto])
89     return mk_error (Invalid_Engine);
90
91   if (engine_ops[proto]->check_version)
92     return (*engine_ops[proto]->check_version) ();
93   else
94     return 0;
95 }
96
97
98 const char *
99 _gpgme_engine_get_info (GpgmeProtocol proto)
100 {
101   static const char fmt[] = " <engine>\n"
102     "  <protocol>%s</protocol>\n"
103     "  <version>%s</version>\n"
104     "  <path>%s</path>\n"
105     " </engine>\n";
106   static const char *const strproto[3] = { "OpenPGP", "CMS", NULL };
107   static const char *engine_info[3];  /* FIXME: MAX_PROTO + 1*/
108   DEFINE_STATIC_LOCK (engine_info_lock);
109
110   if (proto > 2 /* FIXME MAX_PROTO */ || !strproto[proto])
111     return NULL;
112
113   LOCK (engine_info_lock);
114   if (!engine_info[proto])
115     {
116       const char *path = _gpgme_engine_get_path (proto);
117       const char *version = _gpgme_engine_get_version (proto);
118
119       if (path && version)
120         {
121           char *info = malloc (strlen (fmt) + strlen (strproto[proto])
122                                    + strlen (path) + strlen (version) + 1);
123           if (!info)
124             info = " <engine>\n"
125               "  <error>Out of core</error>\n"
126               " </engine>";
127           else
128             sprintf (info, fmt, strproto[proto], version, path);
129           engine_info[proto] = info;
130         }
131     }
132   UNLOCK (engine_info_lock);
133   return engine_info[proto];
134 }
135
136
137 GpgmeError
138 _gpgme_engine_new (GpgmeProtocol proto, EngineObject *r_engine)
139 {
140   EngineObject engine;
141
142   const char *path;
143   const char *version;
144
145   if (proto > sizeof (engine_ops) / sizeof (engine_ops[0]))
146     return mk_error (Invalid_Value);
147
148   if (!engine_ops[proto])
149     return mk_error (Invalid_Engine);
150
151   path = _gpgme_engine_get_path (proto);
152   version = _gpgme_engine_get_version (proto);
153   if (!path || !version)
154     return mk_error (Invalid_Engine);
155
156   engine = calloc (1, sizeof *engine);
157   if (!engine)
158     return mk_error (Out_Of_Core);
159
160   engine->ops = engine_ops[proto];
161   if (engine_ops[proto]->new)
162     {
163       GpgmeError err = (*engine_ops[proto]->new) (&engine->engine);
164       if (err)
165         {
166           free (engine);
167           return err;
168         }
169     }
170   else
171     engine->engine = NULL;
172
173   *r_engine = engine;
174   return 0;
175 }
176
177
178 void
179 _gpgme_engine_release (EngineObject engine)
180 {
181   if (!engine)
182     return;
183
184   if (engine->ops->release)
185     (*engine->ops->release) (engine->engine);
186   free (engine);
187 }
188
189
190 void
191 _gpgme_engine_set_verbosity (EngineObject engine, int verbosity)
192 {
193   if (!engine)
194     return;
195
196   if (engine->ops->set_verbosity)
197     (*engine->ops->set_verbosity) (engine->engine, verbosity);
198 }
199
200
201 void
202 _gpgme_engine_set_status_handler (EngineObject engine,
203                                   GpgmeStatusHandler fnc, void *fnc_value)
204 {
205   if (!engine)
206     return;
207
208   if (engine->ops->set_status_handler)
209     (*engine->ops->set_status_handler) (engine->engine, fnc, fnc_value);
210 }
211
212
213 GpgmeError
214 _gpgme_engine_set_command_handler (EngineObject engine,
215                                    GpgmeCommandHandler fnc, void *fnc_value,
216                                    GpgmeData linked_data)
217 {
218   if (!engine)
219     return mk_error (Invalid_Value);
220
221   if (!engine->ops->set_command_handler)
222     return mk_error (Not_Implemented);
223
224   return (*engine->ops->set_command_handler) (engine->engine,
225                                               fnc, fnc_value, linked_data);
226 }
227
228 GpgmeError _gpgme_engine_set_colon_line_handler (EngineObject engine,
229                                                  GpgmeColonLineHandler fnc,
230                                                  void *fnc_value)
231 {
232   if (!engine)
233     return mk_error (Invalid_Value);
234
235   if (!engine->ops->set_colon_line_handler)
236     return mk_error (Not_Implemented);
237
238   return (*engine->ops->set_colon_line_handler) (engine->engine,
239                                                  fnc, fnc_value);
240 }
241
242 GpgmeError
243 _gpgme_engine_op_decrypt (EngineObject engine, GpgmeData ciph, GpgmeData plain)
244 {
245   if (!engine)
246     return mk_error (Invalid_Value);
247
248   if (!engine->ops->decrypt)
249     return mk_error (Not_Implemented);
250
251   return (*engine->ops->decrypt) (engine->engine, ciph, plain);
252 }
253
254 GpgmeError
255 _gpgme_engine_op_delete (EngineObject engine, GpgmeKey key, int allow_secret)
256 {
257   if (!engine)
258     return mk_error (Invalid_Value);
259
260   if (!engine->ops->delete)
261     return mk_error (Not_Implemented);
262
263   return (*engine->ops->delete) (engine->engine, key, allow_secret);
264 }
265
266
267 GpgmeError
268 _gpgme_engine_op_edit (EngineObject engine, GpgmeKey key, GpgmeData out,
269                        GpgmeCtx ctx /* FIXME */)
270 {
271   if (!engine)
272     return mk_error (Invalid_Value);
273
274   if (!engine->ops->edit)
275     return mk_error (Not_Implemented);
276
277   return (*engine->ops->edit) (engine->engine, key, out, ctx);
278 }
279
280
281 GpgmeError
282 _gpgme_engine_op_encrypt (EngineObject engine, GpgmeRecipients recp,
283                           GpgmeData plain, GpgmeData ciph, int use_armor)
284 {
285   if (!engine)
286     return mk_error (Invalid_Value);
287
288   if (!engine->ops->encrypt)
289     return mk_error (Not_Implemented);
290
291   return (*engine->ops->encrypt) (engine->engine, recp, plain, ciph,
292                                   use_armor);
293 }
294
295
296 GpgmeError
297 _gpgme_engine_op_encrypt_sign (EngineObject engine, GpgmeRecipients recp,
298                                GpgmeData plain, GpgmeData ciph, int use_armor,
299                                GpgmeCtx ctx /* FIXME */)
300 {
301   if (!engine)
302     return mk_error (Invalid_Value);
303
304   if (!engine->ops->encrypt_sign)
305     return mk_error (Not_Implemented);
306
307   return (*engine->ops->encrypt_sign) (engine->engine, recp, plain, ciph,
308                                        use_armor, ctx);
309 }
310
311
312 GpgmeError
313 _gpgme_engine_op_export (EngineObject engine, GpgmeRecipients recp,
314                          GpgmeData keydata, int use_armor)
315 {
316   if (!engine)
317     return mk_error (Invalid_Value);
318
319   if (!engine->ops->export)
320     return mk_error (Not_Implemented);
321
322   return (*engine->ops->export) (engine->engine, recp, keydata,
323                                  use_armor);
324 }
325
326
327 GpgmeError
328 _gpgme_engine_op_genkey (EngineObject engine, GpgmeData help_data,
329                          int use_armor, GpgmeData pubkey, GpgmeData seckey)
330 {
331   if (!engine)
332     return mk_error (Invalid_Value);
333
334   if (!engine->ops->genkey)
335     return mk_error (Not_Implemented);
336
337   return (*engine->ops->genkey) (engine->engine, help_data, use_armor,
338                                  pubkey, seckey);
339 }
340
341
342 GpgmeError
343 _gpgme_engine_op_import (EngineObject engine, GpgmeData keydata)
344 {
345   if (!engine)
346     return mk_error (Invalid_Value);
347
348   if (!engine->ops->import)
349     return mk_error (Not_Implemented);
350
351   return (*engine->ops->import) (engine->engine, keydata);
352 }
353
354
355 GpgmeError
356 _gpgme_engine_op_keylist (EngineObject engine, const char *pattern,
357                           int secret_only, int keylist_mode)
358 {
359   if (!engine)
360     return mk_error (Invalid_Value);
361
362   if (!engine->ops->keylist)
363     return mk_error (Not_Implemented);
364
365   return (*engine->ops->keylist) (engine->engine, pattern, secret_only,
366                                   keylist_mode);
367 }
368
369
370 GpgmeError
371 _gpgme_engine_op_keylist_ext (EngineObject engine, const char *pattern[],
372                               int secret_only, int reserved, int keylist_mode)
373 {
374   if (!engine)
375     return mk_error (Invalid_Value);
376
377   if (!engine->ops->keylist_ext)
378     return mk_error (Not_Implemented);
379
380   return (*engine->ops->keylist_ext) (engine->engine, pattern, secret_only,
381                                       reserved, keylist_mode);
382 }
383
384
385 GpgmeError
386 _gpgme_engine_op_sign (EngineObject engine, GpgmeData in, GpgmeData out,
387                        GpgmeSigMode mode, int use_armor,
388                        int use_textmode, int include_certs,
389                        GpgmeCtx ctx /* FIXME */)
390 {
391   if (!engine)
392     return mk_error (Invalid_Value);
393
394   if (!engine->ops->sign)
395     return mk_error (Not_Implemented);
396
397   return (*engine->ops->sign) (engine->engine, in, out, mode, use_armor,
398                                use_textmode, include_certs, ctx);
399 }
400
401
402 GpgmeError
403 _gpgme_engine_op_trustlist (EngineObject engine, const char *pattern)
404 {
405   if (!engine)
406     return mk_error (Invalid_Value);
407
408   if (!engine->ops->trustlist)
409     return mk_error (Not_Implemented);
410
411   return (*engine->ops->trustlist) (engine->engine, pattern);
412 }
413
414
415 GpgmeError
416 _gpgme_engine_op_verify (EngineObject engine, GpgmeData sig,
417                          GpgmeData signed_text, GpgmeData plaintext)
418 {
419   if (!engine)
420     return mk_error (Invalid_Value);
421
422   if (!engine->ops->verify)
423     return mk_error (Not_Implemented);
424
425   return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext);
426 }
427
428
429 GpgmeError
430 _gpgme_engine_start (EngineObject engine, void *opaque)
431 {
432   if (!engine)
433     return mk_error (Invalid_Value);
434
435   if (!engine->ops->start)
436     return mk_error (Not_Implemented);
437
438   return (*engine->ops->start) (engine->engine, opaque);
439 }
440
441
442 void
443 _gpgme_engine_set_io_cbs (EngineObject engine,
444                           struct GpgmeIOCbs *io_cbs)
445 {
446   if (!engine)
447     return;
448
449   (*engine->ops->set_io_cbs) (engine->engine, io_cbs);
450 }
451
452 void
453 _gpgme_engine_io_event (EngineObject engine,
454                         GpgmeEventIO type, void *type_data)
455 {
456   if (!engine)
457     return;
458
459   (*engine->ops->io_event) (engine->engine, type, type_data);
460 }