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