freebsd-dev/usr.sbin/bsdconfig/share/keymap.subr
Devin Teske ab00ac327a Fix long standing issue in bsdconfig's keymap selection
Since the translation to vt as terminal emulator, the keymaps files
path has changed and this change does not get followed in bsdconfig.
This implicates boot time warnings about a wrong keymap file, what
is very confusing for the new users and for me too, so initialize
the default keymaps search path depending on terminal type.

Differential Revision:	https://reviews.freebsd.org/D8734
Submitted by:	Oliver Pinter <oliver.pinter@hardenedbsd.org>
Reviewed by:	ed, jilles, dteske
MFC after:	3 days
X-MFC-to:	stable/11
Sponsored by:	HardenedBSD
Signed-off-by:	Oliver Pinter <oliver.pinter@hardenedbsd.org>
2017-05-25 18:16:17 +00:00

267 lines
7.8 KiB
Plaintext

if [ ! "$_KEYMAP_SUBR" ]; then _KEYMAP_SUBR=1
#
# Copyright (c) 2013-2015 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD$
#
############################################################ INCLUDES
BSDCFG_SHARE="/usr/share/bsdconfig"
. $BSDCFG_SHARE/common.subr || exit 1
f_dprintf "%s: loading includes..." keymap.subr
f_include $BSDCFG_SHARE/struct.subr
############################################################ CONFIGURATION
#
# Defaults taken from usr.sbin/kbdmap/kbdmap.h
#
: ${DEFAULT_LANG:=en}
case "$( sysctl -n kern.vty )" in
vt) : ${DEFAULT_KEYMAP_DIR:=/usr/share/vt/keymaps} ;;
*) : ${DEFAULT_KEYMAP_DIR:=/usr/share/syscons/keymaps} ;;
esac
############################################################ GLOBALS
KEYMAPS=
NKEYMAPS=0
# A "keymap" from kbdmap's point of view
f_struct_define KEYMAP \
desc \
keym \
mark
#
# Default behavior is to call f_keymap_get_all() automatically when loaded.
#
: ${KEYMAP_SELF_SCAN_ALL=1}
############################################################ FUNCTIONS
# f_keymap_register $name $desc $keym $mark
#
# Register a keymap. A `structure' (see struct.subr) is created with the name
# keymap_$name (so make sure $name contains only alpha-numeric characters or
# the underscore, `_'). The remaining arguments after $name correspond to the
# propertise of the `KEYMAP' structure-type (defined above).
#
# If not already registered, the keymap is then appended to the KEYMAPS
# environment variable, a space-separated list of all registered keymaps.
#
f_keymap_register()
{
local name="$1" desc="$2" keym="$3" mark="$4"
f_struct_new KEYMAP "keymap_$name" || return $FAILURE
keymap_$name set desc "$desc"
keymap_$name set keym "$keym"
keymap_$name set mark "$mark"
# Scan our global register to see if needs ammending
local k found=
for k in $KEYMAPS; do
[ "$k" = "$name" ] || continue
found=1 && break
done
[ "$found" ] || KEYMAPS="$KEYMAPS $name"
return $SUCCESS
}
# f_keymap_checkfile $keymap
#
# Check that $keymap is a readable kbdmap(5) file. Returns success if $keymap
# is a file, is readable, and exists in $DEFAULT_KEYMAP_DIR; otherwise failure.
# If debugging is enabled, an appropriate debug error message is printed if
# $keymap is not available.
#
f_keymap_checkfile()
{
local keym="$1"
# Fixup keymap if it doesn't already contain at least one `/'
[ "${keym#*/}" = "$keym" ] && keym="$DEFAULT_KEYMAP_DIR/$keym"
# Short-cuts
[ -f "$keym" -a -r "$keym" ] && return $SUCCESS
f_debugging || return $FAILURE
# Print an appropriate debug error message
if [ ! -e "$keym" ]; then
f_dprintf "%s: No such file or directory" "$keym"
elif [ ! -f "$keym" ]; then
f_dprintf "%s: Not a file!" "$keym"
elif [ ! -r "$keym" ]; then
f_dprintf "%s: Permission denied" "$keym"
fi
return $FAILURE
}
# f_keymap_get_all
#
# Get all keymap information for kbdmap(5) entries both in the database and
# loosely existing in $DEFAULT_KEYMAP_DIR.
#
f_keymap_get_all()
{
local fname=f_keymap_get_all
local lang="${LC_ALL:-${LC_CTYPE:-${LANG:-$DEFAULT_LANG}}}"
[ "$lang" = "C" ] && lang="$DEFAULT_LANG"
f_dprintf "%s: Looking for keymap files..." $fname
f_dialog_info "$msg_looking_for_keymap_files"
f_dprintf "DEFAULT_LANG=[%s]" "$DEFAULT_LANG"
eval "$( awk -F: -v lang="$lang" -v lang_default="$DEFAULT_LANG" '
BEGIN {
# en_US.ISO8859-1 -> en_..\.ISO8859-1
dialect = lang
if (length(dialect) >= 6 &&
substr(dialect, 3, 1) == "_")
dialect = substr(dialect, 1, 3) ".." \
substr(dialect, 6)
printf "f_dprintf \"dialect=[%%s]\" \"%s\";\n", dialect
# en_US.ISO8859-1 -> en
lang_abk = lang
if (length(lang_abk) >= 3 &&
substr(lang_abk, 3, 1) == "_")
lang_abk = substr(lang_abk, 1, 2)
printf "f_dprintf \"lang_abk=[%%s]\" \"%s\";\n",
lang_abk
}
function find_token(buffer, token)
{
if (split(buffer, tokens, /,/) == 0) return 0
found = 0
for (t in tokens)
if (token == tokens[t]) { found = 1; break }
return found
}
function add_keymap(desc,mark,keym)
{
marks[keym] = mark
name = keym
gsub(/[^[:alnum:]_]/, "_", name)
gsub(/'\''/, "'\''\\'\'\''", desc);
printf "f_keymap_checkfile %s && " \
"f_keymap_register %s '\'%s\'' %s %u\n",
keym, name, desc, keym, mark
}
!/^[[:space:]]*(#|$)/ {
sub(/^[[:space:]]*/, "", $0)
keym = $1
if (keym ~ /^(MENU|FONT)$/) next
lg = ($2 == "" ? lang_default : $2)
# Match the entry and store the type of match we made
# as the mark value (so that if we make a better match
# later on with a higher mark, it overwrites previous)
mark = marks[keym];
if (find_token(lg, lang))
add_keymap($3, 4, keym) # Best match
else if (mark <= 3 && find_token(lg, dialect))
add_keymap($3, 3, keym)
else if (mark <= 2 && find_token(lg, lang_abk))
add_keymap($3, 2, keym)
else if (mark <= 1 && find_token(lg, lang_default))
add_keymap($3, 1, keym)
else if (mark <= 0)
add_keymap($3, 0, keym)
}
' "$DEFAULT_KEYMAP_DIR/INDEX.${DEFAULT_KEYMAP_DIR##*/}" )"
#
# Look for keymaps not in database
#
local direntry keym name
set +f # glob
for direntry in "$DEFAULT_KEYMAP_DIR"/*; do
[ "${direntry##*.}" = ".kbd" ] || continue
keym="${direntry##*/}"
f_str2varname "$keym" name
f_struct keymap_$name && continue
f_keymap_checkfile "$keym" &&
f_keymap_register $name "${keym%.*}" "$keym" 0
f_dprintf "%s: not in kbdmap(5) database" "$keym"
done
#
# Sort the items by their descriptions
#
f_dprintf "%s: Sorting keymap entries by description..." $fname
KEYMAPS=$(
for k in $KEYMAPS; do
echo -n "$k "
# NOTE: Translate '8x8' to '8x08' before sending to
# sort(1) so that things work out as we might expect.
debug= keymap_$k get desc | awk 'gsub(/8x8/,"8x08")||1'
done | sort -k2 | awk '{
printf "%s%s", (started ? " " : ""), $1; started = 1
}'
)
return $SUCCESS
}
# f_keymap_kbdcontrol $keymap
#
# Install keyboard map file from $keymap.
#
f_keymap_kbdcontrol()
{
local keymap="$1"
[ "$keymap" ] || return $SUCCESS
# Fixup keymap if it doesn't already contain at least one `/'
[ "${keymap#*/}" = "$keymap" ] && keymap="$DEFAULT_KEYMAP_DIR/$keymap"
[ "$USE_XDIALOG" ] || kbdcontrol -l "$keymap"
}
############################################################ MAIN
#
# Scan for keymaps unless requeted otherwise
#
f_dprintf "%s: KEYMAP_SELF_SCAN_ALL=[%s]" keymap.subr "$KEYMAP_SELF_SCAN_ALL"
case "$KEYMAP_SELF_SCAN_ALL" in
""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
*) f_keymap_get_all
esac
f_count NKEYMAPS $KEYMAPS
f_dprintf "%s: Found %u keymap file(s)." keymap.subr $NKEYMAPS
f_dprintf "%s: Successfully loaded." keymap.subr
fi # ! $_KEYMAP_SUBR