Exemple #1
0
/**
 * Tries to find plugin with specified name (file name without suffix and path)
 * in standard plugin path.
 * If plugin is found, tries to load it, and if file is not valid plugin, error
 * will be reported.
 * Also check dependencies, and tries to load plugins that this depends on.
 * If anything fails, plugin won't be loaded, and error will be reported.
 * @param name Plugin name
 * @return Plugin load status
 */
PluginLoadStatus plugins_load(char *name) {
	PluginLoadStatus result = PLUG_FILE_NOT_FOUND;

	// Scan all configured plugin directories
	size_t count = config_getvalue_count(loadedPlugins->config,
		"pluginsdir");

	for (size_t i = 0; i < count; i++) {
		DirList dl = dirs_load(config_getvalue_array_string(
			loadedPlugins->config, "pluginsdir", i, "./plugins/"));

		for (int f = 0; f < dl->filesCount; f++) {
			char *basename = dirs_basename(dl->files[f]->name);

			if (dl->files[f]->mode & S_IXUSR && dl->files[f]->mode & S_IFREG &&
				strncmp(basename, name, strlen(name)) == 0) {

				result = plugins_loadplugin(dl->files[f]->path);
			}

			free(basename);

			if (result != PLUG_FILE_NOT_FOUND &&
				result != PLUG_PATH_NOT_FOUND) {

				break;
			}
		}

		dirs_freelist(dl);

		if (result != PLUG_FILE_NOT_FOUND && result != PLUG_PATH_NOT_FOUND) {
			break;
		}
	}

	return result;
} // plugins_load
Exemple #2
0
static const char *exportdescription(const struct exportmode *mode, char *buffer, size_t buffersize) {
    char *result = buffer;
    enum indexcompression ic;
    static const char* compression_names[ic_count] = {
        "uncompressed"
        ,"gzipped"
#ifdef HAVE_LIBBZ2
        ,"bzip2ed"
#endif
    };
    bool needcomma = false,
         needellipsis = false;

    assert (buffersize > 50);
    *buffer++ = ' ';
    buffersize--;
    *buffer++ = '(';
    buffersize--;
    for (ic = ic_first ; ic < ic_count ; ic++) {
        if ((mode->compressions & IC_FLAG(ic)) != 0) {
            size_t l = strlen(compression_names[ic]);
            assert (buffersize > l+3);
            if (needcomma) {
                *buffer++ = ',';
                buffersize--;
            }
            memcpy(buffer, compression_names[ic], l);
            buffer += l;
            buffersize -= l;
            needcomma = true;
        }
    }
    /* should be long enough for the previous things in all cases */
    assert (buffersize > 10);
    if (mode->hooks.count > 0) {
        int i;

        if (needcomma) {
            *buffer++ = ',';
            buffersize--;
        }
        strcpy(buffer, "script: ");
        buffer += 8;
        buffersize -= 8;
        needcomma = false;

        for (i = 0 ; i < mode->hooks.count ; i++) {
            const char *hook = dirs_basename(mode->hooks.values[i]);
            size_t l = strlen(hook);

            if (buffersize < 6) {
                needellipsis = true;
                break;
            }
            if (needcomma) {
                *buffer++ = ',';
                buffersize--;
            }

            if (l > buffersize - 5) {
                memcpy(buffer, hook, buffersize-5);
                buffer += (buffersize-5);
                buffersize -= (buffersize-5);
                needellipsis = true;
                break;
            } else {
                memcpy(buffer, hook, l);
                buffer += l;
                buffersize -= l;
                assert (buffersize >= 2);
            }
            needcomma = true;
        }
    }
    if (needellipsis) {
        /* moveing backward here is easier than checking above */
        if (buffersize < 5) {
            buffer -= (5 - buffersize);
            buffersize = 5;
        }
        *buffer++ = '.';
        buffersize--;
        *buffer++ = '.';
        buffersize--;
        *buffer++ = '.';
        buffersize--;
    }
    assert (buffersize >= 2);
    *buffer++ = ')';
    buffersize--;
    *buffer = '\0';
    return result;
}
Exemple #3
0
/**
 * Load plugin in exactly given filename. It checks plugin's dependencies,
 * and tries to load them too.
 * @param path Path to plugin
 * @return Plugin load status
 */
PluginLoadStatus plugins_loadplugin(char *path) {
	PluginLoadStatus result = PLUG_OK;

	char *pathdup = path;

	if (file_exists(pathdup)) {
		char *basename = dirs_basename(pathdup);

		if (plugins_isloaded(basename)) {
			free(basename);
			printError("plugins", "Plugin %s is already loaded.", pathdup);
			return PLUG_ALREADY_LOADED;
		}

		printError("plugins", "Loading plugin %s", pathdup);

		Plugin plugin = malloc(sizeof(struct sPlugin));

		// Add plugin to linked list, for circular dependency check
		plugin->prev = loadedPlugins->last;
		plugin->next = NULL;
		if (loadedPlugins->last != NULL) {
			loadedPlugins->last->next = plugin;
		} else {
			loadedPlugins->first = plugin;
		}
		loadedPlugins->last = plugin;

		plugin->handle = dlopen(pathdup, RTLD_LAZY | RTLD_GLOBAL);
		if (plugin->handle != NULL) {
			plugin->name = basename;
			plugin->path = strdup(path);

			plugin->info = malloc(sizeof(PluginInfo));
			plugin->info->name = NULL;
			plugin->info->author = NULL;
			plugin->info->version = NULL;
			plugin->info->customData = NULL;
			plugin->info->irc = loadedPlugins->irc;
			plugin->info->config = loadedPlugins->config;
			plugin->info->events = loadedPlugins->events;
			plugin->info->socketpool = loadedPlugins->socketpool;

			plugin->deps = NULL;

			plugin->init = (PluginInitPrototype *)dlsym(
				plugin->handle, "PluginInit");
			plugin->done = (PluginDonePrototype *)dlsym(
				plugin->handle, "PluginDone");
			plugin->beforeDepsUnload = (PluginDonePrototype *)dlsym(
				plugin->handle, "PluginBeforeUnload");

			if (plugin->init != NULL && plugin->done != NULL) {
				// Scan plugin dependencies.

				PluginLoadStatus depsLoad = PLUG_OK;

				// PluginDeps function is optional.
				PluginDepsPrototype *plugindeps =
					(PluginDepsPrototype *)dlsym(plugin->handle, "PluginDeps");
				if (plugindeps != NULL) {
					plugindeps(&plugin->deps);

					if (plugin->deps != NULL) {
						TOKENS tok = tokenizer_tokenize(plugin->deps, ',');
						for (size_t i = 0; i < tok->count; i++) {
							if (!plugins_isloaded(tokenizer_gettok(tok, i))) {
								depsLoad = plugins_load(
									tokenizer_gettok(tok, i));
								if (depsLoad != PLUG_OK) {
									break;
								}
							}
						}
						tokenizer_free(tok);
					}
				}

				if (depsLoad == PLUG_OK) {
					// And finally, when everything is OK, call init function.
					plugin->init(plugin->info);
					result = PLUG_OK;
				} else {
					printError("plugins", "Plugin %s will not be loaded, "
						"because of dependency error.", path);
					result = PLUG_DEPENDENCY;
				}
			} else {
				// If no init and done functions were found.
				plugins_unloadplugin(plugin);
				printError("plugins", "%s is not valid plugin.", pathdup);
				result = PLUG_INVALID;
			}

			// Unload plugin if it's loading failed.
			if (result != PLUG_OK) {
				plugin->done = NULL;
				plugins_unloadplugin(plugin);
			}
		// End of plug->handle != NULL
		} else {
			// Remove plugin from linked list
			loadedPlugins->last = loadedPlugins->last->prev;
			loadedPlugins->last->next = NULL;

			printError("plugins", "Plugin loading error: %s", dlerror());
			result = PLUG_DL_ERROR;
		}
	} else {
		printError("plugins", "Plugin file not found.");
		result = PLUG_FILE_NOT_FOUND;
	}

	return result;
} // plugins_loadplugin
Exemple #4
0
static inline retvalue morgue_name(const char *filekey, char **name_p, int *fd_p) {
    const char *name = dirs_basename(filekey);
    char *firsttry = calc_dirconcat(global.morguedir, name);
    int fd, en, number;
    retvalue r;

    if (FAILEDTOALLOC(firsttry))
        return RET_ERROR_OOM;

    fd = open(firsttry, O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY, 0666);
    if (fd >= 0) {
        assert (fd > 2);
        *name_p = firsttry;
        *fd_p = fd;
        return RET_OK;
    }
    en = errno;
    if (en == ENOENT) {
        r = dirs_make_recursive(global.morguedir);
        if (RET_WAS_ERROR(r)) {
            free(firsttry);
            return r;
        }
        /* try again */
        fd = open(firsttry, O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY, 0666);
        if (fd >= 0) {
            assert (fd > 2);
            *name_p = firsttry;
            *fd_p = fd;
            return RET_OK;
        }
        en = errno;
    }
    if (en != EEXIST) {
        fprintf(stderr, "error %d creating morgue-file %s: %s\n",
                en, firsttry, strerror(en));
        free(firsttry);
        return RET_ERRNO(en);
    }
    /* file exists, try names with -number appended: */
    for (number = 1 ; number < 1000 ; number++) {
        char *try = mprintf("%s-%d", firsttry, number);

        if (FAILEDTOALLOC(try)) {
            free(firsttry);
            return RET_ERROR_OOM;
        }
        fd = open(try, O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY, 0666);
        if (fd >= 0) {
            assert (fd > 2);
            free(firsttry);
            *name_p = try;
            *fd_p = fd;
            return RET_OK;
        }
        free(try);
    }
    free(firsttry);
    fprintf(stderr, "Could not create a new file '%s' in morguedir '%s'!\n",
            name, global.morguedir);
    return RET_ERROR;
}