Example #1
0
static gboolean
loader_supports_file(PurplePlugin *loader, const char *filename)
{
	GList *exts;

	for (exts = PURPLE_PLUGIN_LOADER_INFO(loader)->exts; exts != NULL; exts = exts->next) {
		if (has_file_extension(filename, (char *)exts->data)) {
			return TRUE;
		}
	}

	return FALSE;
}
Example #2
0
/** 
 * \brief Process compiler options.
 * \param argc The number of input parameters.
 * \param argv The input parameter strings.
 * \return Indicates if processing was successful. 
 *         0 = processing successful
 *         1 = processing not successful
 *
 * Processes the input options passed to the compiler
 * and fill the compiler options structure as appropriate.
 * 
 * The following options are supported:
 *  -h: print help
 *  -p: print the IR to a file
 *  -t: test modus, only success/failure log
 *  -o: the output file name (different from 'input'.o)
 */
int process_options(int argc, char *argv[]) {
	int opt;
	int ret = 0;

	/* add a handler to resource manager to free resources
	 * in the case of an error during option processing */
	rm_register_handler(&resource_mgr, free_options, NULL);

	while ((opt = getopt(argc, argv, "hpto:")) != -1) {
		switch (opt) {
		case 'p':
			cc_options.print_ir = 1;
			break;
		case 't':
			/* fewer logs, for automated testing */
			cc_options.print_only_errors = 1;
			break;
		case 'o':
			/* output file */
			cc_options.output_file = strdup(optarg);
			if (cc_options.output_file == NULL) {
				fatal_os_error(OUT_OF_MEMORY, 1, __FILE__, __LINE__, "");
				return 1;
			}
			break;
		case 'h':
			/* print help */
			print_usage(argv[0]);
			rm_cleanup_resources(&resource_mgr);
			exit(EXIT_SUCCESS);

		default: /* '?' */
			/* print usage */
			fprintf(stderr, "ERROR: unknown parameter: %s\n", argv[optind]);
			print_usage(argv[0]);
			return 1;
		}
	}

	if (optind >= argc) {
		fprintf(stderr, "ERROR: missing input file\n");
		print_usage(argv[0]);
		ret = 1;
	} else if (optind < argc - 1) {
		fprintf(stderr, "ERROR: too many input files\n");
		print_usage(argv[0]);
		ret = 1;
	} else {
		cc_options.input_file = strdup(argv[optind]);
		if (cc_options.input_file == NULL) {
			fatal_os_error(OUT_OF_MEMORY, 1, __FILE__, __LINE__, "");
			return 1;
		}

		char *filebase = get_file_basename(cc_options.input_file);
		;
		if (filebase == NULL) {
			return 1;
		}

		if (!has_file_extension(cc_options.input_file, C_EXT)) {
			fprintf(stderr, "ERROR: no C file (.c) as input\n");
			ret = 1;
		} else {
			/* The file name has a valid .c extension */
			if (cc_options.output_file == NULL) {
				/* create output file name <input>.o */
				cc_options.output_file = get_filename_with_ext(filebase,
						OUTPUT_EXT);
				if (cc_options.output_file == NULL) {
					ret = 1;
				}
			}
			if (cc_options.print_ir == 1) {
				/* create IR file name <input>.ir */
				cc_options.ir_file = get_filename_with_ext(filebase, IR_EXT);
				if (cc_options.ir_file == NULL) {
					ret = 1;
				}
			}
		}

		free(filebase);
	}

	return ret;
}
Example #3
0
void
purple_plugin_destroy(PurplePlugin *plugin)
{
#ifdef PURPLE_PLUGINS
	g_return_if_fail(plugin != NULL);

	if (purple_plugin_is_loaded(plugin))
		purple_plugin_unload(plugin);

	plugins = g_list_remove(plugins, plugin);

	if (load_queue != NULL)
		load_queue = g_list_remove(load_queue, plugin);

	/* true, this may leak a little memory if there is a major version
	 * mismatch, but it's a lot better than trying to free something
	 * we shouldn't, and crashing while trying to load an old plugin */
	if(plugin->info == NULL || plugin->info->magic != PURPLE_PLUGIN_MAGIC ||
			plugin->info->major_version != PURPLE_MAJOR_VERSION)
	{
		if(plugin->handle)
			g_module_close(plugin->handle);

		g_free(plugin->path);
		g_free(plugin->error);

		PURPLE_DBUS_UNREGISTER_POINTER(plugin);

		g_free(plugin);
		return;
	}

	if (plugin->info != NULL)
		g_list_free(plugin->info->dependencies);

	if (plugin->native_plugin)
	{
		if (plugin->info != NULL && plugin->info->type == PURPLE_PLUGIN_LOADER)
		{
			PurplePluginLoaderInfo *loader_info;
			GList *exts, *l, *next_l;
			PurplePlugin *p2;

			loader_info = PURPLE_PLUGIN_LOADER_INFO(plugin);

			if (loader_info != NULL && loader_info->exts != NULL)
			{
				for (exts = PURPLE_PLUGIN_LOADER_INFO(plugin)->exts;
					 exts != NULL;
					 exts = exts->next) {

					for (l = purple_plugins_get_all(); l != NULL; l = next_l)
					{
						next_l = l->next;

						p2 = l->data;

						if (p2->path != NULL &&
							has_file_extension(p2->path, exts->data))
						{
							purple_plugin_destroy(p2);
						}
					}
				}

				g_list_free(loader_info->exts);
				loader_info->exts = NULL;
			}

			plugin_loaders = g_list_remove(plugin_loaders, plugin);
		}

		if (plugin->info != NULL && plugin->info->destroy != NULL)
			plugin->info->destroy(plugin);

		/*
		 * I find it extremely useful to do this when using valgrind, as
		 * it keeps all the plugins open, meaning that valgrind is able to
		 * resolve symbol names in leak traces from plugins.
		 */
		if (!g_getenv("PURPLE_LEAKCHECK_HELP") && !RUNNING_ON_VALGRIND)
		{
			if (plugin->handle != NULL)
				g_module_close(plugin->handle);
		}
	}
	else
	{
		PurplePlugin *loader;
		PurplePluginLoaderInfo *loader_info;

		loader = find_loader_for_plugin(plugin);

		if (loader != NULL)
		{
			loader_info = PURPLE_PLUGIN_LOADER_INFO(loader);

			if (loader_info->destroy != NULL)
				loader_info->destroy(plugin);
		}
	}

	g_free(plugin->path);
	g_free(plugin->error);

	PURPLE_DBUS_UNREGISTER_POINTER(plugin);

	g_free(plugin);
#endif /* !PURPLE_PLUGINS */
}
Example #4
0
PurplePlugin *
purple_plugin_probe(const char *filename)
{
#ifdef PURPLE_PLUGINS
	PurplePlugin *plugin = NULL;
	PurplePlugin *loader;
	gpointer unpunned;
	gchar *basename = NULL;
	gboolean (*purple_init_plugin)(PurplePlugin *);

	purple_debug_misc("plugins", "probing %s\n", filename);
	g_return_val_if_fail(filename != NULL, NULL);

	if (!g_file_test(filename, G_FILE_TEST_EXISTS))
		return NULL;

	/* If this plugin has already been probed then exit */
	basename = purple_plugin_get_basename(filename);
	plugin = purple_plugins_find_with_basename(basename);
	g_free(basename);
	if (plugin != NULL)
	{
		if (purple_strequal(filename, plugin->path))
			return plugin;
		else if (!purple_plugin_is_unloadable(plugin))
		{
			purple_debug_warning("plugins", "Not loading %s. "
							"Another plugin with the same name (%s) has already been loaded.\n",
							filename, plugin->path);
			return plugin;
		}
		else
		{
			/* The old plugin was a different file and it was unloadable.
			 * There's no guarantee that this new file with the same name
			 * will be loadable, but unless it fails in one of the silent
			 * ways and the first one didn't, it's not any worse.  The user
			 * will still see a greyed-out plugin, which is what we want. */
			purple_plugin_destroy(plugin);
		}
	}

	plugin = purple_plugin_new(has_file_extension(filename, G_MODULE_SUFFIX), filename);

	if (plugin->native_plugin) {
		const char *error;
#ifdef _WIN32
		/* Suppress error popups for failing to load plugins */
		UINT old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
#endif

		/*
		 * We pass G_MODULE_BIND_LOCAL here to prevent symbols from
		 * plugins being added to the global name space.
		 *
		 * G_MODULE_BIND_LOCAL was added in glib 2.3.3.
		 */
		plugin->handle = g_module_open(filename, G_MODULE_BIND_LOCAL);

		if (plugin->handle == NULL)
		{
			const char *error = g_module_error();
			if (error != NULL && purple_str_has_prefix(error, filename))
			{
				error = error + strlen(filename);

				/* These are just so we don't crash.  If we
				 * got this far, they should always be true. */
				if (*error == ':')
					error++;
				if (*error == ' ')
					error++;
			}

			if (error == NULL || !*error)
			{
				plugin->error = g_strdup(_("Unknown error"));
				purple_debug_error("plugins", "%s is not loadable: Unknown error\n",
						 plugin->path);
			}
			else
			{
				plugin->error = g_strdup(error);
				purple_debug_error("plugins", "%s is not loadable: %s\n",
						 plugin->path, plugin->error);
			}
			plugin->handle = g_module_open(filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);

			if (plugin->handle == NULL)
			{
#ifdef _WIN32
				/* Restore the original error mode */
				SetErrorMode(old_error_mode);
#endif
				purple_plugin_destroy(plugin);
				return NULL;
			}
			else
			{
				/* We were able to load the plugin with lazy symbol binding.
				 * This means we're missing some symbol.  Mark it as
				 * unloadable and keep going so we get the info to display
				 * to the user so they know to rebuild this plugin. */
				plugin->unloadable = TRUE;
			}
		}

		if (!g_module_symbol(plugin->handle, "purple_init_plugin",
							 &unpunned))
		{
			purple_debug_error("plugins", "%s is not usable because the "
							 "'purple_init_plugin' symbol could not be "
							 "found.  Does the plugin call the "
							 "PURPLE_INIT_PLUGIN() macro?\n", plugin->path);

			g_module_close(plugin->handle);
			error = g_module_error();
			if (error != NULL)
				purple_debug_error("plugins", "Error closing module %s: %s\n",
								 plugin->path, error);
			plugin->handle = NULL;

#ifdef _WIN32
			/* Restore the original error mode */
			SetErrorMode(old_error_mode);
#endif
			purple_plugin_destroy(plugin);
			return NULL;
		}
		purple_init_plugin = unpunned;

#ifdef _WIN32
		/* Restore the original error mode */
		SetErrorMode(old_error_mode);
#endif
	}
	else {
		loader = find_loader_for_plugin(plugin);

		if (loader == NULL) {
			purple_plugin_destroy(plugin);
			return NULL;
		}

		purple_init_plugin = PURPLE_PLUGIN_LOADER_INFO(loader)->probe;
	}

	if (!purple_init_plugin(plugin) || plugin->info == NULL)
	{
		purple_plugin_destroy(plugin);
		return NULL;
	}
	else if (plugin->info->ui_requirement &&
			!purple_strequal(plugin->info->ui_requirement, purple_core_get_ui()))
	{
		plugin->error = g_strdup_printf(_("You are using %s, but this plugin requires %s."),
					purple_core_get_ui(), plugin->info->ui_requirement);
		purple_debug_error("plugins", "%s is not loadable: The UI requirement is not met. (%s)\n", plugin->path, plugin->error);
		plugin->unloadable = TRUE;
		return plugin;
	}

	/*
	 * Check to make sure a plugin has defined an id.
	 * Not having this check caused purple_plugin_unload to
	 * enter an infinite loop in certain situations by passing
	 * purple_find_plugin_by_id a NULL value. -- ecoffey
	 */
	if (plugin->info->id == NULL || *plugin->info->id == '\0')
	{
		plugin->error = g_strdup(_("This plugin has not defined an ID."));
		purple_debug_error("plugins", "%s is not loadable: info->id is not defined.\n", plugin->path);
		plugin->unloadable = TRUE;
		return plugin;
	}

	/* Really old plugins. */
	if (plugin->info->magic != PURPLE_PLUGIN_MAGIC)
	{
		if (plugin->info->magic >= 2 && plugin->info->magic <= 4)
		{
			struct _PurplePluginInfo2
			{
				unsigned int api_version;
				PurplePluginType type;
				char *ui_requirement;
				unsigned long flags;
				GList *dependencies;
				PurplePluginPriority priority;

				char *id;
				char *name;
				char *version;
				char *summary;
				char *description;
				char *author;
				char *homepage;

				gboolean (*load)(PurplePlugin *plugin);
				gboolean (*unload)(PurplePlugin *plugin);
				void (*destroy)(PurplePlugin *plugin);

				void *ui_info;
				void *extra_info;
				PurplePluginUiInfo *prefs_info;
				GList *(*actions)(PurplePlugin *plugin, gpointer context);
			} *info2 = (struct _PurplePluginInfo2 *)plugin->info;

			/* This leaks... but only for ancient plugins, so deal with it. */
			plugin->info = g_new0(PurplePluginInfo, 1);

			/* We don't really need all these to display the plugin info, but
			 * I'm copying them all for good measure. */
			plugin->info->magic          = info2->api_version;
			plugin->info->type           = info2->type;
			plugin->info->ui_requirement = info2->ui_requirement;
			plugin->info->flags          = info2->flags;
			plugin->info->dependencies   = info2->dependencies;
			plugin->info->id             = info2->id;
			plugin->info->name           = info2->name;
			plugin->info->version        = info2->version;
			plugin->info->summary        = info2->summary;
			plugin->info->description    = info2->description;
			plugin->info->author         = info2->author;
			plugin->info->homepage       = info2->homepage;
			plugin->info->load           = info2->load;
			plugin->info->unload         = info2->unload;
			plugin->info->destroy        = info2->destroy;
			plugin->info->ui_info        = info2->ui_info;
			plugin->info->extra_info     = info2->extra_info;

			if (info2->api_version >= 3)
				plugin->info->prefs_info = info2->prefs_info;

			if (info2->api_version >= 4)
				plugin->info->actions    = info2->actions;


			plugin->error = g_strdup_printf(_("Plugin magic mismatch %d (need %d)"),
							 plugin->info->magic, PURPLE_PLUGIN_MAGIC);
			purple_debug_error("plugins", "%s is not loadable: Plugin magic mismatch %d (need %d)\n",
					  plugin->path, plugin->info->magic, PURPLE_PLUGIN_MAGIC);
			plugin->unloadable = TRUE;
			return plugin;
		}

		purple_debug_error("plugins", "%s is not loadable: Plugin magic mismatch %d (need %d)\n",
				 plugin->path, plugin->info->magic, PURPLE_PLUGIN_MAGIC);
		purple_plugin_destroy(plugin);
		return NULL;
	}

	if (plugin->info->major_version != PURPLE_MAJOR_VERSION ||
			plugin->info->minor_version > PURPLE_MINOR_VERSION)
	{
		plugin->error = g_strdup_printf(_("ABI version mismatch %d.%d.x (need %d.%d.x)"),
						 plugin->info->major_version, plugin->info->minor_version,
						 PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION);
		purple_debug_error("plugins", "%s is not loadable: ABI version mismatch %d.%d.x (need %d.%d.x)\n",
				 plugin->path, plugin->info->major_version, plugin->info->minor_version,
				 PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION);
		plugin->unloadable = TRUE;
		return plugin;
	}

	if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL)
	{
		/* If plugin is a PRPL, make sure it implements the required functions */
		if ((PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->list_icon == NULL) ||
		    (PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->login == NULL) ||
		    (PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->close == NULL))
		{
			plugin->error = g_strdup(_("Plugin does not implement all required functions (list_icon, login and close)"));
			purple_debug_error("plugins", "%s is not loadable: %s\n",
					 plugin->path, plugin->error);
			plugin->unloadable = TRUE;
			return plugin;
		}

		/* For debugging, let's warn about prpl prefs. */
		if (plugin->info->prefs_info != NULL)
		{
			purple_debug_error("plugins", "%s has a prefs_info, but is a prpl. This is no longer supported.\n",
			                 plugin->path);
		}
	}

	return plugin;
#else
	return NULL;
#endif /* !PURPLE_PLUGINS */
}
Example #5
0
void
purple_plugins_probe(const char *ext)
{
#ifdef PURPLE_PLUGINS
	GDir *dir;
	const gchar *file;
	gchar *path;
	PurplePlugin *plugin;
	GList *cur;
	const char *search_path;

	if (!g_module_supported())
		return;

	/* Probe plugins */
	for (cur = search_paths; cur != NULL; cur = cur->next)
	{
		search_path = cur->data;

		dir = g_dir_open(search_path, 0, NULL);

		if (dir != NULL)
		{
			while ((file = g_dir_read_name(dir)) != NULL)
			{
				path = g_build_filename(search_path, file, NULL);

				if (ext == NULL || has_file_extension(file, ext))
					purple_plugin_probe(path);

				g_free(path);
			}

			g_dir_close(dir);
		}
	}

	/* See if we have any plugins waiting to load */
	while (load_queue != NULL)
	{
		plugin = (PurplePlugin *)load_queue->data;

		load_queue = g_list_remove(load_queue, plugin);

		if (plugin == NULL || plugin->info == NULL)
			continue;

		if (plugin->info->type == PURPLE_PLUGIN_LOADER)
		{
			/* We'll just load this right now. */
			if (!purple_plugin_load(plugin))
			{
				purple_plugin_destroy(plugin);

				continue;
			}

			plugin_loaders = g_list_append(plugin_loaders, plugin);

			for (cur = PURPLE_PLUGIN_LOADER_INFO(plugin)->exts;
				 cur != NULL;
				 cur = cur->next)
			{
				purple_plugins_probe(cur->data);
			}
		}
		else if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL)
		{
			/* We'll just load this right now. */
			if (!purple_plugin_load(plugin))
			{
				purple_plugin_destroy(plugin);

				continue;
			}

			/* Make sure we don't load two PRPLs with the same name? */
			if (purple_find_prpl(plugin->info->id))
			{
				/* Nothing to see here--move along, move along */
				purple_plugin_destroy(plugin);

				continue;
			}

			protocol_plugins = g_list_insert_sorted(protocol_plugins, plugin,
													(GCompareFunc)compare_prpl);
		}
	}
#endif /* PURPLE_PLUGINS */
}