#!/bin/bash # dsys - system settings on Das OS: host name, time zone, language and # console keyboard, in place of hostnamectl, timedatectl and localectl. set -euo pipefail # shellcheck source=helpers.sh . "${DAS_HELPERS:-/usr/lib/das/helpers.sh}" zoneinfo=/usr/share/zoneinfo libc_locales=/etc/default/libc-locales keymaps=/usr/share/kbd/keymaps usage() { if [[ -n $uk ]]; then cat <<'EOF' Використання: dsys [КОМАНДА] [ЗНАЧЕННЯ] info огляд системи (типова команда) hostname [ІМ'Я] показати або змінити ім'я хоста timezone [ЗОНА] показати або змінити часовий пояс (Europe/Kyiv, достатньо й частини назви: Kyiv) timezone list [ФІЛЬТР] усі часові пояси locale [МОВА] показати або змінити мову системи (uk_UA, en_US) locale list [ФІЛЬТР] доступні мови; * — уже зібрані keymap [РОЗКЛАДКА] показати або змінити розкладку консолі (us, ua-utf) keymap list [ФІЛЬТР] доступні розкладки консолі Мову й розкладку графічного сеансу кожен користувач задає в налаштуваннях Xfce і в das-welcome; dsys змінює типові для системи й консолі. EOF else cat <<'EOF' Usage: dsys [COMMAND] [VALUE] info system overview (the default) hostname [NAME] show or change the host name timezone [ZONE] show or change the time zone (Europe/Kyiv, part of the name will do: Kyiv) timezone list [FILTER] all time zones locale [LANGUAGE] show or change the system language (uk_UA, en_US) locale list [FILTER] available languages; * marks the built ones keymap [MAP] show or change the console keyboard map (us, ua-utf) keymap list [FILTER] available console keyboard maps In the graphical session every user picks the language and keyboard in the Xfce settings and in das-welcome; dsys changes the system and console defaults. EOF fi } current_hostname() { cat /etc/hostname 2>/dev/null || hostname } current_timezone() { local tz tz=$(readlink /etc/localtime 2>/dev/null || true) echo "${tz#*zoneinfo/}" } current_locale() { sed -n 's/^LANG=//p' /etc/locale.conf 2>/dev/null | tr -d '"' } rc_value() { sed -n "s/^$1=//p" /etc/rc.conf 2>/dev/null | tr -d '"' | tail -n 1 } # A graphical session keeps its X authority under the old host name session_warning() { if pgrep -x lightdm >/dev/null || [[ -n ${DISPLAY:-} ]]; then say "Перезавантажте комп'ютер: графічний сеанс не відкриватиме нових вікон зі старим іменем." \ "Reboot: the graphical session will not open new windows under the old name." fi } # 3 д 4 год 5 хв / 3 d 4 h 5 min uptime_text() { local s d h m read -r s _ 0)); then say "$d д $h год $m хв" "$d d $h h $m min" elif ((h > 0)); then say "$h год $m хв" "$h h $m min" else say "$m хв" "$m min" fi } cmd_info() { local ntp line pad "$(say "Ім'я хоста:" "Host name:")" 16; current_hostname pad "$(say "Система:" "System:")" 16; echo "$(uname -sr), $(uname -m)" pad "$(say "Працює:" "Up:")" 16; uptime_text pad "$(say "Час:" "Time:")" 16; date '+%Y-%m-%d %H:%M:%S %Z' pad "$(say "Часовий пояс:" "Time zone:")" 16; current_timezone if ntp=$(chronyc -n tracking 2>/dev/null); then if grep -q '^Leap status *: Normal' <<<"$ntp"; then ntp=$(say "синхронізовано (chrony)" "synchronized (chrony)") else ntp=$(say "не синхронізовано (chrony)" "not synchronized (chrony)") fi else ntp=$(say "не працює (dsv enable chronyd)" "not running (dsv enable chronyd)") fi pad "$(say "Синхронізація:" "Time sync:")" 16; echo "$ntp" pad "$(say "Мова:" "Language:")" 16; current_locale pad "$(say "Консоль:" "Console:")" 16 echo "$(say розкладка keymap) $(rc_value KEYMAP || true), $(say шрифт font) $(rc_value FONT || true)" say "Мережа:" "Network:" ip -brief address 2>/dev/null | while read -r line; do [[ $line == lo\ * ]] || echo " $line" done } cmd_hostname() { local new=${1:-} old if [[ -z $new ]]; then current_hostname return fi [[ $new =~ ^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$ ]] || die "'$new': малі латинські літери, цифри й дефіс (не на початку й не в кінці)" \ "'$new': lowercase Latin letters, digits and hyphens (not first or last)" need_root hostname "$new" old=$(current_hostname) echo "$new" >/etc/hostname # The installers add "127.0.1.1 "; keep the line in step if grep -qw -- "$old" /etc/hosts; then sed -i "/^[^#]/s/\([[:space:]]\)${old//./\\.}\([[:space:]]\|$\)/\1$new\2/g" /etc/hosts fi grep -qw -- "$new" /etc/hosts || printf '127.0.1.1\t%s\n' "$new" >>/etc/hosts hostname "$new" say "Ім'я хоста: $new" "Host name: $new" session_warning } # All time zones, from tzdata's table plus UTC timezones() { { awk '!/^#/ { print $3 }' "$zoneinfo/zone1970.tab"; echo UTC; } | sort -u } cmd_timezone() { local zone=${1:-} matches line if [[ -z $zone ]]; then current_timezone return fi if [[ $zone == list ]]; then timezones | grep -i -- "${2:-}" || true return fi if ! timezones | grep -qx -- "$zone"; then # Kyiv -> Europe/Kyiv, when only one zone matches matches=$(timezones | grep -i -- "$zone" || true) if [[ $(grep -c . <<<"$matches") -eq 1 ]]; then zone=$matches elif [[ -n $matches ]]; then say "Кілька часових поясів підходять, уточніть:" "Several time zones match, be more specific:" >&2 head -n 20 <<<"$matches" | while read -r line; do echo " $line"; done >&2 (($(grep -c . <<<"$matches") <= 20)) || echo " ..." >&2 exit 1 else die "невідомий часовий пояс '$zone' (dsys timezone list)" "unknown time zone '$zone' (dsys timezone list)" fi fi need_root timezone "$zone" ln -sfn "$zoneinfo/$zone" /etc/localtime say "Часовий пояс: $zone, зараз $(date '+%H:%M %Z')" "Time zone: $zone, now $(date '+%H:%M %Z')" } # Every UTF-8 locale glibc can build, with * for the enabled ones locales() { sed -n 's/^\(#\?\)\([^ ]*\.UTF-8\) UTF-8[[:space:]]*$/\2 \1/p' "$libc_locales" | awk '{ print ($2 == "#" ? " " : "* ") $1 }' } cmd_locale() { local lang=${1:-} re if [[ -z $lang ]]; then current_locale return fi if [[ $lang == list ]]; then locales | grep -i -- "${2:-}" || true return fi [[ $lang == *.* ]] || lang+=.UTF-8 re=${lang//./\\.} locales | grep -q "^. $re\$" || die "невідома мова '$lang' (dsys locale list)" "unknown language '$lang' (dsys locale list)" need_root locale "$lang" if grep -q "^#$re " "$libc_locales"; then sed -i "s/^#\($re \)/\1/" "$libc_locales" say "Збираю $lang..." "Building $lang..." xbps-reconfigure -f glibc-locales >/dev/null fi # Keep the other settings, Void's default file also has LC_COLLATE=C if grep -q '^LANG=' /etc/locale.conf 2>/dev/null; then sed -i "s/^LANG=.*/LANG=$lang/" /etc/locale.conf else echo "LANG=$lang" >>/etc/locale.conf fi say "Мова системи: $lang (діє з наступного входу)" "System language: $lang (from the next login)" } cmd_keymap() { local map=${1:-} if [[ -z $map ]]; then rc_value KEYMAP return fi if [[ $map == list ]]; then find "$keymaps" -name '*.map.gz' -printf '%f\n' | sed 's/\.map\.gz$//' | sort -u | grep -i -- "${2:-}" || true return fi [[ -n $(find "$keymaps" -name "$map.map.gz" -print -quit) ]] || die "невідома розкладка '$map' (dsys keymap list)" "unknown keyboard map '$map' (dsys keymap list)" need_root keymap "$map" set_rc KEYMAP "$map" # The default console font has no Cyrillic letters if [[ $map == @(ua|ru|by|bg|mk|sr)* && -z $(rc_value FONT) ]]; then set_rc FONT cyr-sun16 fi loadkeys "$map" >/dev/null 2>&1 || true say "Розкладка консолі: $map" "Console keyboard map: $map" } cmd=${1:-info} [[ $# -gt 0 ]] && shift case $cmd in info | status) cmd_info ;; hostname | host) cmd_hostname "$@" ;; timezone | tz) cmd_timezone "$@" ;; locale | lang) cmd_locale "$@" ;; keymap | keyboard) cmd_keymap "$@" ;; -h | --help | help) usage ;; *) usage >&2 exit 1 ;; esac