Browse Source

lib: Add unfinished kdb.c

Serj Kalichev 3 years ago
parent
commit
76312ec57c
1 changed files with 197 additions and 0 deletions
  1. 197 0
      klish/kscheme/kdb.c

+ 197 - 0
klish/kscheme/kdb.c

@@ -0,0 +1,197 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <dlfcn.h>
+
+#include <faux/str.h>
+#include <faux/list.h>
+#include <faux/conv.h>
+#include <faux/error.h>
+#include <klish/khelper.h>
+#include <klish/kdb.h>
+#include <klish/ksym.h>
+
+
+struct kdb_s {
+	char *name;
+	char *sofile;
+	char *options;
+	uint8_t major;
+	uint8_t minor;
+	void *dlhan; // dlopen() handler
+	void *init_fn;
+	void *fini_fn;
+	void *load_fn;
+	void *deploy_fn;
+	void *udata; // User data
+};
+
+
+// Simple methods
+
+// Name
+KGET_STR(db, name);
+
+// ID
+KGET_STR(db, id);
+KSET_STR(db, id);
+
+// File
+KGET_STR(db, file);
+KSET_STR(db, file);
+
+// Conf
+KGET_STR(db, conf);
+KSET_STR(db, conf);
+
+// Version major number
+KGET(db, uint8_t, major);
+KSET(db, uint8_t, major);
+
+// Version minor number
+KGET(db, uint8_t, minor);
+KSET(db, uint8_t, minor);
+
+// User data
+KGET(db, void *, udata);
+KSET(db, void *, udata);
+
+// COMMAND list
+static KCMP_NESTED(db, sym, name);
+static KCMP_NESTED_BY_KEY(db, sym, name);
+KADD_NESTED(db, sym);
+KFIND_NESTED(db, sym);
+KNESTED_LEN(db, sym);
+KNESTED_ITER(db, sym);
+KNESTED_EACH(db, sym);
+
+
+kdb_t *kdb_new(const char *name)
+{
+	kdb_t *db = NULL;
+
+	if (faux_str_is_empty(name))
+		return NULL;
+
+	db = faux_zmalloc(sizeof(*db));
+	assert(db);
+	if (!db)
+		return NULL;
+
+	// Initialize
+	db->name = faux_str_dup(name);
+	db->id = NULL;
+	db->file = NULL;
+	db->conf = NULL;
+	db->major = 0;
+	db->minor = 0;
+	db->dlhan = NULL;
+	db->init_fn = NULL;
+	db->fini_fn = NULL;
+	db->udata = NULL;
+
+	// SYM list
+	db->syms = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_UNIQUE,
+		kdb_sym_compare, kdb_sym_kcompare,
+		(void (*)(void *))ksym_free);
+	assert(db->syms);
+
+	return db;
+}
+
+
+void kdb_free(kdb_t *db)
+{
+	if (!db)
+		return;
+
+	faux_str_free(db->name);
+	faux_str_free(db->id);
+	faux_str_free(db->file);
+	faux_str_free(db->conf);
+	faux_list_free(db->syms);
+
+	if (db->dlhan)
+		dlclose(db->dlhan);
+
+	faux_free(db);
+}
+
+
+bool_t kdb_load(kdb_t *db)
+{
+	char *file_name = NULL;
+	char *init_name = NULL;
+	char *fini_name = NULL;
+	char *major_name = NULL;
+	char *minor_name = NULL;
+	int flag = RTLD_NOW | RTLD_LOCAL;
+	const char *id = NULL;
+	bool_t retcode = BOOL_FALSE;
+	uint8_t *ver = NULL;
+
+	assert(db);
+	if (!db)
+		return BOOL_FALSE;
+
+	if (kdb_id(db))
+		id = kdb_id(db);
+	else
+		id = kdb_name(db);
+
+	// Shared object file name
+	if (kdb_file(db))
+		file_name = faux_str_dup(kdb_file(db));
+	else
+		file_name = faux_str_sprintf(Kdb_SONAME_FMT, id);
+
+	// Symbol names
+	major_name = faux_str_sprintf(Kdb_MAJOR_FMT, id);
+	minor_name = faux_str_sprintf(Kdb_MINOR_FMT, id);
+	init_name = faux_str_sprintf(Kdb_INIT_FMT, id);
+	fini_name = faux_str_sprintf(Kdb_FINI_FMT, id);
+
+	// Open shared object
+	db->dlhan = dlopen(file_name, flag);
+	if (!db->dlhan) {
+//		fprintf(stderr, "Error: Can't open db \"%s\": %s\n",
+//			this->name, dlerror());
+		goto err;
+	}
+
+	// Get db version
+	ver = (uint8_t *)dlsym(db->dlhan, major_name);
+	if (!ver)
+		goto err;
+	kdb_set_major(db, *ver);
+	ver = (uint8_t *)dlsym(db->dlhan, minor_name);
+	if (!ver)
+		goto err;
+	kdb_set_minor(db, *ver);
+
+	// Get db init function
+	db->init_fn = dlsym(db->dlhan, init_name);
+	if (!db->init_fn) {
+//		fprintf(stderr, "Error: Can't get db \"%s\" init function: %s\n",
+//			this->name, dlerror());
+		goto err;
+	}
+
+	// Get db fini function
+	db->fini_fn = dlsym(db->dlhan, fini_name);
+
+	retcode = BOOL_TRUE;
+err:
+	faux_str_free(file_name);
+	faux_str_free(major_name);
+	faux_str_free(minor_name);
+	faux_str_free(init_name);
+	faux_str_free(fini_name);
+
+	if (!retcode && db->dlhan)
+		dlclose(db->dlhan);
+
+	return retcode;
+}