1 Index: grub-0.95/stage2/shared.h
2 ===================================================================
3 --- grub-0.95.orig/stage2/shared.h
4 +++ grub-0.95/stage2/shared.h
5 @@ -1008,9 +1008,11 @@ int grub_seek (int offset);
7 void grub_close (void);
9 -/* List the contents of the directory that was opened with GRUB_OPEN,
10 - printing all completions. */
11 -int dir (char *dirname);
12 +/* List the contents of DIRECTORY. */
13 +int dir (char *dirname, void (*handle)(char *));
15 +/* Wildcard expand the last pathname component of GLOB. */
16 +char *wildcard (char *glob);
18 int set_bootdev (int hdbias);
20 Index: grub-0.95/stage2/stage2.c
21 ===================================================================
22 --- grub-0.95.orig/stage2/stage2.c
23 +++ grub-0.95/stage2/stage2.c
24 @@ -1240,6 +1240,192 @@ get_line_from_config (char *cmdline, int
28 +char *wildcard_prefix, *wildcard_suffix;
29 +char wildcard_matches[1024], *end_wildcard_matches;
31 +static void wildcard_handler(char *name);
33 +/* Match one directory entry against the current wildcard. If the entry
34 + matches, store it in WILDCARD_MATCHES. Silently ignore entries that
35 + don't fit into WILDCARD_MATCHES anymore. */
37 +wildcard_handler(char *name)
39 + char *n = name, *p = wildcard_prefix;
41 + while (*p && *p == *n)
47 + return; /* prefix mismatch */
49 + p = name + grub_strlen (name) - grub_strlen (wildcard_suffix);
50 + /* [n .. p) is the part matching the asterisk */
52 + if (p <= n || grub_strcmp (p, wildcard_suffix) != 0)
53 + return; /* zero-length match or suffix mismatch */
55 + /* store this match */
56 + if (p - n + 2 > sizeof (wildcard_matches) -
57 + (end_wildcard_matches - wildcard_matches))
58 + return; /* out of space */
60 + *end_wildcard_matches++ = *n++;
61 + *end_wildcard_matches++ = 0;
64 +/* Wildcard expand the GLOB argument. Return NULL upon failure, or
65 + a list of 0-terminated expansions, terminated by a zero-length string. */
67 +wildcard (char *glob)
72 + end_wildcard_matches = wildcard_matches;
73 + if (grub_strlen (glob) + 1 > sizeof (path)) {
74 + errnum = ERR_FILELENGTH;
75 + return NULL; /* cannot handle pathnames this long */
77 + grub_strcpy (path, glob);
81 + wildcard_suffix = p;
82 + while (p > path && *p != '/')
86 + errnum = ERR_BAD_FILETYPE;
87 + return NULL; /* Cannot wildcard device names */
90 + wildcard_prefix = glob + (p - path);
91 + for (p = wildcard_prefix;; p++)
95 + /* We cannot do exact matches: this cannot be represented in the
102 + wildcard_suffix = p;
107 + ret = dir (path, wildcard_handler);
108 + /* restore original argument */
109 + wildcard_prefix[grub_strlen (wildcard_prefix)] = '*';
112 + *end_wildcard_matches++ = 0;
113 + return wildcard_matches;
116 +#define skip(str) ((str) + grub_strlen (str) + 1)
118 +static void inplace_sort (char *str);
121 +inplace_sort (char *str)
126 + for (s = str; *s; s = skip (s))
129 + /* we use x as temporary storage */
132 + for (; n >= 2; n--)
137 + for (m = n; m >= 2; m--)
139 + if (grub_strcmp (s, t) > 0)
141 + int ls = skip (s) - s;
142 + int lt = skip (t) - t;
145 + grub_memmove (s + ls, s + lt, t - (s + ls));
156 +static int this_config_len (const char *config);
158 +this_config_len (const char *config)
160 + const char *c = config;
171 +static const char * expand_asterisks (const char *str, int *len,
172 + const char *subst);
174 +/* Expand all asterisks (*) in a menu entry or commands section with its
175 + substitution. Use a backslash as escape character. */
177 +expand_asterisks (const char *str, int *len, const char *subst)
179 + static char buffer[1024];
180 + char *b = buffer, escaped = 0;
181 + const char *end = str + *len;
185 + if (*str == '*' && !escaped)
187 + if (b - buffer + grub_strlen (subst) > sizeof (buffer))
189 + errnum = ERR_FILELENGTH;
192 + grub_strcpy (b, subst);
193 + b += grub_strlen (subst);
195 + else if (*str == '\\' && !escaped)
200 + if (b - buffer + 1 > sizeof (buffer))
202 + errnum = ERR_FILELENGTH;
214 /* This is the starting function in C. */
217 @@ -1260,6 +1446,96 @@ cmain (void)
221 + auto void expand_wildcard_entries (void);
222 + void expand_wildcard_entries (void)
224 + char *config_entry = config_entries;
225 + char *menu_entry = menu_entries;
227 + while (*menu_entry)
229 + char *command = config_entry;
234 + const char *w = "wildcard";
236 + while (*w && *c == *w)
241 + if (*w == 0 && (*c == ' ' || *c == '\t' || *c == '='))
245 + /* This is a wildcard command. Advance to the argument. */
246 + while (*c == ' ' || *c == '\t' || *c == '=')
249 + /* Expand wildcard entry. */
254 + /* Remove the wildcard command from the command section;
255 + it has no meaning beyond the wildcard expansion just
257 + len = grub_strlen (command) + 1;
258 + grub_memmove (command, command + len,
259 + config_len - (command - config_entries));
264 + /* Insert expansion before the wildcard entry in the
265 + list of entry names. */
266 + len = grub_strlen (menu_entry) + 1;
267 + const char *x = expand_asterisks (menu_entry, &len, w);
268 + grub_memmove (menu_entry + len, menu_entry,
269 + menu_len - (menu_entry - menu_entries));
270 + memcpy (menu_entry, x, len);
274 + /* Insert expansion before the wildcard command section
275 + in the list of command sections. */
276 + len = this_config_len (config_entry);
277 + x = expand_asterisks (config_entry, &len, w);
278 + grub_memmove (config_entry + len, config_entry,
279 + config_len - (config_entry -
281 + memcpy (config_entry, x, len);
282 + config_entry += len;
286 + w += grub_strlen (w) + 1;
289 + /* Remove the wildcard command section; it has just
291 + len = grub_strlen (menu_entry) + 1;
292 + grub_memmove (menu_entry, menu_entry + len,
293 + menu_len - (menu_entry - menu_entries));
296 + len = this_config_len(config_entry);
297 + grub_memmove (config_entry, config_entry + len,
298 + config_len - (config_entry - config_entries));
303 + command += grub_strlen (command) + 1;
306 + menu_entry += grub_strlen (menu_entry) + 1;
307 + config_entry += this_config_len(config_entry);
311 /* Initialize the environment for restarting Stage 2. */
312 grub_setjmp (restart_env);
314 @@ -1379,8 +1655,16 @@ cmain (void)
315 config_len = prev_config_len;
319 + close_preset_menu ();
323 menu_entries[menu_len++] = 0;
324 config_entries[config_len++] = 0;
326 + expand_wildcard_entries();
328 grub_memmove (config_entries + config_len, menu_entries,
330 menu_entries = config_entries + config_len;
331 @@ -1395,11 +1679,6 @@ cmain (void)
333 default_entry = fallback_entry;
337 - close_preset_menu ();
343 Index: grub-0.95/stage2/builtins.c
344 ===================================================================
345 --- grub-0.95.orig/stage2/builtins.c
346 +++ grub-0.95/stage2/builtins.c
347 @@ -4831,6 +4831,49 @@ static struct builtin builtin_vbeprobe =
353 +wildcard_func (char *arg, int flags)
355 +#ifdef DEBUG_WILDCARD
356 + char *w = wildcard (arg);
362 + grub_printf("%s ", w);
363 + w += strlen (w) + 1;
372 + /* This special command is interpreted in the config file parser. */
376 +static struct builtin builtin_wildcard =
380 +#ifndef DEBUG_WILDCARD
383 + BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
385 + "Declare this menu entry as a wildcard entry. GLOB is a path containing"
386 + " one asterisk. All files matching this expression are looked up; the"
387 + " menu entry is duplicated for each match with asterisks in other"
388 + " commands replaced by the string matching the asterisk in the wildcard"
394 /* The table of builtin commands. Sorted in dictionary order. */
395 struct builtin *builtin_table[] =
397 @@ -4920,5 +4963,6 @@ struct builtin *builtin_table[] =