| #!/bin/sh | |
| ############################################################################### | |
| # BRLTTY - A background process providing access to the console screen (when in | |
| # text mode) for a blind person using a refreshable braille display. | |
| # | |
| # Copyright (C) 1995-2023 by The BRLTTY Developers. | |
| # | |
| # BRLTTY comes with ABSOLUTELY NO WARRANTY. | |
| # | |
| # This is free software, placed under the terms of the | |
| # GNU Lesser General Public License, as published by the Free Software | |
| # Foundation; either version 2.1 of the License, or (at your option) any | |
| # later version. Please see the file LICENSE-LGPL for details. | |
| # | |
| # Web Page: http://brltty.app/ | |
| # | |
| # This software is maintained by Dave Mielke <dave@mielke.cc>. | |
| ############################################################################### | |
| set -e | |
| . "`dirname "${0}"`/brltty-prologue.sh" | |
| . "${programDirectory}/brltty-config.sh" | |
| showProgramUsagePurpose() { | |
| cat <<END_OF_PROGRAM_USAGE_PURPOSE | |
| Simplify the job of Creating and making changes to BRLTTY's unprivileged user. | |
| END_OF_PROGRAM_USAGE_PURPOSE | |
| } | |
| declare -A privilegeParameters | |
| parseParameterString privilegeParameters "${BRLTTY_PRIVILEGE_PARAMETERS}" lx | |
| readonly defaultUserName="${privilegeParameters["USER"]}" | |
| readonly defaultUserInformation="Braille Device Daemon" | |
| readonly defaultHomeDirectory="${BRLTTY_UPDATABLE_DIRECTORY}" | |
| readonly defaultLoginShell="/sbin/nologin" | |
| showProgramUsageNotes() { | |
| cat <<END_OF_PROGRAM_USAGE_NOTES | |
| When creating a new user, these options have the following defaults: | |
| -d ${defaultHomeDirectory:-the home directory isn't defined} | |
| -g a new group with the same name as the user | |
| -i ${defaultUserInformation} | |
| -l ${defaultLoginShell} | |
| These defaults don't apply when making changes to an existing user. | |
| END_OF_PROGRAM_USAGE_NOTES | |
| } | |
| executeCommand() { | |
| "${useSudo}" && set -- sudo -- "${@}" | |
| if "${testMode}" | |
| then | |
| echo "${*}" | |
| else | |
| "${@}" | |
| fi | |
| } | |
| groupList=() | |
| addGroups() { | |
| while [ "${#}" -gt 0 ] | |
| do | |
| local group="${1}" | |
| shift 1 | |
| [ -n "${group}" ] || continue | |
| [ "${group#*/}" = "${group}" ] || { | |
| group="$(stat -c "%G" "${group}")" || : | |
| [ -n "${group}" ] || continue | |
| } | |
| local g | |
| for g in "${groupList[@]}" | |
| do | |
| [ "${g}" = "${group}" ] && { | |
| group="" | |
| break | |
| } | |
| done | |
| [ -n "${group}" ] && groupList[${#groupList[*]}]="${group}" | |
| done | |
| return 0 | |
| } | |
| addProgramOption a flag noALSA "don't allow playing sound via the ALSA framework" | |
| addProgramOption b flag noBrlapi "don't allow reading BrlAPI's authorization key file" | |
| addProgramOption c flag noConsoles "don't allow access to the virtual consoles" | |
| addProgramOption d string.path homeDirectory "set/change the home (login) directory" | |
| addProgramOption g string.group primaryGroup "set/change the primary (login) group" | |
| addProgramOption i string.text userInformation "set/change the user information (gecos) text" | |
| addProgramOption k flag noKeyboards "don't allow keyboard monitoring" | |
| addProgramOption l string.path loginShell "set/change the login shell" | |
| addProgramOption p flag noPulse "don't allow playing sound via the Pulse Audio server" | |
| addProgramOption s flag noSerial "don't allow access to serial devices" | |
| addProgramOption u flag noUSB "don't allow access to USB devices" | |
| addProgramOption E flag allowChanges "allow changes to an existing user" | |
| addProgramOption G flag noGroups "don't set/change the supplementary group list" | |
| addProgramOption N flag allowCreate "allow creating a new user" | |
| addProgramOption S flag useSudo "use sudo to execute the commands as root" | |
| addProgramOption T flag testMode "test mode - show the commands that would be executed" | |
| addProgramOption U string.user userName "the user to be created/changed" "${defaultUserName}" | |
| parseProgramArguments "${@}" | |
| [ -n "${userName}" ] || userName="${defaultUserName}" | |
| [ -n "${userName}" ] || syntaxError "unprivileged user not configured - use -U (user) to specify" | |
| if id -u "${userName}" >/dev/null 2>&1 | |
| then | |
| "${allowChanges}" || semanticError "user already exists: ${userName} - use -E (existing) to allow" | |
| command=(usermod) | |
| else | |
| "${allowCreate}" || semanticError "user doesn't exist: ${userName} - use -N (new) to allow" | |
| command=(useradd --system) | |
| [ -n "${primaryGroup}" ] || command+=(--user-group) | |
| [ -n "${userInformation}" ] || userInformation="${defaultUserInformation}" | |
| [ -n "${homeDirectory}" ] || homeDirectory="${defaultHomeDirectory}" | |
| [ -n "${loginShell}" ] || loginShell="${defaultLoginShell}" | |
| if [ -n "${homeDirectory}" ] | |
| then | |
| command+=(--create-home) | |
| else | |
| command+=(--no-create-home) | |
| fi | |
| fi | |
| [ -n "${homeDirectory}" ] && command+=(--home "${homeDirectory}") | |
| [ -n "${primaryGroup}" ] && command+=(--gid "${primaryGroup}") | |
| [ -n "${userInformation}" ] && command+=(--comment "${userInformation}") | |
| [ -n "${loginShell}" ] && command+=(--shell "${loginShell}") | |
| "${noGroups}" || { | |
| "${noALSA}" || addGroups audio | |
| "${noBrlapi}" || addGroups "${BRLAPI_KEY_FILE}" | |
| "${noConsoles}" || addGroups tty /dev/vcs1 /dev/tty1 | |
| "${noKeyboards}" || addGroups input | |
| "${noPulse}" || addGroups pulse-access | |
| "${noSerial}" || addGroups /dev/ttyS0 | |
| "${noUSB}" || addGroups /dev/bus/usb | |
| groupsOperand="${groupList[*]}" | |
| groupsOperand="${groupsOperand// /,}" | |
| command+=(--groups "${groupsOperand}") | |
| } | |
| "${testMode}" || { | |
| if "${useSudo}" | |
| then | |
| sudo -v | |
| elif [ "$(id -u)" -ne 0 ] | |
| then | |
| semanticError "not executing as root" | |
| fi | |
| } | |
| command+=(-- "${userName}") | |
| executeCommand "${command[@]}" | |
| exit 0 |