core: Remove cruft from the engine-gpg code.
[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 <https://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 /* If non-NULL, the minimal version required for all engines.  */
67 static char *engine_minimal_version;
68
69
70 \f
71 /* Get the file name of the engine for PROTOCOL.  */
72 static const char *
73 engine_get_file_name (gpgme_protocol_t proto)
74 {
75   if (proto > DIM (engine_ops))
76     return NULL;
77
78   if (engine_ops[proto] && engine_ops[proto]->get_file_name)
79     return (*engine_ops[proto]->get_file_name) ();
80   else
81     return NULL;
82 }
83
84
85 /* Get the standard home dir of the engine for PROTOCOL.  */
86 static const char *
87 engine_get_home_dir (gpgme_protocol_t proto)
88 {
89   if (proto > DIM (engine_ops))
90     return NULL;
91
92   if (engine_ops[proto] && engine_ops[proto]->get_home_dir)
93     return (*engine_ops[proto]->get_home_dir) ();
94   else
95     return NULL;
96 }
97
98
99 /* Get a malloced string containing the version number of the engine
100  * for PROTOCOL.  If this function returns NULL for a valid protocol,
101  * it should be assumed that the engine is a pseudo engine. */
102 static char *
103 engine_get_version (gpgme_protocol_t proto, const char *file_name)
104 {
105   if (proto > DIM (engine_ops))
106     return NULL;
107
108   if (engine_ops[proto] && engine_ops[proto]->get_version)
109     return (*engine_ops[proto]->get_version) (file_name);
110   else
111     return NULL;
112 }
113
114
115 /* Get the required version number of the engine for PROTOCOL.  This
116  * may be NULL. */
117 static const char *
118 engine_get_req_version (gpgme_protocol_t proto)
119 {
120   if (proto > DIM (engine_ops))
121     return NULL;
122
123   if (engine_ops[proto] && engine_ops[proto]->get_req_version)
124     return (*engine_ops[proto]->get_req_version) ();
125   else
126     return NULL;
127 }
128
129
130 /* Verify the version requirement for the engine for PROTOCOL.  */
131 gpgme_error_t
132 gpgme_engine_check_version (gpgme_protocol_t proto)
133 {
134   gpgme_error_t err;
135   gpgme_engine_info_t info;
136   int result;
137
138   LOCK (engine_info_lock);
139   info = engine_info;
140   if (!info)
141     {
142       /* Make sure it is initialized.  */
143       UNLOCK (engine_info_lock);
144       err = gpgme_get_engine_info (&info);
145       if (err)
146         return err;
147
148       LOCK (engine_info_lock);
149     }
150
151   while (info && info->protocol != proto)
152     info = info->next;
153
154   if (!info)
155     result = 0;
156   else
157     result = _gpgme_compare_versions (info->version,
158                                       info->req_version);
159
160   UNLOCK (engine_info_lock);
161   return result ? 0 : trace_gpg_error (GPG_ERR_INV_ENGINE);
162 }
163
164
165 /* Release the engine info INFO.  */
166 void
167 _gpgme_engine_info_release (gpgme_engine_info_t info)
168 {
169   while (info)
170     {
171       gpgme_engine_info_t next_info = info->next;
172
173       if (info->file_name)
174         free (info->file_name);
175       if (info->home_dir)
176         free (info->home_dir);
177       if (info->version)
178         free (info->version);
179       free (info);
180       info = next_info;
181     }
182 }
183
184
185 /* This is an internal function to set a mimimal required version.
186  * This function must only be called by gpgme_set_global_flag.
187  * Returns 0 on success.  */
188 int
189 _gpgme_set_engine_minimal_version (const char *value)
190 {
191   free (engine_minimal_version);
192   if (value)
193     {
194       engine_minimal_version = strdup (value);
195       return !engine_minimal_version;
196     }
197   else
198     {
199       engine_minimal_version = NULL;
200       return 0;
201     }
202 }
203
204
205 /* Get the information about the configured and installed engines.  A
206    pointer to the first engine in the statically allocated linked list
207    is returned in *INFO.  If an error occurs, it is returned.  The
208    returned data is valid until the next gpgme_set_engine_info.  */
209 gpgme_error_t
210 gpgme_get_engine_info (gpgme_engine_info_t *info)
211 {
212   gpgme_error_t err;
213
214   LOCK (engine_info_lock);
215   if (!engine_info)
216     {
217       gpgme_engine_info_t *lastp = &engine_info;
218       gpgme_protocol_t proto_list[] = { GPGME_PROTOCOL_OpenPGP,
219                                         GPGME_PROTOCOL_CMS,
220                                         GPGME_PROTOCOL_GPGCONF,
221                                         GPGME_PROTOCOL_ASSUAN,
222                                         GPGME_PROTOCOL_G13,
223                                         GPGME_PROTOCOL_UISERVER,
224                                         GPGME_PROTOCOL_SPAWN    };
225       unsigned int proto;
226
227       err = 0;
228       for (proto = 0; proto < DIM (proto_list); proto++)
229         {
230           const char *ofile_name = engine_get_file_name (proto_list[proto]);
231           const char *ohome_dir  = engine_get_home_dir (proto_list[proto]);
232           char *version = engine_get_version (proto_list[proto], NULL);
233           char *file_name;
234           char *home_dir;
235
236           if (!ofile_name)
237             continue;
238
239           file_name = strdup (ofile_name);
240           if (!file_name)
241             err = gpg_error_from_syserror ();
242
243           if (ohome_dir)
244             {
245               home_dir = strdup (ohome_dir);
246               if (!home_dir && !err)
247                 err = gpg_error_from_syserror ();
248             }
249           else
250             home_dir = NULL;
251
252           *lastp = calloc (1, sizeof (*engine_info));
253           if (!*lastp && !err)
254             err = gpg_error_from_syserror ();
255
256           /* Check against the optional minimal engine version.  */
257           if (!err && version && engine_minimal_version
258               && !_gpgme_compare_versions (version, engine_minimal_version))
259             {
260 #if GPG_ERROR_VERSION_NUMBER < 0x011900 /* 1.25 */
261               err = gpg_error (GPG_ERR_NO_ENGINE);
262 #else
263               err = gpg_error (GPG_ERR_ENGINE_TOO_OLD);
264 #endif
265             }
266
267           /* Now set the dummy version for pseudo engines.  */
268           if (!err && !version)
269             {
270               version = strdup ("1.0.0");
271               if (!version)
272                 err = gpg_error_from_syserror ();
273             }
274
275           if (err)
276             {
277               _gpgme_engine_info_release (engine_info);
278               engine_info = NULL;
279
280               if (file_name)
281                 free (file_name);
282               if (home_dir)
283                 free (home_dir);
284               if (version)
285                 free (version);
286
287               UNLOCK (engine_info_lock);
288               return err;
289             }
290
291           (*lastp)->protocol = proto_list[proto];
292           (*lastp)->file_name = file_name;
293           (*lastp)->home_dir = home_dir;
294           (*lastp)->version = version;
295           (*lastp)->req_version = engine_get_req_version (proto_list[proto]);
296           if (!(*lastp)->req_version)
297             (*lastp)->req_version = "1.0.0"; /* Dummy for pseudo engines. */
298           (*lastp)->next = NULL;
299           lastp = &(*lastp)->next;
300         }
301     }
302
303   *info = engine_info;
304   UNLOCK (engine_info_lock);
305   return 0;
306 }
307
308
309 /* Get a deep copy of the engine info and return it in INFO.  */
310 gpgme_error_t
311 _gpgme_engine_info_copy (gpgme_engine_info_t *r_info)
312 {
313   gpgme_error_t err = 0;
314   gpgme_engine_info_t info;
315   gpgme_engine_info_t new_info;
316   gpgme_engine_info_t *lastp;
317
318   LOCK (engine_info_lock);
319   info = engine_info;
320   if (!info)
321     {
322       /* Make sure it is initialized.  */
323       UNLOCK (engine_info_lock);
324       err = gpgme_get_engine_info (&info);
325       if (err)
326         return err;
327
328       LOCK (engine_info_lock);
329     }
330
331   new_info = NULL;
332   lastp = &new_info;
333
334   while (info)
335     {
336       char *file_name;
337       char *home_dir;
338       char *version;
339
340       assert (info->file_name);
341       file_name = strdup (info->file_name);
342       if (!file_name)
343         err = gpg_error_from_syserror ();
344
345       if (info->home_dir)
346         {
347           home_dir = strdup (info->home_dir);
348           if (!home_dir && !err)
349             err = gpg_error_from_syserror ();
350         }
351       else
352         home_dir = NULL;
353
354       if (info->version)
355         {
356           version = strdup (info->version);
357           if (!version && !err)
358             err = gpg_error_from_syserror ();
359         }
360       else
361         version = NULL;
362
363       *lastp = malloc (sizeof (*engine_info));
364       if (!*lastp && !err)
365         err = gpg_error_from_syserror ();
366
367       if (err)
368         {
369           _gpgme_engine_info_release (new_info);
370           if (file_name)
371             free (file_name);
372           if (home_dir)
373             free (home_dir);
374           if (version)
375             free (version);
376
377           UNLOCK (engine_info_lock);
378           return err;
379         }
380
381       (*lastp)->protocol = info->protocol;
382       (*lastp)->file_name = file_name;
383       (*lastp)->home_dir = home_dir;
384       (*lastp)->version = version;
385       (*lastp)->req_version = info->req_version;
386       (*lastp)->next = NULL;
387       lastp = &(*lastp)->next;
388
389       info = info->next;
390     }
391
392   *r_info = new_info;
393   UNLOCK (engine_info_lock);
394   return 0;
395 }
396
397
398 /* Set the engine info for the info list INFO, protocol PROTO, to the
399    file name FILE_NAME and the home directory HOME_DIR.  */
400 gpgme_error_t
401 _gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto,
402                         const char *file_name, const char *home_dir)
403 {
404   char *new_file_name;
405   char *new_home_dir;
406   char *new_version;
407
408   /* FIXME: Use some PROTO_MAX definition.  */
409   if (proto > DIM (engine_ops))
410     return gpg_error (GPG_ERR_INV_VALUE);
411
412   while (info && info->protocol != proto)
413     info = info->next;
414
415   if (!info)
416     return trace_gpg_error (GPG_ERR_INV_ENGINE);
417
418   /* Prepare new members.  */
419   if (file_name)
420     new_file_name = strdup (file_name);
421   else
422     {
423       const char *ofile_name = engine_get_file_name (proto);
424       assert (ofile_name);
425       new_file_name = strdup (ofile_name);
426     }
427   if (!new_file_name)
428     return gpg_error_from_syserror ();
429
430   if (home_dir)
431     {
432       new_home_dir = strdup (home_dir);
433       if (!new_home_dir)
434         {
435           free (new_file_name);
436           return gpg_error_from_syserror ();
437         }
438     }
439   else
440     {
441       const char *ohome_dir = engine_get_home_dir (proto);
442       if (ohome_dir)
443         {
444           new_home_dir = strdup (ohome_dir);
445           if (!new_home_dir)
446             {
447               free (new_file_name);
448               return gpg_error_from_syserror ();
449             }
450         }
451       else
452         new_home_dir = NULL;
453     }
454
455   new_version = engine_get_version (proto, new_file_name);
456   if (!new_version)
457     {
458       new_version = strdup ("1.0.0"); /* Fake one for dummy entries.  */
459       if (!new_version)
460         {
461           free (new_file_name);
462           free (new_home_dir);
463         }
464     }
465
466   /* Remove the old members.  */
467   assert (info->file_name);
468   free (info->file_name);
469   if (info->home_dir)
470     free (info->home_dir);
471   if (info->version)
472     free (info->version);
473
474   /* Install the new members.  */
475   info->file_name = new_file_name;
476   info->home_dir = new_home_dir;
477   info->version = new_version;
478
479   return 0;
480 }
481
482
483 /* Set the default engine info for the protocol PROTO to the file name
484    FILE_NAME and the home directory HOME_DIR.  */
485 gpgme_error_t
486 gpgme_set_engine_info (gpgme_protocol_t proto,
487                        const char *file_name, const char *home_dir)
488 {
489   gpgme_error_t err;
490   gpgme_engine_info_t info;
491
492   LOCK (engine_info_lock);
493   info = engine_info;
494   if (!info)
495     {
496       /* Make sure it is initialized.  */
497       UNLOCK (engine_info_lock);
498       err = gpgme_get_engine_info (&info);
499       if (err)
500         return err;
501
502       LOCK (engine_info_lock);
503     }
504
505   err = _gpgme_set_engine_info (info, proto, file_name, home_dir);
506   UNLOCK (engine_info_lock);
507   return err;
508 }
509
510 \f
511 gpgme_error_t
512 _gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine)
513 {
514   engine_t engine;
515
516   if (!info->file_name || !info->version)
517     return trace_gpg_error (GPG_ERR_INV_ENGINE);
518
519   engine = calloc (1, sizeof *engine);
520   if (!engine)
521     return gpg_error_from_syserror ();
522
523   engine->ops = engine_ops[info->protocol];
524   if (engine->ops->new)
525     {
526       gpgme_error_t err;
527       err = (*engine->ops->new) (&engine->engine,
528                                  info->file_name, info->home_dir,
529                                  info->version);
530       if (err)
531         {
532           free (engine);
533           return err;
534         }
535     }
536   else
537     engine->engine = NULL;
538
539   *r_engine = engine;
540   return 0;
541 }
542
543
544 gpgme_error_t
545 _gpgme_engine_reset (engine_t engine)
546 {
547   if (!engine)
548     return gpg_error (GPG_ERR_INV_VALUE);
549
550   if (!engine->ops->reset)
551     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
552
553   return (*engine->ops->reset) (engine->engine);
554 }
555
556
557 void
558 _gpgme_engine_release (engine_t engine)
559 {
560   if (!engine)
561     return;
562
563   if (engine->ops->release)
564     (*engine->ops->release) (engine->engine);
565   free (engine);
566 }
567
568
569 /* Set a status callback which is used to monitor the status values
570  * before they are passed to a handler set with
571  * _gpgme_engine_set_status_handler.  */
572 void
573 _gpgme_engine_set_status_cb (engine_t engine,
574                              gpgme_status_cb_t cb, void *cb_value)
575 {
576   if (!engine)
577     return;
578
579   if (engine->ops->set_status_cb)
580     (*engine->ops->set_status_cb) (engine->engine, cb, cb_value);
581 }
582
583
584 void
585 _gpgme_engine_set_status_handler (engine_t engine,
586                                   engine_status_handler_t fnc, void *fnc_value)
587 {
588   if (!engine)
589     return;
590
591   if (engine->ops->set_status_handler)
592     (*engine->ops->set_status_handler) (engine->engine, fnc, fnc_value);
593 }
594
595
596 gpgme_error_t
597 _gpgme_engine_set_command_handler (engine_t engine,
598                                    engine_command_handler_t fnc,
599                                    void *fnc_value)
600 {
601   if (!engine)
602     return gpg_error (GPG_ERR_INV_VALUE);
603
604   if (!engine->ops->set_command_handler)
605     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
606
607   return (*engine->ops->set_command_handler) (engine->engine, fnc, fnc_value);
608 }
609
610 gpgme_error_t
611 _gpgme_engine_set_colon_line_handler (engine_t engine,
612                                       engine_colon_line_handler_t fnc,
613                                       void *fnc_value)
614 {
615   if (!engine)
616     return gpg_error (GPG_ERR_INV_VALUE);
617
618   if (!engine->ops->set_colon_line_handler)
619     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
620
621   return (*engine->ops->set_colon_line_handler) (engine->engine,
622                                                  fnc, fnc_value);
623 }
624
625 gpgme_error_t
626 _gpgme_engine_set_locale (engine_t engine, int category,
627                           const char *value)
628 {
629   if (!engine)
630     return gpg_error (GPG_ERR_INV_VALUE);
631
632   if (!engine->ops->set_locale)
633     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
634
635   return (*engine->ops->set_locale) (engine->engine, category, value);
636 }
637
638
639 gpgme_error_t
640 _gpgme_engine_set_protocol (engine_t engine, gpgme_protocol_t protocol)
641 {
642   if (!engine)
643     return gpg_error (GPG_ERR_INV_VALUE);
644
645   if (!engine->ops->set_protocol)
646     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
647
648   return (*engine->ops->set_protocol) (engine->engine, protocol);
649 }
650
651
652 /* Pass information about the current context to the engine.  The
653  * engine may use this context to retrieve context specific flags.
654  * Important: The engine is required to immediately copy the required
655  * flags to its own context!
656  *
657  * This function will eventually be used to reduce the number of
658  * explicit passed flags.  */
659 void
660 _gpgme_engine_set_engine_flags (engine_t engine, gpgme_ctx_t ctx)
661 {
662   if (!engine)
663     return;
664
665   if (!engine->ops->set_engine_flags)
666     return;
667
668   (*engine->ops->set_engine_flags) (engine->engine, ctx);
669 }
670
671
672 gpgme_error_t
673 _gpgme_engine_op_decrypt (engine_t engine,
674                           gpgme_decrypt_flags_t flags,
675                           gpgme_data_t ciph,
676                           gpgme_data_t plain, int export_session_key,
677                           const char *override_session_key,
678                           int auto_key_retrieve)
679 {
680   if (!engine)
681     return gpg_error (GPG_ERR_INV_VALUE);
682
683   if (!engine->ops->decrypt)
684     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
685
686   return (*engine->ops->decrypt) (engine->engine, flags, ciph, plain,
687                                   export_session_key, override_session_key,
688                                   auto_key_retrieve);
689 }
690
691
692 gpgme_error_t
693 _gpgme_engine_op_delete (engine_t engine, gpgme_key_t key,
694                          unsigned int flags)
695 {
696   if (!engine)
697     return gpg_error (GPG_ERR_INV_VALUE);
698
699   if (!engine->ops->delete)
700     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
701
702   return (*engine->ops->delete) (engine->engine, key, flags);
703 }
704
705
706 gpgme_error_t
707 _gpgme_engine_op_edit (engine_t engine, int type, gpgme_key_t key,
708                        gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */)
709 {
710   if (!engine)
711     return gpg_error (GPG_ERR_INV_VALUE);
712
713   if (!engine->ops->edit)
714     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
715
716   return (*engine->ops->edit) (engine->engine, type, key, out, ctx);
717 }
718
719
720 gpgme_error_t
721 _gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[],
722                           const char *recpstring,
723                           gpgme_encrypt_flags_t flags,
724                           gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
725 {
726   if (!engine)
727     return gpg_error (GPG_ERR_INV_VALUE);
728
729   if (!engine->ops->encrypt)
730     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
731
732   return (*engine->ops->encrypt) (engine->engine, recp, recpstring,
733                                   flags, plain, ciph, use_armor);
734 }
735
736
737 gpgme_error_t
738 _gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[],
739                                const char *recpstring,
740                                gpgme_encrypt_flags_t flags,
741                                gpgme_data_t plain, gpgme_data_t ciph,
742                                int use_armor, gpgme_ctx_t ctx /* FIXME */)
743 {
744   if (!engine)
745     return gpg_error (GPG_ERR_INV_VALUE);
746
747   if (!engine->ops->encrypt_sign)
748     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
749
750   return (*engine->ops->encrypt_sign) (engine->engine, recp, recpstring,
751                                        flags, plain, ciph, use_armor, ctx);
752 }
753
754
755 gpgme_error_t
756 _gpgme_engine_op_export (engine_t engine, const char *pattern,
757                          gpgme_export_mode_t mode, gpgme_data_t keydata,
758                          int use_armor)
759 {
760   if (!engine)
761     return gpg_error (GPG_ERR_INV_VALUE);
762
763   if (!engine->ops->export)
764     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
765
766   return (*engine->ops->export) (engine->engine, pattern, mode,
767                                  keydata, use_armor);
768 }
769
770
771 gpgme_error_t
772 _gpgme_engine_op_export_ext (engine_t engine, const char *pattern[],
773                              unsigned int reserved, gpgme_data_t keydata,
774                              int use_armor)
775 {
776   if (!engine)
777     return gpg_error (GPG_ERR_INV_VALUE);
778
779   if (!engine->ops->export_ext)
780     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
781
782   return (*engine->ops->export_ext) (engine->engine, pattern, reserved,
783                                      keydata, use_armor);
784 }
785
786
787 gpgme_error_t
788 _gpgme_engine_op_genkey (engine_t engine,
789                          const char *userid, const char *algo,
790                          unsigned long reserved, unsigned long expires,
791                          gpgme_key_t key, unsigned int flags,
792                          gpgme_data_t help_data,
793                          unsigned int extraflags,
794                          gpgme_data_t pubkey, gpgme_data_t seckey)
795 {
796   if (!engine)
797     return gpg_error (GPG_ERR_INV_VALUE);
798
799   if (!engine->ops->genkey)
800     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
801
802   return (*engine->ops->genkey) (engine->engine,
803                                  userid, algo, reserved, expires, key, flags,
804                                  help_data, extraflags,
805                                  pubkey, seckey);
806 }
807
808
809 gpgme_error_t
810 _gpgme_engine_op_keysign (engine_t engine, gpgme_key_t key, const char *userid,
811                           unsigned long expires, unsigned int flags,
812                           gpgme_ctx_t ctx)
813 {
814   if (!engine)
815     return gpg_error (GPG_ERR_INV_VALUE);
816
817   if (!engine->ops->keysign)
818     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
819
820   return (*engine->ops->keysign) (engine->engine,
821                                   key, userid, expires, flags, ctx);
822 }
823
824
825 gpgme_error_t
826 _gpgme_engine_op_tofu_policy (engine_t engine,
827                               gpgme_key_t key,  gpgme_tofu_policy_t policy)
828 {
829   if (!engine)
830     return gpg_error (GPG_ERR_INV_VALUE);
831
832   if (!engine->ops->tofu_policy)
833     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
834
835   return (*engine->ops->tofu_policy) (engine->engine, key, policy);
836 }
837
838
839 gpgme_error_t
840 _gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata,
841                          gpgme_key_t *keyarray)
842 {
843   if (!engine)
844     return gpg_error (GPG_ERR_INV_VALUE);
845
846   if (!engine->ops->import)
847     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
848
849   return (*engine->ops->import) (engine->engine, keydata, keyarray);
850 }
851
852
853 gpgme_error_t
854 _gpgme_engine_op_keylist (engine_t engine, const char *pattern,
855                           int secret_only, gpgme_keylist_mode_t mode,
856                           int engine_flags)
857 {
858   if (!engine)
859     return gpg_error (GPG_ERR_INV_VALUE);
860
861   if (!engine->ops->keylist)
862     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
863
864   return (*engine->ops->keylist) (engine->engine, pattern, secret_only, mode,
865                                   engine_flags);
866 }
867
868
869 gpgme_error_t
870 _gpgme_engine_op_keylist_ext (engine_t engine, const char *pattern[],
871                               int secret_only, int reserved,
872                               gpgme_keylist_mode_t mode, int engine_flags)
873 {
874   if (!engine)
875     return gpg_error (GPG_ERR_INV_VALUE);
876
877   if (!engine->ops->keylist_ext)
878     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
879
880   return (*engine->ops->keylist_ext) (engine->engine, pattern, secret_only,
881                                       reserved, mode, engine_flags);
882 }
883
884
885 gpgme_error_t
886 _gpgme_engine_op_keylist_data (engine_t engine, gpgme_data_t data)
887 {
888   if (!engine)
889     return gpg_error (GPG_ERR_INV_VALUE);
890
891   if (!engine->ops->keylist_data)
892     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
893
894   return (*engine->ops->keylist_data) (engine->engine, data);
895 }
896
897
898 gpgme_error_t
899 _gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_data_t out,
900                        gpgme_sig_mode_t mode, int use_armor,
901                        int use_textmode, int include_certs,
902                        gpgme_ctx_t ctx /* FIXME */)
903 {
904   if (!engine)
905     return gpg_error (GPG_ERR_INV_VALUE);
906
907   if (!engine->ops->sign)
908     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
909
910   return (*engine->ops->sign) (engine->engine, in, out, mode, use_armor,
911                                use_textmode, include_certs, ctx);
912 }
913
914
915 gpgme_error_t
916 _gpgme_engine_op_trustlist (engine_t engine, const char *pattern)
917 {
918   if (!engine)
919     return gpg_error (GPG_ERR_INV_VALUE);
920
921   if (!engine->ops->trustlist)
922     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
923
924   return (*engine->ops->trustlist) (engine->engine, pattern);
925 }
926
927
928 gpgme_error_t
929 _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
930                          gpgme_data_t signed_text, gpgme_data_t plaintext,
931                          gpgme_ctx_t ctx)
932 {
933   if (!engine)
934     return gpg_error (GPG_ERR_INV_VALUE);
935
936   if (!engine->ops->verify)
937     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
938
939   return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext,
940                                  ctx);
941 }
942
943
944 gpgme_error_t
945 _gpgme_engine_op_getauditlog (engine_t engine, gpgme_data_t output,
946                               unsigned int flags)
947 {
948   if (!engine)
949     return gpg_error (GPG_ERR_INV_VALUE);
950
951   if (!engine->ops->getauditlog)
952     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
953
954   return (*engine->ops->getauditlog) (engine->engine, output, flags);
955 }
956
957
958 gpgme_error_t
959 _gpgme_engine_op_assuan_transact (engine_t engine,
960                                   const char *command,
961                                   gpgme_assuan_data_cb_t data_cb,
962                                   void *data_cb_value,
963                                   gpgme_assuan_inquire_cb_t inq_cb,
964                                   void *inq_cb_value,
965                                   gpgme_assuan_status_cb_t status_cb,
966                                   void *status_cb_value)
967 {
968   if (!engine)
969     return gpg_error (GPG_ERR_INV_VALUE);
970
971   if (!engine->ops->opassuan_transact)
972     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
973
974   return (*engine->ops->opassuan_transact) (engine->engine,
975                                             command,
976                                             data_cb, data_cb_value,
977                                             inq_cb, inq_cb_value,
978                                             status_cb, status_cb_value);
979 }
980
981
982 gpgme_error_t
983 _gpgme_engine_op_conf_load (engine_t engine, gpgme_conf_comp_t *conf_p)
984 {
985   if (!engine)
986     return gpg_error (GPG_ERR_INV_VALUE);
987
988   if (!engine->ops->conf_load)
989     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
990
991   return (*engine->ops->conf_load) (engine->engine, conf_p);
992 }
993
994
995 gpgme_error_t
996 _gpgme_engine_op_conf_save (engine_t engine, gpgme_conf_comp_t conf)
997 {
998   if (!engine)
999     return gpg_error (GPG_ERR_INV_VALUE);
1000
1001   if (!engine->ops->conf_save)
1002     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1003
1004   return (*engine->ops->conf_save) (engine->engine, conf);
1005 }
1006
1007
1008 gpgme_error_t
1009 _gpgme_engine_op_conf_dir (engine_t engine, const char *what, char **result)
1010 {
1011   if (!engine)
1012     return gpg_error (GPG_ERR_INV_VALUE);
1013
1014   if (!engine->ops->conf_dir)
1015     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1016
1017   return (*engine->ops->conf_dir) (engine->engine, what, result);
1018 }
1019
1020
1021 gpgme_error_t
1022 _gpgme_engine_op_query_swdb (engine_t engine,
1023                              const char *name, const char *iversion,
1024                              gpgme_query_swdb_result_t result)
1025 {
1026   if (!engine)
1027     return gpg_error (GPG_ERR_INV_VALUE);
1028
1029   if (!engine->ops->query_swdb)
1030     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1031
1032   return (*engine->ops->query_swdb) (engine->engine, name, iversion, result);
1033 }
1034
1035
1036 void
1037 _gpgme_engine_set_io_cbs (engine_t engine, gpgme_io_cbs_t io_cbs)
1038 {
1039   if (!engine)
1040     return;
1041
1042   (*engine->ops->set_io_cbs) (engine->engine, io_cbs);
1043 }
1044
1045
1046 void
1047 _gpgme_engine_io_event (engine_t engine,
1048                         gpgme_event_io_t type, void *type_data)
1049 {
1050   if (!engine)
1051     return;
1052
1053   (*engine->ops->io_event) (engine->engine, type, type_data);
1054 }
1055
1056
1057 /* Cancel the session and the pending operation if any.  */
1058 gpgme_error_t
1059 _gpgme_engine_cancel (engine_t engine)
1060 {
1061   if (!engine)
1062     return gpg_error (GPG_ERR_INV_VALUE);
1063
1064   if (!engine->ops->cancel)
1065     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1066
1067   return (*engine->ops->cancel) (engine->engine);
1068 }
1069
1070
1071 /* Cancel the pending operation, but not the complete session.  */
1072 gpgme_error_t
1073 _gpgme_engine_cancel_op (engine_t engine)
1074 {
1075   if (!engine)
1076     return gpg_error (GPG_ERR_INV_VALUE);
1077
1078   if (!engine->ops->cancel_op)
1079     return 0;
1080
1081   return (*engine->ops->cancel_op) (engine->engine);
1082 }
1083
1084
1085 /* Change the passphrase for KEY.  */
1086 gpgme_error_t
1087 _gpgme_engine_op_passwd (engine_t engine, gpgme_key_t key,
1088                          unsigned int flags)
1089 {
1090   if (!engine)
1091     return gpg_error (GPG_ERR_INV_VALUE);
1092
1093   if (!engine->ops->passwd)
1094     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1095
1096   return (*engine->ops->passwd) (engine->engine, key, flags);
1097 }
1098
1099
1100 /* Set the pinentry mode for ENGINE to MODE.  */
1101 gpgme_error_t
1102 _gpgme_engine_set_pinentry_mode (engine_t engine, gpgme_pinentry_mode_t mode)
1103 {
1104   if (!engine)
1105     return gpg_error (GPG_ERR_INV_VALUE);
1106
1107   if (!engine->ops->set_pinentry_mode)
1108     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1109
1110   return (*engine->ops->set_pinentry_mode) (engine->engine, mode);
1111 }
1112
1113
1114 gpgme_error_t
1115 _gpgme_engine_op_spawn (engine_t engine,
1116                         const char *file, const char *argv[],
1117                         gpgme_data_t datain,
1118                         gpgme_data_t dataout, gpgme_data_t dataerr,
1119                         unsigned int flags)
1120 {
1121   if (!engine)
1122     return gpg_error (GPG_ERR_INV_VALUE);
1123
1124   if (!engine->ops->opspawn)
1125     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1126
1127   return (*engine->ops->opspawn) (engine->engine, file, argv,
1128                                   datain, dataout, dataerr, flags);
1129 }