Esempio n. 1
0
/*
 * plugin_modify_key_value
 * A wrapper function for invoking the plugin dependency set/del call
 * for a changed a key value. 
 * The routine logs on debug.
 * It also checks whether an error was properly registered using clicon_err().
 * Arguments:
 *   db:   The database which contains the key value, most relevant in a set operation
 *         but may possibly in some cases be important in delete operations, although
 *         I cannot think of any,..
 *   key:  The name of the key in the database above.
 *   op:   Either set or delete
 *   dep:  plugin dependency information. Contains function and argument pointers.
 *
 * Returns:
 *  0: OK
 * -1: An error occured in the plugin commit function. It is assumed that 
 *     clicon_err() has been called there. Here, we interpret the clicon_err
 *     as a 'commit' error and does not handle it fatally. 
 */
static int
plugin_modify_key_value(clicon_handle h, 
			char *db, 
			char *key,
			enum trans_cb_type type,
			lv_op_t op,
			dbdep_t *dp)
{
    int retval = -1;

    clicon_debug(2, "commit diff %c%s", (op==LV_SET)?'+':'-', key);
    clicon_err_reset();
    if (dp->dp_callback(h, db, type, op, key, dp->dp_arg) < 0){
	if (!clicon_errno) 	/* sanity: log if clicon_err() is not called ! */
	    clicon_err(OE_DB, 0, "Unknown error: %c%s: plugin does not make clicon_err call on error",
		    (op==LV_SET)?'+':'-', key);
	goto done;
    }
    retval = 0;
  done:
    return retval;
}
Esempio n. 2
0
/*! Load a dynamic plugin object and call its init-function
 * @param[in]  h       Clicon handle
 * @param[in]  file    Which plugin to load
 * @param[in]  function Which function symbol to load and call
 * @param[in]  dlflags See man(3) dlopen
 * @param[out] cpp      Clixon plugin structure (if retval is 1)
 * @retval     1     OK
 * @retval     0     Failed load, log, skip and continue with other plugins
 * @retval     -1    Error
 * @see clixon_plugins_load  Load all plugins
 */
static int
plugin_load_one(clicon_handle   h, 
		char           *file,
		char           *function,
		int             dlflags,
		clixon_plugin **cpp)
{
    int                retval = -1;
    char              *error;
    void              *handle = NULL;
    plginit2_t        *initfn;
    clixon_plugin_api *api = NULL;
    clixon_plugin     *cp = NULL;
    char              *name;
    char              *p;

    clicon_debug(1, "%s file:%s function:%s", __FUNCTION__, file, function);
    dlerror();    /* Clear any existing error */
    if ((handle = dlopen(file, dlflags)) == NULL) {
        error = (char*)dlerror();
	clicon_err(OE_PLUGIN, errno, "dlopen: %s", error ? error : "Unknown error");
	goto done;
    }
    /* call plugin_init() if defined, eg CLIXON_PLUGIN_INIT or CLIXON_BACKEND_INIT */
    if ((initfn = dlsym(handle, function)) == NULL){
	clicon_err(OE_PLUGIN, errno, "Failed to find %s when loading clixon plugin %s", CLIXON_PLUGIN_INIT, file);
	goto done;
    }
    if ((error = (char*)dlerror()) != NULL) {
	clicon_err(OE_UNIX, 0, "dlsym: %s: %s", file, error);
	goto done;
    }
    clicon_err_reset();
    if ((api = initfn(h)) == NULL) {
	if (!clicon_errno){ 	/* if clicon_err() is not called then log and continue */
	    clicon_log(LOG_DEBUG, "Warning: failed to initiate %s", strrchr(file,'/')?strchr(file, '/'):file);
	    retval = 0;
	    goto done;
	}
	else{
	    clicon_err(OE_PLUGIN, errno, "Failed to initiate %s", strrchr(file,'/')?strchr(file, '/'):file);
	    goto done;
	}
    }
    /* Note: sizeof clixon_plugin_api which is largest of clixon_plugin_api:s */
    if ((cp = (clixon_plugin *)malloc(sizeof(struct clixon_plugin))) == NULL){
	clicon_err(OE_UNIX, errno, "malloc");
	goto done;
    }
    memset(cp, 0, sizeof(struct clixon_plugin));
    cp->cp_handle = handle;
    /* Extract string after last '/' in filename, if any */
    name = strrchr(file, '/') ? strrchr(file, '/')+1 : file;
    /* strip extension, eg .so from name */
    if ((p=strrchr(name, '.')) != NULL)
	*p = '\0';
    /* Copy name to struct */
    memcpy(cp->cp_name, name, strlen(name)+1);

    snprintf(cp->cp_name, sizeof(cp->cp_name), "%*s",
	     (int)strlen(name), name);
    cp->cp_api = *api;
    clicon_debug(1, "%s", __FUNCTION__);
    if (cp){
	*cpp = cp;
	cp = NULL;
    }
    retval = 1;
 done:
    if (retval != 1 && handle)
	dlclose(handle);
    if (cp)
	free(cp);
    return retval;
}