static void load_repo_file(const char *repofile) { struct ucl_parser *p; ucl_object_t *obj = NULL; bool fallback = false; const char *myarch = NULL; p = ucl_parser_new(0); myarch = pkg_object_string(pkg_config_get("ABI")); ucl_parser_register_variable (p, "ABI", myarch); pkg_debug(1, "PKgConfig: loading %s", repofile); if (!ucl_parser_add_file(p, repofile)) { pkg_emit_error("Error parsing: %s: %s", repofile, ucl_parser_get_error(p)); if (errno == ENOENT) { ucl_parser_free(p); return; } fallback = true; } if (fallback) { obj = yaml_to_ucl(repofile, NULL, 0); if (obj == NULL) return; } if (fallback) { pkg_emit_error("%s file is using a deprecated format. " "Please replace it with the following:\n" "====== BEGIN %s ======\n" "%s" "\n====== END %s ======\n", repofile, repofile, ucl_object_emit(obj, UCL_EMIT_YAML), repofile); } obj = ucl_parser_get_object(p); if (obj->type == UCL_OBJECT) walk_repo_obj(obj, repofile); ucl_object_free(obj); }
/** * Entry point. */ int main(int argc, char **argv) { // Parse program options char *config_file = NULL; bool server = false; bool collector = false; bool callibrator = false; bool status_only = false; int log_option = 0; char c; while ((c = getopt(argc, argv, "hc:sdflr")) != EOF) { switch (c) { case 'h': { show_help(argv[0]); return 1; } case 'c': config_file = strdup(optarg); break; case 's': status_only = true; break; case 'd': server = true; break; case 'l': collector = true; break; case 'r': callibrator = true; break; case 'f': log_option |= LOG_PERROR; break; default: { fprintf(stderr, "ERROR: Invalid option %c!\n", c); show_help(argv[0]); return 1; } } } if (config_file == NULL) config_file = strdup("/etc/koruza.cfg"); // Load the configuration file struct ucl_parser *parser = ucl_parser_new(UCL_PARSER_KEY_LOWERCASE); ucl_object_t *config = NULL; ucl_object_t *obj = NULL; int ret_value = 0; if (!parser) { fprintf(stderr, "ERROR: Failed to initialize configuration parser!\n"); return 2; } if (!ucl_parser_add_file(parser, config_file)) { fprintf(stderr, "ERROR: Failed to parse configuration file '%s'!\n", config_file); fprintf(stderr, "ERROR: %s\n", ucl_parser_get_error(parser)); ret_value = 2; goto cleanup_exit; } else { config = ucl_parser_get_object(parser); } if (server) { obj = ucl_object_find_key(config, "server"); if (!obj) { fprintf(stderr, "ERROR: Missing server configuration!\n"); ret_value = 2; goto cleanup_exit; } start_server(obj, log_option); } else if (collector) { start_collector(config, log_option); } else if (callibrator) { start_callibrator(config, log_option); } else { start_controller(config, status_only); } cleanup_exit: // Cleanup and exit if (config) ucl_object_free(config); if (parser) ucl_parser_free(parser); return ret_value; }
int pkg_init(const char *path, const char *reposdir) { 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; ucl_object_t *obj = NULL, *cur, *o, *ncfg; ucl_object_iter_t it = NULL; struct sbuf *ukey = NULL; pkg_get_myarch(myabi, BUFSIZ); if (parsed != false) { pkg_emit_error("pkg_init() must only be called once"); return (EPKG_FATAL); } 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); config = ucl_object_insert_key(config, obj, c[i].key, strlen(c[i].key), false); break; case PKG_INT: config = 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: config = 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 = NULL; if (c[i].def == NULL) { obj = ucl_object_typed_new(UCL_OBJECT); } else { walk = buf = c[i].def; while ((buf = strchr(buf, ',')) != NULL) { key = walk; value = walk; while (*value != ',') { if (*value == '=') break; value++; } obj = 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++; } o = ucl_object_insert_key(o, ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM), key, value - key, false); } config = ucl_object_insert_key(config, obj, c[i].key, strlen(c[i].key), false); break; case PKG_ARRAY: obj = NULL; if (c[i].def == NULL) { obj = ucl_object_typed_new(UCL_ARRAY); } else { walk = buf = c[i].def; while ((buf = strchr(buf, ',')) != NULL) { obj = ucl_array_append(obj, ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM)); buf++; walk = buf; } obj = ucl_array_append(obj, ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM)); } config = 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("%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_done(ukey); o = ucl_object_find_keyl(config, sbuf_data(ukey), sbuf_len(ukey)); /* ignore unknown keys */ if (o == NULL) continue; if (o->type != cur->type) { pkg_emit_error("Malformed key %s, ignoring", key); continue; } ncfg = ucl_object_insert_key(ncfg, ucl_object_ref(cur), key, strlen(key), false); } if (ncfg != NULL) { it = NULL; while (( cur = ucl_iterate_object(ncfg, &it, true))) { key = ucl_object_key(cur); config = ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), false); } 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_free(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_free(o); continue; } break; case UCL_OBJECT: walk = buf = val; while ((buf = strchr(buf, ',')) != NULL) { k = walk; value = walk; while (*value != ',') { if (*value == '=') break; value++; } o = 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++; } o = 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: walk = buf = val; while ((buf = strchr(buf, ',')) != NULL) { o = ucl_array_append(o, ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM)); buf++; walk = buf; } o = ucl_array_append(o, ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM)); break; default: /* ignore other types */ break; } if (o != NULL) ncfg = 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); config = ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), false); } ucl_object_unref(ncfg); } disable_plugins_if_static(); parsed = true; ucl_object_unref(obj); ucl_parser_free(p); 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); it = NULL; o = ucl_object_find_key(config, "PKG_ENV"); while ((cur = ucl_iterate_object(o, &it, true))) { evkey = ucl_object_key(cur); if (evkey != NULL && evkey[0] != '\0') setenv(evkey, ucl_object_tostring_forced(cur), 1); } /* load the repositories */ load_repositories(reposdir); 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); }
static void add_repo(ucl_object_t *obj, struct pkg_repo *r, const char *rname) { ucl_object_t *cur, *tmp = NULL; ucl_object_iter_t it = NULL; bool enable = true; const char *url = NULL, *pubkey = NULL, *mirror_type = NULL; const char *signature_type = NULL, *fingerprints = NULL; const char *key; pkg_debug(1, "PkgConfig: parsing repository object %s", rname); while ((cur = ucl_iterate_object(obj, &it, true))) { key = ucl_object_key(cur); if (key == NULL) continue; if (strcasecmp(key, "url") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } url = ucl_object_tostring(cur); } else if (strcasecmp(key, "pubkey") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } pubkey = ucl_object_tostring(cur); } else if (strcasecmp(key, "enabled") == 0) { if (cur->type == UCL_STRING) tmp = ucl_object_fromstring_common(ucl_object_tostring(cur), strlen(ucl_object_tostring(cur)), UCL_STRING_PARSE_BOOLEAN); if (cur->type != UCL_BOOLEAN && (tmp != NULL && tmp->type != UCL_BOOLEAN)) { pkg_emit_error("Expecting a boolean for the " "'%s' key of the '%s' repo", key, rname); if (tmp != NULL) ucl_object_free(tmp); return; } if (tmp != NULL) pkg_emit_error("Warning: expecting a boolean for the '%s' key of the '%s' repo, " " the value has been correctly converted, please consider fixing", key, rname); enable = ucl_object_toboolean(tmp != NULL ? tmp : cur); if (tmp != NULL) ucl_object_free(tmp); } else if (strcasecmp(key, "mirror_type") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } mirror_type = ucl_object_tostring(cur); } else if (strcasecmp(key, "signature_type") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } signature_type = ucl_object_tostring(cur); } else if (strcasecmp(key, "fingerprints") == 0) { if (cur->type != UCL_STRING) { pkg_emit_error("Expecting a string for the " "'%s' key of the '%s' repo", key, rname); return; } fingerprints = ucl_object_tostring(cur); } } if (r == NULL && url == NULL) { pkg_debug(1, "No repo and no url for %s", rname); return; } if (r == NULL) r = pkg_repo_new(rname, url); if (signature_type != NULL) { if (strcasecmp(signature_type, "pubkey") == 0) r->signature_type = SIG_PUBKEY; else if (strcasecmp(signature_type, "fingerprints") == 0) r->signature_type = SIG_FINGERPRINT; else r->signature_type = SIG_NONE; } if (fingerprints != NULL) { free(r->fingerprints); r->fingerprints = strdup(fingerprints); } if (pubkey != NULL) { free(r->pubkey); r->pubkey = strdup(pubkey); } r->enable = enable; if (mirror_type != NULL) { if (strcasecmp(mirror_type, "srv") == 0) r->mirror_type = SRV; else if (strcasecmp(mirror_type, "http") == 0) r->mirror_type = HTTP; else r->mirror_type = NOMIRROR; } }
int main (int argc, char **argv) { ucl_object_t *obj, *cur, *ar, *ar1, *ref, *test_obj, *comments; ucl_object_iter_t it; const ucl_object_t *found, *it_obj, *test; struct ucl_emitter_functions *fn; FILE *out; unsigned char *emitted; const char *fname_out = NULL; struct ucl_parser *parser; int ret = 0; switch (argc) { case 2: fname_out = argv[1]; break; } if (fname_out != NULL) { out = fopen (fname_out, "w"); if (out == NULL) { exit (-errno); } } else { out = stdout; } obj = ucl_object_typed_new (UCL_OBJECT); /* Keys replacing */ cur = ucl_object_fromstring_common ("value1", 0, UCL_STRING_TRIM); ucl_object_insert_key (obj, cur, "key0", 0, false); cur = ucl_object_fromdouble (0.1); assert (ucl_object_replace_key (obj, cur, "key0", 0, false)); /* Create some strings */ cur = ucl_object_fromstring_common (" test string ", 0, UCL_STRING_TRIM); ucl_object_insert_key (obj, cur, "key1", 0, false); cur = ucl_object_fromstring_common (" test \nstring\n\r\n\b\t\f\\\" ", 0, UCL_STRING_TRIM | UCL_STRING_ESCAPE); ucl_object_insert_key (obj, cur, "key2", 0, false); cur = ucl_object_fromstring_common (" test string \n", 0, 0); ucl_object_insert_key (obj, cur, "key3", 0, false); /* Array of numbers */ ar = ucl_object_typed_new (UCL_ARRAY); cur = ucl_object_fromint (10); ucl_array_append (ar, cur); assert (ucl_array_index_of (ar, cur) == 0); cur = ucl_object_fromdouble (10.1); ucl_array_append (ar, cur); assert (ucl_array_index_of (ar, cur) == 1); cur = ucl_object_fromdouble (9.999); ucl_array_prepend (ar, cur); assert (ucl_array_index_of (ar, cur) == 0); ar1 = ucl_object_copy (ar); cur = ucl_object_fromstring ("abc"); ucl_array_prepend (ar1, cur); cur = ucl_object_fromstring ("cde"); ucl_array_prepend (ar1, cur); cur = ucl_object_fromstring ("аАаБаВ"); /* UTF8 */ ucl_array_prepend (ar1, cur); cur = ucl_object_fromstring ("ааБаВ"); /* UTF8 */ ucl_array_prepend (ar1, cur); /* * This is ususally broken or fragile as utf collate is far from perfect cur = ucl_object_fromstring ("баБаВ"); ucl_array_prepend (ar1, cur); cur = ucl_object_fromstring ("ааБаВ"); // hello to @bapt ucl_array_prepend (ar1, cur); */ cur = ucl_object_fromstring ("№"); /* everybody likes emoji in the code */ ucl_array_prepend (ar1, cur); ucl_object_array_sort (ar1, ucl_object_compare_qsort); /* Removing from an array */ cur = ucl_object_fromdouble (1.0); ucl_array_append (ar, cur); cur = ucl_array_delete (ar, cur); assert (ucl_object_todouble (cur) == 1.0); ucl_object_unref (cur); cur = ucl_object_fromdouble (2.0); ucl_array_append (ar, cur); cur = ucl_array_pop_last (ar); assert (ucl_object_todouble (cur) == 2.0); ucl_object_unref (cur); cur = ucl_object_fromdouble (3.0); ucl_array_prepend (ar, cur); cur = ucl_array_pop_first (ar); assert (ucl_object_todouble (cur) == 3.0); ucl_object_unref (cur); ucl_object_insert_key (obj, ar, "key4", 0, false); cur = ucl_object_frombool (true); /* Ref object to test refcounts */ ref = ucl_object_ref (cur); ucl_object_insert_key (obj, cur, "key4", 0, false); /* Empty strings */ cur = ucl_object_fromstring_common (" ", 0, UCL_STRING_TRIM); ucl_object_insert_key (obj, cur, "key5", 0, false); cur = ucl_object_fromstring_common ("", 0, UCL_STRING_ESCAPE); ucl_object_insert_key (obj, cur, "key6", 0, false); cur = ucl_object_fromstring_common (" \n", 0, UCL_STRING_ESCAPE); ucl_object_insert_key (obj, cur, "key7", 0, false); /* Numbers and booleans */ cur = ucl_object_fromstring_common ("1mb", 0, UCL_STRING_ESCAPE | UCL_STRING_PARSE); ucl_object_insert_key (obj, cur, "key8", 0, false); cur = ucl_object_fromstring_common ("3.14", 0, UCL_STRING_PARSE); ucl_object_insert_key (obj, cur, "key9", 0, false); cur = ucl_object_fromstring_common ("true", 0, UCL_STRING_PARSE); ucl_object_insert_key (obj, cur, "key10", 0, false); cur = ucl_object_fromstring_common (" off ", 0, UCL_STRING_PARSE | UCL_STRING_TRIM); ucl_object_insert_key (obj, cur, "key11", 0, false); cur = ucl_object_fromstring_common ("*****@*****.**", 0, UCL_STRING_PARSE_INT); ucl_object_insert_key (obj, cur, "key12", 0, false); cur = ucl_object_fromstring_common ("#test", 0, UCL_STRING_PARSE_INT); ucl_object_insert_key (obj, cur, "key13", 0, false); cur = ucl_object_frombool (true); ucl_object_insert_key (obj, cur, "k=3", 0, false); ucl_object_insert_key (obj, ar1, "key14", 0, false); cur = ucl_object_new_userdata (ud_dtor, ud_emit, NULL); ucl_object_insert_key (obj, cur, "key15", 0, false); /* More tests for keys */ cur = ucl_object_fromlstring ("test", 3); ucl_object_insert_key (obj, cur, "key16", 0, false); test = ucl_object_lookup_any (obj, "key100", "key200", "key300", "key16", NULL); assert (test == cur); test = ucl_object_lookup_len (obj, "key160", 5); assert (test == cur); cur = ucl_object_pop_key (obj, "key16"); assert (test == cur); test = ucl_object_pop_key (obj, "key16"); assert (test == NULL); test = ucl_object_lookup_len (obj, "key160", 5); assert (test == NULL); /* Objects merging tests */ test_obj = ucl_object_new_full (UCL_OBJECT, 2); ucl_object_insert_key (test_obj, cur, "key16", 0, true); ucl_object_merge (obj, test_obj, true); ucl_object_unref (test_obj); /* Array merging test */ test_obj = ucl_object_new_full (UCL_ARRAY, 3); ucl_array_append (test_obj, ucl_object_fromstring ("test")); ucl_array_merge (test_obj, ar1, false); ucl_object_insert_key (obj, test_obj, "key17", 0, true); /* Object deletion */ cur = ucl_object_fromstring ("test"); ucl_object_insert_key (obj, cur, "key18", 0, true); assert (ucl_object_delete_key (obj, "key18")); assert (!ucl_object_delete_key (obj, "key18")); cur = ucl_object_fromlstring ("test", 4); ucl_object_insert_key (obj, cur, "key18\0\0", 7, true); assert (ucl_object_lookup_len (obj, "key18\0\0", 7) == cur); assert (ucl_object_lookup (obj, "key18") == NULL); assert (ucl_object_lookup_len (obj, "key18\0\1", 7) == NULL); assert (ucl_object_delete_keyl (obj, "key18\0\0", 7)); /* Comments */ comments = ucl_object_typed_new (UCL_OBJECT); found = ucl_object_lookup (obj, "key17"); test = ucl_object_lookup (obj, "key16"); ucl_comments_add (comments, found, "# test comment"); assert (ucl_comments_find (comments, found) != NULL); assert (ucl_comments_find (comments, test) == NULL); ucl_comments_move (comments, found, test); assert (ucl_comments_find (comments, found) == NULL); assert (ucl_comments_find (comments, test) != NULL); /* Array replace */ ar1 = ucl_object_typed_new (UCL_ARRAY); cur = ucl_object_fromstring ("test"); cur = ucl_elt_append (cur, ucl_object_fromstring ("test1")); ucl_array_append (ar1, cur); test = ucl_array_replace_index (ar1, ucl_object_fromstring ("test2"), 0); assert (test == cur); /* Try to find using path */ /* Should exist */ found = ucl_object_lookup_path (obj, "key4.1"); assert (found != NULL && ucl_object_toint (found) == 10); /* . should be ignored */ found = ucl_object_lookup_path (obj, ".key4.1"); assert (found != NULL && ucl_object_toint (found) == 10); /* moar dots... */ found = ucl_object_lookup_path (obj, ".key4........1..."); assert (found != NULL && ucl_object_toint (found) == 10); /* No such index */ found = ucl_object_lookup_path (obj, ".key4.3"); assert (found == NULL); /* No such key */ found = ucl_object_lookup_path (obj, "key9..key1"); assert (found == NULL); /* Test iteration */ it = ucl_object_iterate_new (obj); it_obj = ucl_object_iterate_safe (it, true); /* key0 = 0.1 */ assert (ucl_object_type (it_obj) == UCL_FLOAT); it_obj = ucl_object_iterate_safe (it, true); /* key1 = "" */ assert (ucl_object_type (it_obj) == UCL_STRING); it_obj = ucl_object_iterate_safe (it, true); /* key2 = "" */ assert (ucl_object_type (it_obj) == UCL_STRING); it_obj = ucl_object_iterate_safe (it, true); /* key3 = "" */ assert (ucl_object_type (it_obj) == UCL_STRING); it_obj = ucl_object_iterate_safe (it, true); /* key4 = ([float, int, float], boolean) */ ucl_object_iterate_reset (it, it_obj); it_obj = ucl_object_iterate_safe (it, true); assert (ucl_object_type (it_obj) == UCL_FLOAT); it_obj = ucl_object_iterate_safe (it, true); assert (ucl_object_type (it_obj) == UCL_INT); it_obj = ucl_object_iterate_safe (it, true); assert (ucl_object_type (it_obj) == UCL_FLOAT); it_obj = ucl_object_iterate_safe (it, true); assert (ucl_object_type (it_obj) == UCL_BOOLEAN); ucl_object_iterate_free (it); fn = ucl_object_emit_memory_funcs (&emitted); assert (ucl_object_emit_full (obj, UCL_EMIT_CONFIG, fn, comments)); fprintf (out, "%s\n", emitted); ucl_object_emit_funcs_free (fn); ucl_object_unref (obj); ucl_object_unref (comments); parser = ucl_parser_new (UCL_PARSER_NO_IMPLICIT_ARRAYS); if (ucl_parser_add_chunk_full (parser, emitted, strlen (emitted), 3, UCL_DUPLICATE_ERROR, UCL_PARSE_UCL)) { /* Should fail due to duplicate */ assert (0); } else { assert (ucl_parser_get_error (parser) != NULL); ucl_parser_clear_error (parser); ucl_parser_free (parser); parser = ucl_parser_new (0); ucl_parser_add_chunk_full (parser, emitted, strlen (emitted), 3, UCL_DUPLICATE_MERGE, UCL_PARSE_UCL); } assert (ucl_parser_get_column (parser) == 0); assert (ucl_parser_get_linenum (parser) != 0); ucl_parser_clear_error (parser); assert (ucl_parser_get_error_code (parser) == 0); obj = ucl_parser_get_object (parser); ucl_parser_free (parser); ucl_object_free (obj); if (emitted != NULL) { free (emitted); } fclose (out); /* Ref should still be accessible */ ref->value.iv = 100500; ucl_object_unref (ref); return ret; }