dragora-keymap 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. #! /bin/sh -
  2. #
  3. # A script to configure the keyboard map on console
  4. #
  5. # Copyright (c) 2019 Matias Fonzo, <selk@dragora.org>.
  6. #
  7. # Licensed under the Apache License, Version 2.0 (the "License");
  8. # you may not use this file except in compliance with the License.
  9. # You may obtain a copy of the License at
  10. #
  11. # http://www.apache.org/licenses/LICENSE-2.0
  12. #
  13. # Unless required by applicable law or agreed to in writing, software
  14. # distributed under the License is distributed on an "AS IS" BASIS,
  15. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. # See the License for the specific language governing permissions and
  17. # limitations under the License.
  18. # Exit immediately on any error
  19. set -e
  20. PROGRAM="${0##*/}"
  21. TMPDIR="${TMPDIR:-$HOME}"
  22. TMPFILE="${TMPDIR}/.${PROGRAM}.${RANDOM-0}$$"
  23. OUTPUT="${TMPFILE}.data"
  24. LOCKFILE=/tmp/dragora-keymap.lockfile
  25. KEYMAPS="${KEYMAPS:-/usr/share/keymaps/i386}"
  26. chkstatus_or_exit()
  27. {
  28. status=$?
  29. # Clean up temporary files
  30. rm -f -- "$TMPFILE" "$LOCKFILE"
  31. if test $status -ne 0
  32. then
  33. printf "%s\n" "" "Return status = $status" 1>&2
  34. exit 2;
  35. fi
  36. unset status
  37. }
  38. # Sanity checks
  39. if test ! -d "$TMPDIR"
  40. then
  41. echo "${PROGRAM}: \`${TMPDIR}' is not a qualified temporary directory" 1>&2
  42. exit 1;
  43. fi
  44. if test ! -w "$TMPDIR"
  45. then
  46. echo "${PROGRAM}: \`${TMPDIR}' is not a writable temporary directory" 1>&2
  47. exit 1;
  48. fi
  49. if test ! -d "$KEYMAPS"
  50. then
  51. echo "${PROGRAM}: Directory \`${KEYMAPS}' for keyboard maps does not exist as such" 1>&2
  52. exit 1;
  53. fi
  54. trap 'chkstatus_or_exit' EXIT HUP INT QUIT ABRT TERM
  55. umask 077; # Remove access for all but user.
  56. # Unfortunately, loadkeys(1) is limited to the superuser;
  57. # we set a lock to allow only one instance of the script.
  58. if ( set -C ; echo ": $PROGRAM - locked" > $LOCKFILE ) 2> /dev/null
  59. then
  60. true
  61. else
  62. if test -e "$LOCKFILE"
  63. then
  64. echo "Only one instance of \`${PROGRAM}' is allowed." 1>&2
  65. exit 1;
  66. else
  67. echo "${PROGRAM}: \`${LOCKFILE}' lock failed." 1>&2
  68. exit 2;
  69. fi
  70. fi
  71. # Compose output file to be shown
  72. # Use a portable find(1) in terms of options, plus sort(1),
  73. # redirects the standard error to see any possible error
  74. search="$(find "$KEYMAPS" -name '*.map*' -print | sort 2> /dev/tty)"
  75. if test -z "$search"
  76. then
  77. echo "No keyboard maps were found in \`${KEYMAPS}'." 1>&2
  78. exit 1;
  79. fi
  80. # Header
  81. printf "%s\n" \
  82. 'dialog --colors \' \
  83. ' --backtitle "\Zb${PROGRAM} - Keyboard map selection" \' \
  84. ' --title "MAIN MENU" --default-item "qwerty/us" --menu \' \
  85. '"Welcome to \Z3${PROGRAM}\Zn!\n\n\' \
  86. 'The following menu list is organized as keyboard \n\' \
  87. '\"layout/language\". \n\n\' \
  88. 'Select a keyboard map for the console:" 24 56 12 \' \
  89. > $OUTPUT
  90. # Append 'search' to the body
  91. for item in $search
  92. do
  93. level="${item%/*}" # Remove all except the last slash.
  94. level="${level##*/}" # Starting-point under which it was found.
  95. item="${item%.map*}" # Remove extension(s).
  96. item="${item##*/}" # Get the base name.
  97. # Ignore unwanted map directories
  98. case $level in
  99. include | fgGIod)
  100. continue
  101. ;;
  102. *)
  103. echo "\"${level}/$item\" \"\" \\" >> $OUTPUT
  104. ;;
  105. esac
  106. done
  107. unset item level \
  108. search
  109. # End of
  110. printf "2> \$TMPFILE\n\n" >> $OUTPUT
  111. # Import menu
  112. . $OUTPUT
  113. # Read answer from 'TMPFILE'
  114. echo "" >> $TMPFILE; # Append new line for reading.
  115. IFS= read -r REPLY < $TMPFILE || exit 2;
  116. # Compose values by layout/map to be set
  117. layout="${REPLY%/*}"
  118. map="${REPLY##*/}"
  119. unset REPLY
  120. # The temporary files are not needed anymore
  121. rm -f -- "$TMPFILE" "$OUTPUT"
  122. umask 022; # Remove write permission for group and other.
  123. # Set keyboard map
  124. loadkeys "${layout}/$map"
  125. while true
  126. do
  127. testkeys="$(
  128. dialog --colors \
  129. --no-mouse --no-cancel --no-ok \
  130. --backtitle "\Zb${PROGRAM} - Keyboard map check" \
  131. --title "SELECTED KEYMAP: ${layout}/$map" \
  132. --inputbox \
  133. "Try the chosen keyboard map by typing something. Once satisfied\n\
  134. type \Zb\Z71\Zn (or \Zb\Z7y\Zn) then hit \Zb\Z7ENTER\Zn \
  135. to continue. To choose a different keyboard map, type \Zb\Z72\Zn (or \
  136. \Zb\Z7n\Zn) plus \Zb\Z7ENTER\Zn." 10 68 2>&1 > /dev/tty
  137. )"
  138. case $testkeys in
  139. 1 | Y | y)
  140. break
  141. ;;
  142. 2 | N | n)
  143. rm -f -- "$LOCKFILE"
  144. exec "$0"
  145. ;;
  146. esac
  147. done
  148. unset testkeys
  149. dialog --colors \
  150. --backtitle "\Zb${PROGRAM} - Configuration file" \
  151. --title "/etc/rc.conf" --yesno \
  152. "Would do you like to save this change for the next reboot?" 5 62
  153. dialog --clear
  154. echo ""
  155. echo "Setting 'RC_KEYMAP=${layout}/$map' on /etc/rc.conf ..."
  156. echo ",s/^\(RC_KEYMAP\)=.*/\1=${layout}\/${map}/"$'\nw' | \
  157. ed -s /etc/rc.conf && echo Done.