/* Expand *list_inout to contain the mappings from modstrs, followed by the * existing built-in module mappings. */ static krb5_error_code make_full_list(krb5_context context, char **modstrs, struct plugin_mapping ***list_inout) { krb5_error_code ret = 0; size_t count, pos, i, j; struct plugin_mapping **list, **mp; char **mod; /* Allocate space for all of the modules plus a null terminator. */ for (count = 0; modstrs[count] != NULL; count++); for (mp = *list_inout; mp != NULL && *mp != NULL; mp++, count++); list = calloc(count + 1, sizeof(*list)); if (list == NULL) return ENOMEM; /* Parse each profile module entry and store it in the list. */ for (mod = modstrs, pos = 0; *mod != NULL; mod++, pos++) { ret = parse_modstr(context, *mod, &list[pos]); if (ret != 0) { free_mapping_list(list); return ret; } } /* Cannibalize the old list of built-in modules. */ for (mp = *list_inout; mp != NULL && *mp != NULL; mp++, pos++) list[pos] = *mp; assert(pos == count); /* Filter out duplicates, preferring earlier entries to later ones. */ for (i = 0, pos = 0; i < count; i++) { for (j = 0; j < pos; j++) { if (strcmp(list[i]->modname, list[j]->modname) == 0) { free_plugin_mapping(list[i]); break; } } if (j == pos) list[pos++] = list[i]; } list[pos] = NULL; free(*list_inout); *list_inout = list; return 0; }
static int cmdlet_list(CmdLetData *cdata, int ac, char **av) { glob_t globbuf; int ret, i = 0, fid = 0 /* fixed id */, tid = 0; /* template id */ uint32_t modkind[2] = { 0, 0 }; ModRequest fixed; if (ac != 2) { tc_log_error(EXE, "wrong number of arguments for `list' mode"); return STATUS_BAD_PARAM; } /* we support only encoder|multiplexor, yet */ modkind[0] = parse_modstr(av[0]); if (!(modkind[0] & TC_MODULE_ENCODER)) { tc_log_error(EXE, "unknown/unsupported module '%s'", av[0]); return STATUS_BAD_PARAM; } modkind[1] = parse_modstr(av[1]); if (!(modkind[1] & TC_MODULE_MUXER)) { tc_log_error(EXE, "unknown/unsupported module '%s'", av[1]); return STATUS_BAD_PARAM; } if ((modkind[0] & TC_MODULE_FIXED) && (modkind[1] & TC_MODULE_TEMPLATE)) { fid = 0; tid = 1; } else if ((modkind[0] & TC_MODULE_TEMPLATE) && (modkind[1] & TC_MODULE_FIXED)) { fid = 1; tid = 0; } else { tc_log_error(EXE, "incorrect arguments," " maybe you want to use `check' mode?"); return STATUS_BAD_PARAM; } modrequest_init(&fixed); ret = modrequest_load(cdata->factory, &fixed, av[fid]); if (ret != TC_OK) { return STATUS_MODULE_ERROR; } ret = modrequest_scan(cdata->modpath, av[tid], &globbuf); if (ret != 0) { return STATUS_GLOB_FAILED; } ret = modrequest_fill(cdata->factory, cdata->mods, MAX_MODS, &cdata->modsnum, &globbuf); if (ret != TC_OK) { return STATUS_MODULE_ERROR; } for (i = 0; i < cdata->modsnum; i++) { const ModRequest *H = (tid == 0) ?(&cdata->mods[i]) :(&fixed); const ModRequest *T = (tid == 1) ?(&cdata->mods[i]) :(&fixed); check_module_pair(H, T, &(cdata->mods[i]), (verbose == 0) ?TC_INFO :verbose); } CLEANUP(cdata); modrequest_free(&globbuf); ret = modrequest_unload(cdata->factory, &fixed); if (ret != TC_OK) { return STATUS_MODULE_ERROR; } return STATUS_OK; }