Lines 1243-1248
Link Here
|
1243 |
} |
1243 |
} |
1244 |
|
1244 |
|
1245 |
|
1245 |
|
|
|
1246 |
char *wildcard_prefix, *wildcard_suffix; |
1247 |
char wildcard_matches[1024], *end_wildcard_matches; |
1248 |
|
1249 |
static void wildcard_handler(char *name); |
1250 |
|
1251 |
/* Match one directory entry against the current wildcard. If the entry |
1252 |
matches, store it in WILDCARD_MATCHES. Silently ignore entries that |
1253 |
don't fit into WILDCARD_MATCHES anymore. */ |
1254 |
static void |
1255 |
wildcard_handler(char *name) |
1256 |
{ |
1257 |
char *n = name, *p = wildcard_prefix; |
1258 |
|
1259 |
while (*p && *p == *n) |
1260 |
{ |
1261 |
p++; |
1262 |
n++; |
1263 |
} |
1264 |
if (*p) |
1265 |
return; /* prefix mismatch */ |
1266 |
|
1267 |
p = name + grub_strlen (name) - grub_strlen (wildcard_suffix); |
1268 |
/* [n .. p) is the part matching the asterisk */ |
1269 |
|
1270 |
if (p < n || grub_strcmp (p, wildcard_suffix) != 0) |
1271 |
return; /* suffix mismatch */ |
1272 |
|
1273 |
/* store this match */ |
1274 |
if (p - n + 1 > sizeof (wildcard_matches) - |
1275 |
(end_wildcard_matches - wildcard_matches)) |
1276 |
return; /* out of space */ |
1277 |
while (n < p) |
1278 |
*end_wildcard_matches++ = *n++; |
1279 |
*end_wildcard_matches++ = 0; |
1280 |
} |
1281 |
|
1282 |
/* Wildcard expand the GLOB argument. Return NULL upon failure, or |
1283 |
a list of 0-terminated expansions, terminated by a zero-length string. */ |
1284 |
char * |
1285 |
wildcard (char *glob, int *len) |
1286 |
{ |
1287 |
char path[128], *p; |
1288 |
int ret; |
1289 |
|
1290 |
end_wildcard_matches = wildcard_matches; |
1291 |
if (grub_strlen (glob) + 1 > sizeof (path)) { |
1292 |
errnum = ERR_FILELENGTH; |
1293 |
return NULL; /* cannot handle pathnames this long */ |
1294 |
} |
1295 |
grub_strcpy (path, glob); |
1296 |
p = path; |
1297 |
while (*p) |
1298 |
p++; |
1299 |
wildcard_suffix = p; |
1300 |
while (p > path && *p != '/') |
1301 |
p--; |
1302 |
if (*p != '/') |
1303 |
{ |
1304 |
errnum = ERR_BAD_FILETYPE; |
1305 |
return NULL; /* Cannot wildcard device names */ |
1306 |
} |
1307 |
*(++p) = 0; |
1308 |
wildcard_prefix = glob + (p - path); |
1309 |
for (p = wildcard_prefix;; p++) |
1310 |
{ |
1311 |
if (*p == 0) |
1312 |
{ |
1313 |
/* We cannot do exact matches: this cannot be represented in the |
1314 |
result list. */ |
1315 |
return NULL; |
1316 |
} |
1317 |
else if (*p == '*') |
1318 |
{ |
1319 |
*p++ = 0; |
1320 |
wildcard_suffix = p; |
1321 |
break; |
1322 |
} |
1323 |
} |
1324 |
|
1325 |
ret = dir (path, wildcard_handler); |
1326 |
/* restore original argument */ |
1327 |
wildcard_prefix[grub_strlen (wildcard_prefix)] = '*'; |
1328 |
if (!ret) |
1329 |
return NULL; |
1330 |
*len = end_wildcard_matches - wildcard_matches; |
1331 |
return wildcard_matches; |
1332 |
} |
1333 |
|
1334 |
#define skip(str) ((str) + grub_strlen (str) + 1) |
1335 |
|
1336 |
static void inplace_sort (char *str, int len); |
1337 |
|
1338 |
static void |
1339 |
inplace_sort (char *str, int len) |
1340 |
{ |
1341 |
int m, n = 0; |
1342 |
char *s, *t; |
1343 |
|
1344 |
/* we use x as temporary storage */ |
1345 |
char *x = str + len; |
1346 |
|
1347 |
for (s = str; s < x; s = skip (s)) |
1348 |
n++; |
1349 |
|
1350 |
for (; n >= 2; n--) |
1351 |
{ |
1352 |
s = str; |
1353 |
t = skip (s); |
1354 |
|
1355 |
for (m = n; m >= 2; m--) |
1356 |
{ |
1357 |
if (grub_strcmp (s, t) > 0) |
1358 |
{ |
1359 |
int ls = skip (s) - s; |
1360 |
int lt = skip (t) - t; |
1361 |
|
1362 |
memcpy (x, s, ls); |
1363 |
grub_memmove (s + ls, s + lt, t - (s + ls)); |
1364 |
memcpy (s, t, lt); |
1365 |
t = t + lt - ls; |
1366 |
memcpy (t, x, ls); |
1367 |
} |
1368 |
s = t; |
1369 |
t = skip (t); |
1370 |
} |
1371 |
} |
1372 |
} |
1373 |
|
1374 |
#undef skip |
1375 |
|
1376 |
static int this_config_len (const char *config); |
1377 |
static int |
1378 |
this_config_len (const char *config) |
1379 |
{ |
1380 |
const char *c = config; |
1381 |
while (*c) |
1382 |
{ |
1383 |
while (*c) |
1384 |
c++; |
1385 |
c++; |
1386 |
} |
1387 |
c++; |
1388 |
return c - config; |
1389 |
} |
1390 |
|
1391 |
static const char * expand_asterisks (const char *str, int *len, |
1392 |
const char *subst); |
1393 |
|
1394 |
/* Expand all asterisks (*) in a menu entry or commands section with its |
1395 |
substitution. Use a backslash as escape character. */ |
1396 |
static const char * |
1397 |
expand_asterisks (const char *str, int *len, const char *subst) |
1398 |
{ |
1399 |
static char buffer[1024]; |
1400 |
char *b = buffer, escaped = 0; |
1401 |
const char *end = str + *len; |
1402 |
|
1403 |
while (str < end) |
1404 |
{ |
1405 |
if (*str == '*' && !escaped) |
1406 |
{ |
1407 |
if (b - buffer + grub_strlen (subst) > sizeof (buffer)) |
1408 |
{ |
1409 |
errnum = ERR_FILELENGTH; |
1410 |
return NULL; |
1411 |
} |
1412 |
grub_strcpy (b, subst); |
1413 |
b += grub_strlen (subst); |
1414 |
} |
1415 |
else if (*str == '\\' && !escaped) |
1416 |
escaped = 1; |
1417 |
else |
1418 |
{ |
1419 |
escaped = 0; |
1420 |
if (b - buffer + 1 > sizeof (buffer)) |
1421 |
{ |
1422 |
errnum = ERR_FILELENGTH; |
1423 |
return NULL; |
1424 |
} |
1425 |
*b++ = *str; |
1426 |
} |
1427 |
str++; |
1428 |
} |
1429 |
*len = b - buffer; |
1430 |
|
1431 |
return buffer; |
1432 |
} |
1433 |
|
1246 |
/* This is the starting function in C. */ |
1434 |
/* This is the starting function in C. */ |
1247 |
void |
1435 |
void |
1248 |
cmain (void) |
1436 |
cmain (void) |
Lines 1262-1267
Link Here
|
1262 |
menu_entries = (char *) MENU_BUF; |
1450 |
menu_entries = (char *) MENU_BUF; |
1263 |
init_config (); |
1451 |
init_config (); |
1264 |
} |
1452 |
} |
|
|
1453 |
|
1454 |
auto void expand_wildcard_entries (void); |
1455 |
void expand_wildcard_entries (void) |
1456 |
{ |
1457 |
char *config_entry = config_entries; |
1458 |
char *menu_entry = menu_entries; |
1459 |
|
1460 |
while (*menu_entry) |
1461 |
{ |
1462 |
char *command = config_entry; |
1463 |
|
1464 |
do |
1465 |
{ |
1466 |
char *c = command; |
1467 |
const char *w = "wildcard"; |
1468 |
|
1469 |
while (*w && *c == *w) |
1470 |
{ |
1471 |
c++; |
1472 |
w++; |
1473 |
} |
1474 |
if (*w == 0 && (*c == ' ' || *c == '\t' || *c == '=')) |
1475 |
{ |
1476 |
int len, wlen; |
1477 |
|
1478 |
/* This is a wildcard command. Advance to the argument. */ |
1479 |
while (*c == ' ' || *c == '\t' || *c == '=') |
1480 |
c++; |
1481 |
|
1482 |
/* Expand wildcard entry. */ |
1483 |
w = wildcard (c, &wlen); |
1484 |
if (w) |
1485 |
inplace_sort (w, wlen); |
1486 |
|
1487 |
/* Remove the wildcard command from the command section; |
1488 |
it has no meaning beyond the wildcard expansion just |
1489 |
performed. */ |
1490 |
len = grub_strlen (command) + 1; |
1491 |
grub_memmove (command, command + len, |
1492 |
config_len - (command - config_entries)); |
1493 |
config_len -= len; |
1494 |
|
1495 |
while (w && wlen) |
1496 |
{ |
1497 |
/* Insert expansion before the wildcard entry in the |
1498 |
list of entry names. */ |
1499 |
len = grub_strlen (menu_entry) + 1; |
1500 |
const char *x = expand_asterisks (menu_entry, &len, w); |
1501 |
grub_memmove (menu_entry + len, menu_entry, |
1502 |
menu_len - (menu_entry - menu_entries)); |
1503 |
memcpy (menu_entry, x, len); |
1504 |
menu_entry += len; |
1505 |
menu_len += len; |
1506 |
|
1507 |
/* Insert expansion before the wildcard command section |
1508 |
in the list of command sections. */ |
1509 |
len = this_config_len (config_entry); |
1510 |
x = expand_asterisks (config_entry, &len, w); |
1511 |
grub_memmove (config_entry + len, config_entry, |
1512 |
config_len - (config_entry - |
1513 |
config_entries)); |
1514 |
memcpy (config_entry, x, len); |
1515 |
config_entry += len; |
1516 |
config_len += len; |
1517 |
|
1518 |
num_entries++; |
1519 |
wlen -= grub_strlen (w) + 1; |
1520 |
w += grub_strlen (w) + 1; |
1521 |
} |
1522 |
|
1523 |
/* Remove the wildcard command section; it has just |
1524 |
been expanded. */ |
1525 |
len = grub_strlen (menu_entry) + 1; |
1526 |
grub_memmove (menu_entry, menu_entry + len, |
1527 |
menu_len - (menu_entry - menu_entries)); |
1528 |
menu_len -= len; |
1529 |
|
1530 |
len = this_config_len(config_entry); |
1531 |
grub_memmove (config_entry, config_entry + len, |
1532 |
config_len - (config_entry - config_entries)); |
1533 |
config_len -= len; |
1534 |
|
1535 |
num_entries--; |
1536 |
} |
1537 |
command += grub_strlen (command) + 1; |
1538 |
} |
1539 |
while (*command); |
1540 |
menu_entry += grub_strlen (menu_entry) + 1; |
1541 |
config_entry += this_config_len(config_entry); |
1542 |
} |
1543 |
} |
1265 |
|
1544 |
|
1266 |
/* Initialize the environment for restarting Stage 2. */ |
1545 |
/* Initialize the environment for restarting Stage 2. */ |
1267 |
grub_setjmp (restart_env); |
1546 |
grub_setjmp (restart_env); |
Lines 1413-1420
Link Here
|
1413 |
config_len = prev_config_len; |
1692 |
config_len = prev_config_len; |
1414 |
} |
1693 |
} |
1415 |
|
1694 |
|
|
|
1695 |
if (is_preset) |
1696 |
close_preset_menu (); |
1697 |
else |
1698 |
grub_close (); |
1699 |
|
1416 |
menu_entries[menu_len++] = 0; |
1700 |
menu_entries[menu_len++] = 0; |
1417 |
config_entries[config_len++] = 0; |
1701 |
config_entries[config_len++] = 0; |
|
|
1702 |
|
1703 |
expand_wildcard_entries(); |
1704 |
|
1418 |
grub_memmove (config_entries + config_len, menu_entries, |
1705 |
grub_memmove (config_entries + config_len, menu_entries, |
1419 |
menu_len); |
1706 |
menu_len); |
1420 |
menu_entries = config_entries + config_len; |
1707 |
menu_entries = config_entries + config_len; |
Lines 1455-1465
Link Here
|
1455 |
else |
1742 |
else |
1456 |
default_entry = 0; |
1743 |
default_entry = 0; |
1457 |
} |
1744 |
} |
1458 |
|
|
|
1459 |
if (is_preset) |
1460 |
close_preset_menu (); |
1461 |
else |
1462 |
grub_close (); |
1463 |
} |
1745 |
} |
1464 |
while (is_preset); |
1746 |
while (is_preset); |
1465 |
} |
1747 |
} |