Bug#702455: grub-common: wrong Bash auto complete for grub-set-default and grub-reboot

Alfredo Finelli 0x4146 at gmail.com
Wed Mar 6 19:28:00 UTC 2013


Package: grub-common
Version: 1.99-27
Severity: normal
Tags: patch


When using the commands "grub-set-default" and "grub-reboot" it is
possible, thanks to programmable completion, to let bash fill out the
command line with kernel names and boot options obtained from the entries
in "/boot/grub/grub.cfg".  This completion is sometimes wrong.

Here is an example completion with errors.  At the prompt I press <TAB>
after the command name:

      # grub-set-default <TAB>
      Linux, with Linux 3.2.0-4-amd64
      Linux, with Linux 3.2.0-4-amd64 (recovery mode)
      Linux, with Linux 3.8.2-t410
      Linux, with Linux 3.8.2-t410 (recovery mode)
      Grml Rescue System (grml64-small_2012.05.iso)
      Network boot (iPXE)

In this case the correct title of grub menu entries with the Linux kernel
is "Debian GNU/Linux, with Linux ...", not what is shown above.  For this
reason the following command line does not offer any completions:

      # grub-set-default L<TAB>

If instead I try to complete starting with a "D", then I get the following:

      # grub-set-default D<TAB>
      # grub-set-default Debian\ GNU/Linux\,\ with\ Linux\ 3.
      Linux, with Linux 3.2.0-4-amd64
      Linux, with Linux 3.2.0-4-amd64 (recovery mode)
      Linux, with Linux 3.8.2-t410
      Linux, with Linux 3.8.2-t410 (recovery mode)

It offers the correct completion in the command line but still the wrong
list of suggestions.

The file "/etc/bash_completion.d/grub" is where auto completion functions
for grub are defined.  By reading the source I discovered that the
completion specifications for the two commands contain the "-o filenames"
option.  As you can read in the bash manual:

    -o comp-option
        The comp-option controls several aspects of the compspec's behavior
        beyond the simple generation of completions.  comp-option may be
        one of: [...]

        filenames
            Tell readline that the compspec generates filenames, so it can
            perform any filename-specific processing (like adding a slash
            to directory names, quoting special characters, or suppressing
            trailing spaces).  Intended to be used with shell functions.

The two commands "grub-set-default" and "grub-reboot" do not expect a
filename as an argument, instead they work with a number or, in our case, a
menu item title.  We want to auto complete a string that is not a filename.
The character "/" in the word "GNU/Linux" is the offending input because it
is wrongly considered a directory separator.

At first I tried to simply remove the "filenames" option from the
completion specifications, but then I faced a new problem: the user got
a correct list of suggestions but he also had to provide manually for
the correct quoting of the string to the shell.

      # grub-set-default <TAB>
      Debian GNU/Linux, with Linux 3.2.0-4-amd64
      Debian GNU/Linux, with Linux 3.2.0-4-amd64 (recovery mode)
      Debian GNU/Linux, with Linux 3.8.2-t410
      Debian GNU/Linux, with Linux 3.8.2-t410 (recovery mode)
      Grml Rescue System (grml64-small_2012.05.iso)
      Network boot (iPXE)
      # grub-set-default D<TAB>
      # grub-set-default Debian GNU/Linux, with Linux 3.

The string that appears on the command line is unquoted and from there the
shell is not able to complete further; in this example it is trying to find
a completion for the word "3." and not for the full menu entry.

My solution to this problem was to change the way suggestion strings are
generated, so that they appear already quoted.  Then you need just a
<TAB> key press to complete the common prefix and so on, with the same
functionality as with the wrong working "filenames" completion.

      # grub-set-default <TAB>
      # grub-set-default "
      "Debian GNU/Linux, with Linux 3.2.0-4-amd64"
      "Debian GNU/Linux, with Linux 3.2.0-4-amd64 (recovery mode)"
      "Debian GNU/Linux, with Linux 3.8.2-t410"
      "Debian GNU/Linux, with Linux 3.8.2-t410 (recovery mode)"
      "Grml Rescue System (grml64-small_2012.05.iso)"
      "Network boot (iPXE)"
      # grub-set-default "D<TAB>
      # grub-set-default "Debian GNU/Linux, with Linux 3.<TAB>
      "Debian GNU/Linux, with Linux 3.2.0-4-amd64"
      "Debian GNU/Linux, with Linux 3.2.0-4-amd64 (recovery mode)"
      "Debian GNU/Linux, with Linux 3.8.2-t410"
      "Debian GNU/Linux, with Linux 3.8.2-t410 (recovery mode)"

You can find my corrections to the code in the following patch.

Best regards.






--- /etc/bash_completion.d/grub 2013-03-06 11:00:39.676578999 +0100
+++ grub        2013-03-06 19:21:22.525938227 +0100
@@ -116,7 +116,7 @@

     if [ -f "$config_file" ];then
         local IFS=$'\n'
-        COMPREPLY=( $(compgen \
+        COMPREPLY=( $(compgen -P \" -S \" \
             -W "$( awk -F "[\"']" '/menuentry/ { print $2 }' $config_file )" \
             -- "$cur" )) #'# Help emacs syntax highlighting
     fi
@@ -167,12 +167,12 @@

 __grub_set_default_program=$( echo grub-set-default | sed "s,x,x," )
 have ${__grub_set_default_program} && \
-    complete -F _grub_set_entry -o filenames ${__grub_set_default_program}
+    complete -F _grub_set_entry ${__grub_set_default_program}
 unset __grub_set_default_program

 __grub_reboot_program=$( echo grub-reboot | sed "s,x,x," )
 have ${__grub_reboot_program} && \
- complete -F _grub_set_entry -o filenames ${__grub_reboot_program}
+ complete -F _grub_set_entry ${__grub_reboot_program}
 unset __grub_reboot_program






-- System Information:
Debian Release: 7.0
  APT prefers testing
  APT policy: (900, 'testing'), (800, 'unstable')
Architecture: amd64 (x86_64)

Kernel: Linux 3.8.2-t410 (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages grub-common depends on:
ii  gettext-base        0.18.1.1-9
ii  libc6               2.13-38
ii  libdevmapper1.02.1  2:1.02.74-6
ii  libfreetype6        2.4.9-1.1
ii  libfuse2            2.9.0-2+deb7u1
ii  zlib1g              1:1.2.7.dfsg-13

Versions of packages grub-common recommends:
pn  os-prober  <none>

Versions of packages grub-common suggests:
pn  desktop-base   <none>
pn  grub-emu       <none>
pn  multiboot-doc  <none>
ii  xorriso        1.2.2-2

-- no debconf information



More information about the Pkg-grub-devel mailing list