Blob Blame History Raw
From aaea1dbe7731a481a1f62b312a5dd5ac77c10926 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Thu, 10 Sep 2015 18:27:31 -0400
Subject: [PATCH] Reformat to make this easier to work on.

Signed-off-by: Peter Jones <noone@example.com>
---
 grubby.c | 8385 +++++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 4406 insertions(+), 3979 deletions(-)

diff --git a/grubby.c b/grubby.c
index f1af54d..8295a53 100644
--- a/grubby.c
+++ b/grubby.c
@@ -48,7 +48,7 @@
 #define dbgPrintf(format, args...)
 #endif
 
-int debug = 0;	/* Currently just for template debugging */
+int debug = 0;			/* Currently just for template debugging */
 
 #define _(A) (A)
 
@@ -70,50 +70,50 @@ char *saved_command_line = NULL;
 
 /* comments get lumped in with indention */
 struct lineElement {
-    char * item;
-    char * indent;
+	char *item;
+	char *indent;
 };
 
-enum lineType_e { 
-    LT_WHITESPACE   = 1 << 0,
-    LT_TITLE        = 1 << 1,
-    LT_KERNEL       = 1 << 2,
-    LT_INITRD       = 1 << 3,
-    LT_HYPER        = 1 << 4,
-    LT_DEFAULT      = 1 << 5,
-    LT_MBMODULE     = 1 << 6,
-    LT_ROOT         = 1 << 7,
-    LT_FALLBACK     = 1 << 8,
-    LT_KERNELARGS   = 1 << 9,
-    LT_BOOT         = 1 << 10,
-    LT_BOOTROOT     = 1 << 11,
-    LT_LBA          = 1 << 12,
-    LT_OTHER        = 1 << 13,
-    LT_GENERIC      = 1 << 14,
-    LT_ECHO	    = 1 << 16,
-    LT_MENUENTRY    = 1 << 17,
-    LT_ENTRY_END    = 1 << 18,
-    LT_SET_VARIABLE = 1 << 19,
-    LT_KERNEL_EFI   = 1 << 20,
-    LT_INITRD_EFI   = 1 << 21,
-    LT_KERNEL_16    = 1 << 22,
-    LT_INITRD_16    = 1 << 23,
-    LT_UNKNOWN      = 1 << 24,
+enum lineType_e {
+	LT_WHITESPACE = 1 << 0,
+	LT_TITLE = 1 << 1,
+	LT_KERNEL = 1 << 2,
+	LT_INITRD = 1 << 3,
+	LT_HYPER = 1 << 4,
+	LT_DEFAULT = 1 << 5,
+	LT_MBMODULE = 1 << 6,
+	LT_ROOT = 1 << 7,
+	LT_FALLBACK = 1 << 8,
+	LT_KERNELARGS = 1 << 9,
+	LT_BOOT = 1 << 10,
+	LT_BOOTROOT = 1 << 11,
+	LT_LBA = 1 << 12,
+	LT_OTHER = 1 << 13,
+	LT_GENERIC = 1 << 14,
+	LT_ECHO = 1 << 16,
+	LT_MENUENTRY = 1 << 17,
+	LT_ENTRY_END = 1 << 18,
+	LT_SET_VARIABLE = 1 << 19,
+	LT_KERNEL_EFI = 1 << 20,
+	LT_INITRD_EFI = 1 << 21,
+	LT_KERNEL_16 = 1 << 22,
+	LT_INITRD_16 = 1 << 23,
+	LT_UNKNOWN = 1 << 24,
 };
 
 struct singleLine {
-    char * indent;
-    int numElements;
-    struct lineElement * elements;
-    struct singleLine * next;
-    enum lineType_e type;
+	char *indent;
+	int numElements;
+	struct lineElement *elements;
+	struct singleLine *next;
+	enum lineType_e type;
 };
 
 struct singleEntry {
-    struct singleLine * lines;
-    int skip;
-    int multiboot;
-    struct singleEntry * next;
+	struct singleLine *lines;
+	int skip;
+	int multiboot;
+	struct singleEntry *next;
 };
 
 #define GRUBBY_BADIMAGE_OKAY	(1 << 0)
@@ -133,1718 +133,1837 @@ struct singleEntry {
 #define DEFAULT_SAVED_GRUB2 -3
 
 struct keywordTypes {
-    char * key;
-    enum lineType_e type;
-    char nextChar;
-    char separatorChar;
+	char *key;
+	enum lineType_e type;
+	char nextChar;
+	char separatorChar;
 };
 
 struct configFileInfo;
 
-typedef const char *(*findConfigFunc)(struct configFileInfo *);
-typedef const int (*writeLineFunc)(struct configFileInfo *,
-				struct singleLine *line);
-typedef char *(*getEnvFunc)(struct configFileInfo *, char *name);
-typedef int (*setEnvFunc)(struct configFileInfo *, char *name, char *value);
+typedef const char *(*findConfigFunc) (struct configFileInfo *);
+typedef const int (*writeLineFunc) (struct configFileInfo *,
+				    struct singleLine * line);
+typedef char *(*getEnvFunc) (struct configFileInfo *, char *name);
+typedef int (*setEnvFunc) (struct configFileInfo *, char *name, char *value);
 
 struct configFileInfo {
-    char * defaultConfig;
-    findConfigFunc findConfig;
-    writeLineFunc writeLine;
-    getEnvFunc getEnv;
-    setEnvFunc setEnv;
-    struct keywordTypes * keywords;
-    int caseInsensitive;
-    int defaultIsIndex;
-    int defaultIsVariable;
-    int defaultSupportSaved;
-    int defaultIsSaved;
-    int defaultIsUnquoted;
-    enum lineType_e entryStart;
-    enum lineType_e entryEnd;
-    int needsBootPrefix;
-    int argsInQuotes;
-    int maxTitleLength;
-    int titleBracketed;
-    int titlePosition;
-    int mbHyperFirst;
-    int mbInitRdIsModule;
-    int mbConcatArgs;
-    int mbAllowExtraInitRds;
-    char *envFile;
+	char *defaultConfig;
+	findConfigFunc findConfig;
+	writeLineFunc writeLine;
+	getEnvFunc getEnv;
+	setEnvFunc setEnv;
+	struct keywordTypes *keywords;
+	int caseInsensitive;
+	int defaultIsIndex;
+	int defaultIsVariable;
+	int defaultSupportSaved;
+	int defaultIsSaved;
+	int defaultIsUnquoted;
+	enum lineType_e entryStart;
+	enum lineType_e entryEnd;
+	int needsBootPrefix;
+	int argsInQuotes;
+	int maxTitleLength;
+	int titleBracketed;
+	int titlePosition;
+	int mbHyperFirst;
+	int mbInitRdIsModule;
+	int mbConcatArgs;
+	int mbAllowExtraInitRds;
+	char *envFile;
 };
 
 struct keywordTypes grubKeywords[] = {
-    { "title",	    LT_TITLE,	    ' ' },
-    { "root",	    LT_BOOTROOT,    ' ' },
-    { "default",    LT_DEFAULT,	    ' ' },
-    { "fallback",   LT_FALLBACK,    ' ' },
-    { "kernel",	    LT_KERNEL,	    ' ' },
-    { "initrd",	    LT_INITRD,	    ' ',	' ' },
-    { "module",     LT_MBMODULE,    ' ' },
-    { "kernel",     LT_HYPER,       ' ' },
-    { NULL,	    0, 0 },
+	{"title", LT_TITLE, ' '},
+	{"root", LT_BOOTROOT, ' '},
+	{"default", LT_DEFAULT, ' '},
+	{"fallback", LT_FALLBACK, ' '},
+	{"kernel", LT_KERNEL, ' '},
+	{"initrd", LT_INITRD, ' ', ' '},
+	{"module", LT_MBMODULE, ' '},
+	{"kernel", LT_HYPER, ' '},
+	{NULL, 0, 0},
 };
 
-const char *grubFindConfig(struct configFileInfo *cfi) {
-    static const char *configFiles[] = {
-	"/boot/grub/menu.lst",
-	"/etc/grub.conf",
-	NULL
-    };
-    static int i = -1;
-
-    if (i == -1) {
-	for (i = 0; configFiles[i] != NULL; i++) {
-	    dbgPrintf("Checking \"%s\": ", configFiles[i]);
-	    if (!access(configFiles[i], R_OK)) {
-		dbgPrintf("found\n");
-		return configFiles[i];
-	    }
-	    dbgPrintf("not found\n");
+const char *grubFindConfig(struct configFileInfo *cfi)
+{
+	static const char *configFiles[] = {
+		"/boot/grub/menu.lst",
+		"/etc/grub.conf",
+		NULL
+	};
+	static int i = -1;
+
+	if (i == -1) {
+		for (i = 0; configFiles[i] != NULL; i++) {
+			dbgPrintf("Checking \"%s\": ", configFiles[i]);
+			if (!access(configFiles[i], R_OK)) {
+				dbgPrintf("found\n");
+				return configFiles[i];
+			}
+			dbgPrintf("not found\n");
+		}
 	}
-    }
-    return configFiles[i];
+	return configFiles[i];
 }
 
 struct configFileInfo grubConfigType = {
-    .findConfig = grubFindConfig,
-    .keywords = grubKeywords,
-    .defaultIsIndex = 1,
-    .defaultSupportSaved = 1,
-    .entryStart = LT_TITLE,
-    .needsBootPrefix = 1,
-    .mbHyperFirst = 1,
-    .mbInitRdIsModule = 1,
-    .mbAllowExtraInitRds = 1,
-    .titlePosition = 1,
+	.findConfig = grubFindConfig,
+	.keywords = grubKeywords,
+	.defaultIsIndex = 1,
+	.defaultSupportSaved = 1,
+	.entryStart = LT_TITLE,
+	.needsBootPrefix = 1,
+	.mbHyperFirst = 1,
+	.mbInitRdIsModule = 1,
+	.mbAllowExtraInitRds = 1,
+	.titlePosition = 1,
 };
 
 struct keywordTypes grub2Keywords[] = {
-    { "menuentry",  LT_MENUENTRY,   ' ' },
-    { "}",          LT_ENTRY_END,   ' ' },
-    { "echo",       LT_ECHO,        ' ' },
-    { "set",        LT_SET_VARIABLE,' ', '=' },
-    { "root",       LT_BOOTROOT,    ' ' },
-    { "default",    LT_DEFAULT,     ' ' },
-    { "fallback",   LT_FALLBACK,    ' ' },
-    { "linux",      LT_KERNEL,      ' ' },
-    { "linuxefi",   LT_KERNEL_EFI,  ' ' },
-    { "linux16",    LT_KERNEL_16,   ' ' },
-    { "initrd",     LT_INITRD,      ' ', ' ' },
-    { "initrdefi",  LT_INITRD_EFI,  ' ', ' ' },
-    { "initrd16",   LT_INITRD_16,   ' ', ' ' },
-    { "module",     LT_MBMODULE,    ' ' },
-    { "kernel",     LT_HYPER,       ' ' },
-    { NULL, 0, 0 },
+	{"menuentry", LT_MENUENTRY, ' '},
+	{"}", LT_ENTRY_END, ' '},
+	{"echo", LT_ECHO, ' '},
+	{"set", LT_SET_VARIABLE, ' ', '='},
+	{"root", LT_BOOTROOT, ' '},
+	{"default", LT_DEFAULT, ' '},
+	{"fallback", LT_FALLBACK, ' '},
+	{"linux", LT_KERNEL, ' '},
+	{"linuxefi", LT_KERNEL_EFI, ' '},
+	{"linux16", LT_KERNEL_16, ' '},
+	{"initrd", LT_INITRD, ' ', ' '},
+	{"initrdefi", LT_INITRD_EFI, ' ', ' '},
+	{"initrd16", LT_INITRD_16, ' ', ' '},
+	{"module", LT_MBMODULE, ' '},
+	{"kernel", LT_HYPER, ' '},
+	{NULL, 0, 0},
 };
 
-const char *grub2FindConfig(struct configFileInfo *cfi) {
-    static const char *configFiles[] = {
-	"/etc/grub2-efi.cfg",
-	"/etc/grub2.cfg",
-	NULL
-    };
-    static int i = -1;
-    static const char *grub_cfg = "/boot/grub/grub.cfg";
-    int rc = -1;
-
-    if (i == -1) {
-	for (i = 0; configFiles[i] != NULL; i++) {
-	    dbgPrintf("Checking \"%s\": ", configFiles[i]);
-	    if ((rc = access(configFiles[i], R_OK))) {
-		if (errno == EACCES) {
-		    printf("Unable to access bootloader configuration file "
-		    	   "\"%s\": %m\n", configFiles[i]);
-		    exit(1);
+const char *grub2FindConfig(struct configFileInfo *cfi)
+{
+	static const char *configFiles[] = {
+		"/etc/grub2-efi.cfg",
+		"/etc/grub2.cfg",
+		NULL
+	};
+	static int i = -1;
+	static const char *grub_cfg = "/boot/grub/grub.cfg";
+	int rc = -1;
+
+	if (i == -1) {
+		for (i = 0; configFiles[i] != NULL; i++) {
+			dbgPrintf("Checking \"%s\": ", configFiles[i]);
+			if ((rc = access(configFiles[i], R_OK))) {
+				if (errno == EACCES) {
+					printf
+					    ("Unable to access bootloader configuration file "
+					     "\"%s\": %m\n", configFiles[i]);
+					exit(1);
+				}
+				continue;
+			} else {
+				dbgPrintf("found\n");
+				return configFiles[i];
+			}
 		}
-		continue;
-	    } else {
-		dbgPrintf("found\n");
-		return configFiles[i];
-	    }
 	}
-    }
 
-    /* Ubuntu renames grub2 to grub, so check for the grub.d directory
-     * that isn't in grub1, and if it exists, return the config file path
-     * that they use. */
-    if (configFiles[i] == NULL && !access("/etc/grub.d/", R_OK)) {
-	dbgPrintf("found\n");
-	return grub_cfg;
-    }
+	/* Ubuntu renames grub2 to grub, so check for the grub.d directory
+	 * that isn't in grub1, and if it exists, return the config file path
+	 * that they use. */
+	if (configFiles[i] == NULL && !access("/etc/grub.d/", R_OK)) {
+		dbgPrintf("found\n");
+		return grub_cfg;
+	}
 
-    dbgPrintf("not found\n");
-    return configFiles[i];
+	dbgPrintf("not found\n");
+	return configFiles[i];
 }
 
 /* kind of hacky.  It'll give the first 1024 bytes, ish. */
 static char *grub2GetEnv(struct configFileInfo *info, char *name)
 {
-    static char buf[1025];
-    char *s = NULL;
-    char *ret = NULL;
-    char *envFile = info->envFile ? info->envFile : "/boot/grub2/grubenv";
-    int rc = asprintf(&s, "grub2-editenv %s list | grep '^%s='", envFile, name);
-
-    if (rc < 0)
-	return NULL;
-
-    FILE *f = popen(s, "r");
-    if (!f)
-	goto out;
-
-    memset(buf, '\0', sizeof (buf));
-    ret = fgets(buf, 1024, f);
-    pclose(f);
-
-    if (ret) {
-	ret += strlen(name) + 1;
-	ret[strlen(ret) - 1] = '\0';
-    }
-    dbgPrintf("grub2GetEnv(%s): %s\n", name, ret);
+	static char buf[1025];
+	char *s = NULL;
+	char *ret = NULL;
+	char *envFile = info->envFile ? info->envFile : "/boot/grub2/grubenv";
+	int rc =
+	    asprintf(&s, "grub2-editenv %s list | grep '^%s='", envFile, name);
+
+	if (rc < 0)
+		return NULL;
+
+	FILE *f = popen(s, "r");
+	if (!f)
+		goto out;
+
+	memset(buf, '\0', sizeof(buf));
+	ret = fgets(buf, 1024, f);
+	pclose(f);
+
+	if (ret) {
+		ret += strlen(name) + 1;
+		ret[strlen(ret) - 1] = '\0';
+	}
+	dbgPrintf("grub2GetEnv(%s): %s\n", name, ret);
 out:
-    free(s);
-    return ret;
+	free(s);
+	return ret;
 }
 
 static int sPopCount(const char *s, const char *c)
 {
-    int ret = 0;
-    if (!s)
-	return -1;
-    for (int i = 0; s[i] != '\0'; i++)
-	for (int j = 0; c[j] != '\0'; j++)
-	    if (s[i] == c[j])
-		ret++;
-    return ret;
+	int ret = 0;
+	if (!s)
+		return -1;
+	for (int i = 0; s[i] != '\0'; i++)
+		for (int j = 0; c[j] != '\0'; j++)
+			if (s[i] == c[j])
+				ret++;
+	return ret;
 }
 
 static char *shellEscape(const char *s)
 {
-    int l = strlen(s) + sPopCount(s, "'") * 2;
-
-    char *ret = calloc(l+1, sizeof (*ret));
-    if (!ret)
-	return NULL;
-    for (int i = 0, j = 0; s[i] != '\0'; i++, j++) {
-	if (s[i] == '\'')
-	    ret[j++] = '\\';
-	ret[j] = s[i];
-    }
-    return ret;
+	int l = strlen(s) + sPopCount(s, "'") * 2;
+
+	char *ret = calloc(l + 1, sizeof(*ret));
+	if (!ret)
+		return NULL;
+	for (int i = 0, j = 0; s[i] != '\0'; i++, j++) {
+		if (s[i] == '\'')
+			ret[j++] = '\\';
+		ret[j] = s[i];
+	}
+	return ret;
 }
 
 static void unquote(char *s)
 {
-    int l = strlen(s);
+	int l = strlen(s);
 
-    if ((s[l-1] == '\'' && s[0] == '\'') || (s[l-1] == '"' && s[0] == '"')) {
-	memmove(s, s+1, l-2);
-	s[l-2] = '\0';
-    }
+	if ((s[l - 1] == '\'' && s[0] == '\'')
+	    || (s[l - 1] == '"' && s[0] == '"')) {
+		memmove(s, s + 1, l - 2);
+		s[l - 2] = '\0';
+	}
 }
 
 static int grub2SetEnv(struct configFileInfo *info, char *name, char *value)
 {
-    char *s = NULL;
-    int rc = 0;
-    char *envFile = info->envFile ? info->envFile : "/boot/grub2/grubenv";
-
-    unquote(value);
-    value = shellEscape(value);
-    if (!value)
-	    return -1;
-
-    rc = asprintf(&s, "grub2-editenv %s set '%s=%s'", envFile, name, value);
-    free(value);
-    if (rc <0)
-	return -1;
-
-    dbgPrintf("grub2SetEnv(%s): %s\n", name, s);
-    rc = system(s);
-    free(s);
-    return rc;
+	char *s = NULL;
+	int rc = 0;
+	char *envFile = info->envFile ? info->envFile : "/boot/grub2/grubenv";
+
+	unquote(value);
+	value = shellEscape(value);
+	if (!value)
+		return -1;
+
+	rc = asprintf(&s, "grub2-editenv %s set '%s=%s'", envFile, name, value);
+	free(value);
+	if (rc < 0)
+		return -1;
+
+	dbgPrintf("grub2SetEnv(%s): %s\n", name, s);
+	rc = system(s);
+	free(s);
+	return rc;
 }
 
 /* this is a gigantic hack to avoid clobbering grub2 variables... */
 static int is_special_grub2_variable(const char *name)
 {
-    if (!strcmp(name,"\"${next_entry}\""))
-	return 1;
-    if (!strcmp(name,"\"${prev_saved_entry}\""))
-	return 1;
-    return 0;
+	if (!strcmp(name, "\"${next_entry}\""))
+		return 1;
+	if (!strcmp(name, "\"${prev_saved_entry}\""))
+		return 1;
+	return 0;
 }
 
-int sizeOfSingleLine(struct singleLine * line) {
-  int count = 0;
+int sizeOfSingleLine(struct singleLine *line)
+{
+	int count = 0;
 
-  for (int i = 0; i < line->numElements; i++) {
-    int indentSize = 0;
+	for (int i = 0; i < line->numElements; i++) {
+		int indentSize = 0;
 
-    count = count + strlen(line->elements[i].item);
+		count = count + strlen(line->elements[i].item);
 
-    indentSize = strlen(line->elements[i].indent);
-    if (indentSize > 0)
-      count = count + indentSize;
-    else
-      /* be extra safe and add room for whitespaces */
-      count = count + 1;
-  }
+		indentSize = strlen(line->elements[i].indent);
+		if (indentSize > 0)
+			count = count + indentSize;
+		else
+			/* be extra safe and add room for whitespaces */
+			count = count + 1;
+	}
 
-  /* room for trailing terminator */
-  count = count + 1;
+	/* room for trailing terminator */
+	count = count + 1;
 
-  return count;
+	return count;
 }
 
 static int isquote(char q)
 {
-    if (q == '\'' || q == '\"')
-	return 1;
-    return 0;
+	if (q == '\'' || q == '\"')
+		return 1;
+	return 0;
 }
 
-static int iskernel(enum lineType_e type) {
-    return (type == LT_KERNEL || type == LT_KERNEL_EFI || type == LT_KERNEL_16);
+static int iskernel(enum lineType_e type)
+{
+	return (type == LT_KERNEL || type == LT_KERNEL_EFI
+		|| type == LT_KERNEL_16);
 }
 
-static int isinitrd(enum lineType_e type) {
-    return (type == LT_INITRD || type == LT_INITRD_EFI || type == LT_INITRD_16);
+static int isinitrd(enum lineType_e type)
+{
+	return (type == LT_INITRD || type == LT_INITRD_EFI
+		|| type == LT_INITRD_16);
 }
 
-char *grub2ExtractTitle(struct singleLine * line) {
-    char * current;
-    char * current_indent;
-    int current_len;
-    int current_indent_len;
-    int i;
+char *grub2ExtractTitle(struct singleLine *line)
+{
+	char *current;
+	char *current_indent;
+	int current_len;
+	int current_indent_len;
+	int i;
 
-    /* bail out if line does not start with menuentry */
-    if (strcmp(line->elements[0].item, "menuentry"))
-	return NULL;
+	/* bail out if line does not start with menuentry */
+	if (strcmp(line->elements[0].item, "menuentry"))
+		return NULL;
 
-    i = 1;
-    current = line->elements[i].item;
-    current_len = strlen(current);
-
-    /* if second word is quoted, strip the quotes and return single word */
-    if (isquote(*current) && isquote(current[current_len - 1])) {
-	char *tmp;
-
-	tmp = strdup(current+1);
-	if (!tmp)
-	    return NULL;
-	tmp[strlen(tmp)-1] = '\0';
-	return tmp;
-    }
-
-    /* if no quotes, return second word verbatim */
-    if (!isquote(*current))
-	return current;
-
-    /* second element start with a quote, so we have to find the element
-     * whose last character is also quote (assuming it's the closing one) */
-    int resultMaxSize;
-    char * result;
-    /* need to ensure that ' does not match " as we search */
-    char quote_char = *current;
-
-    resultMaxSize = sizeOfSingleLine(line);
-    result = malloc(resultMaxSize);
-    snprintf(result, resultMaxSize, "%s", ++current);
-
-    i++;
-    for (; i < line->numElements; ++i) {
+	i = 1;
 	current = line->elements[i].item;
 	current_len = strlen(current);
-	current_indent = line->elements[i].indent;
-	current_indent_len = strlen(current_indent);
 
-	strncat(result, current_indent, current_indent_len);
-	if (current[current_len-1] != quote_char) {
-	    strncat(result, current, current_len);
-	} else {
-	    strncat(result, current, current_len - 1);
-	    break;
+	/* if second word is quoted, strip the quotes and return single word */
+	if (isquote(*current) && isquote(current[current_len - 1])) {
+		char *tmp;
+
+		tmp = strdup(current + 1);
+		if (!tmp)
+			return NULL;
+		tmp[strlen(tmp) - 1] = '\0';
+		return tmp;
+	}
+
+	/* if no quotes, return second word verbatim */
+	if (!isquote(*current))
+		return current;
+
+	/* second element start with a quote, so we have to find the element
+	 * whose last character is also quote (assuming it's the closing one) */
+	int resultMaxSize;
+	char *result;
+	/* need to ensure that ' does not match " as we search */
+	char quote_char = *current;
+
+	resultMaxSize = sizeOfSingleLine(line);
+	result = malloc(resultMaxSize);
+	snprintf(result, resultMaxSize, "%s", ++current);
+
+	i++;
+	for (; i < line->numElements; ++i) {
+		current = line->elements[i].item;
+		current_len = strlen(current);
+		current_indent = line->elements[i].indent;
+		current_indent_len = strlen(current_indent);
+
+		strncat(result, current_indent, current_indent_len);
+		if (current[current_len - 1] != quote_char) {
+			strncat(result, current, current_len);
+		} else {
+			strncat(result, current, current_len - 1);
+			break;
+		}
 	}
-    }
-    return result;
+	return result;
 }
 
 struct configFileInfo grub2ConfigType = {
-    .findConfig = grub2FindConfig,
-    .getEnv = grub2GetEnv,
-    .setEnv = grub2SetEnv,
-    .keywords = grub2Keywords,
-    .defaultIsIndex = 1,
-    .defaultSupportSaved = 1,
-    .defaultIsVariable = 1,
-    .entryStart = LT_MENUENTRY,
-    .entryEnd = LT_ENTRY_END,
-    .titlePosition = 1,
-    .needsBootPrefix = 1,
-    .mbHyperFirst = 1,
-    .mbInitRdIsModule = 1,
-    .mbAllowExtraInitRds = 1,
+	.findConfig = grub2FindConfig,
+	.getEnv = grub2GetEnv,
+	.setEnv = grub2SetEnv,
+	.keywords = grub2Keywords,
+	.defaultIsIndex = 1,
+	.defaultSupportSaved = 1,
+	.defaultIsVariable = 1,
+	.entryStart = LT_MENUENTRY,
+	.entryEnd = LT_ENTRY_END,
+	.titlePosition = 1,
+	.needsBootPrefix = 1,
+	.mbHyperFirst = 1,
+	.mbInitRdIsModule = 1,
+	.mbAllowExtraInitRds = 1,
 };
 
 struct keywordTypes yabootKeywords[] = {
-    { "label",	    LT_TITLE,	    '=' },
-    { "root",	    LT_ROOT,	    '=' },
-    { "default",    LT_DEFAULT,	    '=' },
-    { "image",	    LT_KERNEL,	    '=' },
-    { "bsd",	    LT_GENERIC,	    '=' },
-    { "macos",	    LT_GENERIC,	    '=' },
-    { "macosx",	    LT_GENERIC,	    '=' },
-    { "magicboot",  LT_GENERIC,	    '=' },
-    { "darwin",	    LT_GENERIC,	    '=' },
-    { "timeout",    LT_GENERIC,	    '=' },
-    { "install",    LT_GENERIC,	    '=' },
-    { "fstype",	    LT_GENERIC,	    '=' },
-    { "hfstype",    LT_GENERIC,	    '=' },
-    { "delay",	    LT_GENERIC,	    '=' },
-    { "defaultos",  LT_GENERIC,     '=' },
-    { "init-message", LT_GENERIC,   '=' },
-    { "enablecdboot", LT_GENERIC,   ' ' },
-    { "enableofboot", LT_GENERIC,   ' ' },
-    { "enablenetboot", LT_GENERIC,  ' ' },
-    { "nonvram",    LT_GENERIC,	    ' ' },
-    { "hide",	    LT_GENERIC,	    ' ' },
-    { "protect",    LT_GENERIC,	    ' ' },
-    { "nobless",    LT_GENERIC,	    ' ' },
-    { "nonvram",    LT_GENERIC,	    ' ' },
-    { "brokenosx",  LT_GENERIC,	    ' ' },
-    { "usemount",   LT_GENERIC,	    ' ' },
-    { "mntpoint",   LT_GENERIC,	    '=' },
-    { "partition",  LT_GENERIC,	    '=' },
-    { "device",	    LT_GENERIC,	    '=' },
-    { "fstype",	    LT_GENERIC,	    '=' },
-    { "initrd",	    LT_INITRD,	    '=',	';' },
-    { "append",	    LT_KERNELARGS,  '=' },
-    { "boot",	    LT_BOOT,	    '=' },
-    { "lba",	    LT_LBA,	    ' ' },
-    { NULL,	    0, 0 },
+	{"label", LT_TITLE, '='},
+	{"root", LT_ROOT, '='},
+	{"default", LT_DEFAULT, '='},
+	{"image", LT_KERNEL, '='},
+	{"bsd", LT_GENERIC, '='},
+	{"macos", LT_GENERIC, '='},
+	{"macosx", LT_GENERIC, '='},
+	{"magicboot", LT_GENERIC, '='},
+	{"darwin", LT_GENERIC, '='},
+	{"timeout", LT_GENERIC, '='},
+	{"install", LT_GENERIC, '='},
+	{"fstype", LT_GENERIC, '='},
+	{"hfstype", LT_GENERIC, '='},
+	{"delay", LT_GENERIC, '='},
+	{"defaultos", LT_GENERIC, '='},
+	{"init-message", LT_GENERIC, '='},
+	{"enablecdboot", LT_GENERIC, ' '},
+	{"enableofboot", LT_GENERIC, ' '},
+	{"enablenetboot", LT_GENERIC, ' '},
+	{"nonvram", LT_GENERIC, ' '},
+	{"hide", LT_GENERIC, ' '},
+	{"protect", LT_GENERIC, ' '},
+	{"nobless", LT_GENERIC, ' '},
+	{"nonvram", LT_GENERIC, ' '},
+	{"brokenosx", LT_GENERIC, ' '},
+	{"usemount", LT_GENERIC, ' '},
+	{"mntpoint", LT_GENERIC, '='},
+	{"partition", LT_GENERIC, '='},
+	{"device", LT_GENERIC, '='},
+	{"fstype", LT_GENERIC, '='},
+	{"initrd", LT_INITRD, '=', ';'},
+	{"append", LT_KERNELARGS, '='},
+	{"boot", LT_BOOT, '='},
+	{"lba", LT_LBA, ' '},
+	{NULL, 0, 0},
 };
 
 struct keywordTypes liloKeywords[] = {
-    { "label",	    LT_TITLE,	    '=' },
-    { "root",	    LT_ROOT,	    '=' },
-    { "default",    LT_DEFAULT,	    '=' },
-    { "image",	    LT_KERNEL,	    '=' },
-    { "other",	    LT_OTHER,	    '=' },
-    { "initrd",	    LT_INITRD,	    '=' },
-    { "append",	    LT_KERNELARGS,  '=' },
-    { "boot",	    LT_BOOT,	    '=' },
-    { "lba",	    LT_LBA,	    ' ' },
-    { NULL,	    0, 0 },
+	{"label", LT_TITLE, '='},
+	{"root", LT_ROOT, '='},
+	{"default", LT_DEFAULT, '='},
+	{"image", LT_KERNEL, '='},
+	{"other", LT_OTHER, '='},
+	{"initrd", LT_INITRD, '='},
+	{"append", LT_KERNELARGS, '='},
+	{"boot", LT_BOOT, '='},
+	{"lba", LT_LBA, ' '},
+	{NULL, 0, 0},
 };
 
 struct keywordTypes eliloKeywords[] = {
-    { "label",	    LT_TITLE,	    '=' },
-    { "root",	    LT_ROOT,	    '=' },
-    { "default",    LT_DEFAULT,	    '=' },
-    { "image",	    LT_KERNEL,	    '=' },
-    { "initrd",	    LT_INITRD,	    '=' },
-    { "append",	    LT_KERNELARGS,  '=' },
-    { "vmm",	    LT_HYPER,       '=' },
-    { NULL,	    0, 0 },
+	{"label", LT_TITLE, '='},
+	{"root", LT_ROOT, '='},
+	{"default", LT_DEFAULT, '='},
+	{"image", LT_KERNEL, '='},
+	{"initrd", LT_INITRD, '='},
+	{"append", LT_KERNELARGS, '='},
+	{"vmm", LT_HYPER, '='},
+	{NULL, 0, 0},
 };
 
 struct keywordTypes siloKeywords[] = {
-    { "label",	    LT_TITLE,	    '=' },
-    { "root",	    LT_ROOT,	    '=' },
-    { "default",    LT_DEFAULT,	    '=' },
-    { "image",	    LT_KERNEL,	    '=' },
-    { "other",	    LT_OTHER,	    '=' },
-    { "initrd",	    LT_INITRD,	    '=' },
-    { "append",	    LT_KERNELARGS,  '=' },
-    { "boot",	    LT_BOOT,	    '=' },
-    { NULL,	    0, 0 },
+	{"label", LT_TITLE, '='},
+	{"root", LT_ROOT, '='},
+	{"default", LT_DEFAULT, '='},
+	{"image", LT_KERNEL, '='},
+	{"other", LT_OTHER, '='},
+	{"initrd", LT_INITRD, '='},
+	{"append", LT_KERNELARGS, '='},
+	{"boot", LT_BOOT, '='},
+	{NULL, 0, 0},
 };
 
 struct keywordTypes ziplKeywords[] = {
-    { "target",     LT_BOOTROOT,    '=' },
-    { "image",      LT_KERNEL,      '=' },
-    { "ramdisk",    LT_INITRD,      '=' },
-    { "parameters", LT_KERNELARGS,  '=' },
-    { "default",    LT_DEFAULT,     '=' },
-    { NULL,         0, 0 },
+	{"target", LT_BOOTROOT, '='},
+	{"image", LT_KERNEL, '='},
+	{"ramdisk", LT_INITRD, '='},
+	{"parameters", LT_KERNELARGS, '='},
+	{"default", LT_DEFAULT, '='},
+	{NULL, 0, 0},
 };
 
 struct keywordTypes extlinuxKeywords[] = {
-    { "label",	    LT_TITLE,	    ' ' },
-    { "root",	    LT_ROOT,	    ' ' },
-    { "default",    LT_DEFAULT,	    ' ' },
-    { "kernel",	    LT_KERNEL,	    ' ' },
-    { "initrd",	    LT_INITRD,      ' ',	',' },
-    { "append",	    LT_KERNELARGS,  ' ' },
-    { "prompt",     LT_UNKNOWN,     ' ' },
-    { NULL,	    0, 0 },
+	{"label", LT_TITLE, ' '},
+	{"root", LT_ROOT, ' '},
+	{"default", LT_DEFAULT, ' '},
+	{"kernel", LT_KERNEL, ' '},
+	{"initrd", LT_INITRD, ' ', ','},
+	{"append", LT_KERNELARGS, ' '},
+	{"prompt", LT_UNKNOWN, ' '},
+	{NULL, 0, 0},
 };
+
 int useextlinuxmenu;
 struct configFileInfo eliloConfigType = {
-    .defaultConfig = "/boot/efi/EFI/redhat/elilo.conf",
-    .keywords = eliloKeywords,
-    .entryStart = LT_KERNEL,
-    .needsBootPrefix = 1,
-    .argsInQuotes = 1,
-    .mbConcatArgs = 1,
-    .titlePosition = 1,
+	.defaultConfig = "/boot/efi/EFI/redhat/elilo.conf",
+	.keywords = eliloKeywords,
+	.entryStart = LT_KERNEL,
+	.needsBootPrefix = 1,
+	.argsInQuotes = 1,
+	.mbConcatArgs = 1,
+	.titlePosition = 1,
 };
 
 struct configFileInfo liloConfigType = {
-    .defaultConfig = "/etc/lilo.conf",
-    .keywords = liloKeywords,
-    .entryStart = LT_KERNEL,
-    .argsInQuotes = 1,
-    .maxTitleLength = 15,
-    .titlePosition = 1,
+	.defaultConfig = "/etc/lilo.conf",
+	.keywords = liloKeywords,
+	.entryStart = LT_KERNEL,
+	.argsInQuotes = 1,
+	.maxTitleLength = 15,
+	.titlePosition = 1,
 };
 
 struct configFileInfo yabootConfigType = {
-    .defaultConfig = "/etc/yaboot.conf",
-    .keywords = yabootKeywords,
-    .entryStart = LT_KERNEL,
-    .needsBootPrefix = 1,
-    .argsInQuotes = 1,
-    .maxTitleLength = 15,
-    .mbAllowExtraInitRds = 1,
-    .titlePosition = 1,
+	.defaultConfig = "/etc/yaboot.conf",
+	.keywords = yabootKeywords,
+	.entryStart = LT_KERNEL,
+	.needsBootPrefix = 1,
+	.argsInQuotes = 1,
+	.maxTitleLength = 15,
+	.mbAllowExtraInitRds = 1,
+	.titlePosition = 1,
 };
 
 struct configFileInfo siloConfigType = {
-    .defaultConfig = "/etc/silo.conf",
-    .keywords = siloKeywords,
-    .entryStart = LT_KERNEL,
-    .needsBootPrefix = 1,
-    .argsInQuotes = 1,
-    .maxTitleLength = 15,
-    .titlePosition = 1,
+	.defaultConfig = "/etc/silo.conf",
+	.keywords = siloKeywords,
+	.entryStart = LT_KERNEL,
+	.needsBootPrefix = 1,
+	.argsInQuotes = 1,
+	.maxTitleLength = 15,
+	.titlePosition = 1,
 };
 
 struct configFileInfo ziplConfigType = {
-    .defaultConfig = "/etc/zipl.conf",
-    .keywords = ziplKeywords,
-    .entryStart = LT_TITLE,
-    .argsInQuotes = 1,
-    .titleBracketed = 1,
+	.defaultConfig = "/etc/zipl.conf",
+	.keywords = ziplKeywords,
+	.entryStart = LT_TITLE,
+	.argsInQuotes = 1,
+	.titleBracketed = 1,
 };
 
 struct configFileInfo extlinuxConfigType = {
-    .defaultConfig = "/boot/extlinux/extlinux.conf",
-    .keywords = extlinuxKeywords,
-    .caseInsensitive = 1,
-    .entryStart = LT_TITLE,
-    .needsBootPrefix = 1,
-    .maxTitleLength = 255,
-    .mbAllowExtraInitRds = 1,
-    .defaultIsUnquoted = 1,
-    .titlePosition = 1,
+	.defaultConfig = "/boot/extlinux/extlinux.conf",
+	.keywords = extlinuxKeywords,
+	.caseInsensitive = 1,
+	.entryStart = LT_TITLE,
+	.needsBootPrefix = 1,
+	.maxTitleLength = 255,
+	.mbAllowExtraInitRds = 1,
+	.defaultIsUnquoted = 1,
+	.titlePosition = 1,
 };
 
 struct grubConfig {
-    struct singleLine * theLines;
-    struct singleEntry * entries;
-    char * primaryIndent;
-    char * secondaryIndent;
-    int defaultImage;		    /* -1 if none specified -- this value is
-				     * written out, overriding original */
-    int fallbackImage;		    /* just like defaultImage */
-    int flags;
-    struct configFileInfo * cfi;
+	struct singleLine *theLines;
+	struct singleEntry *entries;
+	char *primaryIndent;
+	char *secondaryIndent;
+	int defaultImage;	/* -1 if none specified -- this value is
+				 * written out, overriding original */
+	int fallbackImage;	/* just like defaultImage */
+	int flags;
+	struct configFileInfo *cfi;
 };
 
 blkid_cache blkid;
 
-struct singleEntry * findEntryByIndex(struct grubConfig * cfg, int index);
-struct singleEntry * findEntryByPath(struct grubConfig * cfg, 
-				     const char * path, const char * prefix,
-				     int * index);
-struct singleEntry * findEntryByTitle(struct grubConfig * cfg, char *title,
-				      int * index);
-static int readFile(int fd, char ** bufPtr);
-static void lineInit(struct singleLine * line);
-struct singleLine * lineDup(struct singleLine * line);
-static void lineFree(struct singleLine * line);
-static int lineWrite(FILE * out, struct singleLine * line,
-		     struct configFileInfo * cfi);
-static int getNextLine(char ** bufPtr, struct singleLine * line,
-		       struct configFileInfo * cfi);
-static char * getRootSpecifier(char * str);
-static void requote(struct singleLine *line, struct configFileInfo * cfi);
-static void insertElement(struct singleLine * line,
-			  const char * item, int insertHere,
-			  struct configFileInfo * cfi);
-static void removeElement(struct singleLine * line, int removeHere);
-static struct keywordTypes * getKeywordByType(enum lineType_e type,
-					      struct configFileInfo * cfi);
-static enum lineType_e getTypeByKeyword(char * keyword, 
-					struct configFileInfo * cfi);
-static struct singleLine * getLineByType(enum lineType_e type,
-					 struct singleLine * line);
-static int checkForExtLinux(struct grubConfig * config);
-struct singleLine * addLineTmpl(struct singleEntry * entry,
-                                struct singleLine * tmplLine,
-                                struct singleLine * prevLine,
-                                const char * val,
-				struct configFileInfo * cfi);
-struct singleLine *  addLine(struct singleEntry * entry,
-                             struct configFileInfo * cfi,
-                             enum lineType_e type, char * defaultIndent,
-                             const char * val);
-
-static char * sdupprintf(const char *format, ...)
+struct singleEntry *findEntryByIndex(struct grubConfig *cfg, int index);
+struct singleEntry *findEntryByPath(struct grubConfig *cfg,
+				    const char *path, const char *prefix,
+				    int *index);
+struct singleEntry *findEntryByTitle(struct grubConfig *cfg, char *title,
+				     int *index);
+static int readFile(int fd, char **bufPtr);
+static void lineInit(struct singleLine *line);
+struct singleLine *lineDup(struct singleLine *line);
+static void lineFree(struct singleLine *line);
+static int lineWrite(FILE * out, struct singleLine *line,
+		     struct configFileInfo *cfi);
+static int getNextLine(char **bufPtr, struct singleLine *line,
+		       struct configFileInfo *cfi);
+static char *getRootSpecifier(char *str);
+static void requote(struct singleLine *line, struct configFileInfo *cfi);
+static void insertElement(struct singleLine *line,
+			  const char *item, int insertHere,
+			  struct configFileInfo *cfi);
+static void removeElement(struct singleLine *line, int removeHere);
+static struct keywordTypes *getKeywordByType(enum lineType_e type,
+					     struct configFileInfo *cfi);
+static enum lineType_e getTypeByKeyword(char *keyword,
+					struct configFileInfo *cfi);
+static struct singleLine *getLineByType(enum lineType_e type,
+					struct singleLine *line);
+static int checkForExtLinux(struct grubConfig *config);
+struct singleLine *addLineTmpl(struct singleEntry *entry,
+			       struct singleLine *tmplLine,
+			       struct singleLine *prevLine,
+			       const char *val, struct configFileInfo *cfi);
+struct singleLine *addLine(struct singleEntry *entry,
+			   struct configFileInfo *cfi,
+			   enum lineType_e type, char *defaultIndent,
+			   const char *val);
+
+static char *sdupprintf(const char *format, ...)
 #ifdef __GNUC__
-        __attribute__ ((format (printf, 1, 2)));
+    __attribute__ ((format(printf, 1, 2)));
 #else
-        ;
+;
 #endif
 
-static char * sdupprintf(const char *format, ...) {
-    char *buf = NULL;
-    char c;
-    va_list args;
-    size_t size = 0;
-    va_start(args, format);
-    
-    /* XXX requires C99 vsnprintf behavior */
-    size = vsnprintf(&c, 1, format, args) + 1;
-    if (size == -1) {
-	printf("ERROR: vsnprintf behavior is not C99\n");
-	abort();
-    }
-
-    va_end(args);
-    va_start(args, format);
-
-    buf = malloc(size);
-    if (buf == NULL)
-	return NULL;
-    vsnprintf(buf, size, format, args);
-    va_end (args);
+static char *sdupprintf(const char *format, ...)
+{
+	char *buf = NULL;
+	char c;
+	va_list args;
+	size_t size = 0;
+	va_start(args, format);
+
+	/* XXX requires C99 vsnprintf behavior */
+	size = vsnprintf(&c, 1, format, args) + 1;
+	if (size == -1) {
+		printf("ERROR: vsnprintf behavior is not C99\n");
+		abort();
+	}
 
-    return buf;
+	va_end(args);
+	va_start(args, format);
+
+	buf = malloc(size);
+	if (buf == NULL)
+		return NULL;
+	vsnprintf(buf, size, format, args);
+	va_end(args);
+
+	return buf;
 }
 
 static enum lineType_e preferredLineType(enum lineType_e type,
-					 struct configFileInfo *cfi) {
-    if (isEfi && cfi == &grub2ConfigType) {
-	switch (type) {
-	case LT_KERNEL:
-	    return isEfiOnly ? LT_KERNEL : LT_KERNEL_EFI;
-	case LT_INITRD:
-	    return isEfiOnly ? LT_INITRD : LT_INITRD_EFI;
-	default:
-	    return type;
-	}
+					 struct configFileInfo *cfi)
+{
+	if (isEfi && cfi == &grub2ConfigType) {
+		switch (type) {
+		case LT_KERNEL:
+			return isEfiOnly ? LT_KERNEL : LT_KERNEL_EFI;
+		case LT_INITRD:
+			return isEfiOnly ? LT_INITRD : LT_INITRD_EFI;
+		default:
+			return type;
+		}
 #if defined(__i386__) || defined(__x86_64__)
-    } else if (cfi == &grub2ConfigType) {
-	switch (type) {
-	case LT_KERNEL:
-	    return LT_KERNEL_16;
-	case LT_INITRD:
-	    return LT_INITRD_16;
-	default:
-	    return type;
-	}
+	} else if (cfi == &grub2ConfigType) {
+		switch (type) {
+		case LT_KERNEL:
+			return LT_KERNEL_16;
+		case LT_INITRD:
+			return LT_INITRD_16;
+		default:
+			return type;
+		}
 #endif
-    }
-    return type;
+	}
+	return type;
 }
 
-static struct keywordTypes * getKeywordByType(enum lineType_e type,
-					      struct configFileInfo * cfi) {
-    for (struct keywordTypes *kw = cfi->keywords; kw->key; kw++) {
-	if (kw->type == type)
-	    return kw;
-    }
-    return NULL;
+static struct keywordTypes *getKeywordByType(enum lineType_e type,
+					     struct configFileInfo *cfi)
+{
+	for (struct keywordTypes * kw = cfi->keywords; kw->key; kw++) {
+		if (kw->type == type)
+			return kw;
+	}
+	return NULL;
 }
 
-static char *getKeyByType(enum lineType_e type, struct configFileInfo * cfi) {
-    struct keywordTypes *kt = getKeywordByType(type, cfi);
-    if (kt)
-	return kt->key;
-    return "unknown";
+static char *getKeyByType(enum lineType_e type, struct configFileInfo *cfi)
+{
+	struct keywordTypes *kt = getKeywordByType(type, cfi);
+	if (kt)
+		return kt->key;
+	return "unknown";
 }
 
-static char * getpathbyspec(char *device) {
-    if (!blkid)
-        blkid_get_cache(&blkid, NULL);
+static char *getpathbyspec(char *device)
+{
+	if (!blkid)
+		blkid_get_cache(&blkid, NULL);
 
-    return blkid_get_devname(blkid, device, NULL);
+	return blkid_get_devname(blkid, device, NULL);
 }
 
-static char * getuuidbydev(char *device) {
-    if (!blkid)
-	blkid_get_cache(&blkid, NULL);
+static char *getuuidbydev(char *device)
+{
+	if (!blkid)
+		blkid_get_cache(&blkid, NULL);
 
-    return blkid_get_tag_value(blkid, "UUID", device);
+	return blkid_get_tag_value(blkid, "UUID", device);
 }
 
-static enum lineType_e getTypeByKeyword(char * keyword, 
-					struct configFileInfo * cfi) {
-    for (struct keywordTypes *kw = cfi->keywords; kw->key; kw++) {
-	if (cfi->caseInsensitive) {
-	    if (!strcasecmp(keyword, kw->key))
-                return kw->type;
-	} else {
-	    if (!strcmp(keyword, kw->key))
-	        return kw->type;
+static enum lineType_e getTypeByKeyword(char *keyword,
+					struct configFileInfo *cfi)
+{
+	for (struct keywordTypes * kw = cfi->keywords; kw->key; kw++) {
+		if (cfi->caseInsensitive) {
+			if (!strcasecmp(keyword, kw->key))
+				return kw->type;
+		} else {
+			if (!strcmp(keyword, kw->key))
+				return kw->type;
+		}
 	}
-    }
-    return LT_UNKNOWN;
+	return LT_UNKNOWN;
 }
 
-static struct singleLine * getLineByType(enum lineType_e type,
-					 struct singleLine * line) {
-    dbgPrintf("getLineByType(%d): ", type);
-    for (; line; line = line->next) {
-	dbgPrintf("%d:%s ", line->type, 
-		  line->numElements ? line->elements[0].item : "(empty)");
-	if (line->type & type) break;
-    }
-    dbgPrintf(line ? "\n" : " (failed)\n");
-    return line;
+static struct singleLine *getLineByType(enum lineType_e type,
+					struct singleLine *line)
+{
+	dbgPrintf("getLineByType(%d): ", type);
+	for (; line; line = line->next) {
+		dbgPrintf("%d:%s ", line->type,
+			  line->numElements ? line->elements[0].
+			  item : "(empty)");
+		if (line->type & type)
+			break;
+	}
+	dbgPrintf(line ? "\n" : " (failed)\n");
+	return line;
 }
 
-static int isBracketedTitle(struct singleLine * line) {
-    if (line->numElements == 1 && *line->elements[0].item == '[') {
-        int len = strlen(line->elements[0].item);
-        if (*(line->elements[0].item + len - 1) == ']') {
-            /* FIXME: this is a hack... */
-            if (strcmp(line->elements[0].item, "[defaultboot]")) {
-                return 1;
-            }
-        }
-    }
-    return 0;
+static int isBracketedTitle(struct singleLine *line)
+{
+	if (line->numElements == 1 && *line->elements[0].item == '[') {
+		int len = strlen(line->elements[0].item);
+		if (*(line->elements[0].item + len - 1) == ']') {
+			/* FIXME: this is a hack... */
+			if (strcmp(line->elements[0].item, "[defaultboot]")) {
+				return 1;
+			}
+		}
+	}
+	return 0;
 }
 
-static int isEntryStart(struct singleLine * line,
-                            struct configFileInfo * cfi) {
-    return line->type == cfi->entryStart || line->type == LT_OTHER ||
-	(cfi->titleBracketed && isBracketedTitle(line));
+static int isEntryStart(struct singleLine *line, struct configFileInfo *cfi)
+{
+	return line->type == cfi->entryStart || line->type == LT_OTHER ||
+	    (cfi->titleBracketed && isBracketedTitle(line));
 }
 
 /* extract the title from within brackets (for zipl) */
-static char * extractTitle(struct grubConfig *cfg, struct singleLine * line) {
-    /* bracketed title... let's extract it */
-    char * title = NULL;
-    if (line->type == LT_TITLE) {
-	char *tmp = line->elements[cfg->cfi->titlePosition].item;
-	if (cfg->cfi->titleBracketed) {
-	    tmp++;
-	    title = strdup(tmp);
-	    *(title + strlen(title) - 1) = '\0';
-	} else {
-	    title = strdup(tmp);
-	}
-    } else if (line->type == LT_MENUENTRY)
-	title = strdup(line->elements[1].item);
-    else
-	return NULL;
-    return title;
+static char *extractTitle(struct grubConfig *cfg, struct singleLine *line)
+{
+	/* bracketed title... let's extract it */
+	char *title = NULL;
+	if (line->type == LT_TITLE) {
+		char *tmp = line->elements[cfg->cfi->titlePosition].item;
+		if (cfg->cfi->titleBracketed) {
+			tmp++;
+			title = strdup(tmp);
+			*(title + strlen(title) - 1) = '\0';
+		} else {
+			title = strdup(tmp);
+		}
+	} else if (line->type == LT_MENUENTRY)
+		title = strdup(line->elements[1].item);
+	else
+		return NULL;
+	return title;
 }
 
-static int readFile(int fd, char ** bufPtr) {
-    int alloced = 0, size = 0, i = 0;
-    char * buf = NULL;
+static int readFile(int fd, char **bufPtr)
+{
+	int alloced = 0, size = 0, i = 0;
+	char *buf = NULL;
+
+	do {
+		size += i;
+		if ((size + 1024) > alloced) {
+			alloced += 4096;
+			buf = realloc(buf, alloced + 1);
+		}
+	} while ((i = read(fd, buf + size, 1024)) > 0);
 
-    do {
-	size += i;
-	if ((size + 1024) > alloced) {
-	    alloced += 4096;
-	    buf = realloc(buf, alloced + 1);
+	if (i < 0) {
+		fprintf(stderr, _("error reading input: %s\n"),
+			strerror(errno));
+		free(buf);
+		return 1;
 	}
-    } while ((i = read(fd, buf + size, 1024)) > 0);
-
-    if (i < 0) {
-	fprintf(stderr, _("error reading input: %s\n"), strerror(errno));
-        free(buf);
-	return 1;
-    }
 
-    buf = realloc(buf, size + 2);
-    if (size == 0)
-        buf[size++] = '\n';
-    else 
-        if (buf[size - 1] != '\n')
-            buf[size++] = '\n';
-    buf[size] = '\0';
+	buf = realloc(buf, size + 2);
+	if (size == 0)
+		buf[size++] = '\n';
+	else if (buf[size - 1] != '\n')
+		buf[size++] = '\n';
+	buf[size] = '\0';
 
-    *bufPtr = buf;
+	*bufPtr = buf;
 
-    return 0;
+	return 0;
 }
 
-static void lineInit(struct singleLine * line) {
-    line->indent = NULL;
-    line->elements = NULL;
-    line->numElements = 0;
-    line->next = NULL;
+static void lineInit(struct singleLine *line)
+{
+	line->indent = NULL;
+	line->elements = NULL;
+	line->numElements = 0;
+	line->next = NULL;
 }
 
-struct singleLine * lineDup(struct singleLine * line) {
-    struct singleLine * newLine = malloc(sizeof(*newLine));
-
-    newLine->indent = strdup(line->indent);
-    newLine->next = NULL;
-    newLine->type = line->type;
-    newLine->numElements = line->numElements;
-    newLine->elements = malloc(sizeof(*newLine->elements) * 
-			       newLine->numElements);
-
-    for (int i = 0; i < newLine->numElements; i++) {
-	newLine->elements[i].indent = strdup(line->elements[i].indent);
-	newLine->elements[i].item = strdup(line->elements[i].item);
-    }
+struct singleLine *lineDup(struct singleLine *line)
+{
+	struct singleLine *newLine = malloc(sizeof(*newLine));
+
+	newLine->indent = strdup(line->indent);
+	newLine->next = NULL;
+	newLine->type = line->type;
+	newLine->numElements = line->numElements;
+	newLine->elements = malloc(sizeof(*newLine->elements) *
+				   newLine->numElements);
+
+	for (int i = 0; i < newLine->numElements; i++) {
+		newLine->elements[i].indent = strdup(line->elements[i].indent);
+		newLine->elements[i].item = strdup(line->elements[i].item);
+	}
 
-    return newLine;
+	return newLine;
 }
 
-static void lineFree(struct singleLine * line) {
-    if (line->indent) free(line->indent);
+static void lineFree(struct singleLine *line)
+{
+	if (line->indent)
+		free(line->indent);
 
-    for (int i = 0; i < line->numElements; i++) {
-	free(line->elements[i].item); 
-	free(line->elements[i].indent); 
-    }
+	for (int i = 0; i < line->numElements; i++) {
+		free(line->elements[i].item);
+		free(line->elements[i].indent);
+	}
 
-    if (line->elements) free(line->elements);
-    lineInit(line);
+	if (line->elements)
+		free(line->elements);
+	lineInit(line);
 }
 
-static int lineWrite(FILE * out, struct singleLine * line,
-		     struct configFileInfo * cfi) {
-    if (fprintf(out, "%s", line->indent) == -1) return -1;
-
-    for (int i = 0; i < line->numElements; i++) {
-	/* Need to handle this, because we strip the quotes from
-	 * menuentry when read it. */
-	if (line->type == LT_MENUENTRY && i == 1) {
-	    if(!isquote(*line->elements[i].item)) {
-		int substring = 0;
-		/* If the line contains nested quotes, we did not strip
-		 * the "interna" quotes and we must use the right quotes
-		 * again when writing the updated file. */
-		for (int j = i; j < line->numElements; j++) {
-		    if (strchr(line->elements[i].item, '\'') != NULL) {
-		       substring = 1;
-		       fprintf(out, "\"%s\"", line->elements[i].item);
-		       break;
-		    }
-		}
-		if (!substring)
-		    fprintf(out, "\'%s\'", line->elements[i].item);
-	    } else {
-		fprintf(out, "%s", line->elements[i].item);
-	    }
-	    fprintf(out, "%s", line->elements[i].indent);
+static int lineWrite(FILE * out, struct singleLine *line,
+		     struct configFileInfo *cfi)
+{
+	if (fprintf(out, "%s", line->indent) == -1)
+		return -1;
+
+	for (int i = 0; i < line->numElements; i++) {
+		/* Need to handle this, because we strip the quotes from
+		 * menuentry when read it. */
+		if (line->type == LT_MENUENTRY && i == 1) {
+			if (!isquote(*line->elements[i].item)) {
+				int substring = 0;
+				/* If the line contains nested quotes, we did not strip
+				 * the "interna" quotes and we must use the right quotes
+				 * again when writing the updated file. */
+				for (int j = i; j < line->numElements; j++) {
+					if (strchr(line->elements[i].item, '\'')
+					    != NULL) {
+						substring = 1;
+						fprintf(out, "\"%s\"",
+							line->elements[i].item);
+						break;
+					}
+				}
+				if (!substring)
+					fprintf(out, "\'%s\'",
+						line->elements[i].item);
+			} else {
+				fprintf(out, "%s", line->elements[i].item);
+			}
+			fprintf(out, "%s", line->elements[i].indent);
 
-	    continue;
-	}
+			continue;
+		}
 
-	if (i == 1 && line->type == LT_KERNELARGS && cfi->argsInQuotes)
-	    if (fputc('"', out) == EOF) return -1;
+		if (i == 1 && line->type == LT_KERNELARGS && cfi->argsInQuotes)
+			if (fputc('"', out) == EOF)
+				return -1;
 
-	if (fprintf(out, "%s", line->elements[i].item) == -1) return -1;
-	if (i < line->numElements - 1)
-	    if (fprintf(out, "%s", line->elements[i].indent) == -1) return -1;
-    }
+		if (fprintf(out, "%s", line->elements[i].item) == -1)
+			return -1;
+		if (i < line->numElements - 1)
+			if (fprintf(out, "%s", line->elements[i].indent) == -1)
+				return -1;
+	}
 
-    if (line->type == LT_KERNELARGS && cfi->argsInQuotes)
-	if (fputc('"', out) == EOF) return -1;
+	if (line->type == LT_KERNELARGS && cfi->argsInQuotes)
+		if (fputc('"', out) == EOF)
+			return -1;
 
-    if (fprintf(out, "\n") == -1) return -1;
+	if (fprintf(out, "\n") == -1)
+		return -1;
 
-    return 0;
+	return 0;
 }
 
 /* we've guaranteed that the buffer ends w/ \n\0 */
-static int getNextLine(char ** bufPtr, struct singleLine * line,
-                       struct configFileInfo * cfi) {
-    char * end;
-    char * start = *bufPtr;
-    char * chptr;
-    int elementsAlloced = 0;
-    struct lineElement * element;
-    int first = 1;
-
-    lineFree(line);
+static int getNextLine(char **bufPtr, struct singleLine *line,
+		       struct configFileInfo *cfi)
+{
+	char *end;
+	char *start = *bufPtr;
+	char *chptr;
+	int elementsAlloced = 0;
+	struct lineElement *element;
+	int first = 1;
 
-    end = strchr(start, '\n');
-    *end = '\0';
-    *bufPtr = end + 1;
+	lineFree(line);
 
-    for (chptr = start; *chptr && isspace(*chptr); chptr++) ;
+	end = strchr(start, '\n');
+	*end = '\0';
+	*bufPtr = end + 1;
 
-    line->indent = strndup(start, chptr - start);
-    start = chptr;
+	for (chptr = start; *chptr && isspace(*chptr); chptr++) ;
 
-    while (start < end) {
-	/* we know !isspace(*start) */
+	line->indent = strndup(start, chptr - start);
+	start = chptr;
 
-	if (elementsAlloced == line->numElements) {
-	    elementsAlloced += 5;
-	    line->elements = realloc(line->elements,
-				sizeof(*line->elements) * elementsAlloced);
-	}
+	while (start < end) {
+		/* we know !isspace(*start) */
 
-	element = line->elements + line->numElements;
+		if (elementsAlloced == line->numElements) {
+			elementsAlloced += 5;
+			line->elements = realloc(line->elements,
+						 sizeof(*line->elements) *
+						 elementsAlloced);
+		}
 
-	chptr = start;
-	while (*chptr && !isspace(*chptr)) {
-	    if (first && *chptr == '=') break; 
-	    chptr++;
-	}
-	element->item = strndup(start, chptr - start);
-	start = chptr;
+		element = line->elements + line->numElements;
 
-        /* lilo actually accepts the pathological case of append = " foo " */
-        if (*start == '=')
-            chptr = start + 1;
-        else 
-            chptr = start;
+		chptr = start;
+		while (*chptr && !isspace(*chptr)) {
+			if (first && *chptr == '=')
+				break;
+			chptr++;
+		}
+		element->item = strndup(start, chptr - start);
+		start = chptr;
 
-        do {
-            for (; *chptr && isspace(*chptr); chptr++);
-            if (*chptr == '=')
-                chptr = chptr + 1;
-        } while (isspace(*chptr));
+		/* lilo actually accepts the pathological case of append = " foo " */
+		if (*start == '=')
+			chptr = start + 1;
+		else
+			chptr = start;
 
-	element->indent = strndup(start, chptr - start);
-	start = chptr;
+		do {
+			for (; *chptr && isspace(*chptr); chptr++) ;
+			if (*chptr == '=')
+				chptr = chptr + 1;
+		} while (isspace(*chptr));
 
-	line->numElements++;
-	first = 0;
-    }
-
-    if (!line->numElements)
-	line->type = LT_WHITESPACE;
-    else {
-	line->type = getTypeByKeyword(line->elements[0].item, cfi);
-	if (line->type == LT_UNKNOWN) {
-            /* zipl does [title] instead of something reasonable like all
-             * the other boot loaders.  kind of ugly */
-            if (cfi->titleBracketed && isBracketedTitle(line)) {
-                line->type = LT_TITLE;
-            }
-
-	    /* this is awkward, but we need to be able to handle keywords
-	       that begin with a # (specifically for #boot in grub.conf),
-	       but still make comments lines with no elements (everything
-	       stored in the indent */
-	    if (*line->elements[0].item == '#') {
-		char * fullLine;
-		int len;
-
-		len = strlen(line->indent);
-		for (int i = 0; i < line->numElements; i++)
-		    len += strlen(line->elements[i].item) + 
-			   strlen(line->elements[i].indent);
-
-		fullLine = malloc(len + 1);
-		strcpy(fullLine, line->indent);
-		free(line->indent);
-		line->indent = fullLine;
+		element->indent = strndup(start, chptr - start);
+		start = chptr;
 
-		for (int i = 0; i < line->numElements; i++) {
-		    strcat(fullLine, line->elements[i].item);
-		    strcat(fullLine, line->elements[i].indent);
-		    free(line->elements[i].item);
-		    free(line->elements[i].indent);
-		}
+		line->numElements++;
+		first = 0;
+	}
 
+	if (!line->numElements)
 		line->type = LT_WHITESPACE;
-		line->numElements = 0;
-	    }
-	} else {
-		struct keywordTypes *kw;
+	else {
+		line->type = getTypeByKeyword(line->elements[0].item, cfi);
+		if (line->type == LT_UNKNOWN) {
+			/* zipl does [title] instead of something reasonable like all
+			 * the other boot loaders.  kind of ugly */
+			if (cfi->titleBracketed && isBracketedTitle(line)) {
+				line->type = LT_TITLE;
+			}
 
-		kw = getKeywordByType(line->type, cfi);
+			/* this is awkward, but we need to be able to handle keywords
+			   that begin with a # (specifically for #boot in grub.conf),
+			   but still make comments lines with no elements (everything
+			   stored in the indent */
+			if (*line->elements[0].item == '#') {
+				char *fullLine;
+				int len;
+
+				len = strlen(line->indent);
+				for (int i = 0; i < line->numElements; i++)
+					len += strlen(line->elements[i].item) +
+					    strlen(line->elements[i].indent);
+
+				fullLine = malloc(len + 1);
+				strcpy(fullLine, line->indent);
+				free(line->indent);
+				line->indent = fullLine;
+
+				for (int i = 0; i < line->numElements; i++) {
+					strcat(fullLine,
+					       line->elements[i].item);
+					strcat(fullLine,
+					       line->elements[i].indent);
+					free(line->elements[i].item);
+					free(line->elements[i].indent);
+				}
 
-		/* space isn't the only separator, we need to split
-		 * elements up more
-		 */
-		if (!isspace(kw->separatorChar)) {
-		    char indent[2] = "";
-		    indent[0] = kw->separatorChar;
-		    for (int i = 1; i < line->numElements; i++) {
-			char *p;
-			int numNewElements;
-
-			numNewElements = 0;
-			p = line->elements[i].item;
-			while (*p != '\0') {
-				if (*p == kw->separatorChar)
-					numNewElements++;
-				p++;
-			}
-			if (line->numElements + numNewElements >= elementsAlloced) {
-				elementsAlloced += numNewElements + 5;
-				line->elements = realloc(line->elements,
-					    sizeof(*line->elements) * elementsAlloced);
+				line->type = LT_WHITESPACE;
+				line->numElements = 0;
 			}
+		} else {
+			struct keywordTypes *kw;
 
-			for (int j = line->numElements; j > i; j--) {
-				line->elements[j + numNewElements] = line->elements[j];
-			}
-			line->numElements += numNewElements;
+			kw = getKeywordByType(line->type, cfi);
 
-			p = line->elements[i].item;
-			while (*p != '\0') {
+			/* space isn't the only separator, we need to split
+			 * elements up more
+			 */
+			if (!isspace(kw->separatorChar)) {
+				char indent[2] = "";
+				indent[0] = kw->separatorChar;
+				for (int i = 1; i < line->numElements; i++) {
+					char *p;
+					int numNewElements;
+
+					numNewElements = 0;
+					p = line->elements[i].item;
+					while (*p != '\0') {
+						if (*p == kw->separatorChar)
+							numNewElements++;
+						p++;
+					}
+					if (line->numElements +
+					    numNewElements >= elementsAlloced) {
+						elementsAlloced +=
+						    numNewElements + 5;
+						line->elements =
+						    realloc(line->elements,
+							    sizeof(*line->
+								   elements) *
+							    elementsAlloced);
+					}
 
-				while (*p != kw->separatorChar && *p != '\0') p++;
-				if (*p == '\0') {
-					break;
+					for (int j = line->numElements; j > i;
+					     j--) {
+						line->elements[j +
+							       numNewElements] =
+						    line->elements[j];
+					}
+					line->numElements += numNewElements;
+
+					p = line->elements[i].item;
+					while (*p != '\0') {
+
+						while (*p != kw->separatorChar
+						       && *p != '\0')
+							p++;
+						if (*p == '\0') {
+							break;
+						}
+
+						line->elements[i + 1].indent =
+						    line->elements[i].indent;
+						line->elements[i].indent =
+						    strdup(indent);
+						*p++ = '\0';
+						i++;
+						line->elements[i].item =
+						    strdup(p);
+					}
 				}
-
-				line->elements[i + 1].indent = line->elements[i].indent;
-				line->elements[i].indent = strdup(indent);
-				*p++ = '\0';
-				i++;
-				line->elements[i].item = strdup(p);
 			}
-		    }
 		}
 	}
-    }
 
-    return 0;
+	return 0;
 }
 
 static int isnumber(const char *s)
 {
-    int i;
-    for (i = 0; s[i] != '\0'; i++)
-	if (s[i] < '0' || s[i] > '9')
-	    return 0;
-    return i;
+	int i;
+	for (i = 0; s[i] != '\0'; i++)
+		if (s[i] < '0' || s[i] > '9')
+			return 0;
+	return i;
 }
 
-static struct grubConfig * readConfig(const char * inName,
-				      struct configFileInfo * cfi) {
-    int in;
-    char * incoming = NULL, * head;
-    int rc;
-    int sawEntry = 0;
-    int movedLine = 0;
-    struct grubConfig * cfg;
-    struct singleLine * last = NULL, * line, * defaultLine = NULL;
-    char * end;
-    struct singleEntry * entry = NULL;
-    int len;
-    char * buf;
-
-    if (inName == NULL) {
-        printf("Could not find bootloader configuration\n");
-        exit(1);
-    } else if (!strcmp(inName, "-")) {
-	in = 0;
-    } else {
-	if ((in = open(inName, O_RDONLY)) < 0) {
-	    fprintf(stderr, _("error opening %s for read: %s\n"),
-		    inName, strerror(errno));
-	    return NULL;
-	}
-    }
-
-    rc = readFile(in, &incoming);
-    close(in);
-    if (rc) return NULL;
-
-    head = incoming;
-    cfg = malloc(sizeof(*cfg));
-    cfg->primaryIndent = strdup("");
-    cfg->secondaryIndent = strdup("\t");
-    cfg->flags = GRUB_CONFIG_NO_DEFAULT;
-    cfg->cfi = cfi;
-    cfg->theLines = NULL;
-    cfg->entries = NULL;
-    cfg->fallbackImage = 0;
-
-    /* copy everything we have */
-    while (*head) {
-	line = malloc(sizeof(*line));
-	lineInit(line);
-
-	if (getNextLine(&head, line, cfi)) {
-	    free(line);
-	    /* XXX memory leak of everything in cfg */
-	    return NULL;
-	}
-
-	if (!sawEntry && line->numElements) {
-	    free(cfg->primaryIndent);
-	    cfg->primaryIndent = strdup(line->indent);
-	} else if (line->numElements) {
-	    free(cfg->secondaryIndent);
-	    cfg->secondaryIndent = strdup(line->indent);
+static struct grubConfig *readConfig(const char *inName,
+				     struct configFileInfo *cfi)
+{
+	int in;
+	char *incoming = NULL, *head;
+	int rc;
+	int sawEntry = 0;
+	int movedLine = 0;
+	struct grubConfig *cfg;
+	struct singleLine *last = NULL, *line, *defaultLine = NULL;
+	char *end;
+	struct singleEntry *entry = NULL;
+	int len;
+	char *buf;
+
+	if (inName == NULL) {
+		printf("Could not find bootloader configuration\n");
+		exit(1);
+	} else if (!strcmp(inName, "-")) {
+		in = 0;
+	} else {
+		if ((in = open(inName, O_RDONLY)) < 0) {
+			fprintf(stderr, _("error opening %s for read: %s\n"),
+				inName, strerror(errno));
+			return NULL;
+		}
 	}
 
-	if (isEntryStart(line, cfi) || (cfg->entries && !sawEntry)) {
-	    sawEntry = 1;
-	    if (!entry) {
-		cfg->entries = malloc(sizeof(*entry));
-		entry = cfg->entries;
-	    } else {
-		entry->next = malloc(sizeof(*entry));
-		entry = entry->next;
-	    }
-
-	    entry->skip = 0;
-            entry->multiboot = 0;
-	    entry->lines = NULL;
-	    entry->next = NULL;
-	}
-
-	if (line->type == LT_SET_VARIABLE) {
-	    dbgPrintf("found 'set' command (%d elements): ", line->numElements);
-	    dbgPrintf("%s", line->indent);
-	    for (int i = 0; i < line->numElements; i++)
-		dbgPrintf("\"%s\"%s", line->elements[i].item, line->elements[i].indent);
-	    dbgPrintf("\n");
-	    struct keywordTypes *kwType = getKeywordByType(LT_DEFAULT, cfi);
-	    if (kwType && line->numElements == 3 &&
-		    !strcmp(line->elements[1].item, kwType->key) &&
-		    !is_special_grub2_variable(line->elements[2].item)) {
-		dbgPrintf("Line sets default config\n");
-		cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;
-		defaultLine = line;
-	    }
-
-        } else if (iskernel(line->type)) {
-	    /* if by some freak chance this is multiboot and the "module"
-	     * lines came earlier in the template, make sure to use LT_HYPER 
-	     * instead of LT_KERNEL now
-	     */
-	    if (entry && entry->multiboot)
-		line->type = LT_HYPER;
-
-        } else if (line->type == LT_MBMODULE) {
-	    /* go back and fix the LT_KERNEL line to indicate LT_HYPER
-	     * instead, now that we know this is a multiboot entry.
-	     * This only applies to grub, but that's the only place we
-	     * should find LT_MBMODULE lines anyway.
-	     */
-	    for (struct singleLine *l = entry->lines; l; l = l->next) {
-		if (l->type == LT_HYPER)
-		    break;
-		else if (iskernel(l->type)) {
-		    l->type = LT_HYPER;
-		    break;
+	rc = readFile(in, &incoming);
+	close(in);
+	if (rc)
+		return NULL;
+
+	head = incoming;
+	cfg = malloc(sizeof(*cfg));
+	cfg->primaryIndent = strdup("");
+	cfg->secondaryIndent = strdup("\t");
+	cfg->flags = GRUB_CONFIG_NO_DEFAULT;
+	cfg->cfi = cfi;
+	cfg->theLines = NULL;
+	cfg->entries = NULL;
+	cfg->fallbackImage = 0;
+
+	/* copy everything we have */
+	while (*head) {
+		line = malloc(sizeof(*line));
+		lineInit(line);
+
+		if (getNextLine(&head, line, cfi)) {
+			free(line);
+			/* XXX memory leak of everything in cfg */
+			return NULL;
 		}
-	    }
-            entry->multiboot = 1;
-
-	} else if (line->type == LT_HYPER) {
-	    entry->multiboot = 1;
-
-	} else if (line->type == LT_FALLBACK && line->numElements == 2) {
-	    cfg->fallbackImage = strtol(line->elements[1].item, &end, 10);
-	    if (*end) cfg->fallbackImage = -1;
-
-	} else if ((line->type == LT_DEFAULT && cfi->defaultIsUnquoted) ||
-                (line->type == LT_TITLE && line->numElements > 1)) {
-	    /* make the title/default a single argument (undoing our parsing) */
-	    len = 0;
-	    for (int i = 1; i < line->numElements; i++) {
-		len += strlen(line->elements[i].item);
-		len += strlen(line->elements[i].indent);
-	    }
-	    buf = malloc(len + 1);
-	    *buf = '\0';
-
-	    for (int i = 1; i < line->numElements; i++) {
-		strcat(buf, line->elements[i].item);
-		free(line->elements[i].item);
 
-		if ((i + 1) != line->numElements) {
-		    strcat(buf, line->elements[i].indent);
-		    free(line->elements[i].indent);
-		}
-	    }
-
-	    line->elements[1].indent = 
-		    line->elements[line->numElements - 1].indent;
-	    line->elements[1].item = buf;
-	    line->numElements = 2;
-	} else if (line->type == LT_MENUENTRY && line->numElements > 3) {
-	    /* let --remove-kernel="TITLE=what" work */
-	    len = 0;
-	    char *extras;
-	    char *title;
-	    /* initially unseen value */
-	    char quote_char = '\0';
-
-	    for (int i = 1; i < line->numElements; i++) {
-		len += strlen(line->elements[i].item);
-		len += strlen(line->elements[i].indent);
-	    }
-	    buf = malloc(len + 1);
-	    *buf = '\0';
-
-	    /* allocate mem for extra flags. */
-	    extras = malloc(len + 1);
-	    *extras = '\0';
-
-	    /* get title. */
-	    for (int i = 0; i < line->numElements; i++) {
-		if (!strcmp(line->elements[i].item, "menuentry"))
-		    continue;
-		if (isquote(*line->elements[i].item) && quote_char == '\0') {
-		    /* ensure we properly pair off quotes */
-		    quote_char = *line->elements[i].item;
-		    title = line->elements[i].item + 1;
-		} else {
-		    title = line->elements[i].item;
+		if (!sawEntry && line->numElements) {
+			free(cfg->primaryIndent);
+			cfg->primaryIndent = strdup(line->indent);
+		} else if (line->numElements) {
+			free(cfg->secondaryIndent);
+			cfg->secondaryIndent = strdup(line->indent);
 		}
 
-		len = strlen(title);
-	        if (title[len-1] == quote_char) {
-		    strncat(buf, title,len-1);
-		    break;
-		} else {
-		    strcat(buf, title);
-		    strcat(buf, line->elements[i].indent);
-		}
-	    }
-
-	    /* get extras */
-	    int count = 0;
-	    quote_char = '\0';
-	    for (int i = 0; i < line->numElements; i++) {
-		if (count >= 2) {
-		    strcat(extras, line->elements[i].item);
-		    strcat(extras, line->elements[i].indent);
+		if (isEntryStart(line, cfi) || (cfg->entries && !sawEntry)) {
+			sawEntry = 1;
+			if (!entry) {
+				cfg->entries = malloc(sizeof(*entry));
+				entry = cfg->entries;
+			} else {
+				entry->next = malloc(sizeof(*entry));
+				entry = entry->next;
+			}
+
+			entry->skip = 0;
+			entry->multiboot = 0;
+			entry->lines = NULL;
+			entry->next = NULL;
 		}
 
-		if (!strcmp(line->elements[i].item, "menuentry"))
-		    continue;
+		if (line->type == LT_SET_VARIABLE) {
+			dbgPrintf("found 'set' command (%d elements): ",
+				  line->numElements);
+			dbgPrintf("%s", line->indent);
+			for (int i = 0; i < line->numElements; i++)
+				dbgPrintf("\"%s\"%s", line->elements[i].item,
+					  line->elements[i].indent);
+			dbgPrintf("\n");
+			struct keywordTypes *kwType =
+			    getKeywordByType(LT_DEFAULT, cfi);
+			if (kwType && line->numElements == 3
+			    && !strcmp(line->elements[1].item, kwType->key)
+			    && !is_special_grub2_variable(line->elements[2].
+							  item)) {
+				dbgPrintf("Line sets default config\n");
+				cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;
+				defaultLine = line;
+			}
+
+		} else if (iskernel(line->type)) {
+			/* if by some freak chance this is multiboot and the "module"
+			 * lines came earlier in the template, make sure to use LT_HYPER 
+			 * instead of LT_KERNEL now
+			 */
+			if (entry && entry->multiboot)
+				line->type = LT_HYPER;
+
+		} else if (line->type == LT_MBMODULE) {
+			/* go back and fix the LT_KERNEL line to indicate LT_HYPER
+			 * instead, now that we know this is a multiboot entry.
+			 * This only applies to grub, but that's the only place we
+			 * should find LT_MBMODULE lines anyway.
+			 */
+			for (struct singleLine * l = entry->lines; l;
+			     l = l->next) {
+				if (l->type == LT_HYPER)
+					break;
+				else if (iskernel(l->type)) {
+					l->type = LT_HYPER;
+					break;
+				}
+			}
+			entry->multiboot = 1;
+
+		} else if (line->type == LT_HYPER) {
+			entry->multiboot = 1;
+
+		} else if (line->type == LT_FALLBACK && line->numElements == 2) {
+			cfg->fallbackImage =
+			    strtol(line->elements[1].item, &end, 10);
+			if (*end)
+				cfg->fallbackImage = -1;
+
+		} else if ((line->type == LT_DEFAULT && cfi->defaultIsUnquoted)
+			   || (line->type == LT_TITLE
+			       && line->numElements > 1)) {
+			/* make the title/default a single argument (undoing our parsing) */
+			len = 0;
+			for (int i = 1; i < line->numElements; i++) {
+				len += strlen(line->elements[i].item);
+				len += strlen(line->elements[i].indent);
+			}
+			buf = malloc(len + 1);
+			*buf = '\0';
+
+			for (int i = 1; i < line->numElements; i++) {
+				strcat(buf, line->elements[i].item);
+				free(line->elements[i].item);
+
+				if ((i + 1) != line->numElements) {
+					strcat(buf, line->elements[i].indent);
+					free(line->elements[i].indent);
+				}
+			}
+
+			line->elements[1].indent =
+			    line->elements[line->numElements - 1].indent;
+			line->elements[1].item = buf;
+			line->numElements = 2;
+		} else if (line->type == LT_MENUENTRY && line->numElements > 3) {
+			/* let --remove-kernel="TITLE=what" work */
+			len = 0;
+			char *extras;
+			char *title;
+			/* initially unseen value */
+			char quote_char = '\0';
+
+			for (int i = 1; i < line->numElements; i++) {
+				len += strlen(line->elements[i].item);
+				len += strlen(line->elements[i].indent);
+			}
+			buf = malloc(len + 1);
+			*buf = '\0';
+
+			/* allocate mem for extra flags. */
+			extras = malloc(len + 1);
+			*extras = '\0';
+
+			/* get title. */
+			for (int i = 0; i < line->numElements; i++) {
+				if (!strcmp
+				    (line->elements[i].item, "menuentry"))
+					continue;
+				if (isquote(*line->elements[i].item)
+				    && quote_char == '\0') {
+					/* ensure we properly pair off quotes */
+					quote_char = *line->elements[i].item;
+					title = line->elements[i].item + 1;
+				} else {
+					title = line->elements[i].item;
+				}
+
+				len = strlen(title);
+				if (title[len - 1] == quote_char) {
+					strncat(buf, title, len - 1);
+					break;
+				} else {
+					strcat(buf, title);
+					strcat(buf, line->elements[i].indent);
+				}
+			}
+
+			/* get extras */
+			int count = 0;
+			quote_char = '\0';
+			for (int i = 0; i < line->numElements; i++) {
+				if (count >= 2) {
+					strcat(extras, line->elements[i].item);
+					strcat(extras,
+					       line->elements[i].indent);
+				}
+
+				if (!strcmp
+				    (line->elements[i].item, "menuentry"))
+					continue;
 
-		/* count ' or ", there should be two in menuentry line. */
-		if (isquote(*line->elements[i].item) && quote_char == '\0') {
-		    /* ensure we properly pair off quotes */
-	            quote_char = *line->elements[i].item;
-		    count++;
+				/* count ' or ", there should be two in menuentry line. */
+				if (isquote(*line->elements[i].item)
+				    && quote_char == '\0') {
+					/* ensure we properly pair off quotes */
+					quote_char = *line->elements[i].item;
+					count++;
+				}
+
+				len = strlen(line->elements[i].item);
+
+				if (line->elements[i].item[len - 1] ==
+				    quote_char)
+					count++;
+
+				/* ok, we get the final ' or ", others are extras. */
+			}
+			line->elements[1].indent =
+			    line->elements[line->numElements - 2].indent;
+			line->elements[1].item = buf;
+			line->elements[2].indent =
+			    line->elements[line->numElements - 2].indent;
+			line->elements[2].item = extras;
+			line->numElements = 3;
+		} else if (line->type == LT_KERNELARGS && cfi->argsInQuotes) {
+			/* Strip off any " which may be present; they'll be put back
+			   on write. This is one of the few (the only?) places that grubby
+			   canonicalizes the output */
+
+			if (line->numElements >= 2) {
+				int last, len;
+
+				if (isquote(*line->elements[1].item))
+					memmove(line->elements[1].item,
+						line->elements[1].item + 1,
+						strlen(line->elements[1].item +
+						       1) + 1);
+
+				last = line->numElements - 1;
+				len = strlen(line->elements[last].item) - 1;
+				if (isquote(line->elements[last].item[len]))
+					line->elements[last].item[len] = '\0';
+			}
 		}
 
-		len = strlen(line->elements[i].item);
-
-		if (line->elements[i].item[len -1] == quote_char)
-		    count++;
-
-		/* ok, we get the final ' or ", others are extras. */
-            }
-	    line->elements[1].indent =
-		line->elements[line->numElements - 2].indent;
-	    line->elements[1].item = buf;
-	    line->elements[2].indent =
-		line->elements[line->numElements - 2].indent;
-	    line->elements[2].item = extras;
-	    line->numElements = 3;
-	} else if (line->type == LT_KERNELARGS && cfi->argsInQuotes) {
-	    /* Strip off any " which may be present; they'll be put back
-	       on write. This is one of the few (the only?) places that grubby
-	       canonicalizes the output */
-
-	    if (line->numElements >= 2) {
-		int last, len;
-
-		if (isquote(*line->elements[1].item))
-		    memmove(line->elements[1].item, line->elements[1].item + 1,
-			    strlen(line->elements[1].item + 1) + 1);
-
-		last = line->numElements - 1;
-		len = strlen(line->elements[last].item) - 1;
-		if (isquote(line->elements[last].item[len]))
-		    line->elements[last].item[len] = '\0';
-	    }
-	}
-
-	if (line->type == LT_DEFAULT && line->numElements == 2) {
-	    cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;
-	    defaultLine = line;
-	}
-
-	/* If we find a generic config option which should live at the
-	   top of the file, move it there. Old versions of grubby were
-	   probably responsible for putting new images in the wrong 
-	   place in front of it anyway. */
-	if (sawEntry && line->type == LT_GENERIC) {
-		struct singleLine **l = &cfg->theLines;
-		struct singleLine **last_nonws = &cfg->theLines;
-		while (*l) {
-			if ((*l)->type != LT_WHITESPACE)
-				last_nonws = &((*l)->next);
-			l = &((*l)->next);
+		if (line->type == LT_DEFAULT && line->numElements == 2) {
+			cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;
+			defaultLine = line;
 		}
-		line->next = *last_nonws;
-		*last_nonws = line;
-		movedLine = 1;
-		continue; /* without setting 'last' */
-	}
 
-	/* If a second line of whitespace happens after a generic option
-	   which was moved, drop it. */
-	if (movedLine && line->type == LT_WHITESPACE && last->type == LT_WHITESPACE) {
-		lineFree(line);
-		free(line);
+		/* If we find a generic config option which should live at the
+		   top of the file, move it there. Old versions of grubby were
+		   probably responsible for putting new images in the wrong 
+		   place in front of it anyway. */
+		if (sawEntry && line->type == LT_GENERIC) {
+			struct singleLine **l = &cfg->theLines;
+			struct singleLine **last_nonws = &cfg->theLines;
+			while (*l) {
+				if ((*l)->type != LT_WHITESPACE)
+					last_nonws = &((*l)->next);
+				l = &((*l)->next);
+			}
+			line->next = *last_nonws;
+			*last_nonws = line;
+			movedLine = 1;
+			continue;	/* without setting 'last' */
+		}
+
+		/* If a second line of whitespace happens after a generic option
+		   which was moved, drop it. */
+		if (movedLine && line->type == LT_WHITESPACE
+		    && last->type == LT_WHITESPACE) {
+			lineFree(line);
+			free(line);
+			movedLine = 0;
+			continue;
+		}
 		movedLine = 0;
-		continue;
-	}
-	movedLine = 0;
 
-	if (sawEntry) {
-	    if (!entry->lines)
-		entry->lines = line;
-	    else
-		last->next = line;
-	    dbgPrintf("readConfig added %s to %p\n", getKeyByType(line->type, cfi), entry);
+		if (sawEntry) {
+			if (!entry->lines)
+				entry->lines = line;
+			else
+				last->next = line;
+			dbgPrintf("readConfig added %s to %p\n",
+				  getKeyByType(line->type, cfi), entry);
+
+			/* we could have seen this outside of an entry... if so, we
+			 * ignore it like any other line we don't grok */
+			if (line->type == LT_ENTRY_END && sawEntry)
+				sawEntry = 0;
+		} else {
+			if (!cfg->theLines)
+				cfg->theLines = line;
+			else
+				last->next = line;
+			dbgPrintf("readConfig added %s to cfg\n",
+				  getKeyByType(line->type, cfi));
+		}
 
-	    /* we could have seen this outside of an entry... if so, we
-	     * ignore it like any other line we don't grok */
-	    if (line->type == LT_ENTRY_END && sawEntry)
-		sawEntry = 0;
-	} else {
-	    if (!cfg->theLines)
-		cfg->theLines = line;
-	    else
-		last->next = line;
-	    dbgPrintf("readConfig added %s to cfg\n", getKeyByType(line->type, cfi));
+		last = line;
 	}
 
-	last = line;
-    }
-
-    free(incoming);
+	free(incoming);
+
+	dbgPrintf("defaultLine is %s\n", defaultLine ? "set" : "unset");
+	if (defaultLine) {
+		if (defaultLine->numElements > 2 &&
+		    cfi->defaultSupportSaved &&
+		    !strncmp(defaultLine->elements[2].item,
+			     "\"${saved_entry}\"", 16)) {
+			cfg->cfi->defaultIsSaved = 1;
+			cfg->defaultImage = DEFAULT_SAVED_GRUB2;
+			if (cfg->cfi->getEnv) {
+				char *defTitle =
+				    cfi->getEnv(cfg->cfi, "saved_entry");
+				if (defTitle) {
+					int index = 0;
+					if (isnumber(defTitle)) {
+						index = atoi(defTitle);
+						entry =
+						    findEntryByIndex(cfg,
+								     index);
+					} else {
+						entry =
+						    findEntryByTitle(cfg,
+								     defTitle,
+								     &index);
+					}
+					if (entry)
+						cfg->defaultImage = index;
+				}
+			}
+		} else if (cfi->defaultIsVariable) {
+			char *value = defaultLine->elements[2].item;
+			while (*value && (*value == '"' || *value == '\'' ||
+					  *value == ' ' || *value == '\t'))
+				value++;
+			cfg->defaultImage = strtol(value, &end, 10);
+			while (*end && (*end == '"' || *end == '\'' ||
+					*end == ' ' || *end == '\t'))
+				end++;
+			if (*end)
+				cfg->defaultImage = -1;
+		} else if (cfi->defaultSupportSaved &&
+			   !strncmp(defaultLine->elements[1].item, "saved",
+				    5)) {
+			cfg->defaultImage = DEFAULT_SAVED;
+		} else if (cfi->defaultIsIndex) {
+			cfg->defaultImage =
+			    strtol(defaultLine->elements[1].item, &end, 10);
+			if (*end)
+				cfg->defaultImage = -1;
+		} else if (defaultLine->numElements >= 2) {
+			int i = 0;
+			while ((entry = findEntryByIndex(cfg, i))) {
+				for (line = entry->lines; line;
+				     line = line->next)
+					if (line->type == LT_TITLE)
+						break;
+
+				if (!cfi->titleBracketed) {
+					if (line && (line->numElements >= 2) &&
+					    !strcmp(defaultLine->elements[1].
+						    item,
+						    line->elements[1].item))
+						break;
+				} else if (line) {
+					if (!strcmp
+					    (defaultLine->elements[1].item,
+					     extractTitle(cfg, line)))
+						break;
+				}
+				i++;
+				entry = NULL;
+			}
 
-    dbgPrintf("defaultLine is %s\n", defaultLine ? "set" : "unset");
-    if (defaultLine) {
-        if (defaultLine->numElements > 2 &&
-	    cfi->defaultSupportSaved &&
-	    !strncmp(defaultLine->elements[2].item,"\"${saved_entry}\"", 16)) {
-		cfg->cfi->defaultIsSaved = 1;
-		cfg->defaultImage = DEFAULT_SAVED_GRUB2;
-		if (cfg->cfi->getEnv) {
-		    char *defTitle = cfi->getEnv(cfg->cfi, "saved_entry");
-		    if (defTitle) {
+			if (entry) {
+				cfg->defaultImage = i;
+			} else {
+				cfg->defaultImage = -1;
+			}
+		}
+	} else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) {
+		char *defTitle = cfi->getEnv(cfg->cfi, "saved_entry");
+		if (defTitle) {
 			int index = 0;
 			if (isnumber(defTitle)) {
-			    index = atoi(defTitle);
-			    entry = findEntryByIndex(cfg, index);
+				index = atoi(defTitle);
+				entry = findEntryByIndex(cfg, index);
 			} else {
-			    entry = findEntryByTitle(cfg, defTitle, &index);
+				entry = findEntryByTitle(cfg, defTitle, &index);
 			}
 			if (entry)
-			    cfg->defaultImage = index;
-		    }
+				cfg->defaultImage = index;
 		}
-	} else if (cfi->defaultIsVariable) {
-	    char *value = defaultLine->elements[2].item;
-	    while (*value && (*value == '"' || *value == '\'' ||
-		    *value == ' ' || *value == '\t'))
-		value++;
-	    cfg->defaultImage = strtol(value, &end, 10);
-	    while (*end && (*end == '"' || *end == '\'' ||
-		    *end == ' ' || *end == '\t'))
-		end++;
-	    if (*end) cfg->defaultImage = -1;
-	} else if (cfi->defaultSupportSaved && 
-		!strncmp(defaultLine->elements[1].item, "saved", 5)) {
-	    cfg->defaultImage = DEFAULT_SAVED;
-	} else if (cfi->defaultIsIndex) {
-	    cfg->defaultImage = strtol(defaultLine->elements[1].item, &end, 10);
-	    if (*end) cfg->defaultImage = -1;
-	} else if (defaultLine->numElements >= 2) {
-	    int i = 0;
-	    while ((entry = findEntryByIndex(cfg, i))) {
-		for (line = entry->lines; line; line = line->next)
-		    if (line->type == LT_TITLE) break;
-
-                if (!cfi->titleBracketed) {
-                    if (line && (line->numElements >= 2) && 
-                        !strcmp(defaultLine->elements[1].item,
-                                line->elements[1].item)) break;
-                } else if (line) {
-                    if (!strcmp(defaultLine->elements[1].item, 
-                                extractTitle(cfg, line))) break;
-                }
-		i++;
-		entry = NULL;
-	    }
-
-	    if (entry){
-	        cfg->defaultImage = i;
-	    }else{
-	        cfg->defaultImage = -1;
-	    }
-	}
-    } else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) {
-	char *defTitle = cfi->getEnv(cfg->cfi, "saved_entry");
-	if (defTitle) {
-	    int index = 0;
-	    if (isnumber(defTitle)) {
-		index = atoi(defTitle);
-		entry = findEntryByIndex(cfg, index);
-	    } else {
-		entry = findEntryByTitle(cfg, defTitle, &index);
-	    }
-	    if (entry)
-		cfg->defaultImage = index;
-	}
-    } else {
-        cfg->defaultImage = 0;
-    }
-
-    return cfg;
+	} else {
+		cfg->defaultImage = 0;
+	}
+
+	return cfg;
 }
 
-static void writeDefault(FILE * out, char * indent,
-			 char * separator, struct grubConfig * cfg) {
-    struct singleEntry * entry;
-    struct singleLine * line;
-    int i;
-
-    if (!cfg->defaultImage && cfg->flags == GRUB_CONFIG_NO_DEFAULT)
-	return;
-
-    if (cfg->defaultImage == DEFAULT_SAVED)
-	fprintf(out, "%sdefault%ssaved\n", indent, separator);
-    else if (cfg->cfi->defaultIsSaved) {
-	fprintf(out, "%sset default=\"${saved_entry}\"\n", indent);
-	if (cfg->defaultImage >= 0 && cfg->cfi->setEnv) {
-	    char *title;
-	    entry = findEntryByIndex(cfg, cfg->defaultImage);
-	    line = getLineByType(LT_MENUENTRY, entry->lines);
-	    if (!line)
-		line = getLineByType(LT_TITLE, entry->lines);
-	    if (line) {
-		title = extractTitle(cfg, line);
-		if (title)
-		    cfg->cfi->setEnv(cfg->cfi, "saved_entry", title);
-	    }
-	}
-    } else if (cfg->defaultImage > -1) {
-	if (cfg->cfi->defaultIsIndex) {
-	    if (cfg->cfi->defaultIsVariable) {
-	        fprintf(out, "%sset default=\"%d\"\n", indent,
-			cfg->defaultImage);
-	    } else {
-		fprintf(out, "%sdefault%s%d\n", indent, separator,
-			cfg->defaultImage);
-	    }
-	} else {
-	    int image = cfg->defaultImage;
+static void writeDefault(FILE * out, char *indent,
+			 char *separator, struct grubConfig *cfg)
+{
+	struct singleEntry *entry;
+	struct singleLine *line;
+	int i;
 
-	    entry = cfg->entries;
-	    while (entry && entry->skip)
-		entry = entry->next;
+	if (!cfg->defaultImage && cfg->flags == GRUB_CONFIG_NO_DEFAULT)
+		return;
 
-	    i = 0;
-	    while (entry && i < image) {
-		entry = entry->next;
+	if (cfg->defaultImage == DEFAULT_SAVED)
+		fprintf(out, "%sdefault%ssaved\n", indent, separator);
+	else if (cfg->cfi->defaultIsSaved) {
+		fprintf(out, "%sset default=\"${saved_entry}\"\n", indent);
+		if (cfg->defaultImage >= 0 && cfg->cfi->setEnv) {
+			char *title;
+			entry = findEntryByIndex(cfg, cfg->defaultImage);
+			line = getLineByType(LT_MENUENTRY, entry->lines);
+			if (!line)
+				line = getLineByType(LT_TITLE, entry->lines);
+			if (line) {
+				title = extractTitle(cfg, line);
+				if (title)
+					cfg->cfi->setEnv(cfg->cfi,
+							 "saved_entry", title);
+			}
+		}
+	} else if (cfg->defaultImage > -1) {
+		if (cfg->cfi->defaultIsIndex) {
+			if (cfg->cfi->defaultIsVariable) {
+				fprintf(out, "%sset default=\"%d\"\n", indent,
+					cfg->defaultImage);
+			} else {
+				fprintf(out, "%sdefault%s%d\n", indent,
+					separator, cfg->defaultImage);
+			}
+		} else {
+			int image = cfg->defaultImage;
 
-		while (entry && entry->skip)
-		    entry = entry->next;
-		i++;
-	    }
+			entry = cfg->entries;
+			while (entry && entry->skip)
+				entry = entry->next;
 
-	    if (!entry)
-		return;
+			i = 0;
+			while (entry && i < image) {
+				entry = entry->next;
 
-	    line = getLineByType(LT_TITLE, entry->lines);
+				while (entry && entry->skip)
+					entry = entry->next;
+				i++;
+			}
 
-	    if (line && line->numElements >= 2)
-		fprintf(out, "%sdefault%s%s\n", indent, separator,
-			line->elements[1].item);
-            else if (line && (line->numElements == 1) &&
-                     cfg->cfi->titleBracketed) {
-		char *title = extractTitle(cfg, line);
-		if (title) {
-		    fprintf(out, "%sdefault%s%s\n", indent, separator, title);
-		    free(title);
+			if (!entry)
+				return;
+
+			line = getLineByType(LT_TITLE, entry->lines);
+
+			if (line && line->numElements >= 2)
+				fprintf(out, "%sdefault%s%s\n", indent,
+					separator, line->elements[1].item);
+			else if (line && (line->numElements == 1)
+				 && cfg->cfi->titleBracketed) {
+				char *title = extractTitle(cfg, line);
+				if (title) {
+					fprintf(out, "%sdefault%s%s\n", indent,
+						separator, title);
+					free(title);
+				}
+			}
 		}
-            }
 	}
-    }
 }
 
-static int writeConfig(struct grubConfig * cfg, char * outName, 
-		       const char * prefix) {
-    FILE * out;
-    struct singleLine * line;
-    struct singleEntry * entry;
-    char * tmpOutName;
-    int needs = MAIN_DEFAULT;
-    struct stat sb;
-    int i;
-
-    if (!strcmp(outName, "-")) {
-	out = stdout;
-	tmpOutName = NULL;
-    } else {
-	if (!lstat(outName, &sb) && S_ISLNK(sb.st_mode)) {
-	    char * buf;
-	    int len = 256;
-	    int rc;
-
-	    /* most likely the symlink is relative, so change our
-	       directory to the dir of the symlink */
-	    char *dir = strdupa(outName);
-	    rc = chdir(dirname(dir));
-	    do {
-		buf = alloca(len + 1);
-		rc = readlink(basename(outName), buf, len);
-		if (rc == len) len += 256;
-	    } while (rc == len);
-	    
-	    if (rc < 0) {
-		fprintf(stderr, _("grubby: error readlink link %s: %s\n"), 
-			outName, strerror(errno));
-		return 1;
-	    }
-
-	    outName = buf;
-	    outName[rc] = '\0';
-	}
-
-	tmpOutName = alloca(strlen(outName) + 2);
-	sprintf(tmpOutName, "%s-", outName);
-	out = fopen(tmpOutName, "w");
-	if (!out) {
-	    fprintf(stderr, _("grubby: error creating %s: %s\n"), tmpOutName, 
-		    strerror(errno));
-	    return 1;
-	}
-
-	if (!stat(outName, &sb)) {
-	    if (chmod(tmpOutName, sb.st_mode & ~(S_IFMT))) {
-		fprintf(stderr, _("grubby: error setting perms on %s: %s\n"),
-		        tmpOutName, strerror(errno));
-		fclose(out);
-		unlink(tmpOutName);
-                return 1;
-	    }
-	} 
-    }
-
-    line = cfg->theLines;
-    struct keywordTypes *defaultKw = getKeywordByType(LT_DEFAULT, cfg->cfi);
-    while (line) {
-        if (line->type == LT_SET_VARIABLE && defaultKw &&
-		line->numElements == 3 &&
-		!strcmp(line->elements[1].item, defaultKw->key) &&
-		!is_special_grub2_variable(line->elements[2].item)) {
-	    writeDefault(out, line->indent, line->elements[0].indent, cfg);
-	    needs &= ~MAIN_DEFAULT;
-	} else if (line->type == LT_DEFAULT) {
-	    writeDefault(out, line->indent, line->elements[0].indent, cfg);
-	    needs &= ~MAIN_DEFAULT;
-	} else if (line->type == LT_FALLBACK) {
-	    if (cfg->fallbackImage > -1)
-		fprintf(out, "%s%s%s%d\n", line->indent, 
-			line->elements[0].item, line->elements[0].indent,
-			cfg->fallbackImage);
+static int writeConfig(struct grubConfig *cfg, char *outName,
+		       const char *prefix)
+{
+	FILE *out;
+	struct singleLine *line;
+	struct singleEntry *entry;
+	char *tmpOutName;
+	int needs = MAIN_DEFAULT;
+	struct stat sb;
+	int i;
+
+	if (!strcmp(outName, "-")) {
+		out = stdout;
+		tmpOutName = NULL;
 	} else {
-	    if (lineWrite(out, line, cfg->cfi) == -1) {
-                fprintf(stderr, _("grubby: error writing %s: %s\n"),
-                        tmpOutName, strerror(errno));
-                fclose(out);
-                unlink(tmpOutName);
-                return 1;
-            }
-	}
+		if (!lstat(outName, &sb) && S_ISLNK(sb.st_mode)) {
+			char *buf;
+			int len = 256;
+			int rc;
+
+			/* most likely the symlink is relative, so change our
+			   directory to the dir of the symlink */
+			char *dir = strdupa(outName);
+			rc = chdir(dirname(dir));
+			do {
+				buf = alloca(len + 1);
+				rc = readlink(basename(outName), buf, len);
+				if (rc == len)
+					len += 256;
+			} while (rc == len);
+
+			if (rc < 0) {
+				fprintf(stderr,
+					_
+					("grubby: error readlink link %s: %s\n"),
+					outName, strerror(errno));
+				return 1;
+			}
 
-	line = line->next;
-    }
+			outName = buf;
+			outName[rc] = '\0';
+		}
 
-    if (needs & MAIN_DEFAULT) {
-	writeDefault(out, cfg->primaryIndent, "=", cfg);
-	needs &= ~MAIN_DEFAULT;
-    }
+		tmpOutName = alloca(strlen(outName) + 2);
+		sprintf(tmpOutName, "%s-", outName);
+		out = fopen(tmpOutName, "w");
+		if (!out) {
+			fprintf(stderr, _("grubby: error creating %s: %s\n"),
+				tmpOutName, strerror(errno));
+			return 1;
+		}
 
-    i = 0;
-    while ((entry = findEntryByIndex(cfg, i++))) {
-	if (entry->skip) continue;
+		if (!stat(outName, &sb)) {
+			if (chmod(tmpOutName, sb.st_mode & ~(S_IFMT))) {
+				fprintf(stderr,
+					_
+					("grubby: error setting perms on %s: %s\n"),
+					tmpOutName, strerror(errno));
+				fclose(out);
+				unlink(tmpOutName);
+				return 1;
+			}
+		}
+	}
 
-	line = entry->lines;
+	line = cfg->theLines;
+	struct keywordTypes *defaultKw = getKeywordByType(LT_DEFAULT, cfg->cfi);
 	while (line) {
-	    if (lineWrite(out, line, cfg->cfi) == -1) {
-                fprintf(stderr, _("grubby: error writing %s: %s\n"),
-                        tmpOutName, strerror(errno));
-                fclose(out);
-                unlink(tmpOutName);
-                return 1;
-            }
-	    line = line->next;
-	}
-    }
-
-    if (tmpOutName) {
-	if (rename(tmpOutName, outName)) {
-	    fprintf(stderr, _("grubby: error moving %s to %s: %s\n"),
-		    tmpOutName, outName, strerror(errno));
-	    unlink(outName);
-            return 1;
-	}
-    }
-
-    return 0;
-}
-
-static int numEntries(struct grubConfig *cfg) {
-    int i = 0;
-    struct singleEntry * entry;
-
-    entry = cfg->entries;
-    while (entry) {
-        if (!entry->skip)
-            i++;
-        entry = entry->next;
-    }
-    return i;
-}
+		if (line->type == LT_SET_VARIABLE && defaultKw &&
+		    line->numElements == 3 &&
+		    !strcmp(line->elements[1].item, defaultKw->key) &&
+		    !is_special_grub2_variable(line->elements[2].item)) {
+			writeDefault(out, line->indent,
+				     line->elements[0].indent, cfg);
+			needs &= ~MAIN_DEFAULT;
+		} else if (line->type == LT_DEFAULT) {
+			writeDefault(out, line->indent,
+				     line->elements[0].indent, cfg);
+			needs &= ~MAIN_DEFAULT;
+		} else if (line->type == LT_FALLBACK) {
+			if (cfg->fallbackImage > -1)
+				fprintf(out, "%s%s%s%d\n", line->indent,
+					line->elements[0].item,
+					line->elements[0].indent,
+					cfg->fallbackImage);
+		} else {
+			if (lineWrite(out, line, cfg->cfi) == -1) {
+				fprintf(stderr,
+					_("grubby: error writing %s: %s\n"),
+					tmpOutName, strerror(errno));
+				fclose(out);
+				unlink(tmpOutName);
+				return 1;
+			}
+		}
 
-static char *findDiskForRoot()
-{
-    int fd;
-    char buf[65536];
-    char *devname;
-    char *chptr;
-    int rc;
-
-    if ((fd = open(_PATH_MOUNTED, O_RDONLY)) < 0) {
-        fprintf(stderr, "grubby: failed to open %s: %s\n",
-                _PATH_MOUNTED, strerror(errno));
-        return NULL;
-    }
-
-    rc = read(fd, buf, sizeof(buf) - 1);
-    if (rc <= 0) {
-        fprintf(stderr, "grubby: failed to read %s: %s\n",
-                _PATH_MOUNTED, strerror(errno));
-        close(fd);
-        return NULL;
-    }
-    close(fd);
-    buf[rc] = '\0';
-    chptr = buf;
-
-    char *foundanswer = NULL;
-
-    while (chptr && chptr != buf+rc) {
-        devname = chptr;
-
-        /*
-         * The first column of a mtab entry is the device, but if the entry is a
-         * special device it won't start with /, so move on to the next line.
-         */
-        if (*devname != '/') {
-            chptr = strchr(chptr, '\n');
-            if (chptr)
-                chptr++;
-            continue;
-        }
-
-        /* Seek to the next space */
-        chptr = strchr(chptr, ' ');
-        if (!chptr) {
-            fprintf(stderr, "grubby: error parsing %s: %s\n",
-                    _PATH_MOUNTED, strerror(errno));
-            return NULL;
-        }
-
-        /*
-         * The second column of a mtab entry is the mount point, we are looking
-         * for '/' obviously.
-         */
-        if (*(++chptr) == '/' && *(++chptr) == ' ') {
-            /* remember the last / entry in mtab */
-           foundanswer = devname;
-        }
-
-        /* Next line */
-        chptr = strchr(chptr, '\n');
-        if (chptr)
-            chptr++;
-    }
-
-    /* Return the last / entry found */
-    if (foundanswer) {
-        chptr = strchr(foundanswer, ' ');
-        *chptr = '\0';
-        return strdup(foundanswer);
-    }
-
-    return NULL;
-}
+		line = line->next;
+	}
 
-void printEntry(struct singleEntry * entry, FILE *f) {
-    int i;
-    struct singleLine * line;
+	if (needs & MAIN_DEFAULT) {
+		writeDefault(out, cfg->primaryIndent, "=", cfg);
+		needs &= ~MAIN_DEFAULT;
+	}
 
-    for (line = entry->lines; line; line = line->next) {
-	log_message(f, "DBG: %s", line->indent);
-	for (i = 0; i < line->numElements; i++) {
-	    /* Need to handle this, because we strip the quotes from
-	     * menuentry when read it. */
-	    if (line->type == LT_MENUENTRY && i == 1) {
-		if(!isquote(*line->elements[i].item))
-		    log_message(f, "\'%s\'", line->elements[i].item);
-		else
-		    log_message(f, "%s", line->elements[i].item);
-		log_message(f, "%s", line->elements[i].indent);
-		
-		continue;
-	    }
-	    
-	    log_message(f, "%s%s",
-		    line->elements[i].item, line->elements[i].indent);
-	}
-	log_message(f, "\n");
-    }
+	i = 0;
+	while ((entry = findEntryByIndex(cfg, i++))) {
+		if (entry->skip)
+			continue;
+
+		line = entry->lines;
+		while (line) {
+			if (lineWrite(out, line, cfg->cfi) == -1) {
+				fprintf(stderr,
+					_("grubby: error writing %s: %s\n"),
+					tmpOutName, strerror(errno));
+				fclose(out);
+				unlink(tmpOutName);
+				return 1;
+			}
+			line = line->next;
+		}
+	}
+
+	if (tmpOutName) {
+		if (rename(tmpOutName, outName)) {
+			fprintf(stderr,
+				_("grubby: error moving %s to %s: %s\n"),
+				tmpOutName, outName, strerror(errno));
+			unlink(outName);
+			return 1;
+		}
+	}
+
+	return 0;
 }
 
-void notSuitablePrintf(struct singleEntry * entry, int okay, const char *fmt, ...)
+static int numEntries(struct grubConfig *cfg)
 {
-    static int once;
-    va_list argp, argq;
-
-    va_start(argp, fmt);
-
-    va_copy(argq, argp);
-    if (!once) {
-	log_time(NULL);
-	log_message(NULL, "command line: %s\n", saved_command_line);
-    }
-    log_message(NULL, "DBG: Image entry %s: ", okay ? "succeeded" : "failed");
-    log_vmessage(NULL, fmt, argq);
-	
-    printEntry(entry, NULL);
-    va_end(argq);
-
-    if (!debug) {
-	once = 1;
-    	va_end(argp);
-	return;
-    }
+	int i = 0;
+	struct singleEntry *entry;
+
+	entry = cfg->entries;
+	while (entry) {
+		if (!entry->skip)
+			i++;
+		entry = entry->next;
+	}
+	return i;
+}
+
+static char *findDiskForRoot()
+{
+	int fd;
+	char buf[65536];
+	char *devname;
+	char *chptr;
+	int rc;
+
+	if ((fd = open(_PATH_MOUNTED, O_RDONLY)) < 0) {
+		fprintf(stderr, "grubby: failed to open %s: %s\n",
+			_PATH_MOUNTED, strerror(errno));
+		return NULL;
+	}
+
+	rc = read(fd, buf, sizeof(buf) - 1);
+	if (rc <= 0) {
+		fprintf(stderr, "grubby: failed to read %s: %s\n",
+			_PATH_MOUNTED, strerror(errno));
+		close(fd);
+		return NULL;
+	}
+	close(fd);
+	buf[rc] = '\0';
+	chptr = buf;
+
+	char *foundanswer = NULL;
+
+	while (chptr && chptr != buf + rc) {
+		devname = chptr;
+
+		/*
+		 * The first column of a mtab entry is the device, but if the entry is a
+		 * special device it won't start with /, so move on to the next line.
+		 */
+		if (*devname != '/') {
+			chptr = strchr(chptr, '\n');
+			if (chptr)
+				chptr++;
+			continue;
+		}
+
+		/* Seek to the next space */
+		chptr = strchr(chptr, ' ');
+		if (!chptr) {
+			fprintf(stderr, "grubby: error parsing %s: %s\n",
+				_PATH_MOUNTED, strerror(errno));
+			return NULL;
+		}
+
+		/*
+		 * The second column of a mtab entry is the mount point, we are looking
+		 * for '/' obviously.
+		 */
+		if (*(++chptr) == '/' && *(++chptr) == ' ') {
+			/* remember the last / entry in mtab */
+			foundanswer = devname;
+		}
+
+		/* Next line */
+		chptr = strchr(chptr, '\n');
+		if (chptr)
+			chptr++;
+	}
+
+	/* Return the last / entry found */
+	if (foundanswer) {
+		chptr = strchr(foundanswer, ' ');
+		*chptr = '\0';
+		return strdup(foundanswer);
+	}
+
+	return NULL;
+}
+
+void printEntry(struct singleEntry *entry, FILE * f)
+{
+	int i;
+	struct singleLine *line;
+
+	for (line = entry->lines; line; line = line->next) {
+		log_message(f, "DBG: %s", line->indent);
+		for (i = 0; i < line->numElements; i++) {
+			/* Need to handle this, because we strip the quotes from
+			 * menuentry when read it. */
+			if (line->type == LT_MENUENTRY && i == 1) {
+				if (!isquote(*line->elements[i].item))
+					log_message(f, "\'%s\'",
+						    line->elements[i].item);
+				else
+					log_message(f, "%s",
+						    line->elements[i].item);
+				log_message(f, "%s", line->elements[i].indent);
+
+				continue;
+			}
+
+			log_message(f, "%s%s",
+				    line->elements[i].item,
+				    line->elements[i].indent);
+		}
+		log_message(f, "\n");
+	}
+}
 
-    if (okay) {
+void notSuitablePrintf(struct singleEntry *entry, int okay, const char *fmt,
+		       ...)
+{
+	static int once;
+	va_list argp, argq;
+
+	va_start(argp, fmt);
+
+	va_copy(argq, argp);
+	if (!once) {
+		log_time(NULL);
+		log_message(NULL, "command line: %s\n", saved_command_line);
+	}
+	log_message(NULL, "DBG: Image entry %s: ",
+		    okay ? "succeeded" : "failed");
+	log_vmessage(NULL, fmt, argq);
+
+	printEntry(entry, NULL);
+	va_end(argq);
+
+	if (!debug) {
+		once = 1;
+		va_end(argp);
+		return;
+	}
+
+	if (okay) {
+		va_end(argp);
+		return;
+	}
+
+	if (!once)
+		log_message(stderr, "DBG: command line: %s\n",
+			    saved_command_line);
+	once = 1;
+	fprintf(stderr, "DBG: Image entry failed: ");
+	vfprintf(stderr, fmt, argp);
+	printEntry(entry, stderr);
 	va_end(argp);
-	return;
-    }
-
-    if (!once)
-	log_message(stderr, "DBG: command line: %s\n", saved_command_line);
-    once = 1;
-    fprintf(stderr, "DBG: Image entry failed: ");
-    vfprintf(stderr, fmt, argp);
-    printEntry(entry, stderr);
-    va_end(argp);
 }
 
 #define beginswith(s, c) ((s) && (s)[0] == (c))
@@ -1860,281 +1979,317 @@ static int endswith(const char *s, char c)
 	return s[slen] == c;
 }
 
-int suitableImage(struct singleEntry * entry, const char * bootPrefix,
-		  int skipRemoved, int flags) {
-    struct singleLine * line;
-    char * fullName;
-    int i;
-    char * dev;
-    char * rootspec;
-    char * rootdev;
-
-    if (skipRemoved && entry->skip) {
-	notSuitablePrintf(entry, 0, "marked to skip\n");
-	return 0;
-    }
+int suitableImage(struct singleEntry *entry, const char *bootPrefix,
+		  int skipRemoved, int flags)
+{
+	struct singleLine *line;
+	char *fullName;
+	int i;
+	char *dev;
+	char *rootspec;
+	char *rootdev;
+
+	if (skipRemoved && entry->skip) {
+		notSuitablePrintf(entry, 0, "marked to skip\n");
+		return 0;
+	}
 
-    line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines);
-    if (!line) {
-	notSuitablePrintf(entry, 0, "no line found\n");
-	return 0;
-    }
-    if (line->numElements < 2) {
-	notSuitablePrintf(entry, 0, "line has only %d elements\n",
-	    line->numElements);
-	return 0;
-    }
-
-    if (flags & GRUBBY_BADIMAGE_OKAY) {
-	    notSuitablePrintf(entry, 1, "\n");
-	    return 1;
-    }
-
-    fullName = alloca(strlen(bootPrefix) + 
-		      strlen(line->elements[1].item) + 1);
-    rootspec = getRootSpecifier(line->elements[1].item);
-    int rootspec_offset = rootspec ? strlen(rootspec) : 0;
-    int hasslash = endswith(bootPrefix, '/') ||
-    	beginswith(line->elements[1].item + rootspec_offset, '/');
-    sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/",
-            line->elements[1].item + rootspec_offset);
-    if (access(fullName, R_OK)) {
-	notSuitablePrintf(entry, 0, "access to %s failed\n", fullName);
-	return 0;
-    }
-    for (i = 2; i < line->numElements; i++) 
-	if (!strncasecmp(line->elements[i].item, "root=", 5)) break;
-    if (i < line->numElements) {
-	dev = line->elements[i].item + 5;
-    } else {
-	/* look for a lilo style LT_ROOT line */
-	line = getLineByType(LT_ROOT, entry->lines);
+	line =
+	    getLineByType(LT_KERNEL | LT_HYPER | LT_KERNEL_EFI | LT_KERNEL_16,
+			  entry->lines);
+	if (!line) {
+		notSuitablePrintf(entry, 0, "no line found\n");
+		return 0;
+	}
+	if (line->numElements < 2) {
+		notSuitablePrintf(entry, 0, "line has only %d elements\n",
+				  line->numElements);
+		return 0;
+	}
 
-	if (line && line->numElements >= 2) {
-	    dev = line->elements[1].item;
-	} else {
-	    /* didn't succeed in finding a LT_ROOT, let's try LT_KERNELARGS.
-	     * grub+multiboot uses LT_MBMODULE for the args, so check that too.
-	     */
-	    line = getLineByType(LT_KERNELARGS|LT_MBMODULE, entry->lines);
+	if (flags & GRUBBY_BADIMAGE_OKAY) {
+		notSuitablePrintf(entry, 1, "\n");
+		return 1;
+	}
 
-            /* failed to find one */
-            if (!line) {
-		notSuitablePrintf(entry, 0, "no line found\n");
+	fullName = alloca(strlen(bootPrefix) +
+			  strlen(line->elements[1].item) + 1);
+	rootspec = getRootSpecifier(line->elements[1].item);
+	int rootspec_offset = rootspec ? strlen(rootspec) : 0;
+	int hasslash = endswith(bootPrefix, '/') ||
+	    beginswith(line->elements[1].item + rootspec_offset, '/');
+	sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/",
+		line->elements[1].item + rootspec_offset);
+	if (access(fullName, R_OK)) {
+		notSuitablePrintf(entry, 0, "access to %s failed\n", fullName);
 		return 0;
-            }
-
-	    for (i = 1; i < line->numElements; i++) 
-	        if (!strncasecmp(line->elements[i].item, "root=", 5)) break;
-	    if (i < line->numElements)
-	        dev = line->elements[i].item + 5;
-	    else {
-		notSuitablePrintf(entry, 0, "no root= entry found\n");
-		/* it failed too...  can't find root= */
-	        return 0;
-            }
-	}
-    }
-
-    dev = getpathbyspec(dev);
-    if (!getpathbyspec(dev)) {
-        notSuitablePrintf(entry, 0, "can't find blkid entry for %s\n", dev);
-        return 0;
-    } else
+	}
+	for (i = 2; i < line->numElements; i++)
+		if (!strncasecmp(line->elements[i].item, "root=", 5))
+			break;
+	if (i < line->numElements) {
+		dev = line->elements[i].item + 5;
+	} else {
+		/* look for a lilo style LT_ROOT line */
+		line = getLineByType(LT_ROOT, entry->lines);
+
+		if (line && line->numElements >= 2) {
+			dev = line->elements[1].item;
+		} else {
+			/* didn't succeed in finding a LT_ROOT, let's try LT_KERNELARGS.
+			 * grub+multiboot uses LT_MBMODULE for the args, so check that too.
+			 */
+			line =
+			    getLineByType(LT_KERNELARGS | LT_MBMODULE,
+					  entry->lines);
+
+			/* failed to find one */
+			if (!line) {
+				notSuitablePrintf(entry, 0, "no line found\n");
+				return 0;
+			}
+
+			for (i = 1; i < line->numElements; i++)
+				if (!strncasecmp
+				    (line->elements[i].item, "root=", 5))
+					break;
+			if (i < line->numElements)
+				dev = line->elements[i].item + 5;
+			else {
+				notSuitablePrintf(entry, 0,
+						  "no root= entry found\n");
+				/* it failed too...  can't find root= */
+				return 0;
+			}
+		}
+	}
+
 	dev = getpathbyspec(dev);
+	if (!getpathbyspec(dev)) {
+		notSuitablePrintf(entry, 0, "can't find blkid entry for %s\n",
+				  dev);
+		return 0;
+	} else
+		dev = getpathbyspec(dev);
 
-    rootdev = findDiskForRoot();
-    if (!rootdev) {
-        notSuitablePrintf(entry, 0, "can't find root device\n");
-	return 0;
-    }
-
-    if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) {
-        notSuitablePrintf(entry, 0, "uuid missing: rootdev %s, dev %s\n",
-		getuuidbydev(rootdev), getuuidbydev(dev));
-        free(rootdev);
-        return 0;
-    }
-
-    if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) {
-        notSuitablePrintf(entry, 0, "uuid mismatch: rootdev %s, dev %s\n",
-		getuuidbydev(rootdev), getuuidbydev(dev));
-	free(rootdev);
-        return 0;
-    }
+	rootdev = findDiskForRoot();
+	if (!rootdev) {
+		notSuitablePrintf(entry, 0, "can't find root device\n");
+		return 0;
+	}
 
-    free(rootdev);
-    notSuitablePrintf(entry, 1, "\n");
+	if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) {
+		notSuitablePrintf(entry, 0,
+				  "uuid missing: rootdev %s, dev %s\n",
+				  getuuidbydev(rootdev), getuuidbydev(dev));
+		free(rootdev);
+		return 0;
+	}
+
+	if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) {
+		notSuitablePrintf(entry, 0,
+				  "uuid mismatch: rootdev %s, dev %s\n",
+				  getuuidbydev(rootdev), getuuidbydev(dev));
+		free(rootdev);
+		return 0;
+	}
+
+	free(rootdev);
+	notSuitablePrintf(entry, 1, "\n");
 
-    return 1;
+	return 1;
 }
 
 /* returns the first match on or after the one pointed to by index (if index 
    is not NULL) which is not marked as skip */
-struct singleEntry * findEntryByPath(struct grubConfig * config, 
-				     const char * kernel, const char * prefix,
-				     int * index) {
-    struct singleEntry * entry = NULL;
-    struct singleLine * line;
-    int i;
-    char * chptr;
-    char * rootspec = NULL;
-    enum lineType_e checkType = LT_KERNEL;
-
-    if (isdigit(*kernel)) {
-	int * indexVars = alloca(sizeof(*indexVars) * strlen(kernel));
-
-	i = 0;
-	indexVars[i] = strtol(kernel, &chptr, 10);
-	while (*chptr == ',') {
-	    i++;
-	    kernel = chptr + 1;
-	    indexVars[i] = strtol(kernel, &chptr, 10);
-	}
+struct singleEntry *findEntryByPath(struct grubConfig *config,
+				    const char *kernel, const char *prefix,
+				    int *index)
+{
+	struct singleEntry *entry = NULL;
+	struct singleLine *line;
+	int i;
+	char *chptr;
+	char *rootspec = NULL;
+	enum lineType_e checkType = LT_KERNEL;
+
+	if (isdigit(*kernel)) {
+		int *indexVars = alloca(sizeof(*indexVars) * strlen(kernel));
+
+		i = 0;
+		indexVars[i] = strtol(kernel, &chptr, 10);
+		while (*chptr == ',') {
+			i++;
+			kernel = chptr + 1;
+			indexVars[i] = strtol(kernel, &chptr, 10);
+		}
 
-	if (*chptr) {
-	    /* can't parse it, bail */
-	    return NULL;
-	}
+		if (*chptr) {
+			/* can't parse it, bail */
+			return NULL;
+		}
 
-	indexVars[i + 1] = -1;
+		indexVars[i + 1] = -1;
 
-	i = 0;
-	if (index) {
-	    while (i < *index) {
-		i++;
-		if (indexVars[i] == -1) return NULL;
-	    }
-	}
+		i = 0;
+		if (index) {
+			while (i < *index) {
+				i++;
+				if (indexVars[i] == -1)
+					return NULL;
+			}
+		}
 
-	entry = findEntryByIndex(config, indexVars[i]);
-	if (!entry) return NULL;
+		entry = findEntryByIndex(config, indexVars[i]);
+		if (!entry)
+			return NULL;
 
-	line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines);
-	if (!line) return NULL;
+		line =
+		    getLineByType(LT_KERNEL | LT_HYPER | LT_KERNEL_EFI |
+				  LT_KERNEL_16, entry->lines);
+		if (!line)
+			return NULL;
 
-	if (index) *index = indexVars[i];
-	return entry;
-    }
-    
-    if (!strcmp(kernel, "DEFAULT")) {
-	if (index && *index > config->defaultImage) {
-	    entry = NULL;
-	} else {
-	    entry = findEntryByIndex(config, config->defaultImage);
-	    if (entry && entry->skip) 
-		entry = NULL;
-	    else if (index) 
-		*index = config->defaultImage;
+		if (index)
+			*index = indexVars[i];
+		return entry;
 	}
-    } else if (!strcmp(kernel, "ALL")) {
-	if (index)
-	    i = *index;
-	else
-	    i = 0;
 
-	while ((entry = findEntryByIndex(config, i))) {
-	    if (!entry->skip) break;
-	    i++;
-	}
+	if (!strcmp(kernel, "DEFAULT")) {
+		if (index && *index > config->defaultImage) {
+			entry = NULL;
+		} else {
+			entry = findEntryByIndex(config, config->defaultImage);
+			if (entry && entry->skip)
+				entry = NULL;
+			else if (index)
+				*index = config->defaultImage;
+		}
+	} else if (!strcmp(kernel, "ALL")) {
+		if (index)
+			i = *index;
+		else
+			i = 0;
 
-	if (entry && index)
-	    *index = i;
-    } else {
-	if (index)
-	    i = *index;
-	else
-	    i = 0;
+		while ((entry = findEntryByIndex(config, i))) {
+			if (!entry->skip)
+				break;
+			i++;
+		}
 
-	if (!strncmp(kernel, "TITLE=", 6)) {
-	    prefix = "";
-	    checkType = LT_TITLE|LT_MENUENTRY;
-	    kernel += 6;
-	}
+		if (entry && index)
+			*index = i;
+	} else {
+		if (index)
+			i = *index;
+		else
+			i = 0;
 
-	for (entry = findEntryByIndex(config, i); entry; entry = entry->next, i++) {
-	    if (entry->skip) continue;
+		if (!strncmp(kernel, "TITLE=", 6)) {
+			prefix = "";
+			checkType = LT_TITLE | LT_MENUENTRY;
+			kernel += 6;
+		}
 
-	    dbgPrintf("findEntryByPath looking for %d %s in %p\n", checkType, kernel, entry);
+		for (entry = findEntryByIndex(config, i); entry;
+		     entry = entry->next, i++) {
+			if (entry->skip)
+				continue;
+
+			dbgPrintf("findEntryByPath looking for %d %s in %p\n",
+				  checkType, kernel, entry);
+
+			/* check all the lines matching checkType */
+			for (line = entry->lines; line; line = line->next) {
+				enum lineType_e ct = checkType;
+				if (entry->multiboot && checkType == LT_KERNEL)
+					ct = LT_KERNEL | LT_KERNEL_EFI |
+					    LT_MBMODULE | LT_HYPER |
+					    LT_KERNEL_16;
+				else if (checkType & LT_KERNEL)
+					ct = checkType | LT_KERNEL_EFI |
+					    LT_KERNEL_16;
+				line = getLineByType(ct, line);
+				if (!line)
+					break;	/* not found in this entry */
+
+				if (line && line->type != LT_MENUENTRY &&
+				    line->numElements >= 2) {
+					rootspec =
+					    getRootSpecifier(line->elements[1].
+							     item);
+					if (!strcmp
+					    (line->elements[1].item +
+					     ((rootspec !=
+					       NULL) ? strlen(rootspec) : 0),
+					     kernel + strlen(prefix)))
+						break;
+				}
+				if (line->type == LT_MENUENTRY &&
+				    !strcmp(line->elements[1].item, kernel))
+					break;
+			}
 
-	    /* check all the lines matching checkType */
-	    for (line = entry->lines; line; line = line->next) {
-		enum lineType_e ct = checkType;
-		if (entry->multiboot && checkType == LT_KERNEL)
-		    ct = LT_KERNEL|LT_KERNEL_EFI|LT_MBMODULE|LT_HYPER|LT_KERNEL_16;
-		else if (checkType & LT_KERNEL)
-		    ct = checkType | LT_KERNEL_EFI | LT_KERNEL_16;
-		line = getLineByType(ct, line);
-		if (!line)
-		    break;  /* not found in this entry */
-
-		if (line && line->type != LT_MENUENTRY &&
-			line->numElements >= 2) {
-		    rootspec = getRootSpecifier(line->elements[1].item);
-		    if (!strcmp(line->elements[1].item + 
-				((rootspec != NULL) ? strlen(rootspec) : 0),
-				kernel + strlen(prefix)))
-			break;
+			/* make sure this entry has a kernel identifier; this skips
+			 * non-Linux boot entries (could find netbsd etc, though, which is
+			 * unfortunate)
+			 */
+			if (line
+			    && getLineByType(LT_KERNEL | LT_HYPER |
+					     LT_KERNEL_EFI | LT_KERNEL_16,
+					     entry->lines))
+				break;	/* found 'im! */
 		}
-		if(line->type == LT_MENUENTRY &&
-			!strcmp(line->elements[1].item, kernel))
-		    break;
-	    }
 
-	    /* make sure this entry has a kernel identifier; this skips
-	     * non-Linux boot entries (could find netbsd etc, though, which is
-	     * unfortunate)
-	     */
-	    if (line && getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines))
-		break; /* found 'im! */
+		if (index)
+			*index = i;
 	}
 
-	if (index) *index = i;
-    }
-
-    return entry;
+	return entry;
 }
 
-struct singleEntry * findEntryByTitle(struct grubConfig * cfg, char *title,
-				      int * index) {
-    struct singleEntry * entry;
-    struct singleLine * line;
-    int i;
-    char * newtitle;
+struct singleEntry *findEntryByTitle(struct grubConfig *cfg, char *title,
+				     int *index)
+{
+	struct singleEntry *entry;
+	struct singleLine *line;
+	int i;
+	char *newtitle;
+
+	for (i = 0, entry = cfg->entries; entry; entry = entry->next, i++) {
+		if (index && i < *index)
+			continue;
+		line = getLineByType(LT_TITLE, entry->lines);
+		if (!line)
+			line = getLineByType(LT_MENUENTRY, entry->lines);
+		if (!line)
+			continue;
+		newtitle = grub2ExtractTitle(line);
+		if (!newtitle)
+			continue;
+		if (!strcmp(title, newtitle))
+			break;
+	}
 
-    for (i = 0, entry = cfg->entries; entry; entry = entry->next, i++) {
-	if (index && i < *index)
-	    continue;
-	line = getLineByType(LT_TITLE, entry->lines);
-	if (!line)
-	    line = getLineByType(LT_MENUENTRY, entry->lines);
-	if (!line)
-	    continue;
-	newtitle = grub2ExtractTitle(line);
-	if (!newtitle)
-	    continue;
-	if (!strcmp(title, newtitle))
-	    break;
-    }
-
-    if (!entry)
-	return NULL;
+	if (!entry)
+		return NULL;
 
-    if (index)
-	*index = i;
-    return entry;
+	if (index)
+		*index = i;
+	return entry;
 }
 
-struct singleEntry * findEntryByIndex(struct grubConfig * cfg, int index) {
-    struct singleEntry * entry;
+struct singleEntry *findEntryByIndex(struct grubConfig *cfg, int index)
+{
+	struct singleEntry *entry;
 
-    entry = cfg->entries;
-    while (index && entry) {
-	entry = entry->next;
-	index--;
-    }
+	entry = cfg->entries;
+	while (index && entry) {
+		entry = entry->next;
+		index--;
+	}
 
-    return entry;
+	return entry;
 }
 
 /* Find a good template to use for the new kernel. An entry is
@@ -2142,2550 +2297,2822 @@ struct singleEntry * findEntryByIndex(struct grubConfig * cfg, int index) {
  * is going to be removed). Try and use the default entry, but
  * if that doesn't work just take the first. If we can't find one,
  * bail. */
-struct singleEntry * findTemplate(struct grubConfig * cfg, const char * prefix,
-				 int * indexPtr, int skipRemoved, int flags) {
-    struct singleEntry * entry, * entry2;
-    int index;
-
-    if (cfg->cfi->defaultIsSaved) {
-	if (cfg->cfi->getEnv) {
-	    char *defTitle = cfg->cfi->getEnv(cfg->cfi, "saved_entry");
-	    if (defTitle) {
-		int index = 0;
-		if (isnumber(defTitle)) {
-		    index = atoi(defTitle);
-		    entry = findEntryByIndex(cfg, index);
-		} else {
-		    entry = findEntryByTitle(cfg, defTitle, &index);
+struct singleEntry *findTemplate(struct grubConfig *cfg, const char *prefix,
+				 int *indexPtr, int skipRemoved, int flags)
+{
+	struct singleEntry *entry, *entry2;
+	int index;
+
+	if (cfg->cfi->defaultIsSaved) {
+		if (cfg->cfi->getEnv) {
+			char *defTitle =
+			    cfg->cfi->getEnv(cfg->cfi, "saved_entry");
+			if (defTitle) {
+				int index = 0;
+				if (isnumber(defTitle)) {
+					index = atoi(defTitle);
+					entry = findEntryByIndex(cfg, index);
+				} else {
+					entry =
+					    findEntryByTitle(cfg, defTitle,
+							     &index);
+				}
+				if (entry
+				    && suitableImage(entry, prefix, skipRemoved,
+						     flags)) {
+					cfg->defaultImage = index;
+					if (indexPtr)
+						*indexPtr = index;
+					return entry;
+				}
+			}
 		}
+	} else if (cfg->defaultImage > -1) {
+		entry = findEntryByIndex(cfg, cfg->defaultImage);
 		if (entry && suitableImage(entry, prefix, skipRemoved, flags)) {
-		    cfg->defaultImage = index;
-		    if (indexPtr)
-			*indexPtr = index;
-		    return entry;
+			if (indexPtr)
+				*indexPtr = cfg->defaultImage;
+			return entry;
 		}
-	    }
 	}
-    } else if (cfg->defaultImage > -1) {
-	entry = findEntryByIndex(cfg, cfg->defaultImage);
-	if (entry && suitableImage(entry, prefix, skipRemoved, flags)) {
-	    if (indexPtr) *indexPtr = cfg->defaultImage;
-	    return entry;
-	}
-    }
 
-    index = 0;
-    while ((entry = findEntryByIndex(cfg, index))) {
-	if (suitableImage(entry, prefix, skipRemoved, flags)) {
-            int j;
-            for (j = 0; j < index; j++) {
-                entry2 = findEntryByIndex(cfg, j);
-                if (entry2->skip) index--;
-            }
-	    if (indexPtr) *indexPtr = index;
+	index = 0;
+	while ((entry = findEntryByIndex(cfg, index))) {
+		if (suitableImage(entry, prefix, skipRemoved, flags)) {
+			int j;
+			for (j = 0; j < index; j++) {
+				entry2 = findEntryByIndex(cfg, j);
+				if (entry2->skip)
+					index--;
+			}
+			if (indexPtr)
+				*indexPtr = index;
 
-	    return entry;
-	}
+			return entry;
+		}
 
-	index++;
-    }
+		index++;
+	}
 
-    fprintf(stderr, _("grubby fatal error: unable to find a suitable template\n"));
+	fprintf(stderr,
+		_("grubby fatal error: unable to find a suitable template\n"));
 
-    return NULL;
+	return NULL;
 }
 
-char * findBootPrefix(void) {
-    struct stat sb, sb2;
+char *findBootPrefix(void)
+{
+	struct stat sb, sb2;
 
-    stat("/", &sb);
+	stat("/", &sb);
 #ifdef __ia64__
-    stat("/boot/efi/EFI/redhat/", &sb2);
+	stat("/boot/efi/EFI/redhat/", &sb2);
 #else
-    stat("/boot", &sb2);
+	stat("/boot", &sb2);
 #endif
 
-    if (sb.st_dev == sb2.st_dev)
-	return strdup("");
+	if (sb.st_dev == sb2.st_dev)
+		return strdup("");
 
 #ifdef __ia64__
-    return strdup("/boot/efi/EFI/redhat/");
+	return strdup("/boot/efi/EFI/redhat/");
 #else
-    return strdup("/boot");
+	return strdup("/boot");
 #endif
 }
 
-void markRemovedImage(struct grubConfig * cfg, const char * image, 
-		      const char * prefix) {
-    struct singleEntry * entry;
+void markRemovedImage(struct grubConfig *cfg, const char *image,
+		      const char *prefix)
+{
+	struct singleEntry *entry;
 
-    if (!image)
-	return;
+	if (!image)
+		return;
 
-    /* check and see if we're removing the default image */
-    if (isdigit(*image)) {
-	entry = findEntryByPath(cfg, image, prefix, NULL);
-	if(entry)
-	    entry->skip = 1;
-	return;
-    }
+	/* check and see if we're removing the default image */
+	if (isdigit(*image)) {
+		entry = findEntryByPath(cfg, image, prefix, NULL);
+		if (entry)
+			entry->skip = 1;
+		return;
+	}
 
-    while ((entry = findEntryByPath(cfg, image, prefix, NULL)))
-	entry->skip = 1;
+	while ((entry = findEntryByPath(cfg, image, prefix, NULL)))
+		entry->skip = 1;
 }
 
-void setDefaultImage(struct grubConfig * config, int hasNew, 
-		     const char * defaultKernelPath, int newIsDefault,
-		     const char * prefix, int flags, int index) {
-    struct singleEntry * entry, * entry2, * newDefault;
-    int i, j;
-
-    if (newIsDefault) {
-	config->defaultImage = 0;
-	return;
-    } else if ((index >= 0) && config->cfi->defaultIsIndex) {
-	if (findEntryByIndex(config, index))
-	    config->defaultImage = index;
-	else
-	    config->defaultImage = -1;
-	return;
-    } else if (defaultKernelPath) {
-	i = 0;
-	if (findEntryByPath(config, defaultKernelPath, prefix, &i)) {
-	    config->defaultImage = i;
-	} else {
-	    config->defaultImage = -1;
-	    return;
+void setDefaultImage(struct grubConfig *config, int hasNew,
+		     const char *defaultKernelPath, int newIsDefault,
+		     const char *prefix, int flags, int index)
+{
+	struct singleEntry *entry, *entry2, *newDefault;
+	int i, j;
+
+	if (newIsDefault) {
+		config->defaultImage = 0;
+		return;
+	} else if ((index >= 0) && config->cfi->defaultIsIndex) {
+		if (findEntryByIndex(config, index))
+			config->defaultImage = index;
+		else
+			config->defaultImage = -1;
+		return;
+	} else if (defaultKernelPath) {
+		i = 0;
+		if (findEntryByPath(config, defaultKernelPath, prefix, &i)) {
+			config->defaultImage = i;
+		} else {
+			config->defaultImage = -1;
+			return;
+		}
 	}
-    } 
 
-    /* defaultImage now points to what we'd like to use, but before any order 
-       changes */
-    if ((config->defaultImage == DEFAULT_SAVED) ||
-	(config->defaultImage == DEFAULT_SAVED_GRUB2))
-      /* default is set to saved, we don't want to change it */
-      return;
+	/* defaultImage now points to what we'd like to use, but before any order 
+	   changes */
+	if ((config->defaultImage == DEFAULT_SAVED) ||
+	    (config->defaultImage == DEFAULT_SAVED_GRUB2))
+		/* default is set to saved, we don't want to change it */
+		return;
 
-    if (config->defaultImage > -1) 
-	entry = findEntryByIndex(config, config->defaultImage);
-    else
-	entry = NULL;
+	if (config->defaultImage > -1)
+		entry = findEntryByIndex(config, config->defaultImage);
+	else
+		entry = NULL;
 
-    if (entry && !entry->skip) {
-	/* we can preserve the default */
-	if (hasNew)
-	    config->defaultImage++;
-	
-	/* count the number of entries erased before this one */
-	for (j = 0; j < config->defaultImage; j++) {
-	    entry2 = findEntryByIndex(config, j);
-	    if (entry2->skip) config->defaultImage--;
-	}
-    } else if (hasNew) {
-	config->defaultImage = 0;
-    } else {
-	/* Either we just erased the default (or the default line was bad
-	 * to begin with) and didn't put a new one in. We'll use the first
-	 * valid image. */
-	newDefault = findTemplate(config, prefix, &config->defaultImage, 1,
-				  flags);
-	if (!newDefault)
-	    config->defaultImage = -1;
-    }
-}
+	if (entry && !entry->skip) {
+		/* we can preserve the default */
+		if (hasNew)
+			config->defaultImage++;
 
-void setFallbackImage(struct grubConfig * config, int hasNew) {
-    struct singleEntry * entry, * entry2;
-    int j;
-
-    if (config->fallbackImage == -1) return;
-
-    entry = findEntryByIndex(config, config->fallbackImage);
-    if (!entry || entry->skip) {
-	config->fallbackImage = -1;
-	return;
-    }
-
-    if (hasNew)
-	config->fallbackImage++;
-    
-    /* count the number of entries erased before this one */
-    for (j = 0; j < config->fallbackImage; j++) {
-	entry2 = findEntryByIndex(config, j);
-	if (entry2->skip) config->fallbackImage--;
-    }
+		/* count the number of entries erased before this one */
+		for (j = 0; j < config->defaultImage; j++) {
+			entry2 = findEntryByIndex(config, j);
+			if (entry2->skip)
+				config->defaultImage--;
+		}
+	} else if (hasNew) {
+		config->defaultImage = 0;
+	} else {
+		/* Either we just erased the default (or the default line was bad
+		 * to begin with) and didn't put a new one in. We'll use the first
+		 * valid image. */
+		newDefault =
+		    findTemplate(config, prefix, &config->defaultImage, 1,
+				 flags);
+		if (!newDefault)
+			config->defaultImage = -1;
+	}
 }
 
-void displayEntry(struct singleEntry * entry, const char * prefix, int index) {
-    struct singleLine * line;
-    char * root = NULL;
-    int i;
-
-    printf("index=%d\n", index);
-
-    line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines);
-    if (!line) {
-        printf("non linux entry\n");
-        return;
-    }
-
-    if (!strncmp(prefix, line->elements[1].item, strlen(prefix)))
-	printf("kernel=%s\n", line->elements[1].item);
-    else
-	printf("kernel=%s%s\n", prefix, line->elements[1].item);
-
-    if (line->numElements >= 3) {
-	printf("args=\"");
-	i = 2;
-	while (i < line->numElements) {
-	    if (!strncmp(line->elements[i].item, "root=", 5)) {
-		root = line->elements[i].item + 5;
-	    } else {
-		printf("%s%s", line->elements[i].item, 
-			       line->elements[i].indent);
-	    }
-
-	    i++;
-	}
-	printf("\"\n");
-    } else {
-	line = getLineByType(LT_KERNELARGS, entry->lines);
-	if (line) {
-	    char * s;
+void setFallbackImage(struct grubConfig *config, int hasNew)
+{
+	struct singleEntry *entry, *entry2;
+	int j;
 
-	    printf("args=\"");
-	    i = 1;
-	    while (i < line->numElements) {
-		if (!strncmp(line->elements[i].item, "root=", 5)) {
-		    root = line->elements[i].item + 5;
-		} else {
-		    s = line->elements[i].item;
+	if (config->fallbackImage == -1)
+		return;
 
-		    printf("%s%s", s, line->elements[i].indent);
-		}
+	entry = findEntryByIndex(config, config->fallbackImage);
+	if (!entry || entry->skip) {
+		config->fallbackImage = -1;
+		return;
+	}
 
-		i++;
-	    }
+	if (hasNew)
+		config->fallbackImage++;
 
-	    s = line->elements[i - 1].indent;
-	    printf("\"\n");
+	/* count the number of entries erased before this one */
+	for (j = 0; j < config->fallbackImage; j++) {
+		entry2 = findEntryByIndex(config, j);
+		if (entry2->skip)
+			config->fallbackImage--;
 	}
-    }
+}
 
-    if (!root) {
-	line = getLineByType(LT_ROOT, entry->lines);
-	if (line && line->numElements >= 2)
-	    root=line->elements[1].item;
-    }
+void displayEntry(struct singleEntry *entry, const char *prefix, int index)
+{
+	struct singleLine *line;
+	char *root = NULL;
+	int i;
 
-    if (root) {
-	char * s = alloca(strlen(root) + 1);
-	
-	strcpy(s, root);
-	if (s[strlen(s) - 1] == '"')
-	    s[strlen(s) - 1] = '\0';
-	/* make sure the root doesn't have a trailing " */
-	printf("root=%s\n", s);
-    }
+	printf("index=%d\n", index);
 
-    line = getLineByType(LT_INITRD|LT_INITRD_EFI|LT_INITRD_16, entry->lines);
+	line =
+	    getLineByType(LT_KERNEL | LT_HYPER | LT_KERNEL_EFI | LT_KERNEL_16,
+			  entry->lines);
+	if (!line) {
+		printf("non linux entry\n");
+		return;
+	}
 
-    if (line && line->numElements >= 2) {
 	if (!strncmp(prefix, line->elements[1].item, strlen(prefix)))
-	    printf("initrd=");
+		printf("kernel=%s\n", line->elements[1].item);
 	else
-	    printf("initrd=%s", prefix);
-
-	for (i = 1; i < line->numElements; i++)
-	    printf("%s%s", line->elements[i].item, line->elements[i].indent);
-	printf("\n");
-    }
-
-    line = getLineByType(LT_TITLE, entry->lines);
-    if (line) {
-	printf("title=%s\n", line->elements[1].item);
-    } else {
-	char * title;
-	line = getLineByType(LT_MENUENTRY, entry->lines);
-	if (line) {
-	    title = grub2ExtractTitle(line);
-	    if (title)
-		printf("title=%s\n", title);
-	}
-    }
-}
-
-int isSuseSystem(void) {
-    const char * path;
-    const static char default_path[] = "/etc/SuSE-release";
-
-    if ((path = getenv("GRUBBY_SUSE_RELEASE")) == NULL)
-	path = default_path;
-
-    if (!access(path, R_OK))
-	return 1;
-    return 0;
-}
+		printf("kernel=%s%s\n", prefix, line->elements[1].item);
+
+	if (line->numElements >= 3) {
+		printf("args=\"");
+		i = 2;
+		while (i < line->numElements) {
+			if (!strncmp(line->elements[i].item, "root=", 5)) {
+				root = line->elements[i].item + 5;
+			} else {
+				printf("%s%s", line->elements[i].item,
+				       line->elements[i].indent);
+			}
 
-int isSuseGrubConf(const char * path) {
-    FILE * grubConf;
-    char * line = NULL;
-    size_t len = 0, res = 0;
+			i++;
+		}
+		printf("\"\n");
+	} else {
+		line = getLineByType(LT_KERNELARGS, entry->lines);
+		if (line) {
+			char *s;
+
+			printf("args=\"");
+			i = 1;
+			while (i < line->numElements) {
+				if (!strncmp
+				    (line->elements[i].item, "root=", 5)) {
+					root = line->elements[i].item + 5;
+				} else {
+					s = line->elements[i].item;
+
+					printf("%s%s", s,
+					       line->elements[i].indent);
+				}
 
-    grubConf = fopen(path, "r");
-    if (!grubConf) {
-        dbgPrintf("Could not open SuSE configuration file '%s'\n", path);
-	return 0;
-    }
+				i++;
+			}
 
-    while ((res = getline(&line, &len, grubConf)) != -1) {
-	if (!strncmp(line, "setup", 5)) {
-	    fclose(grubConf);
-	    free(line);
-	    return 1;
+			s = line->elements[i - 1].indent;
+			printf("\"\n");
+		}
 	}
-    }
 
-    dbgPrintf("SuSE configuration file '%s' does not appear to be valid\n",
-	      path);
+	if (!root) {
+		line = getLineByType(LT_ROOT, entry->lines);
+		if (line && line->numElements >= 2)
+			root = line->elements[1].item;
+	}
 
-    fclose(grubConf);
-    free(line);
-    return 0;
-}
+	if (root) {
+		char *s = alloca(strlen(root) + 1);
 
-int suseGrubConfGetLba(const char * path, int * lbaPtr) {
-    FILE * grubConf;
-    char * line = NULL;
-    size_t res = 0, len = 0;
+		strcpy(s, root);
+		if (s[strlen(s) - 1] == '"')
+			s[strlen(s) - 1] = '\0';
+		/* make sure the root doesn't have a trailing " */
+		printf("root=%s\n", s);
+	}
 
-    if (!path) return 1;
-    if (!lbaPtr) return 1;
+	line =
+	    getLineByType(LT_INITRD | LT_INITRD_EFI | LT_INITRD_16,
+			  entry->lines);
 
-    grubConf = fopen(path, "r");
-    if (!grubConf) return 1;
+	if (line && line->numElements >= 2) {
+		if (!strncmp(prefix, line->elements[1].item, strlen(prefix)))
+			printf("initrd=");
+		else
+			printf("initrd=%s", prefix);
 
-    while ((res = getline(&line, &len, grubConf)) != -1) {
-	if (line[res - 1] == '\n')
-	    line[res - 1] = '\0';
-	else if (len > res)
-	    line[res] = '\0';
-	else {
-	    line = realloc(line, res + 1);
-	    line[res] = '\0';
+		for (i = 1; i < line->numElements; i++)
+			printf("%s%s", line->elements[i].item,
+			       line->elements[i].indent);
+		printf("\n");
 	}
 
-	if (!strncmp(line, "setup", 5)) {
-	    if (strstr(line, "--force-lba")) {
-	        *lbaPtr = 1;
-	    } else {
-	        *lbaPtr = 0;
-	    }
-	    dbgPrintf("lba: %i\n", *lbaPtr);
-	    break;
+	line = getLineByType(LT_TITLE, entry->lines);
+	if (line) {
+		printf("title=%s\n", line->elements[1].item);
+	} else {
+		char *title;
+		line = getLineByType(LT_MENUENTRY, entry->lines);
+		if (line) {
+			title = grub2ExtractTitle(line);
+			if (title)
+				printf("title=%s\n", title);
+		}
 	}
-    }
-
-    free(line);
-    fclose(grubConf);
-    return 0;
 }
 
-int suseGrubConfGetInstallDevice(const char * path, char ** devicePtr) {
-    FILE * grubConf;
-    char * line = NULL;
-    size_t res = 0, len = 0;
-    char * lastParamPtr = NULL;
-    char * secLastParamPtr = NULL;
-    char installDeviceNumber = '\0';
-    char * bounds = NULL;
-
-    if (!path) return 1;
-    if (!devicePtr) return 1;
-
-    grubConf = fopen(path, "r");
-    if (!grubConf) return 1;
-
-    while ((res = getline(&line, &len, grubConf)) != -1) {
-	if (strncmp(line, "setup", 5))
-	    continue;
-
-	if (line[res - 1] == '\n')
-	    line[res - 1] = '\0';
-	else if (len > res)
-	    line[res] = '\0';
-	else {
-	    line = realloc(line, res + 1);
-	    line[res] = '\0';
-	}
-
-	lastParamPtr = bounds = line + res;
+int isSuseSystem(void)
+{
+	const char *path;
+	const static char default_path[] = "/etc/SuSE-release";
 
-	/* Last parameter in grub may be an optional IMAGE_DEVICE */
-	while (!isspace(*lastParamPtr))
-	    lastParamPtr--;
-	lastParamPtr++;
+	if ((path = getenv("GRUBBY_SUSE_RELEASE")) == NULL)
+		path = default_path;
 
-	secLastParamPtr = lastParamPtr - 2;
-	dbgPrintf("lastParamPtr: %s\n", lastParamPtr);
+	if (!access(path, R_OK))
+		return 1;
+	return 0;
+}
 
-	if (lastParamPtr + 3 > bounds) {
-	    dbgPrintf("lastParamPtr going over boundary");
-	    fclose(grubConf);
-	    free(line);
-	    return 1;
+int isSuseGrubConf(const char *path)
+{
+	FILE *grubConf;
+	char *line = NULL;
+	size_t len = 0, res = 0;
+
+	grubConf = fopen(path, "r");
+	if (!grubConf) {
+		dbgPrintf("Could not open SuSE configuration file '%s'\n",
+			  path);
+		return 0;
 	}
-	if (!strncmp(lastParamPtr, "(hd", 3))
-	    lastParamPtr += 3;
-	dbgPrintf("lastParamPtr: %c\n", *lastParamPtr);
 
-	/*
-	 * Second last parameter will decide wether last parameter is
-	 * an IMAGE_DEVICE or INSTALL_DEVICE
-	 */
-	while (!isspace(*secLastParamPtr))
-	    secLastParamPtr--;
-	secLastParamPtr++;
-
-	if (secLastParamPtr + 3 > bounds) {
-	    dbgPrintf("secLastParamPtr going over boundary");
-	    fclose(grubConf);
-	    free(line);
-	    return 1;
-	}
-	dbgPrintf("secLastParamPtr: %s\n", secLastParamPtr);
-	if (!strncmp(secLastParamPtr, "(hd", 3)) {
-	    secLastParamPtr += 3;
-	    dbgPrintf("secLastParamPtr: %c\n", *secLastParamPtr);
-	    installDeviceNumber = *secLastParamPtr;
-	} else {
-	    installDeviceNumber = *lastParamPtr;
+	while ((res = getline(&line, &len, grubConf)) != -1) {
+		if (!strncmp(line, "setup", 5)) {
+			fclose(grubConf);
+			free(line);
+			return 1;
+		}
 	}
 
-	*devicePtr = malloc(6);
-	snprintf(*devicePtr, 6, "(hd%c)", installDeviceNumber);
-	dbgPrintf("installDeviceNumber: %c\n", installDeviceNumber);
+	dbgPrintf("SuSE configuration file '%s' does not appear to be valid\n",
+		  path);
+
 	fclose(grubConf);
 	free(line);
 	return 0;
-    }
-
-    free(line);
-    fclose(grubConf);
-    return 1;
 }
 
-int grubGetBootFromDeviceMap(const char * device,
-			     char ** bootPtr) {
-    FILE * deviceMap;
-    char * line = NULL;
-    size_t res = 0, len = 0;
-    char * devicePtr;
-    char * bounds = NULL;
-    const char * path;
-    const static char default_path[] = "/boot/grub/device.map";
-
-    if (!device) return 1;
-    if (!bootPtr) return 1;
-
-    if ((path = getenv("GRUBBY_GRUB_DEVICE_MAP")) == NULL)
-	path = default_path;
-
-    dbgPrintf("opening grub device.map file from: %s\n", path);
-    deviceMap = fopen(path, "r");
-    if (!deviceMap)
-	return 1;
-
-    while ((res = getline(&line, &len, deviceMap)) != -1) {
-        if (!strncmp(line, "#", 1))
-	    continue;
-
-	if (line[res - 1] == '\n')
-	    line[res - 1] = '\0';
-	else if (len > res)
-	    line[res] = '\0';
-	else {
-	    line = realloc(line, res + 1);
-	    line[res] = '\0';
-	}
+int suseGrubConfGetLba(const char *path, int *lbaPtr)
+{
+	FILE *grubConf;
+	char *line = NULL;
+	size_t res = 0, len = 0;
 
-	devicePtr = line;
-	bounds = line + res;
+	if (!path)
+		return 1;
+	if (!lbaPtr)
+		return 1;
 
-	while ((isspace(*line) && ((devicePtr + 1) <= bounds)))
-	    devicePtr++;
-	dbgPrintf("device: %s\n", devicePtr);
+	grubConf = fopen(path, "r");
+	if (!grubConf)
+		return 1;
 
-	if (!strncmp(devicePtr, device, strlen(device))) {
-	    devicePtr += strlen(device);
-	    while (isspace(*devicePtr) && ((devicePtr + 1) <= bounds))
-	        devicePtr++;
+	while ((res = getline(&line, &len, grubConf)) != -1) {
+		if (line[res - 1] == '\n')
+			line[res - 1] = '\0';
+		else if (len > res)
+			line[res] = '\0';
+		else {
+			line = realloc(line, res + 1);
+			line[res] = '\0';
+		}
 
-	    *bootPtr = strdup(devicePtr);
-	    break;
+		if (!strncmp(line, "setup", 5)) {
+			if (strstr(line, "--force-lba")) {
+				*lbaPtr = 1;
+			} else {
+				*lbaPtr = 0;
+			}
+			dbgPrintf("lba: %i\n", *lbaPtr);
+			break;
+		}
 	}
-    }
 
-    free(line);
-    fclose(deviceMap);
-    return 0;
+	free(line);
+	fclose(grubConf);
+	return 0;
 }
 
-int suseGrubConfGetBoot(const char * path, char ** bootPtr) {
-    char * grubDevice;
+int suseGrubConfGetInstallDevice(const char *path, char **devicePtr)
+{
+	FILE *grubConf;
+	char *line = NULL;
+	size_t res = 0, len = 0;
+	char *lastParamPtr = NULL;
+	char *secLastParamPtr = NULL;
+	char installDeviceNumber = '\0';
+	char *bounds = NULL;
+
+	if (!path)
+		return 1;
+	if (!devicePtr)
+		return 1;
 
-    if (suseGrubConfGetInstallDevice(path, &grubDevice))
-	dbgPrintf("error looking for grub installation device\n");
-    else
-	dbgPrintf("grubby installation device: %s\n", grubDevice);
+	grubConf = fopen(path, "r");
+	if (!grubConf)
+		return 1;
 
-    if (grubGetBootFromDeviceMap(grubDevice, bootPtr))
-	dbgPrintf("error looking for grub boot device\n");
-    else
-	dbgPrintf("grubby boot device: %s\n", *bootPtr);
+	while ((res = getline(&line, &len, grubConf)) != -1) {
+		if (strncmp(line, "setup", 5))
+			continue;
+
+		if (line[res - 1] == '\n')
+			line[res - 1] = '\0';
+		else if (len > res)
+			line[res] = '\0';
+		else {
+			line = realloc(line, res + 1);
+			line[res] = '\0';
+		}
 
-    free(grubDevice);
-    return 0;
-}
+		lastParamPtr = bounds = line + res;
 
-int parseSuseGrubConf(int * lbaPtr, char ** bootPtr) {
-    /*
-     * This SuSE grub configuration file at this location is not your average
-     * grub configuration file, but instead the grub commands used to setup
-     * grub on that system.
-     */
-    const char * path;
-    const static char default_path[] = "/etc/grub.conf";
+		/* Last parameter in grub may be an optional IMAGE_DEVICE */
+		while (!isspace(*lastParamPtr))
+			lastParamPtr--;
+		lastParamPtr++;
 
-    if ((path = getenv("GRUBBY_SUSE_GRUB_CONF")) == NULL)
-	path = default_path;
+		secLastParamPtr = lastParamPtr - 2;
+		dbgPrintf("lastParamPtr: %s\n", lastParamPtr);
 
-    if (!isSuseGrubConf(path)) return 1;
+		if (lastParamPtr + 3 > bounds) {
+			dbgPrintf("lastParamPtr going over boundary");
+			fclose(grubConf);
+			free(line);
+			return 1;
+		}
+		if (!strncmp(lastParamPtr, "(hd", 3))
+			lastParamPtr += 3;
+		dbgPrintf("lastParamPtr: %c\n", *lastParamPtr);
 
-    if (lbaPtr) {
-        *lbaPtr = 0;
-        if (suseGrubConfGetLba(path, lbaPtr))
-            return 1;
-    }
+		/*
+		 * Second last parameter will decide wether last parameter is
+		 * an IMAGE_DEVICE or INSTALL_DEVICE
+		 */
+		while (!isspace(*secLastParamPtr))
+			secLastParamPtr--;
+		secLastParamPtr++;
+
+		if (secLastParamPtr + 3 > bounds) {
+			dbgPrintf("secLastParamPtr going over boundary");
+			fclose(grubConf);
+			free(line);
+			return 1;
+		}
+		dbgPrintf("secLastParamPtr: %s\n", secLastParamPtr);
+		if (!strncmp(secLastParamPtr, "(hd", 3)) {
+			secLastParamPtr += 3;
+			dbgPrintf("secLastParamPtr: %c\n", *secLastParamPtr);
+			installDeviceNumber = *secLastParamPtr;
+		} else {
+			installDeviceNumber = *lastParamPtr;
+		}
 
-    if (bootPtr) {
-        *bootPtr = NULL;
-        suseGrubConfGetBoot(path, bootPtr);
-    }
+		*devicePtr = malloc(6);
+		snprintf(*devicePtr, 6, "(hd%c)", installDeviceNumber);
+		dbgPrintf("installDeviceNumber: %c\n", installDeviceNumber);
+		fclose(grubConf);
+		free(line);
+		return 0;
+	}
 
-    return 0;
+	free(line);
+	fclose(grubConf);
+	return 1;
 }
 
-int parseSysconfigGrub(int * lbaPtr, char ** bootPtr) {
-    FILE * in;
-    char buf[1024];
-    char * chptr;
-    char * start;
-    char * param;
-
-    in = fopen("/etc/sysconfig/grub", "r");
-    if (!in) return 1;
+int grubGetBootFromDeviceMap(const char *device, char **bootPtr)
+{
+	FILE *deviceMap;
+	char *line = NULL;
+	size_t res = 0, len = 0;
+	char *devicePtr;
+	char *bounds = NULL;
+	const char *path;
+	const static char default_path[] = "/boot/grub/device.map";
+
+	if (!device)
+		return 1;
+	if (!bootPtr)
+		return 1;
 
-    if (lbaPtr) *lbaPtr = 0;
-    if (bootPtr) *bootPtr = NULL;
+	if ((path = getenv("GRUBBY_GRUB_DEVICE_MAP")) == NULL)
+		path = default_path;
 
-    while (fgets(buf, sizeof(buf), in)) {
-	start = buf;
-	while (isspace(*start)) start++;
-	if (*start == '#') continue;
+	dbgPrintf("opening grub device.map file from: %s\n", path);
+	deviceMap = fopen(path, "r");
+	if (!deviceMap)
+		return 1;
 
-	chptr = strchr(start, '=');
-	if (!chptr) continue;
-	chptr--;
-	while (*chptr && isspace(*chptr)) chptr--;
-	chptr++;
-	*chptr = '\0';
+	while ((res = getline(&line, &len, deviceMap)) != -1) {
+		if (!strncmp(line, "#", 1))
+			continue;
+
+		if (line[res - 1] == '\n')
+			line[res - 1] = '\0';
+		else if (len > res)
+			line[res] = '\0';
+		else {
+			line = realloc(line, res + 1);
+			line[res] = '\0';
+		}
 
-	param = chptr + 1;
-	while (*param && isspace(*param)) param++;
-	if (*param == '=') {
-	    param++;
-	    while (*param && isspace(*param)) param++;
-	}
+		devicePtr = line;
+		bounds = line + res;
 
-	chptr = param;
-	while (*chptr && !isspace(*chptr)) chptr++;
-	*chptr = '\0';
+		while ((isspace(*line) && ((devicePtr + 1) <= bounds)))
+			devicePtr++;
+		dbgPrintf("device: %s\n", devicePtr);
 
-	if (!strcmp(start, "forcelba") && !strcmp(param, "1") && lbaPtr)
-	    *lbaPtr = 1;
-	else if (!strcmp(start, "boot") && bootPtr)
-	    *bootPtr = strdup(param);
-    }
+		if (!strncmp(devicePtr, device, strlen(device))) {
+			devicePtr += strlen(device);
+			while (isspace(*devicePtr)
+			       && ((devicePtr + 1) <= bounds))
+				devicePtr++;
 
-    fclose(in);
+			*bootPtr = strdup(devicePtr);
+			break;
+		}
+	}
 
-    return 0;
+	free(line);
+	fclose(deviceMap);
+	return 0;
 }
 
-void dumpSysconfigGrub(void) {
-    char * boot = NULL;
-    int lba;
+int suseGrubConfGetBoot(const char *path, char **bootPtr)
+{
+	char *grubDevice;
 
-    if (isSuseSystem()) {
-        if (parseSuseGrubConf(&lba, &boot)) {
-	    free(boot);
-	    return;
-	}
-    } else {
-        if (parseSysconfigGrub(&lba, &boot)) {
-	    free(boot);
-	    return;
-	}
-    }
+	if (suseGrubConfGetInstallDevice(path, &grubDevice))
+		dbgPrintf("error looking for grub installation device\n");
+	else
+		dbgPrintf("grubby installation device: %s\n", grubDevice);
 
-    if (lba) printf("lba\n");
-    if (boot) {
-	printf("boot=%s\n", boot);
-	free(boot);
-    }
-}
+	if (grubGetBootFromDeviceMap(grubDevice, bootPtr))
+		dbgPrintf("error looking for grub boot device\n");
+	else
+		dbgPrintf("grubby boot device: %s\n", *bootPtr);
 
-int displayInfo(struct grubConfig * config, char * kernel,
-		const char * prefix) {
-    int i = 0;
-    struct singleEntry * entry;
-    struct singleLine * line;
+	free(grubDevice);
+	return 0;
+}
 
-    entry = findEntryByPath(config, kernel, prefix, &i);
-    if (!entry) {
-	fprintf(stderr, _("grubby: kernel not found\n"));
-	return 1;
-    }
+int parseSuseGrubConf(int *lbaPtr, char **bootPtr)
+{
+	/*
+	 * This SuSE grub configuration file at this location is not your average
+	 * grub configuration file, but instead the grub commands used to setup
+	 * grub on that system.
+	 */
+	const char *path;
+	const static char default_path[] = "/etc/grub.conf";
 
-    /* this is a horrible hack to support /etc/sysconfig/grub; there must
-       be a better way */
-    if (config->cfi == &grubConfigType) {
-	dumpSysconfigGrub();
-    } else {
-	line = getLineByType(LT_BOOT, config->theLines);
-	if (line && line->numElements >= 1) {
-	    printf("boot=%s\n", line->elements[1].item);
-	}
+	if ((path = getenv("GRUBBY_SUSE_GRUB_CONF")) == NULL)
+		path = default_path;
 
-	line = getLineByType(LT_LBA, config->theLines);
-	if (line) printf("lba\n");
-    }
+	if (!isSuseGrubConf(path))
+		return 1;
 
-    displayEntry(entry, prefix, i);
+	if (lbaPtr) {
+		*lbaPtr = 0;
+		if (suseGrubConfGetLba(path, lbaPtr))
+			return 1;
+	}
 
-    i++;
-    while ((entry = findEntryByPath(config, kernel, prefix, &i))) {
-	displayEntry(entry, prefix, i);
-	i++;
-    }
+	if (bootPtr) {
+		*bootPtr = NULL;
+		suseGrubConfGetBoot(path, bootPtr);
+	}
 
-    return 0;
+	return 0;
 }
 
-struct singleLine * addLineTmpl(struct singleEntry * entry,
-				struct singleLine * tmplLine,
-				struct singleLine * prevLine,
-				const char * val,
-				struct configFileInfo * cfi)
+int parseSysconfigGrub(int *lbaPtr, char **bootPtr)
 {
-    struct singleLine * newLine = lineDup(tmplLine);
-
-    if (isEfi && cfi == &grub2ConfigType) {
-	enum lineType_e old = newLine->type;
-	newLine->type = preferredLineType(newLine->type, cfi);
-	if (old != newLine->type)
-	    newLine->elements[0].item = getKeyByType(newLine->type, cfi);
-    }
-
-    if (val) {
-	/* override the inherited value with our own.
-	 * This is a little weak because it only applies to elements[1]
-	 */
-	if (newLine->numElements > 1)
-	    removeElement(newLine, 1);
-	insertElement(newLine, val, 1, cfi);
-
-	/* but try to keep the rootspec from the template... sigh */
-	if (tmplLine->type & (LT_HYPER|LT_KERNEL|LT_MBMODULE|LT_INITRD|LT_KERNEL_EFI|LT_INITRD_EFI|LT_KERNEL_16|LT_INITRD_16)) {
-	    char * rootspec = getRootSpecifier(tmplLine->elements[1].item);
-	    if (rootspec != NULL) {
-		free(newLine->elements[1].item);
-		newLine->elements[1].item = 
-		    sdupprintf("%s%s", rootspec, val);
-	    }
-	}
-    }
-
-    dbgPrintf("addLineTmpl(%s)\n", newLine->numElements ? 
-	      newLine->elements[0].item : "");
-
-    if (!entry->lines) {
-	/* first one on the list */
-	entry->lines = newLine;
-    } else if (prevLine) {
-	/* add after prevLine */
-	newLine->next = prevLine->next;
-	prevLine->next = newLine;
-    }
-
-    return newLine;
-}
+	FILE *in;
+	char buf[1024];
+	char *chptr;
+	char *start;
+	char *param;
+
+	in = fopen("/etc/sysconfig/grub", "r");
+	if (!in)
+		return 1;
 
-/* val may be NULL */
-struct singleLine *  addLine(struct singleEntry * entry, 
-			     struct configFileInfo * cfi, 
-			     enum lineType_e type, char * defaultIndent,
-			     const char * val) {
-    struct singleLine * line, * prev;
-    struct keywordTypes * kw;
-    struct singleLine tmpl;
-
-    /* NB: This function shouldn't allocate items on the heap, rather on the
-     * stack since it calls addLineTmpl which will make copies.
-     */
-    if (type == LT_TITLE && cfi->titleBracketed) {
-	/* we're doing a bracketed title (zipl) */
-	tmpl.type = type;
-	tmpl.numElements = 1;
-	tmpl.elements = alloca(sizeof(*tmpl.elements));
-	tmpl.elements[0].item = alloca(strlen(val)+3);
-	sprintf(tmpl.elements[0].item, "[%s]", val);
-	tmpl.elements[0].indent = "";
-	val = NULL;
-    } else if (type == LT_MENUENTRY) {
-	char *lineend = "--class gnu-linux --class gnu --class os {";
-	if (!val) {
-	    fprintf(stderr, "Line type LT_MENUENTRY requires a value\n");
-	    abort();
-	}
-	kw = getKeywordByType(type, cfi);
-	if (!kw) {
-	    fprintf(stderr, "Looking up keyword for unknown type %d\n", type);
-	    abort();
-	}
-	tmpl.indent = "";
-	tmpl.type = type;
-	tmpl.numElements = 3;
-	tmpl.elements = alloca(sizeof(*tmpl.elements) * tmpl.numElements);
-	tmpl.elements[0].item = kw->key;
-	tmpl.elements[0].indent = alloca(2);
-	sprintf(tmpl.elements[0].indent, "%c", kw->nextChar);
-	tmpl.elements[1].item = (char *)val;
-	tmpl.elements[1].indent = alloca(2);
-	sprintf(tmpl.elements[1].indent, "%c", kw->nextChar);
-	tmpl.elements[2].item = alloca(strlen(lineend)+1);
-	strcpy(tmpl.elements[2].item, lineend);
-	tmpl.elements[2].indent = "";
-    } else {
-	kw = getKeywordByType(type, cfi);
-	if (!kw) {
-	    fprintf(stderr, "Looking up keyword for unknown type %d\n", type);
-	    abort();
-	}
-	tmpl.type = type;
-	tmpl.numElements = val ? 2 : 1;
-	tmpl.elements = alloca(sizeof(*tmpl.elements) * tmpl.numElements);
-	tmpl.elements[0].item = kw->key;
-	tmpl.elements[0].indent = alloca(2);
-	sprintf(tmpl.elements[0].indent, "%c", kw->nextChar);
-	if (val) {
-	    tmpl.elements[1].item = (char *)val;
-	    tmpl.elements[1].indent = "";
-	}
-    }
-
-    /* The last non-empty line gives us the indention to us and the line
-       to insert after. Note that comments are considered empty lines, which
-       may not be ideal? If there are no lines or we are looking at the
-       first line, we use defaultIndent (the first line is normally indented
-       differently from the rest) */ 
-    for (line = entry->lines, prev = NULL; line; line = line->next) {
-	if (line->numElements) prev = line;
-	/* fall back on the last line if prev isn't otherwise set */
-	if (!line->next && !prev) prev = line;
-    }
-
-    struct singleLine *menuEntry;
-    menuEntry = getLineByType(LT_MENUENTRY, entry->lines);
-    if (tmpl.type == LT_ENTRY_END) {
-	if (menuEntry)
-	    tmpl.indent = menuEntry->indent;
-	else
-	    tmpl.indent = defaultIndent ?: "";
-    } else if (tmpl.type != LT_MENUENTRY) {
-	if (menuEntry)
-	    tmpl.indent = "\t";
-	else if (prev == entry->lines)
-	    tmpl.indent = defaultIndent ?: "";
-	else
-	    tmpl.indent = prev->indent;
-    }
+	if (lbaPtr)
+		*lbaPtr = 0;
+	if (bootPtr)
+		*bootPtr = NULL;
+
+	while (fgets(buf, sizeof(buf), in)) {
+		start = buf;
+		while (isspace(*start))
+			start++;
+		if (*start == '#')
+			continue;
+
+		chptr = strchr(start, '=');
+		if (!chptr)
+			continue;
+		chptr--;
+		while (*chptr && isspace(*chptr))
+			chptr--;
+		chptr++;
+		*chptr = '\0';
+
+		param = chptr + 1;
+		while (*param && isspace(*param))
+			param++;
+		if (*param == '=') {
+			param++;
+			while (*param && isspace(*param))
+				param++;
+		}
 
-    return addLineTmpl(entry, &tmpl, prev, val, cfi);
-}
+		chptr = param;
+		while (*chptr && !isspace(*chptr))
+			chptr++;
+		*chptr = '\0';
+
+		if (!strcmp(start, "forcelba") && !strcmp(param, "1") && lbaPtr)
+			*lbaPtr = 1;
+		else if (!strcmp(start, "boot") && bootPtr)
+			*bootPtr = strdup(param);
+	}
 
-void removeLine(struct singleEntry * entry, struct singleLine * line) {
-    struct singleLine * prev;
-    int i;
-
-    for (i = 0; i < line->numElements; i++) {
-	free(line->elements[i].item);
-	free(line->elements[i].indent);
-    }
-    free(line->elements);
-    free(line->indent);
-
-    if (line == entry->lines) {
-	entry->lines = line->next;
-    } else {
-	prev = entry->lines;
-	while (prev->next != line) prev = prev->next;
-	prev->next = line->next;
-    }
-
-    free(line);
+	fclose(in);
+
+	return 0;
 }
 
-static void requote(struct singleLine *tmplLine, struct configFileInfo * cfi)
+void dumpSysconfigGrub(void)
 {
-    struct singleLine newLine = {
-	.indent = tmplLine->indent,
-	.type = tmplLine->type,
-	.next = tmplLine->next,
-    };
-    int firstQuotedItem = -1;
-    int quoteLen = 0;
-    int j;
-    int element = 0;
-    char *c;
-
-    c = malloc(strlen(tmplLine->elements[0].item) + 1);
-    strcpy(c, tmplLine->elements[0].item);
-    insertElement(&newLine, c, element++, cfi);
-    free(c);
-    c = NULL;
-
-    for (j = 1; j < tmplLine->numElements; j++) {
-	if (firstQuotedItem == -1) {
-	    quoteLen += strlen(tmplLine->elements[j].item);
-	    
-	    if (isquote(tmplLine->elements[j].item[0])) {
-		firstQuotedItem = j;
-	        quoteLen += strlen(tmplLine->elements[j].indent);
-	    } else {
-		c = malloc(quoteLen + 1);
-		strcpy(c, tmplLine->elements[j].item);
-		insertElement(&newLine, c, element++, cfi);
-		free(c);
-		quoteLen = 0;
-	    }
+	char *boot = NULL;
+	int lba;
+
+	if (isSuseSystem()) {
+		if (parseSuseGrubConf(&lba, &boot)) {
+			free(boot);
+			return;
+		}
 	} else {
-	    int itemlen = strlen(tmplLine->elements[j].item);
-	    quoteLen += itemlen;
-	    quoteLen += strlen(tmplLine->elements[j].indent);
-	    
-	    if (isquote(tmplLine->elements[j].item[itemlen - 1])) {
-		c = malloc(quoteLen + 1);
-		c[0] = '\0';
-		for (int i = firstQuotedItem; i < j+1; i++) {
-		    strcat(c, tmplLine->elements[i].item);
-		    strcat(c, tmplLine->elements[i].indent);
+		if (parseSysconfigGrub(&lba, &boot)) {
+			free(boot);
+			return;
 		}
-		insertElement(&newLine, c, element++, cfi);
-		free(c);
-		
-		firstQuotedItem = -1;
-		quoteLen = 0;
-	    }
-	}
-    }
-    while (tmplLine->numElements)
-	removeElement(tmplLine, 0);
-    if (tmplLine->elements)
-	free(tmplLine->elements);
-
-    tmplLine->numElements = newLine.numElements;
-    tmplLine->elements = newLine.elements;
-}
+	}
 
-static void insertElement(struct singleLine * line,
-			  const char * item, int insertHere,
-			  struct configFileInfo * cfi)
-{
-    struct keywordTypes * kw;
-    char indent[2] = "";
-
-    /* sanity check */
-    if (insertHere > line->numElements) {
-	dbgPrintf("insertElement() adjusting insertHere from %d to %d\n",
-		  insertHere, line->numElements);
-	insertHere = line->numElements;
-    }
-
-    line->elements = realloc(line->elements, (line->numElements + 1) * 
-			     sizeof(*line->elements));
-    memmove(&line->elements[insertHere+1], 
-	    &line->elements[insertHere], 
-	    (line->numElements - insertHere) * 
-	    sizeof(*line->elements));
-    line->elements[insertHere].item = strdup(item);
-
-    kw = getKeywordByType(line->type, cfi);
-
-    if (line->numElements == 0) {
-	indent[0] = '\0';
-    } else if (insertHere == 0) {
-	indent[0] = kw->nextChar;
-    } else if (kw->separatorChar != '\0') {
-	indent[0] = kw->separatorChar;
-    } else {
-	indent[0] = ' ';
-    }
-
-    if (insertHere > 0 && line->elements[insertHere-1].indent[0] == '\0') {
-	/* move the end-of-line forward */
-	line->elements[insertHere].indent = 
-	    line->elements[insertHere-1].indent;
-	line->elements[insertHere-1].indent = strdup(indent);
-    } else {
-	line->elements[insertHere].indent = strdup(indent);
-    }
-
-    line->numElements++;
-
-    dbgPrintf("insertElement(%s, '%s%s', %d)\n",
-	      line->elements[0].item,
-	      line->elements[insertHere].item,
-	      line->elements[insertHere].indent,
-	      insertHere);
+	if (lba)
+		printf("lba\n");
+	if (boot) {
+		printf("boot=%s\n", boot);
+		free(boot);
+	}
 }
 
-static void removeElement(struct singleLine * line, int removeHere) {
-    int i;
+int displayInfo(struct grubConfig *config, char *kernel, const char *prefix)
+{
+	int i = 0;
+	struct singleEntry *entry;
+	struct singleLine *line;
 
-    /* sanity check */
-    if (removeHere >= line->numElements) return;
+	entry = findEntryByPath(config, kernel, prefix, &i);
+	if (!entry) {
+		fprintf(stderr, _("grubby: kernel not found\n"));
+		return 1;
+	}
 
-    dbgPrintf("removeElement(%s, %d:%s)\n", line->elements[0].item, 
-	      removeHere, line->elements[removeHere].item);
+	/* this is a horrible hack to support /etc/sysconfig/grub; there must
+	   be a better way */
+	if (config->cfi == &grubConfigType) {
+		dumpSysconfigGrub();
+	} else {
+		line = getLineByType(LT_BOOT, config->theLines);
+		if (line && line->numElements >= 1) {
+			printf("boot=%s\n", line->elements[1].item);
+		}
 
-    free(line->elements[removeHere].item);
+		line = getLineByType(LT_LBA, config->theLines);
+		if (line)
+			printf("lba\n");
+	}
 
-    if (removeHere > 1) {
-	/* previous argument gets this argument's post-indentation */
-	free(line->elements[removeHere-1].indent);
-	line->elements[removeHere-1].indent =
-	    line->elements[removeHere].indent;
-    } else {
-	free(line->elements[removeHere].indent);
-    }
+	displayEntry(entry, prefix, i);
 
-    /* now collapse the array, but don't bother to realloc smaller */
-    for (i = removeHere; i < line->numElements - 1; i++)
-	line->elements[i] = line->elements[i + 1];
+	i++;
+	while ((entry = findEntryByPath(config, kernel, prefix, &i))) {
+		displayEntry(entry, prefix, i);
+		i++;
+	}
 
-    line->numElements--;
+	return 0;
 }
 
-int argMatch(const char * one, const char * two) {
-    char * first, * second;
-    char * chptr;
+struct singleLine *addLineTmpl(struct singleEntry *entry,
+			       struct singleLine *tmplLine,
+			       struct singleLine *prevLine,
+			       const char *val, struct configFileInfo *cfi)
+{
+	struct singleLine *newLine = lineDup(tmplLine);
+
+	if (isEfi && cfi == &grub2ConfigType) {
+		enum lineType_e old = newLine->type;
+		newLine->type = preferredLineType(newLine->type, cfi);
+		if (old != newLine->type)
+			newLine->elements[0].item =
+			    getKeyByType(newLine->type, cfi);
+	}
 
-    first = strcpy(alloca(strlen(one) + 1), one);
-    second = strcpy(alloca(strlen(two) + 1), two);
+	if (val) {
+		/* override the inherited value with our own.
+		 * This is a little weak because it only applies to elements[1]
+		 */
+		if (newLine->numElements > 1)
+			removeElement(newLine, 1);
+		insertElement(newLine, val, 1, cfi);
+
+		/* but try to keep the rootspec from the template... sigh */
+		if (tmplLine->
+		    type & (LT_HYPER | LT_KERNEL | LT_MBMODULE | LT_INITRD |
+			    LT_KERNEL_EFI | LT_INITRD_EFI | LT_KERNEL_16 |
+			    LT_INITRD_16)) {
+			char *rootspec =
+			    getRootSpecifier(tmplLine->elements[1].item);
+			if (rootspec != NULL) {
+				free(newLine->elements[1].item);
+				newLine->elements[1].item =
+				    sdupprintf("%s%s", rootspec, val);
+			}
+		}
+	}
 
-    chptr = strchr(first, '=');
-    if (chptr) *chptr = '\0';
+	dbgPrintf("addLineTmpl(%s)\n", newLine->numElements ?
+		  newLine->elements[0].item : "");
 
-    chptr = strchr(second, '=');
-    if (chptr) *chptr = '\0';
+	if (!entry->lines) {
+		/* first one on the list */
+		entry->lines = newLine;
+	} else if (prevLine) {
+		/* add after prevLine */
+		newLine->next = prevLine->next;
+		prevLine->next = newLine;
+	}
 
-    return strcmp(first, second);
+	return newLine;
 }
 
-int updateActualImage(struct grubConfig * cfg, const char * image,
-                      const char * prefix, const char * addArgs,
-                      const char * removeArgs, int multibootArgs) {
-    struct singleEntry * entry;
-    struct singleLine * line, * rootLine;
-    int index = 0;
-    int i, k;
-    const char ** newArgs, ** oldArgs;
-    const char ** arg;
-    int useKernelArgs, useRoot;
-    int firstElement;
-    int *usedElements;
-    int doreplace;
-
-    if (!image) return 0;
-
-    if (!addArgs) {
-	newArgs = malloc(sizeof(*newArgs));
-	*newArgs = NULL;
-    } else {
-	if (poptParseArgvString(addArgs, NULL, &newArgs)) {
-	    fprintf(stderr, 
-		    _("grubby: error separating arguments '%s'\n"), addArgs);
-	    return 1;
-	}
-    }
-
-    if (!removeArgs) {
-	oldArgs = malloc(sizeof(*oldArgs));
-	*oldArgs = NULL;
-    } else {
-	if (poptParseArgvString(removeArgs, NULL, &oldArgs)) {
-	    fprintf(stderr, 
-		    _("grubby: error separating arguments '%s'\n"), removeArgs);
-            free(newArgs);
-	    return 1;
-	}
-    }
-
-
-    useKernelArgs = (getKeywordByType(LT_KERNELARGS, cfg->cfi)
-		     && (!multibootArgs || cfg->cfi->mbConcatArgs));
-
-    useRoot = (getKeywordByType(LT_ROOT, cfg->cfi)
-	       && !multibootArgs);
-
-    for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) {
-
-	if (multibootArgs && !entry->multiboot)
-	    continue;
-
-	/* Determine where to put the args.  If this config supports
-	 * LT_KERNELARGS, use that.  Otherwise use
-	 * LT_HYPER/LT_KERNEL/LT_MBMODULE lines.
-	 */
-	if (useKernelArgs) {
-	    line = getLineByType(LT_KERNELARGS, entry->lines);
-	    if (!line) {
-		/* no LT_KERNELARGS, need to add it */
-		line = addLine(entry, cfg->cfi, LT_KERNELARGS, 
-			       cfg->secondaryIndent, NULL);
-	    }
-	    firstElement = 1;
-
-	} else if (multibootArgs) {
-	    line = getLineByType(LT_HYPER, entry->lines);
-	    if (!line) {
-		/* a multiboot entry without LT_HYPER? */
-		continue;
-	    }
-	    firstElement = 2;
-
-	} else {
-	    line = getLineByType(LT_KERNEL|LT_MBMODULE|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines);
-	    if (!line) {
-		/* no LT_KERNEL or LT_MBMODULE in this entry? */
-		continue;
-	    }
-	    firstElement = 2;
-	}
+/* val may be NULL */
+struct singleLine *addLine(struct singleEntry *entry,
+			   struct configFileInfo *cfi,
+			   enum lineType_e type, char *defaultIndent,
+			   const char *val)
+{
+	struct singleLine *line, *prev;
+	struct keywordTypes *kw;
+	struct singleLine tmpl;
 
-	/* handle the elilo case which does:
-	 *   append="hypervisor args -- kernel args"
+	/* NB: This function shouldn't allocate items on the heap, rather on the
+	 * stack since it calls addLineTmpl which will make copies.
 	 */
-	if (entry->multiboot && cfg->cfi->mbConcatArgs) {
-	    /* this is a multiboot entry, make sure there's
-	     * -- on the args line
-	     */
-	    for (i = firstElement; i < line->numElements; i++) {
-		if (!strcmp(line->elements[i].item, "--"))
-		    break;
-	    }
-	    if (i == line->numElements) {
-		/* assume all existing args are kernel args,
-		 * prepend -- to make it official
-		 */
-		insertElement(line, "--", firstElement, cfg->cfi);
-		i = firstElement;
-	    }
-	    if (!multibootArgs) {
-		/* kernel args start after the -- */
-		firstElement = i + 1;
-	    }
-	} else if (cfg->cfi->mbConcatArgs) {
-	    /* this is a non-multiboot entry, remove hyper args */
-	    for (i = firstElement; i < line->numElements; i++) {
-		if (!strcmp(line->elements[i].item, "--"))
-		    break;
-	    }
-	    if (i < line->numElements) {
-		/* remove args up to -- */
-		while (strcmp(line->elements[firstElement].item, "--"))
-		    removeElement(line, firstElement);
-		/* remove -- */
-		removeElement(line, firstElement);
-	    }
-	}
-
-        usedElements = calloc(line->numElements, sizeof(*usedElements));
-
-	for (k = 0, arg = newArgs; *arg; arg++, k++) {
-
-	    doreplace = 1;
-	    for (i = firstElement; i < line->numElements; i++) {
-		if (multibootArgs && cfg->cfi->mbConcatArgs && 
-		    !strcmp(line->elements[i].item, "--")) 
-		{
-		    /* reached the end of hyper args, insert here */
-		    doreplace = 0;
-		    break;  
+	if (type == LT_TITLE && cfi->titleBracketed) {
+		/* we're doing a bracketed title (zipl) */
+		tmpl.type = type;
+		tmpl.numElements = 1;
+		tmpl.elements = alloca(sizeof(*tmpl.elements));
+		tmpl.elements[0].item = alloca(strlen(val) + 3);
+		sprintf(tmpl.elements[0].item, "[%s]", val);
+		tmpl.elements[0].indent = "";
+		val = NULL;
+	} else if (type == LT_MENUENTRY) {
+		char *lineend = "--class gnu-linux --class gnu --class os {";
+		if (!val) {
+			fprintf(stderr,
+				"Line type LT_MENUENTRY requires a value\n");
+			abort();
 		}
-                if (usedElements[i])
-                    continue;
-		if (!argMatch(line->elements[i].item, *arg)) {
-                    usedElements[i]=1;
-		    break;
-                }
-            }
-
-	    if (i < line->numElements && doreplace) {
-		/* direct replacement */
-		free(line->elements[i].item);
-		line->elements[i].item = strdup(*arg);
-
-	    } else if (useRoot && !strncmp(*arg, "root=/dev/", 10)) {
-		/* root= replacement */
-		rootLine = getLineByType(LT_ROOT, entry->lines);
-		if (rootLine) {
-		    free(rootLine->elements[1].item);
-		    rootLine->elements[1].item = strdup(*arg + 5);
-		} else {
-		    rootLine = addLine(entry, cfg->cfi, LT_ROOT, 
-				       cfg->secondaryIndent, *arg + 5);
+		kw = getKeywordByType(type, cfi);
+		if (!kw) {
+			fprintf(stderr,
+				"Looking up keyword for unknown type %d\n",
+				type);
+			abort();
 		}
-	    }
-
-	    else {
-		/* insert/append */
-		insertElement(line, *arg, i, cfg->cfi);
-		usedElements = realloc(usedElements, line->numElements *
-				       sizeof(*usedElements));
-		memmove(&usedElements[i + 1], &usedElements[i],
-			line->numElements - i - 1);
-		usedElements[i] = 1;
-
-		/* if we updated a root= here even though there is a
-		   LT_ROOT available we need to remove the LT_ROOT entry
-		   (this will happen if we switch from a device to a label) */
-		if (useRoot && !strncmp(*arg, "root=", 5)) {
-		    rootLine = getLineByType(LT_ROOT, entry->lines);
-		    if (rootLine)
-			removeLine(entry, rootLine);
+		tmpl.indent = "";
+		tmpl.type = type;
+		tmpl.numElements = 3;
+		tmpl.elements =
+		    alloca(sizeof(*tmpl.elements) * tmpl.numElements);
+		tmpl.elements[0].item = kw->key;
+		tmpl.elements[0].indent = alloca(2);
+		sprintf(tmpl.elements[0].indent, "%c", kw->nextChar);
+		tmpl.elements[1].item = (char *)val;
+		tmpl.elements[1].indent = alloca(2);
+		sprintf(tmpl.elements[1].indent, "%c", kw->nextChar);
+		tmpl.elements[2].item = alloca(strlen(lineend) + 1);
+		strcpy(tmpl.elements[2].item, lineend);
+		tmpl.elements[2].indent = "";
+	} else {
+		kw = getKeywordByType(type, cfi);
+		if (!kw) {
+			fprintf(stderr,
+				"Looking up keyword for unknown type %d\n",
+				type);
+			abort();
 		}
-	    }
-	}
-
-        free(usedElements);
-
-	for (arg = oldArgs; *arg; arg++) {
-	    for (i = firstElement; i < line->numElements; i++) {
-		if (multibootArgs && cfg->cfi->mbConcatArgs && 
-		    !strcmp(line->elements[i].item, "--")) 
-		    /* reached the end of hyper args, stop here */
-		    break;
-		if (!argMatch(line->elements[i].item, *arg)) {
-		    removeElement(line, i);
-		    break;
+		tmpl.type = type;
+		tmpl.numElements = val ? 2 : 1;
+		tmpl.elements =
+		    alloca(sizeof(*tmpl.elements) * tmpl.numElements);
+		tmpl.elements[0].item = kw->key;
+		tmpl.elements[0].indent = alloca(2);
+		sprintf(tmpl.elements[0].indent, "%c", kw->nextChar);
+		if (val) {
+			tmpl.elements[1].item = (char *)val;
+			tmpl.elements[1].indent = "";
 		}
-	    }
-	    /* handle removing LT_ROOT line too */
-	    if (useRoot && !strncmp(*arg, "root=", 5)) {
-		rootLine = getLineByType(LT_ROOT, entry->lines);
-		if (rootLine)
-		    removeLine(entry, rootLine);
-	    }
 	}
 
-	if (line->numElements == 1) {
-	    /* don't need the line at all (note it has to be a
-	       LT_KERNELARGS for this to happen */
-	    removeLine(entry, line);
+	/* The last non-empty line gives us the indention to us and the line
+	   to insert after. Note that comments are considered empty lines, which
+	   may not be ideal? If there are no lines or we are looking at the
+	   first line, we use defaultIndent (the first line is normally indented
+	   differently from the rest) */
+	for (line = entry->lines, prev = NULL; line; line = line->next) {
+		if (line->numElements)
+			prev = line;
+		/* fall back on the last line if prev isn't otherwise set */
+		if (!line->next && !prev)
+			prev = line;
 	}
-    }
 
-    free(newArgs);
-    free(oldArgs);
+	struct singleLine *menuEntry;
+	menuEntry = getLineByType(LT_MENUENTRY, entry->lines);
+	if (tmpl.type == LT_ENTRY_END) {
+		if (menuEntry)
+			tmpl.indent = menuEntry->indent;
+		else
+			tmpl.indent = defaultIndent ? : "";
+	} else if (tmpl.type != LT_MENUENTRY) {
+		if (menuEntry)
+			tmpl.indent = "\t";
+		else if (prev == entry->lines)
+			tmpl.indent = defaultIndent ? : "";
+		else
+			tmpl.indent = prev->indent;
+	}
 
-    return 0;
+	return addLineTmpl(entry, &tmpl, prev, val, cfi);
 }
 
-int updateImage(struct grubConfig * cfg, const char * image,
-                const char * prefix, const char * addArgs,
-                const char * removeArgs, 
-                const char * addMBArgs, const char * removeMBArgs) {
-    int rc = 0;
+void removeLine(struct singleEntry *entry, struct singleLine *line)
+{
+	struct singleLine *prev;
+	int i;
 
-    if (!image) return rc;
+	for (i = 0; i < line->numElements; i++) {
+		free(line->elements[i].item);
+		free(line->elements[i].indent);
+	}
+	free(line->elements);
+	free(line->indent);
 
-    /* update the main args first... */
-    if (addArgs || removeArgs)
-        rc = updateActualImage(cfg, image, prefix, addArgs, removeArgs, 0);
-    if (rc) return rc;
+	if (line == entry->lines) {
+		entry->lines = line->next;
+	} else {
+		prev = entry->lines;
+		while (prev->next != line)
+			prev = prev->next;
+		prev->next = line->next;
+	}
 
-    /* and now any multiboot args */
-    if (addMBArgs || removeMBArgs)
-        rc = updateActualImage(cfg, image, prefix, addMBArgs, removeMBArgs, 1);
-    return rc;
+	free(line);
 }
 
-int addMBInitrd(struct grubConfig * cfg, const char *newMBKernel,
-		 const char * image, const char * prefix, const char * initrd,
-		 const char * title) {
-    struct singleEntry * entry;
-    struct singleLine * line, * kernelLine, *endLine = NULL;
-    int index = 0;
-
-    if (!image) return 0;
-
-    for (; (entry = findEntryByPath(cfg, newMBKernel, prefix, &index)); index++) {
-        kernelLine = getLineByType(LT_MBMODULE, entry->lines);
-        if (!kernelLine) continue;
-
-	/* if title is supplied, the entry's title must match it. */
-	if (title) {
-	    char *linetitle;
-
-	    line = getLineByType(LT_TITLE|LT_MENUENTRY, entry->lines);
-	    if (!line)
-		continue;
-
-	    linetitle = extractTitle(cfg, line);
-	    if (!linetitle)
-		continue;
-	    if (strcmp(title, linetitle)) {
-		free(linetitle);
-		continue;
-	    }
-	    free(linetitle);
-	}
-
-        if (prefix) {
-            int prefixLen = strlen(prefix);
-            if (!strncmp(initrd, prefix, prefixLen))
-                initrd += prefixLen;
-        }
-	endLine = getLineByType(LT_ENTRY_END, entry->lines);
-	if (endLine)
-	    removeLine(entry, endLine);
-        line = addLine(entry, cfg->cfi, preferredLineType(LT_MBMODULE,cfg->cfi),
-			kernelLine->indent, initrd);
-        if (!line)
-	    return 1;
-	if (endLine) {
-	    line = addLine(entry, cfg->cfi, LT_ENTRY_END, "", NULL);
-            if (!line)
-		return 1;
-	}
+static void requote(struct singleLine *tmplLine, struct configFileInfo *cfi)
+{
+	struct singleLine newLine = {
+		.indent = tmplLine->indent,
+		.type = tmplLine->type,
+		.next = tmplLine->next,
+	};
+	int firstQuotedItem = -1;
+	int quoteLen = 0;
+	int j;
+	int element = 0;
+	char *c;
+
+	c = malloc(strlen(tmplLine->elements[0].item) + 1);
+	strcpy(c, tmplLine->elements[0].item);
+	insertElement(&newLine, c, element++, cfi);
+	free(c);
+	c = NULL;
+
+	for (j = 1; j < tmplLine->numElements; j++) {
+		if (firstQuotedItem == -1) {
+			quoteLen += strlen(tmplLine->elements[j].item);
+
+			if (isquote(tmplLine->elements[j].item[0])) {
+				firstQuotedItem = j;
+				quoteLen +=
+				    strlen(tmplLine->elements[j].indent);
+			} else {
+				c = malloc(quoteLen + 1);
+				strcpy(c, tmplLine->elements[j].item);
+				insertElement(&newLine, c, element++, cfi);
+				free(c);
+				quoteLen = 0;
+			}
+		} else {
+			int itemlen = strlen(tmplLine->elements[j].item);
+			quoteLen += itemlen;
+			quoteLen += strlen(tmplLine->elements[j].indent);
+
+			if (isquote(tmplLine->elements[j].item[itemlen - 1])) {
+				c = malloc(quoteLen + 1);
+				c[0] = '\0';
+				for (int i = firstQuotedItem; i < j + 1; i++) {
+					strcat(c, tmplLine->elements[i].item);
+					strcat(c, tmplLine->elements[i].indent);
+				}
+				insertElement(&newLine, c, element++, cfi);
+				free(c);
 
-        break;
-    }
+				firstQuotedItem = -1;
+				quoteLen = 0;
+			}
+		}
+	}
+	while (tmplLine->numElements)
+		removeElement(tmplLine, 0);
+	if (tmplLine->elements)
+		free(tmplLine->elements);
 
-    return 0;
+	tmplLine->numElements = newLine.numElements;
+	tmplLine->elements = newLine.elements;
 }
 
-int updateInitrd(struct grubConfig * cfg, const char * image,
-                 const char * prefix, const char * initrd, const char * title) {
-    struct singleEntry * entry;
-    struct singleLine * line, * kernelLine, *endLine = NULL;
-    int index = 0;
-
-    if (!image) return 0;
-
-    for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) {
-        kernelLine = getLineByType(LT_KERNEL|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines);
-        if (!kernelLine) continue;
-
-	/* if title is supplied, the entry's title must match it. */
-	if (title) {
-	    char *linetitle;
-
-	    line = getLineByType(LT_TITLE|LT_MENUENTRY, entry->lines);
-	    if (!line)
-		continue;
-
-	    linetitle = extractTitle(cfg, line);
-	    if (!linetitle)
-		continue;
-	    if (strcmp(title, linetitle)) {
-		free(linetitle);
-		continue;
-	    }
-	    free(linetitle);
-	}
-
-        line = getLineByType(LT_INITRD|LT_INITRD_EFI|LT_INITRD_16, entry->lines);
-        if (line)
-            removeLine(entry, line);
-        if (prefix) {
-            int prefixLen = strlen(prefix);
-            if (!strncmp(initrd, prefix, prefixLen))
-                initrd += prefixLen;
-        }
-	endLine = getLineByType(LT_ENTRY_END, entry->lines);
-	if (endLine)
-	    removeLine(entry, endLine);
-	enum lineType_e lt;
-	switch(kernelLine->type) {
-	    case LT_KERNEL:
-	        lt = LT_INITRD;
-		break;
-	    case LT_KERNEL_EFI:
-	        lt = LT_INITRD_EFI;
-		break;
-	    case LT_KERNEL_16:
-	        lt = LT_INITRD_16;
-		break;
-	    default:
-	        lt = preferredLineType(LT_INITRD, cfg->cfi);
+static void insertElement(struct singleLine *line,
+			  const char *item, int insertHere,
+			  struct configFileInfo *cfi)
+{
+	struct keywordTypes *kw;
+	char indent[2] = "";
+
+	/* sanity check */
+	if (insertHere > line->numElements) {
+		dbgPrintf
+		    ("insertElement() adjusting insertHere from %d to %d\n",
+		     insertHere, line->numElements);
+		insertHere = line->numElements;
 	}
-        line = addLine(entry, cfg->cfi, lt, kernelLine->indent, initrd);
-        if (!line)
-	    return 1;
-	if (endLine) {
-	    line = addLine(entry, cfg->cfi, LT_ENTRY_END, "", NULL);
-            if (!line)
-		return 1;
+
+	line->elements = realloc(line->elements, (line->numElements + 1) *
+				 sizeof(*line->elements));
+	memmove(&line->elements[insertHere + 1],
+		&line->elements[insertHere],
+		(line->numElements - insertHere) * sizeof(*line->elements));
+	line->elements[insertHere].item = strdup(item);
+
+	kw = getKeywordByType(line->type, cfi);
+
+	if (line->numElements == 0) {
+		indent[0] = '\0';
+	} else if (insertHere == 0) {
+		indent[0] = kw->nextChar;
+	} else if (kw->separatorChar != '\0') {
+		indent[0] = kw->separatorChar;
+	} else {
+		indent[0] = ' ';
+	}
+
+	if (insertHere > 0 && line->elements[insertHere - 1].indent[0] == '\0') {
+		/* move the end-of-line forward */
+		line->elements[insertHere].indent =
+		    line->elements[insertHere - 1].indent;
+		line->elements[insertHere - 1].indent = strdup(indent);
+	} else {
+		line->elements[insertHere].indent = strdup(indent);
 	}
 
-        break;
-    }
+	line->numElements++;
 
-    return 0;
+	dbgPrintf("insertElement(%s, '%s%s', %d)\n",
+		  line->elements[0].item,
+		  line->elements[insertHere].item,
+		  line->elements[insertHere].indent, insertHere);
 }
 
-int checkDeviceBootloader(const char * device, const unsigned char * boot) {
-    int fd;
-    unsigned char bootSect[512];
-    int offset;
+static void removeElement(struct singleLine *line, int removeHere)
+{
+	int i;
 
-    fd = open(device, O_RDONLY);
-    if (fd < 0) {
-	fprintf(stderr, _("grubby: unable to open %s: %s\n"),
-		device, strerror(errno));
-	return 1;
-    }
+	/* sanity check */
+	if (removeHere >= line->numElements)
+		return;
 
-    if (read(fd, bootSect, 512) != 512) {
-	fprintf(stderr, _("grubby: unable to read %s: %s\n"),
-		device, strerror(errno));
-	return 1;
-    }
-    close(fd);
+	dbgPrintf("removeElement(%s, %d:%s)\n", line->elements[0].item,
+		  removeHere, line->elements[removeHere].item);
 
-    /* first three bytes should match, a jmp short should be in there */
-    if (memcmp(boot, bootSect, 3))
-	return 0;
+	free(line->elements[removeHere].item);
 
-    if (boot[1] == JMP_SHORT_OPCODE) {
-	offset = boot[2] + 2;
-    } else if (boot[1] == 0xe8 || boot[1] == 0xe9) {
-	offset = (boot[3] << 8) + boot[2] + 2;
-    } else if (boot[0] == JMP_SHORT_OPCODE) {
-      offset = boot[1] + 2;
-        /*
-	 * it looks like grub, when copying stage1 into the mbr, patches stage1
-	 * right after the JMP location, replacing other instructions such as
-	 * JMPs for NOOPs. So, relax the check a little bit by skipping those
-	 * different bytes.
-	 */
-      if ((bootSect[offset + 1] == NOOP_OPCODE)
-	  && (bootSect[offset + 2] == NOOP_OPCODE)) {
-	offset = offset + 3;
-      }
-    } else if (boot[0] == 0xe8 || boot[0] == 0xe9) {
-	offset = (boot[2] << 8) + boot[1] + 2;
-    } else {
-	return 0;
-    }
+	if (removeHere > 1) {
+		/* previous argument gets this argument's post-indentation */
+		free(line->elements[removeHere - 1].indent);
+		line->elements[removeHere - 1].indent =
+		    line->elements[removeHere].indent;
+	} else {
+		free(line->elements[removeHere].indent);
+	}
 
-    if (memcmp(boot + offset, bootSect + offset, CODE_SEG_SIZE))
-	return 0;
+	/* now collapse the array, but don't bother to realloc smaller */
+	for (i = removeHere; i < line->numElements - 1; i++)
+		line->elements[i] = line->elements[i + 1];
 
-    return 2;
+	line->numElements--;
 }
 
-int checkLiloOnRaid(char * mdDev, const unsigned char * boot) {
-    int fd;
-    char buf[65536];
-    char * end;
-    char * chptr;
-    char * chptr2;
-    int rc;
-
-    /* it's on raid; we need to parse /proc/mdstat and check all of the
-       *raw* devices listed in there */
+int argMatch(const char *one, const char *two)
+{
+	char *first, *second;
+	char *chptr;
 
-    if (!strncmp(mdDev, "/dev/", 5))
-	mdDev += 5;
+	first = strcpy(alloca(strlen(one) + 1), one);
+	second = strcpy(alloca(strlen(two) + 1), two);
 
-    if ((fd = open("/proc/mdstat", O_RDONLY)) < 0) {
-	fprintf(stderr, _("grubby: failed to open /proc/mdstat: %s\n"),
-		strerror(errno));
-	return 2;
-    }
+	chptr = strchr(first, '=');
+	if (chptr)
+		*chptr = '\0';
 
-    rc = read(fd, buf, sizeof(buf) - 1);
-    if (rc < 0 || rc == (sizeof(buf) - 1)) {
-	fprintf(stderr, _("grubby: failed to read /proc/mdstat: %s\n"),
-		strerror(errno));
-	close(fd);
-	return 2;
-    }
-    close(fd);
-    buf[rc] = '\0';
-
-    chptr = buf;
-    while (*chptr) {
-	end = strchr(chptr, '\n');
-	if (!end) break;
-	*end = '\0';
+	chptr = strchr(second, '=');
+	if (chptr)
+		*chptr = '\0';
 
-	if (!strncmp(chptr, mdDev, strlen(mdDev)) && 
-	    chptr[strlen(mdDev)] == ' ') {
-
-	    /* found the device */
-	    while (*chptr && *chptr != ':') chptr++;
-	    chptr++;
-	    while (*chptr && isspace(*chptr)) chptr++;
-
-	    /* skip the "active" bit */
-	    while (*chptr && !isspace(*chptr)) chptr++;
-	    while (*chptr && isspace(*chptr)) chptr++;
-
-	    /* skip the raid level */
-	    while (*chptr && !isspace(*chptr)) chptr++;
-	    while (*chptr && isspace(*chptr)) chptr++;
-
-	    /* everything else is partition stuff */
-	    while (*chptr) {
-		chptr2 = chptr;
-		while (*chptr2 && *chptr2 != '[') chptr2++;
-		if (!*chptr2) break;
-
-		/* yank off the numbers at the end */
-		chptr2--;
-		while (isdigit(*chptr2) && chptr2 > chptr) chptr2--;
-		chptr2++;
-		*chptr2 = '\0';
-
-		/* Better, now we need the /dev/ back. We're done with
-		 * everything before this point, so we can just put
-		 * the /dev/ part there. There will always be room. */
-		memcpy(chptr - 5, "/dev/", 5);
-		rc = checkDeviceBootloader(chptr - 5, boot);
-		if (rc != 2) {
-		    return rc;
-		}
+	return strcmp(first, second);
+}
 
-		chptr = chptr2 + 1;
-		/* skip the [11] bit */
-		while (*chptr && !isspace(*chptr)) chptr++;
-		/* and move to the next one */
-		while (*chptr && isspace(*chptr)) chptr++;
-	    }
+int updateActualImage(struct grubConfig *cfg, const char *image,
+		      const char *prefix, const char *addArgs,
+		      const char *removeArgs, int multibootArgs)
+{
+	struct singleEntry *entry;
+	struct singleLine *line, *rootLine;
+	int index = 0;
+	int i, k;
+	const char **newArgs, **oldArgs;
+	const char **arg;
+	int useKernelArgs, useRoot;
+	int firstElement;
+	int *usedElements;
+	int doreplace;
+
+	if (!image)
+		return 0;
 
-	    /*  we're good to go */
-	    return 2;
+	if (!addArgs) {
+		newArgs = malloc(sizeof(*newArgs));
+		*newArgs = NULL;
+	} else {
+		if (poptParseArgvString(addArgs, NULL, &newArgs)) {
+			fprintf(stderr,
+				_("grubby: error separating arguments '%s'\n"),
+				addArgs);
+			return 1;
+		}
 	}
 
-	chptr = end + 1;
-    }
+	if (!removeArgs) {
+		oldArgs = malloc(sizeof(*oldArgs));
+		*oldArgs = NULL;
+	} else {
+		if (poptParseArgvString(removeArgs, NULL, &oldArgs)) {
+			fprintf(stderr,
+				_("grubby: error separating arguments '%s'\n"),
+				removeArgs);
+			free(newArgs);
+			return 1;
+		}
+	}
 
-    fprintf(stderr, 
-	    _("grubby: raid device /dev/%s not found in /proc/mdstat\n"),
-	    mdDev);
-    return 0;
-}
+	useKernelArgs = (getKeywordByType(LT_KERNELARGS, cfg->cfi)
+			 && (!multibootArgs || cfg->cfi->mbConcatArgs));
 
-int checkForLilo(struct grubConfig * config) {
-    int fd;
-    unsigned char boot[512];
-    struct singleLine * line;
+	useRoot = (getKeywordByType(LT_ROOT, cfg->cfi)
+		   && !multibootArgs);
 
-    for (line = config->theLines; line; line = line->next)
-	if (line->type == LT_BOOT) break;
+	for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) {
 
-    if (!line) { 
-	fprintf(stderr, 
-		_("grubby: no boot line found in lilo configuration\n"));
-	return 1;
-    }
+		if (multibootArgs && !entry->multiboot)
+			continue;
 
-    if (line->numElements != 2) return 1;
+		/* Determine where to put the args.  If this config supports
+		 * LT_KERNELARGS, use that.  Otherwise use
+		 * LT_HYPER/LT_KERNEL/LT_MBMODULE lines.
+		 */
+		if (useKernelArgs) {
+			line = getLineByType(LT_KERNELARGS, entry->lines);
+			if (!line) {
+				/* no LT_KERNELARGS, need to add it */
+				line = addLine(entry, cfg->cfi, LT_KERNELARGS,
+					       cfg->secondaryIndent, NULL);
+			}
+			firstElement = 1;
 
-    fd = open("/boot/boot.b", O_RDONLY);
-    if (fd < 0) {
-	fprintf(stderr, _("grubby: unable to open %s: %s\n"),
-		"/boot/boot.b", strerror(errno));
-	return 1;
-    }
+		} else if (multibootArgs) {
+			line = getLineByType(LT_HYPER, entry->lines);
+			if (!line) {
+				/* a multiboot entry without LT_HYPER? */
+				continue;
+			}
+			firstElement = 2;
 
-    if (read(fd, boot, 512) != 512) {
-	fprintf(stderr, _("grubby: unable to read %s: %s\n"),
-		"/boot/boot.b", strerror(errno));
-	return 1;
-    }
-    close(fd);
+		} else {
+			line =
+			    getLineByType(LT_KERNEL | LT_MBMODULE |
+					  LT_KERNEL_EFI | LT_KERNEL_16,
+					  entry->lines);
+			if (!line) {
+				/* no LT_KERNEL or LT_MBMODULE in this entry? */
+				continue;
+			}
+			firstElement = 2;
+		}
 
-    if (!strncmp("/dev/md", line->elements[1].item, 7))
-	return checkLiloOnRaid(line->elements[1].item, boot);
+		/* handle the elilo case which does:
+		 *   append="hypervisor args -- kernel args"
+		 */
+		if (entry->multiboot && cfg->cfi->mbConcatArgs) {
+			/* this is a multiboot entry, make sure there's
+			 * -- on the args line
+			 */
+			for (i = firstElement; i < line->numElements; i++) {
+				if (!strcmp(line->elements[i].item, "--"))
+					break;
+			}
+			if (i == line->numElements) {
+				/* assume all existing args are kernel args,
+				 * prepend -- to make it official
+				 */
+				insertElement(line, "--", firstElement,
+					      cfg->cfi);
+				i = firstElement;
+			}
+			if (!multibootArgs) {
+				/* kernel args start after the -- */
+				firstElement = i + 1;
+			}
+		} else if (cfg->cfi->mbConcatArgs) {
+			/* this is a non-multiboot entry, remove hyper args */
+			for (i = firstElement; i < line->numElements; i++) {
+				if (!strcmp(line->elements[i].item, "--"))
+					break;
+			}
+			if (i < line->numElements) {
+				/* remove args up to -- */
+				while (strcmp
+				       (line->elements[firstElement].item,
+					"--"))
+					removeElement(line, firstElement);
+				/* remove -- */
+				removeElement(line, firstElement);
+			}
+		}
 
-    return checkDeviceBootloader(line->elements[1].item, boot);
-}
+		usedElements = calloc(line->numElements, sizeof(*usedElements));
 
-int checkForGrub2(struct grubConfig * config) {
-    if (!access("/etc/grub.d/", R_OK))
-	return 2;
+		for (k = 0, arg = newArgs; *arg; arg++, k++) {
 
-    return 1;
-}
+			doreplace = 1;
+			for (i = firstElement; i < line->numElements; i++) {
+				if (multibootArgs && cfg->cfi->mbConcatArgs &&
+				    !strcmp(line->elements[i].item, "--")) {
+					/* reached the end of hyper args, insert here */
+					doreplace = 0;
+					break;
+				}
+				if (usedElements[i])
+					continue;
+				if (!argMatch(line->elements[i].item, *arg)) {
+					usedElements[i] = 1;
+					break;
+				}
+			}
 
-int checkForGrub(struct grubConfig * config) {
-    int fd;
-    unsigned char bootSect[512];
-    char * boot;
-    int onSuse = isSuseSystem();
+			if (i < line->numElements && doreplace) {
+				/* direct replacement */
+				free(line->elements[i].item);
+				line->elements[i].item = strdup(*arg);
+
+			} else if (useRoot && !strncmp(*arg, "root=/dev/", 10)) {
+				/* root= replacement */
+				rootLine = getLineByType(LT_ROOT, entry->lines);
+				if (rootLine) {
+					free(rootLine->elements[1].item);
+					rootLine->elements[1].item =
+					    strdup(*arg + 5);
+				} else {
+					rootLine =
+					    addLine(entry, cfg->cfi, LT_ROOT,
+						    cfg->secondaryIndent,
+						    *arg + 5);
+				}
+			}
 
+			else {
+				/* insert/append */
+				insertElement(line, *arg, i, cfg->cfi);
+				usedElements =
+				    realloc(usedElements,
+					    line->numElements *
+					    sizeof(*usedElements));
+				memmove(&usedElements[i + 1], &usedElements[i],
+					line->numElements - i - 1);
+				usedElements[i] = 1;
+
+				/* if we updated a root= here even though there is a
+				   LT_ROOT available we need to remove the LT_ROOT entry
+				   (this will happen if we switch from a device to a label) */
+				if (useRoot && !strncmp(*arg, "root=", 5)) {
+					rootLine =
+					    getLineByType(LT_ROOT,
+							  entry->lines);
+					if (rootLine)
+						removeLine(entry, rootLine);
+				}
+			}
+		}
 
-    if (onSuse) {
-	if (parseSuseGrubConf(NULL, &boot))
-	    return 0;
-    } else {
-	if (parseSysconfigGrub(NULL, &boot))
-	    return 0;
-    }
+		free(usedElements);
 
-    /* assume grub is not installed -- not an error condition */
-    if (!boot)
-	return 0;
+		for (arg = oldArgs; *arg; arg++) {
+			for (i = firstElement; i < line->numElements; i++) {
+				if (multibootArgs && cfg->cfi->mbConcatArgs &&
+				    !strcmp(line->elements[i].item, "--"))
+					/* reached the end of hyper args, stop here */
+					break;
+				if (!argMatch(line->elements[i].item, *arg)) {
+					removeElement(line, i);
+					break;
+				}
+			}
+			/* handle removing LT_ROOT line too */
+			if (useRoot && !strncmp(*arg, "root=", 5)) {
+				rootLine = getLineByType(LT_ROOT, entry->lines);
+				if (rootLine)
+					removeLine(entry, rootLine);
+			}
+		}
 
-    fd = open("/boot/grub/stage1", O_RDONLY);
-    if (fd < 0)
-	/* this doesn't exist if grub hasn't been installed */
-	return 0;
+		if (line->numElements == 1) {
+			/* don't need the line at all (note it has to be a
+			   LT_KERNELARGS for this to happen */
+			removeLine(entry, line);
+		}
+	}
 
-    if (read(fd, bootSect, 512) != 512) {
-	fprintf(stderr, _("grubby: unable to read %s: %s\n"),
-		"/boot/grub/stage1", strerror(errno));
- 	close(fd);
-	return 1;
-    }
-    close(fd);
+	free(newArgs);
+	free(oldArgs);
 
-    /* The more elaborate checks do not work on SuSE. The checks done
-     * seem to be reasonble (at least for now), so just return success
-     */
-    if (onSuse)
-	return 2;
+	return 0;
+}
 
-    return checkDeviceBootloader(boot, bootSect);
+int updateImage(struct grubConfig *cfg, const char *image,
+		const char *prefix, const char *addArgs,
+		const char *removeArgs,
+		const char *addMBArgs, const char *removeMBArgs)
+{
+	int rc = 0;
+
+	if (!image)
+		return rc;
+
+	/* update the main args first... */
+	if (addArgs || removeArgs)
+		rc = updateActualImage(cfg, image, prefix, addArgs, removeArgs,
+				       0);
+	if (rc)
+		return rc;
+
+	/* and now any multiboot args */
+	if (addMBArgs || removeMBArgs)
+		rc = updateActualImage(cfg, image, prefix, addMBArgs,
+				       removeMBArgs, 1);
+	return rc;
 }
 
-int checkForExtLinux(struct grubConfig * config) {
-    int fd;
-    unsigned char bootSect[512];
-    char * boot;
-    char executable[] = "/boot/extlinux/extlinux";
+int addMBInitrd(struct grubConfig *cfg, const char *newMBKernel,
+		const char *image, const char *prefix, const char *initrd,
+		const char *title)
+{
+	struct singleEntry *entry;
+	struct singleLine *line, *kernelLine, *endLine = NULL;
+	int index = 0;
 
-    printf("entered: checkForExtLinux()\n");
+	if (!image)
+		return 0;
 
-    if (parseSysconfigGrub(NULL, &boot))
-	return 0;
+	for (; (entry = findEntryByPath(cfg, newMBKernel, prefix, &index));
+	     index++) {
+		kernelLine = getLineByType(LT_MBMODULE, entry->lines);
+		if (!kernelLine)
+			continue;
 
-    /* assume grub is not installed -- not an error condition */
-    if (!boot)
-	return 0;
+		/* if title is supplied, the entry's title must match it. */
+		if (title) {
+			char *linetitle;
+
+			line =
+			    getLineByType(LT_TITLE | LT_MENUENTRY,
+					  entry->lines);
+			if (!line)
+				continue;
+
+			linetitle = extractTitle(cfg, line);
+			if (!linetitle)
+				continue;
+			if (strcmp(title, linetitle)) {
+				free(linetitle);
+				continue;
+			}
+			free(linetitle);
+		}
 
-    fd = open(executable, O_RDONLY);
-    if (fd < 0)
-	/* this doesn't exist if grub hasn't been installed */
-	return 0;
+		if (prefix) {
+			int prefixLen = strlen(prefix);
+			if (!strncmp(initrd, prefix, prefixLen))
+				initrd += prefixLen;
+		}
+		endLine = getLineByType(LT_ENTRY_END, entry->lines);
+		if (endLine)
+			removeLine(entry, endLine);
+		line =
+		    addLine(entry, cfg->cfi,
+			    preferredLineType(LT_MBMODULE, cfg->cfi),
+			    kernelLine->indent, initrd);
+		if (!line)
+			return 1;
+		if (endLine) {
+			line = addLine(entry, cfg->cfi, LT_ENTRY_END, "", NULL);
+			if (!line)
+				return 1;
+		}
 
-    if (read(fd, bootSect, 512) != 512) {
-	fprintf(stderr, _("grubby: unable to read %s: %s\n"),
-		executable, strerror(errno));
-	return 1;
-    }
-    close(fd);
+		break;
+	}
 
-    return checkDeviceBootloader(boot, bootSect);
+	return 0;
 }
 
-int checkForYaboot(struct grubConfig * config) {
-    /*
-     * This is a simplistic check that we consider good enough for own puporses
-     *
-     * If we were to properly check if yaboot is *installed* we'd need to:
-     * 1) get the system boot device (LT_BOOT)
-     * 2) considering it's a raw filesystem, check if the yaboot binary matches
-     *    the content on the boot device
-     * 3) if not, copy the binary to a temporary file and run "addnote" on it
-     * 4) check again if binary and boot device contents match
-     */
-    if (!access("/etc/yaboot.conf", R_OK))
-	return 2;
-
-    return 1;
-}
+int updateInitrd(struct grubConfig *cfg, const char *image,
+		 const char *prefix, const char *initrd, const char *title)
+{
+	struct singleEntry *entry;
+	struct singleLine *line, *kernelLine, *endLine = NULL;
+	int index = 0;
 
-int checkForElilo(struct grubConfig * config) {
-    if (!access("/etc/elilo.conf", R_OK))
-	return 2;
+	if (!image)
+		return 0;
 
-    return 1;
-}
+	for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) {
+		kernelLine =
+		    getLineByType(LT_KERNEL | LT_KERNEL_EFI | LT_KERNEL_16,
+				  entry->lines);
+		if (!kernelLine)
+			continue;
 
-static char * getRootSpecifier(char * str) {
-    char * idx, * rootspec = NULL;
+		/* if title is supplied, the entry's title must match it. */
+		if (title) {
+			char *linetitle;
+
+			line =
+			    getLineByType(LT_TITLE | LT_MENUENTRY,
+					  entry->lines);
+			if (!line)
+				continue;
+
+			linetitle = extractTitle(cfg, line);
+			if (!linetitle)
+				continue;
+			if (strcmp(title, linetitle)) {
+				free(linetitle);
+				continue;
+			}
+			free(linetitle);
+		}
 
-    if (*str == '(') {
-        idx = rootspec = strdup(str);
-        while(*idx && (*idx != ')') && (!isspace(*idx))) idx++;
-        *(++idx) = '\0';
-    }
-    return rootspec;
+		line =
+		    getLineByType(LT_INITRD | LT_INITRD_EFI | LT_INITRD_16,
+				  entry->lines);
+		if (line)
+			removeLine(entry, line);
+		if (prefix) {
+			int prefixLen = strlen(prefix);
+			if (!strncmp(initrd, prefix, prefixLen))
+				initrd += prefixLen;
+		}
+		endLine = getLineByType(LT_ENTRY_END, entry->lines);
+		if (endLine)
+			removeLine(entry, endLine);
+		enum lineType_e lt;
+		switch (kernelLine->type) {
+		case LT_KERNEL:
+			lt = LT_INITRD;
+			break;
+		case LT_KERNEL_EFI:
+			lt = LT_INITRD_EFI;
+			break;
+		case LT_KERNEL_16:
+			lt = LT_INITRD_16;
+			break;
+		default:
+			lt = preferredLineType(LT_INITRD, cfg->cfi);
+		}
+		line = addLine(entry, cfg->cfi, lt, kernelLine->indent, initrd);
+		if (!line)
+			return 1;
+		if (endLine) {
+			line = addLine(entry, cfg->cfi, LT_ENTRY_END, "", NULL);
+			if (!line)
+				return 1;
+		}
+
+		break;
+	}
+
+	return 0;
 }
 
-static char * getInitrdVal(struct grubConfig * config,
-			   const char * prefix, struct singleLine *tmplLine,
-			   const char * newKernelInitrd,
-			   const char ** extraInitrds, int extraInitrdCount)
+int checkDeviceBootloader(const char *device, const unsigned char *boot)
 {
-    char *initrdVal, *end;
-    int i;
-    size_t totalSize;
-    size_t prefixLen;
-    char separatorChar;
+	int fd;
+	unsigned char bootSect[512];
+	int offset;
+
+	fd = open(device, O_RDONLY);
+	if (fd < 0) {
+		fprintf(stderr, _("grubby: unable to open %s: %s\n"),
+			device, strerror(errno));
+		return 1;
+	}
 
-    prefixLen = strlen(prefix);
-    totalSize = strlen(newKernelInitrd) - prefixLen + 1 /* \0 */;
+	if (read(fd, bootSect, 512) != 512) {
+		fprintf(stderr, _("grubby: unable to read %s: %s\n"),
+			device, strerror(errno));
+		return 1;
+	}
+	close(fd);
 
-    for (i = 0; i < extraInitrdCount; i++) {
-	totalSize += sizeof(separatorChar);
-	totalSize += strlen(extraInitrds[i]) - prefixLen;
-    }
+	/* first three bytes should match, a jmp short should be in there */
+	if (memcmp(boot, bootSect, 3))
+		return 0;
 
-    initrdVal = end = malloc(totalSize);
+	if (boot[1] == JMP_SHORT_OPCODE) {
+		offset = boot[2] + 2;
+	} else if (boot[1] == 0xe8 || boot[1] == 0xe9) {
+		offset = (boot[3] << 8) + boot[2] + 2;
+	} else if (boot[0] == JMP_SHORT_OPCODE) {
+		offset = boot[1] + 2;
+		/*
+		 * it looks like grub, when copying stage1 into the mbr, patches stage1
+		 * right after the JMP location, replacing other instructions such as
+		 * JMPs for NOOPs. So, relax the check a little bit by skipping those
+		 * different bytes.
+		 */
+		if ((bootSect[offset + 1] == NOOP_OPCODE)
+		    && (bootSect[offset + 2] == NOOP_OPCODE)) {
+			offset = offset + 3;
+		}
+	} else if (boot[0] == 0xe8 || boot[0] == 0xe9) {
+		offset = (boot[2] << 8) + boot[1] + 2;
+	} else {
+		return 0;
+	}
 
-    end = stpcpy (end, newKernelInitrd + prefixLen);
+	if (memcmp(boot + offset, bootSect + offset, CODE_SEG_SIZE))
+		return 0;
 
-    separatorChar = getKeywordByType(LT_INITRD, config->cfi)->separatorChar;
-    for (i = 0; i < extraInitrdCount; i++) {
-	const char *extraInitrd;
-	int j;
+	return 2;
+}
 
-	extraInitrd = extraInitrds[i] + prefixLen;
-	/* Don't add entries that are already there */
-	if (tmplLine != NULL) {
-	    for (j = 2; j < tmplLine->numElements; j++)
-		if (strcmp(extraInitrd, tmplLine->elements[j].item) == 0)
-		    break;
+int checkLiloOnRaid(char *mdDev, const unsigned char *boot)
+{
+	int fd;
+	char buf[65536];
+	char *end;
+	char *chptr;
+	char *chptr2;
+	int rc;
+
+	/* it's on raid; we need to parse /proc/mdstat and check all of the
+	 *raw* devices listed in there */
+
+	if (!strncmp(mdDev, "/dev/", 5))
+		mdDev += 5;
+
+	if ((fd = open("/proc/mdstat", O_RDONLY)) < 0) {
+		fprintf(stderr, _("grubby: failed to open /proc/mdstat: %s\n"),
+			strerror(errno));
+		return 2;
+	}
 
-	    if (j != tmplLine->numElements)
-		continue;
+	rc = read(fd, buf, sizeof(buf) - 1);
+	if (rc < 0 || rc == (sizeof(buf) - 1)) {
+		fprintf(stderr, _("grubby: failed to read /proc/mdstat: %s\n"),
+			strerror(errno));
+		close(fd);
+		return 2;
 	}
+	close(fd);
+	buf[rc] = '\0';
 
-	*end++ = separatorChar;
-	end = stpcpy(end, extraInitrd);
-    }
+	chptr = buf;
+	while (*chptr) {
+		end = strchr(chptr, '\n');
+		if (!end)
+			break;
+		*end = '\0';
+
+		if (!strncmp(chptr, mdDev, strlen(mdDev)) &&
+		    chptr[strlen(mdDev)] == ' ') {
+
+			/* found the device */
+			while (*chptr && *chptr != ':')
+				chptr++;
+			chptr++;
+			while (*chptr && isspace(*chptr))
+				chptr++;
+
+			/* skip the "active" bit */
+			while (*chptr && !isspace(*chptr))
+				chptr++;
+			while (*chptr && isspace(*chptr))
+				chptr++;
+
+			/* skip the raid level */
+			while (*chptr && !isspace(*chptr))
+				chptr++;
+			while (*chptr && isspace(*chptr))
+				chptr++;
+
+			/* everything else is partition stuff */
+			while (*chptr) {
+				chptr2 = chptr;
+				while (*chptr2 && *chptr2 != '[')
+					chptr2++;
+				if (!*chptr2)
+					break;
 
-    return initrdVal;
-}
+				/* yank off the numbers at the end */
+				chptr2--;
+				while (isdigit(*chptr2) && chptr2 > chptr)
+					chptr2--;
+				chptr2++;
+				*chptr2 = '\0';
+
+				/* Better, now we need the /dev/ back. We're done with
+				 * everything before this point, so we can just put
+				 * the /dev/ part there. There will always be room. */
+				memcpy(chptr - 5, "/dev/", 5);
+				rc = checkDeviceBootloader(chptr - 5, boot);
+				if (rc != 2) {
+					return rc;
+				}
 
-int addNewKernel(struct grubConfig * config, struct singleEntry * template, 
-	         const char * prefix,
-		 const char * newKernelPath, const char * newKernelTitle,
-		 const char * newKernelArgs, const char * newKernelInitrd,
-		 const char ** extraInitrds, int extraInitrdCount,
-                 const char * newMBKernel, const char * newMBKernelArgs) {
-    struct singleEntry * new;
-    struct singleLine * newLine = NULL, * tmplLine = NULL, * masterLine = NULL;
-    int needs;
-    char * chptr;
-
-    if (!newKernelPath) return 0;
-
-    /* if the newKernelTitle is too long silently munge it into something
-     * we can live with. truncating is first check, then we'll just mess with
-     * it until it looks better */
-    if (config->cfi->maxTitleLength && 
-	    (strlen(newKernelTitle) > config->cfi->maxTitleLength)) {
-	char * buf = alloca(config->cfi->maxTitleLength + 7);
-	char * numBuf = alloca(config->cfi->maxTitleLength + 1);
-	int i = 1;
-
-	sprintf(buf, "TITLE=%.*s", config->cfi->maxTitleLength, newKernelTitle);
-	while (findEntryByPath(config, buf, NULL, NULL)) {
-	    sprintf(numBuf, "%d", i++);
-	    strcpy(buf + strlen(buf) - strlen(numBuf), numBuf);
-	}
-
-	newKernelTitle = buf + 6;
-    }
-
-    new = malloc(sizeof(*new));
-    new->skip = 0;
-    new->multiboot = 0;
-    new->next = config->entries;
-    new->lines = NULL;
-    config->entries = new;
-
-    /* copy/update from the template */
-    needs = NEED_KERNEL | NEED_TITLE;
-    if (newKernelInitrd)
-	needs |= NEED_INITRD;
-    if (newMBKernel) {
-        needs |= NEED_MB;
-        new->multiboot = 1;
-    }
-
-    if (template) {
-	for (masterLine = template->lines; 
-	     masterLine && (tmplLine = lineDup(masterLine)); 
-	     lineFree(tmplLine), masterLine = masterLine->next) 
-	{
-	    dbgPrintf("addNewKernel processing %d\n", tmplLine->type);
-
-	    /* skip comments */
-	    chptr = tmplLine->indent;
-	    while (*chptr && isspace(*chptr)) chptr++;
-	    if (*chptr == '#') continue;
-
-	    if (iskernel(tmplLine->type) && tmplLine->numElements >= 2) {
-		if (!template->multiboot && (needs & NEED_MB)) {
-		    /* it's not a multiboot template and this is the kernel
-		     * line.  Try to be intelligent about inserting the
-		     * hypervisor at the same time.
-		     */
-		    if (config->cfi->mbHyperFirst) {
-			/* insert the hypervisor first */
-			newLine = addLine(new, config->cfi, LT_HYPER, 
-					  tmplLine->indent,
-					  newMBKernel + strlen(prefix));
-			/* set up for adding the kernel line */
-			free(tmplLine->indent);
-			tmplLine->indent = strdup(config->secondaryIndent);
-			needs &= ~NEED_MB;
-		    }
-		    if (needs & NEED_KERNEL) {
-			/* use addLineTmpl to preserve line elements,
-			 * otherwise we could just call addLine.  Unfortunately
-			 * this means making some changes to the template
-			 * such as the indent change above and the type
-			 * change below.
-			 */
-			struct keywordTypes * mbm_kw = 
-			    getKeywordByType(LT_MBMODULE, config->cfi);
-			if (mbm_kw) {
-			    tmplLine->type = LT_MBMODULE;
-			    free(tmplLine->elements[0].item);
-			    tmplLine->elements[0].item = strdup(mbm_kw->key);
+				chptr = chptr2 + 1;
+				/* skip the [11] bit */
+				while (*chptr && !isspace(*chptr))
+					chptr++;
+				/* and move to the next one */
+				while (*chptr && isspace(*chptr))
+					chptr++;
 			}
-			newLine = addLineTmpl(new, tmplLine, newLine,
-					      newKernelPath + strlen(prefix), config->cfi);
-			needs &= ~NEED_KERNEL;
-		    }
-		    if (needs & NEED_MB) { /* !mbHyperFirst */
-			newLine = addLine(new, config->cfi, LT_HYPER, 
-					  config->secondaryIndent,
-					  newMBKernel + strlen(prefix));
-			needs &= ~NEED_MB;
-		    }
-		} else if (needs & NEED_KERNEL) {
-		    newLine = addLineTmpl(new, tmplLine, newLine, 
-					  newKernelPath + strlen(prefix), config->cfi);
-		    needs &= ~NEED_KERNEL;
-		}
 
-	    } else if (tmplLine->type == LT_HYPER && 
-		       tmplLine->numElements >= 2) {
-		if (needs & NEED_MB) {
-		    newLine = addLineTmpl(new, tmplLine, newLine, 
-					  newMBKernel + strlen(prefix), config->cfi);
-		    needs &= ~NEED_MB;
+			/*  we're good to go */
+			return 2;
 		}
 
-	    } else if (tmplLine->type == LT_MBMODULE && 
-		       tmplLine->numElements >= 2) {
-		if (new->multiboot) {
-		    if (needs & NEED_KERNEL) {
-			newLine = addLineTmpl(new, tmplLine, newLine, 
-					      newKernelPath + 
-					      strlen(prefix), config->cfi);
-			needs &= ~NEED_KERNEL;
-		    } else if (config->cfi->mbInitRdIsModule &&
-			       (needs & NEED_INITRD)) {
-			char *initrdVal;
-			initrdVal = getInitrdVal(config, prefix, tmplLine,
-						 newKernelInitrd, extraInitrds,
-						 extraInitrdCount);
-			newLine = addLineTmpl(new, tmplLine, newLine,
-					      initrdVal, config->cfi);
-			free(initrdVal);
-			needs &= ~NEED_INITRD;
-		    }
-		} else if (needs & NEED_KERNEL) {
-		    /* template is multi but new is not, 
-		     * insert the kernel in the first module slot
-		     */
-		    tmplLine->type = preferredLineType(LT_KERNEL, config->cfi);
-		    free(tmplLine->elements[0].item);
-		    tmplLine->elements[0].item = 
-			strdup(getKeywordByType(tmplLine->type,
-						config->cfi)->key);
-		    newLine = addLineTmpl(new, tmplLine, newLine, 
-					  newKernelPath + strlen(prefix),
-					  config->cfi);
-		    needs &= ~NEED_KERNEL;
-		} else if (needs & NEED_INITRD) {
-		    char *initrdVal;
-		    /* template is multi but new is not,
-		     * insert the initrd in the second module slot
-		     */
-		    tmplLine->type = preferredLineType(LT_INITRD, config->cfi);
-		    free(tmplLine->elements[0].item);
-		    tmplLine->elements[0].item = 
-			strdup(getKeywordByType(tmplLine->type,
-						config->cfi)->key);
-		    initrdVal = getInitrdVal(config, prefix, tmplLine, newKernelInitrd, extraInitrds, extraInitrdCount);
-		    newLine = addLineTmpl(new, tmplLine, newLine, initrdVal, config->cfi);
-		    free(initrdVal);
-		    needs &= ~NEED_INITRD;
-		}
+		chptr = end + 1;
+	}
+
+	fprintf(stderr,
+		_("grubby: raid device /dev/%s not found in /proc/mdstat\n"),
+		mdDev);
+	return 0;
+}
+
+int checkForLilo(struct grubConfig *config)
+{
+	int fd;
+	unsigned char boot[512];
+	struct singleLine *line;
+
+	for (line = config->theLines; line; line = line->next)
+		if (line->type == LT_BOOT)
+			break;
+
+	if (!line) {
+		fprintf(stderr,
+			_
+			("grubby: no boot line found in lilo configuration\n"));
+		return 1;
+	}
+
+	if (line->numElements != 2)
+		return 1;
+
+	fd = open("/boot/boot.b", O_RDONLY);
+	if (fd < 0) {
+		fprintf(stderr, _("grubby: unable to open %s: %s\n"),
+			"/boot/boot.b", strerror(errno));
+		return 1;
+	}
+
+	if (read(fd, boot, 512) != 512) {
+		fprintf(stderr, _("grubby: unable to read %s: %s\n"),
+			"/boot/boot.b", strerror(errno));
+		return 1;
+	}
+	close(fd);
+
+	if (!strncmp("/dev/md", line->elements[1].item, 7))
+		return checkLiloOnRaid(line->elements[1].item, boot);
+
+	return checkDeviceBootloader(line->elements[1].item, boot);
+}
+
+int checkForGrub2(struct grubConfig *config)
+{
+	if (!access("/etc/grub.d/", R_OK))
+		return 2;
+
+	return 1;
+}
+
+int checkForGrub(struct grubConfig *config)
+{
+	int fd;
+	unsigned char bootSect[512];
+	char *boot;
+	int onSuse = isSuseSystem();
+
+	if (onSuse) {
+		if (parseSuseGrubConf(NULL, &boot))
+			return 0;
+	} else {
+		if (parseSysconfigGrub(NULL, &boot))
+			return 0;
+	}
+
+	/* assume grub is not installed -- not an error condition */
+	if (!boot)
+		return 0;
 
-	    } else if (isinitrd(tmplLine->type) && tmplLine->numElements >= 2) {
-		if (needs & NEED_INITRD &&
-		    new->multiboot && !template->multiboot &&
-		    config->cfi->mbInitRdIsModule) {
-		    /* make sure we don't insert the module initrd
-		     * before the module kernel... if we don't do it here,
-		     * it will be inserted following the template.
-		     */
-		    if (!needs & NEED_KERNEL) {
-			char *initrdVal;
-	
-			initrdVal = getInitrdVal(config, prefix, tmplLine, newKernelInitrd, extraInitrds, extraInitrdCount);
-			newLine = addLine(new, config->cfi, LT_MBMODULE,
-					  config->secondaryIndent, 
-					  initrdVal);
-			free(initrdVal);
-			needs &= ~NEED_INITRD;
-		    }
-		} else if (needs & NEED_INITRD) {
-		    char *initrdVal;
-		    initrdVal = getInitrdVal(config, prefix, tmplLine, newKernelInitrd, extraInitrds, extraInitrdCount);
-		    newLine = addLineTmpl(new, tmplLine, newLine, initrdVal, config->cfi);
-		    free(initrdVal);
-		    needs &= ~NEED_INITRD;
+	fd = open("/boot/grub/stage1", O_RDONLY);
+	if (fd < 0)
+		/* this doesn't exist if grub hasn't been installed */
+		return 0;
+
+	if (read(fd, bootSect, 512) != 512) {
+		fprintf(stderr, _("grubby: unable to read %s: %s\n"),
+			"/boot/grub/stage1", strerror(errno));
+		close(fd);
+		return 1;
+	}
+	close(fd);
+
+	/* The more elaborate checks do not work on SuSE. The checks done
+	 * seem to be reasonble (at least for now), so just return success
+	 */
+	if (onSuse)
+		return 2;
+
+	return checkDeviceBootloader(boot, bootSect);
+}
+
+int checkForExtLinux(struct grubConfig *config)
+{
+	int fd;
+	unsigned char bootSect[512];
+	char *boot;
+	char executable[] = "/boot/extlinux/extlinux";
+
+	printf("entered: checkForExtLinux()\n");
+
+	if (parseSysconfigGrub(NULL, &boot))
+		return 0;
+
+	/* assume grub is not installed -- not an error condition */
+	if (!boot)
+		return 0;
+
+	fd = open(executable, O_RDONLY);
+	if (fd < 0)
+		/* this doesn't exist if grub hasn't been installed */
+		return 0;
+
+	if (read(fd, bootSect, 512) != 512) {
+		fprintf(stderr, _("grubby: unable to read %s: %s\n"),
+			executable, strerror(errno));
+		return 1;
+	}
+	close(fd);
+
+	return checkDeviceBootloader(boot, bootSect);
+}
+
+int checkForYaboot(struct grubConfig *config)
+{
+	/*
+	 * This is a simplistic check that we consider good enough for own puporses
+	 *
+	 * If we were to properly check if yaboot is *installed* we'd need to:
+	 * 1) get the system boot device (LT_BOOT)
+	 * 2) considering it's a raw filesystem, check if the yaboot binary matches
+	 *    the content on the boot device
+	 * 3) if not, copy the binary to a temporary file and run "addnote" on it
+	 * 4) check again if binary and boot device contents match
+	 */
+	if (!access("/etc/yaboot.conf", R_OK))
+		return 2;
+
+	return 1;
+}
+
+int checkForElilo(struct grubConfig *config)
+{
+	if (!access("/etc/elilo.conf", R_OK))
+		return 2;
+
+	return 1;
+}
+
+static char *getRootSpecifier(char *str)
+{
+	char *idx, *rootspec = NULL;
+
+	if (*str == '(') {
+		idx = rootspec = strdup(str);
+		while (*idx && (*idx != ')') && (!isspace(*idx)))
+			idx++;
+		*(++idx) = '\0';
+	}
+	return rootspec;
+}
+
+static char *getInitrdVal(struct grubConfig *config,
+			  const char *prefix, struct singleLine *tmplLine,
+			  const char *newKernelInitrd,
+			  const char **extraInitrds, int extraInitrdCount)
+{
+	char *initrdVal, *end;
+	int i;
+	size_t totalSize;
+	size_t prefixLen;
+	char separatorChar;
+
+	prefixLen = strlen(prefix);
+	totalSize = strlen(newKernelInitrd) - prefixLen + 1 /* \0 */ ;
+
+	for (i = 0; i < extraInitrdCount; i++) {
+		totalSize += sizeof(separatorChar);
+		totalSize += strlen(extraInitrds[i]) - prefixLen;
+	}
+
+	initrdVal = end = malloc(totalSize);
+
+	end = stpcpy(end, newKernelInitrd + prefixLen);
+
+	separatorChar = getKeywordByType(LT_INITRD, config->cfi)->separatorChar;
+	for (i = 0; i < extraInitrdCount; i++) {
+		const char *extraInitrd;
+		int j;
+
+		extraInitrd = extraInitrds[i] + prefixLen;
+		/* Don't add entries that are already there */
+		if (tmplLine != NULL) {
+			for (j = 2; j < tmplLine->numElements; j++)
+				if (strcmp
+				    (extraInitrd,
+				     tmplLine->elements[j].item) == 0)
+					break;
+
+			if (j != tmplLine->numElements)
+				continue;
 		}
 
-	    } else if (tmplLine->type == LT_MENUENTRY &&
-		       (needs & NEED_TITLE)) {
-		requote(tmplLine, config->cfi);
-		char *nkt = malloc(strlen(newKernelTitle)+3);
-		strcpy(nkt, "'");
-		strcat(nkt, newKernelTitle);
-		strcat(nkt, "'");
-		newLine = addLineTmpl(new, tmplLine, newLine, nkt, config->cfi);
-		free(nkt);
-		needs &= ~NEED_TITLE;
-	    } else if (tmplLine->type == LT_TITLE && 
-		       (needs & NEED_TITLE)) {
-		if (tmplLine->numElements >= 2) {
-		    newLine = addLineTmpl(new, tmplLine, newLine, 
-					  newKernelTitle, config->cfi);
-		    needs &= ~NEED_TITLE;
-		} else if (tmplLine->numElements == 1 &&
-			   config->cfi->titleBracketed) {
-		    /* addLineTmpl doesn't handle titleBracketed */
-		    newLine = addLine(new, config->cfi, LT_TITLE,
-				      tmplLine->indent, newKernelTitle);
-		    needs &= ~NEED_TITLE;
+		*end++ = separatorChar;
+		end = stpcpy(end, extraInitrd);
+	}
+
+	return initrdVal;
+}
+
+int addNewKernel(struct grubConfig *config, struct singleEntry *template,
+		 const char *prefix,
+		 const char *newKernelPath, const char *newKernelTitle,
+		 const char *newKernelArgs, const char *newKernelInitrd,
+		 const char **extraInitrds, int extraInitrdCount,
+		 const char *newMBKernel, const char *newMBKernelArgs)
+{
+	struct singleEntry *new;
+	struct singleLine *newLine = NULL, *tmplLine = NULL, *masterLine = NULL;
+	int needs;
+	char *chptr;
+
+	if (!newKernelPath)
+		return 0;
+
+	/* if the newKernelTitle is too long silently munge it into something
+	 * we can live with. truncating is first check, then we'll just mess with
+	 * it until it looks better */
+	if (config->cfi->maxTitleLength &&
+	    (strlen(newKernelTitle) > config->cfi->maxTitleLength)) {
+		char *buf = alloca(config->cfi->maxTitleLength + 7);
+		char *numBuf = alloca(config->cfi->maxTitleLength + 1);
+		int i = 1;
+
+		sprintf(buf, "TITLE=%.*s", config->cfi->maxTitleLength,
+			newKernelTitle);
+		while (findEntryByPath(config, buf, NULL, NULL)) {
+			sprintf(numBuf, "%d", i++);
+			strcpy(buf + strlen(buf) - strlen(numBuf), numBuf);
 		}
-	    } else if (tmplLine->type == LT_ECHO) {
-		    requote(tmplLine, config->cfi);
-		    static const char *prefix = "'Loading ";
-		    if (tmplLine->numElements > 1 &&
-			    strstr(tmplLine->elements[1].item, prefix) &&
-			    masterLine->next &&
-			    iskernel(masterLine->next->type)) {
-			char *newTitle = malloc(strlen(prefix) +
-						strlen(newKernelTitle) + 2);
-
-			strcpy(newTitle, prefix);
-			strcat(newTitle, newKernelTitle);
-			strcat(newTitle, "'");
-			newLine = addLine(new, config->cfi, LT_ECHO,
-					tmplLine->indent, newTitle);
-			free(newTitle);
-		    } else {
-			/* pass through other lines from the template */
-			newLine = addLineTmpl(new, tmplLine, newLine, NULL,
-						config->cfi);
-		    }
-	    } else {
-		/* pass through other lines from the template */
-		newLine = addLineTmpl(new, tmplLine, newLine, NULL, config->cfi);
-	    }
+
+		newKernelTitle = buf + 6;
 	}
 
-    } else {
-	/* don't have a template, so start the entry with the 
-	 * appropriate starting line 
-	 */
-	switch (config->cfi->entryStart) {
-	    case LT_KERNEL:
-	    case LT_KERNEL_EFI:
-	    case LT_KERNEL_16:
-		if (new->multiboot && config->cfi->mbHyperFirst) {
-		    /* fall through to LT_HYPER */
-		} else {
-		    newLine = addLine(new, config->cfi,
-		    		      preferredLineType(LT_KERNEL, config->cfi),
-				      config->primaryIndent,
-				      newKernelPath + strlen(prefix));
-		    needs &= ~NEED_KERNEL;
-		    break;
+	new = malloc(sizeof(*new));
+	new->skip = 0;
+	new->multiboot = 0;
+	new->next = config->entries;
+	new->lines = NULL;
+	config->entries = new;
+
+	/* copy/update from the template */
+	needs = NEED_KERNEL | NEED_TITLE;
+	if (newKernelInitrd)
+		needs |= NEED_INITRD;
+	if (newMBKernel) {
+		needs |= NEED_MB;
+		new->multiboot = 1;
+	}
+
+	if (template) {
+		for (masterLine = template->lines;
+		     masterLine && (tmplLine = lineDup(masterLine));
+		     lineFree(tmplLine), masterLine = masterLine->next) {
+			dbgPrintf("addNewKernel processing %d\n",
+				  tmplLine->type);
+
+			/* skip comments */
+			chptr = tmplLine->indent;
+			while (*chptr && isspace(*chptr))
+				chptr++;
+			if (*chptr == '#')
+				continue;
+
+			if (iskernel(tmplLine->type)
+			    && tmplLine->numElements >= 2) {
+				if (!template->multiboot && (needs & NEED_MB)) {
+					/* it's not a multiboot template and this is the kernel
+					 * line.  Try to be intelligent about inserting the
+					 * hypervisor at the same time.
+					 */
+					if (config->cfi->mbHyperFirst) {
+						/* insert the hypervisor first */
+						newLine =
+						    addLine(new, config->cfi,
+							    LT_HYPER,
+							    tmplLine->indent,
+							    newMBKernel +
+							    strlen(prefix));
+						/* set up for adding the kernel line */
+						free(tmplLine->indent);
+						tmplLine->indent =
+						    strdup(config->
+							   secondaryIndent);
+						needs &= ~NEED_MB;
+					}
+					if (needs & NEED_KERNEL) {
+						/* use addLineTmpl to preserve line elements,
+						 * otherwise we could just call addLine.  Unfortunately
+						 * this means making some changes to the template
+						 * such as the indent change above and the type
+						 * change below.
+						 */
+						struct keywordTypes *mbm_kw =
+						    getKeywordByType
+						    (LT_MBMODULE, config->cfi);
+						if (mbm_kw) {
+							tmplLine->type =
+							    LT_MBMODULE;
+							free(tmplLine->
+							     elements[0].item);
+							tmplLine->elements[0].
+							    item =
+							    strdup(mbm_kw->key);
+						}
+						newLine =
+						    addLineTmpl(new, tmplLine,
+								newLine,
+								newKernelPath +
+								strlen(prefix),
+								config->cfi);
+						needs &= ~NEED_KERNEL;
+					}
+					if (needs & NEED_MB) {	/* !mbHyperFirst */
+						newLine =
+						    addLine(new, config->cfi,
+							    LT_HYPER,
+							    config->
+							    secondaryIndent,
+							    newMBKernel +
+							    strlen(prefix));
+						needs &= ~NEED_MB;
+					}
+				} else if (needs & NEED_KERNEL) {
+					newLine =
+					    addLineTmpl(new, tmplLine, newLine,
+							newKernelPath +
+							strlen(prefix),
+							config->cfi);
+					needs &= ~NEED_KERNEL;
+				}
+
+			} else if (tmplLine->type == LT_HYPER &&
+				   tmplLine->numElements >= 2) {
+				if (needs & NEED_MB) {
+					newLine =
+					    addLineTmpl(new, tmplLine, newLine,
+							newMBKernel +
+							strlen(prefix),
+							config->cfi);
+					needs &= ~NEED_MB;
+				}
+
+			} else if (tmplLine->type == LT_MBMODULE &&
+				   tmplLine->numElements >= 2) {
+				if (new->multiboot) {
+					if (needs & NEED_KERNEL) {
+						newLine =
+						    addLineTmpl(new, tmplLine,
+								newLine,
+								newKernelPath +
+								strlen(prefix),
+								config->cfi);
+						needs &= ~NEED_KERNEL;
+					} else if (config->cfi->mbInitRdIsModule
+						   && (needs & NEED_INITRD)) {
+						char *initrdVal;
+						initrdVal =
+						    getInitrdVal(config, prefix,
+								 tmplLine,
+								 newKernelInitrd,
+								 extraInitrds,
+								 extraInitrdCount);
+						newLine =
+						    addLineTmpl(new, tmplLine,
+								newLine,
+								initrdVal,
+								config->cfi);
+						free(initrdVal);
+						needs &= ~NEED_INITRD;
+					}
+				} else if (needs & NEED_KERNEL) {
+					/* template is multi but new is not, 
+					 * insert the kernel in the first module slot
+					 */
+					tmplLine->type =
+					    preferredLineType(LT_KERNEL,
+							      config->cfi);
+					free(tmplLine->elements[0].item);
+					tmplLine->elements[0].item =
+					    strdup(getKeywordByType
+						   (tmplLine->type,
+						    config->cfi)->key);
+					newLine =
+					    addLineTmpl(new, tmplLine, newLine,
+							newKernelPath +
+							strlen(prefix),
+							config->cfi);
+					needs &= ~NEED_KERNEL;
+				} else if (needs & NEED_INITRD) {
+					char *initrdVal;
+					/* template is multi but new is not,
+					 * insert the initrd in the second module slot
+					 */
+					tmplLine->type =
+					    preferredLineType(LT_INITRD,
+							      config->cfi);
+					free(tmplLine->elements[0].item);
+					tmplLine->elements[0].item =
+					    strdup(getKeywordByType
+						   (tmplLine->type,
+						    config->cfi)->key);
+					initrdVal =
+					    getInitrdVal(config, prefix,
+							 tmplLine,
+							 newKernelInitrd,
+							 extraInitrds,
+							 extraInitrdCount);
+					newLine =
+					    addLineTmpl(new, tmplLine, newLine,
+							initrdVal, config->cfi);
+					free(initrdVal);
+					needs &= ~NEED_INITRD;
+				}
+
+			} else if (isinitrd(tmplLine->type)
+				   && tmplLine->numElements >= 2) {
+				if (needs & NEED_INITRD && new->multiboot
+				    && !template->multiboot
+				    && config->cfi->mbInitRdIsModule) {
+					/* make sure we don't insert the module initrd
+					 * before the module kernel... if we don't do it here,
+					 * it will be inserted following the template.
+					 */
+					if (!needs & NEED_KERNEL) {
+						char *initrdVal;
+
+						initrdVal =
+						    getInitrdVal(config, prefix,
+								 tmplLine,
+								 newKernelInitrd,
+								 extraInitrds,
+								 extraInitrdCount);
+						newLine =
+						    addLine(new, config->cfi,
+							    LT_MBMODULE,
+							    config->
+							    secondaryIndent,
+							    initrdVal);
+						free(initrdVal);
+						needs &= ~NEED_INITRD;
+					}
+				} else if (needs & NEED_INITRD) {
+					char *initrdVal;
+					initrdVal =
+					    getInitrdVal(config, prefix,
+							 tmplLine,
+							 newKernelInitrd,
+							 extraInitrds,
+							 extraInitrdCount);
+					newLine =
+					    addLineTmpl(new, tmplLine, newLine,
+							initrdVal, config->cfi);
+					free(initrdVal);
+					needs &= ~NEED_INITRD;
+				}
+
+			} else if (tmplLine->type == LT_MENUENTRY &&
+				   (needs & NEED_TITLE)) {
+				requote(tmplLine, config->cfi);
+				char *nkt = malloc(strlen(newKernelTitle) + 3);
+				strcpy(nkt, "'");
+				strcat(nkt, newKernelTitle);
+				strcat(nkt, "'");
+				newLine =
+				    addLineTmpl(new, tmplLine, newLine, nkt,
+						config->cfi);
+				free(nkt);
+				needs &= ~NEED_TITLE;
+			} else if (tmplLine->type == LT_TITLE &&
+				   (needs & NEED_TITLE)) {
+				if (tmplLine->numElements >= 2) {
+					newLine =
+					    addLineTmpl(new, tmplLine, newLine,
+							newKernelTitle,
+							config->cfi);
+					needs &= ~NEED_TITLE;
+				} else if (tmplLine->numElements == 1 &&
+					   config->cfi->titleBracketed) {
+					/* addLineTmpl doesn't handle titleBracketed */
+					newLine =
+					    addLine(new, config->cfi, LT_TITLE,
+						    tmplLine->indent,
+						    newKernelTitle);
+					needs &= ~NEED_TITLE;
+				}
+			} else if (tmplLine->type == LT_ECHO) {
+				requote(tmplLine, config->cfi);
+				static const char *prefix = "'Loading ";
+				if (tmplLine->numElements > 1 &&
+				    strstr(tmplLine->elements[1].item, prefix)
+				    && masterLine->next
+				    && iskernel(masterLine->next->type)) {
+					char *newTitle =
+					    malloc(strlen(prefix) +
+						   strlen(newKernelTitle) + 2);
+
+					strcpy(newTitle, prefix);
+					strcat(newTitle, newKernelTitle);
+					strcat(newTitle, "'");
+					newLine =
+					    addLine(new, config->cfi, LT_ECHO,
+						    tmplLine->indent, newTitle);
+					free(newTitle);
+				} else {
+					/* pass through other lines from the template */
+					newLine =
+					    addLineTmpl(new, tmplLine, newLine,
+							NULL, config->cfi);
+				}
+			} else {
+				/* pass through other lines from the template */
+				newLine =
+				    addLineTmpl(new, tmplLine, newLine, NULL,
+						config->cfi);
+			}
 		}
 
-	    case LT_HYPER:
-		newLine = addLine(new, config->cfi, LT_HYPER,
-				  config->primaryIndent,
-				  newMBKernel + strlen(prefix));
-		needs &= ~NEED_MB;
-		break;
+	} else {
+		/* don't have a template, so start the entry with the 
+		 * appropriate starting line 
+		 */
+		switch (config->cfi->entryStart) {
+		case LT_KERNEL:
+		case LT_KERNEL_EFI:
+		case LT_KERNEL_16:
+			if (new->multiboot && config->cfi->mbHyperFirst) {
+				/* fall through to LT_HYPER */
+			} else {
+				newLine = addLine(new, config->cfi,
+						  preferredLineType(LT_KERNEL,
+								    config->
+								    cfi),
+						  config->primaryIndent,
+						  newKernelPath +
+						  strlen(prefix));
+				needs &= ~NEED_KERNEL;
+				break;
+			}
 
-	    case LT_MENUENTRY: {
-		char *nkt = malloc(strlen(newKernelTitle)+3);
-		strcpy(nkt, "'");
-		strcat(nkt, newKernelTitle);
-		strcat(nkt, "'");
-	        newLine = addLine(new, config->cfi, LT_MENUENTRY,
-				  config->primaryIndent, nkt);
-		free(nkt);
-		needs &= ~NEED_TITLE;
-		needs |= NEED_END;
-		break;
-	    }
-	    case LT_TITLE:
-		if( useextlinuxmenu != 0 ){	// We just need useextlinuxmenu to not be zero (set above)
-			char * templabel;
-			int x = 0, y = 0;
-
-			templabel = strdup(newKernelTitle);
-			while( templabel[x]){
-				if( templabel[x] == ' ' ){
-					y = x;
-					while( templabel[y] ){
-						templabel[y] = templabel[y+1];
-						y++;
+		case LT_HYPER:
+			newLine = addLine(new, config->cfi, LT_HYPER,
+					  config->primaryIndent,
+					  newMBKernel + strlen(prefix));
+			needs &= ~NEED_MB;
+			break;
+
+		case LT_MENUENTRY:{
+				char *nkt = malloc(strlen(newKernelTitle) + 3);
+				strcpy(nkt, "'");
+				strcat(nkt, newKernelTitle);
+				strcat(nkt, "'");
+				newLine =
+				    addLine(new, config->cfi, LT_MENUENTRY,
+					    config->primaryIndent, nkt);
+				free(nkt);
+				needs &= ~NEED_TITLE;
+				needs |= NEED_END;
+				break;
+			}
+		case LT_TITLE:
+			if (useextlinuxmenu != 0) {	// We just need useextlinuxmenu to not be zero (set above)
+				char *templabel;
+				int x = 0, y = 0;
+
+				templabel = strdup(newKernelTitle);
+				while (templabel[x]) {
+					if (templabel[x] == ' ') {
+						y = x;
+						while (templabel[y]) {
+							templabel[y] =
+							    templabel[y + 1];
+							y++;
+						}
 					}
+					x++;
 				}
-				x++;
+				newLine = addLine(new, config->cfi, LT_TITLE,
+						  config->primaryIndent,
+						  templabel);
+				free(templabel);
+			} else {
+				newLine = addLine(new, config->cfi, LT_TITLE,
+						  config->primaryIndent,
+						  newKernelTitle);
 			}
-			newLine = addLine(new, config->cfi, LT_TITLE,
-					  config->primaryIndent, templabel);
-			free(templabel);
-		}else{
-			newLine = addLine(new, config->cfi, LT_TITLE,
-					  config->primaryIndent, newKernelTitle);
+			needs &= ~NEED_TITLE;
+			break;
+
+		default:
+			abort();
 		}
+	}
+
+	struct singleLine *endLine = NULL;
+	endLine = getLineByType(LT_ENTRY_END, new->lines);
+	if (endLine) {
+		removeLine(new, endLine);
+		needs |= NEED_END;
+	}
+
+	/* add the remainder of the lines, i.e. those that either
+	 * weren't present in the template, or in the case of no template,
+	 * all the lines following the entryStart.
+	 */
+	if (needs & NEED_TITLE) {
+		newLine = addLine(new, config->cfi, LT_TITLE,
+				  config->secondaryIndent, newKernelTitle);
 		needs &= ~NEED_TITLE;
-		break;
+	}
+	if ((needs & NEED_MB) && config->cfi->mbHyperFirst) {
+		newLine = addLine(new, config->cfi, LT_HYPER,
+				  config->secondaryIndent,
+				  newMBKernel + strlen(prefix));
+		needs &= ~NEED_MB;
+	}
+	if (needs & NEED_KERNEL) {
+		newLine = addLine(new, config->cfi,
+				  (new->multiboot
+				   && getKeywordByType(LT_MBMODULE,
+						       config->cfi))
+				  ? LT_MBMODULE : preferredLineType(LT_KERNEL,
+								    config->
+								    cfi),
+				  config->secondaryIndent,
+				  newKernelPath + strlen(prefix));
+		needs &= ~NEED_KERNEL;
+	}
+	if (needs & NEED_MB) {
+		newLine = addLine(new, config->cfi, LT_HYPER,
+				  config->secondaryIndent,
+				  newMBKernel + strlen(prefix));
+		needs &= ~NEED_MB;
+	}
+	if (needs & NEED_INITRD) {
+		char *initrdVal;
+		initrdVal =
+		    getInitrdVal(config, prefix, NULL, newKernelInitrd,
+				 extraInitrds, extraInitrdCount);
+		newLine =
+		    addLine(new, config->cfi,
+			    (new->multiboot
+			     && getKeywordByType(LT_MBMODULE, config->cfi))
+			    ? LT_MBMODULE : preferredLineType(LT_INITRD,
+							      config->cfi),
+			    config->secondaryIndent, initrdVal);
+		free(initrdVal);
+		needs &= ~NEED_INITRD;
+	}
+	if (needs & NEED_END) {
+		newLine = addLine(new, config->cfi, LT_ENTRY_END,
+				  config->secondaryIndent, NULL);
+		needs &= ~NEED_END;
+	}
 
-	    default:
+	if (needs) {
+		printf(_("grubby: needs=%d, aborting\n"), needs);
 		abort();
 	}
-    } 
-
-    struct singleLine *endLine = NULL;
-    endLine = getLineByType(LT_ENTRY_END, new->lines);
-    if (endLine) {
-	    removeLine(new, endLine);
-	    needs |= NEED_END;
-    }
-
-    /* add the remainder of the lines, i.e. those that either
-     * weren't present in the template, or in the case of no template,
-     * all the lines following the entryStart.
-     */
-    if (needs & NEED_TITLE) {
-	newLine = addLine(new, config->cfi, LT_TITLE, 
-			  config->secondaryIndent, 
-			  newKernelTitle);
-	needs &= ~NEED_TITLE;
-    }
-    if ((needs & NEED_MB) && config->cfi->mbHyperFirst) {
-	newLine = addLine(new, config->cfi, LT_HYPER, 
-			  config->secondaryIndent, 
-			  newMBKernel + strlen(prefix));
-	needs &= ~NEED_MB;
-    }
-    if (needs & NEED_KERNEL) {
-	newLine = addLine(new, config->cfi, 
-			  (new->multiboot && getKeywordByType(LT_MBMODULE, 
-							      config->cfi))
-			  	? LT_MBMODULE
-				: preferredLineType(LT_KERNEL, config->cfi),
-			  config->secondaryIndent, 
-			  newKernelPath + strlen(prefix));
-	needs &= ~NEED_KERNEL;
-    }
-    if (needs & NEED_MB) {
-	newLine = addLine(new, config->cfi, LT_HYPER, 
-			  config->secondaryIndent,
-			  newMBKernel + strlen(prefix));
-	needs &= ~NEED_MB;
-    }
-    if (needs & NEED_INITRD) {
-	char *initrdVal;
-	initrdVal = getInitrdVal(config, prefix, NULL, newKernelInitrd, extraInitrds, extraInitrdCount);
-	newLine = addLine(new, config->cfi,
-			  (new->multiboot && getKeywordByType(LT_MBMODULE,
-							      config->cfi))
-			   ? LT_MBMODULE
-			   : preferredLineType(LT_INITRD, config->cfi), 
-			  config->secondaryIndent, 
-			  initrdVal);
-	free(initrdVal);
-	needs &= ~NEED_INITRD;
-    }
-    if (needs & NEED_END) {
-	newLine = addLine(new, config->cfi, LT_ENTRY_END,
-			config->secondaryIndent, NULL);
-	needs &= ~NEED_END;
-    }
-
-    if (needs) {
-	printf(_("grubby: needs=%d, aborting\n"), needs);
-	abort();
-    }
-
-    if (updateImage(config, "0", prefix, newKernelArgs, NULL, 
-                    newMBKernelArgs, NULL)) return 1;
-
-    return 0;
+
+	if (updateImage(config, "0", prefix, newKernelArgs, NULL,
+			newMBKernelArgs, NULL))
+		return 1;
+
+	return 0;
 }
 
-int main(int argc, const char ** argv) {
-    poptContext optCon;
-    const char * grubConfig = NULL;
-    char * outputFile = NULL;
-    int arg = 0;
-    int flags = 0;
-    int badImageOkay = 0;
-    int configureGrub2 = 0;
-    int configureLilo = 0, configureELilo = 0, configureGrub = 0;
-    int configureYaboot = 0, configureSilo = 0, configureZipl = 0;
-    int configureExtLinux = 0;
-    int bootloaderProbe = 0;
-    int extraInitrdCount = 0;
-    char * updateKernelPath = NULL;
-    char * newKernelPath = NULL;
-    char * removeKernelPath = NULL;
-    char * newKernelArgs = NULL;
-    char * newKernelInitrd = NULL;
-    char * newKernelTitle = NULL;
-    char * newKernelVersion = NULL;
-    char * newMBKernel = NULL;
-    char * newMBKernelArgs = NULL;
-    char * removeMBKernelArgs = NULL;
-    char * removeMBKernel = NULL;
-    char * bootPrefix = NULL;
-    char * defaultKernel = NULL;
-    char * removeArgs = NULL;
-    char * kernelInfo = NULL;
-    char * extraInitrds[MAX_EXTRA_INITRDS] = { NULL };
-    char * envPath = NULL;
-    const char * chptr = NULL;
-    struct configFileInfo * cfi = NULL;
-    struct grubConfig * config;
-    struct singleEntry * template = NULL;
-    int copyDefault = 0, makeDefault = 0;
-    int displayDefault = 0;
-    int displayDefaultIndex = 0;
-    int displayDefaultTitle = 0;
-    int defaultIndex = -1;
-    struct poptOption options[] = {
-	{ "add-kernel", 0, POPT_ARG_STRING, &newKernelPath, 0,
-	    _("add an entry for the specified kernel"), _("kernel-path") },
-	{ "add-multiboot", 0, POPT_ARG_STRING, &newMBKernel, 0,
-	    _("add an entry for the specified multiboot kernel"), NULL },
-	{ "args", 0, POPT_ARG_STRING, &newKernelArgs, 0, 
-	    _("default arguments for the new kernel or new arguments for "
-	      "kernel being updated"), _("args") },
-	{ "mbargs", 0, POPT_ARG_STRING, &newMBKernelArgs, 0, 
-	    _("default arguments for the new multiboot kernel or "
-              "new arguments for multiboot kernel being updated"), NULL },
-	{ "bad-image-okay", 0, 0, &badImageOkay, 0,
-	    _("don't sanity check images in boot entries (for testing only)"), 
-	    NULL },
-	{ "boot-filesystem", 0, POPT_ARG_STRING, &bootPrefix, 0,
-	    _("filestystem which contains /boot directory (for testing only)"),
-	    _("bootfs") },
+int main(int argc, const char **argv)
+{
+	poptContext optCon;
+	const char *grubConfig = NULL;
+	char *outputFile = NULL;
+	int arg = 0;
+	int flags = 0;
+	int badImageOkay = 0;
+	int configureGrub2 = 0;
+	int configureLilo = 0, configureELilo = 0, configureGrub = 0;
+	int configureYaboot = 0, configureSilo = 0, configureZipl = 0;
+	int configureExtLinux = 0;
+	int bootloaderProbe = 0;
+	int extraInitrdCount = 0;
+	char *updateKernelPath = NULL;
+	char *newKernelPath = NULL;
+	char *removeKernelPath = NULL;
+	char *newKernelArgs = NULL;
+	char *newKernelInitrd = NULL;
+	char *newKernelTitle = NULL;
+	char *newKernelVersion = NULL;
+	char *newMBKernel = NULL;
+	char *newMBKernelArgs = NULL;
+	char *removeMBKernelArgs = NULL;
+	char *removeMBKernel = NULL;
+	char *bootPrefix = NULL;
+	char *defaultKernel = NULL;
+	char *removeArgs = NULL;
+	char *kernelInfo = NULL;
+	char *extraInitrds[MAX_EXTRA_INITRDS] = { NULL };
+	char *envPath = NULL;
+	const char *chptr = NULL;
+	struct configFileInfo *cfi = NULL;
+	struct grubConfig *config;
+	struct singleEntry *template = NULL;
+	int copyDefault = 0, makeDefault = 0;
+	int displayDefault = 0;
+	int displayDefaultIndex = 0;
+	int displayDefaultTitle = 0;
+	int defaultIndex = -1;
+	struct poptOption options[] = {
+		{"add-kernel", 0, POPT_ARG_STRING, &newKernelPath, 0,
+		 _("add an entry for the specified kernel"), _("kernel-path")},
+		{"add-multiboot", 0, POPT_ARG_STRING, &newMBKernel, 0,
+		 _("add an entry for the specified multiboot kernel"), NULL},
+		{"args", 0, POPT_ARG_STRING, &newKernelArgs, 0,
+		 _("default arguments for the new kernel or new arguments for "
+		   "kernel being updated"), _("args")},
+		{"mbargs", 0, POPT_ARG_STRING, &newMBKernelArgs, 0,
+		 _("default arguments for the new multiboot kernel or "
+		   "new arguments for multiboot kernel being updated"), NULL},
+		{"bad-image-okay", 0, 0, &badImageOkay, 0,
+		 _
+		 ("don't sanity check images in boot entries (for testing only)"),
+		 NULL},
+		{"boot-filesystem", 0, POPT_ARG_STRING, &bootPrefix, 0,
+		 _
+		 ("filestystem which contains /boot directory (for testing only)"),
+		 _("bootfs")},
 #if defined(__i386__) || defined(__x86_64__) || defined (__powerpc64__) || defined (__ia64__)
-	{ "bootloader-probe", 0, POPT_ARG_NONE, &bootloaderProbe, 0,
-	    _("check which bootloader is installed on boot sector") },
+		{"bootloader-probe", 0, POPT_ARG_NONE, &bootloaderProbe, 0,
+		 _("check which bootloader is installed on boot sector")},
 #endif
-	{ "config-file", 'c', POPT_ARG_STRING, &grubConfig, 0,
-	    _("path to grub config file to update (\"-\" for stdin)"), 
-	    _("path") },
-	{ "copy-default", 0, 0, &copyDefault, 0,
-	    _("use the default boot entry as a template for the new entry "
-	      "being added; if the default is not a linux image, or if "
-	      "the kernel referenced by the default image does not exist, "
-	      "the first linux entry whose kernel does exist is used as the "
-	      "template"), NULL },
-	{ "debug", 0, 0, &debug, 0,
-	    _("print debugging information for failures") },
-	{ "default-kernel", 0, 0, &displayDefault, 0,
-	    _("display the path of the default kernel") },
-	{ "default-index", 0, 0, &displayDefaultIndex, 0,
-	    _("display the index of the default kernel") },
-	{ "default-title", 0, 0, &displayDefaultTitle, 0,
-	    _("display the title of the default kernel") },
-	{ "elilo", 0, POPT_ARG_NONE, &configureELilo, 0,
-	    _("configure elilo bootloader") },
-	{ "efi", 0, POPT_ARG_NONE, &isEfi, 0,
-	    _("force grub2 stanzas to use efi") },
-	{ "env", 0, POPT_ARG_STRING, &envPath, 0,
-	    _("path for environment data"),
-	    _("path") },
-	{ "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0,
-	    _("configure extlinux bootloader (from syslinux)") },
-	{ "grub", 0, POPT_ARG_NONE, &configureGrub, 0,
-	    _("configure grub bootloader") },
-	{ "grub2", 0, POPT_ARG_NONE, &configureGrub2, 0,
-	    _("configure grub2 bootloader") },
-	{ "info", 0, POPT_ARG_STRING, &kernelInfo, 0,
-	    _("display boot information for specified kernel"),
-	    _("kernel-path") },
-	{ "initrd", 0, POPT_ARG_STRING, &newKernelInitrd, 0,
-	    _("initrd image for the new kernel"), _("initrd-path") },
-	{ "extra-initrd", 'i', POPT_ARG_STRING, NULL, 'i',
-	    _("auxiliary initrd image for things other than the new kernel"), _("initrd-path") },
-	{ "lilo", 0, POPT_ARG_NONE, &configureLilo, 0,
-	    _("configure lilo bootloader") },
-	{ "make-default", 0, 0, &makeDefault, 0,
-	    _("make the newly added entry the default boot entry"), NULL },
-	{ "output-file", 'o', POPT_ARG_STRING, &outputFile, 0,
-	    _("path to output updated config file (\"-\" for stdout)"), 
-	    _("path") },
-	{ "remove-args", 0, POPT_ARG_STRING, &removeArgs, 0,
-            _("remove kernel arguments"), NULL },
-        { "remove-mbargs", 0, POPT_ARG_STRING, &removeMBKernelArgs, 0,
-	    _("remove multiboot kernel arguments"), NULL },
-	{ "remove-kernel", 0, POPT_ARG_STRING, &removeKernelPath, 0,
-	    _("remove all entries for the specified kernel"), 
-	    _("kernel-path") },
-	{ "remove-multiboot", 0, POPT_ARG_STRING, &removeMBKernel, 0,
-            _("remove all entries for the specified multiboot kernel"), NULL },
-	{ "set-default", 0, POPT_ARG_STRING, &defaultKernel, 0,
-	    _("make the first entry referencing the specified kernel "
-	      "the default"), _("kernel-path") },
-	{ "set-default-index", 0, POPT_ARG_INT, &defaultIndex, 0,
-	    _("make the given entry index the default entry"),
-	    _("entry-index") },
-	{ "silo", 0, POPT_ARG_NONE, &configureSilo, 0,
-	    _("configure silo bootloader") },
-	{ "title", 0, POPT_ARG_STRING, &newKernelTitle, 0,
-	    _("title to use for the new kernel entry"), _("entry-title") },
-	{ "update-kernel", 0, POPT_ARG_STRING, &updateKernelPath, 0,
-	    _("updated information for the specified kernel"), 
-	    _("kernel-path") },
-	{ "version", 'v', 0, NULL, 'v',
-	    _("print the version of this program and exit"), NULL },
-	{ "yaboot", 0, POPT_ARG_NONE, &configureYaboot, 0,
-	    _("configure yaboot bootloader") },
-	{ "zipl", 0, POPT_ARG_NONE, &configureZipl, 0,
-	    _("configure zipl bootloader") },
-	POPT_AUTOHELP
-	{ 0, 0, 0, 0, 0 }
-    };
-
-    useextlinuxmenu=0;
-
-    int i = 0;
-    for (int j = 1; j < argc; j++)
-	i += strlen(argv[j]) + 1;
-    saved_command_line = malloc(i);
-    if (!saved_command_line) {
-	fprintf(stderr, "grubby: %m\n");
-	exit(1);
-    }
-    saved_command_line[0] = '\0';
-    for (int j = 1; j < argc; j++) {
-	strcat(saved_command_line, argv[j]);
-	strncat(saved_command_line, j == argc -1 ? "" : " ", 1);
-    }
-
-    optCon = poptGetContext("grubby", argc, argv, options, 0);
-    poptReadDefaultConfig(optCon, 1);
-
-    while ((arg = poptGetNextOpt(optCon)) >= 0) {
-	switch (arg) {
-	  case 'v':
-	    printf("grubby version %s\n", VERSION);
-	    exit(0);
-	    break;
-	  case 'i':
-	    if (extraInitrdCount < MAX_EXTRA_INITRDS) {
-	    	extraInitrds[extraInitrdCount++] = strdup(poptGetOptArg(optCon));
-	    } else {
-		fprintf(stderr, _("grubby: extra initrd maximum is %d\n"), extraInitrdCount);
+		{"config-file", 'c', POPT_ARG_STRING, &grubConfig, 0,
+		 _("path to grub config file to update (\"-\" for stdin)"),
+		 _("path")},
+		{"copy-default", 0, 0, &copyDefault, 0,
+		 _("use the default boot entry as a template for the new entry "
+		   "being added; if the default is not a linux image, or if "
+		   "the kernel referenced by the default image does not exist, "
+		   "the first linux entry whose kernel does exist is used as the "
+		   "template"), NULL},
+		{"debug", 0, 0, &debug, 0,
+		 _("print debugging information for failures")},
+		{"default-kernel", 0, 0, &displayDefault, 0,
+		 _("display the path of the default kernel")},
+		{"default-index", 0, 0, &displayDefaultIndex, 0,
+		 _("display the index of the default kernel")},
+		{"default-title", 0, 0, &displayDefaultTitle, 0,
+		 _("display the title of the default kernel")},
+		{"elilo", 0, POPT_ARG_NONE, &configureELilo, 0,
+		 _("configure elilo bootloader")},
+		{"efi", 0, POPT_ARG_NONE, &isEfi, 0,
+		 _("force grub2 stanzas to use efi")},
+		{"env", 0, POPT_ARG_STRING, &envPath, 0,
+		 _("path for environment data"),
+		 _("path")},
+		{"extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0,
+		 _("configure extlinux bootloader (from syslinux)")},
+		{"grub", 0, POPT_ARG_NONE, &configureGrub, 0,
+		 _("configure grub bootloader")},
+		{"grub2", 0, POPT_ARG_NONE, &configureGrub2, 0,
+		 _("configure grub2 bootloader")},
+		{"info", 0, POPT_ARG_STRING, &kernelInfo, 0,
+		 _("display boot information for specified kernel"),
+		 _("kernel-path")},
+		{"initrd", 0, POPT_ARG_STRING, &newKernelInitrd, 0,
+		 _("initrd image for the new kernel"), _("initrd-path")},
+		{"extra-initrd", 'i', POPT_ARG_STRING, NULL, 'i',
+		 _
+		 ("auxiliary initrd image for things other than the new kernel"),
+		 _("initrd-path")},
+		{"lilo", 0, POPT_ARG_NONE, &configureLilo, 0,
+		 _("configure lilo bootloader")},
+		{"make-default", 0, 0, &makeDefault, 0,
+		 _("make the newly added entry the default boot entry"), NULL},
+		{"output-file", 'o', POPT_ARG_STRING, &outputFile, 0,
+		 _("path to output updated config file (\"-\" for stdout)"),
+		 _("path")},
+		{"remove-args", 0, POPT_ARG_STRING, &removeArgs, 0,
+		 _("remove kernel arguments"), NULL},
+		{"remove-mbargs", 0, POPT_ARG_STRING, &removeMBKernelArgs, 0,
+		 _("remove multiboot kernel arguments"), NULL},
+		{"remove-kernel", 0, POPT_ARG_STRING, &removeKernelPath, 0,
+		 _("remove all entries for the specified kernel"),
+		 _("kernel-path")},
+		{"remove-multiboot", 0, POPT_ARG_STRING, &removeMBKernel, 0,
+		 _("remove all entries for the specified multiboot kernel"),
+		 NULL},
+		{"set-default", 0, POPT_ARG_STRING, &defaultKernel, 0,
+		 _("make the first entry referencing the specified kernel "
+		   "the default"), _("kernel-path")},
+		{"set-default-index", 0, POPT_ARG_INT, &defaultIndex, 0,
+		 _("make the given entry index the default entry"),
+		 _("entry-index")},
+		{"silo", 0, POPT_ARG_NONE, &configureSilo, 0,
+		 _("configure silo bootloader")},
+		{"title", 0, POPT_ARG_STRING, &newKernelTitle, 0,
+		 _("title to use for the new kernel entry"), _("entry-title")},
+		{"update-kernel", 0, POPT_ARG_STRING, &updateKernelPath, 0,
+		 _("updated information for the specified kernel"),
+		 _("kernel-path")},
+		{"version", 'v', 0, NULL, 'v',
+		 _("print the version of this program and exit"), NULL},
+		{"yaboot", 0, POPT_ARG_NONE, &configureYaboot, 0,
+		 _("configure yaboot bootloader")},
+		{"zipl", 0, POPT_ARG_NONE, &configureZipl, 0,
+		 _("configure zipl bootloader")},
+		POPT_AUTOHELP {0, 0, 0, 0, 0}
+	};
+
+	useextlinuxmenu = 0;
+
+	int i = 0;
+	for (int j = 1; j < argc; j++)
+		i += strlen(argv[j]) + 1;
+	saved_command_line = malloc(i);
+	if (!saved_command_line) {
+		fprintf(stderr, "grubby: %m\n");
+		exit(1);
+	}
+	saved_command_line[0] = '\0';
+	for (int j = 1; j < argc; j++) {
+		strcat(saved_command_line, argv[j]);
+		strncat(saved_command_line, j == argc - 1 ? "" : " ", 1);
+	}
+
+	optCon = poptGetContext("grubby", argc, argv, options, 0);
+	poptReadDefaultConfig(optCon, 1);
+
+	while ((arg = poptGetNextOpt(optCon)) >= 0) {
+		switch (arg) {
+		case 'v':
+			printf("grubby version %s\n", VERSION);
+			exit(0);
+			break;
+		case 'i':
+			if (extraInitrdCount < MAX_EXTRA_INITRDS) {
+				extraInitrds[extraInitrdCount++] =
+				    strdup(poptGetOptArg(optCon));
+			} else {
+				fprintf(stderr,
+					_
+					("grubby: extra initrd maximum is %d\n"),
+					extraInitrdCount);
+				return 1;
+			}
+			break;
+		}
+	}
+
+	if (arg < -1) {
+		fprintf(stderr, _("grubby: bad argument %s: %s\n"),
+			poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
+			poptStrerror(arg));
 		return 1;
-	    }
-	    break;
 	}
-    }
 
-    if (arg < -1) {
-	fprintf(stderr, _("grubby: bad argument %s: %s\n"),
-		poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
-		poptStrerror(arg));
-	return 1;
-    }
+	if ((chptr = poptGetArg(optCon))) {
+		fprintf(stderr, _("grubby: unexpected argument %s\n"), chptr);
+		return 1;
+	}
 
-    if ((chptr = poptGetArg(optCon))) {
-	fprintf(stderr, _("grubby: unexpected argument %s\n"), chptr);
-	return 1;
-    }
+	if ((configureLilo + configureGrub2 + configureGrub + configureELilo +
+	     configureYaboot + configureSilo + configureZipl +
+	     configureExtLinux) > 1) {
+		fprintf(stderr,
+			_("grubby: cannot specify multiple bootloaders\n"));
+		return 1;
+	} else if (bootloaderProbe && grubConfig) {
+		fprintf(stderr,
+			_
+			("grubby: cannot specify config file with --bootloader-probe\n"));
+		return 1;
+	} else if (configureGrub2) {
+		cfi = &grub2ConfigType;
+		if (envPath)
+			cfi->envFile = envPath;
+	} else if (configureLilo) {
+		cfi = &liloConfigType;
+	} else if (configureGrub) {
+		cfi = &grubConfigType;
+	} else if (configureELilo) {
+		cfi = &eliloConfigType;
+	} else if (configureYaboot) {
+		cfi = &yabootConfigType;
+	} else if (configureSilo) {
+		cfi = &siloConfigType;
+	} else if (configureZipl) {
+		cfi = &ziplConfigType;
+	} else if (configureExtLinux) {
+		cfi = &extlinuxConfigType;
+		useextlinuxmenu = 1;
+	}
 
-    if ((configureLilo + configureGrub2 + configureGrub + configureELilo + 
-		configureYaboot + configureSilo + configureZipl +
-		configureExtLinux ) > 1) {
-	fprintf(stderr, _("grubby: cannot specify multiple bootloaders\n"));
-	return 1;
-    } else if (bootloaderProbe && grubConfig) {
-	fprintf(stderr, 
-	    _("grubby: cannot specify config file with --bootloader-probe\n"));
-	return 1;
-    } else if (configureGrub2) {
-	cfi = &grub2ConfigType;
-	if (envPath)
-	    cfi->envFile = envPath;
-    } else if (configureLilo) {
-	cfi = &liloConfigType;
-    } else if (configureGrub) {
-	cfi = &grubConfigType;
-    } else if (configureELilo) {
-	cfi = &eliloConfigType;
-    } else if (configureYaboot) {
-	cfi = &yabootConfigType;
-    } else if (configureSilo) {
-        cfi = &siloConfigType;
-    } else if (configureZipl) {
-        cfi = &ziplConfigType;
-    } else if (configureExtLinux) {
-	cfi = &extlinuxConfigType;
-	useextlinuxmenu=1;
-    }
-
-    if (!cfi) {
-        if (grub2FindConfig(&grub2ConfigType)) {
-	    cfi = &grub2ConfigType;
-	    if (envPath)
-		cfi->envFile = envPath;
-        } else
-      #ifdef __ia64__
-	    cfi = &eliloConfigType;
-      #elif __powerpc__
-	    cfi = &yabootConfigType;
-      #elif __sparc__
-            cfi = &siloConfigType;
-      #elif __s390__
-            cfi = &ziplConfigType;
-      #elif __s390x__
-            cfi = &ziplConfigtype;
-      #else
-	    cfi = &grubConfigType;
-      #endif
-    }
-
-    if (!grubConfig) {
-	if (cfi->findConfig)
-	    grubConfig = cfi->findConfig(cfi);
-	if (!grubConfig)
-	    grubConfig = cfi->defaultConfig;
-    }
-
-    if (bootloaderProbe && (displayDefault || kernelInfo || newKernelVersion ||
-			    newKernelPath || removeKernelPath || makeDefault ||
-			    defaultKernel || displayDefaultIndex || displayDefaultTitle ||
-			    (defaultIndex >= 0))) {
-	fprintf(stderr, _("grubby: --bootloader-probe may not be used with "
+	if (!cfi) {
+		if (grub2FindConfig(&grub2ConfigType)) {
+			cfi = &grub2ConfigType;
+			if (envPath)
+				cfi->envFile = envPath;
+		} else
+#ifdef __ia64__
+			cfi = &eliloConfigType;
+#elif __powerpc__
+			cfi = &yabootConfigType;
+#elif __sparc__
+			cfi = &siloConfigType;
+#elif __s390__
+			cfi = &ziplConfigType;
+#elif __s390x__
+			cfi = &ziplConfigtype;
+#else
+			cfi = &grubConfigType;
+#endif
+	}
+
+	if (!grubConfig) {
+		if (cfi->findConfig)
+			grubConfig = cfi->findConfig(cfi);
+		if (!grubConfig)
+			grubConfig = cfi->defaultConfig;
+	}
+
+	if (bootloaderProbe
+	    && (displayDefault || kernelInfo || newKernelVersion
+		|| newKernelPath || removeKernelPath || makeDefault
+		|| defaultKernel || displayDefaultIndex || displayDefaultTitle
+		|| (defaultIndex >= 0))) {
+		fprintf(stderr,
+			_("grubby: --bootloader-probe may not be used with "
 			  "specified option"));
-	return 1;
-    }
+		return 1;
+	}
 
-    if ((displayDefault || kernelInfo) && (newKernelVersion || newKernelPath ||
-			   removeKernelPath)) {
-	fprintf(stderr, _("grubby: --default-kernel and --info may not "
+	if ((displayDefault || kernelInfo)
+	    && (newKernelVersion || newKernelPath || removeKernelPath)) {
+		fprintf(stderr,
+			_("grubby: --default-kernel and --info may not "
 			  "be used when adding or removing kernels\n"));
-	return 1;
-    }
+		return 1;
+	}
 
-    if (newKernelPath && !newKernelTitle) {
-	fprintf(stderr, _("grubby: kernel title must be specified\n"));
-	return 1;
-    } else if (!newKernelPath && (copyDefault ||
-				  (newKernelInitrd && !updateKernelPath)||
-				  makeDefault || extraInitrdCount > 0)) {
-	fprintf(stderr, _("grubby: kernel path expected\n"));
-	return 1;
-    }
+	if (newKernelPath && !newKernelTitle) {
+		fprintf(stderr, _("grubby: kernel title must be specified\n"));
+		return 1;
+	} else if (!newKernelPath && (copyDefault ||
+				      (newKernelInitrd && !updateKernelPath) ||
+				      makeDefault || extraInitrdCount > 0)) {
+		fprintf(stderr, _("grubby: kernel path expected\n"));
+		return 1;
+	}
 
-    if (newKernelPath && updateKernelPath) {
-	fprintf(stderr, _("grubby: --add-kernel and --update-kernel may"
-		          "not be used together"));
-	return 1;
-    }
+	if (newKernelPath && updateKernelPath) {
+		fprintf(stderr, _("grubby: --add-kernel and --update-kernel may"
+				  "not be used together"));
+		return 1;
+	}
 
-    if (makeDefault && defaultKernel) {
-	fprintf(stderr, _("grubby: --make-default and --default-kernel "
-			  "may not be used together\n"));
-	return 1;
-    } else if (defaultKernel && removeKernelPath &&
-		!strcmp(defaultKernel, removeKernelPath)) {
-	fprintf(stderr, _("grubby: cannot make removed kernel the default\n"));
-	return 1;
-    } else if (defaultKernel && newKernelPath &&
-		!strcmp(defaultKernel, newKernelPath)) {
-	makeDefault = 1;
-	defaultKernel = NULL;
-    }
-    else if (defaultKernel && (defaultIndex >= 0)) {
-	fprintf(stderr, _("grubby: --set-default and --set-default-index "
+	if (makeDefault && defaultKernel) {
+		fprintf(stderr, _("grubby: --make-default and --default-kernel "
+				  "may not be used together\n"));
+		return 1;
+	} else if (defaultKernel && removeKernelPath &&
+		   !strcmp(defaultKernel, removeKernelPath)) {
+		fprintf(stderr,
+			_("grubby: cannot make removed kernel the default\n"));
+		return 1;
+	} else if (defaultKernel && newKernelPath &&
+		   !strcmp(defaultKernel, newKernelPath)) {
+		makeDefault = 1;
+		defaultKernel = NULL;
+	} else if (defaultKernel && (defaultIndex >= 0)) {
+		fprintf(stderr,
+			_("grubby: --set-default and --set-default-index "
 			  "may not be used together\n"));
-	return 1;
-    }
+		return 1;
+	}
 
-    if (grubConfig && !strcmp(grubConfig, "-") && !outputFile) {
-	fprintf(stderr, _("grubby: output file must be specified if stdin "
-			"is used\n"));
-	return 1;
-    }
+	if (grubConfig && !strcmp(grubConfig, "-") && !outputFile) {
+		fprintf(stderr,
+			_("grubby: output file must be specified if stdin "
+			  "is used\n"));
+		return 1;
+	}
 
-    if (!removeKernelPath && !newKernelPath && !displayDefault && !defaultKernel
-	&& !kernelInfo && !bootloaderProbe && !updateKernelPath
-	&& !removeMBKernel && !displayDefaultIndex && !displayDefaultTitle
-	&& (defaultIndex == -1)) {
-	fprintf(stderr, _("grubby: no action specified\n"));
-	return 1;
-    }
+	if (!removeKernelPath && !newKernelPath && !displayDefault
+	    && !defaultKernel && !kernelInfo && !bootloaderProbe
+	    && !updateKernelPath && !removeMBKernel && !displayDefaultIndex
+	    && !displayDefaultTitle && (defaultIndex == -1)) {
+		fprintf(stderr, _("grubby: no action specified\n"));
+		return 1;
+	}
 
-    flags |= badImageOkay ? GRUBBY_BADIMAGE_OKAY : 0;
+	flags |= badImageOkay ? GRUBBY_BADIMAGE_OKAY : 0;
 
-    if (cfi->needsBootPrefix) {
-	if (!bootPrefix) {
-	    bootPrefix = findBootPrefix();
-	    if (!bootPrefix) return 1;
+	if (cfi->needsBootPrefix) {
+		if (!bootPrefix) {
+			bootPrefix = findBootPrefix();
+			if (!bootPrefix)
+				return 1;
+		} else {
+			/* this shouldn't end with a / */
+			if (bootPrefix[strlen(bootPrefix) - 1] == '/')
+				bootPrefix[strlen(bootPrefix) - 1] = '\0';
+		}
 	} else {
-	    /* this shouldn't end with a / */
-	    if (bootPrefix[strlen(bootPrefix) - 1] == '/')
-		bootPrefix[strlen(bootPrefix) - 1] = '\0';
+		bootPrefix = "";
 	}
-    } else {
-	bootPrefix = "";
-    }
-
-    if (!cfi->mbAllowExtraInitRds &&
-	extraInitrdCount > 0) {
-	fprintf(stderr, _("grubby: %s doesn't allow multiple initrds\n"), cfi->defaultConfig);
-	return 1;
-    }
-
-    if (bootloaderProbe) {
-	int lrc = 0, grc = 0, gr2c = 0, extrc = 0, yrc = 0, erc = 0;
-	struct grubConfig * lconfig, * gconfig, * yconfig, * econfig;
-
-	const char *grub2config = grub2FindConfig(&grub2ConfigType);
-	if (grub2config) {
-	    gconfig = readConfig(grub2config, &grub2ConfigType);
-	    if (!gconfig)
-		gr2c = 1;
-	    else
-		gr2c = checkForGrub2(gconfig);
-	} 
-
-	const char *grubconfig = grubFindConfig(&grubConfigType);
-	if (!access(grubconfig, F_OK)) {
-	    gconfig = readConfig(grubconfig, &grubConfigType);
-	    if (!gconfig)
-		grc = 1;
-	    else
-		grc = checkForGrub(gconfig);
-	} 
-
-	if (!access(liloConfigType.defaultConfig, F_OK)) {
-	    lconfig = readConfig(liloConfigType.defaultConfig, &liloConfigType);
-	    if (!lconfig)
-		lrc = 1;
-	    else
-		lrc = checkForLilo(lconfig);
-	} 
-
-	if (!access(eliloConfigType.defaultConfig, F_OK)) {
-	    econfig = readConfig(eliloConfigType.defaultConfig,
-				 &eliloConfigType);
-	    if (!econfig)
-		erc = 1;
-	    else
-		erc = checkForElilo(econfig);
-	}
-
-	if (!access(extlinuxConfigType.defaultConfig, F_OK)) {
-	    lconfig = readConfig(extlinuxConfigType.defaultConfig, &extlinuxConfigType);
-	    if (!lconfig)
-		extrc = 1;
-	    else
-		extrc = checkForExtLinux(lconfig);
-	} 
-
-
-	if (!access(yabootConfigType.defaultConfig, F_OK)) {
-	    yconfig = readConfig(yabootConfigType.defaultConfig,
-				 &yabootConfigType);
-	    if (!yconfig)
-		yrc = 1;
-	    else
-		yrc = checkForYaboot(yconfig);
-	}
-
-	if (lrc == 1 || grc == 1 || gr2c == 1 || extrc == 1 || yrc == 1 ||
-		erc == 1)
-	    return 1;
-
-	if (lrc == 2) printf("lilo\n");
-	if (gr2c == 2) printf("grub2\n");
-	if (grc == 2) printf("grub\n");
-	if (extrc == 2) printf("extlinux\n");
-	if (yrc == 2) printf("yaboot\n");
-	if (erc == 2) printf("elilo\n");
 
-	return 0;
-    }
+	if (!cfi->mbAllowExtraInitRds && extraInitrdCount > 0) {
+		fprintf(stderr,
+			_("grubby: %s doesn't allow multiple initrds\n"),
+			cfi->defaultConfig);
+		return 1;
+	}
 
-    if (grubConfig == NULL) {
-	printf("Could not find bootloader configuration file.\n");
-	exit(1);
-    }
+	if (bootloaderProbe) {
+		int lrc = 0, grc = 0, gr2c = 0, extrc = 0, yrc = 0, erc = 0;
+		struct grubConfig *lconfig, *gconfig, *yconfig, *econfig;
+
+		const char *grub2config = grub2FindConfig(&grub2ConfigType);
+		if (grub2config) {
+			gconfig = readConfig(grub2config, &grub2ConfigType);
+			if (!gconfig)
+				gr2c = 1;
+			else
+				gr2c = checkForGrub2(gconfig);
+		}
 
-    config = readConfig(grubConfig, cfi);
-    if (!config) return 1;
+		const char *grubconfig = grubFindConfig(&grubConfigType);
+		if (!access(grubconfig, F_OK)) {
+			gconfig = readConfig(grubconfig, &grubConfigType);
+			if (!gconfig)
+				grc = 1;
+			else
+				grc = checkForGrub(gconfig);
+		}
 
-    if (displayDefault) {
-	struct singleLine * line;
-	struct singleEntry * entry;
-        char * rootspec;
+		if (!access(liloConfigType.defaultConfig, F_OK)) {
+			lconfig =
+			    readConfig(liloConfigType.defaultConfig,
+				       &liloConfigType);
+			if (!lconfig)
+				lrc = 1;
+			else
+				lrc = checkForLilo(lconfig);
+		}
 
-	if (config->defaultImage == -1) return 0;
-	if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
-		cfi->defaultIsSaved)
-	    config->defaultImage = 0;
-	entry = findEntryByIndex(config, config->defaultImage);
-	if (!entry) return 0;
-	if (!suitableImage(entry, bootPrefix, 0, flags)) return 0;
+		if (!access(eliloConfigType.defaultConfig, F_OK)) {
+			econfig = readConfig(eliloConfigType.defaultConfig,
+					     &eliloConfigType);
+			if (!econfig)
+				erc = 1;
+			else
+				erc = checkForElilo(econfig);
+		}
 
-	line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines);
-	if (!line) return 0;
+		if (!access(extlinuxConfigType.defaultConfig, F_OK)) {
+			lconfig =
+			    readConfig(extlinuxConfigType.defaultConfig,
+				       &extlinuxConfigType);
+			if (!lconfig)
+				extrc = 1;
+			else
+				extrc = checkForExtLinux(lconfig);
+		}
 
-        rootspec = getRootSpecifier(line->elements[1].item);
-        printf("%s%s\n", bootPrefix, line->elements[1].item + 
-               ((rootspec != NULL) ? strlen(rootspec) : 0));
+		if (!access(yabootConfigType.defaultConfig, F_OK)) {
+			yconfig = readConfig(yabootConfigType.defaultConfig,
+					     &yabootConfigType);
+			if (!yconfig)
+				yrc = 1;
+			else
+				yrc = checkForYaboot(yconfig);
+		}
 
-	return 0;
+		if (lrc == 1 || grc == 1 || gr2c == 1 || extrc == 1 || yrc == 1
+		    || erc == 1)
+			return 1;
 
-    } else if (displayDefaultTitle) {
-	struct singleLine * line;
-	struct singleEntry * entry;
+		if (lrc == 2)
+			printf("lilo\n");
+		if (gr2c == 2)
+			printf("grub2\n");
+		if (grc == 2)
+			printf("grub\n");
+		if (extrc == 2)
+			printf("extlinux\n");
+		if (yrc == 2)
+			printf("yaboot\n");
+		if (erc == 2)
+			printf("elilo\n");
 
-	if (config->defaultImage == -1)
-	    return 0;
-	if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
-		cfi->defaultIsSaved)
-	    config->defaultImage = 0;
-	entry = findEntryByIndex(config, config->defaultImage);
-	if (!entry)
 		return 0;
+	}
+
+	if (grubConfig == NULL) {
+		printf("Could not find bootloader configuration file.\n");
+		exit(1);
+	}
+
+	config = readConfig(grubConfig, cfi);
+	if (!config)
+		return 1;
+
+	if (displayDefault) {
+		struct singleLine *line;
+		struct singleEntry *entry;
+		char *rootspec;
+
+		if (config->defaultImage == -1)
+			return 0;
+		if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
+		    cfi->defaultIsSaved)
+			config->defaultImage = 0;
+		entry = findEntryByIndex(config, config->defaultImage);
+		if (!entry)
+			return 0;
+		if (!suitableImage(entry, bootPrefix, 0, flags))
+			return 0;
+
+		line =
+		    getLineByType(LT_KERNEL | LT_HYPER | LT_KERNEL_EFI |
+				  LT_KERNEL_16, entry->lines);
+		if (!line)
+			return 0;
+
+		rootspec = getRootSpecifier(line->elements[1].item);
+		printf("%s%s\n", bootPrefix, line->elements[1].item +
+		       ((rootspec != NULL) ? strlen(rootspec) : 0));
 
-	if (!configureGrub2) {
-	    char *title;
-	    line = getLineByType(LT_TITLE, entry->lines);
-	    if (!line)
 		return 0;
-	    title = extractTitle(config, line);
-	    if (!title)
+
+	} else if (displayDefaultTitle) {
+		struct singleLine *line;
+		struct singleEntry *entry;
+
+		if (config->defaultImage == -1)
+			return 0;
+		if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
+		    cfi->defaultIsSaved)
+			config->defaultImage = 0;
+		entry = findEntryByIndex(config, config->defaultImage);
+		if (!entry)
+			return 0;
+
+		if (!configureGrub2) {
+			char *title;
+			line = getLineByType(LT_TITLE, entry->lines);
+			if (!line)
+				return 0;
+			title = extractTitle(config, line);
+			if (!title)
+				return 0;
+			printf("%s\n", title);
+			free(title);
+		} else {
+			char *title;
+
+			dbgPrintf
+			    ("This is GRUB2, default title is embeded in menuentry\n");
+			line = getLineByType(LT_MENUENTRY, entry->lines);
+			if (!line)
+				return 0;
+			title = grub2ExtractTitle(line);
+			if (title)
+				printf("%s\n", title);
+		}
 		return 0;
-	    printf("%s\n", title);
-	    free(title);
-	} else {
-	    char * title;
 
-	    dbgPrintf("This is GRUB2, default title is embeded in menuentry\n");
-	    line = getLineByType(LT_MENUENTRY, entry->lines);
-	    if (!line)
+	} else if (displayDefaultIndex) {
+		if (config->defaultImage == -1)
+			return 0;
+		if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
+		    cfi->defaultIsSaved)
+			config->defaultImage = 0;
+		printf("%i\n", config->defaultImage);
 		return 0;
-	    title = grub2ExtractTitle(line);
-	    if (title)
-		printf("%s\n", title);
+
+	} else if (kernelInfo)
+		return displayInfo(config, kernelInfo, bootPrefix);
+
+	if (copyDefault) {
+		template = findTemplate(config, bootPrefix, NULL, 0, flags);
+		if (!template)
+			return 1;
 	}
-	return 0;
 
-    } else if (displayDefaultIndex) {
-        if (config->defaultImage == -1) return 0;
-	if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
-		cfi->defaultIsSaved)
-	    config->defaultImage = 0;
-        printf("%i\n", config->defaultImage);
-        return 0;
-
-    } else if (kernelInfo)
-	return displayInfo(config, kernelInfo, bootPrefix);
-
-    if (copyDefault) {
-	template = findTemplate(config, bootPrefix, NULL, 0, flags);
-	if (!template) return 1;
-    }
-
-    markRemovedImage(config, removeKernelPath, bootPrefix);
-    markRemovedImage(config, removeMBKernel, bootPrefix);
-    setDefaultImage(config, newKernelPath != NULL, defaultKernel, makeDefault, 
-		    bootPrefix, flags, defaultIndex);
-    setFallbackImage(config, newKernelPath != NULL);
-    if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,
-                    removeArgs, newMBKernelArgs, removeMBKernelArgs)) return 1;
-    if (updateKernelPath && newKernelInitrd) {
-	    if (newMBKernel) {
-		    if (addMBInitrd(config, newMBKernel, updateKernelPath,
+	markRemovedImage(config, removeKernelPath, bootPrefix);
+	markRemovedImage(config, removeMBKernel, bootPrefix);
+	setDefaultImage(config, newKernelPath != NULL, defaultKernel,
+			makeDefault, bootPrefix, flags, defaultIndex);
+	setFallbackImage(config, newKernelPath != NULL);
+	if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,
+			removeArgs, newMBKernelArgs, removeMBKernelArgs))
+		return 1;
+	if (updateKernelPath && newKernelInitrd) {
+		if (newMBKernel) {
+			if (addMBInitrd(config, newMBKernel, updateKernelPath,
 					bootPrefix, newKernelInitrd,
 					newKernelTitle))
-			    return 1;
-	    } else {
-		    if (updateInitrd(config, updateKernelPath, bootPrefix,
-					newKernelInitrd, newKernelTitle))
-			return 1;
-	    }
-    }
-    if (addNewKernel(config, template, bootPrefix, newKernelPath, 
-                     newKernelTitle, newKernelArgs, newKernelInitrd, 
-                     (const char **)extraInitrds, extraInitrdCount,
-                     newMBKernel, newMBKernelArgs)) return 1;
-    
-
-    if (numEntries(config) == 0) {
-        fprintf(stderr, _("grubby: doing this would leave no kernel entries. "
-                          "Not writing out new config.\n"));
-        return 1;
-    }
-
-    if (!outputFile)
-	outputFile = (char *)grubConfig;
-
-    return writeConfig(config, outputFile, bootPrefix);
+				return 1;
+		} else {
+			if (updateInitrd(config, updateKernelPath, bootPrefix,
+					 newKernelInitrd, newKernelTitle))
+				return 1;
+		}
+	}
+	if (addNewKernel(config, template, bootPrefix, newKernelPath,
+			 newKernelTitle, newKernelArgs, newKernelInitrd,
+			 (const char **)extraInitrds, extraInitrdCount,
+			 newMBKernel, newMBKernelArgs))
+		return 1;
+
+	if (numEntries(config) == 0) {
+		fprintf(stderr,
+			_("grubby: doing this would leave no kernel entries. "
+			  "Not writing out new config.\n"));
+		return 1;
+	}
+
+	if (!outputFile)
+		outputFile = (char *)grubConfig;
+
+	return writeConfig(config, outputFile, bootPrefix);
 }
-- 
2.4.3