#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <assert.h>
#include <ctype.h>
#include "libgrub_cmd.def"
#include "libgrub_impl.h"
typedef int (*barg_parsef_t)(const grub_line_t *, grub_barg_t *);
static const barg_parsef_t barg_parse[] = {
#define menu_cmd(cmd, num, flag, parsef) parsef,
#include "libgrub_cmd.def"
};
size_t
clean_path(char *path)
{
int i, c;
size_t k, n;
n = strlen(path) + 1;
for (i = 0; (c = path[i]) != 0 && !isspace(c); i++) {
if (c == '/' && (k = strspn(path + i, "/") - 1) != 0) {
n -= k;
bcopy(path + i + k, path + i, n - i);
}
}
return (n - 1);
}
static size_t
barg_cmdline(const grub_barg_t *barg, char *cmd, size_t size)
{
size_t n;
const grub_fsdesc_t *fsd;
if (!IS_BARG_VALID(barg) ||
(fsd = grub_get_rootfsd(&barg->gb_root)) == NULL)
return ((size_t)-1);
if (fsd->gfs_mountp[0] != 0) {
if ((n = snprintf(cmd, size, "%s%s", fsd->gfs_mountp,
barg->gb_kernel)) >= size)
return (n);
return (clean_path(cmd));
} else
return (snprintf(cmd, size, "%s %s", fsd->gfs_dev,
barg->gb_kernel));
}
int
grub_entry_construct_barg(grub_entry_t *ent)
{
int ret = 0;
grub_barg_t *barg;
grub_line_t *lp, *lend;
grub_menu_t *mp;
assert(ent);
barg = &ent->ge_barg;
mp = ent->ge_menu;
assert(barg);
assert(mp);
(void) memset(barg, 0, sizeof (*barg));
barg->gb_entry = ent;
(void) bcopy(&mp->gm_root, &barg->gb_root, sizeof (barg->gb_root));
lend = ent->ge_end->gl_next;
for (lp = ent->ge_start; lp != lend; lp = lp->gl_next) {
if (lp->gl_cmdtp >= GRBM_CMD_NUM)
ret = EG_INVALIDCMD;
else
ret = barg_parse[lp->gl_cmdtp](lp, barg);
if (ret != 0)
break;
}
barg->gb_errline = lp;
if (ret == 0) {
if (barg->gb_kernel[0] != 0 && barg->gb_module[0] != 0)
barg->gb_flags |= GRBM_VALID_FLAG;
}
return (ret);
}
const char *
grub_entry_get_fstyp(const grub_entry_t *ent)
{
if (IS_ENTRY_BARG_VALID(ent))
return (ent->ge_barg.gb_root.gr_fstyp);
else
return (NULL);
}
const char *
grub_entry_get_kernel(const grub_entry_t *ent)
{
if (IS_ENTRY_BARG_VALID(ent))
return (ent->ge_barg.gb_kernel);
else
return (NULL);
}
const char *
grub_entry_get_module(const grub_entry_t *ent)
{
if (IS_ENTRY_BARG_VALID(ent))
return (ent->ge_barg.gb_module);
else
return (NULL);
}
const char *
grub_entry_get_error_desc(const grub_entry_t *ent)
{
assert(ent != NULL);
return ("Not implemented");
}
const grub_fsdesc_t *
grub_entry_get_rootfs(const grub_entry_t *ent)
{
if (IS_ENTRY_BARG_VALID(ent))
return (grub_get_rootfsd(&ent->ge_barg.gb_root));
else
return (NULL);
}
size_t
grub_entry_get_cmdline(grub_entry_t *ent, char *cmdline, size_t size)
{
if (IS_ENTRY_VALID(ent) && (grub_entry_construct_barg(ent) == 0))
return (barg_cmdline(&ent->ge_barg, cmdline, size));
else
return ((size_t)-1);
}