Merge commit 'syslinux-3.82'
authorH. Peter Anvin <hpa@zytor.com>
Tue, 9 Jun 2009 17:49:31 +0000 (10:49 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Tue, 9 Jun 2009 17:49:31 +0000 (10:49 -0700)
Conflicts:
com32/menu/menumain.c

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
1  2 
com32/menu/menumain.c

@@@ -692,381 -666,383 +692,384 @@@ static void print_timeout_message(int t
  }
  
  /* Set the background screen, etc. */
 -static void
 -prepare_screen_for_menu(void)
 +static void prepare_screen_for_menu(void)
  {
 -  console_color_table = cm->color_table;
 -  console_color_table_size = menu_color_table_size;
 -  set_background(cm->menu_background);
 +    console_color_table = cm->color_table;
 +    console_color_table_size = menu_color_table_size;
 +    set_background(cm->menu_background);
  }
  
 -static const char *
 -do_hidden_menu(void)
 +static const char *do_hidden_menu(void)
  {
 -  int key;
 -  int timeout_left, this_timeout;
 +    int key;
 +    int timeout_left, this_timeout;
  
 -  clear_screen();
 +    clear_screen();
  
 -  if ( !setjmp(timeout_jump) ) {
 -    timeout_left = cm->timeout;
 +    if (!setjmp(timeout_jump)) {
 +      timeout_left = cm->timeout;
  
 -    while (!cm->timeout || timeout_left) {
 -      int tol = timeout_left/CLK_TCK;
 +      while (!cm->timeout || timeout_left) {
 +          int tol = timeout_left / CLK_TCK;
  
 -      print_timeout_message(tol, HIDDEN_ROW, cm->messages[MSG_AUTOBOOT]);
 +          print_timeout_message(tol, HIDDEN_ROW, cm->messages[MSG_AUTOBOOT]);
  
 -      this_timeout = min(timeout_left, CLK_TCK);
 -      key = mygetkey(this_timeout);
 +          this_timeout = min(timeout_left, CLK_TCK);
 +          key = mygetkey(this_timeout);
  
 -      if (key != KEY_NONE)
 -      return NULL;            /* Key pressed */
 +          if (key != KEY_NONE)
 +              return NULL;    /* Key pressed */
  
 -      timeout_left -= this_timeout;
 +          timeout_left -= this_timeout;
 +      }
      }
 -  }
  
-     return cm->menu_entries[cm->defentry]->cmdline;   /* Default entry */
 -  if (cm->ontimeout)
 -    return cm->ontimeout;
 -  return cm->menu_entries[cm->defentry]->cmdline; /* Default entry */
++    if (cm->ontimeout)
++      return cm->ontimeout;
++    else
++      return cm->menu_entries[cm->defentry]->cmdline; /* Default entry */
  }
  
 -static const char *
 -run_menu(void)
 +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;
 -
 -  /* 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) {
 -      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);
 +    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;
 +
 +    /* 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;
      }
  
 -    prev_entry = entry;  prev_top = top;
 -    cm->curentry = entry;
 -    cm->curtop = top;
 +    /* Do this before hiddenmenu handling, so we show the background */
 +    prepare_screen_for_menu();
  
 -    /* Cursor movement cancels timeout */
 -    if ( entry != cm->defentry )
 -      key_timeout = 0;
 +    /* Handle hiddenmenu */
 +    if (hiddenmenu) {
 +      cmdline = do_hidden_menu();
 +      if (cmdline)
 +          return cmdline;
  
 -    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;
 +      /* Otherwise display the menu now; the timeout has already been
 +         cancelled, since the user pressed a key. */
 +      hiddenmenu = 0;
 +      key_timeout = 0;
      }
  
 -    this_timeout = min(min(key_timeout, timeout_left), (clock_t)CLK_TCK);
 -    key = mygetkey(this_timeout);
 +    /* Handle both local and global timeout */
 +    if (setjmp(timeout_jump)) {
 +      entry = cm->defentry;
  
 -    if ( key != KEY_NONE ) {
 -      timeout_left = key_timeout;
 -      if ( to_clear )
 -      printf("\033[%d;1H\1#0\033[K", TIMEOUT_ROW);
 -    }
 +      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));
  
 -    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 {
 +      draw_menu(cm->ontimeout ? -1 : entry, top, 1);
 +      cmdline =
 +          cm->ontimeout ? cm->ontimeout : cm->menu_entries[entry]->cmdline;
        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;
 -      default:
 -        done = 0;
 -        break;
 +    }
 +
 +    while (!done) {
 +      if (entry <= 0) {
 +          entry = 0;
 +          while (entry < cm->nentries && is_disabled(cm->menu_entries[entry]))
 +              entry++;
        }
 -      }
 -      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();
 +      if (entry >= cm->nentries) {
 +          entry = cm->nentries - 1;
 +          while (entry > 0 && is_disabled(cm->menu_entries[entry]))
 +              entry--;
        }
 -      }
 -      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);
 +
 +      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 ( ok ) {
 -        cmdline = edit_cmdline(me->cmdline, top);
 -        done = !!cmdline;
 -        clear = 1;            /* In case we hit [Esc] and done is null */
 +      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 {
 -        draw_row(entry-top+4+VSHIFT, entry, top, 0, 0);
 +          to_clear = 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);
 +      this_timeout = min(min(key_timeout, timeout_left), (clock_t) CLK_TCK);
 +      key = mygetkey(this_timeout);
  
 -      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? */
 +      if (key != KEY_NONE) {
 +          timeout_left = key_timeout;
 +          if (to_clear)
 +              printf("\033[%d;1H\1#0\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 (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;
 +              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? */
 +              }
 +          }
 +          break;
        }
 -      }
 -      break;
      }
 -  }
  
 -  printf("\033[?25h");                /* Show cursor */
 +    printf("\033[?25h");      /* Show cursor */
  
 -  /* Return the label name so localboot and ipappend work */
 -  return cmdline;
 +    /* Return the label name so localboot and ipappend work */
 +    return cmdline;
  }
  
  int menu_main(int argc, char *argv[])