core: Make the status-fd monitor work for all gpgsm commands.
[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                                    gpgme_data_t linked_data)
601 {
602   if (!engine)
603     return gpg_error (GPG_ERR_INV_VALUE);
604
605   if (!engine->ops->set_command_handler)
606     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
607
608   return (*engine->ops->set_command_handler) (engine->engine,
609                                               fnc, fnc_value, linked_data);
610 }
611
612 gpgme_error_t
613 _gpgme_engine_set_colon_line_handler (engine_t engine,
614                                       engine_colon_line_handler_t fnc,
615                                       void *fnc_value)
616 {
617   if (!engine)
618     return gpg_error (GPG_ERR_INV_VALUE);
619
620   if (!engine->ops->set_colon_line_handler)
621     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
622
623   return (*engine->ops->set_colon_line_handler) (engine->engine,
624                                                  fnc, fnc_value);
625 }
626
627 gpgme_error_t
628 _gpgme_engine_set_locale (engine_t engine, int category,
629                           const char *value)
630 {
631   if (!engine)
632     return gpg_error (GPG_ERR_INV_VALUE);
633
634   if (!engine->ops->set_locale)
635     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
636
637   return (*engine->ops->set_locale) (engine->engine, category, value);
638 }
639
640
641 gpgme_error_t
642 _gpgme_engine_set_protocol (engine_t engine, gpgme_protocol_t protocol)
643 {
644   if (!engine)
645     return gpg_error (GPG_ERR_INV_VALUE);
646
647   if (!engine->ops->set_protocol)
648     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
649
650   return (*engine->ops->set_protocol) (engine->engine, protocol);
651 }
652
653
654 /* Pass information about the current context to the engine.  The
655  * engine may use this context to retrieve context specific flags.
656  * Important: The engine is required to immediately copy the required
657  * flags to its own context!
658  *
659  * This function will eventually be used to reduce the number of
660  * explicit passed flags.  */
661 void
662 _gpgme_engine_set_engine_flags (engine_t engine, gpgme_ctx_t ctx)
663 {
664   if (!engine)
665     return;
666
667   if (!engine->ops->set_engine_flags)
668     return;
669
670   (*engine->ops->set_engine_flags) (engine->engine, ctx);
671 }
672
673
674 gpgme_error_t
675 _gpgme_engine_op_decrypt (engine_t engine,
676                           gpgme_decrypt_flags_t flags,
677                           gpgme_data_t ciph,
678                           gpgme_data_t plain, int export_session_key,
679                           const char *override_session_key,
680                           int auto_key_retrieve)
681 {
682   if (!engine)
683     return gpg_error (GPG_ERR_INV_VALUE);
684
685   if (!engine->ops->decrypt)
686     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
687
688   return (*engine->ops->decrypt) (engine->engine, flags, ciph, plain,
689                                   export_session_key, override_session_key,
690                                   auto_key_retrieve);
691 }
692
693
694 gpgme_error_t
695 _gpgme_engine_op_delete (engine_t engine, gpgme_key_t key,
696                          unsigned int flags)
697 {
698   if (!engine)
699     return gpg_error (GPG_ERR_INV_VALUE);
700
701   if (!engine->ops->delete)
702     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
703
704   return (*engine->ops->delete) (engine->engine, key, flags);
705 }
706
707
708 gpgme_error_t
709 _gpgme_engine_op_edit (engine_t engine, int type, gpgme_key_t key,
710                        gpgme_data_t out, gpgme_ctx_t ctx /* FIXME */)
711 {
712   if (!engine)
713     return gpg_error (GPG_ERR_INV_VALUE);
714
715   if (!engine->ops->edit)
716     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
717
718   return (*engine->ops->edit) (engine->engine, type, key, out, ctx);
719 }
720
721
722 gpgme_error_t
723 _gpgme_engine_op_encrypt (engine_t engine, gpgme_key_t recp[],
724                           const char *recpstring,
725                           gpgme_encrypt_flags_t flags,
726                           gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
727 {
728   if (!engine)
729     return gpg_error (GPG_ERR_INV_VALUE);
730
731   if (!engine->ops->encrypt)
732     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
733
734   return (*engine->ops->encrypt) (engine->engine, recp, recpstring,
735                                   flags, plain, ciph, use_armor);
736 }
737
738
739 gpgme_error_t
740 _gpgme_engine_op_encrypt_sign (engine_t engine, gpgme_key_t recp[],
741                                const char *recpstring,
742                                gpgme_encrypt_flags_t flags,
743                                gpgme_data_t plain, gpgme_data_t ciph,
744                                int use_armor, gpgme_ctx_t ctx /* FIXME */)
745 {
746   if (!engine)
747     return gpg_error (GPG_ERR_INV_VALUE);
748
749   if (!engine->ops->encrypt_sign)
750     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
751
752   return (*engine->ops->encrypt_sign) (engine->engine, recp, recpstring,
753                                        flags, plain, ciph, use_armor, ctx);
754 }
755
756
757 gpgme_error_t
758 _gpgme_engine_op_export (engine_t engine, const char *pattern,
759                          gpgme_export_mode_t mode, gpgme_data_t keydata,
760                          int use_armor)
761 {
762   if (!engine)
763     return gpg_error (GPG_ERR_INV_VALUE);
764
765   if (!engine->ops->export)
766     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
767
768   return (*engine->ops->export) (engine->engine, pattern, mode,
769                                  keydata, use_armor);
770 }
771
772
773 gpgme_error_t
774 _gpgme_engine_op_export_ext (engine_t engine, const char *pattern[],
775                              unsigned int reserved, gpgme_data_t keydata,
776                              int use_armor)
777 {
778   if (!engine)
779     return gpg_error (GPG_ERR_INV_VALUE);
780
781   if (!engine->ops->export_ext)
782     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
783
784   return (*engine->ops->export_ext) (engine->engine, pattern, reserved,
785                                      keydata, use_armor);
786 }
787
788
789 gpgme_error_t
790 _gpgme_engine_op_genkey (engine_t engine,
791                          const char *userid, const char *algo,
792                          unsigned long reserved, unsigned long expires,
793                          gpgme_key_t key, unsigned int flags,
794                          gpgme_data_t help_data,
795                          unsigned int extraflags,
796                          gpgme_data_t pubkey, gpgme_data_t seckey)
797 {
798   if (!engine)
799     return gpg_error (GPG_ERR_INV_VALUE);
800
801   if (!engine->ops->genkey)
802     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
803
804   return (*engine->ops->genkey) (engine->engine,
805                                  userid, algo, reserved, expires, key, flags,
806                                  help_data, extraflags,
807                                  pubkey, seckey);
808 }
809
810
811 gpgme_error_t
812 _gpgme_engine_op_keysign (engine_t engine, gpgme_key_t key, const char *userid,
813                           unsigned long expires, unsigned int flags,
814                           gpgme_ctx_t ctx)
815 {
816   if (!engine)
817     return gpg_error (GPG_ERR_INV_VALUE);
818
819   if (!engine->ops->keysign)
820     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
821
822   return (*engine->ops->keysign) (engine->engine,
823                                   key, userid, expires, flags, ctx);
824 }
825
826
827 gpgme_error_t
828 _gpgme_engine_op_tofu_policy (engine_t engine,
829                               gpgme_key_t key,  gpgme_tofu_policy_t policy)
830 {
831   if (!engine)
832     return gpg_error (GPG_ERR_INV_VALUE);
833
834   if (!engine->ops->tofu_policy)
835     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
836
837   return (*engine->ops->tofu_policy) (engine->engine, key, policy);
838 }
839
840
841 gpgme_error_t
842 _gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata,
843                          gpgme_key_t *keyarray)
844 {
845   if (!engine)
846     return gpg_error (GPG_ERR_INV_VALUE);
847
848   if (!engine->ops->import)
849     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
850
851   return (*engine->ops->import) (engine->engine, keydata, keyarray);
852 }
853
854
855 gpgme_error_t
856 _gpgme_engine_op_keylist (engine_t engine, const char *pattern,
857                           int secret_only, gpgme_keylist_mode_t mode,
858                           int engine_flags)
859 {
860   if (!engine)
861     return gpg_error (GPG_ERR_INV_VALUE);
862
863   if (!engine->ops->keylist)
864     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
865
866   return (*engine->ops->keylist) (engine->engine, pattern, secret_only, mode,
867                                   engine_flags);
868 }
869
870
871 gpgme_error_t
872 _gpgme_engine_op_keylist_ext (engine_t engine, const char *pattern[],
873                               int secret_only, int reserved,
874                               gpgme_keylist_mode_t mode, int engine_flags)
875 {
876   if (!engine)
877     return gpg_error (GPG_ERR_INV_VALUE);
878
879   if (!engine->ops->keylist_ext)
880     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
881
882   return (*engine->ops->keylist_ext) (engine->engine, pattern, secret_only,
883                                       reserved, mode, engine_flags);
884 }
885
886
887 gpgme_error_t
888 _gpgme_engine_op_keylist_data (engine_t engine, gpgme_data_t data)
889 {
890   if (!engine)
891     return gpg_error (GPG_ERR_INV_VALUE);
892
893   if (!engine->ops->keylist_data)
894     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
895
896   return (*engine->ops->keylist_data) (engine->engine, data);
897 }
898
899
900 gpgme_error_t
901 _gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_data_t out,
902                        gpgme_sig_mode_t mode, int use_armor,
903                        int use_textmode, int include_certs,
904                        gpgme_ctx_t ctx /* FIXME */)
905 {
906   if (!engine)
907     return gpg_error (GPG_ERR_INV_VALUE);
908
909   if (!engine->ops->sign)
910     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
911
912   return (*engine->ops->sign) (engine->engine, in, out, mode, use_armor,
913                                use_textmode, include_certs, ctx);
914 }
915
916
917 gpgme_error_t
918 _gpgme_engine_op_trustlist (engine_t engine, const char *pattern)
919 {
920   if (!engine)
921     return gpg_error (GPG_ERR_INV_VALUE);
922
923   if (!engine->ops->trustlist)
924     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
925
926   return (*engine->ops->trustlist) (engine->engine, pattern);
927 }
928
929
930 gpgme_error_t
931 _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
932                          gpgme_data_t signed_text, gpgme_data_t plaintext,
933                          gpgme_ctx_t ctx)
934 {
935   if (!engine)
936     return gpg_error (GPG_ERR_INV_VALUE);
937
938   if (!engine->ops->verify)
939     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
940
941   return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext,
942                                  ctx);
943 }
944
945
946 gpgme_error_t
947 _gpgme_engine_op_getauditlog (engine_t engine, gpgme_data_t output,
948                               unsigned int flags)
949 {
950   if (!engine)
951     return gpg_error (GPG_ERR_INV_VALUE);
952
953   if (!engine->ops->getauditlog)
954     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
955
956   return (*engine->ops->getauditlog) (engine->engine, output, flags);
957 }
958
959
960 gpgme_error_t
961 _gpgme_engine_op_assuan_transact (engine_t engine,
962                                   const char *command,
963                                   gpgme_assuan_data_cb_t data_cb,
964                                   void *data_cb_value,
965                                   gpgme_assuan_inquire_cb_t inq_cb,
966                                   void *inq_cb_value,
967                                   gpgme_assuan_status_cb_t status_cb,
968                                   void *status_cb_value)
969 {
970   if (!engine)
971     return gpg_error (GPG_ERR_INV_VALUE);
972
973   if (!engine->ops->opassuan_transact)
974     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
975
976   return (*engine->ops->opassuan_transact) (engine->engine,
977                                             command,
978                                             data_cb, data_cb_value,
979                                             inq_cb, inq_cb_value,
980                                             status_cb, status_cb_value);
981 }
982
983
984 gpgme_error_t
985 _gpgme_engine_op_conf_load (engine_t engine, gpgme_conf_comp_t *conf_p)
986 {
987   if (!engine)
988     return gpg_error (GPG_ERR_INV_VALUE);
989
990   if (!engine->ops->conf_load)
991     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
992
993   return (*engine->ops->conf_load) (engine->engine, conf_p);
994 }
995
996
997 gpgme_error_t
998 _gpgme_engine_op_conf_save (engine_t engine, gpgme_conf_comp_t conf)
999 {
1000   if (!engine)
1001     return gpg_error (GPG_ERR_INV_VALUE);
1002
1003   if (!engine->ops->conf_save)
1004     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1005
1006   return (*engine->ops->conf_save) (engine->engine, conf);
1007 }
1008
1009
1010 gpgme_error_t
1011 _gpgme_engine_op_conf_dir (engine_t engine, const char *what, char **result)
1012 {
1013   if (!engine)
1014     return gpg_error (GPG_ERR_INV_VALUE);
1015
1016   if (!engine->ops->conf_dir)
1017     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1018
1019   return (*engine->ops->conf_dir) (engine->engine, what, result);
1020 }
1021
1022
1023 gpgme_error_t
1024 _gpgme_engine_op_query_swdb (engine_t engine,
1025                              const char *name, const char *iversion,
1026                              gpgme_query_swdb_result_t result)
1027 {
1028   if (!engine)
1029     return gpg_error (GPG_ERR_INV_VALUE);
1030
1031   if (!engine->ops->query_swdb)
1032     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1033
1034   return (*engine->ops->query_swdb) (engine->engine, name, iversion, result);
1035 }
1036
1037
1038 void
1039 _gpgme_engine_set_io_cbs (engine_t engine, gpgme_io_cbs_t io_cbs)
1040 {
1041   if (!engine)
1042     return;
1043
1044   (*engine->ops->set_io_cbs) (engine->engine, io_cbs);
1045 }
1046
1047
1048 void
1049 _gpgme_engine_io_event (engine_t engine,
1050                         gpgme_event_io_t type, void *type_data)
1051 {
1052   if (!engine)
1053     return;
1054
1055   (*engine->ops->io_event) (engine->engine, type, type_data);
1056 }
1057
1058
1059 /* Cancel the session and the pending operation if any.  */
1060 gpgme_error_t
1061 _gpgme_engine_cancel (engine_t engine)
1062 {
1063   if (!engine)
1064     return gpg_error (GPG_ERR_INV_VALUE);
1065
1066   if (!engine->ops->cancel)
1067     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1068
1069   return (*engine->ops->cancel) (engine->engine);
1070 }
1071
1072
1073 /* Cancel the pending operation, but not the complete session.  */
1074 gpgme_error_t
1075 _gpgme_engine_cancel_op (engine_t engine)
1076 {
1077   if (!engine)
1078     return gpg_error (GPG_ERR_INV_VALUE);
1079
1080   if (!engine->ops->cancel_op)
1081     return 0;
1082
1083   return (*engine->ops->cancel_op) (engine->engine);
1084 }
1085
1086
1087 /* Change the passphrase for KEY.  */
1088 gpgme_error_t
1089 _gpgme_engine_op_passwd (engine_t engine, gpgme_key_t key,
1090                          unsigned int flags)
1091 {
1092   if (!engine)
1093     return gpg_error (GPG_ERR_INV_VALUE);
1094
1095   if (!engine->ops->passwd)
1096     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1097
1098   return (*engine->ops->passwd) (engine->engine, key, flags);
1099 }
1100
1101
1102 /* Set the pinentry mode for ENGINE to MODE.  */
1103 gpgme_error_t
1104 _gpgme_engine_set_pinentry_mode (engine_t engine, gpgme_pinentry_mode_t mode)
1105 {
1106   if (!engine)
1107     return gpg_error (GPG_ERR_INV_VALUE);
1108
1109   if (!engine->ops->set_pinentry_mode)
1110     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1111
1112   return (*engine->ops->set_pinentry_mode) (engine->engine, mode);
1113 }
1114
1115
1116 gpgme_error_t
1117 _gpgme_engine_op_spawn (engine_t engine,
1118                         const char *file, const char *argv[],
1119                         gpgme_data_t datain,
1120                         gpgme_data_t dataout, gpgme_data_t dataerr,
1121                         unsigned int flags)
1122 {
1123   if (!engine)
1124     return gpg_error (GPG_ERR_INV_VALUE);
1125
1126   if (!engine->ops->opspawn)
1127     return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1128
1129   return (*engine->ops->opspawn) (engine->engine, file, argv,
1130                                   datain, dataout, dataerr, flags);
1131 }