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