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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
/** * 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; } }
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); }
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; }