~darkmuggle-deactivatedaccount/ubuntu/quantal/grub2/fix-872244

« back to all changes in this revision

Viewing changes to grub-core/script/lexer.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* lexer.c - The scripting lexer.  */
 
2
/*
 
3
 *  GRUB  --  GRand Unified Bootloader
 
4
 *  Copyright (C) 2005,2006,2007,2008,2009,2010  Free Software Foundation, Inc.
 
5
 *
 
6
 *  GRUB 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 3 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  GRUB 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.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
#include <config.h>
 
21
 
 
22
#include <grub/parser.h>
 
23
#include <grub/misc.h>
 
24
#include <grub/mm.h>
 
25
#include <grub/script_sh.h>
 
26
 
 
27
#include "grub_script.tab.h"
 
28
#include "grub_script.yy.h"
 
29
 
 
30
void
 
31
grub_script_lexer_ref (struct grub_lexer_param *state)
 
32
{
 
33
  state->refs++;
 
34
}
 
35
 
 
36
void
 
37
grub_script_lexer_deref (struct grub_lexer_param *state)
 
38
{
 
39
  state->refs--;
 
40
}
 
41
 
 
42
/* Start recording all characters passing through the lexer.  */
 
43
unsigned
 
44
grub_script_lexer_record_start (struct grub_parser_param *parser)
 
45
{
 
46
  struct grub_lexer_param *lexer = parser->lexerstate;
 
47
 
 
48
  lexer->record++;
 
49
  if (lexer->recording)
 
50
    return lexer->recordpos;
 
51
 
 
52
  lexer->recordpos = 0;
 
53
  lexer->recordlen = GRUB_LEXER_INITIAL_RECORD_SIZE;
 
54
  lexer->recording = grub_malloc (lexer->recordlen);
 
55
  if (!lexer->recording)
 
56
    {
 
57
      grub_script_yyerror (parser, 0);
 
58
      lexer->recordlen = 0;
 
59
    }
 
60
  return lexer->recordpos;
 
61
}
 
62
 
 
63
char *
 
64
grub_script_lexer_record_stop (struct grub_parser_param *parser, unsigned offset)
 
65
{
 
66
  int count;
 
67
  char *result;
 
68
  struct grub_lexer_param *lexer = parser->lexerstate;
 
69
 
 
70
  if (!lexer->record)
 
71
    return 0;
 
72
 
 
73
  lexer->record--;
 
74
  if (!lexer->recording)
 
75
    return 0;
 
76
 
 
77
  count = lexer->recordpos - offset;
 
78
  result = grub_script_malloc (parser, count + 1);
 
79
  if (result) {
 
80
    grub_strncpy (result, lexer->recording + offset, count);
 
81
    result[count] = '\0';
 
82
  }
 
83
 
 
84
  if (lexer->record == 0)
 
85
    {
 
86
      grub_free (lexer->recording);
 
87
      lexer->recording = 0;
 
88
      lexer->recordlen = 0;
 
89
      lexer->recordpos = 0;
 
90
    }
 
91
  return result;
 
92
}
 
93
 
 
94
/* Record STR if input recording is enabled.  */
 
95
void
 
96
grub_script_lexer_record (struct grub_parser_param *parser, char *str)
 
97
{
 
98
  int len;
 
99
  char *old;
 
100
  struct grub_lexer_param *lexer = parser->lexerstate;
 
101
 
 
102
  if (!lexer->record || !lexer->recording)
 
103
    return;
 
104
 
 
105
  len = grub_strlen (str);
 
106
  if (lexer->recordpos + len + 1 > lexer->recordlen)
 
107
    {
 
108
      old = lexer->recording;
 
109
      lexer->recordlen = grub_max (len, lexer->recordlen) * 2;
 
110
      lexer->recording = grub_realloc (lexer->recording, lexer->recordlen);
 
111
      if (!lexer->recording)
 
112
        {
 
113
          grub_free (old);
 
114
          lexer->recordpos = 0;
 
115
          lexer->recordlen = 0;
 
116
          grub_script_yyerror (parser, 0);
 
117
          return;
 
118
        }
 
119
    }
 
120
  grub_strcpy (lexer->recording + lexer->recordpos, str);
 
121
  lexer->recordpos += len;
 
122
}
 
123
 
 
124
/* Read next line of input if necessary, and set yyscanner buffers.  */
 
125
int
 
126
grub_script_lexer_yywrap (struct grub_parser_param *parserstate,
 
127
                          const char *input)
 
128
{
 
129
  int len;
 
130
  char *p = 0;
 
131
  char *line = 0;
 
132
  YY_BUFFER_STATE buffer;
 
133
  struct grub_lexer_param *lexerstate = parserstate->lexerstate;
 
134
 
 
135
  if (! lexerstate->refs && ! lexerstate->prefix && ! input)
 
136
    return 1;
 
137
 
 
138
  if (! lexerstate->getline && ! input)
 
139
    {
 
140
      grub_script_yyerror (parserstate, "unexpected end of file");
 
141
      return 1;
 
142
    }
 
143
 
 
144
  line = 0;
 
145
  if (! input)
 
146
    lexerstate->getline (&line, 1);
 
147
  else
 
148
    line = grub_strdup (input);
 
149
 
 
150
  /* Ensure '\n' at the end.  */
 
151
  if (line && line[0] == '\0')
 
152
    {
 
153
      grub_free (line);
 
154
      line = grub_strdup ("\n");
 
155
    }
 
156
 
 
157
  if (line && (len = grub_strlen(line)) && line[len - 1] != '\n')
 
158
    {
 
159
      p = grub_realloc (line, len + 2);
 
160
      if (p)
 
161
        {
 
162
          p[len++] = '\n';
 
163
          p[len] = '\0';
 
164
        }
 
165
      line = p;
 
166
    }
 
167
 
 
168
  if (! line)
 
169
    {
 
170
      grub_script_yyerror (parserstate, "out of memory");
 
171
      return 1;
 
172
    }
 
173
 
 
174
  /* Prepend any left over unput-text.  */
 
175
  if (lexerstate->prefix)
 
176
    {
 
177
      int plen = grub_strlen (lexerstate->prefix);
 
178
 
 
179
      p = grub_malloc (len + plen + 1);
 
180
      if (! p)
 
181
        {
 
182
          grub_free (line);
 
183
          return 1;
 
184
        }
 
185
      grub_strcpy (p, lexerstate->prefix);
 
186
      lexerstate->prefix = 0;
 
187
 
 
188
      grub_strcpy (p + plen, line);
 
189
      grub_free (line);
 
190
 
 
191
      line = p;
 
192
      len = len + plen;
 
193
    }
 
194
 
 
195
  buffer = yy_scan_string (line, lexerstate->yyscanner);
 
196
  grub_free (line);
 
197
 
 
198
  if (! buffer)
 
199
    {
 
200
      grub_script_yyerror (parserstate, 0);
 
201
      return 1;
 
202
    }
 
203
  return 0;
 
204
}
 
205
 
 
206
struct grub_lexer_param *
 
207
grub_script_lexer_init (struct grub_parser_param *parser, char *script,
 
208
                        grub_reader_getline_t getline)
 
209
{
 
210
  struct grub_lexer_param *lexerstate;
 
211
 
 
212
  lexerstate = grub_zalloc (sizeof (*lexerstate));
 
213
  if (!lexerstate)
 
214
    return 0;
 
215
 
 
216
  lexerstate->size = GRUB_LEXER_INITIAL_TEXT_SIZE;
 
217
  lexerstate->text = grub_malloc (lexerstate->size);
 
218
  if (!lexerstate->text)
 
219
    {
 
220
      grub_free (lexerstate);
 
221
      return 0;
 
222
    }
 
223
 
 
224
  lexerstate->getline = getline;        /* rest are all zeros already */
 
225
  if (yylex_init (&lexerstate->yyscanner))
 
226
    {
 
227
      grub_free (lexerstate->text);
 
228
      grub_free (lexerstate);
 
229
      return 0;
 
230
    }
 
231
 
 
232
  yyset_extra (parser, lexerstate->yyscanner);
 
233
  parser->lexerstate = lexerstate;
 
234
 
 
235
  if (grub_script_lexer_yywrap (parser, script ?: "\n"))
 
236
    {
 
237
      parser->lexerstate = 0;
 
238
      yylex_destroy (lexerstate->yyscanner);
 
239
      grub_free (lexerstate->yyscanner);
 
240
      grub_free (lexerstate->text);
 
241
      grub_free (lexerstate);
 
242
      return 0;
 
243
    }
 
244
 
 
245
  return lexerstate;
 
246
}
 
247
 
 
248
void
 
249
grub_script_lexer_fini (struct grub_lexer_param *lexerstate)
 
250
{
 
251
  if (!lexerstate)
 
252
    return;
 
253
 
 
254
  yylex_destroy (lexerstate->yyscanner);
 
255
 
 
256
  grub_free (lexerstate->recording);
 
257
  grub_free (lexerstate->text);
 
258
  grub_free (lexerstate);
 
259
}
 
260
 
 
261
int
 
262
grub_script_yylex (union YYSTYPE *value,
 
263
                   struct grub_parser_param *parserstate)
 
264
{
 
265
  char *str;
 
266
  int token;
 
267
  grub_script_arg_type_t type;
 
268
  struct grub_lexer_param *lexerstate = parserstate->lexerstate;
 
269
 
 
270
  value->arg = 0;
 
271
  if (parserstate->err)
 
272
    return GRUB_PARSER_TOKEN_BAD;
 
273
 
 
274
  if (lexerstate->eof)
 
275
    return GRUB_PARSER_TOKEN_EOF;
 
276
 
 
277
  /* 
 
278
   * Words with environment variables, like foo${bar}baz needs
 
279
   * multiple tokens to be merged into a single grub_script_arg.  We
 
280
   * use two variables to achieve this: lexerstate->merge_start and
 
281
   * lexerstate->merge_end
 
282
   */
 
283
 
 
284
  lexerstate->merge_start = 0;
 
285
  lexerstate->merge_end = 0;
 
286
  do
 
287
    {
 
288
      /* Empty lexerstate->text.  */
 
289
      lexerstate->used = 1;
 
290
      lexerstate->text[0] = '\0';
 
291
 
 
292
      token = yylex (value, lexerstate->yyscanner);
 
293
      if (token == GRUB_PARSER_TOKEN_BAD)
 
294
        break;
 
295
 
 
296
      /* Merging feature uses lexerstate->text instead of yytext.  */
 
297
      if (lexerstate->merge_start)
 
298
        {
 
299
          str = lexerstate->text;
 
300
          type = lexerstate->type;
 
301
        }
 
302
      else
 
303
        {
 
304
          str = yyget_text (lexerstate->yyscanner);
 
305
          type = GRUB_SCRIPT_ARG_TYPE_TEXT;
 
306
        }
 
307
      grub_dprintf("lexer", "token %u text [%s]\n", token, str);
 
308
 
 
309
      value->arg = grub_script_arg_add (parserstate, value->arg, type, str);
 
310
    }
 
311
  while (lexerstate->merge_start && !lexerstate->merge_end);
 
312
 
 
313
  if (!value->arg || parserstate->err)
 
314
    return GRUB_PARSER_TOKEN_BAD;
 
315
 
 
316
  return token;
 
317
}
 
318
 
 
319
void
 
320
grub_script_yyerror (struct grub_parser_param *state, char const *err)
 
321
{
 
322
  if (err)
 
323
    grub_error (GRUB_ERR_INVALID_COMMAND, err);
 
324
 
 
325
  grub_print_error ();
 
326
  state->err++;
 
327
}