aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorprofkhaos <profkhaos@Khaos-Phantom.(none)>2009-08-20 19:40:08 +0300
committerprofkhaos <profkhaos@Khaos-Phantom.(none)>2009-08-20 19:40:08 +0300
commit157b3a28a060a0bbfce0f047c8fa3712e0520207 (patch)
treeb657737d44b7000ed9f4c347cf2028317c1d1bbd
parent97f408c190b315e3bc42d59a5f1fb9bd37afe9f4 (diff)
downloadbak.git-157b3a28a060a0bbfce0f047c8fa3712e0520207.tar.gz
bak.git-157b3a28a060a0bbfce0f047c8fa3712e0520207.tar.xz
bak.git-157b3a28a060a0bbfce0f047c8fa3712e0520207.zip
CLI with history and c32 smart loading
-rw-r--r--com32/elflink/modules/cli.h2
-rw-r--r--com32/include/sys/exec.h13
-rw-r--r--com32/include/sys/module.h7
-rw-r--r--com32/lib/sys/module/colors.c191
-rw-r--r--com32/lib/sys/module/exec.c108
-rw-r--r--com32/lib/sys/module/menu.h227
-rw-r--r--com32/lib/sys/module/readconfig.c1061
-rw-r--r--com32/lib/sys/module/refstr.c105
-rw-r--r--com32/lib/sys/module/refstr.h40
-rw-r--r--core/elflink/cli.c80
-rw-r--r--core/elflink/cli.h5
-rw-r--r--core/elflink/load_env32.c52
12 files changed, 241 insertions, 1650 deletions
diff --git a/com32/elflink/modules/cli.h b/com32/elflink/modules/cli.h
index b71c894d..76f57aed 100644
--- a/com32/elflink/modules/cli.h
+++ b/com32/elflink/modules/cli.h
@@ -6,7 +6,7 @@
struct cli_command
{
struct list_head list;
- char command[MAX_CMDLINE_LEN];
+ char *command;
};
struct list_head cli_history_head;
diff --git a/com32/include/sys/exec.h b/com32/include/sys/exec.h
index 31a1af2e..0cb33bce 100644
--- a/com32/include/sys/exec.h
+++ b/com32/include/sys/exec.h
@@ -20,6 +20,19 @@
#define EXEC_ROOT_NAME "_root_.c32"
/**
+ * spawn_load - Load a library module or executes an executable one
+ * @name the name of the library/executable to use, including the extension
+ * (e.g. 'sort.c32')
+ * @argv: a NULL-terminated vector of string arguments, starting with
+ * the program name.
+ *
+ * This procedure in essence loads takes the name of a module and checks to see what
+ * kind of module it is ( executable or library ), after which is performs the
+ * appropriate action, either spawning or simply loading the module into memory.
+ */
+extern int spawn_load(const char *name,const char **argv);
+
+/**
* exec_init - Initialize the dynamic execution environment.
*
* Among others, it initializes the module subsystem and loads the root
diff --git a/com32/include/sys/module.h b/com32/include/sys/module.h
index 368a4139..1d94c094 100644
--- a/com32/include/sys/module.h
+++ b/com32/include/sys/module.h
@@ -23,6 +23,13 @@
#define MODULE_NAME_SIZE 256
/*
+ * Some common information about what kind of modules we're dealing with
+ */
+#define UNKNOWN_MODULE -1
+#define EXEC_MODULE 0
+#define LIB_MODULE 1
+
+/*
* Initialization and finalization function signatures
*/
diff --git a/com32/lib/sys/module/colors.c b/com32/lib/sys/module/colors.c
deleted file mode 100644
index 6505d101..00000000
--- a/com32/lib/sys/module/colors.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston MA 02110-1301, USA; either version 2 of the License, or
- * (at your option) any later version; incorporated herein by reference.
- *
- * ----------------------------------------------------------------------- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <colortbl.h>
-#include <sys/module.h>
-#include "menu.h"
-
-struct color_table *console_color_table = &default_color_table;
-int console_color_table_size =
- (sizeof default_color_table / sizeof(struct color_table));
-
-
-/*
- * The color/attribute indexes (\1#X, \2#XX, \3#XXX) are as follows
- *
- * 00 - screen Rest of the screen
- * 01 - border Border area
- * 02 - title Title bar
- * 03 - unsel Unselected menu item
- * 04 - hotkey Unselected hotkey
- * 05 - sel Selection bar
- * 06 - hotsel Selected hotkey
- * 07 - scrollbar Scroll bar
- * 08 - tabmsg Press [Tab] message
- * 09 - cmdmark Command line marker
- * 10 - cmdline Command line
- * 11 - pwdborder Password box border
- * 12 - pwdheader Password box header
- * 13 - pwdentry Password box contents
- * 14 - timeout_msg Timeout message
- * 15 - timeout Timeout counter
- * 16 - help Current entry help text
- * 17 - disabled Disabled menu item
- */
-
-static const struct color_table default_colors[] = {
- {"screen", "37;40", 0x80ffffff, 0x00000000, SHADOW_NORMAL},
- {"border", "30;44", 0x40000000, 0x00000000, SHADOW_NORMAL},
- {"title", "1;36;44", 0xc00090f0, 0x00000000, SHADOW_NORMAL},
- {"unsel", "37;44", 0x90ffffff, 0x00000000, SHADOW_NORMAL},
- {"hotkey", "1;37;44", 0xffffffff, 0x00000000, SHADOW_NORMAL},
- {"sel", "7;37;40", 0xe0000000, 0x20ff8000, SHADOW_ALL},
- {"hotsel", "1;7;37;40", 0xe0400000, 0x20ff8000, SHADOW_ALL},
- {"scrollbar", "30;44", 0x40000000, 0x00000000, SHADOW_NORMAL},
- {"tabmsg", "31;40", 0x90ffff00, 0x00000000, SHADOW_NORMAL},
- {"cmdmark", "1;36;40", 0xc000ffff, 0x00000000, SHADOW_NORMAL},
- {"cmdline", "37;40", 0xc0ffffff, 0x00000000, SHADOW_NORMAL},
- {"pwdborder", "30;47", 0x80ffffff, 0x20ffffff, SHADOW_NORMAL},
- {"pwdheader", "31;47", 0x80ff8080, 0x20ffffff, SHADOW_NORMAL},
- {"pwdentry", "30;47", 0x80ffffff, 0x20ffffff, SHADOW_NORMAL},
- {"timeout_msg", "37;40", 0x80ffffff, 0x00000000, SHADOW_NORMAL},
- {"timeout", "1;37;40", 0xc0ffffff, 0x00000000, SHADOW_NORMAL},
- {"help", "37;40", 0xc0ffffff, 0x00000000, SHADOW_NORMAL},
- {"disabled", "1;30;44", 0x60cccccc, 0x00000000, SHADOW_NORMAL},
-};
-
-#define NCOLORS (sizeof default_colors/sizeof default_colors[0])
-const int message_base_color = NCOLORS;
-const int menu_color_table_size = NCOLORS + 256;
-
-/* Algorithmically generate the msgXX colors */
-void set_msg_colors_global(struct color_table *tbl,
- unsigned int fg, unsigned int bg,
- enum color_table_shadow shadow)
-{
- struct color_table *cp = tbl + message_base_color;
- unsigned int i;
- unsigned int fga, bga;
- unsigned int fgh, bgh;
- unsigned int fg_idx, bg_idx;
- unsigned int fg_rgb, bg_rgb;
-
- static const unsigned int pc2rgb[8] =
- { 0x000000, 0x0000ff, 0x00ff00, 0x00ffff, 0xff0000, 0xff00ff, 0xffff00,
- 0xffffff
- };
-
- /* Converting PC RGBI to sensible RGBA values is an "interesting"
- proposition. This algorithm may need plenty of tweaking. */
-
- fga = fg & 0xff000000;
- fgh = ((fg >> 1) & 0xff000000) | 0x80000000;
-
- bga = bg & 0xff000000;
- bgh = ((bg >> 1) & 0xff000000) | 0x80000000;
-
- for (i = 0; i < 256; i++) {
- fg_idx = i & 15;
- bg_idx = i >> 4;
-
- fg_rgb = pc2rgb[fg_idx & 7] & fg;
- bg_rgb = pc2rgb[bg_idx & 7] & bg;
-
- if (fg_idx & 8) {
- /* High intensity foreground */
- fg_rgb |= fgh;
- } else {
- fg_rgb |= fga;
- }
-
- if (bg_idx == 0) {
- /* Default black background, assume transparent */
- bg_rgb = 0;
- } else if (bg_idx & 8) {
- bg_rgb |= bgh;
- } else {
- bg_rgb |= bga;
- }
-
- cp->argb_fg = fg_rgb;
- cp->argb_bg = bg_rgb;
- cp->shadow = shadow;
- cp++;
- }
-}
-
-struct color_table *default_color_table(void)
-{
- unsigned int i;
- const struct color_table *dp;
- struct color_table *cp;
- struct color_table *color_table;
- static const int pc2ansi[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
- static char msg_names[6 * 256];
- char *mp;
-
- color_table = calloc(NCOLORS + 256, sizeof(struct color_table));
-
- dp = default_colors;
- cp = color_table;
-
- for (i = 0; i < NCOLORS; i++) {
- *cp = *dp;
- cp->ansi = refstrdup(dp->ansi);
- cp++;
- dp++;
- }
-
- mp = msg_names;
- for (i = 0; i < 256; i++) {
- cp->name = mp;
- mp += sprintf(mp, "msg%02x", i) + 1;
-
- rsprintf(&cp->ansi, "%s3%d;4%d", (i & 8) ? "1;" : "",
- pc2ansi[i & 7], pc2ansi[(i >> 4) & 7]);
- cp++;
- }
-
- /*** XXX: This needs to move to run_menu() ***/
- console_color_table = color_table;
- console_color_table_size = NCOLORS + 256;
-
- set_msg_colors_global(color_table, MSG_COLORS_DEF_FG,
- MSG_COLORS_DEF_BG, MSG_COLORS_DEF_SHADOW);
-
- return color_table;
-}
-
-struct color_table *copy_color_table(const struct color_table *master)
-{
- const struct color_table *dp;
- struct color_table *color_table, *cp;
- unsigned int i;
-
- color_table = calloc(NCOLORS + 256, sizeof(struct color_table));
-
- dp = master;
- cp = color_table;
-
- for (i = 0; i < NCOLORS + 256; i++) {
- *cp = *dp;
- cp->ansi = refstr_get(dp->ansi);
- cp++;
- dp++;
- }
-
- return color_table;
-}
-
diff --git a/com32/lib/sys/module/exec.c b/com32/lib/sys/module/exec.c
index 5671774c..52fa04d1 100644
--- a/com32/lib/sys/module/exec.c
+++ b/com32/lib/sys/module/exec.c
@@ -45,6 +45,13 @@ int exec_init(void)
return 0;
}
+int get_module_type(struct elf_module *module)
+{
+ if(module->main_func) return EXEC_MODULE;
+ else if(module->init_func) return LIB_MODULE;
+ return UNKNOWN_MODULE;
+}
+
int load_library(const char *name)
{
int res;
@@ -111,10 +118,11 @@ int spawnv(const char *name, const char **argv)
const char **arg;
int argc;
char **argp, **args;
- struct elf_module *module = module_alloc(name);
struct elf_module *previous;
malloc_tag_t prev_mem_tag;
+ struct elf_module *module = module_alloc(name);
+
if (module == NULL)
return -1;
@@ -125,6 +133,11 @@ int spawnv(const char *name, const char **argv)
return res;
}
+ if (module->main_func == NULL) {
+ // We can't execute without a main function
+ module_unload(module);
+ return -1;
+ }
/*if (module->main_func != NULL) {
const char **last_arg = argv;
void *old_tag;
@@ -208,8 +221,101 @@ int spawnl(const char *name, const char *arg, ...)
return spawnv(name, &arg);
}
+int spawn_load(const char *name,const char **argv)
+{
+ int res, ret_val = 0;
+ const char **arg;
+ int argc;
+ char **argp, **args;
+ struct elf_module *previous;
+ malloc_tag_t prev_mem_tag;
+ struct elf_module *module = module_alloc(name);
+
+ int type;
+
+ if (module == NULL)
+ return -1;
+
+ res = module_load(module);
+
+
+ if (res != 0) {
+ module_unload(module);
+ return res;
+ }
+
+ type=get_module_type(module);
+
+ if(type==LIB_MODULE)
+ {
+ if (module->init_func != NULL) {
+ res = (*(module->init_func))();
+ DBG_PRINT("Initialization function returned: %d\n", res);
+ } else {
+ DBG_PRINT("No initialization function present.\n");
+ }
+
+ if (res != 0) {
+ module_unload(module);
+ return res;
+ }
+ return 0;
+ }
+ else if(type==EXEC_MODULE)
+ {
+ previous = __syslinux_current;
+ prev_mem_tag = __mem_get_tag_global();
+
+ // Setup the new process context
+ __syslinux_current = module;
+ __mem_set_tag_global((malloc_tag_t)module);
+
+ // Generate a new process copy of argv (on the stack)
+ argc = 0;
+ for (arg = argv; *arg; arg++)
+ argc++;
+
+ args = alloca((argc+1) * sizeof(char *));
+
+ for (arg = argv, argp = args; *arg; arg++, argp++) {
+ size_t l = strlen(*arg)+1;
+ *argp = alloca(l);
+ memcpy(*argp, *arg, l);
+ }
+
+ *args = NULL;
+
+ // Execute the program
+ ret_val = setjmp(module->u.x.process_exit);
+
+ if (ret_val)
+ ret_val--; /* Valid range is 0-255 */
+ else if (!module->main_func)
+ ret_val = -1;
+ else
+ exit((*module->main_func)(argc, args)); /* Actually run! */
+
+ // Clean up the allocation context
+ __free_tagged(module);
+ // Restore the allocation context
+ __mem_set_tag_global(prev_mem_tag);
+ // Restore the process context
+ __syslinux_current = previous;
+
+ res = module_unload(module);
+
+ if (res != 0) {
+ return res;
+ }
+
+ return ((unsigned int)ret_val & 0xFF);
+ }
+ module_unload(module);
+ return -1;
+}
void exec_term(void)
{
modules_term();
}
+
diff --git a/com32/lib/sys/module/menu.h b/com32/lib/sys/module/menu.h
deleted file mode 100644
index 1d7dee80..00000000
--- a/com32/lib/sys/module/menu.h
+++ /dev/null
@@ -1,227 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston MA 02110-1301, USA; either version 2 of the License, or
- * (at your option) any later version; incorporated herein by reference.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * menu.h
- *
- * Header file for the simple menu system
- */
-
-#ifndef MENU_H
-#define MENU_H
-
-#include <time.h>
-#include <sys/time.h>
-#include <sys/times.h>
-#include <inttypes.h>
-#include <unistd.h>
-#include <colortbl.h>
-#include <stdbool.h>
-#include "refstr.h"
-
-#ifndef CLK_TCK
-# define CLK_TCK sysconf(_SC_CLK_TCK)
-#endif
-
-struct menu;
-
-/* Note: the _UNRES variants must always be immediately after their
- "normal" versions. */
-enum menu_action {
- MA_NONE, /* Undefined value */
- MA_CMD, /* Execute a command */
- MA_DISABLED, /* Disabled menu entry */
- MA_SUBMENU, /* This is a submenu entry */
- MA_GOTO, /* Go to another menu */
- MA_GOTO_UNRES, /* Unresolved go to */
- MA_QUIT, /* Quit to CLI */
- MA_EXIT, /* Exit to higher-level menu */
- MA_EXIT_UNRES, /* Unresolved exit */
-};
-
-struct menu_entry {
- struct menu *menu; /* Parent menu */
- const char *displayname;
- const char *label;
- const char *passwd;
- char *helptext;
- const char *cmdline;
- struct menu *submenu;
- struct menu_entry *next; /* Linked list of all labels across menus */
- int entry; /* Entry number inside menu */
- enum menu_action action;
- unsigned char hotkey;
- bool save; /* Save this entry if selected */
-};
-
-static inline bool is_disabled(struct menu_entry *me)
-{
- return me->action == MA_DISABLED;
-}
-
-enum kernel_type {
- /* Meta-types for internal use */
- KT_NONE,
- KT_LOCALBOOT,
-
- /* The ones we can pass off to SYSLINUX, in order */
- KT_KERNEL, /* Undefined type */
- KT_LINUX, /* Linux kernel */
- KT_BOOT, /* Bootstrap program */
- KT_BSS, /* Boot sector with patch */
- KT_PXE, /* PXE NBP */
- KT_FDIMAGE, /* Floppy disk image */
- KT_COMBOOT, /* COMBOOT image */
- KT_COM32, /* COM32 image */
- KT_CONFIG, /* Configuration file */
-};
-
-extern const char *const kernel_types[];
-
-/* Configurable integer parameters */
-enum parameter_number {
- P_WIDTH,
- P_MARGIN,
- P_PASSWD_MARGIN,
- P_MENU_ROWS,
- P_TABMSG_ROW,
- P_CMDLINE_ROW,
- P_END_ROW,
- P_PASSWD_ROW,
- P_TIMEOUT_ROW,
- P_HELPMSG_ROW,
- P_HELPMSGEND_ROW,
- P_HSHIFT,
- P_VSHIFT,
- P_HIDDEN_ROW,
-
- NPARAMS
-};
-
-/* Configurable messages */
-enum message_number {
- MSG_TITLE,
- MSG_AUTOBOOT,
- MSG_TAB,
- MSG_NOTAB,
- MSG_PASSPROMPT,
-
- MSG_COUNT
-};
-
-struct messages {
- const char *name; /* Message configuration name */
- const char *defmsg; /* Default message text */
-};
-
-struct menu_parameter {
- const char *name;
- int value;
-};
-
-extern const struct menu_parameter mparm[NPARAMS];
-
-struct fkey_help {
- const char *textname;
- const char *background;
-};
-
-struct menu {
- struct menu *next; /* Linked list of all menus */
- const char *label; /* Goto label for this menu */
- struct menu *parent;
- struct menu_entry *parent_entry; /* Entry for self in parent */
-
- struct menu_entry **menu_entries;
- struct menu_entry *menu_hotkeys[256];
-
- const char *messages[MSG_COUNT];
- int mparm[NPARAMS];
-
- int nentries;
- int nentries_space;
- int defentry;
- int timeout;
-
- bool allowedit;
- bool save; /* MENU SAVE default for this menu */
-
- int curentry;
- int curtop;
-
- const char *title;
- const char *ontimeout;
- const char *onerror;
- const char *menu_master_passwd;
- const char *menu_background;
-
- struct color_table *color_table;
-
- struct fkey_help fkeyhelp[12];
-};
-
-extern struct menu *root_menu, *start_menu, *hide_menu, *menu_list;
-
-/* 2048 is the current definition inside syslinux */
-#define MAX_CMDLINE_LEN 2048
-
-/* These are global parameters regardless of which menu we're displaying */
-extern int shiftkey;
-extern int hiddenmenu;
-extern long long totaltimeout;
-
-void parse_configs(char **argv);
-int draw_background(const char *filename);
-
-static inline int my_isspace(char c)
-{
- return (unsigned char)c <= ' ';
-}
-
-int my_isxdigit(char c);
-unsigned int hexval(char c);
-unsigned int hexval2(const char *p);
-uint32_t parse_argb(char **p);
-
-int menu_main(int argc, char *argv[]);
-void console_prepare(void);
-void console_cleanup(void);
-
-extern const int message_base_color, menu_color_table_size;
-int mygetkey(clock_t timeout);
-int show_message_file(const char *filename, const char *background);
-
-/* passwd.c */
-int passwd_compare(const char *passwd, const char *entry);
-
-/* colors.c */
-#define MSG_COLORS_DEF_FG 0x90ffffff
-#define MSG_COLORS_DEF_BG 0x80ffffff
-#define MSG_COLORS_DEF_SHADOW SHADOW_NORMAL
-void set_msg_colors_global(struct color_table *tbl,
- unsigned int fg, unsigned int bg,
- enum color_table_shadow shadow);
-struct color_table *default_color_table(void);
-struct color_table *copy_color_table(const struct color_table *master);
-extern const int message_base_color;
-
-/* background.c */
-extern const char *current_background;
-void set_background(const char *new_background);
-
-/* execute.c */
-void execute(const char *cmdline, enum kernel_type type);
-
-/* drain.c */
-void drain_keyboard(void);
-
-#endif /* MENU_H */
diff --git a/com32/lib/sys/module/readconfig.c b/com32/lib/sys/module/readconfig.c
deleted file mode 100644
index 0049c181..00000000
--- a/com32/lib/sys/module/readconfig.c
+++ /dev/null
@@ -1,1061 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 2004-2009 H. Peter Anvin - All Rights Reserved
- * Copyright 2009 Intel Corporation; author: H. Peter Anvin
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston MA 02110-1301, USA; either version 2 of the License, or
- * (at your option) any later version; incorporated herein by reference.
- *
- * ----------------------------------------------------------------------- */
-
-#include <stdio.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <minmax.h>
-#include <alloca.h>
-#include <inttypes.h>
-#include <colortbl.h>
-#include <com32.h>
-#include <syslinux/adv.h>
-#include <syslinux/config.h>
-#include <sys/module.h>
-#include <syslinux/config.h>
-
-#include "menu.h"
-
-/* Empty refstring */
-const char *empty_string;
-
-/* Root menu, starting menu, hidden menu, and list of all menus */
-struct menu *root_menu, *start_menu, *hide_menu, *menu_list;
-
-/* These are global parameters regardless of which menu we're displaying */
-int shiftkey = 0; /* Only display menu if shift key pressed */
-int hiddenmenu = 0;
-long long totaltimeout = 0;
-
-/* Keep track of global default */
-static int has_ui = 0; /* DEFAULT only counts if UI is found */
-static const char *globaldefault = NULL;
-static bool menusave = false; /* True if there is any "menu save" */
-
-/* Linked list of all entires, hidden or not; used by unlabel() */
-static struct menu_entry *all_entries;
-static struct menu_entry **all_entries_end = &all_entries;
-
-static const struct messages messages[MSG_COUNT] = {
- [MSG_AUTOBOOT] = {"autoboot", "Automatic boot in # second{,s}..."},
- [MSG_TAB] = {"tabmsg", "Press [Tab] to edit options"},
- [MSG_NOTAB] = {"notabmsg", ""},
- [MSG_PASSPROMPT] = {"passprompt", "Password required"},
-};
-
-#define astrdup(x) ({ char *__x = (x); \
- size_t __n = strlen(__x) + 1; \
- char *__p = alloca(__n); \
- if ( __p ) memcpy(__p, __x, __n); \
- __p; })
-
-/* Must match enum kernel_type */
-const char *const kernel_types[] = {
- "none",
- "localboot",
- "kernel",
- "linux",
- "boot",
- "bss",
- "pxe",
- "fdimage",
- "comboot",
- "com32",
- "config",
- NULL
-};
-
-/*
- * Search the list of all menus for a specific label
- */
-static struct menu *find_menu(const char *label)
-{
- struct menu *m;
-
- for (m = menu_list; m; m = m->next) {
- if (!strcmp(label, m->label))
- return m;
- }
-
- return NULL;
-}
-
-#define MAX_LINE 4096
-
-static char *skipspace(char *p)
-{
- while (*p && my_isspace(*p))
- p++;
-
- return p;
-}
-
-/* Strip ^ from a string, returning a new reference to the same refstring
- if none present */
-static const char *strip_caret(const char *str)
-{
- const char *p, *r;
- char *q;
- int carets = 0;
-
- p = str;
- for (;;) {
- p = strchr(p, '^');
- if (!p)
- break;
- carets++;
- p++;
- }
-
- if (!carets)
- return refstr_get(str);
-
- r = q = refstr_alloc(strlen(str) - carets);
- for (p = str; *p; p++)
- if (*p != '^')
- *q++ = *p;
-
- *q = '\0'; /* refstr_alloc() already did this... */
-
- return r;
-}
-
-/* Check to see if we are at a certain keyword (case insensitive) */
-/* Returns a pointer to the first character past the keyword */
-static char *looking_at(char *line, const char *kwd)
-{
- char *p = line;
- const char *q = kwd;
-
- while (*p && *q && ((*p ^ *q) & ~0x20) == 0) {
- p++;
- q++;
- }
-
- if (*q)
- return NULL; /* Didn't see the keyword */
-
- return my_isspace(*p) ? p : NULL; /* Must be EOL or whitespace */
-}
-
-static struct menu *new_menu(struct menu *parent,
- struct menu_entry *parent_entry, const char *label)
-{
- struct menu *m = calloc(1, sizeof(struct menu));
- int i;
-
- m->label = label;
- m->title = refstr_get(empty_string);
-
- if (parent) {
- /* Submenu */
- m->parent = parent;
- m->parent_entry = parent_entry;
- parent_entry->action = MA_SUBMENU;
- parent_entry->submenu = m;
-
- for (i = 0; i < MSG_COUNT; i++)
- m->messages[i] = refstr_get(parent->messages[i]);
-
- memcpy(m->mparm, parent->mparm, sizeof m->mparm);
-
- m->allowedit = parent->allowedit;
- m->timeout = parent->timeout;
- m->save = parent->save;
-
- m->ontimeout = refstr_get(parent->ontimeout);
- m->onerror = refstr_get(parent->onerror);
- m->menu_master_passwd = refstr_get(parent->menu_master_passwd);
- m->menu_background = refstr_get(parent->menu_background);
-
- m->color_table = copy_color_table(parent->color_table);
-
- for (i = 0; i < 12; i++) {
- m->fkeyhelp[i].textname = refstr_get(parent->fkeyhelp[i].textname);
- m->fkeyhelp[i].background =
- refstr_get(parent->fkeyhelp[i].background);
- }
- } else {
- /* Root menu */
- for (i = 0; i < MSG_COUNT; i++)
- m->messages[i] = refstrdup(messages[i].defmsg);
- for (i = 0; i < NPARAMS; i++)
- m->mparm[i] = mparm[i].value;
-
- m->allowedit = true; /* Allow edits of the command line */
- m->color_table = default_color_table();
- }
-
- m->next = menu_list;
- menu_list = m;
-
- return m;
-}
-
-struct labeldata {
- const char *label;
- const char *kernel;
- enum kernel_type type;
- const char *append;
- const char *initrd;
- const char *menulabel;
- const char *passwd;
- char *helptext;
- unsigned int ipappend;
- unsigned int menuhide;
- unsigned int menudefault;
- unsigned int menuseparator;
- unsigned int menudisabled;
- unsigned int menuindent;
- enum menu_action action;
- int save;
- struct menu *submenu;
-};
-
-/* Menu currently being parsed */
-static struct menu *current_menu;
-
-static void clear_label_data(struct labeldata *ld)
-{
- refstr_put(ld->label);
- refstr_put(ld->kernel);
- refstr_put(ld->append);
- refstr_put(ld->initrd);
- refstr_put(ld->menulabel);
- refstr_put(ld->passwd);
-
- memset(ld, 0, sizeof *ld);
-}
-
-static struct menu_entry *new_entry(struct menu *m)
-{
- struct menu_entry *me;
-
- if (m->nentries >= m->nentries_space) {
- if (!m->nentries_space)
- m->nentries_space = 1;
- else
- m->nentries_space <<= 1;
-
- m->menu_entries = realloc(m->menu_entries, m->nentries_space *
- sizeof(struct menu_entry *));
- }
-
- me = calloc(1, sizeof(struct menu_entry));
- me->menu = m;
- me->entry = m->nentries;
- m->menu_entries[m->nentries++] = me;
- *all_entries_end = me;
- all_entries_end = &me->next;
-
- return me;
-}
-
-static void consider_for_hotkey(struct menu *m, struct menu_entry *me)
-{
- const char *p = strchr(me->displayname, '^');
-
- if (me->action != MA_DISABLED) {
- if (p && p[1]) {
- unsigned char hotkey = p[1] & ~0x20;
- if (!m->menu_hotkeys[hotkey]) {
- me->hotkey = hotkey;
- m->menu_hotkeys[hotkey] = me;
- }
- }
- }
-}
-
-static void record(struct menu *m, struct labeldata *ld, const char *append)
-{
- int i;
- struct menu_entry *me;
- const struct syslinux_ipappend_strings *ipappend;
-
- if (!ld->label)
- return; /* Nothing defined */
-
- /* Hidden entries are recorded on a special "hidden menu" */
- if (ld->menuhide)
- m = hide_menu;
-
- if (ld->label) {
- char ipoptions[4096], *ipp;
- const char *a;
- char *s;
-
- me = new_entry(m);
-
- me->displayname = ld->menulabel
- ? refstr_get(ld->menulabel) : refstr_get(ld->label);
- me->label = refstr_get(ld->label);
- me->passwd = refstr_get(ld->passwd);
- me->helptext = ld->helptext;
- me->hotkey = 0;
- me->action = ld->action ? ld->action : MA_CMD;
- me->save = ld->save ? (ld->save > 0) : m->save;
-
- if (ld->menuindent) {
- const char *dn;
-
- rsprintf(&dn, "%*s%s", ld->menuindent, "", me->displayname);
- refstr_put(me->displayname);
- me->displayname = dn;
- }
-
- if (ld->menuseparator) {
- refstr_put(me->displayname);
- me->displayname = refstr_get(empty_string);
- }
-
- if (ld->menuseparator || ld->menudisabled) {
- me->action = MA_DISABLED;
- refstr_put(me->label);
- me->label = NULL;
- refstr_put(me->passwd);
- me->passwd = NULL;
- }
-
- if (ld->menulabel)
- consider_for_hotkey(m, me);
-
- switch (me->action) {
- case MA_CMD:
- ipp = ipoptions;
- *ipp = '\0';
-
- if (ld->initrd)
- ipp += sprintf(ipp, " initrd=%s", ld->initrd);
-
- if (ld->ipappend) {
- ipappend = syslinux_ipappend_strings();
- for (i = 0; i < ipappend->count; i++) {
- if ((ld->ipappend & (1U << i)) && ipappend->ptr[i])
- ipp += sprintf(ipp, " %s", ipappend->ptr[i]);
- }
- }
-
- a = ld->append;
- if (!a)
- a = append;
- if (!a || (a[0] == '-' && !a[1]))
- a = "";
- s = a[0] ? " " : "";
- if (ld->type == KT_KERNEL) {
- rsprintf(&me->cmdline, "%s%s%s%s", ld->kernel, s, a, ipoptions);
- } else {
- rsprintf(&me->cmdline, ".%s %s%s%s%s",
- kernel_types[ld->type], ld->kernel, s, a, ipoptions);
- }
- break;
-
- case MA_GOTO_UNRES:
- case MA_EXIT_UNRES:
- me->cmdline = refstr_get(ld->kernel);
- break;
-
- case MA_GOTO:
- case MA_EXIT:
- me->submenu = ld->submenu;
- break;
-
- default:
- break;
- }
-
- if (ld->menudefault && me->action == MA_CMD)
- m->defentry = m->nentries - 1;
- }
-
- clear_label_data(ld);
-}
-
-static struct menu *begin_submenu(const char *tag)
-{
- struct menu_entry *me;
-
- if (!tag[0])
- tag = NULL;
-
- me = new_entry(current_menu);
- me->displayname = refstrdup(tag);
- return new_menu(current_menu, me, refstr_get(me->displayname));
-}
-
-static struct menu *end_submenu(void)
-{
- return current_menu->parent ? current_menu->parent : current_menu;
-}
-
-static struct menu_entry *find_label(const char *str)
-{
- const char *p;
- struct menu_entry *me;
- int pos;
-
- p = str;
- while (*p && !my_isspace(*p))
- p++;
-
- /* p now points to the first byte beyond the kernel name */
- pos = p - str;
-
- for (me = all_entries; me; me = me->next) {
- if (!strncmp(str, me->label, pos) && !me->label[pos])
- return me;
- }
-
- return NULL;
-}
-
-static const char *unlabel(const char *str)
-{
- /* Convert a CLI-style command line to an executable command line */
- const char *p;
- const char *q;
- struct menu_entry *me;
- int pos;
-
- p = str;
- while (*p && !my_isspace(*p))
- p++;
-
- /* p now points to the first byte beyond the kernel name */
- pos = p - str;
-
- for (me = all_entries; me; me = me->next) {
- if (!strncmp(str, me->label, pos) && !me->label[pos]) {
- /* Found matching label */
- rsprintf(&q, "%s%s", me->cmdline, p);
- refstr_put(str);
- return q;
- }
- }
-
- return str;
-}
-
-static const char *refdup_word(char **p)
-{
- char *sp = *p;
- char *ep = sp;
-
- while (*ep && !my_isspace(*ep))
- ep++;
-
- *p = ep;
- return refstrndup(sp, ep - sp);
-}
-
-int my_isxdigit(char c)
-{
- unsigned int uc = c;
-
- return (uc - '0') < 10 || ((uc | 0x20) - 'a') < 6;
-}
-
-unsigned int hexval(char c)
-{
- unsigned char uc = c | 0x20;
- unsigned int v;
-
- v = uc - '0';
- if (v < 10)
- return v;
-
- return uc - 'a' + 10;
-}
-
-unsigned int hexval2(const char *p)
-{
- return (hexval(p[0]) << 4) + hexval(p[1]);
-}
-
-uint32_t parse_argb(char **p)
-{
- char *sp = *p;
- char *ep;
- uint32_t argb;
- size_t len, dl;
-
- if (*sp == '#')
- sp++;
-
- ep = sp;
-
- while (my_isxdigit(*ep))
- ep++;
-
- *p = ep;
- len = ep - sp;
-
- switch (len) {
- case 3: /* #rgb */
- argb =
- 0xff000000 +
- (hexval(sp[0]) * 0x11 << 16) +
- (hexval(sp[1]) * 0x11 << 8) + (hexval(sp[2]) * 0x11);
- break;
- case 4: /* #argb */
- argb =
- (hexval(sp[0]) * 0x11 << 24) +
- (hexval(sp[1]) * 0x11 << 16) +
- (hexval(sp[2]) * 0x11 << 8) + (hexval(sp[3]) * 0x11);
- break;
- case 6: /* #rrggbb */
- case 9: /* #rrrgggbbb */
- case 12: /* #rrrrggggbbbb */
- dl = len / 3;
- argb =
- 0xff000000 +
- (hexval2(sp + 0) << 16) +
- (hexval2(sp + dl) << 8) + hexval2(sp + dl * 2);
- break;
- case 8: /* #aarrggbb */
- /* #aaarrrgggbbb is indistinguishable from #rrrrggggbbbb,
- assume the latter is a more common format */
- case 16: /* #aaaarrrrggggbbbb */
- dl = len / 4;
- argb =
- (hexval2(sp + 0) << 24) +
- (hexval2(sp + dl) << 16) +
- (hexval2(sp + dl * 2) << 8) + hexval2(sp + dl * 3);
- break;
- default:
- argb = 0xffff0000; /* Bright red (error indication) */
- break;
- }
-
- return argb;
-}
-
-/*
- * Parser state. This is global so that including multiple
- * files work as expected, which is that everything works the
- * same way as if the files had been concatenated together.
- */
-static const char *append = NULL;
-static unsigned int ipappend = 0;
-static struct labeldata ld;
-
-static int parse_one_config(const char *filename);
-
-static char *is_kernel_type(char *cmdstr, enum kernel_type *type)
-{
- const char *const *p;
- char *q;
- enum kernel_type t = KT_NONE;
-
- for (p = kernel_types; *p; p++, t++) {
- if ((q = looking_at(cmdstr, *p))) {
- *type = t;
- return q;
- }
- }
-
- return NULL;
-}
-
-static char *is_message_name(char *cmdstr, enum message_number *msgnr)
-{
- char *q;
- enum message_number i;
-
- for (i = 0; i < MSG_COUNT; i++) {
- if ((q = looking_at(cmdstr, messages[i].name))) {
- *msgnr = i;
- return q;
- }
- }
-
- return NULL;
-}
-
-static char *is_fkey(char *cmdstr, int *fkeyno)
-{
- char *q;
- int no;
-
- if ((cmdstr[0] | 0x20) != 'f')
- return NULL;
-
- no = strtoul(cmdstr + 1, &q, 10);
- if (!my_isspace(*q))
- return NULL;
-
- if (no < 0 || no > 12)
- return NULL;
-
- *fkeyno = (no == 0) ? 10 : no - 1;
- return q;
-}
-
-static void parse_config_file(FILE * f)
-{
- char line[MAX_LINE], *p, *ep, ch;
- enum kernel_type type;
- enum message_number msgnr;
- int fkeyno;
- struct menu *m = current_menu;
-
- while (fgets(line, sizeof line, f)) {
- p = strchr(line, '\r');
- if (p)
- *p = '\0';
- p = strchr(line, '\n');
- if (p)
- *p = '\0';
-
- p = skipspace(line);
-
- if (looking_at(p, "menu")) {
- p = skipspace(p + 4);
-
- if (looking_at(p, "label")) {
- if (ld.label) {
- refstr_put(ld.menulabel);
- ld.menulabel = refstrdup(skipspace(p + 5));
- } else if (m->parent_entry) {
- refstr_put(m->parent_entry->displayname);
- m->parent_entry->displayname = refstrdup(skipspace(p + 5));
- consider_for_hotkey(m->parent, m->parent_entry);
- if (!m->title[0]) {
- /* MENU LABEL -> MENU TITLE on submenu */
- refstr_put(m->title);
- m->title = strip_caret(m->parent_entry->displayname);
- }
- }
- } else if (looking_at(p, "title")) {
- refstr_put(m->title);
- m->title = refstrdup(skipspace(p + 5));
- if (m->parent_entry) {
- /* MENU TITLE -> MENU LABEL on submenu */
- if (m->parent_entry->displayname == m->label) {
- refstr_put(m->parent_entry->displayname);
- m->parent_entry->displayname = refstr_get(m->title);
- }
- }
- } else if (looking_at(p, "default")) {
- if (ld.label) {
- ld.menudefault = 1;
- } else if (m->parent_entry) {
- m->parent->defentry = m->parent_entry->entry;
- }
- } else if (looking_at(p, "hide")) {
- ld.menuhide = 1;
- } else if (looking_at(p, "passwd")) {
- if (ld.label) {
- refstr_put(ld.passwd);
- ld.passwd = refstrdup(skipspace(p + 6));
- } else if (m->parent_entry) {
- refstr_put(m->parent_entry->passwd);
- m->parent_entry->passwd = refstrdup(skipspace(p + 6));
- }
- } else if (looking_at(p, "shiftkey")) {
- shiftkey = 1;
- } else if (looking_at(p, "save")) {
- menusave = true;
- if (ld.label)
- ld.save = 1;
- else
- m->save = true;
- } else if (looking_at(p, "nosave")) {
- if (ld.label)
- ld.save = -1;
- else
- m->save = false;
- } else if (looking_at(p, "onerror")) {
- refstr_put(m->onerror);
- m->onerror = refstrdup(skipspace(p + 7));
- } else if (looking_at(p, "master")) {
- p = skipspace(p + 6);
- if (looking_at(p, "passwd")) {
- refstr_put(m->menu_master_passwd);
- m->menu_master_passwd = refstrdup(skipspace(p + 6));
- }
- } else if ((ep = looking_at(p, "include"))) {
- goto do_include;
- } else if ((ep = looking_at(p, "background"))) {
- p = skipspace(ep);
- refstr_put(m->menu_background);
- m->menu_background = refdup_word(&p);
- } else if ((ep = looking_at(p, "hidden"))) {
- hiddenmenu = 1;
- } else if ((ep = is_message_name(p, &msgnr))) {
- refstr_put(m->messages[msgnr]);
- m->messages[msgnr] = refstrdup(skipspace(ep));
- } else if ((ep = looking_at(p, "color")) ||
- (ep = looking_at(p, "colour"))) {
- int i;
- struct color_table *cptr;
- p = skipspace(ep);
- cptr = m->color_table;
- for (i = 0; i < menu_color_table_size; i++) {
- if ((ep = looking_at(p, cptr->name))) {
- p = skipspace(ep);
- if (*p) {
- if (looking_at(p, "*")) {
- p++;
- } else {
- refstr_put(cptr->ansi);
- cptr->ansi = refdup_word(&p);
- }
-
- p = skipspace(p);
- if (*p) {
- if (looking_at(p, "*"))
- p++;
- else
- cptr->argb_fg = parse_argb(&p);
-
- p = skipspace(p);
- if (*p) {
- if (looking_at(p, "*"))
- p++;
- else
- cptr->argb_bg = parse_argb(&p);
-
- /* Parse a shadow mode */
- p = skipspace(p);
- ch = *p | 0x20;
- if (ch == 'n') /* none */
- cptr->shadow = SHADOW_NONE;
- else if (ch == 's') /* std, standard */
- cptr->shadow = SHADOW_NORMAL;
- else if (ch == 'a') /* all */
- cptr->shadow = SHADOW_ALL;
- else if (ch == 'r') /* rev, reverse */
- cptr->shadow = SHADOW_REVERSE;
- }
- }
- }
- break;
- }
- cptr++;
- }
- } else if ((ep = looking_at(p, "msgcolor")) ||
- (ep = looking_at(p, "msgcolour"))) {
- unsigned int fg_mask = MSG_COLORS_DEF_FG;
- unsigned int bg_mask = MSG_COLORS_DEF_BG;
- enum color_table_shadow shadow = MSG_COLORS_DEF_SHADOW;
-
- p = skipspace(ep);
- if (*p) {
- if (!looking_at(p, "*"))
- fg_mask = parse_argb(&p);
-
- p = skipspace(p);
- if (*p) {
- if (!looking_at(p, "*"))
- bg_mask = parse_argb(&p);
-
- p = skipspace(p);
- switch (*p | 0x20) {
- case 'n':
- shadow = SHADOW_NONE;
- break;
- case 's':
- shadow = SHADOW_NORMAL;
- break;
- case 'a':
- shadow = SHADOW_ALL;
- break;
- case 'r':
- shadow = SHADOW_REVERSE;
- break;
- default:
- /* go with default */
- break;
- }
- }
- }
- set_msg_colors_global(m->color_table, fg_mask, bg_mask, shadow);
- } else if (looking_at(p, "separator")) {
- record(m, &ld, append);
- ld.label = refstr_get(empty_string);
- ld.menuseparator = 1;
- record(m, &ld, append);
- } else if (looking_at(p, "disable") || looking_at(p, "disabled")) {
- ld.menudisabled = 1;
- } else if (looking_at(p, "indent")) {
- ld.menuindent = atoi(skipspace(p + 6));
- } else if (looking_at(p, "begin")) {
- record(m, &ld, append);
- m = current_menu = begin_submenu(skipspace(p + 5));
- } else if (looking_at(p, "end")) {
- record(m, &ld, append);
- m = current_menu = end_submenu();
- } else if (looking_at(p, "quit")) {
- if (ld.label)
- ld.action = MA_QUIT;
- } else if (looking_at(p, "goto")) {
- if (ld.label) {
- ld.action = MA_GOTO_UNRES;
- refstr_put(ld.kernel);
- ld.kernel = refstrdup(skipspace(p + 4));
- }
- } else if (looking_at(p, "exit")) {
- p = skipspace(p + 4);
- if (ld.label && m->parent) {
- if (*p) {
- /* This is really just a goto, except for the marker */
- ld.action = MA_EXIT_UNRES;
- refstr_put(ld.kernel);
- ld.kernel = refstrdup(p);
- } else {
- ld.action = MA_EXIT;
- ld.submenu = m->parent;
- }
- }
- } else if (looking_at(p, "start")) {
- start_menu = m;
- } else {
- /* Unknown, check for layout parameters */
- enum parameter_number mp;
- for (mp = 0; mp < NPARAMS; mp++) {
- if ((ep = looking_at(p, mparm[mp].name))) {
- m->mparm[mp] = atoi(skipspace(ep));
- break;
- }
- }
- }
- } else if (looking_at(p, "text")) {
- enum text_cmd {
- TEXT_UNKNOWN,
- TEXT_HELP
- } cmd = TEXT_UNKNOWN;
- int len = ld.helptext ? strlen(ld.helptext) : 0;
- int xlen;
-
- p = skipspace(p + 4);
-
- if (looking_at(p, "help"))
- cmd = TEXT_HELP;
-
- while (fgets(line, sizeof line, f)) {
- p = skipspace(line);
- if (looking_at(p, "endtext"))
- break;
-
- xlen = strlen(line);
-
- switch (cmd) {
- case TEXT_UNKNOWN:
- break;
- case TEXT_HELP:
- ld.helptext = realloc(ld.helptext, len + xlen + 1);
- memcpy(ld.helptext + len, line, xlen + 1);
- len += xlen;
- break;
- }
- }
- } else if ((ep = is_fkey(p, &fkeyno))) {
- p = skipspace(ep);
- if (m->fkeyhelp[fkeyno].textname) {
- refstr_put(m->fkeyhelp[fkeyno].textname);
- m->fkeyhelp[fkeyno].textname = NULL;
- }
- if (m->fkeyhelp[fkeyno].background) {
- refstr_put(m->fkeyhelp[fkeyno].background);
- m->fkeyhelp[fkeyno].background = NULL;
- }
-
- refstr_put(m->fkeyhelp[fkeyno].textname);
- m->fkeyhelp[fkeyno].textname = refdup_word(&p);
- if (*p) {
- p = skipspace(p);
- m->fkeyhelp[fkeyno].background = refdup_word(&p);
- }
- } else if ((ep = looking_at(p, "include"))) {
-do_include:
- {
- const char *file;
- p = skipspace(ep);
- file = refdup_word(&p);
- p = skipspace(p);
- if (*p) {
- record(m, &ld, append);
- m = current_menu = begin_submenu(p);
- parse_one_config(file);
- record(m, &ld, append);
- m = current_menu = end_submenu();
- } else {
- parse_one_config(file);
- }
- refstr_put(file);
- }
- } else if (looking_at(p, "append")) {
- const char *a = refstrdup(skipspace(p + 6));
- if (ld.label) {
- refstr_put(ld.append);
- ld.append = a;
- } else {
- refstr_put(append);
- append = a;
- }
- } else if (looking_at(p, "initrd")) {
- const char *a = refstrdup(skipspace(p + 6));
- if (ld.label) {
- refstr_put(ld.initrd);
- ld.initrd = a;
- } else {
- /* Ignore */
- }
- } else if (looking_at(p, "label")) {
- p = skipspace(p + 5);
- record(m, &ld, append);
- ld.label = refstrdup(p);
- ld.kernel = refstrdup(p);
- ld.type = KT_KERNEL;
- ld.passwd = NULL;
- ld.append = NULL;
- ld.initrd = NULL;
- ld.menulabel = NULL;
- ld.helptext = NULL;
- ld.ipappend = ipappend;
- ld.menudefault = ld.menuhide = ld.menuseparator =
- ld.menudisabled = ld.menuindent = 0;
- } else if ((ep = is_kernel_type(p, &type))) {
- if (ld.label) {
- refstr_put(ld.kernel);
- ld.kernel = refstrdup(skipspace(ep));
- ld.type = type;
- }
- } else if (looking_at(p, "timeout")) {
- m->timeout = (atoi(skipspace(p + 7)) * CLK_TCK + 9) / 10;
- } else if (looking_at(p, "totaltimeout")) {
- totaltimeout = (atoll(skipspace(p + 13)) * CLK_TCK + 9) / 10;
- } else if (looking_at(p, "ontimeout")) {
- m->ontimeout = refstrdup(skipspace(p + 9));
- } else if (looking_at(p, "allowoptions")) {
- m->allowedit = !!atoi(skipspace(p + 12));
- } else if (looking_at(p, "ipappend")) {
- if (ld.label)
- ld.ipappend = atoi(skipspace(p + 8));
- else
- ipappend = atoi(skipspace(p + 8));
- } else if (looking_at(p, "default")) {
- refstr_put(globaldefault);
- globaldefault = refstrdup(skipspace(p + 7));
- } else if (looking_at(p, "ui")) {
- has_ui = 1;
- }
- }
-}
-
-static int parse_one_config(const char *filename)
-{
- FILE *f;
-
- if (!strcmp(filename, "~"))
- filename = syslinux_config_file();
-
- f = fopen(filename, "r");
- if (!f)
- return -1;
-
- parse_config_file(f);
- fclose(f);
-
- return 0;
-}
-
-static void resolve_gotos(void)
-{
- struct menu_entry *me;
- struct menu *m;
-
- for (me = all_entries; me; me = me->next) {
- if (me->action == MA_GOTO_UNRES || me->action == MA_EXIT_UNRES) {
- m = find_menu(me->cmdline);
- refstr_put(me->cmdline);
- me->cmdline = NULL;
- if (m) {
- me->submenu = m;
- me->action--; /* Drop the _UNRES */
- } else {
- me->action = MA_DISABLED;
- }
- }
- }
-}
-
-void parse_configs(char **argv)
-{
- const char *filename;
- struct menu *m;
- struct menu_entry *me;
-
- empty_string = refstrdup("");
-
- /* Initialize defaults for the root and hidden menus */
- hide_menu = new_menu(NULL, NULL, refstrdup(".hidden"));
- root_menu = new_menu(NULL, NULL, refstrdup(".top"));
- start_menu = root_menu;
-
- /* Other initialization */
- memset(&ld, 0, sizeof(struct labeldata));
-
- /* Actually process the files */
- current_menu = root_menu;
- if (!*argv) {
- parse_one_config("~");
- } else {
- while ((filename = *argv++))
- parse_one_config(filename);
- }
-
- /* On final EOF process the last label statement */
- record(current_menu, &ld, append);
-
- /* Common postprocessing */
- resolve_gotos();
-
- /* Handle global default */
- if (has_ui && globaldefault) {
- me = find_label(globaldefault);
- if (me && me->menu != hide_menu) {
- me->menu->defentry = me->entry;
- start_menu = me->menu;
- }
- }
-
- /* If "menu save" is active, let the ADV override the global default */
- if (menusave) {
- size_t len;
- const char *lbl = syslinux_getadv(ADV_MENUSAVE, &len);
- char *lstr;
- if (lbl && len) {
- lstr = refstr_alloc(len);
- memcpy(lstr, lbl, len); /* refstr_alloc() adds the final null */
- me = find_label(lstr);
- if (me && me->menu != hide_menu) {
- me->menu->defentry = me->entry;
- start_menu = me->menu;
- }
- refstr_put(lstr);
- }
- }
-
- /* Final per-menu initialization, with all labels known */
- for (m = menu_list; m; m = m->next) {
- m->curentry = m->defentry; /* All menus start at their defaults */
-
- if (m->ontimeout)
- m->ontimeout = unlabel(m->ontimeout);
- if (m->onerror)
- m->onerror = unlabel(m->onerror);
- }
-}
-
diff --git a/com32/lib/sys/module/refstr.c b/com32/lib/sys/module/refstr.c
deleted file mode 100644
index 97ab1edb..00000000
--- a/com32/lib/sys/module/refstr.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 2008 H. Peter Anvin - All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston MA 02110-1301, USA; either version 2 of the License, or
- * (at your option) any later version; incorporated herein by reference.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * refstr.c
- *
- * Simple reference-counted strings
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include "refstr.h"
-
-/* Allocate space for a refstring of len bytes, plus final null */
-/* The final null is inserted in the string; the rest is uninitialized. */
-char *refstr_alloc(size_t len)
-{
- char *r = malloc(sizeof(unsigned int) + len + 1);
- if (!r)
- return NULL;
- *(unsigned int *)r = 1;
- r += sizeof(unsigned int);
- r[len] = '\0';
- return r;
-}
-
-const char *refstrndup(const char *str, size_t len)
-{
- char *r;
-
- if (!str)
- return NULL;
-
- len = strnlen(str, len);
- r = refstr_alloc(len);
- if (r)
- memcpy(r, str, len);
- return r;
-}
-
-const char *refstrdup(const char *str)
-{
- char *r;
- size_t len;
-
- if (!str)
- return NULL;
-
- len = strlen(str);
- r = refstr_alloc(len);
- if (r)
- memcpy(r, str, len);
- return r;
-}
-
-int vrsprintf(const char **bufp, const char *fmt, va_list ap)
-{
- va_list ap1;
- int len;
- char *p;
-
- va_copy(ap1, ap);
- len = vsnprintf(NULL, 0, fmt, ap1);
- va_end(ap1);
-
- *bufp = p = refstr_alloc(len);
- if (!p)
- return -1;
-
- return vsnprintf(p, len + 1, fmt, ap);
-}
-
-int rsprintf(const char **bufp, const char *fmt, ...)
-{
- int rv;
- va_list ap;
-
- va_start(ap, fmt);
- rv = vrsprintf(bufp, fmt, ap);
- va_end(ap);
-
- return rv;
-}
-
-void refstr_put(const char *r)
-{
- unsigned int *ref;
-
- if (r) {
- ref = (unsigned int *)r - 1;
-
- if (!--*ref)
- free(ref);
- }
-}
diff --git a/com32/lib/sys/module/refstr.h b/com32/lib/sys/module/refstr.h
deleted file mode 100644
index 7001d407..00000000
--- a/com32/lib/sys/module/refstr.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 2008 H. Peter Anvin - All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- * Boston MA 02110-1301, USA; either version 2 of the License, or
- * (at your option) any later version; incorporated herein by reference.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * refstr.h
- *
- * Simple reference-counted strings
- */
-
-#ifndef REFSTR_H
-#define REFSTR_H
-
-#include <stddef.h>
-#include <stdarg.h>
-
-static inline __attribute__ ((always_inline))
-const char *refstr_get(const char *r)
-{
- if (r)
- ((unsigned int *)r)[-1]++;
- return r;
-}
-
-void refstr_put(const char *);
-char *refstr_alloc(size_t);
-const char *refstrdup(const char *);
-const char *refstrndup(const char *, size_t);
-int rsprintf(const char **, const char *, ...);
-int vrsprintf(const char **, const char *, va_list);
-
-#endif
diff --git a/core/elflink/cli.c b/core/elflink/cli.c
index 11359ea8..e58d6948 100644
--- a/core/elflink/cli.c
+++ b/core/elflink/cli.c
@@ -10,6 +10,8 @@
#include <limits.h>
#include <minmax.h>
#include <linux/list.h>
+#include <sys/exec.h>
+#include <sys/module.h>
#include "getkey.h"
#include "common.h"
@@ -58,7 +60,7 @@ int mygetkey(clock_t timeout)
const char *edit_cmdline(const char *input, int top /*, int width */,int (*pDraw_Menu)(int, int, int),void (*show_fkey)(int))
{
static char cmdline[MAX_CMDLINE_LEN];
- char temp_cmdline[MAX_CMDLINE_LEN];
+ char temp_cmdline[MAX_CMDLINE_LEN]={};
int key, len, prev_len, cursor;
int redraw = 1; /* We enter with the menu already drawn */
int x, y;
@@ -66,7 +68,7 @@ const char *edit_cmdline(const char *input, int top /*, int width */,int (*pDraw
const char *ret;
int width = 0;
struct cli_command *comm_counter;
- comm_counter=list_entry(cli_history_head.next, typeof(*comm_counter),list);
+ comm_counter=list_entry(cli_history_head.next->prev, typeof(*comm_counter),list);
if (!width) {
int height;
@@ -74,7 +76,7 @@ const char *edit_cmdline(const char *input, int top /*, int width */,int (*pDraw
width = 80;
}
- printf("width = %d\n", width);
+ //printf("width = %d\n", width);
strncpy(cmdline, input, MAX_CMDLINE_LEN);
cmdline[MAX_CMDLINE_LEN - 1] = '\0';
@@ -273,7 +275,7 @@ const char *edit_cmdline(const char *input, int top /*, int width */,int (*pDraw
redraw = 1;
}
break;
- case KEY_DOWN:
+ case KEY_UP:
{
if(!list_empty(&cli_history_head))
{
@@ -291,7 +293,7 @@ const char *edit_cmdline(const char *input, int top /*, int width */,int (*pDraw
}
}
break;
- case KEY_UP:
+ case KEY_DOWN:
{
if(!list_empty(&cli_history_head))
{
@@ -343,3 +345,71 @@ const char *edit_cmdline(const char *input, int top /*, int width */,int (*pDraw
return ret;
}
+void process_command(const char *cmd)
+{
+ char **cmd_line = malloc((MAX_COMMAND_ARGS+1)*sizeof(char*));
+ char *temp_cmd=(char*)malloc(sizeof(char)*(strlen(cmd)+1));
+ int argc = 0, len_mn;
+ char *crt_arg,*module_name;
+
+ strcpy(temp_cmd,cmd);
+ module_name = strtok(cmd, COMMAND_DELIM);
+ len_mn=strlen(module_name);
+
+ if(!strcmp(module_name+len_mn-4,".c32"))
+ {
+ if(module_find(module_name) != NULL) goto cleanup;
+ do
+ {
+ crt_arg = strtok(NULL, COMMAND_DELIM);
+ if (crt_arg != NULL && strlen(crt_arg) > 0)
+ {
+ cmd_line[argc] = crt_arg;
+ argc++;
+ }
+ else
+ {
+ break;
+ }
+ }while (argc < MAX_COMMAND_ARGS);
+ cmd_line[argc] = NULL;
+ /*int i;
+ for(i=0;i<argc;i++)
+ {
+ printf("%s\n",cmd_line[i]);
+ }*/
+ spawn_load(module_name,cmd_line);
+ }
+ else if(!strcmp(module_name+len_mn-2,".0"))
+ {
+ //printf("%s\n",temp_cmd);
+ execute(cmd,KT_PXE);
+ }
+ else if(!strcmp(module_name+len_mn-3,".bs"))
+ {
+ //printf("%s\n",temp_cmd);
+ }
+ else if(!strcmp(module_name+len_mn-4,".img"))
+ {
+ //printf("%s\n",temp_cmd);
+ execute(cmd,KT_FDIMAGE);
+ }
+ else if(!strcmp(module_name+len_mn-4,".bin"))
+ {
+ printf("%s\n",temp_cmd);
+ }
+ else if(!strcmp(module_name+len_mn-4,".bss"))
+ {
+ //printf("%s\n",temp_cmd);
+ execute(cmd,KT_BSS);
+ }
+ else if(!strcmp(module_name+len_mn-4,".com") || !strcmp(module_name+len_mn-4,".cbt"))
+ {
+ //printf("%s\n",temp_cmd);
+ execute(cmd,KT_COMBOOT);
+ }
+cleanup:
+ free(cmd_line);
+ free(temp_cmd);
+}
+
diff --git a/core/elflink/cli.h b/core/elflink/cli.h
index b71c894d..c810539f 100644
--- a/core/elflink/cli.h
+++ b/core/elflink/cli.h
@@ -2,11 +2,13 @@
#define CLI_H
#define MAX_CMD_HISTORY 64
+#define COMMAND_DELIM " \t\n" // Whitespace delimiters
+#define MAX_COMMAND_ARGS 40
struct cli_command
{
struct list_head list;
- char command[MAX_CMDLINE_LEN];
+ char *command;
};
struct list_head cli_history_head;
@@ -14,5 +16,6 @@ struct list_head cli_history_head;
extern void clear_screen(void);
extern int mygetkey(clock_t timeout);
extern const char *edit_cmdline(const char *input, int top /*, int width */,int (*pDraw_Menu)(int, int, int),void (*show_fkey)(int));
+extern void process_command(const char *cmd);
#endif
diff --git a/core/elflink/load_env32.c b/core/elflink/load_env32.c
index 9e022c69..a4c81396 100644
--- a/core/elflink/load_env32.c
+++ b/core/elflink/load_env32.c
@@ -72,22 +72,10 @@ void load_env32(com32sys_t * regs)
{
call_constr();
char *cmdline;
- struct cli_command c1,c2,c3,*aux;
+ struct cli_command c1,c2,c3,*comm,*aux;
openconsole(&dev_rawcon_r, &dev_ansiserial_w);
INIT_LIST_HEAD(&cli_history_head);
- strcpy(c1.command,"command 1");
- strcpy(c2.command,"command 2");
- strcpy(c3.command,"command 3");
- list_add(&(c1.list),&cli_history_head);
- list_add(&(c2.list),&cli_history_head);
- list_add(&(c3.list),&cli_history_head);
-
- list_for_each_entry(aux, &cli_history_head, list)
- {
- printf("%s\n",aux->command);
- }
-
printf("Calling initilization constructor procedures...\n");
printf("Starting 32 bit elf module subsystem...\n");
init_module_subsystem(&core_module);
@@ -97,10 +85,36 @@ void load_env32(com32sys_t * regs)
printf("Str table size: %d\n",core_module.strtable_size);
printf("Sym table size: %d\n",core_module.symtable_size);
- cmdline=edit_cmdline("",1,NULL,NULL);
- printf("\n%s\n",cmdline);
- //fgets(cmdline,100,stdin);
+ c1.command=(char*)malloc(sizeof(char)*16);
+ c2.command=(char*)malloc(sizeof(char)*16);
+ c3.command=(char*)malloc(sizeof(char)*16);
+ strcpy(c1.command,"command 1");
+ strcpy(c2.command,"command 2");
+ strcpy(c3.command,"command 3");
+ list_add(&(c1.list),&cli_history_head);
+ list_add(&(c2.list),&cli_history_head);
+ list_add(&(c3.list),&cli_history_head);
+
+
+ /*list_for_each_entry(aux,&cli_history_head,list)
+ {
+ printf("%s\n",aux->command);
+ }*/
+
+ while(1)
+ {
+ cmdline=edit_cmdline("",1,NULL,NULL);
+ aux=list_entry(cli_history_head.next, typeof(*aux),list);
+ if(strcmp(aux->command,cmdline))
+ {
+ comm=(struct cli_command*)malloc(sizeof(struct cli_command*));
+ comm->command=(char*)malloc(sizeof(char)*(strlen(cmdline)+1));
+ strcpy(comm->command,cmdline);
+ list_add(&(comm->list),&cli_history_head);
+ process_command(cmdline);
+ }
+ }
int i,n=5;
char **argv;
@@ -124,13 +138,15 @@ void load_env32(com32sys_t * regs)
printf("Loading crypt-md5.c32\n%d\n",load_library("dyn/crypt-md5.c32"));
printf("Loading passwd.c32\n%d\n",load_library("dyn/passwd.c32"));
printf("Loading get_key.c32\n%d\n",load_library("dyn/get_key.c32"));
- printf("Loading menumain.c32\n%d\n",load_library("dyn/menumain.c32"));
+ //printf("Loading menumain.c32\n%d\n",load_library("dyn/menumain.c32"));
+ spawn_load("dyn/menumain.c32",0);
/*printf("\n\nTrying to spawn 'dyn/hello.dyn'\n\n");
spawnv("dyn/hello.dyn",0);
printf("\nTest done\n");*/
//printf("%d\n",spawnv("mytest.c32",argv));
- spawnl("mytest.c32", "mytest",(regs->edi.w[0]), NULL);
+ spawn_load("mytest.c32",argv);
+ //spawnl("mytest.c32", "mytest",(regs->edi.w[0]), NULL);
//printf("Done\n");
while(1) 1; /* we don't have anything better to do so hang around for a bit */