doc: Fix documentation of struct data types
[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   };
59
60
61 /* The engine info.  */
62 static gpgme_engine_info_t engine_info;
63 DEFINE_STATIC_LOCK (engine_info_lock);
64
65 \f
66 /* Get the file name of the engine for PROTOCOL.  */
67 static const char *
68 engine_get_file_name (gpgme_protocol_t proto)
69 {
70   if (proto > DIM (engine_ops))
71     return NULL;
72
73   if (engine_ops[proto] && engine_ops[proto]->get_file_name)
74     return (*engine_ops[proto]->get_file_name) ();
75   else
76     return NULL;
77 }
78
79
80 /* Get the standard home dir of the engine for PROTOCOL.  */
81 static const char *
82 engine_get_home_dir (gpgme_protocol_t proto)
83 {
84   if (proto > DIM (engine_ops))
85     return NULL;
86
87   if (engine_ops[proto] && engine_ops[proto]->get_home_dir)
88     return (*engine_ops[proto]->get_home_dir) ();
89   else
90     return NULL;
91 }
92
93
94 /* Get a malloced string containing the version number of the engine
95    for PROTOCOL.  */
96 static char *
97 engine_get_version (gpgme_protocol_t proto, const char *file_name)
98 {
99   if (proto > DIM (engine_ops))
100     return NULL;
101
102   if (engine_ops[proto] && engine_ops[proto]->get_version)
103     return (*engine_ops[proto]->get_version) (file_name);
104   else
105     return NULL;
106 }
107
108
109 /* Get the required version number of the engine for PROTOCOL.  */
110 static const char *
111 engine_get_req_version (gpgme_protocol_t proto)
112 {
113   if (proto > DIM (engine_ops))
114     return NULL;
115
116   if (engine_ops[proto] && engine_ops[proto]->get_req_version)
117     return (*engine_ops[proto]->get_req_version) ();
118   else
119     return NULL;
120 }
121
122
123 /* Verify the version requirement for the engine for PROTOCOL.  */
124 gpgme_error_t
125 gpgme_engine_check_version (gpgme_protocol_t proto)
126 {
127   gpgme_error_t err;
128   gpgme_engine_info_t info;
129   int result;
130
131   LOCK (engine_info_lock);
132   info = engine_info;
133   if (!info)
134     {
135       /* Make sure it is initialized.  */
136       UNLOCK (engine_info_lock);
137       err = gpgme_get_engine_info (&info);
138       if (err)
139         return err;
140
141       LOCK (engine_info_lock);
142     }
143
144   while (info && info->protocol != proto)
145     info = info->next;
146
147   if (!info)
148     result = 0;
149   else
150     result = _gpgme_compare_versions (info->version,
151                                       info->req_version);
152
153   UNLOCK (engine_info_lock);
154   return result ? 0 : trace_gpg_error (GPG_ERR_INV_ENGINE);
155 }
156
157
158 /* Release the engine info INFO.  */
159 void
160 _gpgme_engine_info_release (gpgme_engine_info_t info)
161 {
162   while (info)
163     {
164       gpgme_engine_info_t next_info = info->next;
165
166       assert (info->file_name);
167       free (info->file_name);
168       if (info->home_dir)
169         free (info->home_dir);
170       if (info->version)
171         free (info->version);
172       free (info);
173       info = next_info;
174     }
175 }
176
177
178 /* Get the information about the configured and installed engines.  A
179    pointer to the first engine in the statically allocated linked list
180    is returned in *INFO.  If an error occurs, it is returned.  The
181    returned data is valid until the next gpgme_set_engine_info.  */
182 gpgme_error_t
183 gpgme_get_engine_info (gpgme_engine_info_t *info)
184 {
185   gpgme_error_t err;
186
187   LOCK (engine_info_lock);
188   if (!engine_info)
189     {
190       gpgme_engine_info_t *lastp = &engine_info;
191       gpgme_protocol_t proto_list[] = { GPGME_PROTOCOL_OpenPGP,
192                                         GPGME_PROTOCOL_CMS,
193                                         GPGME_PROTOCOL_GPGCONF,
194                                         GPGME_PROTOCOL_ASSUAN,
195                                         GPGME_PROTOCOL_G13,
196                                         GPGME_PROTOCOL_UISERVER };
197       unsigned int proto;
198
199       err = 0;
200       for (proto = 0; proto < DIM (proto_list); proto++)
201         {
202           const char *ofile_name = engine_get_file_name (proto_list[proto]);
203           const char *ohome_dir  = engine_get_home_dir (proto_list[proto]);
204           char *file_name;
205           char *home_dir;
206
207           if (!ofile_name)
208             continue;
209
210           file_name = strdup (ofile_name);
211           if (!file_name)
212             err = gpg_error_from_syserror ();
213
214           if (ohome_dir)
215             {
216               home_dir = strdup (ohome_dir);
217               if (!home_dir && !err)
218                 err = gpg_error_from_syserror ();
219             }
220           else
221             home_dir = NULL;
222
223           *lastp = malloc (sizeof (*engine_info));
224           if (!*lastp && !err)
225             err = gpg_error_from_syserror ();
226
227           if (err)
228             {
229               _gpgme_engine_info_release (engine_info);
230               engine_info = NULL;
231
232               if (file_name)
233                 free (file_name);
234               if (home_dir)
235                 free (home_dir);
236
237               UNLOCK (engine_info_lock);
238               return err;
239             }
240
241           (*lastp)->protocol = proto_list[proto];
242           (*lastp)->file_name = file_name;
243           (*lastp)->home_dir = home_dir;
244           (*lastp)->version = engine_get_version (proto_list[proto], NULL);
245           (*lastp)->req_version = engine_get_req_version (proto_list[proto]);
246           (*lastp)->next = NULL;
247           lastp = &(*lastp)->next;
248         }
249     }
250
251   *info = engine_info;
252   UNLOCK (engine_info_lock);
253   return 0;
254 }
255
256
257 /* Get a deep copy of the engine info and return it in INFO.  */
258 gpgme_error_t
259 _gpgme_engine_info_copy (gpgme_engine_info_t *r_info)
260 {
261   gpgme_error_t err = 0;
262   gpgme_engine_info_t info;
263   gpgme_engine_info_t new_info;
264   gpgme_engine_info_t *lastp;
265
266   LOCK (engine_info_lock);
267   info = engine_info;
268   if (!info)
269     {
270       /* Make sure it is initialized.  */
271       UNLOCK (engine_info_lock);
272       err = gpgme_get_engine_info (&info);
273       if (err)
274         return err;
275
276       LOCK (engine_info_lock);
277     }
278
279   new_info = NULL;
280   lastp = &new_info;
281
282   while (info)
283     {
284       char *file_name;
285       char *home_dir;
286       char *version;
287
288       assert (info->file_name);
289       file_name = strdup (info->file_name);
290       if (!file_name)
291         err = gpg_error_from_syserror ();
292
293       if (info->home_dir)
294         {
295           home_dir = strdup (info->home_dir);
296           if (!home_dir && !err)
297             err = gpg_error_from_syserror ();
298         }
299       else
300         home_dir = NULL;
301
302       if (info->version)
303         {
304           version = strdup (info->version);
305           if (!version && !err)
306             err = gpg_error_from_syserror ();
307         }
308       else
309         version = NULL;
310
311       *lastp = malloc (sizeof (*engine_info));
312       if (!*lastp && !err)
313         err = gpg_error_from_syserror ();
314
315       if (err)
316         {
317           _gpgme_engine_info_release (new_info);
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 err;
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_syserror ();
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_syserror ();
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_syserror ();
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_syserror ();
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
926
927 /* Set the pinentry mode for ENGINE to MODE.  */
928 gpgme_error_t
929 _gpgme_engine_set_pinentry_mode (engine_t engine, gpgme_pinentry_mode_t mode)
930 {
931   if (!engine)
932     return gpg_error (GPG_ERR_INV_VALUE);
933
934   if (!engine->ops->set_pinentry_mode)
935     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
936
937   return (*engine->ops->set_pinentry_mode) (engine->engine, mode);
938 }