Пример #1
0
static const char *do_hidden_menu(void)
{
    int key;
    int timeout_left, this_timeout;

    clear_screen();

    if (!setjmp(timeout_jump)) {
	timeout_left = cm->timeout;

	while (!cm->timeout || timeout_left) {
	    int tol = timeout_left / CLK_TCK;

	    print_timeout_message(tol, HIDDEN_ROW, cm->messages[MSG_AUTOBOOT]);

	    this_timeout = min(timeout_left, CLK_TCK);
	    key = mygetkey(this_timeout);

	    if (key != KEY_NONE)
		return NULL;	/* Key pressed */

	    timeout_left -= this_timeout;
	}
    }

    /* Clear the message from the screen */
    print_timeout_message(0, HIDDEN_ROW, "");

    if (cm->ontimeout)
	return cm->ontimeout;
    else
	return cm->menu_entries[cm->defentry]->cmdline; /* Default entry */
}
Пример #2
0
int show_message_file(const char *filename, const char *background)
{
  int rv = KEY_NONE;
  const char *old_background = NULL;

  if (background) {
    old_background = current_background;
    set_background(background);
  }

  if ( !(rv = draw_message_file(filename)) )
    rv = mygetkey(0);		/* Wait for keypress */

  if (old_background)
    set_background(old_background);

  return rv;
}
Пример #3
0
static const char *run_menu(void)
{
    int key;
    int done = 0;
    volatile int entry = cm->curentry;
    int prev_entry = -1;
    volatile int top = cm->curtop;
    int prev_top = -1;
    int clear = 1, to_clear;
    const char *cmdline = NULL;
    volatile clock_t key_timeout, timeout_left, this_timeout;
    const struct menu_entry *me;
    bool hotkey = false;

    /* Note: for both key_timeout and timeout == 0 means no limit */
    timeout_left = key_timeout = cm->timeout;

    /* If we're in shiftkey mode, exit immediately unless a shift key
       is pressed */
    if (shiftkey && !shift_is_held()) {
	return cm->menu_entries[cm->defentry]->cmdline;
    } else {
	shiftkey = 0;
    }

    /* Do this before hiddenmenu handling, so we show the background */
    prepare_screen_for_menu();

    /* Handle hiddenmenu */
    if (hiddenmenu) {
	cmdline = do_hidden_menu();
	if (cmdline)
	    return cmdline;

	/* Otherwise display the menu now; the timeout has already been
	   cancelled, since the user pressed a key. */
	hiddenmenu = 0;
	key_timeout = 0;
    }

    /* Handle both local and global timeout */
    if (setjmp(timeout_jump)) {
	entry = cm->defentry;

	if (top < 0 || top < entry - MENU_ROWS + 1)
	    top = max(0, entry - MENU_ROWS + 1);
	else if (top > entry || top > max(0, cm->nentries - MENU_ROWS))
	    top = min(entry, max(0, cm->nentries - MENU_ROWS));

	draw_menu(cm->ontimeout ? -1 : entry, top, 1);
	cmdline =
	    cm->ontimeout ? cm->ontimeout : cm->menu_entries[entry]->cmdline;
	done = 1;
    }

    while (!done) {
	if (entry <= 0) {
	    entry = 0;
	    while (entry < cm->nentries && is_disabled(cm->menu_entries[entry]))
		entry++;
	}
	if (entry >= cm->nentries - 1) {
	    entry = cm->nentries - 1;
	    while (entry > 0 && is_disabled(cm->menu_entries[entry]))
		entry--;
	}

	me = cm->menu_entries[entry];

	if (top < 0 || top < entry - MENU_ROWS + 1)
	    top = max(0, entry - MENU_ROWS + 1);
	else if (top > entry || top > max(0, cm->nentries - MENU_ROWS))
	    top = min(entry, max(0, cm->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 */
	    if (clear >= 2)
		prepare_screen_for_menu();
	    clear_screen();
	    clear = 0;
	    prev_entry = prev_top = -1;
	}

	if (top != prev_top) {
	    draw_menu(entry, top, 1);
	    display_help(me->helptext);
	} else if (entry != prev_entry) {
	    draw_row(prev_entry - top + 4 + VSHIFT, entry, top, 0, 0);
	    draw_row(entry - top + 4 + VSHIFT, entry, top, 0, 0);
	    display_help(me->helptext);
	}

	prev_entry = entry;
	prev_top = top;
	cm->curentry = entry;
	cm->curtop = top;

	/* Cursor movement cancels timeout */
	if (entry != cm->defentry)
	    key_timeout = 0;

	if (key_timeout) {
	    int tol = timeout_left / CLK_TCK;
	    print_timeout_message(tol, TIMEOUT_ROW, cm->messages[MSG_AUTOBOOT]);
	    to_clear = 1;
	} else {
	    to_clear = 0;
	}

	if (hotkey && me->immediate) {
	    /* If the hotkey was flagged immediate, simulate pressing ENTER */
	    key = KEY_ENTER;
	} else {
	    this_timeout = min(min(key_timeout, timeout_left),
			       (clock_t) CLK_TCK);
	    key = mygetkey(this_timeout);

	    if (key != KEY_NONE) {
		timeout_left = key_timeout;
		if (to_clear)
		    printf("\033[%d;1H\1#0\033[K", TIMEOUT_ROW);
	    }
	}

	hotkey = false;

	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 (me->passwd) {
		clear = 1;
		done = ask_passwd(me->passwd);
	    } else {
		done = 1;
	    }
	    cmdline = NULL;
	    if (done) {
		switch (me->action) {
		case MA_CMD:
		    cmdline = me->cmdline;
		    break;
		case MA_SUBMENU:
		case MA_GOTO:
		case MA_EXIT:
		    done = 0;
		    clear = 2;
		    cm = me->submenu;
		    entry = cm->curentry;
		    top = cm->curtop;
		    break;
		case MA_QUIT:
		    /* Quit menu system */
		    done = 1;
		    clear = 1;
		    draw_row(entry - top + 4 + VSHIFT, -1, top, 0, 0);
		    break;
		case MA_HELP:
		    key = show_message_file(me->cmdline, me->background);
		    /* If the exit was an F-key, display that help screen */
		    show_fkey(key);
		    done = 0;
		    clear = 1;
		    break;
		default:
		    done = 0;
		    break;
		}
	    }
	    if (done && !me->passwd) {
		/* Only save a new default if we don't have a password... */
		if (me->save && me->label) {
		    syslinux_setadv(ADV_MENUSAVE, strlen(me->label), me->label);
		    syslinux_adv_write();
		}
	    }
	    break;

	case KEY_UP:
	case KEY_CTRL('P'):
	    while (entry > 0) {
		entry--;
		if (entry < top)
		    top -= MENU_ROWS;
		if (!is_disabled(cm->menu_entries[entry]))
		    break;
	    }
	    break;

	case KEY_DOWN:
	case KEY_CTRL('N'):
	    while (entry < cm->nentries - 1) {
		entry++;
		if (entry >= top + MENU_ROWS)
		    top += MENU_ROWS;
		if (!is_disabled(cm->menu_entries[entry]))
		    break;
	    }
	    break;

	case KEY_PGUP:
	case KEY_LEFT:
	case KEY_CTRL('B'):
	case '<':
	    entry -= MENU_ROWS;
	    top -= MENU_ROWS;
	    while (entry > 0 && is_disabled(cm->menu_entries[entry])) {
		entry--;
		if (entry < top)
		    top -= MENU_ROWS;
	    }
	    break;

	case KEY_PGDN:
	case KEY_RIGHT:
	case KEY_CTRL('F'):
	case '>':
	case ' ':
	    entry += MENU_ROWS;
	    top += MENU_ROWS;
	    while (entry < cm->nentries - 1
		   && is_disabled(cm->menu_entries[entry])) {
		entry++;
		if (entry >= top + MENU_ROWS)
		    top += MENU_ROWS;
	    }
	    break;

	case '-':
	    while (entry > 0) {
		entry--;
		top--;
		if (!is_disabled(cm->menu_entries[entry]))
		    break;
	    }
	    break;

	case '+':
	    while (entry < cm->nentries - 1) {
		entry++;
		top++;
		if (!is_disabled(cm->menu_entries[entry]))
		    break;
	    }
	    break;

	case KEY_CTRL('A'):
	case KEY_HOME:
	    top = entry = 0;
	    break;

	case KEY_CTRL('E'):
	case KEY_END:
	    entry = cm->nentries - 1;
	    top = max(0, cm->nentries - MENU_ROWS);
	    break;

	case KEY_F1:
	case KEY_F2:
	case KEY_F3:
	case KEY_F4:
	case KEY_F5:
	case KEY_F6:
	case KEY_F7:
	case KEY_F8:
	case KEY_F9:
	case KEY_F10:
	case KEY_F11:
	case KEY_F12:
	    show_fkey(key);
	    clear = 1;
	    break;

	case KEY_TAB:
	    if (cm->allowedit && me->action == MA_CMD) {
		int ok = 1;

		key_timeout = 0;	/* Cancels timeout */
		draw_row(entry - top + 4 + VSHIFT, -1, top, 0, 0);

		if (cm->menu_master_passwd) {
		    ok = ask_passwd(NULL);
		    clear_screen();
		    draw_menu(-1, top, 0);
		} else {
		    /* Erase [Tab] message and help text */
		    printf("\033[%d;1H\1#0\033[K", TABMSG_ROW);
		    display_help(NULL);
		}

		if (ok) {
		    cmdline = edit_cmdline(me->cmdline, top);
		    done = !!cmdline;
		    clear = 1;	/* In case we hit [Esc] and done is null */
		} else {
		    draw_row(entry - top + 4 + VSHIFT, entry, top, 0, 0);
		}
	    }
	    break;
	case KEY_CTRL('C'):	/* Ctrl-C */
	case KEY_ESC:		/* Esc */
	    if (cm->parent) {
		cm = cm->parent;
		clear = 2;
		entry = cm->curentry;
		top = cm->curtop;
	    } else if (cm->allowedit) {
		done = 1;
		clear = 1;
		key_timeout = 0;

		draw_row(entry - top + 4 + VSHIFT, -1, top, 0, 0);

		if (cm->menu_master_passwd)
		    done = ask_passwd(NULL);
	    }
	    break;
	default:
	    if (key > 0 && key < 0xFF) {
		key &= ~0x20;	/* Upper case */
		if (cm->menu_hotkeys[key]) {
		    key_timeout = 0;
		    entry = cm->menu_hotkeys[key]->entry;
		    /* Should we commit at this point? */
		    hotkey = true;
		}
	    }
	    break;
	}
    }

    printf("\033[?25h");	/* Show cursor */

    /* Return the label name so localboot and ipappend work */
    return cmdline;
}
Пример #4
0
static const char *edit_cmdline(const 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 */

    strlcpy(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#9> \2#10%s",
		   CMDLINE_ROW, pad_line(cmdline, 0, max(len, prev_len)));
	    printf("\2#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 -= (prevcursor - cursor);
		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;

	case KEY_F1:
	case KEY_F2:
	case KEY_F3:
	case KEY_F4:
	case KEY_F5:
	case KEY_F6:
	case KEY_F7:
	case KEY_F8:
	case KEY_F9:
	case KEY_F10:
	case KEY_F11:
	case KEY_F12:
	    show_fkey(key);
	    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;
	}
    }
}
Пример #5
0
static int ask_passwd(const char *menu_entry)
{
    char user_passwd[WIDTH], *p;
    int done;
    int key;
    int x;
    int rv;

    printf("\033[%d;%dH\2#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\2#12 %s \033[%d;%dH\2#13",
	   PASSWD_ROW, (WIDTH - (strlen(cm->messages[MSG_PASSPROMPT]) + 2)) / 2,
	   cm->messages[MSG_PASSPROMPT], PASSWD_ROW + 1, PASSWD_MARGIN + 3);

    drain_keyboard();

    /* 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';

    rv = (cm->menu_master_passwd &&
	  passwd_compare(cm->menu_master_passwd, user_passwd))
	|| (menu_entry && passwd_compare(menu_entry, user_passwd));

    /* Clean up */
    memset(user_passwd, 0, WIDTH);
    drain_keyboard();

    return rv;
}