From: H. Peter Anvin Date: Tue, 5 Sep 2006 22:46:27 +0000 (-0700) Subject: Merge with 3.2x branch X-Git-Tag: syslinux-3.30-pre2^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9b5f55b2369d4cc19ef8038c752716d40ba77961;p=platform%2Fupstream%2Fsyslinux.git Merge with 3.2x branch Conflicts: com32/modules/Makefile com32/modules/menu.c com32/modules/menu.h com32/modules/readconfig.c version --- 9b5f55b2369d4cc19ef8038c752716d40ba77961 diff --cc com32/modules/Makefile index c9f0a6e,efba4c3..c45b057 --- a/com32/modules/Makefile +++ b/com32/modules/Makefile @@@ -44,8 -44,8 +44,8 @@@ AUXDIR = $(LIBDIR)/syslinu INCDIR = /usr/include COM32DIR = $(AUXDIR)/com32 - MODULES = chain.c32 menu.c32 vesamenu.c32 ethersel.c32 mboot.c32 dmitest.c32 -MODULES = chain.c32 menu.c32 ethersel.c32 mboot.c32 dmitest.c32 cpuidtest.c32 -TESTFILES = menu.lnx ++MODULES = chain.c32 menu.c32 vesamenu.c32 ethersel.c32 mboot.c32 dmitest.c32 cpuidtest.c32 +TESTFILES = all: $(MODULES) $(TESTFILES) diff --cc com32/modules/menu.h index 6b249d3,ea17dbc..e85e4ca --- a/com32/modules/menu.h +++ b/com32/modules/menu.h @@@ -60,12 -60,10 +60,13 @@@ extern long long totaltimeout extern char *menu_title; extern char *ontimeout; + extern char *onerror; extern char *menu_master_passwd; +extern char *menu_background; + void parse_config(const char *filename); +extern int (*draw_background)(const char *filename); static inline int my_isspace(char c) { diff --cc com32/modules/menumain.c index c82a582,0000000..91ee5d4 mode 100644,000000..100644 --- a/com32/modules/menumain.c +++ b/com32/modules/menumain.c @@@ -1,873 -1,0 +1,876 @@@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004-2006 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., 53 Temple Place Ste 330, + * Boston MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * menumain.c + * + * Simple menu system which displays a list and allows the user to select + * a command line and/or edit it. + */ + +#define _GNU_SOURCE /* Needed for asprintf() on Linux */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __COM32__ +#include +#endif + +#include "menu.h" + +int (*draw_background)(const char *filename); + +/* + * The color/attribute indexes (\1#XX) 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 + */ + +static const struct color_table default_color_table[] = { + { "screen", "0;37;40", 0x80ffffff, 0x00000000 }, + { "border", "0;30;44", 0x40000000, 0x00000000 }, + { "title", "1;36;44", 0xc00090f0, 0x00000000 }, + { "unsel", "0;37;44", 0x90ffffff, 0x00000000 }, + { "hotkey", "1;37;44", 0xffffffff, 0x00000000 }, + { "sel", "0;7;37;40", 0xcf101010, 0x20ff8000 }, + { "hotsel", "1;7;37;40", 0xff353535, 0x20ff8000 }, + { "scrollbar", "0;30;44", 0x40000000, 0x00000000 }, + { "tabmsg", "0;31;40", 0x90ffff00, 0x00000000 }, + { "cmdmark", "1;36;40", 0xc000ffff, 0x00000000 }, + { "cmdline", "0;37;40", 0xc0ffffff, 0x00000000 }, + { "pwdborder", "0;30;47", 0x80ffffff, 0x20ffffff }, + { "pwdheader", "0;31;47", 0x80ff8080, 0x20ffffff }, + { "pwdentry", "0;30;47", 0x80ffffff, 0x20ffffff }, + { "timeout_msg", "0;37;40", 0x80ffffff, 0x00000000 }, + { "timeout", "1;37;40", 0xc0ffffff, 0x00000000 }, +}; + +#define NCOLORS (sizeof default_color_table/sizeof(struct color_table)) + +struct menu_parameter mparm[] = { + { "width", 80 }, + { "margin", 10 }, + { "passwordmargin", 3 }, + { "rows", 12 }, + { "tabmsgrow", 18 }, + { "cmdlinerow", 18 }, + { "endrow", 24 }, + { "passwordrow", 11 }, + { "timeoutrow", 20 }, + { NULL, 0 } +}; + +#define WIDTH mparm[0].value +#define MARGIN mparm[1].value +#define PASSWD_MARGIN mparm[2].value +#define MENU_ROWS mparm[3].value +#define TABMSG_ROW mparm[4].value +#define CMDLINE_ROW mparm[5].value +#define END_ROW mparm[6].value +#define PASSWD_ROW mparm[7].value +#define TIMEOUT_ROW mparm[8].value + +static void +install_default_color_table(void) +{ + unsigned int i; + const struct color_table *dp; + struct color_table *cp; + static struct color_table color_table[NCOLORS]; + + dp = default_color_table; + cp = color_table; + + for (i = 0; i < NCOLORS; i++) { + if (cp->ansi) + free((void *)cp->ansi); + + cp->name = dp->name; + cp->ansi = strdup(dp->ansi); + cp->argb_fg = dp->argb_fg; + cp->argb_bg = dp->argb_bg; + + cp++; + dp++; + } + + console_color_table = color_table; + console_color_table_size = NCOLORS; +} + +static char * +pad_line(const char *text, int align, int width) +{ + static char buffer[MAX_CMDLINE_LEN]; + int n, p; + + if ( width >= (int) sizeof buffer ) + return NULL; /* Can't do it */ + + n = strlen(text); + if ( n >= width ) + n = width; + + memset(buffer, ' ', width); + buffer[width] = 0; + p = ((width-n)*align)>>1; + memcpy(buffer+p, text, n); + + return buffer; +} + +/* Display an entry, with possible hotkey highlight. Assumes + that the current attribute is the non-hotkey one, and will + guarantee that as an exit condition as well. */ +static void +display_entry(const struct menu_entry *entry, const char *attrib, + const char *hotattrib, int width) +{ + const char *p = entry->displayname; + + while ( width ) { + if ( *p ) { + if ( *p == '^' ) { + p++; + if ( *p && ((unsigned char)*p & ~0x20) == entry->hotkey ) { + fputs(hotattrib, stdout); + putchar(*p++); + fputs(attrib, stdout); + width--; + } + } else { + putchar(*p++); + width--; + } + } else { + putchar(' '); + width--; + } + } +} + +static void +draw_row(int y, int sel, int top, int sbtop, int sbbot) +{ + int i = (y-4)+top; + + printf("\033[%d;%dH\1#01\016x\017%s ", + y, MARGIN+1, (i == sel) ? "\1#05" : "\1#03"); + + if ( i >= nentries ) { + fputs(pad_line("", 0, WIDTH-2*MARGIN-4), stdout); + } else { + display_entry(&menu_entries[i], + (i == sel) ? "\1#05" : "\1#03", + (i == sel) ? "\1#06" : "\1#04", + WIDTH-2*MARGIN-4); + } + + if ( nentries <= MENU_ROWS ) { + printf(" \1#01\016x\017"); + } else if ( sbtop > 0 ) { + if ( y >= sbtop && y <= sbbot ) + printf(" \1#07\016a\017"); + else + printf(" \1#01\016x\017"); + } else { + putchar(' '); /* Don't modify the scrollbar */ + } +} + +static int +passwd_compare(const char *passwd, const char *entry) +{ + const char *p; + SHA1_CTX ctx; + unsigned char sha1[20], pwdsha1[20]; + + if ( passwd[0] != '$' ) /* Plaintext passwd, yuck! */ + return !strcmp(entry, passwd); + + if ( strncmp(passwd, "$4$", 3) ) + return 0; /* Only SHA-1 passwds supported */ + + SHA1Init(&ctx); + + if ( (p = strchr(passwd+3, '$')) ) { + SHA1Update(&ctx, (void *)passwd+3, p-(passwd+3)); + p++; + } else { + p = passwd+3; /* Assume no salt */ + } + + SHA1Update(&ctx, (void *)entry, strlen(entry)); + SHA1Final(sha1, &ctx); + + memset(pwdsha1, 0, 20); + unbase64(pwdsha1, 20, p); + + return !memcmp(sha1, pwdsha1, 20); +} + +static jmp_buf timeout_jump; + +static int mygetkey(clock_t timeout) +{ + clock_t t0, t; + clock_t tto, to; + int key; + + if ( !totaltimeout ) + return get_key(stdin, timeout); + + for (;;) { + tto = min(totaltimeout, INT_MAX); + to = timeout ? min(tto, timeout) : tto; + + t0 = times(NULL); + key = get_key(stdin, to); + t = times(NULL) - t0; + + if ( totaltimeout <= t ) + longjmp(timeout_jump, 1); + + totaltimeout -= t; + + if ( key != KEY_NONE ) + return key; + + if ( timeout ) { + if ( timeout <= t ) + return KEY_NONE; + + timeout -= t; + } + } +} + +static int +ask_passwd(const char *menu_entry) +{ + static const char title[] = "Password required"; + char user_passwd[WIDTH], *p; + int done; + int key; + int x; + + printf("\033[%d;%dH\1#11\016l", PASSWD_ROW, PASSWD_MARGIN+1); + for ( x = 2 ; x <= WIDTH-2*PASSWD_MARGIN-1 ; x++ ) + putchar('q'); + + printf("k\033[%d;%dHx", PASSWD_ROW+1, PASSWD_MARGIN+1); + for ( x = 2 ; x <= WIDTH-2*PASSWD_MARGIN-1 ; x++ ) + putchar(' '); + + printf("x\033[%d;%dHm", PASSWD_ROW+2, PASSWD_MARGIN+1); + for ( x = 2 ; x <= WIDTH-2*PASSWD_MARGIN-1 ; x++ ) + putchar('q'); + + printf("j\017\033[%d;%dH\1#12 %s \033[%d;%dH\1#13", + PASSWD_ROW, (WIDTH-((int)sizeof(title)+1))/2, + title, PASSWD_ROW+1, PASSWD_MARGIN+3); + + /* Actually allow user to type a password, then compare to the SHA1 */ + done = 0; + p = user_passwd; + + while ( !done ) { + key = mygetkey(0); + + switch ( key ) { + case KEY_ENTER: + case KEY_CTRL('J'): + done = 1; + break; + + case KEY_ESC: + case KEY_CTRL('C'): + p = user_passwd; /* No password entered */ + done = 1; + break; + + case KEY_BACKSPACE: + case KEY_DEL: + case KEY_DELETE: + if ( p > user_passwd ) { + printf("\b \b"); + p--; + } + break; + + case KEY_CTRL('U'): + while ( p > user_passwd ) { + printf("\b \b"); + p--; + } + break; + + default: + if ( key >= ' ' && key <= 0xFF && + (p-user_passwd) < WIDTH-2*PASSWD_MARGIN-5 ) { + *p++ = key; + putchar('*'); + } + break; + } + } + + if ( p == user_passwd ) + return 0; /* No password entered */ + + *p = '\0'; + + return (menu_master_passwd && passwd_compare(menu_master_passwd, user_passwd)) + || (menu_entry && passwd_compare(menu_entry, user_passwd)); +} + + +static void +draw_menu(int sel, int top, int edit_line) +{ + int x, y; + int sbtop = 0, sbbot = 0; + + if ( nentries > MENU_ROWS ) { + int sblen = MENU_ROWS*MENU_ROWS/nentries; + sbtop = (MENU_ROWS-sblen+1)*top/(nentries-MENU_ROWS+1); + sbbot = sbtop + sblen - 1; + + sbtop += 4; sbbot += 4; /* Starting row of scrollbar */ + } + + printf("\033[1;%dH\1#01\016l", MARGIN+1); + for ( x = 2 ; x <= WIDTH-2*MARGIN-1 ; x++ ) + putchar('q'); + + printf("k\033[2;%dH\1#01x\017\1#02 %s \1#01\016x", + MARGIN+1, + pad_line(menu_title, 1, WIDTH-2*MARGIN-4)); + + printf("\033[3;%dH\1#01t", MARGIN+1); + for ( x = 2 ; x <= WIDTH-2*MARGIN-1 ; x++ ) + putchar('q'); + fputs("u\017", stdout); + + for ( y = 4 ; y < 4+MENU_ROWS ; y++ ) + draw_row(y, sel, top, sbtop, sbbot); + + printf("\033[%d;%dH\1#01\016m", y, MARGIN+1); + for ( x = 2 ; x <= WIDTH-2*MARGIN-1 ; x++ ) + putchar('q'); + fputs("j\017", stdout); + + if ( edit_line && allowedit && !menu_master_passwd ) + printf("\1#08\033[%d;1H%s", TABMSG_ROW, + pad_line("Press [Tab] to edit options", 1, WIDTH)); + + printf("\1#00\033[%d;1H", END_ROW); +} + +static void +clear_screen(void) +{ + fputs("\033e\033%@\033)0\033(B\1#00\033[?25l\033[2J", stdout); +} + +static const char * +edit_cmdline(char *input, int top) +{ + static char cmdline[MAX_CMDLINE_LEN]; + int key, len, prev_len, cursor; + int redraw = 1; /* We enter with the menu already drawn */ + + strncpy(cmdline, input, MAX_CMDLINE_LEN); + cmdline[MAX_CMDLINE_LEN-1] = '\0'; + + len = cursor = strlen(cmdline); + prev_len = 0; + + for (;;) { + if ( redraw > 1 ) { + /* Clear and redraw whole screen */ + /* Enable ASCII on G0 and DEC VT on G1; do it in this order + to avoid confusing the Linux console */ + clear_screen(); + draw_menu(-1, top, 1); + prev_len = 0; + } + + if ( redraw > 0 ) { + /* Redraw the command line */ + printf("\033[?25l\033[%d;1H\1#09> \1#10%s", + CMDLINE_ROW, pad_line(cmdline, 0, prev_len)); + printf("\1#10\033[%d;3H%s\033[?25h", + CMDLINE_ROW, pad_line(cmdline, 0, cursor)); + prev_len = len; + redraw = 0; + } + + key = mygetkey(0); + + switch( key ) { + case KEY_CTRL('L'): + redraw = 2; + break; + + case KEY_ENTER: + case KEY_CTRL('J'): + return cmdline; + + case KEY_ESC: + case KEY_CTRL('C'): + return NULL; + + case KEY_BACKSPACE: + case KEY_DEL: + if ( cursor ) { + memmove(cmdline+cursor-1, cmdline+cursor, len-cursor+1); + len--; + cursor--; + redraw = 1; + } + break; + + case KEY_CTRL('D'): + case KEY_DELETE: + if ( cursor < len ) { + memmove(cmdline+cursor, cmdline+cursor+1, len-cursor); + len--; + redraw = 1; + } + break; + + case KEY_CTRL('U'): + if ( len ) { + len = cursor = 0; + cmdline[len] = '\0'; + redraw = 1; + } + break; + + case KEY_CTRL('W'): + if ( cursor ) { + int prevcursor = cursor; + + while ( cursor && my_isspace(cmdline[cursor-1]) ) + cursor--; + + while ( cursor && !my_isspace(cmdline[cursor-1]) ) + cursor--; + + memmove(cmdline+cursor, cmdline+prevcursor, len-prevcursor+1); + len -= (cursor-prevcursor); + redraw = 1; + } + break; + + case KEY_LEFT: + case KEY_CTRL('B'): + if ( cursor ) { + cursor--; + redraw = 1; + } + break; + + case KEY_RIGHT: + case KEY_CTRL('F'): + if ( cursor < len ) { + putchar(cmdline[cursor++]); + } + break; + + case KEY_CTRL('K'): + if ( cursor < len ) { + cmdline[len = cursor] = '\0'; + redraw = 1; + } + break; + + case KEY_HOME: + case KEY_CTRL('A'): + if ( cursor ) { + cursor = 0; + redraw = 1; + } + break; + + case KEY_END: + case KEY_CTRL('E'): + if ( cursor != len ) { + cursor = len; + redraw = 1; + } + break; + + default: + if ( key >= ' ' && key <= 0xFF && len < MAX_CMDLINE_LEN-1 ) { + if ( cursor == len ) { + cmdline[len] = key; + cmdline[++len] = '\0'; + cursor++; + putchar(key); + prev_len++; + } else { + memmove(cmdline+cursor+1, cmdline+cursor, len-cursor+1); + cmdline[cursor++] = key; + len++; + redraw = 1; + } + } + break; + } + } +} + +static inline int +shift_is_held(void) +{ + uint8_t shift_bits = *(uint8_t *)0x417; + + return !!(shift_bits & 0x5d); /* Caps/Scroll/Alt/Shift */ +} + +static const char * +run_menu(void) +{ + int key; + int done = 0; + volatile int entry = defentry, prev_entry = -1; + int top = 0, prev_top = -1; + int clear = 1, to_clear; + const char *cmdline = NULL; + volatile clock_t key_timeout, timeout_left, this_timeout; + + /* Note: for both key_timeout and timeout == 0 means no limit */ + timeout_left = key_timeout = timeout; + + /* If we're in shiftkey mode, exit immediately unless a shift key is pressed */ + if ( shiftkey && !shift_is_held() ) { + return menu_entries[defentry].cmdline; + } + + /* Handle both local and global timeout */ + if ( setjmp(timeout_jump) ) { + entry = defentry; + + if ( top < 0 || top < entry-MENU_ROWS+1 ) + top = max(0, entry-MENU_ROWS+1); + else if ( top > entry || top > max(0,nentries-MENU_ROWS) ) + top = min(entry, max(0,nentries-MENU_ROWS)); + + draw_menu(ontimeout ? -1 : entry, top, 1); + cmdline = ontimeout ? ontimeout : menu_entries[entry].cmdline; + done = 1; + } + + while ( !done ) { + if ( entry < 0 ) + entry = 0; + else if ( entry >= nentries ) + entry = nentries-1; + + if ( top < 0 || top < entry-MENU_ROWS+1 ) + top = max(0, entry-MENU_ROWS+1); + else if ( top > entry || top > max(0,nentries-MENU_ROWS) ) + top = min(entry, max(0,nentries-MENU_ROWS)); + + /* Start with a clear screen */ + if ( clear ) { + /* Clear and redraw whole screen */ + /* Enable ASCII on G0 and DEC VT on G1; do it in this order + to avoid confusing the Linux console */ + clear_screen(); + clear = 0; + prev_entry = prev_top = -1; + } + + if ( top != prev_top ) { + draw_menu(entry, top, 1); + } else if ( entry != prev_entry ) { + draw_row(prev_entry-top+4, entry, top, 0, 0); + draw_row(entry-top+4, entry, top, 0, 0); + } + + prev_entry = entry; prev_top = top; + + /* Cursor movement cancels timeout */ + if ( entry != defentry ) + key_timeout = 0; + + if ( key_timeout ) { + int tol = timeout_left/CLK_TCK; + int nc = snprintf(NULL, 0, " Automatic boot in %d seconds ", tol); + printf("\033[%d;%dH\1#14 Automatic boot in \1#15%d\1#14 seconds ", + TIMEOUT_ROW, 1+((WIDTH-nc)>>1), tol); + to_clear = 1; + } else { + to_clear = 0; + } + + this_timeout = min(min(key_timeout, timeout_left), CLK_TCK); + key = mygetkey(this_timeout); + + if ( key != KEY_NONE ) { + timeout_left = key_timeout; + if ( to_clear ) + printf("\033[%d;1H\1#00\033[K", TIMEOUT_ROW); + } + + switch ( key ) { + case KEY_NONE: /* Timeout */ + /* This is somewhat hacky, but this at least lets the user + know what's going on, and still deals with "phantom inputs" + e.g. on serial ports. + + Warning: a timeout will boot the default entry without any + password! */ + if ( key_timeout ) { + if ( timeout_left <= this_timeout ) + longjmp(timeout_jump, 1); + + timeout_left -= this_timeout; + } + break; + + case KEY_CTRL('L'): + clear = 1; + break; + + case KEY_ENTER: + case KEY_CTRL('J'): + key_timeout = 0; /* Cancels timeout */ + if ( menu_entries[entry].passwd ) { + clear = 1; + done = ask_passwd(menu_entries[entry].passwd); + } else { + done = 1; + } + cmdline = menu_entries[entry].cmdline; + break; + + case KEY_UP: + case KEY_CTRL('P'): + if ( entry > 0 ) { + entry--; + if ( entry < top ) + top -= MENU_ROWS; + } + break; + + case KEY_DOWN: + case KEY_CTRL('N'): + if ( entry < nentries-1 ) { + entry++; + if ( entry >= top+MENU_ROWS ) + top += MENU_ROWS; + } + break; + + case KEY_PGUP: + case KEY_LEFT: + case KEY_CTRL('B'): + case '<': + entry -= MENU_ROWS; + top -= MENU_ROWS; + break; + + case KEY_PGDN: + case KEY_RIGHT: + case KEY_CTRL('F'): + case '>': + case ' ': + entry += MENU_ROWS; + top += MENU_ROWS; + break; + + case '-': + entry--; + top--; + break; + + case '+': + entry++; + top++; + break; + + case KEY_CTRL('A'): + case KEY_HOME: + top = entry = 0; + break; + + case KEY_CTRL('E'): + case KEY_END: + entry = nentries - 1; + top = max(0, nentries-MENU_ROWS); + break; + + case KEY_TAB: + if ( allowedit ) { + int ok = 1; + + key_timeout = 0; /* Cancels timeout */ + draw_row(entry-top+4, -1, top, 0, 0); + + if ( menu_master_passwd ) { + ok = ask_passwd(NULL); + clear_screen(); + draw_menu(-1, top, 0); + } else { + /* Erase [Tab] message */ + printf("\033[%d;1H\1#00\033[K", TABMSG_ROW); + } + + if ( ok ) { + cmdline = edit_cmdline(menu_entries[entry].cmdline, top); + done = !!cmdline; + clear = 1; /* In case we hit [Esc] and done is null */ + } else { + draw_row(entry-top+4, entry, top, 0, 0); + } + } + break; + case KEY_CTRL('C'): /* Ctrl-C */ + case KEY_ESC: /* Esc */ + if ( allowedit ) { + done = 1; + clear = 1; + key_timeout = 0; + + draw_row(entry-top+4, -1, top, 0, 0); + + if ( menu_master_passwd ) + done = ask_passwd(NULL); + } + break; + default: + if ( key > 0 && key < 0xFF ) { + key &= ~0x20; /* Upper case */ + if ( menu_hotkeys[key] ) { + key_timeout = 0; + entry = menu_hotkeys[key] - menu_entries; + /* Should we commit at this point? */ + } + } + break; + } + } + + printf("\033[?25h"); /* Show cursor */ + + /* Return the label name so localboot and ipappend work */ + return cmdline; +} + + +static void +execute(const char *cmdline) +{ +#ifdef __COM32__ + com32sys_t ireg; + const char *p; + char *q = __com32.cs_bounce; + const char *kernel, *args; + + memset(&ireg, 0, sizeof ireg); + + kernel = q; + p = cmdline; + while ( *p && !my_isspace(*p) ) { + *q++ = *p++; + } + *q++ = '\0'; + + args = q; + while ( *p && my_isspace(*p) ) + p++; + + strcpy(q, p); + + if ( !strcmp(kernel, ".localboot") ) { + ireg.eax.w[0] = 0x0014; /* Local boot */ + ireg.edx.w[0] = strtoul(args, NULL, 0); + } else { + ireg.eax.w[0] = 0x0016; /* Run kernel image */ + ireg.esi.w[0] = OFFS(kernel); + ireg.ds = SEG(kernel); + ireg.ebx.w[0] = OFFS(args); + ireg.es = SEG(args); + /* ireg.ecx.l = 0; */ /* We do ipappend "manually" */ + /* ireg.edx.l = 0; */ + } + + __intcall(0x22, &ireg, NULL); + + /* If this returns, something went bad; return to menu */ +#else + /* For testing... */ + printf("\n\033[0m>>> %s\n", cmdline); + exit(0); +#endif +} + +int menu_main(int argc, char *argv[]) +{ + const char *cmdline; + + (void)argc; + + install_default_color_table(); + fputs("\1#00", stdout); + + parse_config(argv[1]); + + if (draw_background && menu_background) + draw_background(menu_background); + + if ( !nentries ) { + fputs("No LABEL entries found in configuration file!\n", stdout); + return 1; /* Error! */ + } + + for(;;) { + cmdline = run_menu(); + + printf("\033[?25h\033[%d;1H\033[0m", END_ROW); - if ( cmdline ) ++ if ( cmdline ) { + execute(cmdline); - else ++ if ( onerror ) ++ execute(onerror); ++ } else { + return 0; /* Exit */ ++ } + } +} diff --cc com32/modules/readconfig.c index 7d2ee21,69404d0..0a77956 --- a/com32/modules/readconfig.c +++ b/com32/modules/readconfig.c @@@ -35,9 -36,8 +37,10 @@@ char *onerror = NULL char *menu_master_passwd = NULL; +char *menu_background = NULL; + struct menu_entry menu_entries[MAX_ENTRIES]; + struct menu_entry hide_entries[MAX_ENTRIES]; struct menu_entry *menu_hotkeys[256]; #define astrdup(x) ({ char *__x = (x); \