From 887b31ee12704e8c9da3bf4d26801d9236146192 Mon Sep 17 00:00:00 2001
From: sinanmohd <sinan@sinanmohd.com>
Date: Tue, 3 Sep 2024 18:58:49 +0530
Subject: nix: init

---
 include/nix.h   |  4 ++++
 meson.build     |  1 +
 src/evanix.c    | 51 +++++++++++++++++++++++++++++++++++++++++++++++----
 src/jobs.c      | 18 ++++++++----------
 src/meson.build |  9 ++++++++-
 src/nix.c       | 42 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 110 insertions(+), 15 deletions(-)
 create mode 100644 include/nix.h
 create mode 100644 src/nix.c

diff --git a/include/nix.h b/include/nix.h
new file mode 100644
index 0000000..8533a82
--- /dev/null
+++ b/include/nix.h
@@ -0,0 +1,4 @@
+#include <nix/nix_api_value.h>
+
+void _nix_get_string_strdup(const char *str, unsigned n, void *user_data);
+int _nix_init(nix_c_context **nix_ctx);
diff --git a/meson.build b/meson.build
index 46c59d3..edb1055 100644
--- a/meson.build
+++ b/meson.build
@@ -19,6 +19,7 @@ add_project_arguments(
 )
 
 cjson_dep = dependency('libcjson')
+nix_store_dep = dependency('nix-store-c')
 highs_dep = dependency('highs')
 sqlite_dep = dependency('sqlite3')
 evanix_inc = include_directories('include')
diff --git a/src/evanix.c b/src/evanix.c
index 92f9596..25bbd8e 100644
--- a/src/evanix.c
+++ b/src/evanix.c
@@ -1,10 +1,12 @@
 #include <errno.h>
 #include <getopt.h>
+#include <nix/nix_api_value.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "build.h"
 #include "evanix.h"
+#include "nix.h"
 #include "queue.h"
 #include "solver_conformity.h"
 #include "solver_highs.h"
@@ -52,6 +54,8 @@ static int evanix(char *expr);
 static int evanix_free(struct evanix_opts_t *opts);
 static int opts_read(struct evanix_opts_t *opts, char **expr, int argc,
 		     char *argv[]);
+static int evanix_opts_system_set(struct evanix_opts_t *opts,
+				  nix_c_context *nix_ctx);
 
 /* This function returns errno on failure, consistent with the POSIX threads
  * functions, rather than returning -errno. */
@@ -71,13 +75,42 @@ static int evanix_build_thread_create(struct build_thread *build_thread)
 	return 0;
 }
 
+static int evanix_opts_system_set(struct evanix_opts_t *opts,
+				  nix_c_context *nix_ctx)
+{
+	nix_err nix_ret;
+
+	if (opts->system)
+		return 0;
+
+	nix_ret = nix_setting_get(nix_ctx, "system", _nix_get_string_strdup,
+				  &opts->system);
+	if (nix_ret != NIX_OK) {
+		print_err("%s", nix_err_msg(NULL, nix_ctx, NULL));
+		return -EPERM;
+	} else if (opts->system == NULL) {
+		return -EPERM;
+	}
+
+	return 0;
+}
+
 static int evanix(char *expr)
 {
+	nix_c_context *nix_ctx = NULL;
 	struct queue_thread *queue_thread = NULL;
 	struct build_thread *build_thread = NULL;
 	FILE *jobs_stream = NULL; /* nix-eval-jobs stdout */
 	int ret = 0;
 
+	ret = _nix_init(&nix_ctx);
+	if (ret < 0)
+		goto out_free;
+
+	ret = evanix_opts_system_set(&evanix_opts, nix_ctx);
+	if (ret < 0)
+		goto out_free;
+
 	ret = jobs_init(&jobs_stream, expr);
 	if (ret < 0)
 		goto out_free;
@@ -127,6 +160,7 @@ static int evanix(char *expr)
 	}
 
 out_free:
+	nix_c_context_free(nix_ctx);
 	fclose(jobs_stream);
 	queue_thread_free(queue_thread);
 	free(build_thread);
@@ -182,7 +216,13 @@ static int opts_read(struct evanix_opts_t *opts, char **expr, int argc,
 			opts->isdryrun = true;
 			break;
 		case 's':
-			opts->system = optarg;
+			opts->system = strdup(optarg);
+			if (opts->system == NULL) {
+				print_err("%s", strerror(errno));
+				ret = -errno;
+				goto out_free_evanix;
+			}
+
 			break;
 		case 'r':
 			opts->solver_report = true;
@@ -194,7 +234,8 @@ static int opts_read(struct evanix_opts_t *opts, char **expr, int argc,
 					"Try 'evanix --help' for more "
 					"information.\n",
 					c);
-				return -EINVAL;
+				ret = -EINVAL;
+				goto out_free_evanix;
 			}
 
 			ret = sqlite3_open_v2(optarg, &opts->statistics.db,
@@ -212,7 +253,8 @@ static int opts_read(struct evanix_opts_t *opts, char **expr, int argc,
 						 NULL);
 			if (ret != SQLITE_OK) {
 				print_err("%s", "Failed to prepare sql");
-				return -EPERM;
+				ret = -EPERM;
+				goto out_free_evanix;
 			}
 
 			break;
@@ -351,11 +393,12 @@ static int evanix_free(struct evanix_opts_t *opts)
 {
 	int ret;
 
+	free(opts->system);
+
 	if (opts->statistics.statement) {
 		sqlite3_finalize(opts->statistics.statement);
 		opts->statistics.statement = NULL;
 	}
-
 	if (opts->statistics.db) {
 		ret = sqlite3_close(opts->statistics.db);
 		if (ret != SQLITE_OK) {
diff --git a/src/jobs.c b/src/jobs.c
index 41fa3f3..fa2e267 100644
--- a/src/jobs.c
+++ b/src/jobs.c
@@ -508,16 +508,14 @@ int job_read(FILE *stream, struct job **job)
 		goto out_free;
 	}
 
-	if (evanix_opts.system != NULL) {
-		temp = cJSON_GetObjectItemCaseSensitive(root, "system");
-		if (!cJSON_IsString(temp)) {
-			ret = JOB_READ_JSON_INVAL;
-			goto out_free;
-		}
-		if (strcmp(evanix_opts.system, temp->valuestring)) {
-			ret = JOB_READ_SYS_MISMATCH;
-			goto out_free;
-		}
+	temp = cJSON_GetObjectItemCaseSensitive(root, "system");
+	if (!cJSON_IsString(temp)) {
+		ret = JOB_READ_JSON_INVAL;
+		goto out_free;
+	}
+	if (strcmp(evanix_opts.system, temp->valuestring)) {
+		ret = JOB_READ_SYS_MISMATCH;
+		goto out_free;
 	}
 
 	temp = cJSON_GetObjectItemCaseSensitive(root, "name");
diff --git a/src/meson.build b/src/meson.build
index 03f045b..8a4158a 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -11,10 +11,17 @@ e = executable(
 		'solver_conformity.c',
 		'solver_highs.c',
 		'solver_sjf.c',
+		'nix.c',
+	],
+
+	dependencies: [
+		cjson_dep,
+		highs_dep,
+		sqlite_dep,
+		nix_store_dep
 	],
 
 	include_directories: evanix_inc,
-	dependencies: [ cjson_dep, highs_dep, sqlite_dep ],
 	install: true,
 	c_args: [f'-DNIX_EVAL_JOBS_PATH=@NIX_EVAL_JOBS_PATH@'],
 )
diff --git a/src/nix.c b/src/nix.c
new file mode 100644
index 0000000..f1b3a5a
--- /dev/null
+++ b/src/nix.c
@@ -0,0 +1,42 @@
+#include <errno.h>
+#include <string.h>
+
+#include "nix.h"
+#include "util.h"
+
+void _nix_get_string_strdup(const char *str, unsigned n, void *user_data)
+{
+	char **s = user_data;
+
+	*s = strndup(str, n);
+	if (*s == NULL)
+		print_err("%s", strerror(errno));
+}
+
+int _nix_init(nix_c_context **nix_ctx)
+{
+	nix_err nix_ret;
+	nix_c_context *nc;
+	int ret = 0;
+
+	nc = nix_c_context_create();
+	if (nix_ctx == NULL) {
+		print_err("%s", "Failed to create nix context");
+		return -EPERM;
+	}
+
+	nix_ret = nix_libstore_init(nc);
+	if (nix_ret != NIX_OK) {
+		print_err("%s", nix_err_msg(NULL, nc, NULL));
+		ret = -EPERM;
+		goto out_free_nc;
+	}
+
+out_free_nc:
+	if (ret < 0)
+		nix_c_context_free(nc);
+	else
+		*nix_ctx = nc;
+
+	return ret;
+}
-- 
cgit v1.2.3