Merge branch 'gpgmepp'
[gpgme.git] / src / engine.c
1 /* engine.c - GPGME engine support.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003, 2004, 2006, 2009, 2010 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 Lesser General Public License as
9    published by the Free Software Foundation; either version 2.1 of
10    the License, or (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    Lesser General Public License for more details.
16
17    You should have received a copy of the GNU Lesser General Public
18    License along with this program; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <assert.h>
28
29 #include "gpgme.h"
30 #include "util.h"
31 #include "sema.h"
32 #include "ops.h"
33 #include "debug.h"
34
35 #include "engine.h"
36 #include "engine-backend.h"
37
38
39 struct engine
40 {
41   struct engine_ops *ops;
42   void *engine;
43 };
44
45
46 static struct engine_ops *engine_ops[] =
47   {
48     &_gpgme_engine_ops_gpg,             /* OpenPGP.  */
49     &_gpgme_engine_ops_gpgsm,           /* CMS.  */
50     &_gpgme_engine_ops_gpgconf,         /* gpg-conf.  */
51     &_gpgme_engine_ops_assuan,          /* Low-Level Assuan.  */
52     &_gpgme_engine_ops_g13,             /* Crypto VFS.  */
53 #ifdef ENABLE_UISERVER
54     &_gpgme_engine_ops_uiserver,        /* UI-Server.  */
55 #else
56     NULL,
57 #endif
58     &_gpgme_engine_ops_spawn
59   };
60
61
62 /* The engine info.  */
63 static gpgme_engine_info_t engine_info;
64 DEFINE_STATIC_LOCK (engine_info_lock);
65
66 \f
67 /* Get the file name of the engine for PROTOCOL.  */
68 static const char *
69 engine_get_file_name (gpgme_protocol_t proto)
70 {
71   if (proto > DIM (engine_ops))
72     return NULL;
73
74   if (engine_ops[proto] && engine_ops[proto]->get_file_name)
75     return (*engine_ops[proto]->get_file_name) ();
76   else
77     return NULL;
78 }
79
80
81 /* Get the standard home dir of the engine for PROTOCOL.  */
82 static const char *
83 engine_get_home_dir (gpgme_protocol_t proto)
84 {
85   if (proto > DIM (engine_ops))
86     return NULL;
87
88   if (engine_ops[proto] && engine_ops[proto]->get_home_dir)
89     return (*engine_ops[proto]->get_home_dir) ();
90   else
91     return NULL;
92 }
93
94
95 /* Get a malloced string containing the version number of the engine
96    for PROTOCOL.  */
97 static char *
98 engine_get_version (gpgme_protocol_t proto, const char *file_name)
99 {
100   if (proto > DIM (engine_ops))
101     return NULL;
102
103   if (engine_ops[proto] && engine_ops[proto]->get_version)
104     return (*engine_ops[proto]->get_version) (file_name);
105   else
106     return NULL;
107 }
108
109
110 /* Get the required version number of the engine for PROTOCOL.  */
111 static const char *
112 engine_get_req_version (gpgme_protocol_t proto)
113 {
114   if (proto > DIM (engine_ops))
115     return NULL;
116
117   if (engine_ops[proto] && engine_ops[proto]->get_req_version)
118     return (*engine_ops[proto]->get_req_version) ();
119   else
120     return NULL;
121 }
122
123
124 /* Verify the version requirement for the engine for PROTOCOL.  */
125 gpgme_error_t
126 gpgme_engine_check_version (gpgme_protocol_t proto)
127 {
128   gpgme_error_t err;
129   gpgme_engine_info_t info;
130   int result;
131
132   LOCK (engine_info_lock);
133   info = engine_info;
134   if (!info)
135     {
136       /* Make sure it is initialized.  */
137       UNLOCK (engine_info_lock);
138       err = gpgme_get_engine_info (&info);
139       if (err)
140         return err;
141
142       LOCK (engine_info_lock);
143     }
144
145   while (info && info->protocol != proto)
146     info = info->next;
147
148   if (!info)
149     result = 0;
150   else
151     result = _gpgme_compare_versions (info->version,
152                                       info->req_version);
153
154   UNLOCK (engine_info_lock);
155   return result ? 0 : trace_gpg_error (GPG_ERR_INV_ENGINE);
156 }
157
158
159 /* Release the engine info INFO.  */
160 void
161 _gpgme_engine_info_release (gpgme_engine_info_t info)
162 {
163   while (info)
164     {
165       gpgme_engine_info_t next_info = info->next;
166
167       assert (info->file_name);
168       free (info->file_name);
169       if (info->home_dir)
170         free (info->home_dir);
171       if (info->version)
172         free (info->version);
173       free (info);
174       info = next_info;
175     }
176 }
177
178
179 /* Get the information about the configured and installed engines.  A
180    pointer to the first engine in the statically allocated linked list
181    is returned in *INFO.  If an error occurs, it is returned.  The
182    returned data is valid until the next gpgme_set_engine_info.  */
183 gpgme_error_t
184 gpgme_get_engine_info (gpgme_engine_info_t *info)
185 {
186   gpgme_error_t err;
187
188   LOCK (engine_info_lock);
189   if (!engine_info)
190     {
191       gpgme_engine_info_t *lastp = &engine_info;
192       gpgme_protocol_t proto_list[] = { GPGME_PROTOCOL_OpenPGP,
193                                         GPGME_PROTOCOL_CMS,
194                                         GPGME_PROTOCOL_GPGCONF,
195                                         GPGME_PROTOCOL_ASSUAN,
196                                         GPGME_PROTOCOL_G13,
197                                         GPGME_PROTOCOL_UISERVER,
198                                         GPGME_PROTOCOL_SPAWN    };
199       unsigned int proto;
200
201       err = 0;
202       for (proto = 0; proto < DIM (proto_list); proto++)
203         {
204           const char *ofile_name = engine_get_file_name (proto_list[proto]);
205           const char *ohome_dir  = engine_get_home_dir (proto_list[proto]);
206           char *file_name;
207           char *home_dir;
208
209           if (!ofile_name)
210             continue;
211
212           file_name = strdup (ofile_name);
213           if (!file_name)
214             err = gpg_error_from_syserror ();
215
216           if (ohome_dir)
217             {
218               home_dir = strdup (ohome_dir);
219               if (!home_dir && !err)
220                 err = gpg_error_from_syserror ();
221             }
222           else
223             home_dir = NULL;
224
225           *lastp = malloc (sizeof (*engine_info));
226           if (!*lastp && !err)
227             err = gpg_error_from_syserror ();
228
229           if (err)
230             {
231               _gpgme_engine_info_release (engine_info);
232               engine_info = NULL;
233
234               if (file_name)
235                 free (file_name);
236               if (home_dir)
237                 free (home_dir);
238
239               UNLOCK (engine_info_lock);
240               return err;
241             }
242
243           (*lastp)->protocol = proto_list[proto];
244           (*lastp)->file_name = file_name;
245           (*lastp)->home_dir = home_dir;
246           (*lastp)->version = engine_get_version (proto_list[proto], NULL);
247           (*lastp)->req_version = engine_get_req_version (proto_list[proto]);
248           (*lastp)->next = NULL;
249           lastp = &(*lastp)->next;
250         }
251     }
252
253   *info = engine_info;
254   UNLOCK (engine_info_lock);
255   return 0;
256 }
257
258
259 /* Get a deep copy of the engine info and return it in INFO.  */
260 gpgme_error_t
261 _gpgme_engine_info_copy (gpgme_engine_info_t *r_info)
262 {
263   gpgme_error_t err = 0;
264   gpgme_engine_info_t info;
265   gpgme_engine_info_t new_info;
266   gpgme_engine_info_t *lastp;
267
268   LOCK (engine_info_lock);
269   info = engine_info;
270   if (!info)
271     {
272       /* Make sure it is initialized.  */
273       UNLOCK (engine_info_lock);
274       err = gpgme_get_engine_info (&info);
275       if (err)
276         return err;
277
278       LOCK (engine_info_lock);
279     }
280
281   new_info = NULL;
282   lastp = &new_info;
283
284   while (info)
285     {
286       char *file_name;
287       char *home_dir;
288       char *version;
289
290       assert (info->file_name);
291       file_name = strdup (info->file_name);
292       if (!file_name)
293         err = gpg_error_from_syserror ();
294
295       if (info->home_dir)
296         {
297           home_dir = strdup (info->home_dir);
298           if (!home_dir && !err)
299             err = gpg_error_from_syserror ();
300         }
301       else
302         home_dir = NULL;
303
304       if (info->version)
305         {
306           version = strdup (info->version);
307           if (!version && !err)
308             err = gpg_error_from_syserror ();
309         }
310       else
311         version = NULL;
312
313       *lastp = malloc (sizeof (*engine_info));
314       if (!*lastp && !err)
315         err = gpg_error_from_syserror ();
316
317       if (err)
318         {
319           _gpgme_engine_info_release (new_info);
320           if (file_name)
321             free (file_name);
322           if (home_dir)
323             free (home_dir);
324           if (version)
325             free (version);
326
327           UNLOCK (engine_info_lock);
328           return err;
329         }
330
331       (*lastp)->protocol = info->protocol;
332       (*lastp)->file_name = file_name;
333       (*lastp)->home_dir = home_dir;
334       (*lastp)->version = version;
335       (*lastp)->req_version = info->req_version;
336       (*lastp)->next = NULL;
337       lastp = &(*lastp)->next;
338
339       info = info->next;
340     }
341
342   *r_info = new_info;
343   UNLOCK (engine_info_lock);
344   return 0;
345 }
346
347
348 /* Set the engine info for the info list INFO, protocol PROTO, to the
349    file name FILE_NAME and the home directory HOME_DIR.  */
350 gpgme_error_t
351 _gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto,
352                         const char *file_name, const char *home_dir)
353 {
354   char *new_file_name;
355   char *new_home_dir;
356
357   /* FIXME: Use some PROTO_MAX definition.  */
358   if (proto > DIM (engine_ops))
359     return gpg_error (GPG_ERR_INV_VALUE);
360
361   while (info && info->protocol != proto)
362     info = info->next;
363
364   if (!info)
365     return trace_gpg_error (GPG_ERR_INV_ENGINE);
366
367   /* Prepare new members.  */
368   if (file_name)
369     new_file_name = strdup (file_name);
370   else
371     {
372       const char *ofile_name = engine_get_file_name (proto);
373       assert (ofile_name);
374       new_file_name = strdup (ofile_name);
375     }
376   if (!new_file_name)
377     return gpg_error_from_syserror ();
378
379   if (home_dir)
380     {
381       new_home_dir = strdup (home_dir);
382       if (!new_home_dir)
383         {
384           free (new_file_name);
385           return gpg_error_from_syserror ();
386         }
387     }
388   else
389     {
390       const char *ohome_dir = engine_get_home_dir (proto);
391       if (ohome_dir)
392         {
393           new_home_dir = strdup (ohome_dir);
394           if (!new_home_dir)
395             {
396               free (new_file_name);
397               return gpg_error_from_syserror ();
398             }
399         }
400       else
401         new_home_dir = NULL;
402     }
403
404   /* Remove the old members.  */
405   assert (info->file_name);
406   free (info->file_name);
407   if (info->home_dir)
408     free (info->home_dir);
409   if (info->version)
410     free (info->version);
411
412   /* Install the new members.  */
413   info->file_name = new_file_name;
414   info->home_dir = new_home_dir;
415   info->version = engine_get_version (proto, new_file_name);
416
417   return 0;
418 }
419
420
421 /* Set the default engine info for the protocol PROTO to the file name
422    FILE_NAME and the home directory HOME_DIR.  */
423 gpgme_error_t
424 gpgme_set_engine_info (gpgme_protocol_t proto,
425                        const char *file_name, const char *home_dir)
426 {
427   gpgme_error_t err;
428   gpgme_engine_info_t info;
429
430   LOCK (engine_info_lock);
431   info = engine_info;
432   if (!info)
433     {
434       /* Make sure it is initialized.  */
435       UNLOCK (engine_info_lock);
436       err = gpgme_get_engine_info (&info);
437       if (err)
438         return err;
439
440       LOCK (engine_info_lock);
441     }
442
443   err = _gpgme_set_engine_info (info, proto, file_name, home_dir);
444   UNLOCK (engine_info_lock);
445   return err;
446 }
447
448 \f
449 gpgme_error_t
450 _gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine)
451 {
452   engine_t engine;
453
454   if (!info->file_name || !info->version)
455     return trace_gpg_error (GPG_ERR_INV_ENGINE);
456
457   engine = calloc (1, sizeof *engine);
458   if (!engine)
459     return gpg_error_from_syserror ();
460
461   engine->ops = engine_ops[info->protocol];
462   if (engine->ops->new)
463     {
464       gpgme_error_t err;
465       err = (*engine->ops->new) (&engine->engine,
466                                  info->file_name, info->home_dir);
467       if (err)
468         {
469           free (engine);
470           return err;
471         }
472     }
473   else
474     engine->engine = NULL;
475
476   *r_engine = engine;
477   return 0;
478 }
479
480
481 gpgme_error_t
482 _gpgme_engine_reset (engine_t engine)
483 {
484   if (!engine)
485     return gpg_error (GPG_ERR_INV_VALUE);
486
487   if (!engine->ops->reset)
488     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
489
490   return (*engine->ops->reset) (engine->engine);
491 }
492
493
494 void
495 _gpgme_engine_release (engine_t engine)
496 {
497   if (!engine)
498     return;
499
500   if (engine->ops->release)
501     (*engine->ops->release) (engine->engine);
502   free (engine);
503 }
504
505
506 void
507 _gpgme_engine_set_status_handler (engine_t engine,
508                                   engine_status_handler_t fnc, void *fnc_value)
509 {
510   if (!engine)
511     return;
512
513   if (engine->ops->set_status_handler)
514     (*engine->ops->set_status_handler) (engine->engine, fnc, fnc_value);
515 }
516
517
518 gpgme_error_t
519 _gpgme_engine_set_command_handler (engine_t engine,
520                                    engine_command_handler_t fnc,
521                                    void *fnc_value,
522                                    gpgme_data_t linked_data)
523 {
524   if (!engine)
525     return gpg_error (GPG_ERR_INV_VALUE);
526
527   if (!engine->ops->set_command_handler)
528     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
529
530   return (*engine->ops->set_command_handler) (engine->engine,
531                                               fnc, fnc_value, linked_data);
532 }
533
534 gpgme_error_t
535 _gpgme_engine_set_colon_line_handler (engine_t engine,
536                                       engine_colon_line_handler_t fnc,
537                                       void *fnc_value)
538 {
539   if (!engine)
540     return gpg_error (GPG_ERR_INV_VALUE);
541
542   if (!engine->ops->set_colon_line_handler)
543     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
544
545   return (*engine->ops->set_colon_line_handler) (engine->engine,
546                                                  fnc, fnc_value);
547 }
548
549 gpgme_error_t
550 _gpgme_engine_set_locale (engine_t engine, int category,
551                           const char *value)
552 {
553   if (!engine)
554     return gpg_error (GPG_ERR_INV_VALUE);
555
556   if (!engine->ops->set_locale)
557     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
558
559   return (*engine->ops->set_locale) (engine->engine, category, value);
560 }
561
562
563 gpgme_error_t
564 _gpgme_engine_set_protocol (engine_t engine, gpgme_protocol_t protocol)
565 {
566   if (!engine)
567     return gpg_error (GPG_ERR_INV_VALUE);
568
569   if (!engine->ops->set_protocol)
570     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
571
572   return (*engine->ops->set_protocol) (engine->engine, protocol);
573 }
574
575
576 gpgme_error_t
577 _gpgme_engine_op_decrypt (engine_t engine, gpgme_data_t ciph,
578                           gpgme_data_t plain)
579 {
580   if (!engine)
581     return gpg_error (GPG_ERR_INV_VALUE);
582
583   if (!engine->ops->decrypt)
584     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
585
586   return (*engine->ops->decrypt) (engine->engine, ciph, plain);
587 }
588
589
590 gpgme_error_t
591 _gpgme_engine_op_decrypt_verify (engine_t engine, gpgme_data_t ciph,
592                                  gpgme_data_t plain)
593 {
594   if (!engine)
595     return gpg_error (GPG_ERR_INV_VALUE);
596
597   if (!engine->ops->decrypt_verify)
598     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
599
600   return (*engine->ops->decrypt_verify) (engine->engine, ciph, plain);
601 }
602
603
604 gpgme_error_t
605 _gpgme_engine_op_delete (engine_t engine, gpgme_key_t key,
606                          int allow_secret)
607 {
608   if (!engine)
609     return gpg_error (GPG_ERR_INV_VALUE);
610
611   if (!engine->ops->delete)
612     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
613
614   return (*engine->ops->delete) (engine->engine, key, allow_secret);
615 }
616
617
618 gpgme_error_t
619 _gpgme_engine_op_edit (engine_t engine, int type, gpgme_key_t key,
620                        gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */)
621 {
622   if (!engine)
623     return gpg_error (GPG_ERR_INV_VALUE);
624
625   if (!engine->ops->edit)
626     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
627
628   return (*engine->ops->edit) (engine->engine, type, key, out, ctx);
629 }
630
631
632 gpgme_error_t
633 _gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[],
634                           gpgme_encrypt_flags_t flags,
635                           gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
636 {
637   if (!engine)
638     return gpg_error (GPG_ERR_INV_VALUE);
639
640   if (!engine->ops->encrypt)
641     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
642
643   return (*engine->ops->encrypt) (engine->engine, recp, flags, plain, ciph,
644                                   use_armor);
645 }
646
647
648 gpgme_error_t
649 _gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[],
650                                gpgme_encrypt_flags_t flags,
651                                gpgme_data_t plain, gpgme_data_t ciph,
652                                int use_armor, gpgme_ctx_t ctx /* FIXME */)
653 {
654   if (!engine)
655     return gpg_error (GPG_ERR_INV_VALUE);
656
657   if (!engine->ops->encrypt_sign)
658     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
659
660   return (*engine->ops->encrypt_sign) (engine->engine, recp, flags,
661                                        plain, ciph, use_armor, ctx);
662 }
663
664
665 gpgme_error_t
666 _gpgme_engine_op_export (engine_t engine, const char *pattern,
667                          gpgme_export_mode_t mode, gpgme_data_t keydata,
668                          int use_armor)
669 {
670   if (!engine)
671     return gpg_error (GPG_ERR_INV_VALUE);
672
673   if (!engine->ops->export)
674     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
675
676   return (*engine->ops->export) (engine->engine, pattern, mode,
677                                  keydata, use_armor);
678 }
679
680
681 gpgme_error_t
682 _gpgme_engine_op_export_ext (engine_t engine, const char *pattern[],
683                              unsigned int reserved, gpgme_data_t keydata,
684                              int use_armor)
685 {
686   if (!engine)
687     return gpg_error (GPG_ERR_INV_VALUE);
688
689   if (!engine->ops->export_ext)
690     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
691
692   return (*engine->ops->export_ext) (engine->engine, pattern, reserved,
693                                      keydata, use_armor);
694 }
695
696
697 gpgme_error_t
698 _gpgme_engine_op_genkey (engine_t engine, gpgme_data_t help_data,
699                          int use_armor, gpgme_data_t pubkey,
700                          gpgme_data_t seckey)
701 {
702   if (!engine)
703     return gpg_error (GPG_ERR_INV_VALUE);
704
705   if (!engine->ops->genkey)
706     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
707
708   return (*engine->ops->genkey) (engine->engine, help_data, use_armor,
709                                  pubkey, seckey);
710 }
711
712
713 gpgme_error_t
714 _gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata,
715                          gpgme_key_t *keyarray)
716 {
717   if (!engine)
718     return gpg_error (GPG_ERR_INV_VALUE);
719
720   if (!engine->ops->import)
721     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
722
723   return (*engine->ops->import) (engine->engine, keydata, keyarray);
724 }
725
726
727 gpgme_error_t
728 _gpgme_engine_op_keylist (engine_t engine, const char *pattern,
729                           int secret_only, gpgme_keylist_mode_t mode,
730                           int engine_flags)
731 {
732   if (!engine)
733     return gpg_error (GPG_ERR_INV_VALUE);
734
735   if (!engine->ops->keylist)
736     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
737
738   return (*engine->ops->keylist) (engine->engine, pattern, secret_only, mode,
739                                   engine_flags);
740 }
741
742
743 gpgme_error_t
744 _gpgme_engine_op_keylist_ext (engine_t engine, const char *pattern[],
745                               int secret_only, int reserved,
746                               gpgme_keylist_mode_t mode, int engine_flags)
747 {
748   if (!engine)
749     return gpg_error (GPG_ERR_INV_VALUE);
750
751   if (!engine->ops->keylist_ext)
752     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
753
754   return (*engine->ops->keylist_ext) (engine->engine, pattern, secret_only,
755                                       reserved, mode, engine_flags);
756 }
757
758
759 gpgme_error_t
760 _gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_data_t out,
761                        gpgme_sig_mode_t mode, int use_armor,
762                        int use_textmode, int include_certs,
763                        gpgme_ctx_t ctx /* FIXME */)
764 {
765   if (!engine)
766     return gpg_error (GPG_ERR_INV_VALUE);
767
768   if (!engine->ops->sign)
769     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
770
771   return (*engine->ops->sign) (engine->engine, in, out, mode, use_armor,
772                                use_textmode, include_certs, ctx);
773 }
774
775
776 gpgme_error_t
777 _gpgme_engine_op_trustlist (engine_t engine, const char *pattern)
778 {
779   if (!engine)
780     return gpg_error (GPG_ERR_INV_VALUE);
781
782   if (!engine->ops->trustlist)
783     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
784
785   return (*engine->ops->trustlist) (engine->engine, pattern);
786 }
787
788
789 gpgme_error_t
790 _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
791                          gpgme_data_t signed_text, gpgme_data_t plaintext)
792 {
793   if (!engine)
794     return gpg_error (GPG_ERR_INV_VALUE);
795
796   if (!engine->ops->verify)
797     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
798
799   return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext);
800 }
801
802
803 gpgme_error_t
804 _gpgme_engine_op_getauditlog (engine_t engine, gpgme_data_t output,
805                               unsigned int flags)
806 {
807   if (!engine)
808     return gpg_error (GPG_ERR_INV_VALUE);
809
810   if (!engine->ops->getauditlog)
811     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
812
813   return (*engine->ops->getauditlog) (engine->engine, output, flags);
814 }
815
816
817 gpgme_error_t
818 _gpgme_engine_op_assuan_transact (engine_t engine,
819                                   const char *command,
820                                   gpgme_assuan_data_cb_t data_cb,
821                                   void *data_cb_value,
822                                   gpgme_assuan_inquire_cb_t inq_cb,
823                                   void *inq_cb_value,
824                                   gpgme_assuan_status_cb_t status_cb,
825                                   void *status_cb_value)
826 {
827   if (!engine)
828     return gpg_error (GPG_ERR_INV_VALUE);
829
830   if (!engine->ops->opassuan_transact)
831     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
832
833   return (*engine->ops->opassuan_transact) (engine->engine,
834                                             command,
835                                             data_cb, data_cb_value,
836                                             inq_cb, inq_cb_value,
837                                             status_cb, status_cb_value);
838 }
839
840
841 gpgme_error_t
842 _gpgme_engine_op_conf_load (engine_t engine, gpgme_conf_comp_t *conf_p)
843 {
844   if (!engine)
845     return gpg_error (GPG_ERR_INV_VALUE);
846
847   if (!engine->ops->conf_load)
848     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
849
850   return (*engine->ops->conf_load) (engine->engine, conf_p);
851 }
852
853
854 gpgme_error_t
855 _gpgme_engine_op_conf_save (engine_t engine, gpgme_conf_comp_t conf)
856 {
857   if (!engine)
858     return gpg_error (GPG_ERR_INV_VALUE);
859
860   if (!engine->ops->conf_save)
861     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
862
863   return (*engine->ops->conf_save) (engine->engine, conf);
864 }
865
866
867 void
868 _gpgme_engine_set_io_cbs (engine_t engine, gpgme_io_cbs_t io_cbs)
869 {
870   if (!engine)
871     return;
872
873   (*engine->ops->set_io_cbs) (engine->engine, io_cbs);
874 }
875
876
877 void
878 _gpgme_engine_io_event (engine_t engine,
879                         gpgme_event_io_t type, void *type_data)
880 {
881   if (!engine)
882     return;
883
884   (*engine->ops->io_event) (engine->engine, type, type_data);
885 }
886
887
888 /* Cancel the session and the pending operation if any.  */
889 gpgme_error_t
890 _gpgme_engine_cancel (engine_t engine)
891 {
892   if (!engine)
893     return gpg_error (GPG_ERR_INV_VALUE);
894
895   if (!engine->ops->cancel)
896     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
897
898   return (*engine->ops->cancel) (engine->engine);
899 }
900
901
902 /* Cancel the pending operation, but not the complete session.  */
903 gpgme_error_t
904 _gpgme_engine_cancel_op (engine_t engine)
905 {
906   if (!engine)
907     return gpg_error (GPG_ERR_INV_VALUE);
908
909   if (!engine->ops->cancel_op)
910     return 0;
911
912   return (*engine->ops->cancel_op) (engine->engine);
913 }
914
915
916 /* Change the passphrase for KEY.  */
917 gpgme_error_t
918 _gpgme_engine_op_passwd (engine_t engine, gpgme_key_t key,
919                          unsigned int flags)
920 {
921   if (!engine)
922     return gpg_error (GPG_ERR_INV_VALUE);
923
924   if (!engine->ops->passwd)
925     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
926
927   return (*engine->ops->passwd) (engine->engine, key, flags);
928 }
929
930
931 /* Set the pinentry mode for ENGINE to MODE.  */
932 gpgme_error_t
933 _gpgme_engine_set_pinentry_mode (engine_t engine, gpgme_pinentry_mode_t mode)
934 {
935   if (!engine)
936     return gpg_error (GPG_ERR_INV_VALUE);
937
938   if (!engine->ops->set_pinentry_mode)
939     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
940
941   return (*engine->ops->set_pinentry_mode) (engine->engine, mode);
942 }
943
944
945 gpgme_error_t
946 _gpgme_engine_op_spawn (engine_t engine,
947                         const char *file, const char *argv[],
948                         gpgme_data_t datain,
949                         gpgme_data_t dataout, gpgme_data_t dataerr,
950                         unsigned int flags)
951 {
952   if (!engine)
953     return gpg_error (GPG_ERR_INV_VALUE);
954
955   if (!engine->ops->opspawn)
956     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
957
958   return (*engine->ops->opspawn) (engine->engine, file, argv,
959                                   datain, dataout, dataerr, flags);
960 }