+#ifdef USE_PAM
+ if (!options.use_pam)
+ remove_kbdint_device("pam");
+#endif
+
+ kbdintctxt = xmalloc(sizeof(KbdintAuthctxt));
+ if (strcmp(devs, "") == 0) {
+ buffer_init(&b);
+ for (i = 0; devices[i]; i++) {
+ if (buffer_len(&b) > 0)
+ buffer_append(&b, ",", 1);
+ buffer_append(&b, devices[i]->name,
+ strlen(devices[i]->name));
+ }
+ buffer_append(&b, "\0", 1);
+ kbdintctxt->devices = xstrdup(buffer_ptr(&b));
+ buffer_free(&b);
+ } else {
+ kbdintctxt->devices = xstrdup(devs);
+ }
+ debug("kbdint_alloc: devices '%s'", kbdintctxt->devices);
+ kbdintctxt->ctxt = NULL;
+ kbdintctxt->device = NULL;
+ kbdintctxt->nreq = 0;
+
+ return kbdintctxt;
+}
+static void
+kbdint_reset_device(KbdintAuthctxt *kbdintctxt)
+{
+ if (kbdintctxt->ctxt) {
+ kbdintctxt->device->free_ctx(kbdintctxt->ctxt);
+ kbdintctxt->ctxt = NULL;
+ }
+ kbdintctxt->device = NULL;
+}
+static void
+kbdint_free(KbdintAuthctxt *kbdintctxt)
+{
+ if (kbdintctxt->device)
+ kbdint_reset_device(kbdintctxt);
+ if (kbdintctxt->devices) {
+ xfree(kbdintctxt->devices);
+ kbdintctxt->devices = NULL;
+ }
+ xfree(kbdintctxt);
+}
+/* get next device */
+static int
+kbdint_next_device(KbdintAuthctxt *kbdintctxt)
+{
+ size_t len;
+ char *t;
+ int i;
+
+ if (kbdintctxt->device)
+ kbdint_reset_device(kbdintctxt);
+ do {
+ len = kbdintctxt->devices ?
+ strcspn(kbdintctxt->devices, ",") : 0;
+
+ if (len == 0)
+ break;
+ for (i = 0; devices[i]; i++)
+ if (strncmp(kbdintctxt->devices, devices[i]->name, len) == 0)
+ kbdintctxt->device = devices[i];
+ t = kbdintctxt->devices;
+ kbdintctxt->devices = t[len] ? xstrdup(t+len+1) : NULL;
+ xfree(t);
+ debug2("kbdint_next_device: devices %s", kbdintctxt->devices ?
+ kbdintctxt->devices : "<empty>");
+ } while (kbdintctxt->devices && !kbdintctxt->device);
+
+ return kbdintctxt->device ? 1 : 0;
+}