osmo-config-merge: Fix some small issues

Allocate NULL context after exit_usage() calls and free it before exit
so * sanitizer is happy.
Also handle the error cases gracefully when a file is unreadable or
formatted wrong.

Change-Id: I966e63a3f7d0ff71ee0b88922aa3807d073aa232
diff --git a/utils/osmo-config-merge.c b/utils/osmo-config-merge.c
index c76e42d..a872d64 100644
--- a/utils/osmo-config-merge.c
+++ b/utils/osmo-config-merge.c
@@ -44,6 +44,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <errno.h>
 
 #include <osmocom/core/linuxlist.h>
 #include <osmocom/core/talloc.h>
@@ -126,8 +127,11 @@
 	unsigned int line_num = 0;
 
 	infile = fopen(fname, "r");
-	if (!infile)
+	if (!infile) {
+		fprintf(stderr, "Could not open file '%s': %s\n",
+			fname, strerror(errno));
 		return NULL;
+	}
 
 	root = node_alloc(ctx);
 	last = root;
@@ -140,7 +144,7 @@
 			if (indent > cur_indent+1) {
 				fprintf(stderr, "File '%s' isn't well-formed in line %u, aborting!\n",
 					fname, line_num);
-				exit(2);
+				return NULL;
 			}
 			/* new child to last node */
 			n = node_alloc_child(last);
@@ -229,8 +233,7 @@
 	const char *base_fname, *patch_fname;
 	struct node *base_tree, *patch_tree;
 	bool debug_enabled = false;
-
-	void *ctx = talloc_named_const(NULL, 0, "root");
+	void *ctx;
 
 	if (argc < 3)
 		exit_usage(1);
@@ -245,9 +248,16 @@
 			exit_usage(1);
 	}
 
+	ctx = talloc_named_const(NULL, 0, "root");
+
 	base_tree = file_read(ctx, base_fname);
 	patch_tree = file_read(ctx, patch_fname);
 
+	if (!base_tree || ! patch_tree) {
+		talloc_free(ctx);
+		return 2;
+	}
+
 	if (debug_enabled) {
 		fprintf(stderr, "====== dumping tree (base)\n");
 		dump_node(base_tree, stderr, true);
@@ -265,6 +275,7 @@
 	/* make AddressSanitizer / LeakSanitizer happy by recursively freeing the trees */
 	talloc_free(patch_tree);
 	talloc_free(base_tree);
+	talloc_free(ctx);
 
 	return 0;
 }