]> git.ozlabs.org Git - petitboot/blob - discover/grub2/script.c
discover/grub2: Add var expansion code
[petitboot] / discover / grub2 / script.c
1
2 #include <sys/types.h>
3 #include <regex.h>
4 #include <string.h>
5
6 #include <talloc/talloc.h>
7
8 #include "grub2.h"
9
10 struct env_entry {
11         const char              *name;
12         const char              *value;
13         struct list_item        list;
14 };
15
16 static const char *env_lookup(struct grub2_script *script,
17                 const char *name, int name_len)
18 {
19         struct env_entry *entry;
20         const char *str;
21
22         str = talloc_strndup(script, name, name_len);
23         printf("%s: %s\n", __func__, str);
24
25         list_for_each_entry(&script->environment, entry, list)
26                 if (!strncmp(entry->name, name, name_len))
27                         return entry->value;
28
29         return NULL;
30 }
31
32 static bool expand_word(struct grub2_script *script, struct grub2_word *word)
33 {
34         const char *val, *src;
35         char *dest = NULL;
36         regmatch_t match;
37         int n;
38
39         src = word->text;
40
41         n = regexec(&script->var_re, src, 1, &match, 0);
42         if (n == 0)
43                 return false;
44
45         val = env_lookup(script, src + match.rm_so,
46                                  match.rm_eo - match.rm_so);
47         if (val)
48                 val = "";
49
50         dest = talloc_strndup(script, src, match.rm_so);
51         dest = talloc_asprintf_append(dest, "%s%s", val, src + match.rm_eo);
52
53         word->text = dest;
54         return true;
55 }
56
57 /* iterate through the words in an argv, looking for expansions. If a
58  * word is marked with expand == true, then we process any variable
59  * substitutions.
60  *
61  * Once that's done, we may (if split == true) have to split the word to create
62  * new argv items
63  */
64 static void process_expansions(struct grub2_script *script,
65                 struct grub2_argv *argv)
66 {
67         struct grub2_word *word;
68
69         list_for_each_entry(&argv->words, word, argv_list) {
70                 if (!word->expand)
71                         continue;
72
73                 expand_word(script, word);
74         }
75 }
76
77 static int script_destroy(void *p)
78 {
79         struct grub2_script *script = p;
80         regfree(&script->var_re);
81         return 0;
82 }
83
84 struct grub2_script *create_script(void *ctx)
85 {
86         struct grub2_script *script;
87         int rc;
88
89         script = talloc(ctx, struct grub2_script);
90
91         rc = regcomp(&script->var_re,
92                 "\\$\\{?([[:alpha:]][_[:alnum:]]*|[0-9]|[\\?@\\*#])\\}?",
93                         REG_EXTENDED);
94         if (rc) {
95                 char err[200];
96                 regerror(rc, &script->var_re, err, sizeof(err));
97                 fprintf(stderr, "RE error %d: %s\n", rc, err);
98                 talloc_free(script);
99                 return NULL;
100
101         }
102         talloc_set_destructor(script, script_destroy);
103
104         list_init(&script->environment);
105
106         return script;
107 }
108