summaryrefslogtreecommitdiffstats
path: root/discover/grub2/script.c
blob: 067b0c9440857f48b0ce4c0ad84c3e3e559484ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

#include <sys/types.h>
#include <regex.h>
#include <string.h>

#include <talloc/talloc.h>

#include "grub2.h"

struct env_entry {
	const char		*name;
	const char		*value;
	struct list_item	list;
};

static const char *env_lookup(struct grub2_script *script,
		const char *name, int name_len)
{
	struct env_entry *entry;
	const char *str;

	str = talloc_strndup(script, name, name_len);
	printf("%s: %s\n", __func__, str);

	list_for_each_entry(&script->environment, entry, list)
		if (!strncmp(entry->name, name, name_len))
			return entry->value;

	return NULL;
}

static bool expand_word(struct grub2_script *script, struct grub2_word *word)
{
	const char *val, *src;
	char *dest = NULL;
	regmatch_t match;
	int n;

	src = word->text;

	n = regexec(&script->var_re, src, 1, &match, 0);
	if (n == 0)
		return false;

	val = env_lookup(script, src + match.rm_so,
				 match.rm_eo - match.rm_so);
	if (val)
		val = "";

	dest = talloc_strndup(script, src, match.rm_so);
	dest = talloc_asprintf_append(dest, "%s%s", val, src + match.rm_eo);

	word->text = dest;
	return true;
}

/* iterate through the words in an argv, looking for expansions. If a
 * word is marked with expand == true, then we process any variable
 * substitutions.
 *
 * Once that's done, we may (if split == true) have to split the word to create
 * new argv items
 */
static void process_expansions(struct grub2_script *script,
		struct grub2_argv *argv)
{
	struct grub2_word *word;

	list_for_each_entry(&argv->words, word, argv_list) {
		if (!word->expand)
			continue;

		expand_word(script, word);
	}
}

static int script_destroy(void *p)
{
	struct grub2_script *script = p;
	regfree(&script->var_re);
	return 0;
}

struct grub2_script *create_script(void *ctx)
{
	struct grub2_script *script;
	int rc;

	script = talloc(ctx, struct grub2_script);

	rc = regcomp(&script->var_re,
		"\\$\\{?([[:alpha:]][_[:alnum:]]*|[0-9]|[\\?@\\*#])\\}?",
			REG_EXTENDED);
	if (rc) {
		char err[200];
		regerror(rc, &script->var_re, err, sizeof(err));
		fprintf(stderr, "RE error %d: %s\n", rc, err);
		talloc_free(script);
		return NULL;

	}
	talloc_set_destructor(script, script_destroy);

	list_init(&script->environment);

	return script;
}

OpenPOWER on IntegriCloud