int elektraSpecloadOpen (Plugin * handle, Key * errorKey) { Specload * specload = elektraMalloc (sizeof (Specload)); KeySet * conf = elektraPluginGetConfig (handle); if (ksLookupByName (conf, "system/module", 0) != NULL || ksLookupByName (conf, "system/sendspec", 0) != NULL) { elektraFree (specload); return ELEKTRA_PLUGIN_STATUS_SUCCESS; } if (!getAppAndArgs (conf, &specload->app, &specload->argv, errorKey)) { elektraFree (specload); return ELEKTRA_PLUGIN_STATUS_ERROR; } specload->quickDumpConfig = ksNew (0, KS_END); specload->quickDump = elektraInvokeOpen ("quickdump", specload->quickDumpConfig, errorKey); if (!specload->quickDump) { elektraFree (specload); return ELEKTRA_PLUGIN_STATUS_ERROR; } elektraPluginSetData (handle, specload); return ELEKTRA_PLUGIN_STATUS_SUCCESS; }
/** * Checks whether specload mode was invoked and if so, sends the specification over stdout * in the format expected by specload. * * You MUST not output anything to stdout before invoking this function. Ideally invoking this * is the first thing you do in your main()-function. * * This function will ONLY RETURN, if specload mode was NOT invoked. Otherwise it will call `exit()`. * * @param argc pass the value of argc from main * @param argv pass the value of argv from main */ void specloadCheck (int argc, const char ** argv) { if (argc != 2 || strcmp (argv[1], "--elektra-spec") != 0) { return; } KeySet * spec = ksNew (6, keyNew("", KEY_META, "mountpoint", "tests_gen_elektra_context.ini", KEY_END), keyNew ("/mydouble", KEY_VALUE, "0.0", KEY_META, "default", "0.0", KEY_META, "type", "double", KEY_END), keyNew ("/myfloatarray/#", KEY_VALUE, "0.0", KEY_META, "default", "0.0", KEY_META, "type", "float", KEY_END), keyNew ("/myint", KEY_VALUE, "0", KEY_META, "default", "0", KEY_META, "type", "long", KEY_END), keyNew ("/mystring", KEY_META, "default", "", KEY_META, "type", "string", KEY_END), keyNew ("/print", KEY_VALUE, "0", KEY_META, "default", "0", KEY_META, "type", "boolean", KEY_END), KS_END); ; Key * parentKey = keyNew ("spec/tests/script/gen/elektra/simple", KEY_END); KeySet * specloadConf = ksNew (1, keyNew ("system/sendspec", KEY_END), KS_END); ElektraInvokeHandle * specload = elektraInvokeOpen ("specload", specloadConf, parentKey); int result = elektraInvoke2Args (specload, "sendspec", spec, parentKey); elektraInvokeClose (specload, parentKey); keyDel (parentKey); ksDel (specloadConf); ksDel (spec); exit (result == ELEKTRA_PLUGIN_STATUS_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE); }
static int elektraResolveFilename (Key * parentKey, ElektraResolveTempfile tmpFile) { int rc = 0; void * handle = elektraInvokeOpen ("resolver", 0, 0); if (!handle) { rc = -1; goto RESOLVE_FAILED; } ElektraResolved * resolved = NULL; typedef ElektraResolved * (*resolveFileFunc) (elektraNamespace, const char *, ElektraResolveTempfile, Key *); resolveFileFunc resolveFunc = *(resolveFileFunc *) elektraInvokeGetFunction (handle, "filename"); if (!resolveFunc) { rc = -1; goto RESOLVE_FAILED; } typedef void (*freeHandleFunc) (ElektraResolved *); freeHandleFunc freeHandle = *(freeHandleFunc *) elektraInvokeGetFunction (handle, "freeHandle"); if (!freeHandle) { rc = -1; goto RESOLVE_FAILED; } resolved = resolveFunc (keyGetNamespace (parentKey), keyString (parentKey), tmpFile, parentKey); if (!resolved) { rc = -1; goto RESOLVE_FAILED; } else { keySetString (parentKey, resolved->fullPath); freeHandle (resolved); } RESOLVE_FAILED: elektraInvokeClose (handle, 0); return rc; }
/** * @brief decodes Base64 encoded data by utilizing libinvoke. * @param input holds the Base64 encoded data string * @param output will be set to an allocated buffer holding the decoded data or NULL if the allocation failed. Must be freed by the caller on success. * @param outputLength will be set to the amount of decoded bytes. * @param errorKey will hold an error description if libinvoke fails. * @retval 1 on success * @retval -1 if the provided string has not been encoded with Base64 * @retval -2 if the output buffer allocation failed * @retval -3 if libinvoke reported an error (errorKey is being set). */ int CRYPTO_PLUGIN_FUNCTION (base64Decode) (Key * errorKey, const char * input, kdb_octet_t ** output, size_t * outputLength) { ElektraInvokeHandle * handle = elektraInvokeOpen ("base64", 0, errorKey); if (!handle) { return -3; } typedef int (*base64DecodeFunction) (const char * input, kdb_octet_t ** output, size_t * outputLength); base64DecodeFunction decodingFunction = *(base64DecodeFunction *) elektraInvokeGetFunction (handle, "base64Decode"); if (!decodingFunction) { elektraInvokeClose (handle, 0); return -3; } int result = decodingFunction (input, output, outputLength); elektraInvokeClose (handle, 0); return result; }
/** * @brief Encodes arbitrary data using the Base64 schema by utilizing libinvoke. * @param errorKey will hold an error description if libinvoke fails. * @param input holds the data to be encoded * @param inputLength tells how many bytes the input buffer is holding. * @param output points to an allocated string holding the Base64 encoded input data or NULL if the string can not be allocated. Must be * freed by the caller. * @retval 1 on success * @retval -1 if libinvoke reported an error (errorKey is being set). */ int CRYPTO_PLUGIN_FUNCTION (base64Encode) (Key * errorKey, const kdb_octet_t * input, const size_t inputLength, char ** output) { ElektraInvokeHandle * handle = elektraInvokeOpen ("base64", 0, errorKey); if (!handle) { return -1; } typedef char * (*base64EncodeFunction) (const kdb_octet_t * input, const size_t inputLength); base64EncodeFunction encodingFunction = *(base64EncodeFunction *) elektraInvokeGetFunction (handle, "base64Encode"); if (!encodingFunction) { elektraInvokeClose (handle, 0); return -1; } *output = encodingFunction (input, inputLength); elektraInvokeClose (handle, 0); return 1; }
* @copyright BSD License (see LICENSE.md or https://www.libelektra.org) * */ #include "dini.h" #include <kdbhelper.h> int elektraDiniOpen (Plugin * handle, Key * errorKey ELEKTRA_UNUSED) { Dini * dini = elektraMalloc (sizeof (Dini)); dini->dumpConfig = ksDup (elektraPluginGetConfig (handle)); dini->iniConfig = ksDup (elektraPluginGetConfig (handle)); dini->dump = elektraInvokeOpen ("dump", dini->dumpConfig, 0); dini->ini = elektraInvokeOpen ("ini", dini->iniConfig, 0); dini->bin = elektraInvokeOpen ("binary", dini->iniConfig, 0); dini->dumpErrors = keyNew ("", KEY_END); elektraPluginSetData (handle, dini); return dini->ini ? ELEKTRA_PLUGIN_STATUS_SUCCESS : ELEKTRA_PLUGIN_STATUS_ERROR; } int elektraDiniClose (Plugin * handle, Key * errorKey ELEKTRA_UNUSED) { Dini * dini = elektraPluginGetData (handle); elektraInvokeClose (dini->bin, 0);
/** Initialize a plugin to be executed in its own process * * This will prepare all the required resources and then fork the current * process. After the initialization the child process will typically * call the command loop while the parent starts to send commands to it. * Also the resulting process information has to be stored for the plugin. * In order to allow users to handle custom plugin data this will not * automatically call elektraPluginSetData. * * Typically called in a plugin's open function like (assuming no custom plugin data): * @code int elektraPluginOpen (Plugin * handle, Key * errorKey) { ElektraPluginProcess * pp = elektraPluginGetData (handle); if (pp == NULL) { if ((pp = elektraPluginProcessInit (errorKey)) == NULL) return ELEKTRA_PLUGIN_STATUS_ERROR; elektraPluginSetData (handle, pp); if (!elektraPluginProcessIsParent (pp)) elektraPluginProcessStart (handle, pp); } if (elektraPluginProcessIsParent (pp)) return elektraPluginProcessOpen (pp, errorKey); // actual plugin functionality to be executed in a child process return ELEKTRA_PLUGIN_STATUS_SUCCESS; } * @endcode * * @param handle the plugin's handle * @param errorKey a key where error messages will be set * @retval NULL if the initialization failed * @retval a pointer to the information * @ingroup processplugin **/ ElektraPluginProcess * elektraPluginProcessInit (Key * errorKey) { // First time initialization ElektraPluginProcess * pp; pp = elektraMalloc (sizeof (ElektraPluginProcess)); pp->counter = 0; pp->pluginData = NULL; pp->parentCommandPipeKey = NULL; pp->parentPayloadPipeKey = NULL; pp->childCommandPipeKey = NULL; pp->childPayloadPipeKey = NULL; pp->dump = elektraInvokeOpen ("dump", 0, errorKey); if (!pp->dump) { cleanupPluginData (pp, errorKey, 0); ELEKTRA_SET_ERROR (190, errorKey, "Failed to initialize the dump plugin"); return NULL; } // As generally recommended, ignore SIGPIPE because we will notice that the // commandKeySet has been transferred incorrectly anyway to detect broken pipes signal (SIGPIPE, SIG_IGN); // Prepare the pipes if (!makePipe (pp, errorKey, "parentCommandPipe", pp->parentCommandPipe) || !makePipe (pp, errorKey, "parentPayloadPipe", pp->parentPayloadPipe) || !makePipe (pp, errorKey, "childCommandPipe", pp->childCommandPipe) || !makePipe (pp, errorKey, "childPayloadPipe", pp->childPayloadPipe)) return NULL; pp->pid = fork (); if (pp->pid < 0) { cleanupPluginData (pp, errorKey, 1); ELEKTRA_SET_ERRORF (190, errorKey, "Failed to fork the plugin process, fork () returned %d", pp->pid); return NULL; } int pipeIdx = elektraPluginProcessIsParent (pp); close (pp->parentCommandPipe[!pipeIdx]); close (pp->parentPayloadPipe[!pipeIdx]); close (pp->childCommandPipe[pipeIdx]); close (pp->childPayloadPipe[pipeIdx]); ELEKTRA_LOG_DEBUG ("parentCommandPipe[%d] has file descriptor %d", pipeIdx, pp->parentCommandPipe[pipeIdx]); ELEKTRA_LOG_DEBUG ("parentPayloadPipe[%d] has file descriptor %d", pipeIdx, pp->parentPayloadPipe[pipeIdx]); ELEKTRA_LOG_DEBUG ("childCommandPipe[%d] has file descriptor %d", !pipeIdx, pp->childCommandPipe[!pipeIdx]); ELEKTRA_LOG_DEBUG ("childPayloadPipe[%d] has file descriptor %d", !pipeIdx, pp->childPayloadPipe[!pipeIdx]); // Prepare the keys for the pipes to use with dump pp->parentCommandPipeKey = makePipeKey ("parentCommandPipe", pp->parentCommandPipe[pipeIdx]); pp->parentPayloadPipeKey = makePipeKey ("parentPayloadPipe", pp->parentPayloadPipe[pipeIdx]); pp->childCommandPipeKey = makePipeKey ("childCommandPipe", pp->childCommandPipe[!pipeIdx]); pp->childPayloadPipeKey = makePipeKey ("childPayloadPipe", pp->childPayloadPipe[!pipeIdx]); ELEKTRA_LOG_DEBUG ("parentCommandPipeKey is %s on %d", keyString (pp->parentCommandPipeKey), pp->pid); ELEKTRA_LOG_DEBUG ("parentPayloadPipeKey is %s on %d", keyString (pp->parentPayloadPipeKey), pp->pid); ELEKTRA_LOG_DEBUG ("childCommandPipeKey is %s on %d", keyString (pp->childCommandPipeKey), pp->pid); ELEKTRA_LOG_DEBUG ("childPayloadPipeKey is %s on %d", keyString (pp->childPayloadPipeKey), pp->pid); ELEKTRA_LOG_DEBUG ("The pluginprocess is set with the pid %d", pp->pid); return pp; }
* Note: To use this function with elektraInvoke2Args, call elektraInvokeOpen with a config containing * the key 'system/sendspec'. This postpones the check for an existent app until elektraSpecloadGet is called. * * @param handle A specload plugin handle. * @param spec The specification to send. * @param parentKey The parent key under which the target specload instance was mounted. Value unused. * * @retval #ELEKTRA_PLUGIN_STATUS_SUCCESS on success * @retval #ELEKTRA_PLUGIN_STATUS_ERROR on error */ int elektraSpecloadSendSpec (Plugin * handle ELEKTRA_UNUSED, KeySet * spec, Key * parentKey) { Key * errorKey = keyNew (0, KEY_END); KeySet * quickDumpConf = ksNew (0, KS_END); ElektraInvokeHandle * quickDump = elektraInvokeOpen ("quickdump", quickDumpConf, errorKey); Key * quickDumpParent = keyNew (keyName (parentKey), KEY_VALUE, STDOUT_FILENAME, KEY_END); int result = elektraInvoke2Args (quickDump, "set", spec, quickDumpParent); elektraInvokeClose (quickDump, errorKey); keyDel (errorKey); keyDel (quickDumpParent); ksDel (quickDumpConf); return result == ELEKTRA_PLUGIN_STATUS_SUCCESS ? ELEKTRA_PLUGIN_STATUS_SUCCESS : ELEKTRA_PLUGIN_STATUS_ERROR; } int elektraSpecloadGet (Plugin * handle, KeySet * returned, Key * parentKey) {