doc/
[gpgme.git] / gpgme / keylist.c
1 /* keylist.c - Listing keys.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003 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 General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (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    General Public License for more details.
16  
17    You should have received a copy of the GNU General Public License
18    along with GPGME; if not, write to the Free Software Foundation,
19    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #if HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <time.h>
28 #include <assert.h>
29 #include <ctype.h>
30
31 #include "util.h"
32 #include "context.h"
33 #include "ops.h"
34 #include "key.h"
35
36 \f
37 struct keylist_result_s
38 {
39   int truncated;
40   GpgmeData xmlinfo;
41 };
42
43
44 void
45 _gpgme_release_keylist_result (KeylistResult result)
46 {
47   if (!result)
48     return;
49   free (result);
50 }
51
52
53 /* Append some XML info.  args is currently ignore but we might want
54    to add more information in the future (like source of the
55    keylisting.  With args of NULL the XML structure is closed.  */
56 static void
57 append_xml_keylistinfo (GpgmeData *rdh, char *args)
58 {
59   GpgmeData dh;
60
61   if (!*rdh)
62     {
63       if (gpgme_data_new (rdh))
64         return; /* FIXME: We are ignoring out-of-core.  */
65       dh = *rdh;
66       _gpgme_data_append_string (dh, "<GnupgOperationInfo>\n");
67     }
68   else
69     {
70       dh = *rdh;
71       _gpgme_data_append_string (dh, "  </keylisting>\n");
72     }
73
74   if (!args)
75     {
76       /* Just close the XML containter.  */
77       _gpgme_data_append_string (dh, "</GnupgOperationInfo>\n");
78       return;
79     }
80
81   _gpgme_data_append_string (dh, "  <keylisting>\n    <truncated/>\n");
82     
83 }
84
85
86 static GpgmeError
87 keylist_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
88 {
89   test_and_allocate_result (ctx, keylist);
90
91   switch (code)
92     {
93     case GPGME_STATUS_TRUNCATED:
94       ctx->result.keylist->truncated = 1;
95       break;
96
97     case GPGME_STATUS_EOF:
98       if (ctx->result.keylist->truncated)
99         append_xml_keylistinfo (&ctx->result.keylist->xmlinfo, "1");
100       if (ctx->result.keylist->xmlinfo)
101         {
102           append_xml_keylistinfo (&ctx->result.keylist->xmlinfo, NULL);
103           _gpgme_set_op_info (ctx, ctx->result.keylist->xmlinfo);
104           ctx->result.keylist->xmlinfo = NULL;
105         }
106       break;
107
108     default:
109       break;
110     }
111   return 0;
112 }
113
114 \f
115 static time_t
116 parse_timestamp (char *timestamp)
117 {
118   if (!*timestamp)
119     return 0;
120
121   return (time_t) strtoul (timestamp, NULL, 10);
122 }
123
124
125 static void
126 set_mainkey_trust_info (GpgmeKey key, const char *src)
127 {
128   /* Look at letters and stop at the first digit.  */
129   while (*src && !isdigit (*src))
130     {
131       switch (*src)
132         {
133         case 'e':
134           key->keys.flags.expired = 1;
135           break;
136
137         case 'r':
138           key->keys.flags.revoked = 1;
139           break;
140
141         case 'd':
142           /* Note that gpg 1.3 won't print that anymore but only uses
143              the capabilities field. */
144           key->keys.flags.disabled = 1;
145           break;
146
147         case 'i':
148           key->keys.flags.invalid = 1;
149           break;
150         }
151       src++;
152     }
153 }
154
155
156 static void
157 set_userid_flags (GpgmeKey key, const char *src)
158 {
159   struct user_id_s *uid = key->last_uid;
160
161   assert (uid);
162   /* Look at letters and stop at the first digit.  */
163   while (*src && !isdigit (*src))
164     {
165       switch (*src)
166         {
167         case 'r':
168           uid->revoked = 1;
169           break;
170           
171         case 'i':
172           uid->invalid = 1;
173           break;
174
175         case 'n':
176           uid->validity = GPGME_VALIDITY_NEVER;
177           break;
178
179         case 'm':
180           uid->validity = GPGME_VALIDITY_MARGINAL;
181           break;
182
183         case 'f':
184           uid->validity = GPGME_VALIDITY_FULL;
185           break;
186
187         case 'u':
188           uid->validity = GPGME_VALIDITY_ULTIMATE;
189           break;
190         }
191       src++;
192     }
193 }
194
195
196 static void
197 set_subkey_trust_info (struct subkey_s *subkey, const char *src)
198 {
199   /* Look at letters and stop at the first digit.  */
200   while (*src && !isdigit (*src))
201     {
202       switch (*src)
203         {
204         case 'e':
205           subkey->flags.expired = 1;
206           break;
207
208         case 'r':
209           subkey->flags.revoked = 1;
210           break;
211
212         case 'd':
213           subkey->flags.disabled = 1;
214           break;
215
216         case 'i':
217           subkey->flags.invalid = 1;
218           break;
219         }
220       src++;
221     }
222 }
223
224
225 static void
226 set_mainkey_capability (GpgmeKey key, const char *src)
227 {
228   while (*src)
229     {
230       switch (*src)
231         {
232         case 'e':
233           key->keys.flags.can_encrypt = 1;
234           break;
235
236         case 's':
237           key->keys.flags.can_sign = 1;
238           break;
239
240         case 'c':
241           key->keys.flags.can_certify = 1;
242           break;
243
244         case 'd':
245         case 'D':
246           /* Note, that this flag is also set using the key validity
247              field for backward compatibility with gpg 1.2.  We use d
248              and D, so that a future gpg version will be able to
249              disable certain subkeys. Currently it is expected that
250              gpg sets this for the primary key. */
251           key->keys.flags.disabled = 1;
252           break;
253
254         case 'E':
255           key->gloflags.can_encrypt = 1;
256           break;
257
258         case 'S':
259           key->gloflags.can_sign = 1;
260           break;
261
262         case 'C':
263           key->gloflags.can_certify = 1;
264           break;
265         }
266       src++;
267     }
268 }
269
270
271 static void
272 set_subkey_capability (struct subkey_s *subkey, const char *src)
273 {
274   while (*src)
275     {
276       switch (*src)
277         {
278         case 'e':
279           subkey->flags.can_encrypt = 1;
280           break;
281
282         case 's':
283           subkey->flags.can_sign = 1;
284           break;
285
286         case 'c':
287           subkey->flags.can_certify = 1;
288           break;
289         }
290       src++;
291     }
292 }
293
294 static void
295 set_ownertrust (GpgmeKey key, const char *src)
296 {
297   /* Look at letters and stop at the first digit.  */
298   while (*src && !isdigit (*src))
299     {
300       switch (*src)
301         {
302         case 'n':
303           key->otrust = GPGME_VALIDITY_NEVER;
304           break;
305
306         case 'm':
307           key->otrust = GPGME_VALIDITY_MARGINAL;
308           break;
309
310         case 'f':
311           key->otrust = GPGME_VALIDITY_FULL;
312           break;
313
314         case 'u':
315           key->otrust = GPGME_VALIDITY_ULTIMATE;
316           break;
317
318         default:
319           key->otrust = GPGME_VALIDITY_UNKNOWN;
320           break;
321         }
322       src++;
323     }
324 }
325
326
327 /* We have read an entire key into ctx->tmp_key and should now finish
328    it.  It is assumed that this releases ctx->tmp_key.  */
329 static void
330 finish_key (GpgmeCtx ctx)
331 {
332   GpgmeKey key = ctx->tmp_key;
333
334   ctx->tmp_key = NULL;
335
336   if (key)
337     _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_KEY, key);
338 }
339
340
341 /* Note: We are allowed to modify LINE.  */
342 static GpgmeError
343 keylist_colon_handler (GpgmeCtx ctx, char *line)
344 {
345   enum
346     {
347       RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR, RT_SSB, RT_SEC,
348       RT_CRT, RT_CRS, RT_REV
349     }
350   rectype = RT_NONE;
351 #define NR_FIELDS 13
352   char *field[NR_FIELDS];
353   int fields = 0;
354   GpgmeKey key = ctx->tmp_key;
355   struct subkey_s *subkey = NULL;
356   struct certsig_s *certsig = NULL;
357
358   DEBUG3 ("keylist_colon_handler ctx = %p, key = %p, line = %s\n",
359           ctx, key, line ? line : "(null)");
360
361   if (!line)
362     {
363       /* End Of File.  */
364       finish_key (ctx);
365       return 0;
366     }
367
368   while (line && fields < NR_FIELDS)
369     {
370       field[fields++] = line;
371       line = strchr (line, ':');
372       if (line)
373         *(line++) = '\0';
374     }
375
376   if (!strcmp (field[0], "sig"))
377     rectype = RT_SIG;
378   else if (!strcmp (field[0], "rev"))
379     rectype = RT_REV;
380   else if (!strcmp (field[0], "uid") && key)
381     rectype = RT_UID;
382   else if (!strcmp (field[0], "sub") && key)
383     {
384       /* Start a new subkey.  */
385       rectype = RT_SUB; 
386       if (!(subkey = _gpgme_key_add_subkey (key)))
387         return GPGME_Out_Of_Core;
388     }
389   else if (!strcmp (field[0], "ssb") && key)
390     {
391       /* Start a new secret subkey.  */
392       rectype = RT_SSB;
393       if (!(subkey = _gpgme_key_add_secret_subkey (key)))
394         return GPGME_Out_Of_Core;
395     }
396   else if (!strcmp (field[0], "pub"))
397     {
398       /* Start a new keyblock.  */
399       if (_gpgme_key_new (&key))
400         /* The only kind of error we can get.  */
401         return GPGME_Out_Of_Core;
402       rectype = RT_PUB;
403       finish_key (ctx);
404       assert (!ctx->tmp_key);
405       ctx->tmp_key = key;
406     }
407   else if (!strcmp (field[0], "sec"))
408     {
409       /* Start a new keyblock,  */
410       if (_gpgme_key_new_secret (&key))
411         return GPGME_Out_Of_Core;
412       rectype = RT_SEC;
413       finish_key (ctx);
414       assert (!ctx->tmp_key);
415       ctx->tmp_key = key;
416     }
417   else if (!strcmp (field[0], "crt"))
418     {
419       /* Start a new certificate.  */
420       if (_gpgme_key_new (&key))
421         return GPGME_Out_Of_Core;
422       key->x509 = 1;
423       rectype = RT_CRT;
424       finish_key (ctx);
425       assert (!ctx->tmp_key);
426       ctx->tmp_key = key;
427     }
428   else if (!strcmp (field[0], "crs"))
429     {
430       /* Start a new certificate.  */
431       if (_gpgme_key_new_secret (&key))
432         return GPGME_Out_Of_Core;
433       key->x509 = 1;
434       rectype = RT_CRS;
435       finish_key (ctx);
436       assert (!ctx->tmp_key);
437       ctx->tmp_key = key;
438     }
439   else if (!strcmp (field[0], "fpr") && key) 
440     rectype = RT_FPR;
441   else 
442     rectype = RT_NONE;
443
444   /* Only look at signatures immediately following a user ID.  For
445      this, clear the user ID pointer when encountering anything but a
446      signature.  */
447   if (rectype != RT_SIG && rectype != RT_REV)
448     ctx->tmp_uid = NULL;
449
450   switch (rectype)
451     {
452     case RT_CRT:
453     case RT_CRS:
454       /* Field 8 has the X.509 serial number.  */
455       if (fields >= 8)
456         {
457           key->issuer_serial = strdup (field[7]);
458           if (!key->issuer_serial)
459             return GPGME_Out_Of_Core;
460         }
461
462       /* Field 10 is not used for gpg due to --fixed-list-mode option
463          but GPGSM stores the issuer name.  */
464       if (fields >= 10 && _gpgme_decode_c_string (field[9],
465                                                   &key->issuer_name, 0))
466         return GPGME_Out_Of_Core;
467       /* Fall through!  */
468
469     case RT_PUB:
470     case RT_SEC:
471       /* Field 2 has the trust info.  */
472       if (fields >= 2)
473         set_mainkey_trust_info (key, field[1]);
474
475       /* Field 3 has the key length.  */
476       if (fields >= 3)
477         {
478           int i = atoi (field[2]);
479           /* Ignore invalid values.  */
480           if (i > 1)
481             key->keys.key_len = i; 
482         }
483
484       /* Field 4 has the public key algorithm.  */
485       if (fields >= 4)
486         {
487           int i = atoi (field[3]);
488           if (i >= 1 && i < 128)
489             key->keys.key_algo = i;
490         }
491
492       /* Field 5 has the long keyid.  */
493       if (fields >= 5 && strlen (field[4]) == DIM(key->keys.keyid) - 1)
494         strcpy (key->keys.keyid, field[4]);
495
496       /* Field 6 has the timestamp (seconds).  */
497       if (fields >= 6)
498         key->keys.timestamp = parse_timestamp (field[5]);
499
500       /* Field 7 has the expiration time (seconds).  */
501       if (fields >= 7)
502         key->keys.expires_at = parse_timestamp (field[6]);
503
504       /* Field 9 has the ownertrust.  */
505       if (fields >= 9)
506         set_ownertrust (key, field[8]);
507
508       /* Field 11 has the signature class.  */
509
510       /* Field 12 has the capabilities.  */
511       if (fields >= 12)
512         set_mainkey_capability (key, field[11]);
513       break;
514
515     case RT_SUB:
516     case RT_SSB:
517       /* Field 2 has the trust info.  */
518       if (fields >= 2)
519         set_subkey_trust_info (subkey, field[1]);
520
521       /* Field 3 has the key length.  */
522       if (fields >= 3)
523         {
524           int i = atoi (field[2]);
525           /* Ignore invalid values.  */
526           if (i > 1)
527             subkey->key_len = i;
528         }
529
530       /* Field 4 has the public key algorithm.  */
531       if (fields >= 4)
532         {
533           int i = atoi (field[3]);
534           if (i >= 1 && i < 128)
535             subkey->key_algo = i;
536         }
537
538       /* Field 5 has the long keyid.  */
539       if (fields >= 5 && strlen (field[4]) == DIM(subkey->keyid) - 1)
540         strcpy (subkey->keyid, field[4]);
541
542       /* Field 6 has the timestamp (seconds).  */
543       if (fields >= 6)
544         subkey->timestamp = parse_timestamp (field[5]);
545
546       /* Field 7 has the expiration time (seconds).  */
547       if (fields >= 7)
548         subkey->expires_at = parse_timestamp (field[6]);
549
550       /* Field 8 is reserved (LID).  */
551       /* Field 9 has the ownertrust.  */
552       /* Field 10, the user ID, is n/a for a subkey.  */
553       
554       /* Field 11 has the signature class.  */
555
556       /* Field 12 has the capabilities.  */
557       if (fields >= 12)
558         set_subkey_capability (subkey, field[11]);
559       break;
560
561     case RT_UID:
562       /* Field 2 has the trust info, and field 10 has the user ID.  */
563       if (fields >= 10)
564         {
565           if (_gpgme_key_append_name (key, field[9]))
566             return GPGME_Out_Of_Core;
567           else
568             {
569               if (field[1])
570                 set_userid_flags (key, field[1]);
571               ctx->tmp_uid = key->last_uid;
572             }
573         }
574       break;
575
576     case RT_FPR:
577       /* Field 10 has the fingerprint (take only the first one).  */
578       if (fields >= 10 && !key->keys.fingerprint && field[9] && *field[9])
579         {
580           key->keys.fingerprint = strdup (field[9]);
581           if (!key->keys.fingerprint)
582             return GPGME_Out_Of_Core;
583         }
584
585       /* Field 13 has the gpgsm chain ID (take only the first one).  */
586       if (fields >= 13 && !key->chain_id && *field[12])
587         {
588           key->chain_id = strdup (field[12]);
589           if (!key->chain_id)
590             return GPGME_Out_Of_Core;
591         }
592       break;
593
594     case RT_SIG:
595     case RT_REV:
596       if (!ctx->tmp_uid)
597         return 0;
598
599       /* Start a new (revoked) signature.  */
600       assert (ctx->tmp_uid == key->last_uid);
601       certsig = _gpgme_key_add_certsig (key, (fields >= 10) ? field[9] : NULL);
602       if (!certsig)
603         return GPGME_Out_Of_Core;
604
605       /* Field 2 has the calculated trust ('!', '-', '?', '%').  */
606       if (fields >= 2)
607         switch (field[1][0])
608           {
609           case '!':
610             certsig->sig_stat = GPGME_SIG_STAT_GOOD;
611             break;
612
613           case '-':
614             certsig->sig_stat = GPGME_SIG_STAT_BAD;
615             break;
616
617           case '?':
618             certsig->sig_stat = GPGME_SIG_STAT_NOKEY;
619             break;
620
621           case '%':
622             certsig->sig_stat = GPGME_SIG_STAT_ERROR;
623             break;
624
625           default:
626             certsig->sig_stat = GPGME_SIG_STAT_NONE;
627             break;
628           }
629
630       /* Field 4 has the public key algorithm.  */
631       if (fields >= 4)
632         {
633           int i = atoi (field[3]);
634           if (i >= 1 && i < 128)
635             certsig->algo = i;
636         }
637       
638       /* Field 5 has the long keyid.  */
639       if (fields >= 5 && strlen (field[4]) == DIM(certsig->keyid) - 1)
640         strcpy (certsig->keyid, field[4]);
641       
642       /* Field 6 has the timestamp (seconds).  */
643       if (fields >= 6)
644         certsig->timestamp = parse_timestamp (field[5]);
645
646       /* Field 7 has the expiration time (seconds).  */
647       if (fields >= 7)
648         certsig->expires_at = parse_timestamp (field[6]);
649
650       /* Field 11 has the signature class (eg, 0x30 means revoked).  */
651       if (fields >= 11)
652         if (field[10][0] && field[10][1])
653           {
654             int class = _gpgme_hextobyte (field[10]);
655             if (class >= 0)
656               {
657                 certsig->sig_class = class;
658                 if (class == 0x30)
659                   certsig->flags.revoked = 1;
660               }
661             if (field[10][2] == 'x')
662               certsig->flags.exportable = 1;
663           }
664       break;
665
666     case RT_NONE:
667       /* Unknown record.  */
668       break;
669     }
670   return 0;
671 }
672
673
674 void
675 _gpgme_op_keylist_event_cb (void *data, GpgmeEventIO type, void *type_data)
676 {
677   GpgmeCtx ctx = (GpgmeCtx) data;
678   GpgmeKey key = (GpgmeKey) type_data;
679   struct key_queue_item_s *q, *q2;
680
681   assert (type == GPGME_EVENT_NEXT_KEY);
682
683   _gpgme_key_cache_add (key);
684
685   q = malloc (sizeof *q);
686   if (!q)
687     {
688       gpgme_key_release (key);
689       /* FIXME       return GPGME_Out_Of_Core; */
690       return;
691     }
692   q->key = key;
693   q->next = NULL;
694   /* FIXME: Lock queue.  Use a tail pointer?  */
695   if (!(q2 = ctx->key_queue))
696     ctx->key_queue = q;
697   else
698     {
699       for (; q2->next; q2 = q2->next)
700         ;
701       q2->next = q;
702     }
703   ctx->key_cond = 1;
704   /* FIXME: Unlock queue.  */
705 }
706
707
708 /**
709  * gpgme_op_keylist_start:
710  * @c: context 
711  * @pattern: a GnuPG user ID or NULL for all
712  * @secret_only: List only keys where the secret part is available
713  * 
714  * Note that this function also cancels a pending key listing
715  * operaton. To actually retrieve the key, use
716  * gpgme_op_keylist_next().
717  * 
718  * Return value:  0 on success or an errorcode. 
719  **/
720 GpgmeError
721 gpgme_op_keylist_start (GpgmeCtx ctx, const char *pattern, int secret_only)
722 {
723   GpgmeError err = 0;
724
725   err = _gpgme_op_reset (ctx, 2);
726   if (err)
727     goto leave;
728
729   gpgme_key_release (ctx->tmp_key);
730   ctx->tmp_key = NULL;
731   /* Fixme: Release key_queue.  */
732
733   _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
734   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
735                                               keylist_colon_handler, ctx);
736   if (err)
737     goto leave;
738
739   /* We don't want to use the verbose mode as this will also print the
740      key signatures which is in most cases not needed and furthermore
741      we just ignore those lines - This should speed up things.  */
742   _gpgme_engine_set_verbosity (ctx->engine, 0);
743
744   err = _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
745                                   ctx->keylist_mode);
746
747  leave:
748   if (err)
749     {
750       ctx->pending = 0; 
751       _gpgme_engine_release (ctx->engine);
752       ctx->engine = NULL;
753     }
754   return err;
755 }
756
757
758 /**
759  * gpgme_op_keylist_ext_start:
760  * @c: context 
761  * @pattern: a NULL terminated array of search patterns
762  * @secret_only: List only keys where the secret part is available
763  * @reserved: Should be 0.
764  * 
765  * Note that this function also cancels a pending key listing
766  * operaton. To actually retrieve the key, use
767  * gpgme_op_keylist_next().
768  * 
769  * Return value:  0 on success or an errorcode. 
770  **/
771 GpgmeError
772 gpgme_op_keylist_ext_start (GpgmeCtx ctx, const char *pattern[],
773                             int secret_only, int reserved)
774 {
775   GpgmeError err = 0;
776
777   err = _gpgme_op_reset (ctx, 2);
778   if (err)
779     goto leave;
780
781   gpgme_key_release (ctx->tmp_key);
782   ctx->tmp_key = NULL;
783
784   _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
785   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
786                                               keylist_colon_handler, ctx);
787   if (err)
788     goto leave;
789
790   /* We don't want to use the verbose mode as this will also print the
791      key signatures which is in most cases not needed and furthermore
792      we just ignore those lines - This should speed up things.  */
793   _gpgme_engine_set_verbosity (ctx->engine, 0);
794
795   err = _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
796                                       reserved, ctx->keylist_mode);
797
798  leave:
799   if (err)
800     {
801       ctx->pending = 0; 
802       _gpgme_engine_release (ctx->engine);
803       ctx->engine = NULL;
804     }
805   return err;
806 }
807
808
809 /**
810  * gpgme_op_keylist_next:
811  * @c: Context
812  * @r_key: Returned key object
813  * 
814  * Return the next key from the key listing started with
815  * gpgme_op_keylist_start().  The caller must free the key using
816  * gpgme_key_release().  If the last key has already been returned the
817  * last time the function was called, %GPGME_EOF is returned and the
818  * operation is finished.
819  * 
820  * Return value: 0 on success, %GPGME_EOF or another error code.
821  **/
822 GpgmeError
823 gpgme_op_keylist_next (GpgmeCtx ctx, GpgmeKey *r_key)
824 {
825   struct key_queue_item_s *queue_item;
826
827   if (!r_key)
828     return GPGME_Invalid_Value;
829   *r_key = NULL;
830   if (!ctx)
831     return GPGME_Invalid_Value;
832   if (!ctx->pending)
833     return GPGME_No_Request;
834
835   if (!ctx->key_queue)
836     {
837       GpgmeError err = _gpgme_wait_on_condition (ctx, &ctx->key_cond);
838       if (err)
839         {
840           ctx->pending = 0;
841           return err;
842         }
843       if (!ctx->pending)
844         {
845           /* The operation finished.  Because not all keys might have
846              been returned to the caller yet, we just reset the
847              pending flag to 1.  This will cause us to call
848              _gpgme_wait_on_condition without any active file
849              descriptors, but that is a no-op, so it is safe.  */
850           ctx->pending = 1;
851         }
852       if (!ctx->key_cond)
853         {
854           ctx->pending = 0;
855           return GPGME_EOF;
856         }
857       ctx->key_cond = 0; 
858       assert (ctx->key_queue);
859     }
860   queue_item = ctx->key_queue;
861   ctx->key_queue = queue_item->next;
862   if (!ctx->key_queue)
863     ctx->key_cond = 0;
864   
865   *r_key = queue_item->key;
866   free (queue_item);
867   return 0;
868 }
869
870
871 /**
872  * gpgme_op_keylist_end:
873  * @c: Context
874  * 
875  * Ends the keylist operation and allows to use the context for some
876  * other operation next.
877  **/
878 GpgmeError
879 gpgme_op_keylist_end (GpgmeCtx ctx)
880 {
881   if (!ctx)
882     return GPGME_Invalid_Value;
883   if (!ctx->pending)
884     return GPGME_No_Request;
885
886   ctx->pending = 0;
887   return 0;
888 }