~ubuntu-branches/ubuntu/utopic/grub/utopic

« back to all changes in this revision

Viewing changes to stage2/stage2.c

  • Committer: Bazaar Package Importer
  • Author(s): Jason Thomas
  • Date: 2002-02-04 15:35:01 UTC
  • Revision ID: james.westby@ubuntu.com-20020204153501-neulkag77r3a2m0v
Tags: upstream-0.91
ImportĀ upstreamĀ versionĀ 0.91

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  GRUB  --  GRand Unified Bootloader
 
3
 *  Copyright (C) 2000, 2001  Free Software Foundation, Inc.
 
4
 *
 
5
 *  This program is free software; you can redistribute it and/or modify
 
6
 *  it under the terms of the GNU General Public License as published by
 
7
 *  the Free Software Foundation; either version 2 of the License, or
 
8
 *  (at your option) any later version.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
18
 */
 
19
 
 
20
#include "shared.h"
 
21
 
 
22
grub_jmp_buf restart_env;
 
23
 
 
24
#if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS)
 
25
 
 
26
# if defined(PRESET_MENU_STRING)
 
27
static const char *preset_menu = PRESET_MENU_STRING;
 
28
# elif defined(SUPPORT_DISKLESS)
 
29
/* Execute the command "bootp" automatically.  */
 
30
static const char *preset_menu = "bootp\n";
 
31
# endif /* SUPPORT_DISKLESS */
 
32
 
 
33
static int preset_menu_offset;
 
34
 
 
35
static int
 
36
open_preset_menu (void)
 
37
{
 
38
#ifdef GRUB_UTIL
 
39
  /* Unless the user explicitly requests to use the preset menu,
 
40
     always opening the preset menu fails in the grub shell.  */
 
41
  if (! use_preset_menu)
 
42
    return 0;
 
43
#endif /* GRUB_UTIL */
 
44
  
 
45
  preset_menu_offset = 0;
 
46
  return preset_menu != 0;
 
47
}
 
48
 
 
49
static int
 
50
read_from_preset_menu (char *buf, int maxlen)
 
51
{
 
52
  int len = grub_strlen (preset_menu + preset_menu_offset);
 
53
 
 
54
  if (len > maxlen)
 
55
    len = maxlen;
 
56
 
 
57
  grub_memmove (buf, preset_menu + preset_menu_offset, len);
 
58
  preset_menu_offset += len;
 
59
 
 
60
  return len;
 
61
}
 
62
 
 
63
static void
 
64
close_preset_menu (void)
 
65
{
 
66
  /* Disable the preset menu.  */
 
67
  preset_menu = 0;
 
68
}
 
69
 
 
70
#else /* ! PRESET_MENU_STRING && ! SUPPORT_DISKLESS */
 
71
 
 
72
#define open_preset_menu()      0
 
73
#define read_from_preset_menu(buf, maxlen)      0
 
74
#define close_preset_menu()
 
75
 
 
76
#endif /* ! PRESET_MENU_STRING && ! SUPPORT_DISKLESS */
 
77
 
 
78
 
 
79
static char *
 
80
get_entry (char *list, int num, int nested)
 
81
{
 
82
  int i;
 
83
 
 
84
  for (i = 0; i < num; i++)
 
85
    {
 
86
      do
 
87
        {
 
88
          while (*(list++));
 
89
        }
 
90
      while (nested && *(list++));
 
91
    }
 
92
 
 
93
  return list;
 
94
}
 
95
 
 
96
 
 
97
static void
 
98
print_entries (int y, int size, int first, char *menu_entries)
 
99
{
 
100
  int i;
 
101
  int disp_up = DISP_UP;
 
102
  int disp_down = DISP_DOWN;
 
103
 
 
104
#ifdef SUPPORT_SERIAL
 
105
  if (terminal & TERMINAL_SERIAL)
 
106
    {
 
107
      disp_up = ACS_UARROW;
 
108
      disp_down = ACS_DARROW;
 
109
    }
 
110
#endif /* SUPPORT_SERIAL */
 
111
  
 
112
  gotoxy (77, y + 1);
 
113
 
 
114
  if (first)
 
115
    grub_putchar (disp_up);
 
116
  else
 
117
    grub_putchar (' ');
 
118
 
 
119
  menu_entries = get_entry (menu_entries, first, 0);
 
120
 
 
121
  for (i = 1; i <= size; i++)
 
122
    {
 
123
      int j = 0;
 
124
 
 
125
      gotoxy (3, y + i);
 
126
 
 
127
      while (*menu_entries)
 
128
        {
 
129
          if (j < 71)
 
130
            {
 
131
              grub_putchar (*menu_entries);
 
132
              j++;
 
133
            }
 
134
 
 
135
          menu_entries++;
 
136
        }
 
137
 
 
138
      if (*(menu_entries - 1))
 
139
        menu_entries++;
 
140
 
 
141
      for (; j < 71; j++)
 
142
        grub_putchar (' ');
 
143
    }
 
144
 
 
145
  gotoxy (77, y + size);
 
146
 
 
147
  if (*menu_entries)
 
148
    grub_putchar (disp_down);
 
149
  else
 
150
    grub_putchar (' ');
 
151
}
 
152
 
 
153
 
 
154
static void
 
155
print_entries_raw (int size, int first, char *menu_entries)
 
156
{
 
157
  int i;
 
158
 
 
159
#define LINE_LENGTH 67
 
160
 
 
161
  for (i = 0; i < LINE_LENGTH; i++)
 
162
    grub_putchar ('-');
 
163
  grub_putchar ('\n');
 
164
 
 
165
  for (i = first; i < size; i++)
 
166
    {
 
167
      /* grub's printf can't %02d so ... */
 
168
      if (i < 10)
 
169
        grub_putchar (' ');
 
170
      grub_printf ("%d: %s\n", i, get_entry (menu_entries, i, 0));
 
171
    }
 
172
 
 
173
  for (i = 0; i < LINE_LENGTH; i++)
 
174
    grub_putchar ('-');
 
175
  grub_putchar ('\n');
 
176
 
 
177
#undef LINE_LENGTH
 
178
}
 
179
 
 
180
 
 
181
static void
 
182
print_border (int y, int size)
 
183
{
 
184
  int i;
 
185
  int disp_ul = DISP_UL;
 
186
  int disp_ur = DISP_UR;
 
187
  int disp_ll = DISP_LL;
 
188
  int disp_lr = DISP_LR;
 
189
  int disp_horiz = DISP_HORIZ;
 
190
  int disp_vert = DISP_VERT;
 
191
 
 
192
#ifdef SUPPORT_SERIAL
 
193
  if (terminal & TERMINAL_SERIAL)
 
194
    {
 
195
      disp_ul = ACS_ULCORNER;
 
196
      disp_ur = ACS_URCORNER;
 
197
      disp_ll = ACS_LLCORNER;
 
198
      disp_lr = ACS_LRCORNER;
 
199
      disp_horiz = ACS_HLINE;
 
200
      disp_vert = ACS_VLINE;
 
201
    }
 
202
#endif /* SUPPORT_SERIAL */
 
203
  
 
204
#ifndef GRUB_UTIL
 
205
  /* Color the menu. The menu is 75 * 14 characters.  */
 
206
# ifdef SUPPORT_SERIAL
 
207
  if ((terminal & TERMINAL_CONSOLE)
 
208
#  ifdef SUPPORT_HERCULES
 
209
      || (terminal & TERMINAL_HERCULES)
 
210
#  endif
 
211
      )
 
212
# endif
 
213
    {
 
214
      for (i = 0; i < 14; i++)
 
215
        {
 
216
          int j;
 
217
          for (j = 0; j < 75; j++)
 
218
            {
 
219
              gotoxy (j + 1, i + y);
 
220
              set_attrib (normal_color);
 
221
            }
 
222
        }
 
223
    }
 
224
#endif
 
225
 
 
226
  gotoxy (1, y);
 
227
 
 
228
  grub_putchar (disp_ul);
 
229
  for (i = 0; i < 73; i++)
 
230
    grub_putchar (disp_horiz);
 
231
  grub_putchar (disp_ur);
 
232
 
 
233
  i = 1;
 
234
 
 
235
  while (1)
 
236
    {
 
237
      gotoxy (1, y + i);
 
238
 
 
239
      if (i > size)
 
240
        break;
 
241
 
 
242
      grub_putchar (disp_vert);
 
243
      gotoxy (75, y + i);
 
244
      grub_putchar (disp_vert);
 
245
 
 
246
      i++;
 
247
    }
 
248
 
 
249
  grub_putchar (disp_ll);
 
250
  for (i = 0; i < 73; i++)
 
251
    grub_putchar (disp_horiz);
 
252
  grub_putchar (disp_lr);
 
253
}
 
254
 
 
255
static void
 
256
set_line (int y, int entryno, int attr, char *menu_entries)
 
257
{
 
258
  int x;
 
259
 
 
260
#ifdef SUPPORT_SERIAL
 
261
  if (terminal & TERMINAL_SERIAL)
 
262
    {
 
263
      menu_entries = get_entry (menu_entries, entryno, 0);
 
264
      gotoxy (2, y);
 
265
      grub_putchar (' ');
 
266
      for (x = 3; x < 75; x++)
 
267
        {
 
268
          if (*menu_entries && x < 71)
 
269
            grub_putchar (*menu_entries++);
 
270
          else
 
271
            grub_putchar (' ');
 
272
        }
 
273
    }
 
274
  else
 
275
#endif /* SUPPORT_SERIAL */
 
276
    {
 
277
      for (x = 2; x < 75; x++)
 
278
        {
 
279
          gotoxy (x, y);
 
280
          set_attrib (attr);
 
281
        }
 
282
    }
 
283
 
 
284
  gotoxy (74, y);
 
285
}
 
286
 
 
287
/* Set the attribute of the line Y to normal state.  */
 
288
static void
 
289
set_line_normal (int y, int entryno, char *menu_entries)
 
290
{
 
291
#ifdef GRUB_UTIL
 
292
  set_line (y, entryno, A_NORMAL, menu_entries);
 
293
#else
 
294
  set_line (y, entryno, normal_color, menu_entries);
 
295
#endif
 
296
}
 
297
 
 
298
/* Set the attribute of the line Y to highlight state.  */
 
299
static void
 
300
set_line_highlight (int y, int entryno, char *menu_entries)
 
301
{
 
302
#ifdef SUPPORT_SERIAL
 
303
  if (terminal & TERMINAL_SERIAL)
 
304
    grub_printf ("\e[7m");
 
305
#endif /* SUPPORT_SERIAL */
 
306
  
 
307
#ifdef GRUB_UTIL
 
308
  set_line (y, entryno, A_REVERSE, menu_entries);
 
309
#else
 
310
  set_line (y, entryno, highlight_color, menu_entries);
 
311
#endif
 
312
  
 
313
#ifdef SUPPORT_SERIAL
 
314
  if (terminal & TERMINAL_SERIAL)
 
315
    grub_printf ("\e[0m");
 
316
#endif /* SUPPORT_SERIAL */
 
317
}
 
318
 
 
319
static void
 
320
run_menu (char *menu_entries, char *config_entries, int num_entries,
 
321
          char *heap, int entryno)
 
322
{
 
323
  int c, time1, time2 = -1, first_entry = 0;
 
324
  char *cur_entry = 0;
 
325
  int disp_up = DISP_UP;
 
326
  int disp_down = DISP_DOWN;
 
327
 
 
328
  /*
 
329
   *  Main loop for menu UI.
 
330
   */
 
331
 
 
332
restart:
 
333
  /* Dumb terminal always use all entries for display 
 
334
     invariant for TERMINAL_DUMB: first_entry == 0  */
 
335
  if (! (terminal & TERMINAL_DUMB))
 
336
    {
 
337
      while (entryno > 11)
 
338
        {
 
339
          first_entry++;
 
340
          entryno--;
 
341
        }
 
342
    }
 
343
 
 
344
  /* If the timeout was expired or wasn't set, force to show the menu
 
345
     interface. */
 
346
  if (grub_timeout < 0)
 
347
    show_menu = 1;
 
348
  
 
349
  /* If SHOW_MENU is false, don't display the menu until ESC is pressed.  */
 
350
  if (! show_menu)
 
351
    {
 
352
      /* Get current time.  */
 
353
      while ((time1 = getrtsecs ()) == 0xFF)
 
354
        ;
 
355
 
 
356
      while (1)
 
357
        {
 
358
          /* Check if ESC is pressed.  */
 
359
          if (checkkey () != -1 && ASCII_CHAR (getkey ()) == '\e')
 
360
            {
 
361
              grub_timeout = -1;
 
362
              show_menu = 1;
 
363
              break;
 
364
            }
 
365
 
 
366
          /* If GRUB_TIMEOUT is expired, boot the default entry.  */
 
367
          if (grub_timeout >=0
 
368
              && (time1 = getrtsecs ()) != time2
 
369
              && time1 != 0xFF)
 
370
            {
 
371
              if (grub_timeout <= 0)
 
372
                {
 
373
                  grub_timeout = -1;
 
374
                  goto boot_entry;
 
375
                }
 
376
              
 
377
              time2 = time1;
 
378
              grub_timeout--;
 
379
              
 
380
              /* Print a message.  */
 
381
              grub_printf ("\rPress `ESC' to enter the menu... %d   ",
 
382
                           grub_timeout);
 
383
            }
 
384
        }
 
385
    }
 
386
 
 
387
  /* Only display the menu if the user wants to see it. */
 
388
  if (show_menu)
 
389
    {
 
390
      /* Disable the auto fill mode.  */
 
391
      auto_fill = 0;
 
392
      
 
393
      init_page ();
 
394
#ifndef GRUB_UTIL
 
395
# ifdef SUPPORT_SERIAL
 
396
      if (terminal & TERMINAL_CONSOLE)
 
397
# endif /* SUPPORT_SERIAL */
 
398
        nocursor ();
 
399
#endif /* ! GRUB_UTIL */
 
400
 
 
401
      if (! (terminal & TERMINAL_DUMB))      
 
402
          print_border (3, 12);
 
403
 
 
404
#ifdef GRUB_UTIL
 
405
      /* In the grub shell, always use ACS_*.  */
 
406
      disp_up = ACS_UARROW;
 
407
      disp_down = ACS_DARROW;
 
408
#else /* ! GRUB_UTIL */
 
409
# ifdef SUPPORT_SERIAL
 
410
      if ((terminal & TERMINAL_CONSOLE)
 
411
#  ifdef SUPPORT_HERCULES
 
412
          || (terminal & TERMINAL_HERCULES)
 
413
#  endif /* SUPPORT_HERCULES */
 
414
          )
 
415
        {
 
416
          disp_up = DISP_UP;
 
417
          disp_down = DISP_DOWN;
 
418
        }
 
419
      else
 
420
        {
 
421
          disp_up = ACS_UARROW;
 
422
          disp_down = ACS_DARROW;
 
423
        }
 
424
# endif /* SUPPORT_SERIAL */
 
425
#endif /* ! GRUB_UTIL */
 
426
      
 
427
      if (terminal & TERMINAL_DUMB)
 
428
          print_entries_raw (num_entries, first_entry, menu_entries);
 
429
 
 
430
      grub_printf ("\n\
 
431
      Use the %c and %c keys to select which entry is highlighted.\n",
 
432
                   disp_up, disp_down);
 
433
      
 
434
      if (! auth && password)
 
435
        {
 
436
          printf ("\
 
437
      Press enter to boot the selected OS or \'p\' to enter a\n\
 
438
      password to unlock the next set of features.");
 
439
        }
 
440
      else
 
441
        {
 
442
          if (config_entries)
 
443
            printf ("\
 
444
      Press enter to boot the selected OS, \'e\' to edit the\n\
 
445
      commands before booting, or \'c\' for a command-line.");
 
446
          else
 
447
            printf ("\
 
448
      Press \'b\' to boot, \'e\' to edit the selected command in the\n\
 
449
      boot sequence, \'c\' for a command-line, \'o\' to open a new line\n\
 
450
      after (\'O\' for before) the selected line, \'d\' to remove the\n\
 
451
      selected line, or escape to go back to the main menu.");
 
452
        }
 
453
 
 
454
      if (terminal & TERMINAL_DUMB)      
 
455
        grub_printf ("\n\nThe selected entry is %d ", entryno);
 
456
      else
 
457
      {
 
458
          print_entries (3, 12, first_entry, menu_entries);
 
459
          
 
460
          /* highlight initial line */
 
461
          set_line_highlight (4 + entryno, first_entry + entryno, 
 
462
                              menu_entries);
 
463
      }
 
464
    }
 
465
 
 
466
  /* XX using RT clock now, need to initialize value */
 
467
  while ((time1 = getrtsecs()) == 0xFF);
 
468
 
 
469
  while (1)
 
470
    {
 
471
      /* Initialize to NULL just in case...  */
 
472
      cur_entry = NULL;
 
473
 
 
474
      if (grub_timeout >= 0 && (time1 = getrtsecs()) != time2 && time1 != 0xFF)
 
475
        {
 
476
          if (grub_timeout <= 0)
 
477
            {
 
478
              grub_timeout = -1;
 
479
              break;
 
480
            }
 
481
 
 
482
          /* else not booting yet! */
 
483
          time2  = time1;
 
484
 
 
485
          if (terminal & TERMINAL_DUMB)
 
486
              grub_printf ("\r    Entry %d will be booted automatically in %d seconds.   ", 
 
487
                           entryno, grub_timeout);
 
488
          else
 
489
          {
 
490
              gotoxy (3, 22);
 
491
              printf ("The highlighted entry will be booted automatically in %d seconds.    ", grub_timeout);
 
492
              gotoxy (74, 4 + entryno);
 
493
          }
 
494
          
 
495
          grub_timeout--;
 
496
        }
 
497
 
 
498
      /* Check for a keypress, however if TIMEOUT has been expired
 
499
         (GRUB_TIMEOUT == -1) relax in GETKEY even if no key has been
 
500
         pressed.  
 
501
         This avoids polling (relevant in the grub-shell and later on
 
502
         in grub if interrupt driven I/O is done).  */
 
503
      if ((checkkey () != -1) || (grub_timeout == -1)) 
 
504
        {
 
505
          /* Key was pressed, show which entry is selected before GETKEY,
 
506
             since we're comming in here also on GRUB_TIMEOUT == -1 and
 
507
             hang in GETKEY */
 
508
          if (terminal & TERMINAL_DUMB)
 
509
            grub_printf ("\r    Highlighted entry is %d: ", entryno);
 
510
 
 
511
          c = translate_keycode (getkey ());
 
512
 
 
513
          if (grub_timeout >= 0)
 
514
            {
 
515
              if (terminal & TERMINAL_DUMB)
 
516
                grub_putchar ('\r');
 
517
              else
 
518
                gotoxy (3, 22);
 
519
              printf ("                                                                    ");
 
520
              grub_timeout = -1;
 
521
              fallback_entry = -1;
 
522
              if (! (terminal & TERMINAL_DUMB))
 
523
                gotoxy (74, 4 + entryno);
 
524
            }
 
525
 
 
526
          /* We told them above (at least in SUPPORT_SERIAL) to use
 
527
             '^' or 'v' so accept these keys.  */
 
528
          if (c == 16 || c == '^')
 
529
            {
 
530
              if (terminal & TERMINAL_DUMB)
 
531
                {
 
532
                  if (entryno > 0)
 
533
                    entryno--;
 
534
                }
 
535
              else
 
536
                {
 
537
                  if (entryno > 0)
 
538
                    {
 
539
                      set_line_normal (4 + entryno, first_entry + entryno,
 
540
                                       menu_entries);
 
541
                      entryno--;
 
542
                      set_line_highlight (4 + entryno, first_entry + entryno,
 
543
                                          menu_entries);
 
544
                    }
 
545
                  else if (first_entry > 0)
 
546
                    {
 
547
                      first_entry--;
 
548
                      print_entries (3, 12, first_entry, menu_entries);
 
549
                      set_line_highlight (4, first_entry + entryno, 
 
550
                                          menu_entries);
 
551
                    }
 
552
                }
 
553
            }
 
554
          if ((c == 14 || c == 'v') && first_entry + entryno + 1 < num_entries)
 
555
            {
 
556
              if (terminal & TERMINAL_DUMB)
 
557
                entryno++;
 
558
              else
 
559
                if (entryno < 11)
 
560
                  {
 
561
                    set_line_normal (4 + entryno, first_entry + entryno,
 
562
                                     menu_entries);
 
563
                    entryno++;
 
564
                    set_line_highlight (4 + entryno, first_entry + entryno,
 
565
                                        menu_entries);
 
566
                  }
 
567
                else if (num_entries > 12 + first_entry)
 
568
                  {
 
569
                    first_entry++;
 
570
                    print_entries (3, 12, first_entry, menu_entries);
 
571
                    set_line_highlight (15, first_entry + entryno, menu_entries);
 
572
                  }
 
573
            }
 
574
 
 
575
          if (config_entries)
 
576
            {
 
577
              if ((c == '\n') || (c == '\r'))
 
578
                break;
 
579
            }
 
580
          else
 
581
            {
 
582
              if ((c == 'd') || (c == 'o') || (c == 'O'))
 
583
                {
 
584
                  if (! (terminal & TERMINAL_DUMB))
 
585
                    set_line_normal (4 + entryno, first_entry + entryno,
 
586
                                     menu_entries);
 
587
 
 
588
                  /* insert after is almost exactly like insert before */
 
589
                  if (c == 'o')
 
590
                    {
 
591
                      /* But `o' differs from `O', since it may causes
 
592
                         the menu screen to scroll up.  */
 
593
                      if (entryno < 11 || (terminal & TERMINAL_DUMB))
 
594
                        entryno++;
 
595
                      else
 
596
                        first_entry++;
 
597
                      
 
598
                      c = 'O';
 
599
                    }
 
600
 
 
601
                  cur_entry = get_entry (menu_entries,
 
602
                                         first_entry + entryno,
 
603
                                         0);
 
604
 
 
605
                  if (c == 'O')
 
606
                    {
 
607
                      memmove (cur_entry + 2, cur_entry,
 
608
                               ((int) heap) - ((int) cur_entry));
 
609
 
 
610
                      cur_entry[0] = ' ';
 
611
                      cur_entry[1] = 0;
 
612
 
 
613
                      heap += 2;
 
614
 
 
615
                      num_entries++;
 
616
                    }
 
617
                  else if (num_entries > 0)
 
618
                    {
 
619
                      char *ptr = get_entry(menu_entries,
 
620
                                            first_entry + entryno + 1,
 
621
                                            0);
 
622
 
 
623
                      memmove (cur_entry, ptr, ((int) heap) - ((int) ptr));
 
624
                      heap -= (((int) ptr) - ((int) cur_entry));
 
625
 
 
626
                      num_entries--;
 
627
 
 
628
                      if (entryno >= num_entries)
 
629
                        entryno--;
 
630
                      if (first_entry && num_entries < 12 + first_entry)
 
631
                        first_entry--;
 
632
                    }
 
633
 
 
634
                  if (terminal & TERMINAL_DUMB)
 
635
                    {
 
636
                      grub_printf ("\n\n");
 
637
                      print_entries_raw (num_entries, first_entry,
 
638
                                         menu_entries);
 
639
                      grub_printf ("\n");
 
640
                    }
 
641
                  else
 
642
                    {
 
643
                      print_entries (3, 12, first_entry, menu_entries);
 
644
                      set_line_highlight (4 + entryno, first_entry + entryno,
 
645
                                          menu_entries);
 
646
                    }
 
647
                }
 
648
 
 
649
              cur_entry = menu_entries;
 
650
              if (c == 27)
 
651
                return;
 
652
              if (c == 'b')
 
653
                break;
 
654
            }
 
655
 
 
656
          if (! auth && password)
 
657
            {
 
658
              if (c == 'p')
 
659
                {
 
660
                  /* Do password check here! */
 
661
                  char entered[32];
 
662
                  char *pptr = password;
 
663
 
 
664
                  if (terminal & TERMINAL_DUMB)
 
665
                    grub_printf ("\r                                    ");
 
666
                  else
 
667
                    gotoxy (1, 21);
 
668
 
 
669
                  /* Wipe out the previously entered password */
 
670
                  memset (entered, 0, sizeof (entered));
 
671
                  get_cmdline (" Password: ", entered, 31, '*', 0);
 
672
 
 
673
                  while (! isspace (*pptr) && *pptr)
 
674
                    pptr++;
 
675
 
 
676
                  /* Make sure that PASSWORD is NUL-terminated.  */
 
677
                  *pptr++ = 0;
 
678
 
 
679
                  if (! check_password (entered, password, password_type))
 
680
                    {
 
681
                      char *new_file = config_file;
 
682
                      while (isspace (*pptr))
 
683
                        pptr++;
 
684
 
 
685
                      /* If *PPTR is NUL, then allow the user to use
 
686
                         privileged instructions, otherwise, load
 
687
                         another configuration file.  */
 
688
                      if (*pptr != 0)
 
689
                        {
 
690
                          while ((*(new_file++) = *(pptr++)) != 0)
 
691
                            ;
 
692
 
 
693
                          /* Make sure that the user will not have
 
694
                             authority in the next configuration.  */
 
695
                          auth = 0;
 
696
                          return;
 
697
                        }
 
698
                      else
 
699
                        {
 
700
                          /* Now the user is superhuman.  */
 
701
                          auth = 1;
 
702
                          goto restart;
 
703
                        }
 
704
                    }
 
705
                  else
 
706
                    {
 
707
                      printf ("Failed!\n      Press any key to continue...");
 
708
                      getkey ();
 
709
                      goto restart;
 
710
                    }
 
711
                }
 
712
            }
 
713
          else
 
714
            {
 
715
              if (c == 'e')
 
716
                {
 
717
                  int new_num_entries = 0, i = 0;
 
718
                  char *new_heap;
 
719
 
 
720
                  if (config_entries)
 
721
                    {
 
722
                      new_heap = heap;
 
723
                      cur_entry = get_entry (config_entries,
 
724
                                             first_entry + entryno,
 
725
                                             1);
 
726
                    }
 
727
                  else
 
728
                    {
 
729
                      /* safe area! */
 
730
                      new_heap = heap + NEW_HEAPSIZE + 1;
 
731
                      cur_entry = get_entry (menu_entries,
 
732
                                             first_entry + entryno,
 
733
                                             0);
 
734
                    }
 
735
 
 
736
                  do
 
737
                    {
 
738
                      while ((*(new_heap++) = cur_entry[i++]) != 0);
 
739
                      new_num_entries++;
 
740
                    }
 
741
                  while (config_entries && cur_entry[i]);
 
742
 
 
743
                  /* this only needs to be done if config_entries is non-NULL,
 
744
                     but it doesn't hurt to do it always */
 
745
                  *(new_heap++) = 0;
 
746
 
 
747
                  if (config_entries)
 
748
                    run_menu (heap, NULL, new_num_entries, new_heap, 0);
 
749
                  else
 
750
                    {
 
751
                      cls ();
 
752
                      print_cmdline_message (0);
 
753
 
 
754
                      new_heap = heap + NEW_HEAPSIZE + 1;
 
755
 
 
756
                      saved_drive = boot_drive;
 
757
                      saved_partition = install_partition;
 
758
                      current_drive = 0xFF;
 
759
 
 
760
                      if (! get_cmdline (PACKAGE " edit> ", new_heap,
 
761
                                         NEW_HEAPSIZE + 1, 0, 1))
 
762
                        {
 
763
                          int j = 0;
 
764
 
 
765
                          /* get length of new command */
 
766
                          while (new_heap[j++])
 
767
                            ;
 
768
 
 
769
                          if (j < 2)
 
770
                            {
 
771
                              j = 2;
 
772
                              new_heap[0] = ' ';
 
773
                              new_heap[1] = 0;
 
774
                            }
 
775
 
 
776
                          /* align rest of commands properly */
 
777
                          memmove (cur_entry + j, cur_entry + i,
 
778
                                   ((int) heap) - (((int) cur_entry) + i));
 
779
 
 
780
                          /* copy command to correct area */
 
781
                          memmove (cur_entry, new_heap, j);
 
782
 
 
783
                          heap += (j - i);
 
784
                        }
 
785
                    }
 
786
 
 
787
                  goto restart;
 
788
                }
 
789
              if (c == 'c')
 
790
                {
 
791
                  enter_cmdline (heap, 0);
 
792
                  goto restart;
 
793
                }
 
794
#ifdef GRUB_UTIL
 
795
              if (c == 'q')
 
796
                {
 
797
                  /* The same as ``quit''.  */
 
798
                  stop ();
 
799
                }
 
800
#endif
 
801
            }
 
802
        }
 
803
    }
 
804
 
 
805
  /* Attempt to boot an entry.  */
 
806
  
 
807
 boot_entry:
 
808
  /* Enable the auto fill mode.  */
 
809
  auto_fill = 1;
 
810
  
 
811
  while (1)
 
812
    {
 
813
      cls ();
 
814
 
 
815
      if (config_entries)
 
816
        printf ("  Booting \'%s\'\n\n",
 
817
                get_entry (menu_entries, first_entry + entryno, 0));
 
818
      else
 
819
        printf ("  Booting command-list\n\n");
 
820
 
 
821
      if (! cur_entry)
 
822
        cur_entry = get_entry (config_entries, first_entry + entryno, 1);
 
823
 
 
824
      /* Set CURRENT_ENTRYNO for the command "savedefault".  */
 
825
      current_entryno = first_entry + entryno;
 
826
      
 
827
      if (run_script (cur_entry, heap))
 
828
        {
 
829
          if (fallback_entry < 0)
 
830
            break;
 
831
          else
 
832
            {
 
833
              cur_entry = NULL;
 
834
              first_entry = 0;
 
835
              entryno = fallback_entry;
 
836
              fallback_entry = -1;
 
837
            }
 
838
        }
 
839
      else
 
840
        break;
 
841
    }
 
842
 
 
843
  show_menu = 1;
 
844
  goto restart;
 
845
}
 
846
 
 
847
 
 
848
static int
 
849
get_line_from_config (char *cmdline, int maxlen, int read_from_file)
 
850
{
 
851
  int pos = 0, literal = 0, comment = 0;
 
852
  char c;  /* since we're loading it a byte at a time! */
 
853
  
 
854
  while (1)
 
855
    {
 
856
      if (read_from_file)
 
857
        {
 
858
          if (! grub_read (&c, 1))
 
859
            break;
 
860
        }
 
861
      else
 
862
        {
 
863
          if (! read_from_preset_menu (&c, 1))
 
864
            break;
 
865
        }
 
866
      
 
867
      /* translate characters first! */
 
868
      if (c == '\\' && ! literal)
 
869
        {
 
870
          literal = 1;
 
871
          continue;
 
872
        }
 
873
      if (c == '\r')
 
874
        continue;
 
875
      if ((c == '\t') || (literal && (c == '\n')))
 
876
        c = ' ';
 
877
 
 
878
      literal = 0;
 
879
 
 
880
      if (comment)
 
881
        {
 
882
          if (c == '\n')
 
883
            comment = 0;
 
884
        }
 
885
      else if (! pos)
 
886
        {
 
887
          if (c == '#')
 
888
            comment = 1;
 
889
          else if ((c != ' ') && (c != '\n'))
 
890
            cmdline[pos++] = c;
 
891
        }
 
892
      else
 
893
        {
 
894
          if (c == '\n')
 
895
            break;
 
896
 
 
897
          if (pos < maxlen)
 
898
            cmdline[pos++] = c;
 
899
        }
 
900
    }
 
901
 
 
902
  cmdline[pos] = 0;
 
903
 
 
904
  return pos;
 
905
}
 
906
 
 
907
 
 
908
/* This is the starting function in C.  */
 
909
void
 
910
cmain (void)
 
911
{
 
912
  int config_len, menu_len, num_entries;
 
913
  char *config_entries, *menu_entries;
 
914
  char *kill_buf = (char *) KILL_BUF;
 
915
 
 
916
  auto void reset (void);
 
917
  void reset (void)
 
918
    {
 
919
      auto_fill = 1;
 
920
      config_len = 0;
 
921
      menu_len = 0;
 
922
      num_entries = 0;
 
923
      config_entries = (char *) mbi.drives_addr + mbi.drives_length;
 
924
      menu_entries = (char *) MENU_BUF;
 
925
      init_config ();
 
926
    }
 
927
      
 
928
  /* Initialize the environment for restarting Stage 2.  */
 
929
  grub_setjmp (restart_env);
 
930
  
 
931
  /* Initialize the kill buffer.  */
 
932
  *kill_buf = 0;
 
933
 
 
934
  /* Never return.  */
 
935
  for (;;)
 
936
    {
 
937
      int is_opened, is_preset;
 
938
 
 
939
      reset ();
 
940
      
 
941
      /* Here load the configuration file.  */
 
942
      
 
943
#ifdef GRUB_UTIL
 
944
      if (use_config_file)
 
945
#endif /* GRUB_UTIL */
 
946
        {
 
947
          do
 
948
            {
 
949
              /* STATE 0:  Before any title command.
 
950
                 STATE 1:  In a title command.
 
951
                 STATE >1: In a entry after a title command.  */
 
952
              int state = 0, prev_config_len = 0, prev_menu_len = 0;
 
953
              char *cmdline;
 
954
 
 
955
              /* Try the preset menu first. This will succeed at most once,
 
956
                 because close_preset_menu disables the preset menu.  */
 
957
              is_opened = is_preset = open_preset_menu ();
 
958
              if (! is_opened)
 
959
                {
 
960
                  is_opened = grub_open (config_file);
 
961
                  errnum = ERR_NONE;
 
962
                }
 
963
 
 
964
              if (! is_opened)
 
965
                break;
 
966
 
 
967
              /* This is necessary, because the menu must be overrided.  */
 
968
              reset ();
 
969
              
 
970
              cmdline = (char *) CMDLINE_BUF;
 
971
              while (get_line_from_config (cmdline, NEW_HEAPSIZE,
 
972
                                           ! is_preset))
 
973
                {
 
974
                  struct builtin *builtin;
 
975
                  
 
976
                  /* Get the pointer to the builtin structure.  */
 
977
                  builtin = find_command (cmdline);
 
978
                  errnum = 0;
 
979
                  if (! builtin)
 
980
                    /* Unknown command. Just skip now.  */
 
981
                    continue;
 
982
                  
 
983
                  if (builtin->flags & BUILTIN_TITLE)
 
984
                    {
 
985
                      char *ptr;
 
986
                      
 
987
                      /* the command "title" is specially treated.  */
 
988
                      if (state > 1)
 
989
                        {
 
990
                          /* The next title is found.  */
 
991
                          num_entries++;
 
992
                          config_entries[config_len++] = 0;
 
993
                          prev_menu_len = menu_len;
 
994
                          prev_config_len = config_len;
 
995
                        }
 
996
                      else
 
997
                        {
 
998
                          /* The first title is found.  */
 
999
                          menu_len = prev_menu_len;
 
1000
                          config_len = prev_config_len;
 
1001
                        }
 
1002
                      
 
1003
                      /* Reset the state.  */
 
1004
                      state = 1;
 
1005
                      
 
1006
                      /* Copy title into menu area.  */
 
1007
                      ptr = skip_to (1, cmdline);
 
1008
                      while ((menu_entries[menu_len++] = *(ptr++)) != 0)
 
1009
                        ;
 
1010
                    }
 
1011
                  else if (! state)
 
1012
                    {
 
1013
                      /* Run a command found is possible.  */
 
1014
                      if (builtin->flags & BUILTIN_MENU)
 
1015
                        {
 
1016
                          char *arg = skip_to (1, cmdline);
 
1017
                          (builtin->func) (arg, BUILTIN_MENU);
 
1018
                          errnum = 0;
 
1019
                        }
 
1020
                      else
 
1021
                        /* Ignored.  */
 
1022
                        continue;
 
1023
                    }
 
1024
                  else
 
1025
                    {
 
1026
                      char *ptr = cmdline;
 
1027
                      
 
1028
                      state++;
 
1029
                      /* Copy config file data to config area.  */
 
1030
                      while ((config_entries[config_len++] = *ptr++) != 0)
 
1031
                        ;
 
1032
                    }
 
1033
                }
 
1034
              
 
1035
              if (state > 1)
 
1036
                {
 
1037
                  /* Finish the last entry.  */
 
1038
                  num_entries++;
 
1039
                  config_entries[config_len++] = 0;
 
1040
                }
 
1041
              else
 
1042
                {
 
1043
                  menu_len = prev_menu_len;
 
1044
                  config_len = prev_config_len;
 
1045
                }
 
1046
              
 
1047
              menu_entries[menu_len++] = 0;
 
1048
              config_entries[config_len++] = 0;
 
1049
              grub_memmove (config_entries + config_len, menu_entries,
 
1050
                            menu_len);
 
1051
              menu_entries = config_entries + config_len;
 
1052
              
 
1053
              /* Check if the default entry is present. Otherwise reset
 
1054
                 it to fallback if fallback is valid, or to DEFAULT_ENTRY 
 
1055
                 if not.  */
 
1056
              if (default_entry >= num_entries)
 
1057
                {
 
1058
                  if (fallback_entry < 0 || fallback_entry >= num_entries)
 
1059
                    default_entry = 0;
 
1060
                  else
 
1061
                    default_entry = fallback_entry;
 
1062
                }
 
1063
              
 
1064
              if (is_preset)
 
1065
                close_preset_menu ();
 
1066
              else
 
1067
                grub_close ();
 
1068
            }
 
1069
          while (is_preset);
 
1070
        }
 
1071
 
 
1072
      if (! num_entries)
 
1073
        {
 
1074
          /* If no acceptable config file, goto command-line, starting
 
1075
             heap from where the config entries would have been stored
 
1076
             if there were any.  */
 
1077
          enter_cmdline (config_entries, 1);
 
1078
        }
 
1079
      else
 
1080
        {
 
1081
          /* Run menu interface.  */
 
1082
          run_menu (menu_entries, config_entries, num_entries,
 
1083
                    menu_entries + menu_len, default_entry);
 
1084
        }
 
1085
    }
 
1086
}