]> git.ozlabs.org Git - petitboot/blob - discover/grub2/script.c
discover/grub2: Remove debug printfs
[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 #define to_stmt_simple(stmt) \
11         container_of(stmt, struct grub2_statement_simple, st)
12 #define to_stmt_if(stmt) \
13         container_of(stmt, struct grub2_statement_if, st)
14
15 struct env_entry {
16         const char              *name;
17         const char              *value;
18         struct list_item        list;
19 };
20
21 static const char *env_lookup(struct grub2_script *script,
22                 const char *name, int name_len)
23 {
24         struct env_entry *entry;
25
26         list_for_each_entry(&script->environment, entry, list)
27                 if (!strncmp(entry->name, name, name_len)
28                                 && entry->name[name_len] == '\0')
29                         return entry->value;
30
31         return NULL;
32 }
33
34 static bool expand_word(struct grub2_script *script, struct grub2_word *word)
35 {
36         const char *val, *src;
37         char *dest = NULL;
38         regmatch_t match;
39         int n, i;
40
41         src = word->text;
42
43         n = regexec(&script->var_re, src, 1, &match, 0);
44         if (n != 0)
45                 return false;
46
47         i = 0;
48         if (src[match.rm_so + 1] == '{')
49                 i++;
50
51         val = env_lookup(script, src + match.rm_so + 1 + i,
52                                  match.rm_eo - match.rm_so - 1 - (i * 2));
53         if (!val)
54                 val = "";
55
56         dest = talloc_strndup(script, src, match.rm_so);
57         dest = talloc_asprintf_append(dest, "%s%s", val, src + match.rm_eo);
58
59         word->text = dest;
60         return true;
61 }
62
63 /* iterate through the words in an argv, looking for expansions. If a
64  * word is marked with expand == true, then we process any variable
65  * substitutions.
66  *
67  * Once that's done, we may (if split == true) have to split the word to create
68  * new argv items
69  */
70 static void process_expansions(struct grub2_script *script,
71                 struct grub2_argv *argv)
72 {
73         struct grub2_word *word;
74
75         list_for_each_entry(&argv->words, word, argv_list) {
76                 if (!word->expand)
77                         continue;
78
79                 expand_word(script, word);
80         }
81 }
82
83 int statements_execute(struct grub2_script *script,
84                 struct grub2_statements *stmts)
85 {
86         struct grub2_statement *stmt;
87         int rc = 0;
88
89         list_for_each_entry(&stmts->list, stmt, list) {
90                 if (stmt->exec)
91                         rc = stmt->exec(script, stmt);
92         }
93         return rc;
94 }
95
96 int statement_simple_execute(struct grub2_script *script,
97                 struct grub2_statement *statement)
98 {
99         struct grub2_statement_simple *st = to_stmt_simple(statement);
100
101         if (!st->argv)
102                 return 0;
103
104         process_expansions(script, st->argv);
105
106         return 0;
107 }
108
109 int statement_if_execute(struct grub2_script *script,
110                 struct grub2_statement *statement)
111 {
112         struct grub2_statement_if *st = to_stmt_if(statement);
113         struct grub2_statements *case_stmts;
114         int rc;
115
116         rc = st->condition->exec(script, st->condition);
117
118         if (rc == 0)
119                 case_stmts = st->true_case;
120         else
121                 case_stmts = st->false_case;
122
123         if (case_stmts)
124                 statements_execute(script, case_stmts);
125         else
126                 rc = 0;
127
128         return rc;
129 }
130
131 static void init_env(struct grub2_script *script)
132 {
133         struct env_entry *env;
134
135         list_init(&script->environment);
136
137         env = talloc(script, struct env_entry);
138         env->name = talloc_strdup(env, "prefix");
139         env->value = talloc_strdup(env, "/");
140
141         list_add(&script->environment, &env->list);
142 }
143
144
145 void script_execute(struct grub2_script *script)
146 {
147         statements_execute(script, script->statements);
148 }
149
150 static int script_destroy(void *p)
151 {
152         struct grub2_script *script = p;
153         regfree(&script->var_re);
154         return 0;
155 }
156
157 struct grub2_script *create_script(void *ctx)
158 {
159         struct grub2_script *script;
160         int rc;
161
162         script = talloc(ctx, struct grub2_script);
163
164         rc = regcomp(&script->var_re,
165                 "\\$\\{?([[:alpha:]][_[:alnum:]]*|[0-9]|[\\?@\\*#])\\}?",
166                         REG_EXTENDED);
167         if (rc) {
168                 char err[200];
169                 regerror(rc, &script->var_re, err, sizeof(err));
170                 fprintf(stderr, "RE error %d: %s\n", rc, err);
171                 talloc_free(script);
172                 return NULL;
173
174         }
175         talloc_set_destructor(script, script_destroy);
176
177         init_env(script);
178
179         return script;
180 }
181