Merge branch 'master' of git://github.com/illumos/illumos-gate
[unleashed.git] / usr / src / grub / grub-0.97 / stage2 / cmdline.c
blob46c5fda027ae31744c92a42f7b7f41e1754d60f1
1 /* cmdline.c - the device-independent GRUB text command line */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 1999,2000,2001,2002,2004 Free Software Foundation, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <shared.h>
22 #include <term.h>
24 extern struct term_entry *current_term;
26 #ifdef SUPPORT_DISKLESS
27 # include <grub.h>
28 #endif
30 grub_jmp_buf restart_cmdline_env;
32 /* Find the next word from CMDLINE and return the pointer. If
33 AFTER_EQUAL is non-zero, assume that the character `=' is treated as
34 a space. Caution: this assumption is for backward compatibility. */
35 char *
36 skip_to (int after_equal, char *cmdline)
38 /* Skip until we hit whitespace, or maybe an equal sign. */
39 while (*cmdline && *cmdline != ' ' && *cmdline != '\t' &&
40 ! (after_equal && *cmdline == '='))
41 cmdline ++;
43 /* Skip whitespace, and maybe equal signs. */
44 while (*cmdline == ' ' || *cmdline == '\t' ||
45 (after_equal && *cmdline == '='))
46 cmdline ++;
48 return cmdline;
51 /* Print a helpful message for the command-line interface. */
52 void
53 print_cmdline_message (int forever)
55 printf (" [ Minimal BASH-like line editing is supported. For the first word, TAB\n"
56 " lists possible command completions. Anywhere else TAB lists the possible\n"
57 " completions of a device/filename.%s ]\n",
58 (forever ? "" : " ESC at any time exits."));
61 /* Find the builtin whose command name is COMMAND and return the
62 pointer. If not found, return 0. */
63 struct builtin *
64 find_command (char *command)
66 char *ptr;
67 char c;
68 struct builtin **builtin;
70 /* Find the first space and terminate the command name. */
71 ptr = command;
72 while (*ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '=')
73 ptr ++;
75 c = *ptr;
76 *ptr = 0;
78 /* Seek out the builtin whose command name is COMMAND. */
79 for (builtin = builtin_table; *builtin != 0; builtin++)
81 int ret = grub_strcmp (command, (*builtin)->name);
83 if (ret == 0)
85 /* Find the builtin for COMMAND. */
86 *ptr = c;
87 return *builtin;
89 else if (ret < 0)
90 break;
93 /* Cannot find COMMAND. */
94 errnum = ERR_UNRECOGNIZED;
95 *ptr = c;
96 return 0;
99 /* Initialize the data for the command-line. */
100 static void
101 init_cmdline (void)
103 /* Initialization. */
104 saved_drive = boot_drive;
105 saved_partition = install_partition;
106 current_drive = GRUB_INVALID_DRIVE;
107 errnum = 0;
108 count_lines = -1;
110 /* Restore memory probe state. */
111 mbi.mem_upper = saved_mem_upper;
112 if (mbi.mmap_length)
113 mbi.flags |= MB_INFO_MEM_MAP;
115 /* Initialize the data for the builtin commands. */
116 init_builtins ();
119 /* Enter the command-line interface. HEAP is used for the command-line
120 buffer. Return only if FOREVER is nonzero and get_cmdline returns
121 nonzero (ESC is pushed). */
122 void
123 enter_cmdline (char *heap, int forever)
125 /* Initialize the data and print a message. */
126 init_cmdline ();
127 grub_setjmp (restart_cmdline_env);
128 init_page ();
129 #ifdef SUPPORT_DISKLESS
130 print_network_configuration ();
131 grub_putchar ('\n');
132 #endif
133 print_cmdline_message (forever);
135 while (1)
137 struct builtin *builtin;
138 char *arg;
140 *heap = 0;
141 print_error ();
142 errnum = ERR_NONE;
144 /* Get the command-line with the minimal BASH-like interface. */
145 if (get_cmdline (PACKAGE "> ", heap, 2048, 0, 1))
146 return;
148 /* If there was no command, grab a new one. */
149 if (! heap[0])
150 continue;
152 /* Find a builtin. */
153 builtin = find_command (heap);
154 if (! builtin)
155 continue;
157 /* If BUILTIN cannot be run in the command-line, skip it. */
158 if (! (builtin->flags & BUILTIN_CMDLINE))
160 errnum = ERR_UNRECOGNIZED;
161 continue;
164 /* Invalidate the cache, because the user may exchange removable
165 disks. */
166 buf_drive = -1;
168 /* Start to count lines, only if the internal pager is in use. */
169 if (use_pager)
170 count_lines = 0;
172 /* Run BUILTIN->FUNC. */
173 arg = skip_to (1, heap);
174 (builtin->func) (arg, BUILTIN_CMDLINE);
176 /* Finish the line count. */
177 count_lines = -1;
181 /* Run an entry from the script SCRIPT. HEAP is used for the
182 command-line buffer. If an error occurs, return non-zero, otherwise
183 return zero. */
185 run_script (char *script, char *heap)
187 char *old_entry;
188 char *cur_entry = script;
190 /* Initialize the data. */
191 init_cmdline ();
193 while (1)
195 struct builtin *builtin;
196 char *arg;
198 print_error ();
200 if (errnum)
202 errnum = ERR_NONE;
205 * At this point something must have gone wrong, so dump the
206 * buffer and flip output back on.
208 builtin = find_command("verbose");
209 (builtin->func) ("on", BUILTIN_SCRIPT);
211 /* If a fallback entry is defined, don't prompt a user's
212 intervention. */
213 if (fallback_entryno < 0)
215 grub_printf ("\nPress any key to continue...");
216 (void) getkey ();
219 return 1;
222 /* Copy the first string in CUR_ENTRY to HEAP. */
223 old_entry = cur_entry;
224 while (*cur_entry++)
227 grub_memmove (heap, old_entry, (int) cur_entry - (int) old_entry);
228 if (! *heap)
230 /* If there is no more command in SCRIPT... */
232 /* If any kernel is not loaded, just exit successfully. */
233 if (kernel_type == KERNEL_TYPE_NONE)
234 return 0;
236 if (reset_term)
237 if (current_term->shutdown) {
238 (*current_term->shutdown)();
239 current_term = term_table; /* assumption: console is first */
243 /* Otherwise, the command boot is run implicitly. */
244 grub_memmove (heap, "boot", 5);
247 /* Find a builtin. */
248 builtin = find_command (heap);
249 if (! builtin)
251 grub_printf ("%s\n", old_entry);
252 continue;
255 if (! (builtin->flags & BUILTIN_NO_ECHO))
256 grub_printf ("%s\n", old_entry);
258 /* If BUILTIN cannot be run in the command-line, skip it. */
259 if (! (builtin->flags & BUILTIN_CMDLINE))
261 errnum = ERR_UNRECOGNIZED;
262 continue;
265 /* Invalidate the cache, because the user may exchange removable
266 disks. */
267 buf_drive = -1;
269 /* Run BUILTIN->FUNC. */
270 arg = skip_to (1, heap);
271 (builtin->func) (arg, BUILTIN_SCRIPT);