Пример #1
0
void loadonlymaximalfrommemory(void) {
	cp_context_t *ctx;
	cp_plugin_info_t *plugin;
	cp_status_t status;
	int errors, bytesloaded = 0, i;
	const char *pd;
	char *pdfilename, *membuffer;
	FILE *f;

	/* Load plugin descriptor to memory buffer */
	pd = plugindir("maximal");
	check((pdfilename = malloc((strlen(pd) + strlen(CP_FNAMESEP_STR) + strlen(PLUGINFILENAME) + 1) * sizeof(char))) != NULL);
	strcpy(pdfilename, pd);
	strcat(pdfilename, CP_FNAMESEP_STR PLUGINFILENAME);
	check((membuffer = malloc(MEMBUFFERSIZE * sizeof(unsigned char))) != NULL);
	check((f = fopen(pdfilename, "r")) != NULL);
	do {
		i = fread(membuffer + bytesloaded, sizeof(char), MEMBUFFERSIZE - bytesloaded, f);
		check(!ferror(f));
		bytesloaded += i;
	} while (i > 0);
	fclose(f);
	
	/* Load plugin descriptor from memory buffer */
	ctx = init_context(CP_LOG_ERROR, &errors);
	check((plugin = cp_load_plugin_descriptor_from_memory(ctx, membuffer, bytesloaded, &status)) != NULL && status == CP_OK);

	/* Clean up */
	free(membuffer);
	cp_release_info(ctx, plugin);
	cp_destroy();
	check(errors == 0);
}
Пример #2
0
static int start(void *d) {
	plugin_data_t *data = d;
	cp_extension_t **exts;
	
	exts = cp_get_extensions_info(data->ctx, "symuser.strings", NULL, NULL);
	if (exts != NULL && exts[0] != NULL) {
		const char *symname;
		
		symname = cp_lookup_cfg_value(exts[0]->configuration, "@string-symbol");
		if (symname != NULL) {
			data->str = cp_resolve_symbol(data->ctx, exts[0]->plugin->identifier, symname, NULL);
			if (data->str == NULL) {
				cp_log(data->ctx, CP_LOG_ERROR, "Could not resolve symbol specified by extension.");
			}
		} else {
			cp_log(data->ctx, CP_LOG_ERROR, "No string-symbol attribute present in extension.");
		} 
	} else {
		cp_log(data->ctx, CP_LOG_ERROR, "No extensions available.");
	}
	if (exts != NULL) {
		cp_release_info(data->ctx, exts);
	}
	if (data->str == NULL) {
		return CP_ERR_RUNTIME;
	}
	return cp_define_symbol(data->ctx, "used_string", (void *) data->str);
}
Пример #3
0
static void scanupgrade_checkpver(cp_context_t *ctx, const char *plugin, const char *ver) {
	cp_plugin_info_t *pi;
	cp_status_t status;
	
	check((pi = cp_get_plugin_info(ctx, plugin, &status)) != NULL && status == CP_OK);
	check(ver == NULL ? pi->version == NULL : (pi->version != NULL && strcmp(pi->version, ver) == 0));
	cp_release_info(ctx, pi); 
}
Пример #4
0
void loadonlymaximal(void) {
	cp_context_t *ctx;
	cp_plugin_info_t *plugin;
	cp_status_t status;
	int errors;
	
	ctx = init_context(CP_LOG_ERROR, &errors);
	check((plugin = cp_load_plugin_descriptor(ctx, plugindir("maximal"), &status)) != NULL && status == CP_OK);
	cp_release_info(ctx, plugin);
	cp_destroy();
	check(errors == 0);
}
Пример #5
0
void infologger(void) {
	cp_context_t *ctx;
	cp_plugin_info_t *plugin;
	cp_status_t status;
	struct log_count_t lc = { CP_LOG_INFO, 0, 0 };

	ctx = init_context(CP_LOG_WARNING, NULL);
	check(cp_register_logger(ctx, counting_logger, &lc, CP_LOG_INFO) == CP_OK);
	check((plugin = cp_load_plugin_descriptor(ctx, plugindir("minimal"), &status)) != NULL && status == CP_OK);
	check(cp_install_plugin(ctx, plugin) == CP_OK);
	cp_release_info(ctx, plugin);
	cp_destroy();
	check(lc.count_max > 0 && lc.count_above_max == 0);
}
Пример #6
0
void nocollections(void) {
	cp_context_t *ctx;
	cp_plugin_info_t **plugins;
	cp_status_t status;
	int errors;
	int i;
	
	ctx = init_context(CP_LOG_ERROR, &errors);
	check(cp_scan_plugins(ctx, 0) == CP_OK);
	check((plugins = cp_get_plugins_info(ctx, &status, &i)) != NULL && status == CP_OK && i == 0);
	cp_release_info(ctx, plugins);
	cp_destroy();
	check(errors == 0);
}
Пример #7
0
void twologgers(void) {
	cp_context_t *ctx;
	cp_plugin_info_t *plugin;
	cp_status_t status;
	struct log_count_t lc = { CP_LOG_DEBUG, 0, 0 };
	int count = 0;
	int errors;

	ctx = init_context(CP_LOG_ERROR, &errors);
	check(cp_register_logger(ctx, counting_logger, &lc, CP_LOG_DEBUG) == CP_OK);
	check(count == 0 && lc.count_max > 0 && lc.count_above_max == 0);
	check(cp_register_logger(ctx, increment_logger, &count, CP_LOG_INFO) == CP_OK);
	check(count == 0 && lc.count_max > 0 && lc.count_above_max == 0);
	check((plugin = cp_load_plugin_descriptor(ctx, plugindir("minimal"), &status)) != NULL && status == CP_OK);
	check(cp_install_plugin(ctx, plugin) == CP_OK);
	cp_release_info(ctx, plugin);
	check(count > 0 && lc.count_max > 0 && lc.count_above_max > 0);
	cp_destroy();
	check(errors == 0);
}
Пример #8
0
void extcfgutils(void) {
	cp_context_t *ctx;
	cp_plugin_info_t *plugin;
	cp_extension_t *ext;
	cp_cfg_element_t *ce, *cebase;
	const char *str;
	int errors;
	cp_status_t status;
	int i;

	ctx = init_context(CP_LOG_ERROR, &errors);
	check((plugin = cp_load_plugin_descriptor(ctx, plugindir("maximal"), &status)) != NULL && status == CP_OK);
	for (i = 0, ext = NULL; ext == NULL && i < plugin->num_extensions; i++) {
		cp_extension_t *e = plugin->extensions + i;
		if (e->identifier != NULL && !strcmp(e->local_id, "ext1")) {
			ext = e;
		}
	}
	check(ext != NULL);

	// Look up using forward path
	check((ce = cp_lookup_cfg_element(ext->configuration, "structure/parameter")) != NULL && ce->value != NULL && strcmp(ce->value, "parameter") == 0);
	check((ce = cebase = cp_lookup_cfg_element(ext->configuration, "structure/deeper/struct/is")) != NULL && ce->value != NULL && strcmp(ce->value, "here") == 0);
	check((str = cp_lookup_cfg_value(ext->configuration, "structure/parameter")) != NULL && strcmp(str, "parameter") == 0);
	check((str = cp_lookup_cfg_value(ext->configuration, "@name")) != NULL && strcmp(str, "Extension 1") == 0);

	// Look up using reverse path
	check((ce = cp_lookup_cfg_element(cebase, "../../../parameter/../deeper")) != NULL && strcmp(ce->name, "deeper") == 0);
	check((str = cp_lookup_cfg_value(cebase, "../../../../@name")) != NULL && strcmp(str, "Extension 1") == 0);

	// Look up nonexisting components
	check(cp_lookup_cfg_element(ext->configuration, "non/existing") == NULL);
	check(cp_lookup_cfg_element(ext->configuration, "structure/../..") == NULL);
	check(cp_lookup_cfg_value(ext->configuration, "non/existing") == NULL);
	check(cp_lookup_cfg_value(ext->configuration, "structure/../..") == NULL);
	check(cp_lookup_cfg_value(ext->configuration, "structure@nonexisting") == NULL);

	cp_release_info(ctx, plugin);
	cp_destroy_context(ctx);
	check(errors == 0);
}
Пример #9
0
/**
 * Classifies a file based on file extension. This classifier uses extensions
 * installed at the file type extension point. Therefore we need pointer to
 * the plug-in context to access the extensions. A plug-in instance initializes
 * the classifier structure with the plug-in context pointer and registers a
 * virtual symbol pointing to the classifier.
 */
static int classify(void *d, const char *path) {
	cp_context_t *ctx = d;
	cp_extension_t **exts;
	const char *type = NULL;
	int i;

	// Go through all extensions registered at the extension point
	exts = cp_get_extensions_info(ctx, "org.c-pluff.examples.cpfile.extension.file-types", NULL, NULL);
	if (exts == NULL) {
		cp_log(ctx, CP_LOG_ERROR, "Could not resolve file type extensions.");
		return 0;
	}
	for (i = 0; type == NULL && exts[i] != NULL; i++) {
		int j;

		// Go through all file types provided by the extension
		for (j = 0; type == NULL && j < exts[i]->configuration->num_children; j++) {
			cp_cfg_element_t *elem = exts[i]->configuration->children + j;
			const char *desc = NULL;

			if (strcmp(elem->name, "file-type") == 0
				&& (desc = cp_lookup_cfg_value(elem, "@description")) != NULL
				&& (is_of_type(path, elem))) {
				type = desc;
			}
		}
	}

	// Release extension information
	cp_release_info(ctx, exts);

	// Print file type if recognized, otherwise try other classifiers
	if (type != NULL) {
		fputs(type, stdout);
		putchar('\n');
		return 1;
	} else {
		return 0;
	}
}
Пример #10
0
void plugincallbacks(void) {
	cp_context_t *ctx;
	cp_status_t status;
	cp_plugin_info_t *plugin;
	int errors;
	cbc_counters_t *counters;

	ctx = init_context(CP_LOG_ERROR, &errors);
	cp_set_context_args(ctx, argv);
	check((plugin = cp_load_plugin_descriptor(ctx, "tmp/install/plugins/callbackcounter", &status)) != NULL && status == CP_OK);
	check(cp_install_plugin(ctx, plugin) == CP_OK);
	cp_release_info(ctx, plugin);

	// Start plug-in implicitly by resolving a symbol
	check((counters = cp_resolve_symbol(ctx, "callbackcounter", "cbc_counters", &status)) != NULL && status == CP_OK);
	check(counters->create == 1);
	check(counters->start == 1);
	check(counters->logger == 0);
	check(counters->listener == 1);
	check(counters->run == 0);
	check(counters->stop == 0);
	check(counters->destroy == 0);
	check(counters->context_arg_0 != NULL && strcmp(counters->context_arg_0, argv[0]) == 0);

	// Cause warning
	check(cp_start_plugin(ctx, "nonexisting") == CP_ERR_UNKNOWN);
	check(counters->create == 1);
	check(counters->start == 1);
	check(counters->logger == 1);
	check(counters->listener == 1);
	check(counters->run == 0);
	check(counters->stop == 0);
	check(counters->destroy == 0);

	// Run run function once
	check(cp_run_plugins_step(ctx));
	check(counters->create == 1);
	check(counters->start == 1);
	check(counters->logger == 1);
	check(counters->listener == 1);
	check(counters->run == 1);
	check(counters->stop == 0);
	check(counters->destroy == 0);

	// Run run function until no more work to be done (run = 3)
	cp_run_plugins(ctx);
	check(counters->create == 1);
	check(counters->start == 1);
	check(counters->logger == 1);
	check(counters->listener == 1);
	check(counters->run == 3);
	check(counters->stop == 0);
	check(counters->destroy == 0);

	/*
	 * Normally symbols must not be accessed after they have been released.
	 * We still access counters here because we know that the plug-in
	 * implementation does not free the counter data.
	 */
	cp_release_symbol(ctx, counters);

	// Stop plug-in
	check(cp_stop_plugin(ctx, "callbackcounter") == CP_OK);
	check(counters->create == 1);
	check(counters->start == 1);
	check(counters->logger == 1);
	check(counters->listener == 2);
	check(counters->run == 3);
	check(counters->stop == 1);
	// for now 1 but might be 0 in future (delay destroy)
	check(counters->destroy == 0 || counters->destroy == 1);

	// Uninstall plugin
	check(cp_uninstall_plugin(ctx, "callbackcounter") == CP_OK);
	check(counters->create == 1);
	check(counters->start == 1);
	check(counters->logger == 1);
	check(counters->listener == 2);
	check(counters->run == 3);
	check(counters->stop == 1);
	check(counters->destroy == 1);

	cp_destroy();
	check(errors == 0);

	/* Free the counter data that was intentionally leaked by the plug-in */
	free(counters);
}
Пример #11
0
CP_C_API cp_status_t cp_scan_plugins(cp_context_t *context, int flags) {
	hash_t *avail_plugins = NULL;
	list_t *started_plugins = NULL;
	cp_plugin_info_t **plugins = NULL;
	char *pdir_path = NULL;
	int pdir_path_size = 0;
	int plugins_stopped = 0;
	cp_status_t status = CP_OK;
	
	CHECK_NOT_NULL(context);
	
	cpi_lock_context(context);
	cpi_check_invocation(context, CPI_CF_ANY, __func__);
	cpi_debug(context, N_("Plug-in scan is starting."));
	do {
		lnode_t *lnode;
		hscan_t hscan;
		hnode_t *hnode;
	
		// Create a hash for available plug-ins 
		if ((avail_plugins = hash_create(HASHCOUNT_T_MAX, (int (*)(const void *, const void *)) strcmp, NULL)) == NULL) {
			status = CP_ERR_RESOURCE;
			break;
		}
	
		// Scan plug-in directories for available plug-ins 
		lnode = list_first(context->env->plugin_dirs);
		while (lnode != NULL) {
			const char *dir_path;
			DIR *dir;
			
			dir_path = lnode_get(lnode);
			dir = opendir(dir_path);
			if (dir != NULL) {
				int dir_path_len;
				struct dirent *de;
				
				dir_path_len = strlen(dir_path);
				if (dir_path[dir_path_len - 1] == CP_FNAMESEP_CHAR) {
					dir_path_len--;
				}
				errno = 0;
				while ((de = readdir(dir)) != NULL) {
					if (de->d_name[0] != '\0' && de->d_name[0] != '.') {
						int pdir_path_len = dir_path_len + 1 + strlen(de->d_name) + 1;
						cp_plugin_info_t *plugin;
						cp_status_t s;
						hnode_t *hnode;

						// Allocate memory for plug-in descriptor path 
						if (pdir_path_size <= pdir_path_len) {
							char *new_pdir_path;
						
							if (pdir_path_size == 0) {
								pdir_path_size = 128;
							}
							while (pdir_path_size <= pdir_path_len) {
								pdir_path_size *= 2;
							}
							new_pdir_path = realloc(pdir_path, pdir_path_size * sizeof(char));
							if (new_pdir_path == NULL) {
								cpi_errorf(context, N_("Could not check possible plug-in location %s%c%s due to insufficient system resources."), dir_path, CP_FNAMESEP_CHAR, de->d_name);
								status = CP_ERR_RESOURCE;
								// continue loading plug-ins from other directories 
								continue;
							}
							pdir_path = new_pdir_path;
						}
					
						// Construct plug-in descriptor path 
						strcpy(pdir_path, dir_path);
						pdir_path[dir_path_len] = CP_FNAMESEP_CHAR;
						strcpy(pdir_path + dir_path_len + 1, de->d_name);
							
						// Try to load a plug-in 
						plugin = cp_load_plugin_descriptor(context, pdir_path, &s);
						if (plugin == NULL) {
							status = s;
							// continue loading plug-ins from other directories 
							continue;
						}
					
						// Insert plug-in to the list of available plug-ins 
						if ((hnode = hash_lookup(avail_plugins, plugin->identifier)) != NULL) {
							cp_plugin_info_t *plugin2 = hnode_get(hnode);
							if (cpi_vercmp(plugin->version, plugin2->version) > 0) {
								hash_delete_free(avail_plugins, hnode);
								cp_release_info(context, plugin2);
								hnode = NULL;
							}
						}
						if (hnode == NULL) {
							if (!hash_alloc_insert(avail_plugins, plugin->identifier, plugin)) {
								cpi_errorf(context, N_("Plug-in %s version %s could not be loaded due to insufficient system resources."), plugin->identifier, plugin->version);
								cp_release_info(context, plugin);
								status = CP_ERR_RESOURCE;
								// continue loading plug-ins from other directories 
								continue;
							}
						}
						
					}
					errno = 0;
				}
				if (errno) {
					cpi_errorf(context, N_("Could not read plug-in directory %s: %s"), dir_path, strerror(errno));
					status = CP_ERR_IO;
					// continue loading plug-ins from other directories 
				}
				closedir(dir);
			} else {
				cpi_errorf(context, N_("Could not open plug-in directory %s: %s"), dir_path, strerror(errno));
				status = CP_ERR_IO;
				// continue loading plug-ins from other directories 
			}
			
			lnode = list_next(context->env->plugin_dirs, lnode);
		}
		
		// Copy the list of started plug-ins, if necessary 
		if ((flags & CP_SP_RESTART_ACTIVE)
			&& (flags & (CP_SP_UPGRADE | CP_SP_STOP_ALL_ON_INSTALL))) {
			int i;
			cp_status_t s;

			if ((plugins = cp_get_plugins_info(context, &s, NULL)) == NULL) {
				status = s;
				break;
			}
			if ((started_plugins = list_create(LISTCOUNT_T_MAX)) == NULL) {
				status = CP_ERR_RESOURCE;
				break;
			}
			for (i = 0; plugins[i] != NULL; i++) {
				cp_plugin_state_t state;
				
				state = cp_get_plugin_state(context, plugins[i]->identifier);
				if (state == CP_PLUGIN_STARTING || state == CP_PLUGIN_ACTIVE) {
					char *pid;
				
					if ((pid = strdup(plugins[i]->identifier)) == NULL) {
						status = CP_ERR_RESOURCE;
						break;
					}
					if ((lnode = lnode_create(pid)) == NULL) {
						free(pid);
						status = CP_ERR_RESOURCE;
						break;
					}
					list_append(started_plugins, lnode);
				}
			}
			cpi_release_info(context, plugins);
			plugins = NULL;
		}
		
		// Install/upgrade plug-ins 
		hash_scan_begin(&hscan, avail_plugins);
		while ((hnode = hash_scan_next(&hscan)) != NULL) {
			cp_plugin_info_t *plugin;
			cp_plugin_t *ip = NULL;
			hnode_t *hn2;
			int s;
			
			plugin = hnode_get(hnode);
			hn2 = hash_lookup(context->env->plugins, plugin->identifier);
			if (hn2 != NULL) {
				ip = hnode_get(hn2);
			}
			
			// Unload the installed plug-in if it is to be upgraded 
			if (ip != NULL
				&& (flags & CP_SP_UPGRADE)
				&& ((ip->plugin->version == NULL && plugin->version != NULL)
					|| (ip->plugin->version != NULL
						&& plugin->version != NULL
						&& cpi_vercmp(plugin->version, ip->plugin->version) > 0))) {
				if ((flags & (CP_SP_STOP_ALL_ON_UPGRADE | CP_SP_STOP_ALL_ON_INSTALL))
					&& !plugins_stopped) {
					plugins_stopped = 1;
					cp_stop_plugins(context);
				}
				s = cp_uninstall_plugin(context, plugin->identifier);
				assert(s == CP_OK);
				ip = NULL;
			}
			
			// Install the plug-in, if to be installed 
			if (ip == NULL) {
				if ((flags & CP_SP_STOP_ALL_ON_INSTALL) && !plugins_stopped) {
					plugins_stopped = 1;
					cp_stop_plugins(context);
				}
				if ((s = cp_install_plugin(context, plugin)) != CP_OK) {
					status = s;
					break;
				}
			}
			
			// Remove the plug-in from the hash
			hash_scan_delfree(avail_plugins, hnode);
			cp_release_info(context, plugin);
		}
		
		// Restart stopped plug-ins if necessary 
		if (started_plugins != NULL) {
			lnode = list_first(started_plugins);
			while (lnode != NULL) {
				char *pid;
				int s;
				
				pid = lnode_get(lnode);
				s = cp_start_plugin(context, pid);
				if (s != CP_OK) {
					status = s;
				}
				lnode = list_next(started_plugins, lnode);
			}
		}
		
	} while (0);

	// Report error
	switch (status) {
		case CP_OK:
			cpi_debug(context, N_("Plug-in scan has completed successfully."));
			break;
		case CP_ERR_RESOURCE:
			cpi_error(context, N_("Could not scan plug-ins due to insufficient system resources."));
			break;
		default:
			cpi_error(context, N_("Could not scan plug-ins."));
			break;
	}
	cpi_unlock_context(context);
	
	// Release resources 
	if (pdir_path != NULL) {
		free(pdir_path);
	}
	if (avail_plugins != NULL) {
		hscan_t hscan;
		hnode_t *hnode;
		
		hash_scan_begin(&hscan, avail_plugins);
		while ((hnode = hash_scan_next(&hscan)) != NULL) {
			cp_plugin_info_t *p = hnode_get(hnode);
			hash_scan_delfree(avail_plugins, hnode);
			cp_release_info(context, p);
		}
		hash_destroy(avail_plugins);
	}
	if (started_plugins != NULL) {
		list_process(started_plugins, NULL, cpi_process_free_ptr);
		list_destroy(started_plugins);
	}
	if (plugins != NULL) {
		cp_release_info(context, plugins);
	}

	return status;
}