#include <pcre2.h>
#include <pakfire/errno.h>
+#include <pakfire/execute.h>
#include <pakfire/logging.h>
#include <pakfire/parser.h>
#include <pakfire/pakfire.h>
size_t num_declarations;
// Regular expressions
+ pcre2_code* regex_command;
pcre2_code* regex_variable;
};
size_t pcre2_offset;
PCRE2_UCHAR errmsg[256];
+ // Commands
+ if (!parser->regex_command && parser->flags & PAKFIRE_PARSER_FLAGS_EXPAND_COMMANDS) {
+ parser->regex_command = pcre2_compile((PCRE2_SPTR)"%\\((.*)\\)",
+ PCRE2_ZERO_TERMINATED, 0, &pcre2_errno, &pcre2_offset, NULL);
+
+ if (!parser->regex_command) {
+ pcre2_get_error_message(pcre2_errno, errmsg, sizeof(errmsg));
+ ERROR(parser->pakfire, "PCRE2 compilation failed at offset %zu: %s\n",
+ pcre2_offset, errmsg);
+
+ return 1;
+ }
+
+ // Enable JIT
+ pcre2_errno = pcre2_jit_compile(parser->regex_command, PCRE2_JIT_COMPLETE);
+ if (pcre2_errno) {
+ pcre2_get_error_message(pcre2_errno, errmsg, sizeof(errmsg));
+ ERROR(parser->pakfire, "Enabling JIT on commands failed: %s\n", errmsg);
+ return 1;
+ }
+ }
+
+ // Variables
if (!parser->regex_variable) {
parser->regex_variable = pcre2_compile((PCRE2_SPTR)"%\\{([A-Za-z0-9_\\-]+)\\}",
PCRE2_ZERO_TERMINATED, 0, &pcre2_errno, &pcre2_offset, NULL);
return d;
}
+static int pakfire_parser_expand_commands(PakfireParser parser, char** buffer) {
+ int r = 0;
+ PCRE2_UCHAR* command = NULL;
+ PCRE2_SIZE command_length;
+ PCRE2_UCHAR* pattern = NULL;
+ PCRE2_SIZE pattern_length;
+
+ DEBUG(parser->pakfire, "Searching for commands in:\n%s\n", *buffer);
+
+ // Allocate memory for results
+ pcre2_match_data* match = pcre2_match_data_create_from_pattern(
+ parser->regex_command, NULL);
+
+ // Arguments passed to pakfire_execute
+ const char* argv[4] = {
+ "/bin/sh", "-c", NULL /* will be replaced by command later */, NULL,
+ };
+
+ while (1) {
+ // Perform matching
+ int r = pcre2_jit_match(parser->regex_command,
+ (PCRE2_UCHAR*)*buffer, strlen(*buffer), 0, 0, match, NULL);
+
+ // End loop when we have expanded all variables
+ if (r == PCRE2_ERROR_NOMATCH)
+ break;
+
+ // Extract the command
+ r = pcre2_substring_get_bynumber(match, 1, &command, &command_length);
+ if (r)
+ goto ERROR;
+
+ DEBUG(parser->pakfire, "Expanding command: %s\n", command);
+
+ // Update argv
+ argv[2] = (const char*)command;
+
+ // The output of the command
+ const char* output = "XXX";
+
+ // Execute the command inside the Pakfire environment
+ r = pakfire_execute(parser->pakfire, argv, NULL, 0, NULL);
+ if (r) {
+ // Just log this and continue
+ DEBUG(parser->pakfire, "Command '%s' failed with return code %d\n", command, r);
+ }
+
+ // Find the entire matched pattern
+ r = pcre2_substring_get_bynumber(match, 0, &pattern, &pattern_length);
+ if (r)
+ goto ERROR;
+
+ // Replace all occurrences
+ char* tmp = pakfire_string_replace(*buffer, (const char*)pattern, output);
+ if (!tmp)
+ goto ERROR;
+
+ // Replace buffer
+ free(*buffer);
+ *buffer = tmp;
+
+ // Free resources
+ pcre2_substring_free(command);
+ command = NULL;
+
+ pcre2_substring_free(pattern);
+ pattern = NULL;
+ }
+
+ERROR:
+ pcre2_match_data_free(match);
+
+ if (command)
+ pcre2_substring_free(command);
+ if (pattern)
+ pcre2_substring_free(pattern);
+
+ return r;
+}
+
static int pakfire_parser_expand_variables(PakfireParser parser,
const char* namespace, char** buffer) {
+ int r = 0;
PCRE2_UCHAR* variable = NULL;
PCRE2_SIZE variable_length;
PCRE2_UCHAR* pattern = NULL;
PCRE2_SIZE pattern_length;
- // Compile all regular expressions
- int r = pakfire_parser_compile_regex(parser);
- if (r)
- goto ERROR;
-
// Allocate memory for results
- pcre2_match_data* match = pcre2_match_data_create_from_pattern(parser->regex_variable, NULL);
+ pcre2_match_data* match = pcre2_match_data_create_from_pattern(
+ parser->regex_variable, NULL);
// Search for any variables
while (1) {
if (!pos)
return buffer;
+ // Compile all regular expressions
+ int r = pakfire_parser_compile_regex(parser);
+ if (r) {
+ free(buffer);
+ return NULL;
+ }
+
// Expand all variables
- int r = pakfire_parser_expand_variables(parser, namespace, &buffer);
+ r = pakfire_parser_expand_variables(parser, namespace, &buffer);
if (r) {
if (buffer)
free(buffer);
return NULL;
}
+ // Expand all commands
+ if (parser->flags & PAKFIRE_PARSER_FLAGS_EXPAND_COMMANDS) {
+ r = pakfire_parser_expand_commands(parser, &buffer);
+ if (r) {
+ if (buffer)
+ free(buffer);
+
+ return NULL;
+ }
+ }
+
return buffer;
}