1 /* app.c - Application selection.
2 * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <https://www.gnu.org/licenses/>.
29 #include "app-common.h"
34 static npth_mutex_t app_list_lock;
38 print_progress_line (void *opaque, const char *what, int pc, int cur, int tot)
45 snprintf (line, sizeof line, "%s %c %d %d", what, pc, cur, tot);
46 send_status_direct (ctrl, "PROGRESS", line);
51 /* Lock the reader SLOT. This function shall be used right before
52 calling any of the actual application functions to serialize access
53 to the reader. We do this always even if the reader is not
54 actually used. This allows an actual connection to assume that it
55 never shares a reader (while performing one command). Returns 0 on
56 success; only then the unlock_reader function must be called after
57 returning from the handler. */
59 lock_app (app_t app, ctrl_t ctrl)
61 if (npth_mutex_lock (&app->lock))
63 gpg_error_t err = gpg_error_from_syserror ();
64 log_error ("failed to acquire APP lock for %p: %s\n",
65 app, gpg_strerror (err));
69 apdu_set_progress_cb (app->slot, print_progress_line, ctrl);
74 /* Release a lock on the reader. See lock_reader(). */
76 unlock_app (app_t app)
78 apdu_set_progress_cb (app->slot, NULL, NULL);
80 if (npth_mutex_unlock (&app->lock))
82 gpg_error_t err = gpg_error_from_syserror ();
83 log_error ("failed to release APP lock for %p: %s\n",
84 app, gpg_strerror (err));
89 /* This function may be called to print information pertaining to the
90 current state of this module to the log. */
96 npth_mutex_lock (&app_list_lock);
97 for (a = app_top; a; a = a->next)
98 log_info ("app_dump_state: app=%p type='%s'\n", a, a->apptype);
99 npth_mutex_unlock (&app_list_lock);
102 /* Check wether the application NAME is allowed. This does not mean
103 we have support for it though. */
105 is_app_allowed (const char *name)
109 for (l=opt.disabled_applications; l; l = l->next)
110 if (!strcmp (l->d, name))
117 check_conflict (app_t app, const char *name)
119 if (!app || !name || (app->apptype && !ascii_strcasecmp (app->apptype, name)))
122 log_info ("application '%s' in use - can't switch\n",
123 app->apptype? app->apptype : "<null>");
125 return gpg_error (GPG_ERR_CONFLICT);
128 /* This function is used by the serialno command to check for an
129 application conflict which may appear if the serialno command is
130 used to request a specific application and the connection has
131 already done a select_application. */
133 check_application_conflict (const char *name, app_t app)
135 return check_conflict (app, name);
140 release_application_internal (app_t app)
143 log_bug ("trying to release an already released context\n");
149 app_reset (app_t app, ctrl_t ctrl, int send_reset)
153 err = lock_app (app, ctrl);
159 int sw = apdu_reset (app->slot);
161 err = gpg_error (GPG_ERR_CARD_RESET);
163 /* Release the same application which is used by other sessions. */
164 send_client_notifications (app, 1);
168 ctrl->app_ctx = NULL;
169 release_application_internal (app);
177 app_new_register (int slot, ctrl_t ctrl, const char *name)
181 unsigned char *result = NULL;
185 /* Need to allocate a new one. */
186 app = xtrycalloc (1, sizeof *app);
189 err = gpg_error_from_syserror ();
190 log_info ("error allocating context: %s\n", gpg_strerror (err));
195 app->card_status = (unsigned int)-1;
197 if (npth_mutex_init (&app->lock, NULL))
199 err = gpg_error_from_syserror ();
200 log_error ("error initializing mutex: %s\n", gpg_strerror (err));
205 err = lock_app (app, ctrl);
212 want_undefined = (name && !strcmp (name, "undefined"));
214 /* Try to read the GDO file first to get a default serial number.
215 We skip this if the undefined application has been requested. */
218 err = iso7816_select_file (slot, 0x3F00, 1, NULL, NULL);
220 err = iso7816_select_file (slot, 0x2F02, 0, NULL, NULL);
222 err = iso7816_read_binary (slot, 0, 0, &result, &resultlen);
226 const unsigned char *p;
228 p = find_tlv_unchecked (result, resultlen, 0x5A, &n);
230 resultlen -= (p-result);
231 if (p && n > resultlen && n == 0x0d && resultlen+1 == n)
233 /* The object it does not fit into the buffer. This is an
234 invalid encoding (or the buffer is too short. However, I
235 have some test cards with such an invalid encoding and
236 therefore I use this ugly workaround to return something
237 I can further experiment with. */
238 log_info ("enabling BMI testcard workaround\n");
242 if (p && n <= resultlen)
244 /* The GDO file is pretty short, thus we simply reuse it for
245 storing the serial number. */
246 memmove (result, p, n);
247 app->serialno = result;
248 app->serialnolen = n;
249 err = app_munge_serialno (app);
259 /* For certain error codes, there is no need to try more. */
260 if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT
261 || gpg_err_code (err) == GPG_ERR_ENODEV)
264 /* Figure out the application to use. */
267 /* We switch to the "undefined" application only if explicitly
269 app->apptype = "UNDEFINED";
273 err = gpg_error (GPG_ERR_NOT_FOUND);
275 if (err && is_app_allowed ("openpgp")
276 && (!name || !strcmp (name, "openpgp")))
277 err = app_select_openpgp (app);
278 if (err && is_app_allowed ("nks") && (!name || !strcmp (name, "nks")))
279 err = app_select_nks (app);
280 if (err && is_app_allowed ("p15") && (!name || !strcmp (name, "p15")))
281 err = app_select_p15 (app);
282 if (err && is_app_allowed ("geldkarte")
283 && (!name || !strcmp (name, "geldkarte")))
284 err = app_select_geldkarte (app);
285 if (err && is_app_allowed ("dinsig") && (!name || !strcmp (name, "dinsig")))
286 err = app_select_dinsig (app);
287 if (err && is_app_allowed ("sc-hsm") && (!name || !strcmp (name, "sc-hsm")))
288 err = app_select_sc_hsm (app);
289 if (err && name && gpg_err_code (err) != GPG_ERR_OBJ_TERM_STATE)
290 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
296 log_info ("can't select application '%s': %s\n",
297 name, gpg_strerror (err));
299 log_info ("no supported card application found: %s\n",
306 app->require_get_status = 1; /* For token, this can be 0. */
308 npth_mutex_lock (&app_list_lock);
311 npth_mutex_unlock (&app_list_lock);
316 /* If called with NAME as NULL, select the best fitting application
317 and return a context; otherwise select the application with NAME
318 and return a context. Returns an error code and stores NULL at
319 R_APP if no application was found or no card is present. */
321 select_application (ctrl_t ctrl, const char *name, app_t *r_app,
322 int scan, const unsigned char *serialno_bin,
323 size_t serialno_bin_len)
330 if (scan || !app_top)
334 err = apdu_dev_list_start (opt.reader_port, &l);
343 slot = apdu_open_reader (l, !app_top);
348 sw = apdu_connect (slot);
350 if (sw == SW_HOST_CARD_INACTIVE)
353 sw = apdu_reset (slot);
356 if (!sw || sw == SW_HOST_ALREADY_CONNECTED)
358 else if (sw == SW_HOST_NO_CARD)
359 err = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
361 err = gpg_error (GPG_ERR_ENODEV);
364 err = app_new_register (slot, ctrl, name);
367 /* We close a reader with no card. */
368 apdu_close_reader (slot);
372 apdu_dev_list_finish (l);
375 npth_mutex_lock (&app_list_lock);
376 for (a = app_top; a; a = a->next)
379 if (serialno_bin == NULL)
381 if (a->serialnolen == serialno_bin_len
382 && !memcmp (a->serialno, serialno_bin, a->serialnolen))
389 err = check_conflict (a, name);
398 err = gpg_error (GPG_ERR_ENODEV);
400 npth_mutex_unlock (&app_list_lock);
407 get_supported_applications (void)
409 const char *list[] = {
416 /* Note: "undefined" is not listed here because it needs special
417 treatment by the client. */
424 for (nbytes=1, idx=0; list[idx]; idx++)
425 nbytes += strlen (list[idx]) + 1 + 1;
427 buffer = xtrymalloc (nbytes);
431 for (p=buffer, idx=0; list[idx]; idx++)
432 if (is_app_allowed (list[idx]))
433 p = stpcpy (stpcpy (p, list[idx]), ":\n");
440 /* Deallocate the application. */
442 deallocate_app (app_t app)
444 app_t a, a_prev = NULL;
446 for (a = app_top; a; a = a->next)
452 a_prev->next = a->next;
459 log_error ("trying to release context used yet (%d)\n", app->ref_count);
463 app->fnc.deinit (app);
464 app->fnc.deinit = NULL;
467 xfree (app->serialno);
471 /* Free the resources associated with the application APP. APP is
472 allowed to be NULL in which case this is a no-op. Note that we are
473 using reference counting to track the users of the application and
474 actually deferring the deallocation to allow for a later reuse by
477 release_application (app_t app)
482 /* We don't deallocate app here. Instead, we keep it. This is
483 useful so that a card does not get reset even if only one session
484 is using the card - this way the PIN cache and other cached data
487 lock_app (app, NULL);
488 release_application_internal (app);
494 /* The serial number may need some cosmetics. Do it here. This
495 function shall only be called once after a new serial number has
496 been put into APP->serialno.
500 FF 00 00 = For serial numbers starting with an FF
501 FF 01 00 = Some german p15 cards return an empty serial number so the
502 serial number from the EF(TokenInfo) is used instead.
503 FF 7F 00 = No serialno.
505 All other serial number not starting with FF are used as they are.
508 app_munge_serialno (app_t app)
510 if (app->serialnolen && app->serialno[0] == 0xff)
512 /* The serial number starts with our special prefix. This
513 requires that we put our default prefix "FF0000" in front. */
514 unsigned char *p = xtrymalloc (app->serialnolen + 3);
516 return gpg_error_from_syserror ();
517 memcpy (p, "\xff\0", 3);
518 memcpy (p+3, app->serialno, app->serialnolen);
519 app->serialnolen += 3;
520 xfree (app->serialno);
523 else if (!app->serialnolen)
525 unsigned char *p = xtrymalloc (3);
527 return gpg_error_from_syserror ();
528 memcpy (p, "\xff\x7f", 3);
529 app->serialnolen = 3;
530 xfree (app->serialno);
538 /* Retrieve the serial number of the card. The serial number is
539 returned as a malloced string (hex encoded) in SERIAL. Caller must
540 free SERIAL unless the function returns an error. */
542 app_get_serialno (app_t app)
549 if (!app->serialnolen)
550 serial = xtrystrdup ("FF7F00");
552 serial = bin2hex (app->serialno, app->serialnolen, NULL);
558 /* Write out the application specifig status lines for the LEARN
561 app_write_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
566 return gpg_error (GPG_ERR_INV_VALUE);
567 if (!app->fnc.learn_status)
568 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
570 /* We do not send APPTYPE if only keypairinfo is requested. */
571 if (app->apptype && !(flags & 1))
572 send_status_direct (ctrl, "APPTYPE", app->apptype);
573 err = lock_app (app, ctrl);
576 err = app->fnc.learn_status (app, ctrl, flags);
582 /* Read the certificate with id CERTID (as returned by learn_status in
583 the CERTINFO status lines) and return it in the freshly allocated
584 buffer put into CERT and the length of the certificate put into
587 app_readcert (app_t app, ctrl_t ctrl, const char *certid,
588 unsigned char **cert, size_t *certlen)
593 return gpg_error (GPG_ERR_INV_VALUE);
595 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
596 if (!app->fnc.readcert)
597 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
598 err = lock_app (app, ctrl);
601 err = app->fnc.readcert (app, certid, cert, certlen);
607 /* Read the key with ID KEYID. On success a canonical encoded
608 S-expression with the public key will get stored at PK and its
609 length (for assertions) at PKLEN; the caller must release that
610 buffer. On error NULL will be stored at PK and PKLEN and an error
613 This function might not be supported by all applications. */
615 app_readkey (app_t app, ctrl_t ctrl, int advanced, const char *keyid,
616 unsigned char **pk, size_t *pklen)
625 if (!app || !keyid || !pk || !pklen)
626 return gpg_error (GPG_ERR_INV_VALUE);
628 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
629 if (!app->fnc.readkey)
630 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
631 err = lock_app (app, ctrl);
634 err= app->fnc.readkey (app, advanced, keyid, pk, pklen);
640 /* Perform a GETATTR operation. */
642 app_getattr (app_t app, ctrl_t ctrl, const char *name)
646 if (!app || !name || !*name)
647 return gpg_error (GPG_ERR_INV_VALUE);
649 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
651 if (app->apptype && name && !strcmp (name, "APPTYPE"))
653 send_status_direct (ctrl, "APPTYPE", app->apptype);
656 if (name && !strcmp (name, "SERIALNO"))
660 serial = app_get_serialno (app);
662 return gpg_error (GPG_ERR_INV_VALUE);
664 send_status_direct (ctrl, "SERIALNO", serial);
669 if (!app->fnc.getattr)
670 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
671 err = lock_app (app, ctrl);
674 err = app->fnc.getattr (app, ctrl, name);
679 /* Perform a SETATTR operation. */
681 app_setattr (app_t app, ctrl_t ctrl, const char *name,
682 gpg_error_t (*pincb)(void*, const char *, char **),
684 const unsigned char *value, size_t valuelen)
688 if (!app || !name || !*name || !value)
689 return gpg_error (GPG_ERR_INV_VALUE);
691 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
692 if (!app->fnc.setattr)
693 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
694 err = lock_app (app, ctrl);
697 err = app->fnc.setattr (app, name, pincb, pincb_arg, value, valuelen);
702 /* Create the signature and return the allocated result in OUTDATA.
703 If a PIN is required the PINCB will be used to ask for the PIN; it
704 should return the PIN in an allocated buffer and put it into PIN. */
706 app_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
707 gpg_error_t (*pincb)(void*, const char *, char **),
709 const void *indata, size_t indatalen,
710 unsigned char **outdata, size_t *outdatalen )
714 if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
715 return gpg_error (GPG_ERR_INV_VALUE);
717 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
719 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
720 err = lock_app (app, ctrl);
723 err = app->fnc.sign (app, keyidstr, hashalgo,
726 outdata, outdatalen);
729 log_info ("operation sign result: %s\n", gpg_strerror (err));
733 /* Create the signature using the INTERNAL AUTHENTICATE command and
734 return the allocated result in OUTDATA. If a PIN is required the
735 PINCB will be used to ask for the PIN; it should return the PIN in
736 an allocated buffer and put it into PIN. */
738 app_auth (app_t app, ctrl_t ctrl, const char *keyidstr,
739 gpg_error_t (*pincb)(void*, const char *, char **),
741 const void *indata, size_t indatalen,
742 unsigned char **outdata, size_t *outdatalen )
746 if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
747 return gpg_error (GPG_ERR_INV_VALUE);
749 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
751 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
752 err = lock_app (app, ctrl);
755 err = app->fnc.auth (app, keyidstr,
758 outdata, outdatalen);
761 log_info ("operation auth result: %s\n", gpg_strerror (err));
766 /* Decrypt the data in INDATA and return the allocated result in OUTDATA.
767 If a PIN is required the PINCB will be used to ask for the PIN; it
768 should return the PIN in an allocated buffer and put it into PIN. */
770 app_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
771 gpg_error_t (*pincb)(void*, const char *, char **),
773 const void *indata, size_t indatalen,
774 unsigned char **outdata, size_t *outdatalen,
775 unsigned int *r_info)
781 if (!app || !indata || !indatalen || !outdata || !outdatalen || !pincb)
782 return gpg_error (GPG_ERR_INV_VALUE);
784 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
785 if (!app->fnc.decipher)
786 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
787 err = lock_app (app, ctrl);
790 err = app->fnc.decipher (app, keyidstr,
797 log_info ("operation decipher result: %s\n", gpg_strerror (err));
802 /* Perform the WRITECERT operation. */
804 app_writecert (app_t app, ctrl_t ctrl,
805 const char *certidstr,
806 gpg_error_t (*pincb)(void*, const char *, char **),
808 const unsigned char *data, size_t datalen)
812 if (!app || !certidstr || !*certidstr || !pincb)
813 return gpg_error (GPG_ERR_INV_VALUE);
815 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
816 if (!app->fnc.writecert)
817 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
818 err = lock_app (app, ctrl);
821 err = app->fnc.writecert (app, ctrl, certidstr,
822 pincb, pincb_arg, data, datalen);
825 log_info ("operation writecert result: %s\n", gpg_strerror (err));
830 /* Perform the WRITEKEY operation. */
832 app_writekey (app_t app, ctrl_t ctrl,
833 const char *keyidstr, unsigned int flags,
834 gpg_error_t (*pincb)(void*, const char *, char **),
836 const unsigned char *keydata, size_t keydatalen)
840 if (!app || !keyidstr || !*keyidstr || !pincb)
841 return gpg_error (GPG_ERR_INV_VALUE);
843 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
844 if (!app->fnc.writekey)
845 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
846 err = lock_app (app, ctrl);
849 err = app->fnc.writekey (app, ctrl, keyidstr, flags,
850 pincb, pincb_arg, keydata, keydatalen);
853 log_info ("operation writekey result: %s\n", gpg_strerror (err));
858 /* Perform a SETATTR operation. */
860 app_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
862 gpg_error_t (*pincb)(void*, const char *, char **),
867 if (!app || !keynostr || !*keynostr || !pincb)
868 return gpg_error (GPG_ERR_INV_VALUE);
870 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
871 if (!app->fnc.genkey)
872 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
873 err = lock_app (app, ctrl);
876 err = app->fnc.genkey (app, ctrl, keynostr, flags,
877 createtime, pincb, pincb_arg);
880 log_info ("operation genkey result: %s\n", gpg_strerror (err));
885 /* Perform a GET CHALLENGE operation. This function is special as it
886 directly accesses the card without any application specific
889 app_get_challenge (app_t app, ctrl_t ctrl, size_t nbytes, unsigned char *buffer)
893 if (!app || !nbytes || !buffer)
894 return gpg_error (GPG_ERR_INV_VALUE);
896 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
897 err = lock_app (app, ctrl);
900 err = iso7816_get_challenge (app->slot, nbytes, buffer);
907 /* Perform a CHANGE REFERENCE DATA or RESET RETRY COUNTER operation. */
909 app_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode,
910 gpg_error_t (*pincb)(void*, const char *, char **),
915 if (!app || !chvnostr || !*chvnostr || !pincb)
916 return gpg_error (GPG_ERR_INV_VALUE);
918 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
919 if (!app->fnc.change_pin)
920 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
921 err = lock_app (app, ctrl);
924 err = app->fnc.change_pin (app, ctrl, chvnostr, reset_mode,
928 log_info ("operation change_pin result: %s\n", gpg_strerror (err));
933 /* Perform a VERIFY operation without doing anything lese. This may
934 be used to initialze a the PIN cache for long lasting other
935 operations. Its use is highly application dependent. */
937 app_check_pin (app_t app, ctrl_t ctrl, const char *keyidstr,
938 gpg_error_t (*pincb)(void*, const char *, char **),
943 if (!app || !keyidstr || !*keyidstr || !pincb)
944 return gpg_error (GPG_ERR_INV_VALUE);
946 return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
947 if (!app->fnc.check_pin)
948 return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
949 err = lock_app (app, ctrl);
952 err = app->fnc.check_pin (app, keyidstr, pincb, pincb_arg);
955 log_info ("operation check_pin result: %s\n", gpg_strerror (err));
960 report_change (int slot, int old_status, int cur_status)
962 char *homestr, *envstr;
967 snprintf (templ, sizeof templ, "reader_%d.status", slot);
968 fname = make_filename (gnupg_homedir (), templ, NULL );
969 fp = fopen (fname, "w");
973 (cur_status & 1)? "USABLE":
974 (cur_status & 4)? "ACTIVE":
975 (cur_status & 2)? "PRESENT": "NOCARD");
980 homestr = make_filename (gnupg_homedir (), NULL);
981 if (gpgrt_asprintf (&envstr, "GNUPGHOME=%s", homestr) < 0)
982 log_error ("out of core while building environment\n");
986 const char *args[9], *envs[2];
987 char numbuf1[30], numbuf2[30], numbuf3[30];
992 sprintf (numbuf1, "%d", slot);
993 sprintf (numbuf2, "0x%04X", old_status);
994 sprintf (numbuf3, "0x%04X", cur_status);
995 args[0] = "--reader-port";
997 args[2] = "--old-code";
999 args[4] = "--new-code";
1001 args[6] = "--status";
1002 args[7] = ((cur_status & 1)? "USABLE":
1003 (cur_status & 4)? "ACTIVE":
1004 (cur_status & 2)? "PRESENT": "NOCARD");
1007 fname = make_filename (gnupg_homedir (), "scd-event", NULL);
1008 err = gnupg_spawn_process_detached (fname, args, envs);
1009 if (err && gpg_err_code (err) != GPG_ERR_ENOENT)
1010 log_error ("failed to run event handler '%s': %s\n",
1011 fname, gpg_strerror (err));
1019 scd_update_reader_status_file (void)
1023 npth_mutex_lock (&app_list_lock);
1024 for (a = app_top; a; a = app_next)
1027 if (a->require_get_status)
1030 unsigned int status;
1031 sw = apdu_get_status (a->slot, 0, &status);
1033 if (sw == SW_HOST_NO_READER)
1035 /* Most likely the _reader_ has been unplugged. */
1040 /* Get status failed. Ignore that. */
1044 if (a->card_status != status)
1046 report_change (a->slot, a->card_status, status);
1047 send_client_notifications (a, status == 0);
1051 log_debug ("Removal of a card: %d\n", a->slot);
1052 apdu_close_reader (a->slot);
1056 a->card_status = status;
1060 npth_mutex_unlock (&app_list_lock);
1063 /* This function must be called once to initialize this module. This
1064 has to be done before a second thread is spawned. We can't do the
1065 static initialization because Pth emulation code might not be able
1066 to do a static init; in particular, it is not possible for W32. */
1068 initialize_module_command (void)
1072 if (npth_mutex_init (&app_list_lock, NULL))
1074 err = gpg_error_from_syserror ();
1075 log_error ("app: error initializing mutex: %s\n", gpg_strerror (err));
1079 return apdu_init ();
1083 app_list_start (void)
1085 npth_mutex_lock (&app_list_lock);
1090 app_list_finish (void)
1092 npth_mutex_unlock (&app_list_lock);
1096 app_send_card_list (ctrl_t ctrl)
1101 npth_mutex_lock (&app_list_lock);
1102 for (a = app_top; a; a = a->next)
1104 if (DIM (buf) < 2 * a->serialnolen + 1)
1107 bin2hex (a->serialno, a->serialnolen, buf);
1108 send_status_direct (ctrl, "SERIALNO", buf);
1110 npth_mutex_unlock (&app_list_lock);