mce-modules.c 5.19 KB
Newer Older
1 2 3 4 5
/**
 * @file mce-modules.c
 * Module handling for MCE
 * <p>
 * Copyright © 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
6
 * Copyright (C) 2012-2019 Jolla Ltd.
7 8
 * <p>
 * @author David Weinehall <david.weinehall@nokia.com>
9
 * @author Simo Piiroinen <simo.piiroinen@jollamobile.com>
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 * mce is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * mce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with mce.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "mce-modules.h"

26 27 28 29 30 31 32
#include "mce.h"
#include "mce-log.h"
#include "mce-conf.h"

#include <stdio.h>

#include <gmodule.h>
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51

/** List of all loaded modules */
static GSList *modules = NULL;

/**
 * Dump information about mce modules to stdout
 */
void mce_modules_dump_info(void)
{
	GModule *module;
	gint i;

	for (i = 0; (module = g_slist_nth_data(modules, i)) != NULL; i++) {
		const gchar *modulename = g_module_name(module);
		module_info_struct *modinfo;
		gchar *tmp = NULL;
		gpointer mip;

		fprintf(stdout,
52 53
			"\n"
			"Module: %s\n", modulename);
54 55 56 57 58 59 60 61 62 63 64 65 66 67

		if (g_module_symbol(module,
				    "module_info",
				    &mip) == FALSE) {
			fprintf(stdout,
				"        %-32s\n",
				"module lacks information");
			continue;
		}

		modinfo = (module_info_struct *)mip;

		fprintf(stdout,
			"        %-32s %s\n",
68 69
			"name:",
			modinfo->name ? modinfo->name : "<undefined>");
70 71 72 73 74 75

		if (modinfo->depends != NULL)
			tmp = g_strjoinv(",", (gchar **)(modinfo->depends));

		fprintf(stdout,
			"        %-32s %s\n",
76
			"depends:",
77 78 79 80 81 82 83 84 85 86
			tmp ? tmp : "");

		g_free(tmp);
		tmp = NULL;

		if (modinfo->recommends != NULL)
			tmp = g_strjoinv(",", (gchar **)(modinfo->recommends));

		fprintf(stdout,
			"        %-32s %s\n",
87
			"recommends:",
88 89 90 91 92 93 94 95 96 97
			tmp ? tmp : "");

		g_free(tmp);
		tmp = NULL;

		if (modinfo->provides != NULL)
			tmp = g_strjoinv(",", (gchar **)(modinfo->provides));

		fprintf(stdout,
			"        %-32s %s\n",
98
			"provides:",
99 100 101 102 103 104 105 106 107 108
			tmp ? tmp : "");

		g_free(tmp);
		tmp = NULL;

		if (modinfo->enhances != NULL)
			tmp = g_strjoinv(",", (gchar **)(modinfo->enhances));

		fprintf(stdout,
			"        %-32s %s\n",
109
			"enhances:",
110 111 112 113 114 115 116 117 118 119
			tmp ? tmp : "");

		g_free(tmp);
		tmp = NULL;

		if (modinfo->conflicts != NULL)
			tmp = g_strjoinv(",", (gchar **)(modinfo->conflicts));

		fprintf(stdout,
			"        %-32s %s\n",
120
			"conflicts:",
121 122 123 124 125 126 127 128 129 130
			tmp ? tmp : "");

		g_free(tmp);
		tmp = NULL;

		if (modinfo->replaces != NULL)
			tmp = g_strjoinv(",", (gchar **)(modinfo->replaces));

		fprintf(stdout,
			"        %-32s %s\n",
131
			"replaces:",
132 133 134 135
			tmp ? tmp : "");

		g_free(tmp);

136 137
		fprintf(stdout,	"        %-32s %d\n",
			"priority:",
138 139 140 141
			modinfo->priority);
	}
}

142 143 144 145 146 147 148 149 150 151 152 153 154
/** Construct path for named mce plugin
 *
 * @param directory Location of the plugin
 * @module_name Name of the plugin
 *
 * @return Path to shared object
 */
static gchar * mce_modules_build_path(const gchar *directory,
				      const gchar *module_name)
{
	return g_strdup_printf("%s/%s.so", directory, module_name);
}

155 156 157 158 159 160 161 162 163 164 165 166 167 168
/**
 * Init function for the mce-modules component
 *
 * @return TRUE on success, FALSE on failure
 */
gboolean mce_modules_init(void)
{
	gchar **modlist = NULL;
	gsize length;
	gchar *path = NULL;

	/* Get the module path */
	path = mce_conf_get_string(MCE_CONF_MODULES_GROUP,
				   MCE_CONF_MODULES_PATH,
169
				   DEFAULT_MCE_MODULE_PATH);
170 171 172 173

	/* Get the list modules to load */
	modlist = mce_conf_get_string_list(MCE_CONF_MODULES_GROUP,
					   MCE_CONF_MODULES_MODULES,
174
					   &length);
175 176 177 178 179 180

	if (modlist != NULL) {
		gint i;

		for (i = 0; modlist[i]; i++) {
			GModule *module;
181
			gchar *tmp = mce_modules_build_path(path, modlist[i]);
182

183
			mce_log(LL_INFO,
184 185 186 187 188 189 190
				"Loading module: %s from %s",
				modlist[i], path);

			if ((module = g_module_open(tmp, 0)) != NULL) {
				/* XXX: check dependencies, conflicts, et al */
				modules = g_slist_prepend(modules, module);
			} else {
191 192 193
				const char *err = g_module_error();
				mce_log(LL_ERR, "%s", err ?: "unknown error");
				mce_log(LL_ERR,
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
					"Failed to load module: %s; skipping",
					modlist[i]);
			}

			g_free(tmp);
		}

		g_strfreev(modlist);
	}

	g_free(path);

	return TRUE;
}

/**
 * Exit function for the mce-modules component
 */
void mce_modules_exit(void)
{
	GModule *module;
	gint i;

	if (modules != NULL) {
		for (i = 0; (module = g_slist_nth_data(modules, i)) != NULL; i++) {
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
			if( mce_in_valgrind_mode() ) {
				/* Do not actually unmap the plugins so that
				 * valgrind can still locate the symbols at
				 * exit time. */
				gpointer addr = 0;
				g_module_symbol(module, "g_module_unload", &addr);
				if( addr ) {
					mce_log(LL_WARN, "simulating module %s unload",
						g_module_name(module));
					void (*unload)(GModule *) = addr;
					unload(module);
				}
				else {
					mce_log(LL_WARN, "skipping module %s unload",
						g_module_name(module));
				}
				continue;
			}
237 238 239 240 241 242 243 244 245
			g_module_close(module);
		}

		g_slist_free(modules);
		modules = NULL;
	}

	return;
}