int pkg_ini(const char *path, const char *reposdir, pkg_init_flags flags) { struct ucl_parser *p = NULL; size_t i; const char *val = NULL; const char *buf, *walk, *value, *key, *k; const char *evkey = NULL; const char *nsname = NULL; const char *evpipe = NULL; const ucl_object_t *cur, *object; ucl_object_t *obj = NULL, *o, *ncfg; ucl_object_iter_t it = NULL; struct sbuf *ukey = NULL; bool fatal_errors = false; k = NULL; o = NULL; pkg_get_myarch(myabi, BUFSIZ); pkg_get_myarch_legacy(myabi_legacy, BUFSIZ); if (parsed != false) { pkg_emit_error("pkg_init() must only be called once"); return (EPKG_FATAL); } if (((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4) && ((flags & PKG_INIT_FLAG_USE_IPV6) == PKG_INIT_FLAG_USE_IPV6)) { pkg_emit_error("Invalid flags for pkg_init()"); return (EPKG_FATAL); } config = ucl_object_typed_new(UCL_OBJECT); for (i = 0; i < c_size; i++) { switch (c[i].type) { case PKG_STRING: obj = ucl_object_fromstring_common( c[i].def != NULL ? c[i].def : "", 0, UCL_STRING_TRIM); ucl_object_insert_key(config, obj, c[i].key, strlen(c[i].key), false); break; case PKG_INT: ucl_object_insert_key(config, ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_INT), c[i].key, strlen(c[i].key), false); break; case PKG_BOOL: ucl_object_insert_key(config, ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_BOOLEAN), c[i].key, strlen(c[i].key), false); break; case PKG_OBJECT: obj = ucl_object_typed_new(UCL_OBJECT); if (c[i].def != NULL) { walk = buf = c[i].def; while ((buf = strchr(buf, ',')) != NULL) { key = walk; value = walk; while (*value != ',') { if (*value == '=') break; value++; } ucl_object_insert_key(obj, ucl_object_fromstring_common(value + 1, buf - value - 1, UCL_STRING_TRIM), key, value - key, false); buf++; walk = buf; } key = walk; value = walk; while (*value != ',') { if (*value == '=') break; value++; } if (o == NULL) o = ucl_object_typed_new(UCL_OBJECT); ucl_object_insert_key(o, ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM), key, value - key, false); } ucl_object_insert_key(config, obj, c[i].key, strlen(c[i].key), false); break; case PKG_ARRAY: obj = ucl_object_typed_new(UCL_ARRAY); if (c[i].def != NULL) { walk = buf = c[i].def; while ((buf = strchr(buf, ',')) != NULL) { ucl_array_append(obj, ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM)); buf++; walk = buf; } ucl_array_append(obj, ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM)); } ucl_object_insert_key(config, obj, c[i].key, strlen(c[i].key), false); break; } } if (path == NULL) path = PREFIX"/etc/pkg.conf"; p = ucl_parser_new(0); errno = 0; obj = NULL; if (!ucl_parser_add_file(p, path)) { if (errno != ENOENT) pkg_emit_error("Invalid configuration file: %s", ucl_parser_get_error(p)); } else { obj = ucl_parser_get_object(p); } ncfg = NULL; while (obj != NULL && (cur = ucl_iterate_object(obj, &it, true))) { sbuf_init(&ukey); key = ucl_object_key(cur); for (i = 0; key[i] != '\0'; i++) sbuf_putc(ukey, toupper(key[i])); sbuf_finish(ukey); object = ucl_object_find_keyl(config, sbuf_data(ukey), sbuf_len(ukey)); if (strncasecmp(sbuf_data(ukey), "PACKAGESITE", sbuf_len(ukey)) == 0 || strncasecmp(sbuf_data(ukey), "PUBKEY", sbuf_len(ukey)) == 0 || strncasecmp(sbuf_data(ukey), "MIRROR_TYPE", sbuf_len(ukey)) == 0) { pkg_emit_error("%s in pkg.conf is no longer " "supported. Convert to the new repository style." " See pkg.conf(5)", sbuf_data(ukey)); fatal_errors = true; continue; } /* ignore unknown keys */ if (object == NULL) continue; if (object->type != cur->type) { pkg_emit_error("Malformed key %s, ignoring", key); continue; } if (ncfg == NULL) ncfg = ucl_object_typed_new(UCL_OBJECT); ucl_object_insert_key(ncfg, ucl_object_copy(cur), sbuf_data(ukey), sbuf_len(ukey), true); } if (fatal_errors) { ucl_object_unref(ncfg); ucl_parser_free(p); return (EPKG_FATAL); } if (ncfg != NULL) { it = NULL; while (( cur = ucl_iterate_object(ncfg, &it, true))) { key = ucl_object_key(cur); ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), true); } ucl_object_unref(ncfg); } ncfg = NULL; it = NULL; while ((cur = ucl_iterate_object(config, &it, true))) { o = NULL; key = ucl_object_key(cur); val = getenv(key); if (val == NULL) continue; switch (cur->type) { case UCL_STRING: o = ucl_object_fromstring_common(val, 0, UCL_STRING_TRIM); break; case UCL_INT: o = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_INT); if (o->type != UCL_INT) { pkg_emit_error("Invalid type for environment " "variable %s, got %s, while expecting an integer", key, val); ucl_object_unref(o); continue; } break; case UCL_BOOLEAN: o = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_BOOLEAN); if (o->type != UCL_BOOLEAN) { pkg_emit_error("Invalid type for environment " "variable %s, got %s, while expecting a boolean", key, val); ucl_object_unref(o); continue; } break; case UCL_OBJECT: o = ucl_object_typed_new(UCL_OBJECT); walk = buf = val; while ((buf = strchr(buf, ',')) != NULL) { k = walk; value = walk; while (*value != ',') { if (*value == '=') break; value++; } ucl_object_insert_key(o, ucl_object_fromstring_common(value + 1, buf - value - 1, UCL_STRING_TRIM), k, value - k, false); buf++; walk = buf; } key = walk; value = walk; while (*value != '\0') { if (*value == '=') break; value++; } ucl_object_insert_key(o, ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM), k, value - k, false); break; case UCL_ARRAY: o = ucl_object_typed_new(UCL_ARRAY); walk = buf = val; while ((buf = strchr(buf, ',')) != NULL) { ucl_array_append(o, ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM)); buf++; walk = buf; } ucl_array_append(o, ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM)); break; default: /* ignore other types */ break; } if (o != NULL) { if (ncfg == NULL) ncfg = ucl_object_typed_new(UCL_OBJECT); ucl_object_insert_key(ncfg, o, key, strlen(key), true); } } if (ncfg != NULL) { it = NULL; while (( cur = ucl_iterate_object(ncfg, &it, true))) { key = ucl_object_key(cur); ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), true); } ucl_object_unref(ncfg); } disable_plugins_if_static(); parsed = true; ucl_object_unref(obj); ucl_parser_free(p); if (strcmp(pkg_object_string(pkg_config_get("ABI")), "unknown") == 0) { pkg_emit_error("Unable to determine ABI"); return (EPKG_FATAL); } pkg_debug(1, "%s", "pkg initialized"); /* Start the event pipe */ evpipe = pkg_object_string(pkg_config_get("EVENT_PIPE")); if (evpipe != NULL) connect_evpipe(evpipe); debug_level = pkg_object_int(pkg_config_get("DEBUG_LEVEL")); it = NULL; object = ucl_object_find_key(config, "PKG_ENV"); while ((cur = ucl_iterate_object(object, &it, true))) { evkey = ucl_object_key(cur); pkg_debug(1, "Setting env var: %s", evkey); if (evkey != NULL && evkey[0] != '\0') setenv(evkey, ucl_object_tostring_forced(cur), 1); } /* load the repositories */ load_repositories(reposdir, flags); setenv("HTTP_USER_AGENT", "pkg/"PKGVERSION, 1); /* bypass resolv.conf with specified NAMESERVER if any */ nsname = pkg_object_string(pkg_config_get("NAMESERVER")); if (nsname != NULL) set_nameserver(ucl_object_tostring_forced(o)); return (EPKG_OK); }
int config_init(void) { char *val; int i; const char *localbase; char *env_list_item; char confpath[MAXPATHLEN]; struct config_value *cv; char abi[BUFSIZ]; for (i = 0; i < CONFIG_SIZE; i++) { val = getenv(c[i].key); if (val != NULL) { c[i].envset = true; switch (c[i].type) { case PKG_CONFIG_LIST: /* Split up comma-separated items from env. */ c[i].list = malloc(sizeof(*c[i].list)); STAILQ_INIT(c[i].list); for (env_list_item = strtok(val, ","); env_list_item != NULL; env_list_item = strtok(NULL, ",")) { cv = malloc(sizeof(struct config_value)); cv->value = strdup(env_list_item); STAILQ_INSERT_TAIL(c[i].list, cv, next); } break; default: c[i].val = val; break; } } } /* Read LOCALBASE/etc/pkg.conf first. */ localbase = getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE; snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf", localbase); if (access(confpath, F_OK) == 0 && read_conf_file(confpath, CONFFILE_PKG)) goto finalize; /* Then read in all repos from REPOS_DIR list of directories. */ if (c[REPOS_DIR].list == NULL) { c[REPOS_DIR].list = malloc(sizeof(*c[REPOS_DIR].list)); STAILQ_INIT(c[REPOS_DIR].list); cv = malloc(sizeof(struct config_value)); cv->value = strdup("/etc/pkg"); STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); cv = malloc(sizeof(struct config_value)); if (asprintf(&cv->value, "%s/etc/pkg/repos", localbase) < 0) goto finalize; STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); } STAILQ_FOREACH(cv, c[REPOS_DIR].list, next) if (load_repositories(cv->value)) goto finalize; finalize: if (c[ABI].val == NULL && c[ABI].value == NULL) { if (pkg_get_myabi(abi, BUFSIZ) != 0) errx(EXIT_FAILURE, "Failed to determine the system " "ABI"); c[ABI].val = abi; } subst_packagesite(c[ABI].value != NULL ? c[ABI].value : c[ABI].val); return (0); }