Browse Source

kplugin: init and fini

Serj Kalichev 3 years ago
parent
commit
c2a54624d6
3 changed files with 245 additions and 2 deletions
  1. 5 0
      klish/kplugin.h
  2. 34 2
      klish/kscheme/kplugin.c
  3. 206 0
      klish/kscheme/kscheme.c

+ 5 - 0
klish/kplugin.h

@@ -31,6 +31,8 @@
 #define KPLUGIN_FINI_FMT "kplugin_%s_fini"
 
 
+typedef struct kcontext_s kcontext_t;
+
 typedef struct kplugin_s kplugin_t;
 
 typedef faux_list_node_t kplugin_syms_node_t;
@@ -54,6 +56,9 @@ uint8_t kplugin_minor(const kplugin_t *plugin);
 bool_t kplugin_set_minor(kplugin_t *plugin, uint8_t minor);
 void *kplugin_udata(const kplugin_t *plugin);
 bool_t kplugin_set_udata(kplugin_t *plugin, void *udata);
+bool_t kplugin_load(kplugin_t *plugin);
+int kplugin_init(kplugin_t *plugin, kcontext_t *context);
+int kplugin_fini(kplugin_t *plugin, kcontext_t *context);
 
 // syms
 bool_t kplugin_add_sym(kplugin_t *plugin, ksym_t *sym);

+ 34 - 2
klish/kscheme/kplugin.c

@@ -22,8 +22,8 @@ struct kplugin_s {
 	uint8_t major;
 	uint8_t minor;
 	void *dlhan; // dlopen() handler
-	void *init_fn;
-	void *fini_fn;
+	ksym_fn init_fn;
+	ksym_fn fini_fn;
 	void *udata; // User data
 	faux_list_t *syms;
 };
@@ -195,3 +195,35 @@ err:
 
 	return retcode;
 }
+
+
+int kplugin_init(kplugin_t *plugin, kcontext_t *context)
+{
+	assert(plugin);
+	if (!plugin)
+		return -1;
+	assert(context);
+	if (!context)
+		return -1;
+
+	if (!plugin->init_fn)
+		return -1;
+
+	return plugin->init_fn(context);
+}
+
+
+int kplugin_fini(kplugin_t *plugin, kcontext_t *context)
+{
+	assert(plugin);
+	if (!plugin)
+		return -1;
+	assert(context);
+	if (!context)
+		return -1;
+
+	if (!plugin->fini_fn)
+		return 0; // Fini function is not mandatory so it's ok
+
+	return plugin->fini_fn(context);
+}

+ 206 - 0
klish/kscheme/kscheme.c

@@ -89,3 +89,209 @@ void kscheme_free(kscheme_t *scheme)
 	faux_list_free(scheme->views);
 	faux_free(scheme);
 }
+
+#if 0
+/** @brief Prepares schema for execution.
+ *
+ * It loads plugins, link unresolved symbols, then iterates all the
+ * objects and link them to each other, check access
+ * permissions. Without this function the schema is not fully functional.
+ */
+int kscheme_prepare(kscheme_t *scheme)
+{
+	clish_command_t *cmd;
+	clish_view_t *view;
+	clish_nspace_t *nspace;
+	lub_list_t *view_tree, *nspace_tree;
+	lub_list_node_t *nspace_iter, *view_iter;
+	lub_bintree_t *cmd_tree;
+	lub_bintree_iterator_t cmd_iter;
+	clish_hook_access_fn_t *access_fn = NULL;
+	clish_paramv_t *paramv;
+	int i = 0;
+
+	/* Add statically linked plugins */
+	while (clish_plugin_builtin_list[i].name) {
+		clish_plugin_t *plugin;
+		plugin = clish_shell_find_create_plugin(this,
+			clish_plugin_builtin_list[i].name);
+		clish_plugin__set_init(plugin,
+			clish_plugin_builtin_list[i].init);
+		clish_plugin__set_builtin_flag(plugin, BOOL_TRUE);
+		i++;
+	}
+
+	/* Add default plugin to the list of plugins */
+	if (this->default_plugin) {
+		clish_shell_find_create_plugin(this, "clish");
+		/* Default hooks */
+		for (i = 0; i < CLISH_SYM_TYPE_MAX; i++) {
+			if (this->hooks_use[i])
+				continue;
+			if (!clish_plugin_default_hook[i])
+				continue;
+			clish_sym__set_name(this->hooks[i],
+				clish_plugin_default_hook[i]);
+		}
+	}
+	/* Add default syms to unresolved table */
+	for (i = 0; i < CLISH_SYM_TYPE_MAX; i++) {
+		if (clish_sym__get_name(this->hooks[i]))
+			lub_list_add(this->syms, this->hooks[i]);
+	}
+
+	/* Load plugins and link symbols */
+	if (clish_shell_load_plugins(this) < 0)
+		return -1;
+	if (clish_shell_link_plugins(this) < 0)
+		return -1;
+
+	access_fn = clish_sym__get_func(clish_shell_get_hook(this, CLISH_SYM_TYPE_ACCESS));
+
+	/* Iterate the VIEWs */
+	view_tree = this->view_tree;
+	view_iter = lub_list_iterator_init(view_tree);
+	while(view_iter) {
+		lub_list_node_t *old_view_iter;
+		view = (clish_view_t *)lub_list_node__get_data(view_iter);
+		old_view_iter = view_iter;
+		view_iter = lub_list_node__get_next(view_iter);
+		/* Check access rights for the VIEW */
+		if (access_fn && clish_view__get_access(view) &&
+			access_fn(this, clish_view__get_access(view))) {
+#ifdef DEBUG
+			fprintf(stderr, "Warning: Access denied. Remove VIEW \"%s\"\n",
+				clish_view__get_name(view));
+#endif
+			lub_list_del(view_tree, old_view_iter);
+			lub_list_node_free(old_view_iter);
+			clish_view_delete(view);
+			continue;
+		}
+
+		/* Iterate the NAMESPACEs */
+		nspace_tree = clish_view__get_nspaces(view);
+		nspace_iter = lub_list__get_head(nspace_tree);
+		while(nspace_iter) {
+			clish_view_t *ref_view;
+			lub_list_node_t *old_nspace_iter;
+			nspace = (clish_nspace_t *)lub_list_node__get_data(nspace_iter);
+			old_nspace_iter = nspace_iter;
+			nspace_iter = lub_list_node__get_next(nspace_iter);
+			/* Resolve NAMESPACEs and remove unresolved ones */
+			ref_view = clish_shell_find_view(this, clish_nspace__get_view_name(nspace));
+			if (!ref_view) {
+#ifdef DEBUG
+				fprintf(stderr, "Warning: Remove unresolved NAMESPACE \"%s\" from \"%s\" VIEW\n",
+					clish_nspace__get_view_name(nspace), clish_view__get_name(view));
+#endif
+				lub_list_del(nspace_tree, old_nspace_iter);
+				lub_list_node_free(old_nspace_iter);
+				clish_nspace_delete(nspace);
+				continue;
+			}
+			clish_nspace__set_view(nspace, ref_view);
+			clish_nspace__set_view_name(nspace, NULL); /* Free some memory */
+			/* Check access rights for the NAMESPACE */
+			if (access_fn && (
+				/* Check NAMESPASE owned access */
+				(clish_nspace__get_access(nspace) && access_fn(this, clish_nspace__get_access(nspace)))
+				||
+				/* Check referenced VIEW's access */
+				(clish_view__get_access(ref_view) && access_fn(this, clish_view__get_access(ref_view)))
+				)) {
+#ifdef DEBUG
+				fprintf(stderr, "Warning: Access denied. Remove NAMESPACE \"%s\" from \"%s\" VIEW\n",
+					clish_nspace__get_view_name(nspace), clish_view__get_name(view));
+#endif
+				lub_list_del(nspace_tree, old_nspace_iter);
+				lub_list_node_free(old_nspace_iter);
+				clish_nspace_delete(nspace);
+				continue;
+			}
+		}
+
+		/* Iterate the COMMANDs */
+		cmd_tree = clish_view__get_tree(view);
+		cmd = lub_bintree_findfirst(cmd_tree);
+		for (lub_bintree_iterator_init(&cmd_iter, cmd_tree, cmd);
+			cmd; cmd = lub_bintree_iterator_next(&cmd_iter)) {
+			int cmd_is_alias = clish_command__get_alias(cmd)?1:0;
+			clish_param_t *args = NULL;
+
+			/* Check access rights for the COMMAND */
+			if (access_fn && clish_command__get_access(cmd) &&
+				access_fn(this, clish_command__get_access(cmd))) {
+#ifdef DEBUG
+				fprintf(stderr, "Warning: Access denied. Remove COMMAND \"%s\" from VIEW \"%s\"\n",
+					clish_command__get_name(cmd), clish_view__get_name(view));
+#endif
+				lub_bintree_remove(cmd_tree, cmd);
+				clish_command_delete(cmd);
+				continue;
+			}
+
+			/* Resolve command aliases */
+			if (cmd_is_alias) {
+				clish_view_t *aview;
+				clish_command_t *cmdref;
+				const char *alias_view = clish_command__get_alias_view(cmd);
+				if (!alias_view)
+					aview = clish_command__get_pview(cmd);
+				else
+					aview = clish_shell_find_view(this, alias_view);
+				if (!aview /* Removed or broken VIEW */
+					||
+					/* Removed or broken referenced COMMAND */
+					!(cmdref = clish_view_find_command(aview, clish_command__get_alias(cmd), BOOL_FALSE))
+					) {
+#ifdef DEBUG
+					fprintf(stderr, "Warning: Remove unresolved link \"%s\" from \"%s\" VIEW\n",
+						clish_command__get_name(cmd), clish_view__get_name(view));
+#endif
+					lub_bintree_remove(cmd_tree, cmd);
+					clish_command_delete(cmd);
+					continue;
+					/*fprintf(stderr, CLISH_XML_ERROR_STR"Broken VIEW for alias \"%s\"\n",
+						clish_command__get_name(cmd));
+					return -1; */
+					/*fprintf(stderr, CLISH_XML_ERROR_STR"Broken alias \"%s\"\n",
+						clish_command__get_name(cmd));
+					return -1; */
+				}
+				if (!clish_command_alias_to_link(cmd, cmdref)) {
+					fprintf(stderr, CLISH_XML_ERROR_STR"Something wrong with alias \"%s\"\n",
+						clish_command__get_name(cmd));
+					return -1;
+				}
+				/* Check access rights for newly constructed COMMAND.
+				   Now the link has access filed from referenced command.
+				 */
+				if (access_fn && clish_command__get_access(cmd) &&
+					access_fn(this, clish_command__get_access(cmd))) {
+#ifdef DEBUG
+					fprintf(stderr, "Warning: Access denied. Remove COMMAND \"%s\" from VIEW \"%s\"\n",
+						clish_command__get_name(cmd), clish_view__get_name(view));
+#endif
+					lub_bintree_remove(cmd_tree, cmd);
+					clish_command_delete(cmd);
+					continue;
+				}
+			}
+			if (cmd_is_alias) /* Don't duplicate paramv processing for aliases */
+				continue;
+			/* Iterate PARAMeters */
+			paramv = clish_command__get_paramv(cmd);
+			if (iterate_paramv(this, paramv, access_fn) < 0)
+				return -1;
+			/* Resolve PTYPE for args */
+			if ((args = clish_command__get_args(cmd))) {
+				if (!resolve_ptype(this, args))
+					return -1;
+			}
+		}
+	}
+
+	return 0;
+}
+#endif