/*********************************************************************************************************************************** Build list of parameters to use for perl main ***********************************************************************************************************************************/ String * perlMain(void) { FUNCTION_TEST_VOID(); // Add command arguments to pass to main String *commandParam = strNew(""); for (unsigned int paramIdx = 0; paramIdx < strLstSize(cfgCommandParam()); paramIdx++) strCatFmt(commandParam, ",'%s'", strPtr(strLstGet(cfgCommandParam(), paramIdx))); // Construct Perl main call String *mainCall = strNewFmt( "($iResult, $bErrorC, $strMessage) = " PGBACKREST_MAIN "('%s'%s)", cfgCommandName(cfgCommand()), strPtr(commandParam)); FUNCTION_TEST_RETURN(mainCall); }
/*********************************************************************************************************************************** Initialize Perl ***********************************************************************************************************************************/ static void perlInit(void) { FUNCTION_TEST_VOID(); if (!my_perl) { // Initialize Perl with dummy args and environment int argc = 1; const char *argv[1] = {strPtr(cfgExe())}; const char *env[1] = {NULL}; PERL_SYS_INIT3(&argc, (char ***)&argv, (char ***)&env); // Create the interpreter const char *embedding[] = {"", "-e", "0"}; my_perl = perl_alloc(); perl_construct(my_perl); // Don't let $0 assignment update the proctitle or embedding[0] PL_origalen = 1; // Start the interpreter perl_parse(my_perl, xs_init, 3, (char **)embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); // Use customer loader to get all embedded modules eval_pv("splice(@INC, 0, 0, " LOADER_SUB ");", true); // Now that the custom loader is installed, load the main module; eval_pv("use " PGBACKREST_MODULE ";", true); // Set config data -- this is done separately to avoid it being included in stack traces perlEval(strNewFmt(PGBACKREST_MAIN "ConfigSet('%s', '%s')", strPtr(cfgExe()), strPtr(perlOptionJson()))); } FUNCTION_TEST_RETURN_VOID(); }
/*********************************************************************************************************************************** Wrapper for lstNew() ***********************************************************************************************************************************/ StringList * strLstNew(void) { FUNCTION_TEST_VOID(); FUNCTION_TEST_RETURN((StringList *)lstNew(sizeof(String *))); }
/*********************************************************************************************************************************** Build JSON output from options ***********************************************************************************************************************************/ String * perlOptionJson(void) { FUNCTION_TEST_VOID(); String *result = NULL; MEM_CONTEXT_TEMP_BEGIN() { KeyValue *configKv = kvNew(); for (ConfigOption optionId = 0; optionId < CFG_OPTION_TOTAL; optionId++) { // Skip if not valid if (!cfgOptionValid(optionId)) continue; Variant *optionVar = varNewKv(kvNew()); // Add valid kvPut(varKv(optionVar), VARSTRDEF("valid"), BOOL_TRUE_VAR); // Add source const Variant *source = NULL; switch (cfgOptionSource(optionId)) { case cfgSourceParam: { source = VARSTRDEF("param"); break; } case cfgSourceConfig: { source = VARSTRDEF("config"); break; } case cfgSourceDefault: { source = VARSTRDEF("default"); break; } } kvPut(varKv(optionVar), VARSTRDEF("source"), source); // Add negate and reset kvPut(varKv(optionVar), VARSTRDEF("negate"), VARBOOL(cfgOptionNegate(optionId))); kvPut(varKv(optionVar), VARSTRDEF("reset"), VARBOOL(cfgOptionReset(optionId))); // Add value if it is set if (cfgOptionTest(optionId)) { const Variant *valueVar = NULL; switch (cfgDefOptionType(cfgOptionDefIdFromId(optionId))) { case cfgDefOptTypeBoolean: case cfgDefOptTypeFloat: case cfgDefOptTypeInteger: case cfgDefOptTypePath: case cfgDefOptTypeSize: case cfgDefOptTypeString: { valueVar = cfgOption(optionId); break; } case cfgDefOptTypeHash: { valueVar = varNewKv(kvNew()); const KeyValue *valueKv = cfgOptionKv(optionId); const VariantList *keyList = kvKeyList(valueKv); for (unsigned int listIdx = 0; listIdx < varLstSize(keyList); listIdx++) kvPut(varKv(valueVar), varLstGet(keyList, listIdx), kvGet(valueKv, varLstGet(keyList, listIdx))); break; } case cfgDefOptTypeList: { valueVar = varNewKv(kvNew()); const VariantList *valueList = cfgOptionLst(optionId); for (unsigned int listIdx = 0; listIdx < varLstSize(valueList); listIdx++) kvPut(varKv(valueVar), varLstGet(valueList, listIdx), BOOL_TRUE_VAR); break; } } kvPut(varKv(optionVar), VARSTRDEF("value"), valueVar); } kvPut(configKv, VARSTRZ(cfgOptionName(optionId)), optionVar); } memContextSwitch(MEM_CONTEXT_OLD()); result = jsonFromKv(configKv, 0); memContextSwitch(MEM_CONTEXT_TEMP()); } MEM_CONTEXT_TEMP_END(); FUNCTION_TEST_RETURN(result); }
/*********************************************************************************************************************************** Get/set buffer size ***********************************************************************************************************************************/ size_t ioBufferSize(void) { FUNCTION_TEST_VOID(); FUNCTION_TEST_RETURN(bufferSize); }