~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

Viewing changes to grub-core/normal/cmdline.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Robert Millan, Updated translations
  • Date: 2010-11-22 12:24:56 UTC
  • mfrom: (1.26.4 upstream) (17.3.36 sid)
  • mto: (17.3.43 sid)
  • mto: This revision was merged to the branch mainline in revision 89.
  • Revision ID: james.westby@ubuntu.com-20101122122456-y82z3sfb7k4zfdcc
Tags: 1.99~20101122-1
[ Colin Watson ]
* New Bazaar snapshot.  Too many changes to list in full, but some of the
  more user-visible ones are as follows:
  - GRUB script:
    + Function parameters, "break", "continue", "shift", "setparams",
      "return", and "!".
    + "export" command supports multiple variable names.
    + Multi-line quoted strings support.
    + Wildcard expansion.
  - sendkey support.
  - USB hotunplugging and USB serial support.
  - Rename CD-ROM to cd on BIOS.
  - Add new --boot-directory option to grub-install, grub-reboot, and
    grub-set-default; the old --root-directory option is still accepted
    but was often confusing.
  - Basic btrfs detection/UUID support (but no file reading yet).
  - bash-completion for utilities.
  - If a device is listed in device.map, always assume that it is
    BIOS-visible rather than using extra layers such as LVM or RAID.
  - Add grub-mknetdir script (closes: #550658).
  - Remove deprecated "root" command.
  - Handle RAID devices containing virtio components.
  - GRUB Legacy configuration file support (via grub-menulst2cfg).
  - Keyboard layout support (via grub-mklayout and grub-kbdcomp).
  - Check generated grub.cfg for syntax errors before saving.
  - Pause execution for at most ten seconds if any errors are displayed,
    so that the user has a chance to see them.
  - Support submenus.
  - Write embedding zone using Reed-Solomon, so that it's robust against
    being partially overwritten (closes: #550702, #591416, #593347).
  - GRUB_DISABLE_LINUX_RECOVERY and GRUB_DISABLE_NETBSD_RECOVERY merged
    into a single GRUB_DISABLE_RECOVERY variable.
  - Fix loader memory allocation failure (closes: #551627).
  - Don't call savedefault on recovery entries (closes: #589325).
  - Support triple-indirect blocks on ext2 (closes: #543924).
  - Recognise DDF1 fake RAID (closes: #603354).

[ Robert Millan ]
* Use dpkg architecture wildcards.

[ Updated translations ]
* Slovenian (Vanja Cvelbar).  Closes: #604003
* Dzongkha (dawa pemo via Tenzin Dendup).  Closes: #604102

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  GRUB  --  GRand Unified Bootloader
 
3
 *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2009  Free Software Foundation, Inc.
 
4
 *
 
5
 *  GRUB 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 3 of the License, or
 
8
 *  (at your option) any later version.
 
9
 *
 
10
 *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
 
17
 */
 
18
 
 
19
#include <grub/normal.h>
 
20
#include <grub/misc.h>
 
21
#include <grub/term.h>
 
22
#include <grub/err.h>
 
23
#include <grub/types.h>
 
24
#include <grub/mm.h>
 
25
#include <grub/partition.h>
 
26
#include <grub/disk.h>
 
27
#include <grub/file.h>
 
28
#include <grub/env.h>
 
29
#include <grub/i18n.h>
 
30
#include <grub/charset.h>
 
31
 
 
32
static grub_uint32_t *kill_buf;
 
33
 
 
34
static int hist_size;
 
35
static grub_uint32_t **hist_lines = 0;
 
36
static int hist_pos = 0;
 
37
static int hist_end = 0;
 
38
static int hist_used = 0;
 
39
 
 
40
grub_err_t
 
41
grub_set_history (int newsize)
 
42
{
 
43
  grub_uint32_t **old_hist_lines = hist_lines;
 
44
  hist_lines = grub_malloc (sizeof (grub_uint32_t *) * newsize);
 
45
 
 
46
  /* Copy the old lines into the new buffer.  */
 
47
  if (old_hist_lines)
 
48
    {
 
49
      /* Remove the lines that don't fit in the new buffer.  */
 
50
      if (newsize < hist_used)
 
51
        {
 
52
          int i;
 
53
          int delsize = hist_used - newsize;
 
54
          hist_used = newsize;
 
55
 
 
56
          for (i = 1; i <= delsize; i++)
 
57
            {
 
58
              int pos = hist_end - i;
 
59
              if (pos < 0)
 
60
                pos += hist_size;
 
61
              grub_free (old_hist_lines[pos]);
 
62
            }
 
63
 
 
64
          hist_end -= delsize;
 
65
          if (hist_end < 0)
 
66
            hist_end += hist_size;
 
67
        }
 
68
 
 
69
      if (hist_pos < hist_end)
 
70
        grub_memmove (hist_lines, old_hist_lines + hist_pos,
 
71
                      (hist_end - hist_pos) * sizeof (grub_uint32_t *));
 
72
      else if (hist_used)
 
73
        {
 
74
          /* Copy the older part.  */
 
75
          grub_memmove (hist_lines, old_hist_lines + hist_pos,
 
76
                        (hist_size - hist_pos) * sizeof (grub_uint32_t *));
 
77
 
 
78
          /* Copy the newer part. */
 
79
          grub_memmove (hist_lines + hist_size - hist_pos, old_hist_lines,
 
80
                        hist_end * sizeof (grub_uint32_t *));
 
81
        }
 
82
    }
 
83
 
 
84
  grub_free (old_hist_lines);
 
85
 
 
86
  hist_size = newsize;
 
87
  hist_pos = 0;
 
88
  hist_end = hist_used;
 
89
  return 0;
 
90
}
 
91
 
 
92
/* Get the entry POS from the history where `0' is the newest
 
93
   entry.  */
 
94
static grub_uint32_t *
 
95
grub_history_get (int pos)
 
96
{
 
97
  pos = (hist_pos + pos) % hist_size;
 
98
  return hist_lines[pos];
 
99
}
 
100
 
 
101
static grub_size_t
 
102
strlen_ucs4 (const grub_uint32_t *s)
 
103
{
 
104
  const grub_uint32_t *p = s;
 
105
 
 
106
  while (*p)
 
107
    p++;
 
108
 
 
109
  return p - s;
 
110
}
 
111
 
 
112
/* Replace the history entry on position POS with the string S.  */
 
113
static void
 
114
grub_history_set (int pos, grub_uint32_t *s, grub_size_t len)
 
115
{
 
116
  grub_free (hist_lines[pos]);
 
117
  hist_lines[pos] = grub_malloc ((len + 1) * sizeof (grub_uint32_t));
 
118
  if (!hist_lines[pos])
 
119
    {
 
120
      grub_print_error ();
 
121
      grub_errno = GRUB_ERR_NONE;
 
122
      return ;
 
123
    }
 
124
  grub_memcpy (hist_lines[pos], s, len * sizeof (grub_uint32_t));
 
125
  hist_lines[pos][len] = 0;
 
126
}
 
127
 
 
128
/* Insert a new history line S on the top of the history.  */
 
129
static void
 
130
grub_history_add (grub_uint32_t *s, grub_size_t len)
 
131
{
 
132
  /* Remove the oldest entry in the history to make room for a new
 
133
     entry.  */
 
134
  if (hist_used + 1 > hist_size)
 
135
    {
 
136
      hist_end--;
 
137
      if (hist_end < 0)
 
138
        hist_end = hist_size + hist_end;
 
139
 
 
140
      grub_free (hist_lines[hist_end]);
 
141
    }
 
142
  else
 
143
    hist_used++;
 
144
 
 
145
  /* Move to the next position.  */
 
146
  hist_pos--;
 
147
  if (hist_pos < 0)
 
148
    hist_pos = hist_size + hist_pos;
 
149
 
 
150
  /* Insert into history.  */
 
151
  hist_lines[hist_pos] = NULL;
 
152
  grub_history_set (hist_pos, s, len);
 
153
}
 
154
 
 
155
/* Replace the history entry on position POS with the string S.  */
 
156
static void
 
157
grub_history_replace (int pos, grub_uint32_t *s, grub_size_t len)
 
158
{
 
159
  grub_history_set ((hist_pos + pos) % hist_size, s, len);
 
160
}
 
161
 
 
162
/* A completion hook to print items.  */
 
163
static void
 
164
print_completion (const char *item, grub_completion_type_t type, int count)
 
165
{
 
166
  if (count == 0)
 
167
    {
 
168
      /* If this is the first time, print a label.  */
 
169
      
 
170
      grub_puts ("");
 
171
      switch (type)
 
172
        {
 
173
        case GRUB_COMPLETION_TYPE_COMMAND:
 
174
          grub_puts_ (N_("Possible commands are:"));
 
175
          break;
 
176
        case GRUB_COMPLETION_TYPE_DEVICE:
 
177
          grub_puts_ (N_("Possible devices are:"));
 
178
          break;
 
179
        case GRUB_COMPLETION_TYPE_FILE:
 
180
          grub_puts_ (N_("Possible files are:"));
 
181
          break;
 
182
        case GRUB_COMPLETION_TYPE_PARTITION:
 
183
          grub_puts_ (N_("Possible partitions are:"));
 
184
          break;
 
185
        case GRUB_COMPLETION_TYPE_ARGUMENT:
 
186
          grub_puts_ (N_("Possible arguments are:"));
 
187
          break;
 
188
        default:
 
189
          grub_puts_ (N_("Possible things are:"));
 
190
          break;
 
191
        }
 
192
      grub_puts ("");
 
193
    }
 
194
 
 
195
  if (type == GRUB_COMPLETION_TYPE_PARTITION)
 
196
    {
 
197
      grub_normal_print_device_info (item);
 
198
      grub_errno = GRUB_ERR_NONE;
 
199
    }
 
200
  else
 
201
    grub_printf (" %s", item);
 
202
}
 
203
 
 
204
struct cmdline_term
 
205
{
 
206
  unsigned xpos, ypos, ystart, width, height;
 
207
  struct grub_term_output *term;
 
208
};
 
209
 
 
210
/* Get a command-line. If ESC is pushed, return zero,
 
211
   otherwise return command line.  */
 
212
/* FIXME: The dumb interface is not supported yet.  */
 
213
char *
 
214
grub_cmdline_get (const char *prompt)
 
215
{
 
216
  grub_size_t lpos, llen;
 
217
  grub_size_t plen;
 
218
  grub_uint32_t *buf;
 
219
  grub_size_t max_len = 256;
 
220
  int key;
 
221
  int histpos = 0;
 
222
  auto void cl_insert (const grub_uint32_t *str);
 
223
  auto void cl_delete (unsigned len);
 
224
  auto inline void __attribute__ ((always_inline)) cl_print (struct cmdline_term *cl_term, int pos,
 
225
                        grub_uint32_t c);
 
226
  auto void cl_set_pos (struct cmdline_term *cl_term);
 
227
  auto void cl_print_all (int pos, grub_uint32_t c);
 
228
  auto void cl_set_pos_all (void);
 
229
  auto void init_clterm (struct cmdline_term *cl_term_cur);
 
230
  auto void init_clterm_all (void);
 
231
  const char *prompt_translated = _(prompt);
 
232
  struct cmdline_term *cl_terms;
 
233
  char *ret;
 
234
  unsigned nterms;
 
235
 
 
236
  void cl_set_pos (struct cmdline_term *cl_term)
 
237
  {
 
238
    cl_term->xpos = (plen + lpos) % (cl_term->width - 1);
 
239
    cl_term->ypos = cl_term->ystart + (plen + lpos) / (cl_term->width - 1);
 
240
    grub_term_gotoxy (cl_term->term, cl_term->xpos, cl_term->ypos);
 
241
  }
 
242
 
 
243
  void cl_set_pos_all ()
 
244
  {
 
245
    unsigned i;
 
246
    for (i = 0; i < nterms; i++)
 
247
      cl_set_pos (&cl_terms[i]);
 
248
  }
 
249
 
 
250
  inline void __attribute__ ((always_inline)) cl_print (struct cmdline_term *cl_term, int pos, grub_uint32_t c)
 
251
    {
 
252
      grub_uint32_t *p;
 
253
 
 
254
      for (p = buf + pos; p < buf + llen; p++)
 
255
        {
 
256
          if (c)
 
257
            grub_putcode (c, cl_term->term);
 
258
          else
 
259
            grub_putcode (*p, cl_term->term);
 
260
          cl_term->xpos++;
 
261
          if (cl_term->xpos >= cl_term->width - 1)
 
262
            {
 
263
              cl_term->xpos = 0;
 
264
              if (cl_term->ypos >= (unsigned) (cl_term->height - 1))
 
265
                cl_term->ystart--;
 
266
              else
 
267
                cl_term->ypos++;
 
268
              grub_putcode ('\n', cl_term->term);
 
269
            }
 
270
        }
 
271
    }
 
272
 
 
273
  void cl_print_all (int pos, grub_uint32_t c)
 
274
  {
 
275
    unsigned i;
 
276
    for (i = 0; i < nterms; i++)
 
277
      cl_print (&cl_terms[i], pos, c);
 
278
  }
 
279
 
 
280
  void cl_insert (const grub_uint32_t *str)
 
281
    {
 
282
      grub_size_t len = strlen_ucs4 (str);
 
283
 
 
284
      if (len + llen >= max_len)
 
285
        {
 
286
          grub_uint32_t *nbuf;
 
287
          max_len *= 2;
 
288
          nbuf = grub_realloc (buf, sizeof (grub_uint32_t) * max_len);
 
289
          if (nbuf)
 
290
            buf = nbuf;
 
291
          else
 
292
            {
 
293
              grub_print_error ();
 
294
              grub_errno = GRUB_ERR_NONE;
 
295
              max_len /= 2;
 
296
            }
 
297
        }
 
298
 
 
299
      if (len + llen < max_len)
 
300
        {
 
301
          grub_memmove (buf + lpos + len, buf + lpos,
 
302
                        (llen - lpos + 1) * sizeof (grub_uint32_t));
 
303
          grub_memmove (buf + lpos, str, len * sizeof (grub_uint32_t));
 
304
 
 
305
          llen += len;
 
306
          cl_set_pos_all ();
 
307
          cl_print_all (lpos, 0);
 
308
          lpos += len;
 
309
          cl_set_pos_all ();
 
310
        }
 
311
    }
 
312
 
 
313
  void cl_delete (unsigned len)
 
314
    {
 
315
      if (lpos + len <= llen)
 
316
        {
 
317
          grub_size_t saved_lpos = lpos;
 
318
 
 
319
          lpos = llen - len;
 
320
          cl_set_pos_all ();
 
321
          cl_print_all (lpos, ' ');
 
322
          lpos = saved_lpos;
 
323
          cl_set_pos_all ();
 
324
 
 
325
          grub_memmove (buf + lpos, buf + lpos + len,
 
326
                        sizeof (grub_uint32_t) * (llen - lpos + 1));
 
327
          llen -= len;
 
328
          cl_print_all (lpos, 0);
 
329
          cl_set_pos_all ();
 
330
        }
 
331
    }
 
332
 
 
333
  void init_clterm (struct cmdline_term *cl_term_cur)
 
334
  {
 
335
    cl_term_cur->xpos = plen;
 
336
    cl_term_cur->ypos = (grub_term_getxy (cl_term_cur->term) & 0xFF);
 
337
    cl_term_cur->ystart = cl_term_cur->ypos;
 
338
    cl_term_cur->width = grub_term_width (cl_term_cur->term);
 
339
    cl_term_cur->height = grub_term_height (cl_term_cur->term);
 
340
  }
 
341
 
 
342
  void init_clterm_all (void)
 
343
  {
 
344
    unsigned i;
 
345
    for (i = 0; i < nterms; i++)
 
346
      init_clterm (&cl_terms[i]);
 
347
  }
 
348
 
 
349
  buf = grub_malloc (max_len * sizeof (grub_uint32_t));
 
350
  if (!buf)
 
351
    return 0;
 
352
 
 
353
  plen = grub_strlen (prompt_translated) + sizeof (" ") - 1;
 
354
  lpos = llen = 0;
 
355
  buf[0] = '\0';
 
356
 
 
357
  {
 
358
    grub_term_output_t term;
 
359
 
 
360
    FOR_ACTIVE_TERM_OUTPUTS(term)
 
361
      if ((grub_term_getxy (term) >> 8) != 0)
 
362
        grub_putcode ('\n', term);
 
363
  }
 
364
  grub_printf ("%s ", prompt_translated);
 
365
  grub_normal_reset_more ();
 
366
 
 
367
  {
 
368
    struct cmdline_term *cl_term_cur;
 
369
    struct grub_term_output *cur;
 
370
    nterms = 0;
 
371
    FOR_ACTIVE_TERM_OUTPUTS(cur)
 
372
      nterms++;
 
373
 
 
374
    cl_terms = grub_malloc (sizeof (cl_terms[0]) * nterms);
 
375
    if (!cl_terms)
 
376
      return 0;
 
377
    cl_term_cur = cl_terms;
 
378
    FOR_ACTIVE_TERM_OUTPUTS(cur)
 
379
    {
 
380
      cl_term_cur->term = cur;
 
381
      init_clterm (cl_term_cur);
 
382
      cl_term_cur++;
 
383
    }
 
384
  }
 
385
 
 
386
  if (hist_used == 0)
 
387
    grub_history_add (buf, llen);
 
388
 
 
389
  grub_refresh ();
 
390
 
 
391
  while ((key = grub_getkey ()) != '\n' && key != '\r')
 
392
    {
 
393
      switch (key)
 
394
        {
 
395
        case GRUB_TERM_CTRL | 'a':
 
396
        case GRUB_TERM_KEY_HOME:
 
397
          lpos = 0;
 
398
          cl_set_pos_all ();
 
399
          break;
 
400
 
 
401
        case GRUB_TERM_CTRL | 'b':
 
402
        case GRUB_TERM_KEY_LEFT:
 
403
          if (lpos > 0)
 
404
            {
 
405
              lpos--;
 
406
              cl_set_pos_all ();
 
407
            }
 
408
          break;
 
409
 
 
410
        case GRUB_TERM_CTRL | 'e':
 
411
        case GRUB_TERM_KEY_END:
 
412
          lpos = llen;
 
413
          cl_set_pos_all ();
 
414
          break;
 
415
 
 
416
        case GRUB_TERM_CTRL | 'f':
 
417
        case GRUB_TERM_KEY_RIGHT:
 
418
          if (lpos < llen)
 
419
            {
 
420
              lpos++;
 
421
              cl_set_pos_all ();
 
422
            }
 
423
          break;
 
424
 
 
425
        case GRUB_TERM_CTRL | 'i':
 
426
        case '\t':
 
427
          {
 
428
            int restore;
 
429
            char *insertu8;
 
430
            char *bufu8;
 
431
            grub_uint32_t c;
 
432
 
 
433
            c = buf[lpos];
 
434
            buf[lpos] = '\0';
 
435
 
 
436
            bufu8 = grub_ucs4_to_utf8_alloc (buf, lpos);
 
437
            buf[lpos] = c;
 
438
            if (!bufu8)
 
439
              {
 
440
                grub_print_error ();
 
441
                grub_errno = GRUB_ERR_NONE;
 
442
                break;
 
443
              }
 
444
 
 
445
            insertu8 = grub_normal_do_completion (bufu8, &restore,
 
446
                                                  print_completion);
 
447
            grub_free (bufu8);
 
448
 
 
449
            grub_normal_reset_more ();
 
450
 
 
451
            if (restore)
 
452
              {
 
453
                /* Restore the prompt.  */
 
454
                grub_printf ("\n%s ", prompt_translated);
 
455
                init_clterm_all ();
 
456
                cl_print_all (0, 0);
 
457
              }
 
458
 
 
459
            if (insertu8)
 
460
              {
 
461
                grub_size_t insertlen;
 
462
                grub_ssize_t t;
 
463
                grub_uint32_t *insert;
 
464
 
 
465
                insertlen = grub_strlen (insertu8);
 
466
                insert = grub_malloc ((insertlen + 1) * sizeof (grub_uint32_t));
 
467
                if (!insert)
 
468
                  {
 
469
                    grub_free (insertu8);
 
470
                    grub_print_error ();
 
471
                    grub_errno = GRUB_ERR_NONE;
 
472
                    break;
 
473
                  }
 
474
                t = grub_utf8_to_ucs4 (insert, insertlen,
 
475
                                       (grub_uint8_t *) insertu8,
 
476
                                       insertlen, 0);
 
477
                if (t > 0)
 
478
                  {
 
479
                    if (insert[t-1] == ' ' && buf[lpos] == ' ')
 
480
                      {
 
481
                        insert[t-1] = 0;
 
482
                        if (t != 1)
 
483
                          cl_insert (insert);
 
484
                        lpos++;
 
485
                      }
 
486
                    else
 
487
                      {
 
488
                        insert[t] = 0;
 
489
                        cl_insert (insert);
 
490
                      }
 
491
                  }
 
492
 
 
493
                grub_free (insertu8);
 
494
                grub_free (insert);
 
495
              }
 
496
            cl_set_pos_all ();
 
497
          }
 
498
          break;
 
499
 
 
500
        case GRUB_TERM_CTRL | 'k':
 
501
          if (lpos < llen)
 
502
            {
 
503
              if (kill_buf)
 
504
                grub_free (kill_buf);
 
505
 
 
506
              kill_buf = grub_malloc ((llen - lpos + 1)
 
507
                                      * sizeof (grub_uint32_t));
 
508
              if (grub_errno)
 
509
                {
 
510
                  grub_print_error ();
 
511
                  grub_errno = GRUB_ERR_NONE;
 
512
                }
 
513
              else
 
514
                {
 
515
                  grub_memcpy (kill_buf, buf + lpos,
 
516
                               (llen - lpos + 1) * sizeof (grub_uint32_t));
 
517
                  kill_buf[llen - lpos] = 0;
 
518
                }
 
519
 
 
520
              cl_delete (llen - lpos);
 
521
            }
 
522
          break;
 
523
 
 
524
        case GRUB_TERM_CTRL | 'n':
 
525
        case GRUB_TERM_KEY_DOWN:
 
526
          {
 
527
            grub_uint32_t *hist;
 
528
 
 
529
            lpos = 0;
 
530
 
 
531
            if (histpos > 0)
 
532
              {
 
533
                grub_history_replace (histpos, buf, llen);
 
534
                histpos--;
 
535
              }
 
536
 
 
537
            cl_delete (llen);
 
538
            hist = grub_history_get (histpos);
 
539
            cl_insert (hist);
 
540
 
 
541
            break;
 
542
          }
 
543
 
 
544
        case GRUB_TERM_KEY_UP:
 
545
        case GRUB_TERM_CTRL | 'p':
 
546
          {
 
547
            grub_uint32_t *hist;
 
548
 
 
549
            lpos = 0;
 
550
 
 
551
            if (histpos < hist_used - 1)
 
552
              {
 
553
                grub_history_replace (histpos, buf, llen);
 
554
                histpos++;
 
555
              }
 
556
 
 
557
            cl_delete (llen);
 
558
            hist = grub_history_get (histpos);
 
559
 
 
560
            cl_insert (hist);
 
561
          }
 
562
          break;
 
563
 
 
564
        case GRUB_TERM_CTRL | 'u':
 
565
          if (lpos > 0)
 
566
            {
 
567
              grub_size_t n = lpos;
 
568
 
 
569
              if (kill_buf)
 
570
                grub_free (kill_buf);
 
571
 
 
572
              kill_buf = grub_malloc (n + 1);
 
573
              if (grub_errno)
 
574
                {
 
575
                  grub_print_error ();
 
576
                  grub_errno = GRUB_ERR_NONE;
 
577
                }
 
578
              if (kill_buf)
 
579
                {
 
580
                  grub_memcpy (kill_buf, buf, n);
 
581
                  kill_buf[n] = '\0';
 
582
                }
 
583
 
 
584
              lpos = 0;
 
585
              cl_set_pos_all ();
 
586
              cl_delete (n);
 
587
            }
 
588
          break;
 
589
 
 
590
        case GRUB_TERM_CTRL | 'y':
 
591
          if (kill_buf)
 
592
            cl_insert (kill_buf);
 
593
          break;
 
594
 
 
595
        case '\e':
 
596
          grub_free (cl_terms);
 
597
          return 0;
 
598
 
 
599
        case '\b':
 
600
          if (lpos > 0)
 
601
            {
 
602
              lpos--;
 
603
              cl_set_pos_all ();
 
604
            }
 
605
          else
 
606
            break;
 
607
          /* fall through */
 
608
 
 
609
        case GRUB_TERM_CTRL | 'd':
 
610
        case GRUB_TERM_KEY_DC:
 
611
          if (lpos < llen)
 
612
            cl_delete (1);
 
613
          break;
 
614
 
 
615
        default:
 
616
          if (grub_isprint (key))
 
617
            {
 
618
              grub_uint32_t str[2];
 
619
 
 
620
              str[0] = key;
 
621
              str[1] = '\0';
 
622
              cl_insert (str);
 
623
            }
 
624
          break;
 
625
        }
 
626
 
 
627
      grub_refresh ();
 
628
    }
 
629
 
 
630
  grub_xputs ("\n");
 
631
  grub_refresh ();
 
632
 
 
633
  /* Remove leading spaces.  */
 
634
  lpos = 0;
 
635
  while (buf[lpos] == ' ')
 
636
    lpos++;
 
637
 
 
638
  histpos = 0;
 
639
  if (strlen_ucs4 (buf) > 0)
 
640
    {
 
641
      grub_uint32_t empty[] = { 0 };
 
642
      grub_history_replace (histpos, buf, llen);
 
643
      grub_history_add (empty, 0);
 
644
    }
 
645
 
 
646
  ret = grub_ucs4_to_utf8_alloc (buf + lpos, llen - lpos + 1);
 
647
  grub_free (buf);
 
648
  grub_free (cl_terms);
 
649
  return ret;
 
650
}