void grub_efidisk_fini (void) { free_devices (fd_devices); free_devices (hd_devices); free_devices (cd_devices); }
static void table_destroy(struct dm_table *t) { unsigned int i; /* free the indexes (see dm_table_complete) */ if (t->depth >= 2) vfree(t->index[t->depth - 2]); /* free the targets */ for (i = 0; i < t->num_targets; i++) { struct dm_target *tgt = t->targets + i; if (tgt->type->dtr) tgt->type->dtr(tgt); dm_put_target_type(tgt->type); } vfree(t->highs); /* free the device list */ if (t->devices.next != &t->devices) { DMWARN("devices still present during destroy: " "dm_table_remove_device calls missing"); free_devices(&t->devices); } kfree(t); }
void sane_exit (void) { struct device *dev; for (dev = devices_head; dev; dev = dev->next) if (dev->dn != -1) sane_close(dev); /* implies flush */ free_devices (); }
void glwtQuitLinux() { if(glwt.linux_input.inotify_fd > 0) close(glwt.linux_input.inotify_fd); if(glwt.linux_input.epoll_fd > 0) close(glwt.linux_input.epoll_fd); free_devices(); memset(&glwt.linux_input, 0, sizeof(struct glwt_linux_input)); }
/* Enumerate all disks to name devices. */ static void enumerate_disks (void) { struct grub_efidisk_data *devices; devices = make_devices (); if (! devices) return; name_devices (devices); free_devices (devices); }
/* Some utility functions to map GRUB devices with EFI devices. */ grub_efi_handle_t grub_efidisk_get_current_bdev_handle (void) { struct grub_efidisk_data *d; d = get_device_from_drive (current_drive); if (d == NULL) return NULL; if (current_drive == GRUB_INVALID_DRIVE) return NULL; if (current_drive == cdrom_drive) return d->handle; if (! (current_drive & 0x80)) return d->handle; /* If this is the whole disk, just return its own data. */ else if (current_partition == 0xFFFFFF) return d->handle; /* Otherwise, we must query the corresponding device to the firmware. */ else { struct grub_efidisk_data *devices; grub_efi_handle_t handle = 0; auto int find_partition (struct grub_efidisk_data *c); int find_partition (struct grub_efidisk_data *c) { grub_efi_hard_drive_device_path_t hd; grub_memcpy (&hd, c->last_device_path, sizeof (hd)); if ((GRUB_EFI_DEVICE_PATH_TYPE (c->last_device_path) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE) && (GRUB_EFI_DEVICE_PATH_SUBTYPE (c->last_device_path) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE) && (part_start == hd.partition_start)) { handle = c->handle; return 1; } return 0; } devices = make_devices (); iterate_child_devices (devices, d, find_partition); free_devices (devices); if (handle != 0) return handle; }
int fpga_free_model(struct fpga_model* model) { int rc; if (!model) return 0; rc = model->rc; free_devices(model); free(model->tmp_str); strarray_free(&model->str); free(model->tiles); free_xc6_routing_bitpos(model->sw_bitpos); memset(model, 0, sizeof(*model)); return rc; }
SANE_Status sane_get_devices (const SANE_Device *** device_list, SANE_Bool local) { SANEI_Config config; struct device *dev; int dev_count; int i; DBG (3, "%s: %p, %d\n", __FUNCTION__, (const void *)device_list, local); if (devlist) { if (device_list) *device_list = devlist; return SANE_STATUS_GOOD; } free_devices (); config.count = 0; config.descriptors = NULL; config.values = NULL; sanei_configure_attach (XEROX_CONFIG_FILE, &config, list_conf_devices); for (dev_count = 0, dev = devices_head; dev; dev = dev->next) dev_count++; devlist = malloc ((dev_count + 1) * sizeof (*devlist)); if (!devlist) { DBG (1, "%s: malloc: no memory\n", __FUNCTION__); return SANE_STATUS_NO_MEM; } for (i = 0, dev = devices_head; dev; dev = dev->next) devlist[i++] = &dev->sane; devlist[i++] = NULL; if (device_list) *device_list = devlist; return SANE_STATUS_GOOD; }
static int enable_all_gpus(Options *op, XConfigPtr config, XConfigLayoutPtr layout) { DevicesPtr pDevices; int i; pDevices = find_devices(op); if (!pDevices) { nv_error_msg("Unable to determine number of GPUs in system; cannot " "honor '--enable-all-gpus' option."); return FALSE; } /* free all existing X screens, monitors, devices, and adjacencies */ xconfigFreeScreenList(&config->screens); xconfigFreeDeviceList(&config->devices); xconfigFreeMonitorList(&config->monitors); xconfigFreeAdjacencyList(&layout->adjacencies); /* add N new screens; this will also add device and monitor sections */ for (i = 0; i < pDevices->nDevices; i++) { xconfigGenerateAddScreen(config, pDevices->devices[i].dev.bus, pDevices->devices[i].dev.domain, pDevices->devices[i].dev.slot, pDevices->devices[i].name, i, "nvidia", "NVIDIA Corporation"); } free_devices(pDevices); /* create adjacencies for the layout */ create_adjacencies(op, config, layout); return TRUE; } /* enable_all_gpus() */
static void nm_backend_data_cleanup(struct connline_context *context) { struct nm_dbus *nm = context->backend_data; if (nm == NULL) return; if (nm->state_watched == TRUE) connline_dbus_remove_watch(context->dbus_cnx, NM_STATE_SIGNAL_MATCH_RULE, watch_nm_state, context); if (nm->call != NULL) { dbus_pending_call_cancel(nm->call); dbus_pending_call_unref(nm->call); } free_devices(nm); free(nm); context->backend_data = NULL; }
/* * get_screens_to_clone() - try to detect automatically how many heads has each * device in order to use that number to create more than two separate X * screens. If the user specifies the option --num-x-screens <quantity>, that * value is used. If neither the user specifies the quantity or the number of * heads can be detected automatically, it uses 2 heads (the standard * behavior). This function returns an array of size nscreens with the number * of screens to clone per screen candidate. The caller is responsible of * freeing the memory of that array. */ static int* get_screens_to_clone(Options *op, const XConfigScreenPtr *screen_candidates, int nscreens) { DevicesPtr pDevices; int *screens_to_clone, *supported_screens; int i, j, devs_found; screens_to_clone = nvalloc(nscreens * sizeof(int)); supported_screens = nvalloc(nscreens * sizeof(int)); /* Detect the number of supported screens per screen candidate */ devs_found = FALSE; pDevices = find_devices(op); if (pDevices) { for (i = 0; i < nscreens; i++) { int bus, slot, scratch; if (!screen_candidates[i]) { continue; } /* parse the bus id for this candidate screen */ if (!xconfigParsePciBusString(screen_candidates[i]->device->busid, &bus, &slot, &scratch)) { continue; } for (j = 0; j < pDevices->nDevices; j++) { if ((pDevices->devices[j].dev.bus == bus) && (pDevices->devices[j].dev.slot == slot)) { if (pDevices->devices[j].crtcs > 0) { supported_screens[i] = pDevices->devices[j].crtcs; } break; } } } free_devices(pDevices); devs_found = TRUE; } /* If user has defined a number of screens per GPU, use that value */ if (op->num_x_screens > 0) { for (i = 0; i < nscreens; i++) { if (!screen_candidates[i]) { continue; } /* Print error when user specifies more X screens than supported */ if (devs_found && op->num_x_screens > supported_screens[i]) { nv_warning_msg("Number of X screens specified is higher than the " "supported quantity (%d)", supported_screens[i]); } screens_to_clone[i] = op->num_x_screens; } goto done; } for (i = 0; i < nscreens; i++) { if (screen_candidates[i]) { if (devs_found) { /* If devices found, use the supported screens number */ screens_to_clone[i] = supported_screens[i]; } else { /* Default behavior (2 heads per GPU) */ screens_to_clone[i] = 2; } } } done: nvfree(supported_screens); return screens_to_clone; }
static int enable_separate_x_screens(Options *op, XConfigPtr config, XConfigLayoutPtr layout) { XConfigScreenPtr screen, *screenlist = NULL; XConfigAdjacencyPtr adj; int* screens_to_clone = NULL; int i, nscreens = 0; int have_busids; /* step 1: build the list of screens that are candidate to be cloned */ if (op->screen) { screen = xconfigFindScreen(op->screen, config->screens); if (!screen) { nv_error_msg("Unable to find screen '%s'.", op->screen); return FALSE; } screenlist = nvalloc(sizeof(XConfigScreenPtr)); screenlist[0] = screen; nscreens = 1; } else { for (adj = layout->adjacencies; adj; adj = adj->next) { nscreens++; screenlist = realloc(screenlist, sizeof(XConfigScreenPtr) * nscreens); screenlist[nscreens-1] = adj->screen; } } if (!nscreens) return FALSE; /* step 2: do all screens in the list have a bus ID? */ have_busids = TRUE; for (i = 0; i < nscreens; i++) { if (screenlist[i] && screenlist[i]->device && screenlist[i]->device->busid) { // this screen has a busid } else { have_busids = FALSE; break; } } /* * if not everyone has a bus id, then let's assign bus ids to all * the screens; XXX what if _some_ already have busids? Too bad, * we're going to reassign all of them. */ if (!have_busids) { DevicesPtr pDevices; pDevices = find_devices(op); if (!pDevices) { nv_error_msg("Unable to determine number or location of " "GPUs in system; cannot " "honor '--separate-x-screens' option."); return FALSE; } for (i = 0; i < nscreens; i++) { if (i >= pDevices->nDevices) { /* * we have more screens than GPUs, this screen is no * longer a candidate */ screenlist[i] = NULL; continue; } screenlist[i]->device->busid = nvalloc(32); xconfigFormatPciBusString(screenlist[i]->device->busid, 32, pDevices->devices[i].dev.domain, pDevices->devices[i].dev.bus, pDevices->devices[i].dev.slot, 0); screenlist[i]->device->board = nvstrdup(pDevices->devices[i].name); } free_devices(pDevices); } /* step 3 */ clean_screen_list(screenlist, config, nscreens); /* step 4 */ screens_to_clone = get_screens_to_clone(op, screenlist, nscreens); /* step 5: clone each eligible screen */ for (i = 0; i < nscreens; i++) { if (!screenlist[i]) continue; while (--screens_to_clone[i] > 0) { clone_screen(screenlist[i], screens_to_clone[i]); } } nvfree(screens_to_clone); /* step 6: wipe the existing adjacencies and recreate them */ xconfigFreeAdjacencyList(&layout->adjacencies); create_adjacencies(op, config, layout); /* free unused device and monitor sections */ free_unused_devices(op, config); free_unused_monitors(op, config); /* free stuff */ free(screenlist); return TRUE; } /* enable_separate_x_screens() */
DevicesPtr find_devices(Options *op) { DevicesPtr pDevices = NULL; DisplayDevicePtr pDisplayDevice; int i, j, n, count = 0; unsigned int mask, bit; DeviceRec tmpDevice; NvCfgPciDevice *devs = NULL; NvCfgBool is_primary_device; NvCfgBool ret; char *lib_path; void *lib_handle; NvCfgBool (*__getDevices)(int *n, NvCfgDevice **devs); NvCfgBool (*__openDevice)(int bus, int slot, NvCfgDeviceHandle *handle); NvCfgBool (*__getPciDevices)(int *n, NvCfgPciDevice **devs); NvCfgBool (*__openPciDevice)(int domain, int bus, int slot, int function, NvCfgDeviceHandle *handle); NvCfgBool (*__getNumCRTCs)(NvCfgDeviceHandle handle, int *crtcs); NvCfgBool (*__getProductName)(NvCfgDeviceHandle handle, char **name); NvCfgBool (*__getDisplayDevices)(NvCfgDeviceHandle handle, unsigned int *display_device_mask); NvCfgBool (*__getEDID)(NvCfgDeviceHandle handle, unsigned int display_device, NvCfgDisplayDeviceInformation *info); NvCfgBool (*__isPrimaryDevice)(NvCfgDeviceHandle handle, NvCfgBool *is_primary_device); NvCfgBool (*__closeDevice)(NvCfgDeviceHandle handle); NvCfgBool (*__getDeviceUUID)(NvCfgDeviceHandle handle, char **uuid); /* dlopen() the nvidia-cfg library */ #define __LIB_NAME "libnvidia-cfg.so.1" if (op->nvidia_cfg_path) { lib_path = nvstrcat(op->nvidia_cfg_path, "/", __LIB_NAME, NULL); } else { lib_path = strdup(__LIB_NAME); } lib_handle = dlopen(lib_path, RTLD_NOW); nvfree(lib_path); if (!lib_handle) { nv_warning_msg("error opening %s: %s.", __LIB_NAME, dlerror()); return NULL; } #define __GET_FUNC(proc, name) \ (proc) = dlsym(lib_handle, (name)); \ if (!(proc)) { \ nv_warning_msg("error retrieving symbol %s from %s: %s", \ (name), __LIB_NAME, dlerror()); \ dlclose(lib_handle); \ return NULL; \ } /* required functions */ __GET_FUNC(__getDevices, "nvCfgGetDevices"); __GET_FUNC(__openDevice, "nvCfgOpenDevice"); __GET_FUNC(__getPciDevices, "nvCfgGetPciDevices"); __GET_FUNC(__openPciDevice, "nvCfgOpenPciDevice"); __GET_FUNC(__getNumCRTCs, "nvCfgGetNumCRTCs"); __GET_FUNC(__getProductName, "nvCfgGetProductName"); __GET_FUNC(__getDisplayDevices, "nvCfgGetDisplayDevices"); __GET_FUNC(__getEDID, "nvCfgGetEDID"); __GET_FUNC(__closeDevice, "nvCfgCloseDevice"); __GET_FUNC(__getDeviceUUID, "nvCfgGetDeviceUUID"); /* optional functions */ __isPrimaryDevice = dlsym(lib_handle, "nvCfgIsPrimaryDevice"); if (__getPciDevices(&count, &devs) != NVCFG_TRUE) { return NULL; } if (count == 0) return NULL; pDevices = nvalloc(sizeof(DevicesRec)); pDevices->devices = nvalloc(sizeof(DeviceRec) * count); pDevices->nDevices = count; for (i = 0; i < count; i++) { pDevices->devices[i].dev = devs[i]; if (__openPciDevice(devs[i].domain, devs[i].bus, devs[i].slot, 0, &(pDevices->devices[i].handle)) != NVCFG_TRUE) { goto fail; } if (__getNumCRTCs(pDevices->devices[i].handle, &pDevices->devices[i].crtcs) != NVCFG_TRUE) { goto fail; } if (__getProductName(pDevices->devices[i].handle, &pDevices->devices[i].name) != NVCFG_TRUE) { /* This call may fail with little impact to the Device section */ pDevices->devices[i].name = NULL; } if (__getDeviceUUID(pDevices->devices[i].handle, &pDevices->devices[i].uuid) != NVCFG_TRUE) { goto fail; } if (__getDisplayDevices(pDevices->devices[i].handle, &mask) != NVCFG_TRUE) { goto fail; } pDevices->devices[i].displayDeviceMask = mask; /* count the number of display devices */ for (n = j = 0; j < 32; j++) { if (mask & (1 << j)) n++; } pDevices->devices[i].nDisplayDevices = n; if (n) { /* allocate the info array of the right size */ pDevices->devices[i].displayDevices = nvalloc(sizeof(DisplayDeviceRec) * n); /* fill in the info array */ for (n = j = 0; j < 32; j++) { bit = 1 << j; if (!(bit & mask)) continue; pDisplayDevice = &pDevices->devices[i].displayDevices[n]; pDisplayDevice->mask = bit; if (__getEDID(pDevices->devices[i].handle, bit, &pDisplayDevice->info) != NVCFG_TRUE) { pDisplayDevice->info_valid = FALSE; } else { pDisplayDevice->info_valid = TRUE; } n++; } } else { pDevices->devices[i].displayDevices = NULL; } if ((i != 0) && (__isPrimaryDevice != NULL) && (__isPrimaryDevice(pDevices->devices[i].handle, &is_primary_device) == NVCFG_TRUE) && (is_primary_device == NVCFG_TRUE)) { memcpy(&tmpDevice, &pDevices->devices[0], sizeof(DeviceRec)); memcpy(&pDevices->devices[0], &pDevices->devices[i], sizeof(DeviceRec)); memcpy(&pDevices->devices[i], &tmpDevice, sizeof(DeviceRec)); } ret = __closeDevice(pDevices->devices[i].handle); pDevices->devices[i].handle = NULL; if (ret != NVCFG_TRUE) { goto fail; } } goto done; fail: nv_warning_msg("Unable to use the nvidia-cfg library to query NVIDIA " "hardware."); for (i = 0; i < pDevices->nDevices; i++) { /* close the opened device */ if (pDevices->devices[i].handle) { __closeDevice(pDevices->devices[i].handle); } } free_devices(pDevices); pDevices = NULL; /* fall through */ done: if (devs) free(devs); return pDevices; } /* find_devices() */
static void nm_devices_cb(DBusPendingCall *pending, void *user_data) { struct connline_context *context = user_data; char **devices_obj = NULL; DBusMessageIter arg; DBusMessage *reply; struct nm_dbus *nm; int len; int i; if (dbus_pending_call_get_completed(pending) == FALSE) return; nm = context->backend_data; nm->call = NULL; reply = dbus_pending_call_steal_reply(pending); if (reply == NULL) goto error; if (dbus_message_iter_init(reply, &arg) == FALSE) goto error; if (connline_dbus_get_array(&arg, DBUS_TYPE_OBJECT_PATH, &len, &devices_obj) < 0) goto error; if (devices_obj != NULL && len > 0) { free_devices(nm); nm->nb_devices = len; nm->devices = calloc(nm->nb_devices, sizeof(char *)); if (nm->devices == NULL) goto error; for (i = 0; i < len; i++) { nm->devices[i] = strdup(devices_obj[i]); if (nm->devices[i] == NULL) { nm->nb_devices = i; goto error; } } nm->current_device = 0; if (nm_device_get_all(context) < 0) goto error; free(devices_obj); } dbus_message_unref(reply); dbus_pending_call_unref(pending); return; error: free(devices_obj); if (reply != NULL) dbus_message_unref(reply); dbus_pending_call_unref(pending); nm_backend_data_cleanup(context); __connline_call_error_callback(context, false); }
static void nm_device_all_cb(DBusPendingCall *pending, void *user_data) { struct connline_context *context = user_data; char ip[INET_ADDRSTRLEN+1]; char **properties = NULL; unsigned int dev_state; unsigned int dev_type; const char *interface; dbus_bool_t managed; DBusMessageIter arg; DBusMessage *reply; struct nm_dbus *nm; struct in_addr in4; unsigned int ip4; if (dbus_pending_call_get_completed(pending) == FALSE) return; nm = context->backend_data; nm->call = NULL; reply = dbus_pending_call_steal_reply(pending); if (reply == NULL) goto error; if (dbus_message_iter_init(reply, &arg) == FALSE) goto error; if (connline_dbus_get_dict_entry_basic(&arg, "Managed", DBUS_TYPE_BOOLEAN, &managed) < 0) goto error; if (managed == FALSE) goto next; if (connline_dbus_get_dict_entry_basic(&arg, "State", DBUS_TYPE_UINT32, &dev_state) < 0) goto error; if (dev_state != NM_DEVICE_STATE_ACTIVATED) goto next; if (connline_dbus_get_dict_entry_basic(&arg, "DeviceType", DBUS_TYPE_UINT32, &dev_type) < 0) goto error; nm->bearer = nm_device_type_to_bearer(dev_type); if (!(context->bearer_type == CONNLINE_BEARER_UNKNOWN || nm->bearer & context->bearer_type)) goto next; __connline_call_connected_callback(context); free_devices(nm); if (connline_dbus_get_dict_entry_basic(&arg, "Ip4Address", DBUS_TYPE_UINT32, &ip4) < 0) goto error; memset(ip, 0, INET_ADDRSTRLEN+1); in4.s_addr = ip4; if (inet_ntop(AF_INET, &in4, ip, INET_ADDRSTRLEN+1) == NULL) goto error; if (connline_dbus_get_dict_entry_basic(&arg, "IpInterface", DBUS_TYPE_STRING, &interface) < 0) goto error; properties = insert_into_property_list(properties, "bearer", connline_bearer_to_string(nm->bearer)); properties = insert_into_property_list(properties, "interface", interface); properties = insert_into_property_list(properties, "address", ip); if (properties != NULL) __connline_call_property_callback(context, properties); goto out; next: nm->current_device++; if (nm->current_device < nm->nb_devices) { if (nm_device_get_all(context) < 0) goto error; } else { free_devices(nm); __connline_call_disconnected_callback(context); } out: dbus_message_unref(reply); dbus_pending_call_unref(pending); return; error: if (reply != NULL) dbus_message_unref(reply); dbus_pending_call_unref(pending); nm_backend_data_cleanup(context); __connline_call_error_callback(context, false); }
/* PAM entry point for authentication verification */ int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv) { struct passwd *pw = NULL, pw_s; const char *user = NULL; cfg_t cfg_st; cfg_t *cfg = &cfg_st; char buffer[BUFSIZE]; char *buf = NULL; char *authfile_dir; int authfile_dir_len; int pgu_ret, gpn_ret; int retval = PAM_IGNORE; device_t *devices = NULL; unsigned n_devices = 0; parse_cfg(flags, argc, argv, cfg); if (!cfg->origin) { if (!strcpy(buffer, DEFAULT_ORIGIN_PREFIX)) { DBG(("Unable to create origin string")); goto done; } if (gethostname (buffer + strlen(DEFAULT_ORIGIN_PREFIX), BUFSIZE - strlen(DEFAULT_ORIGIN_PREFIX)) == -1) { DBG(("Unable to get host name")); goto done; } DBG(("Origin not specified, using \"%s\"", buffer)); cfg->origin = strdup(buffer); } if (!cfg->origin) { DBG(("Unable to allocate memory")); goto done; } if (!cfg->appid) { DBG(("Appid not specified, using the same value of origin (%s)", cfg->origin)); cfg->appid = strdup(cfg->origin); } if (!cfg->appid) { DBG(("Unable to allocate memory")); goto done; } if (cfg->max_devs == 0) { DBG(("Maximum devices number not set. Using default (%d)", MAX_DEVS)); cfg->max_devs = MAX_DEVS; } devices = malloc(sizeof(device_t) * cfg->max_devs); if (!devices) { DBG(("Unable to allocate memory")); return PAM_IGNORE; } pgu_ret = pam_get_user(pamh, &user, NULL); if (pgu_ret != PAM_SUCCESS || user == NULL) { DBG(("Unable to access user %s", user)); free(devices); devices = NULL; return PAM_CONV_ERR; } DBG(("Requesting authentication for user %s", user)); gpn_ret = getpwnam_r(user, &pw_s, buffer, sizeof(buffer), &pw); if (gpn_ret != 0 || pw == NULL || pw->pw_dir == NULL || pw->pw_dir[0] != '/') { DBG(("Unable to retrieve credentials for user %s, (%s)", user, strerror(errno))); retval = PAM_USER_UNKNOWN; goto done; } DBG(("Found user %s", user)); DBG(("Home directory for %s is %s", user, pw->pw_dir)); if (!cfg->auth_file) { buf = NULL; authfile_dir = secure_getenv(DEFAULT_AUTHFILE_DIR_VAR); if (!authfile_dir) { DBG(("Variable %s is not set. Using default value ($HOME/.config/)", DEFAULT_AUTHFILE_DIR_VAR)); authfile_dir_len = strlen(pw->pw_dir) + strlen("/.config") + strlen(DEFAULT_AUTHFILE) + 1; buf = malloc(sizeof(char) * (authfile_dir_len)); if (!buf) { DBG(("Unable to allocate memory")); retval = PAM_IGNORE; goto done; } strcpy(buf, pw->pw_dir); strcat(buf, "/.config"); strcat(buf, DEFAULT_AUTHFILE); } else { DBG(("Variable %s set to %s", DEFAULT_AUTHFILE_DIR_VAR, authfile_dir)); authfile_dir_len = strlen(authfile_dir) + strlen(DEFAULT_AUTHFILE) + 1; buf = malloc(sizeof(char) * (authfile_dir_len)); if (!buf) { DBG(("Unable to allocate memory")); retval = PAM_IGNORE; goto done; } strcpy(buf, authfile_dir); strcat(buf, DEFAULT_AUTHFILE); } DBG(("Using default authentication file %s", buf)); cfg->auth_file = strdup(buf); if (!cfg->auth_file) { DBG(("Unable to allocate memory")); retval = PAM_IGNORE; goto done; } free(buf); buf = NULL; } else { DBG(("Using authentication file %s", cfg->auth_file)); } retval = get_devices_from_authfile(cfg->auth_file, user, cfg->max_devs, cfg->debug, devices, &n_devices); if (retval != 1) { DBG(("Unable to get devices from file %s", cfg->auth_file)); retval = PAM_AUTHINFO_UNAVAIL; goto done; } if (n_devices == 0) { if (cfg->nouserok) { DBG(("Found no devices but nouserok specified. Skipping authentication")); retval = PAM_SUCCESS; goto done; } else { DBG(("Found no devices. Aborting.")); retval = PAM_AUTHINFO_UNAVAIL; goto done; } } if (cfg->manual == 0) { if (cfg->interactive) { converse(pamh, PAM_PROMPT_ECHO_ON, "Insert your U2F device, then press ENTER.\n"); } retval = do_authentication(cfg, devices, n_devices, pamh); } else { retval = do_manual_authentication(cfg, devices, n_devices, pamh); } if (retval != 1) { DBG(("do_authentication returned %d", retval)); retval = PAM_AUTH_ERR; goto done; } retval = PAM_SUCCESS; done: free_devices(devices, n_devices); if (buf) { free(buf); buf = NULL; } if (cfg->alwaysok && retval != PAM_SUCCESS) { DBG(("alwaysok needed (otherwise return with %d)", retval)); retval = PAM_SUCCESS; } DBG(("done. [%s]", pam_strerror(pamh, retval))); return retval; }