From 545d95bd9c66ebf04bc02b8554124215dba9c18d Mon Sep 17 00:00:00 2001 From: "T. R. Bernstein" <137705289+trbernstein@users.noreply.github.com> Date: Fri, 28 Jun 2024 17:17:47 +0200 Subject: [PATCH] Convert indention from spaces to tabs --- bootstrap.sh | 182 +++++++-------- install.sh | 175 ++++++++------- modules/01-system-settings.sh | 168 +++++++------- modules/02-create-filevault-user.sh | 328 ++++++++++++++-------------- modules/03-install-brew.sh | 272 +++++++++++------------ modules/04-install-brew-apps.sh | 120 +++++----- modules/05-install-remap-keys.sh | 206 ++++++++--------- modules/06-install-mas-apps.sh | 60 ++--- modules/07-install-binaries.sh | 74 +++---- modules/08-install-zsh-libraries.sh | 70 +++--- modules/09-install-fonts.sh | 42 ++-- modules/lib.sh | 128 +++++------ 12 files changed, 912 insertions(+), 913 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 2fe53e0..aeb873e 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -2,158 +2,158 @@ # vi: set ft=zsh tw=80 ts=2 function versionGT() { - [[ "${1%.*}" -gt "${2%.*}" ]] || [[ "${1%.*}" -eq "${2%.*}" && "${1#*.}" -gt "${2#*.}" ]] + [[ "${1%.*}" -gt "${2%.*}" ]] || [[ "${1%.*}" -eq "${2%.*}" && "${1#*.}" -gt "${2#*.}" ]] } function majorMinor() { - echo "${1%%.*}.$(x="${1#*.}" echo "${x%%.*}")" + echo "${1%%.*}.$(x="${1#*.}" echo "${x%%.*}")" } function shouldInstallCommandLineTools() { - local macosVersion=$(majorMinor $(/usr/bin/sw_vers -productVersion)) - if version_gt "${macosVersion}" "10.13" - then - ! [[ -e "/Library/Developer/CommandLineTools/usr/bin/git" ]] - else - ! [[ -e "/Library/Developer/CommandLineTools/usr/bin/git" ]] || - ! [[ -e "/usr/include/iconv.h" ]] - fi + local macosVersion=$(majorMinor $(/usr/bin/sw_vers -productVersion)) + if version_gt "${macosVersion}" "10.13" + then + ! [[ -e "/Library/Developer/CommandLineTools/usr/bin/git" ]] + else + ! [[ -e "/Library/Developer/CommandLineTools/usr/bin/git" ]] || + ! [[ -e "/usr/include/iconv.h" ]] + fi } function removeNewlines() { - printf "%s" "${1/"$'\n'"/}" + printf "%s" "${1/"$'\n'"/}" } function acceptXcodeLicense() { - xcodebuild -license accept + xcodebuild -license accept } function installCommandLineTools() { - shouldInstallCommandLineTools || return - cltPlaceholder="/tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress" - touch ${cltPlaceholder} + shouldInstallCommandLineTools || return + cltPlaceholder="/tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress" + touch ${cltPlaceholder} - cltLabelCommand="/usr/sbin/softwareupdate -l | - grep -B 1 -E 'Command Line Tools' | - awk -F'*' '/^ *\\*/ {print \$2}' | - sed -e 's/^ *Label: //' -e 's/^ *//' | - sort -V | - tail -n1" - cltLabel="$(removeNewlines "$(/bin/bash -c "${cltLabelCommand}")")" + cltLabelCommand="/usr/sbin/softwareupdate -l | + grep -B 1 -E 'Command Line Tools' | + awk -F'*' '/^ *\\*/ {print \$2}' | + sed -e 's/^ *Label: //' -e 's/^ *//' | + sort -V | + tail -n1" + cltLabel="$(removeNewlines "$(/bin/bash -c "${cltLabelCommand}")")" - if [[ -n "${cltLabel}" ]] - then - /usr/sbin/softwareupdate -i ${cltLabel} - /usr/bin/xcode-select --switch /Library/Developer/CommandLineTools - fi - rm -f ${cltPlaceholder} + if [[ -n "${cltLabel}" ]] + then + /usr/sbin/softwareupdate -i ${cltLabel} + /usr/bin/xcode-select --switch /Library/Developer/CommandLineTools + fi + rm -f ${cltPlaceholder} } function ensureCommandLineTools() { - installCommandLineTools - acceptXcodeLicense + installCommandLineTools + acceptXcodeLicense } function ensureDocopts() { - which docopts > /dev/null && return - local fileURL="${DOCOPTS_URL:-https://github.com/astzweig/docopts/releases/download/v.0.7.0/docopts_darwin_amd64}" - curl --output ./docopts -fsSL "${fileURL}" || return - chmod u+x ./docopts - PATH="${PATH}:`pwd`" + which docopts > /dev/null && return + local fileURL="${DOCOPTS_URL:-https://github.com/astzweig/docopts/releases/download/v.0.7.0/docopts_darwin_amd64}" + curl --output ./docopts -fsSL "${fileURL}" || return + chmod u+x ./docopts + PATH="${PATH}:`pwd`" } function cloneMacOSSystemRepo() { - local repoUrl="${MACOS_SYSTEM_REPO_URL:-https://github.com/astzweig/macos-system.git}" - git clone --depth 1 -q "${repoUrl}" . 2> /dev/null || return 10 - [ -n "${MACOS_SYSTEM_REPO_BRANCH}" ] && git checkout -q ${MACOS_SYSTEM_REPO_BRANCH} 2> /dev/null || true + local repoUrl="${MACOS_SYSTEM_REPO_URL:-https://github.com/astzweig/macos-system.git}" + git clone --depth 1 -q "${repoUrl}" . 2> /dev/null || return 10 + [ -n "${MACOS_SYSTEM_REPO_BRANCH}" ] && git checkout -q ${MACOS_SYSTEM_REPO_BRANCH} 2> /dev/null || true } function cloneZSHLibRepo() { - local zshlibRepoUrl="${ZSHLIB_REPO_URL:-https://github.com/astzweig/zshlib.git}" - git config --file=.gitmodules submodule.zshlib.url "${zshlibRepoUrl}" - git submodule -q sync - [ -n "${ZSHLIB_REPO_BRANCH}" ] && git submodule set-branch -b ${ZSHLIB_REPO_BRANCH} `git config --file=.gitmodules submodule.zshlib.path` 2> /dev/null || true - git submodule -q update --depth 1 --init --recursive --remote 2> /dev/null || return 10 + local zshlibRepoUrl="${ZSHLIB_REPO_URL:-https://github.com/astzweig/zshlib.git}" + git config --file=.gitmodules submodule.zshlib.url "${zshlibRepoUrl}" + git submodule -q sync + [ -n "${ZSHLIB_REPO_BRANCH}" ] && git submodule set-branch -b ${ZSHLIB_REPO_BRANCH} `git config --file=.gitmodules submodule.zshlib.path` 2> /dev/null || true + git submodule -q update --depth 1 --init --recursive --remote 2> /dev/null || return 10 } function isDebug() { - test "${DEBUG}" = true -o "${DEBUG}" = 1 + test "${DEBUG}" = true -o "${DEBUG}" = 1 } function printSuccess() { - print "${colors[green]}${*}${colors[reset]}" + print "${colors[green]}${*}${colors[reset]}" } function printError() { - print "${errColors[red]}${*}${errColors[reset]}" >&2 + print "${errColors[red]}${*}${errColors[reset]}" >&2 } function printFailedWithError() { - print "${colors[red]}failed.${colors[reset]}" - print "$*" >&2 + print "${colors[red]}failed.${colors[reset]}" + print "$*" >&2 } function defineColors() { - local -A colorCodes=(red "`tput setaf 9`" green "`tput setaf 10`" reset "`tput sgr0`") - [ -t 1 ] && colors=("${(kv)colorCodes[@]}") - [ -t 2 ] && errColors=("${(kv)colorCodes[@]}") + local -A colorCodes=(red "`tput setaf 9`" green "`tput setaf 10`" reset "`tput sgr0`") + [ -t 1 ] && colors=("${(kv)colorCodes[@]}") + [ -t 2 ] && errColors=("${(kv)colorCodes[@]}") } function ensureRepo() { - local repoName="$1" cmdName="${2}" - print -n "Installing ${1}..." - $cmdName || { printFailedWithError "This script requires $repoName but was not able to clone it. Please ensure access to the $repoName repository."; return 10} - printSuccess 'done' + local repoName="$1" cmdName="${2}" + print -n "Installing ${1}..." + $cmdName || { printFailedWithError "This script requires $repoName but was not able to clone it. Please ensure access to the $repoName repository."; return 10} + printSuccess 'done' } function ensureBinary() { - local binaryName="$1" cmdName="${2}" - print -n "Ensure ${1} is installed..." - $cmdName || { printFailedWithError "This script requires $binaryName but was neither able to locate and install it. Please install $binaryName and add it to one of the PATH directories."; return 10} - printSuccess 'done' + local binaryName="$1" cmdName="${2}" + print -n "Ensure ${1} is installed..." + $cmdName || { printFailedWithError "This script requires $binaryName but was neither able to locate and install it. Please install $binaryName and add it to one of the PATH directories."; return 10} + printSuccess 'done' } function configureTerminal() { - if [ -t 0 ]; then - traps+=("stty $(stty -g)") - stty -echo - fi + if [ -t 0 ]; then + traps+=("stty $(stty -g)") + stty -echo + fi - if [ -t 1 ]; then - traps+=('tput cnorm') - tput civis - export TERMINAL_CURSOR_HIDDEN=true - fi + if [ -t 1 ]; then + traps+=('tput cnorm') + tput civis + export TERMINAL_CURSOR_HIDDEN=true + fi } function main() { - local traps=() - local -A colors=() errColors=() - defineColors + local traps=() + local -A colors=() errColors=() + defineColors - configureTerminal - local tmpdir="`mktemp -d -t 'macos-system'`" - isDebug || traps+=("rm -fr -- '${tmpdir}'") - trap ${(j.;.)traps} INT TERM EXIT - pushd -q "${tmpdir}" - print -l "Working directory is: ${tmpdir}" + configureTerminal + local tmpdir="`mktemp -d -t 'macos-system'`" + isDebug || traps+=("rm -fr -- '${tmpdir}'") + trap ${(j.;.)traps} INT TERM EXIT + pushd -q "${tmpdir}" + print -l "Working directory is: ${tmpdir}" - print 'Ensure command line tools are available.' - ensureCommandLineTools - ensureRepo 'macos-system' cloneMacOSSystemRepo || return - ensureRepo 'zshlib' cloneZSHLibRepo || return - ensureBinary 'docopts' ensureDocopts || return + print 'Ensure command line tools are available.' + ensureCommandLineTools + ensureRepo 'macos-system' cloneMacOSSystemRepo || return + ensureRepo 'zshlib' cloneZSHLibRepo || return + ensureBinary 'docopts' ensureDocopts || return - print 'Will now run the installer.' - local -A colors=() errColors=() - [ -t 1 ] && tput cnorm - isDebug && export MACOS_SYSTEM_DEBUG=true - "${tmpdir}/install.sh" "$@" - [ -t 1 ] && tput civis - popd -q + print 'Will now run the installer.' + local -A colors=() errColors=() + [ -t 1 ] && tput cnorm + isDebug && export MACOS_SYSTEM_DEBUG=true + "${tmpdir}/install.sh" "$@" + [ -t 1 ] && tput civis + popd -q } if [[ "${ZSH_EVAL_CONTEXT}" == toplevel || "${ZSH_EVAL_CONTEXT}" == cmdarg ]]; then - _DIR="${0:A:h}" - main "$@" + _DIR="${0:A:h}" + main "$@" fi diff --git a/install.sh b/install.sh index 9440d86..eeb2fe8 100755 --- a/install.sh +++ b/install.sh @@ -2,106 +2,105 @@ # vi: set ft=zsh tw=80 ts=2 runModule() { - "$@" + "$@" } function askNecessaryQuestions() { - local mod= configArgs=() - config setappname "de.astzweig.macos.system-setup" - if [ -n "${config_only}" ]; then - lop -- -d "Config only option given with value:" -d "${config_only}" - config setconfigfile "${config_only}" - elif [ -n "${config}" ]; then - config setconfigfile "${config}" - configArgs=(-x) - fi - askUserModuleQuestions ${configArgs} -c config -v moduleAnswers ${modulesToInstall} + local mod= configArgs=() + config setappname "de.astzweig.macos.system-setup" + if [ -n "${config_only}" ]; then + lop -- -d "Config only option given with value:" -d "${config_only}" + config setconfigfile "${config_only}" + elif [ -n "${config}" ]; then + config setconfigfile "${config}" + configArgs=(-x) + fi + askUserModuleQuestions ${configArgs} -c config -v moduleAnswers ${modulesToInstall} } function printModulesToInstall() { - lop -- -d 'Modules that will install are:' -d "${modulesToInstall}" - for mod in "${modulesToInstall[@]}"; do - print "${mod}" - done | abbreviatePaths - exit 0 + lop -- -d 'Modules that will install are:' -d "${modulesToInstall}" + for mod in "${modulesToInstall[@]}"; do + print "${mod}" + done | abbreviatePaths + exit 0 } function generateModuleOptions() { - local value answerKey optionKey argName - for answerKey in ${(k)moduleAnswers}; do - [[ ${answerKey} = ${mod}_* ]] || continue - optionKey="${answerKey#${mod}_}" - argName=${optionKey//_/-}; - value="${moduleAnswers[${answerKey}]}" - if [[ "${optionKey}" =~ ^[[:alpha:]]$ ]]; then - moduleOptions+=("-${argName}" "${value}") - elif [[ "${optionKey}" =~ ^[[:alpha:]][-[:alpha:]]+$ ]]; then - moduleOptions+=("--${argName}" "${value}") - else - moduleOptions+=("${argName}" "${value}") - fi - done + local value answerKey optionKey argName + for answerKey in ${(k)moduleAnswers}; do + [[ ${answerKey} = ${mod}_* ]] || continue + optionKey="${answerKey#${mod}_}" + argName=${optionKey//_/-}; + value="${moduleAnswers[${answerKey}]}" + if [[ "${optionKey}" =~ ^[[:alpha:]]$ ]]; then + moduleOptions+=("-${argName}" "${value}") + elif [[ "${optionKey}" =~ ^[[:alpha:]][-[:alpha:]]+$ ]]; then + moduleOptions+=("--${argName}" "${value}") + else + moduleOptions+=("${argName}" "${value}") + fi + done } function filterPasswordOptions() { - local opt= hide=false - for opt in ${moduleOptions}; do - [[ ${hide} = true ]] && { opt='******'; hide=false } - [[ $opt =~ ^--?.*password ]] && hide=true - filteredOptions+=($opt) - done + local opt= hide=false + for opt in ${moduleOptions}; do + [[ ${hide} = true ]] && { opt='******'; hide=false } + [[ $opt =~ ^--?.*password ]] && hide=true + filteredOptions+=($opt) + done } function installModules() { - local mod moduleOptions filteredOptions - for mod in ${modulesToInstall}; do - moduleOptions=() - filteredOptions=() - generateModuleOptions - filterPasswordOptions - [[ "${verbose}" == true ]] && moduleOptions+=(-v) - [[ -n ${logfile} ]] && moduleOptions+=(-d ${logfile}) - [[ -n ${noninteractive} ]] && moduleOptions+=(--noninteractive) - lop -- -d "Running ${mod}" -d "with ${#moduleOptions} args:" -d "${filteredOptions}" - runModule ${mod} ${moduleOptions} - done + local mod moduleOptions filteredOptions + for mod in ${modulesToInstall}; do + moduleOptions=() + filteredOptions=() + generateModuleOptions + filterPasswordOptions + [[ "${verbose}" == true ]] && moduleOptions+=(-v) + [[ -n ${logfile} ]] && moduleOptions+=(-d ${logfile}) + lop -- -d "Running ${mod}" -d "with ${#moduleOptions} args:" -d "${filteredOptions}" + runModule ${mod} ${moduleOptions} + done } function isMacOS() { - autoload is-at-least - [ "`uname -s`" = Darwin ] || return - is-at-least "10.13" "`sw_vers -productVersion 2> /dev/null`" + autoload is-at-least + [ "`uname -s`" = Darwin ] || return + is-at-least "10.13" "`sw_vers -productVersion 2> /dev/null`" } function isPlistBuddyInstalled() { - test -x /usr/libexec/PlistBuddy && return - which PlistBuddy >&! /dev/null && return + test -x /usr/libexec/PlistBuddy && return + which PlistBuddy >&! /dev/null && return } function checkPrerequisites() { - isMacOS || { lop -- -e 'This setup is only for macOS 10.13 and up.'; return 10 } - isPlistBuddyInstalled || { lop -- -e 'This setup requires PlistBuddy to be either at /usr/libexec or in any of the PATH directories.'; return 11 } + isMacOS || { lop -- -e 'This setup is only for macOS 10.13 and up.'; return 10 } + isPlistBuddyInstalled || { lop -- -e 'This setup requires PlistBuddy to be either at /usr/libexec or in any of the PATH directories.'; return 11 } } function configureTerminal() { - if [ -t 0 ]; then - traps+=("stty $(stty -g)") - stty -echo - fi - if [ -t 1 ]; then - traps+=('tput cnorm') - tput civis - export TERMINAL_CURSOR_HIDDEN=true - fi + if [ -t 0 ]; then + traps+=("stty $(stty -g)") + stty -echo + fi + if [ -t 1 ]; then + traps+=('tput cnorm') + tput civis + export TERMINAL_CURSOR_HIDDEN=true + fi } function main() { - local traps=() - configureTerminal - trap ${(j.;.)traps} INT TERM EXIT - autoloadZShLib || return - checkPrerequisites || return - eval "`docopts -f -V - -h - : "$@" <<- USAGE + local traps=() + configureTerminal + trap ${(j.;.)traps} INT TERM EXIT + autoloadZShLib || return + checkPrerequisites || return + eval "`docopts -f -V - -h - : "$@" <<- USAGE Usage: $0 [options] [-m PATH]... [...] Install all modules in module search path. If any arg is given, @@ -127,28 +126,28 @@ function main() { Copyright (C) 2022 Rezart Qelibari, Astzweig GmbH & Co. KG License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law. USAGE`" - local allModules=() modulesToInstall=() - local -A moduleAnswers - configureLogging - lop -- -d "Current working dir is: `pwd`" - lop -- -d "Called main with $# args: $*" + local allModules=() modulesToInstall=() + local -A moduleAnswers + configureLogging + lop -- -d "Current working dir is: `pwd`" + lop -- -d "Called main with $# args: $*" - [[ -n ${noninteractive} && -z ${config} ]] && { lop -- -e 'A config file must be provided in noninteractive mode.'; return 10 } + [[ -n ${noninteractive} && -z ${config} ]] && { lop -- -e 'A config file must be provided in noninteractive mode.'; return 10 } - modpath+=("${_DIR}/modules") - loadModules -v modulesToInstall ${$(echo -m):^^modpath} "${module[@]}" - [ "${list}" = true ] && printModulesToInstall + modpath+=("${_DIR}/modules") + loadModules -v modulesToInstall ${$(echo -m):^^modpath} "${module[@]}" + [ "${list}" = true ] && printModulesToInstall - askNecessaryQuestions - [ -z "${config_only}" ] || return 0 - requireRootPrivileges - installModules + askNecessaryQuestions + [ -z "${config_only}" ] || return 0 + requireRootPrivileges + installModules } if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then - _DIR="${0:A:h}" - export ASTZWEIG_MACOS_SYSTEM_LIB=${_DIR}/modules/lib.sh - export ASTZWEIG_ZSHLIB=${_DIR}/zshlib - source "${ASTZWEIG_MACOS_SYSTEM_LIB}" - main "$@" + _DIR="${0:A:h}" + export ASTZWEIG_MACOS_SYSTEM_LIB=${_DIR}/modules/lib.sh + export ASTZWEIG_ZSHLIB=${_DIR}/zshlib + source "${ASTZWEIG_MACOS_SYSTEM_LIB}" + main "$@" fi diff --git a/modules/01-system-settings.sh b/modules/01-system-settings.sh index 5d38dca..648ef7a 100755 --- a/modules/01-system-settings.sh +++ b/modules/01-system-settings.sh @@ -2,32 +2,32 @@ # vi: set ft=zsh tw=80 ts=2 function getQuestionsPrerequisites() { - cmds=( - [systemsetup]='' - ) - requireRootPrivileges + cmds=( + [systemsetup]='' + ) + requireRootPrivileges } function getExecPrerequisites() { - cmds=( - [osascript]='' - [scutil]='' - [systemsetup]='' - [nvram]='' - [pmset]='' - [defaults]='' - [/usr/libexec/ApplicationFirewall/socketfilterfw]='' - [launchctl]='' - ) + cmds=( + [osascript]='' + [scutil]='' + [systemsetup]='' + [nvram]='' + [pmset]='' + [defaults]='' + [/usr/libexec/ApplicationFirewall/socketfilterfw]='' + [launchctl]='' + ) } function getQuestions() { - local timezones - timezones="`systemsetup -listtimezones | tail -n +2 | awk '{print $1}' | paste -sd, -`" - questions=( - 'i: hostname=What shall the hostname of this host be?' - 's: timezone=What shall the timezone of this host be? # choose from:'"${timezones};" - ) + local timezones + timezones="`systemsetup -listtimezones | tail -n +2 | awk '{print $1}' | paste -sd, -`" + questions=( + 'i: hostname=What shall the hostname of this host be?' + 's: timezone=What shall the timezone of this host be? # choose from:'"${timezones};" + ) } function quitSystemPreferences() { @@ -35,93 +35,93 @@ function quitSystemPreferences() { } function setComputerName() { - scutil --set ComputerName "${hostname}" - scutil --set HostName "${hostname}" - scutil --set LocalHostName "${hostname}" - systemsetup -setcomputername "${hostname}" - systemsetup -setlocalsubnetname "${hostname}" + scutil --set ComputerName "${hostname}" + scutil --set HostName "${hostname}" + scutil --set LocalHostName "${hostname}" + systemsetup -setcomputername "${hostname}" + systemsetup -setlocalsubnetname "${hostname}" } function configureComputerHostname() { - local currentComputerName="`scutil --get ComputerName`" - if [[ "${currentComputerName}" != "${hostname}" ]]; then - lop -- -i 'Hostname of computer has not been set.' -i "Will set to ${hostname}." - indicateActivity -- 'Set computer name' setComputerName - else - lop -- -i 'Hostname of computer seems to have already been set. Skipping.' -i "Hostname: $currentComputerName" - fi + local currentComputerName="`scutil --get ComputerName`" + if [[ "${currentComputerName}" != "${hostname}" ]]; then + lop -- -i 'Hostname of computer has not been set.' -i "Will set to ${hostname}." + indicateActivity -- 'Set computer name' setComputerName + else + lop -- -i 'Hostname of computer seems to have already been set. Skipping.' -i "Hostname: $currentComputerName" + fi } function configureBasicSystem(){ - # Disable the sound effects on boot - nvram SystemAudioVolume=" " + # Disable the sound effects on boot + nvram SystemAudioVolume=" " - systemsetup -settimezone "${timezone}" >&! /dev/null - systemsetup -setusingnetworktime on >&! /dev/null - systemsetup -setnetworktimeserver 'time.apple.com' >&! /dev/null - systemsetup -setsleep never >&! /dev/null - systemsetup -setwakeonnetworkaccess off >&! /dev/null - systemsetup -setrestartfreeze on >&! /dev/null - systemsetup -f -setremotelogin off >&! /dev/null - systemsetup -setremoteappleevents off >&! /dev/null + systemsetup -settimezone "${timezone}" >&! /dev/null + systemsetup -setusingnetworktime on >&! /dev/null + systemsetup -setnetworktimeserver 'time.apple.com' >&! /dev/null + systemsetup -setsleep never >&! /dev/null + systemsetup -setwakeonnetworkaccess off >&! /dev/null + systemsetup -setrestartfreeze on >&! /dev/null + systemsetup -f -setremotelogin off >&! /dev/null + systemsetup -setremoteappleevents off >&! /dev/null } function configurePowerManagement() { - cmd=(pmset -a) - ${cmd} displaysleep 0 - ${cmd} disksleep 0 - ${cmd} sleep 0 - ${cmd} womp 0 - ${cmd} acwake 0 - ${cmd} proximitywake 0 - ${cmd} destroyfvkeyonstandby 1 - pmset -b acwake 1 - ${cmd} lidwake 1 - ${cmd} halfdim 1 - ${cmd} powernap 1 - ${cmd} hibernatemode 0 + cmd=(pmset -a) + ${cmd} displaysleep 0 + ${cmd} disksleep 0 + ${cmd} sleep 0 + ${cmd} womp 0 + ${cmd} acwake 0 + ${cmd} proximitywake 0 + ${cmd} destroyfvkeyonstandby 1 + pmset -b acwake 1 + ${cmd} lidwake 1 + ${cmd} halfdim 1 + ${cmd} powernap 1 + ${cmd} hibernatemode 0 } function configureLoginWindow() { - cmd=(defaults write '/Library/Preferences/com.apple.loginwindow') - ${cmd} DisableFDEAutoLogin -bool true - ${cmd} SHOWFULLNAME -bool true - ${cmd} AdminHostInfo -string HostName - ${cmd} GuestEnabled -bool false + cmd=(defaults write '/Library/Preferences/com.apple.loginwindow') + ${cmd} DisableFDEAutoLogin -bool true + ${cmd} SHOWFULLNAME -bool true + ${cmd} AdminHostInfo -string HostName + ${cmd} GuestEnabled -bool false } function configureMacOSFirewall() { - cmd=(/usr/libexec/ApplicationFirewall/socketfilterfw) - ${cmd} --setglobalstate on - ${cmd} --setblockall off - ${cmd} --setstealthmode on - ${cmd} --setallowsigned on - ${cmd} --setallowsignedapp on + cmd=(/usr/libexec/ApplicationFirewall/socketfilterfw) + ${cmd} --setglobalstate on + ${cmd} --setblockall off + ${cmd} --setstealthmode on + ${cmd} --setallowsigned on + ${cmd} --setallowsignedapp on } function configure_system() { - lop -y h1 -- -i 'Configure System Settings' - quitSystemPreferences - configureComputerHostname - indicateActivity -- 'Configuring systemsetup and nvram' configureBasicSystem - indicateActivity -- 'Configuring power management' configurePowerManagement - indicateActivity -- 'Configuring login window' configureLoginWindow - indicateActivity -- 'Configure global umask' launchctl config user umask 027 - indicateActivity -- 'Configure macOS firewall' configureMacOSFirewall + lop -y h1 -- -i 'Configure System Settings' + quitSystemPreferences + configureComputerHostname + indicateActivity -- 'Configuring systemsetup and nvram' configureBasicSystem + indicateActivity -- 'Configuring power management' configurePowerManagement + indicateActivity -- 'Configuring login window' configureLoginWindow + indicateActivity -- 'Configure global umask' launchctl config user umask 027 + indicateActivity -- 'Configure macOS firewall' configureMacOSFirewall } function getUsage() { - local cmdName=$1 text='' - read -r -d '' text <<- USAGE + local cmdName=$1 text='' + read -r -d '' text <<- USAGE Usage: $cmdName show-questions [ ]... $cmdName [-v] [-d FILE] --hostname NAME --timezone ZONE - + Set energy, basic network and host preferences. - + Options: - --hostname NAME Set NAME as current host's host name. - --timezone ZONE Set ZONE as current host's timezone [default: Europe/Berlin]. + --hostname NAME Set NAME as current host's host name. + --timezone ZONE Set ZONE as current host's timezone [default: Europe/Berlin]. -d FILE, --logfile FILE Print log message to logfile instead of stdout. -v, --verbose Be more verbose. ---- @@ -129,11 +129,11 @@ function getUsage() { Copyright (C) 2022 Rezart Qelibari, Astzweig GmbH & Co. KG License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law. USAGE - print -- ${text} + print -- ${text} } if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then - test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } - source "${ASTZWEIG_MACOS_SYSTEM_LIB}" - module_main $0 "$@" + test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } + source "${ASTZWEIG_MACOS_SYSTEM_LIB}" + module_main $0 "$@" fi diff --git a/modules/02-create-filevault-user.sh b/modules/02-create-filevault-user.sh index 979d86f..3ca4077 100755 --- a/modules/02-create-filevault-user.sh +++ b/modules/02-create-filevault-user.sh @@ -2,138 +2,138 @@ # vi: set ft=zsh tw=80 ts=2 function getComputerName() { - local moduleAnswer - local computerName="`scutil --get ComputerName 2> /dev/null`" - getModuleAnswerByKeyRegEx '_hostname$' && computerName=$moduleAnswer - print -- $computerName + local moduleAnswer + local computerName="`scutil --get ComputerName 2> /dev/null`" + getModuleAnswerByKeyRegEx '_hostname$' && computerName=$moduleAnswer + print -- $computerName } function getDefaultFullname() { - local computerName="`getComputerName`" - lop -- -d 'Default full name based on current computer name is:' -d "$computerName" - print "${computerName}" + local computerName="`getComputerName`" + lop -- -d 'Default full name based on current computer name is:' -d "$computerName" + print "${computerName}" } function getDefaultUsername() { - local username="`getDefaultFullname | tr '[:upper:]' '[:lower:]' | tr -C '[:alnum:]\n' '-'`" - lop -- -d 'Default username based on current computer name is:' -d "$username" - print "${username}" + local username="`getDefaultFullname | tr '[:upper:]' '[:lower:]' | tr -C '[:alnum:]\n' '-'`" + lop -- -d 'Default username based on current computer name is:' -d "$username" + print "${username}" } function isAPFSFilesystem() { - [[ $(diskutil info / | awk 'sub(/File System Personality: /,""){print $0}') = *APFS* ]] + [[ $(diskutil info / | awk 'sub(/File System Personality: /,""){print $0}') = *APFS* ]] } function getUsersWithSecureToken() { - local username uuid - for uuid in ${$(diskutil apfs listUsers / | awk '/\+\-\-/ {print $2}')}; do - username="$(dscl . -search /Users GeneratedUID ${uuid} | awk 'NR==1{print $1}')" - checkSecureTokenForUser ${username} && secureTokenUsers+=("${username}") - done + local username uuid + for uuid in ${$(diskutil apfs listUsers / | awk '/\+\-\-/ {print $2}')}; do + username="$(dscl . -search /Users GeneratedUID ${uuid} | awk 'NR==1{print $1}')" + checkSecureTokenForUser ${username} && secureTokenUsers+=("${username}") + done } function getDefaultUserPictures() { - pushd -q '/Library/User Pictures' - defaultUserPictures=("${(@f)$(find -E . -type f -iregex '.*\.(tif|png|jpeg|jpg)' | abbreviatePaths)}") - popd -q + pushd -q '/Library/User Pictures' + defaultUserPictures=("${(@f)$(find -E . -type f -iregex '.*\.(tif|png|jpeg|jpg)' | abbreviatePaths)}") + popd -q } function convertPathToDefaultPicture() { - local resolved='' - lop -- -d 'Converting path' -d "${filevault_picture}" -d 'to default picture path if necessary.' - if [ -r "${filevault_picture}" ]; then - lop -- -d 'Path seems to be a valid path already. Skipping conversion.' - return - fi - pushd -q '/Library/User Pictures' - resolved="`find "$_" -type f -path "*${filevault_picture}" 2> /dev/null`" - lop -- -d 'Resolved path is' -d "${resolved}" - popd -q - [ -n "${resolved}" -a -r "${resolved}" ] && filevault_picture="${resolved}" + local resolved='' + lop -- -d 'Converting path' -d "${filevault_picture}" -d 'to default picture path if necessary.' + if [ -r "${filevault_picture}" ]; then + lop -- -d 'Path seems to be a valid path already. Skipping conversion.' + return + fi + pushd -q '/Library/User Pictures' + resolved="`find "$_" -type f -path "*${filevault_picture}" 2> /dev/null`" + lop -- -d 'Resolved path is' -d "${resolved}" + popd -q + [ -n "${resolved}" -a -r "${resolved}" ] && filevault_picture="${resolved}" } function _isPathToPicture() { - local filevault_picture=$1 - convertPathToDefaultPicture - [ -r "${filevault_picture}" ] || { lop -- -d 'Resolved path is not a valid path. Returning.'; return 10 } - [[ "${filevault_picture:e:l}" =~ (tif|png|jpeg|jpg) ]] || return 11 + local filevault_picture=$1 + convertPathToDefaultPicture + [ -r "${filevault_picture}" ] || { lop -- -d 'Resolved path is not a valid path. Returning.'; return 10 } + [[ "${filevault_picture:e:l}" =~ (tif|png|jpeg|jpg) ]] || return 11 } function isPathToPicture() { - indicateActivity -- "Verifying $1 as picture path" _isPathToPicture $1 + indicateActivity -- "Verifying $1 as picture path" _isPathToPicture $1 } function _checkSecureTokenForUser() { - local u=$1 - sysadminctl -secureTokenStatus "${u}" 2>&1 | grep ENABLED >&! /dev/null + local u=$1 + sysadminctl -secureTokenStatus "${u}" 2>&1 | grep ENABLED >&! /dev/null } function checkSecureTokenForUser() { - local u=$1 - indicateActivity -- "Checking if user $u has a secure token set" _checkSecureTokenForUser $u + local u=$1 + indicateActivity -- "Checking if user $u has a secure token set" _checkSecureTokenForUser $u } function _checkUserPassword() { - local username=$1 password=$2 - dscl . -authonly ${username} ${password} >&! /dev/null + local username=$1 password=$2 + dscl . -authonly ${username} ${password} >&! /dev/null } function checkSecureTokenUserPassword() { - indicateActivity -- "Checking password for user ${secure_token_user_username}" _checkUserPassword ${secure_token_user_username} ${secure_token_user_password} + indicateActivity -- "Checking password for user ${secure_token_user_username}" _checkUserPassword ${secure_token_user_username} ${secure_token_user_password} } function checkFileVaultUserPassword() { - indicateActivity -- "Checking password for user ${filevault_username}" _checkUserPassword ${filevault_username} ${filevault_password} + indicateActivity -- "Checking password for user ${filevault_username}" _checkUserPassword ${filevault_username} ${filevault_password} } function _doesFileVaultUserExist() { - dscl . -list /Users | grep "${filevault_username}" >&! /dev/null + dscl . -list /Users | grep "${filevault_username}" >&! /dev/null } function doesFileVaultUserExist() { - indicateActivity -- "Checking if ${filevault_username} already exists" _doesFileVaultUserExist + indicateActivity -- "Checking if ${filevault_username} already exists" _doesFileVaultUserExist } function _createFileVaultUser() { - local un=${filevault_username} fn=${filevault_fullname} pw=${filevault_password} result= - lop -- -d 'Creating FileVault user' -d "${un}" - sysadminctl -addUser ${un} -fullName ${fn} -shell /usr/bin/false -home /var/empty -password ${pw} -picture ${filevault_picture} - result=$? - lop -- -d 'Return value of sysadminctl is ' -d "$?" - return $result + local un=${filevault_username} fn=${filevault_fullname} pw=${filevault_password} result= + lop -- -d 'Creating FileVault user' -d "${un}" + sysadminctl -addUser ${un} -fullName ${fn} -shell /usr/bin/false -home /var/empty -password ${pw} -picture ${filevault_picture} + result=$? + lop -- -d 'Return value of sysadminctl is ' -d "$?" + return $result } function createFileVaultUser() { - indicateActivity -- "Creating FileVault user ${filevault_username}" _createFileVaultUser + indicateActivity -- "Creating FileVault user ${filevault_username}" _createFileVaultUser } function _configureFileVaultUser() { - local un=${filevault_username} - dscl . -create "/Users/${un}" IsHidden 1 - chsh -s /usr/bin/false "${un}" >&! /dev/null + local un=${filevault_username} + dscl . -create "/Users/${un}" IsHidden 1 + chsh -s /usr/bin/false "${un}" >&! /dev/null } function configureFileVaultUser() { - indicateActivity -- "Configuring FileVault user ${filevault_username}" _configureFileVaultUser + indicateActivity -- "Configuring FileVault user ${filevault_username}" _configureFileVaultUser } function configureSecureToken() { - local un=${filevault_username} up=${filevault_password} - local stun=${secure_token_user_username} stup=${secure_token_user_password} - indicateActivity -- "Enable secure token for ${un}" sysadminctl -secureTokenOn "${un}" -password "${up}" -adminUser "${stun}" -adminPassword "${stup}" + local un=${filevault_username} up=${filevault_password} + local stun=${secure_token_user_username} stup=${secure_token_user_password} + indicateActivity -- "Enable secure token for ${un}" sysadminctl -secureTokenOn "${un}" -password "${up}" -adminUser "${stun}" -adminPassword "${stup}" } function canUserUnlockDisk() { - local username=$1 - for fdeuser in ${(f)"$(fdesetup list | cut -d',' -f1)"}; do - [[ ${fdeuser} = ${username} ]] && return - done - return 1 + local username=$1 + for fdeuser in ${(f)"$(fdesetup list | cut -d',' -f1)"}; do + [[ ${fdeuser} = ${username} ]] && return + done + return 1 } function getFDESetupXMLForUser() { - local username="${1}" password="${2}" - cat <<- XML + local username="${1}" password="${2}" + cat <<- XML @@ -148,157 +148,157 @@ function getFDESetupXMLForUser() { } function _enableFileVaultForSecureTokenUser() { - local username="${1}" password="${2}" - getFDESetupXMLForUser "${username}" "${password}" | fdesetup enable -inputplist + local username="${1}" password="${2}" + getFDESetupXMLForUser "${username}" "${password}" | fdesetup enable -inputplist } function enableFileVaultForSecureTokenUser() { - fdesetup isactive >&! /dev/null && return - indicateActivity -- "Enable FileVault for secure token" _enableFileVaultForSecureTokenUser ${secure_token_user_username} ${secure_token_user_password} + fdesetup isactive >&! /dev/null && return + indicateActivity -- "Enable FileVault for secure token" _enableFileVaultForSecureTokenUser ${secure_token_user_username} ${secure_token_user_password} } function _allowUserToUnlockDisk() { - local username="${1}" password="${2}" - getFDESetupXMLForUser ${username} ${password} | fdesetup add -inputplist + local username="${1}" password="${2}" + getFDESetupXMLForUser ${username} ${password} | fdesetup add -inputplist } function allowFileVaultUserToUnlockDisk() { - indicateActivity -- "Allow FileVault user to unlock disk" _allowUserToUnlockDisk ${filevault_username} ${filevault_password} + indicateActivity -- "Allow FileVault user to unlock disk" _allowUserToUnlockDisk ${filevault_username} ${filevault_password} } function _allowOnlyFileVaultUserToUnlock() { - local fdeuser - for fdeuser in ${(f)"$(fdesetup list | cut -d',' -f1)"}; do - [[ ${fdeuser} != ${filevault_username} ]] && fdesetup remove -user "${fdeuser}" - done - return 0 + local fdeuser + for fdeuser in ${(f)"$(fdesetup list | cut -d',' -f1)"}; do + [[ ${fdeuser} != ${filevault_username} ]] && fdesetup remove -user "${fdeuser}" + done + return 0 } function allowOnlyFileVaultUserToUnlock() { - indicateActivity -- "Disallow everyone else from unlocking disk" _allowOnlyFileVaultUserToUnlock + indicateActivity -- "Disallow everyone else from unlocking disk" _allowOnlyFileVaultUserToUnlock } function configure_system() { - lop -y h1 -- -i 'Setup FileVault System' - checkSecureTokenForUser "${secure_token_user_username}" || { lop -- -e 'The provided secure token user has no secure token.'; return 10 } - checkSecureTokenUserPassword || { lop -- -e 'The secure token user password is incorrect.'; return 11 } - indicateActivity -- "Resolving path of picture ${filevault_picture}" convertPathToDefaultPicture - isPathToPicture "${filevault_picture}" || { lop -- -e 'The provided FileVault user picture is not a valid path to a TIF, PNG or JPEG file.'; return 12 } + lop -y h1 -- -i 'Setup FileVault System' + checkSecureTokenForUser "${secure_token_user_username}" || { lop -- -e 'The provided secure token user has no secure token.'; return 10 } + checkSecureTokenUserPassword || { lop -- -e 'The secure token user password is incorrect.'; return 11 } + indicateActivity -- "Resolving path of picture ${filevault_picture}" convertPathToDefaultPicture + isPathToPicture "${filevault_picture}" || { lop -- -e 'The provided FileVault user picture is not a valid path to a TIF, PNG or JPEG file.'; return 12 } - if doesFileVaultUserExist; then - checkFileVaultUserPassword || { lop -- -e 'The FileVault user password is incorrect.'; return 13 } - else - createFileVaultUser || { lop -- -e 'Was not able to create FileVault user.'; return 14 } - fi - configureFileVaultUser || { lop -- -e 'Could not configure FileVault user.'; return 15 } - enableFileVaultForSecureTokenUser || { lop -- -e 'Could not enable FileVault for secure token user.'; return 16 } - checkSecureTokenForUser "${filevault_username}" || configureSecureToken || { lop -- -e 'Could not configure secure token for FileVault user.'; return 17 } - canUserUnlockDisk ${filevault_username} || allowFileVaultUserToUnlockDisk || { lop -- -e 'Was not able to allow FileVault user to unlock disk.'; return 18 } - allowOnlyFileVaultUserToUnlock "${filevault_username}" || { lop -- -e 'Was not able to deactivate all other user from unlocking disk.'; return 19 } - indicateActivity -- 'Update APFS preboot volume' diskutil apfs updatePreboot / || { lop -- -e 'Was not able to update APFS preboot volume.'; return 20 } + if doesFileVaultUserExist; then + checkFileVaultUserPassword || { lop -- -e 'The FileVault user password is incorrect.'; return 13 } + else + createFileVaultUser || { lop -- -e 'Was not able to create FileVault user.'; return 14 } + fi + configureFileVaultUser || { lop -- -e 'Could not configure FileVault user.'; return 15 } + enableFileVaultForSecureTokenUser || { lop -- -e 'Could not enable FileVault for secure token user.'; return 16 } + checkSecureTokenForUser "${filevault_username}" || configureSecureToken || { lop -- -e 'Could not configure secure token for FileVault user.'; return 17 } + canUserUnlockDisk ${filevault_username} || allowFileVaultUserToUnlockDisk || { lop -- -e 'Was not able to allow FileVault user to unlock disk.'; return 18 } + allowOnlyFileVaultUserToUnlock "${filevault_username}" || { lop -- -e 'Was not able to deactivate all other user from unlocking disk.'; return 19 } + indicateActivity -- 'Update APFS preboot volume' diskutil apfs updatePreboot / || { lop -- -e 'Was not able to update APFS preboot volume.'; return 20 } } function getHelpPrerequisites() { - cmds=( - [tr]='' - [scutil]='' - ) - addDocoptsToCmds + cmds=( + [tr]='' + [scutil]='' + ) + addDocoptsToCmds } function getQuestionsPrerequisites() { - cmds=( - [find]='' - [dscl]='' - [dseditgroup]='' - [awk]='' - [diskutil]='' - [sysadminctl]='' - ) - isAPFSFilesystem || { lop -- -e 'This module requires an APFS filesystem.'; return 10 } + cmds=( + [find]='' + [dscl]='' + [dseditgroup]='' + [awk]='' + [diskutil]='' + [sysadminctl]='' + ) + isAPFSFilesystem || { lop -- -e 'This module requires an APFS filesystem.'; return 10 } } function getExecPrerequisites() { - cmds=( - [cut]='' - [cat]='' - [fdesetup]='' - [base64]='' - [dsimport]='' - ) - requireRootPrivileges + cmds=( + [cut]='' + [cat]='' + [fdesetup]='' + [base64]='' + [dsimport]='' + ) + requireRootPrivileges } function getQuestions() { - local secureTokenUsers=() defaultUserPictures=() - local defaultUsername="`getDefaultUsername`" defaultFullname="`getDefaultFullname`" - getUsersWithSecureToken - getDefaultUserPictures - local defaultUsernameHint= defaultFullnameHint= - [ -n "${defaultUsername}" ] && defaultUsernameHint="default:${defaultUsername};" - [ -n "${defaultFullname}" ] && defaultFullnameHint="default:${defaultFullname};" - questions=( - 'i: filevault-fullname=What shall the FileVault user'\''s full name be? # '"${defaultFullnameHint}" - 'i: filevault-username=What shall the FileVault user'\''s username be? # '"${defaultUsernameHint}" - 'p: filevault-password=What shall the FileVault user'\''s password be?' - 's: filevault-picture=Select a picture for FileVault user or enter the path to your own picture # validator:'"${cmdPath}"',is-picture;choose from:'"${(j.,.)defaultUserPictures};" - 's: secure-token-user-username=Which user with a secure token shall be used? # choose from:'"${(j.,.)secureTokenUsers};" - 'p: secure-token-user-password=What is the secure token user'\''s password?' - ) + local secureTokenUsers=() defaultUserPictures=() + local defaultUsername="`getDefaultUsername`" defaultFullname="`getDefaultFullname`" + getUsersWithSecureToken + getDefaultUserPictures + local defaultUsernameHint= defaultFullnameHint= + [ -n "${defaultUsername}" ] && defaultUsernameHint="default:${defaultUsername};" + [ -n "${defaultFullname}" ] && defaultFullnameHint="default:${defaultFullname};" + questions=( + 'i: filevault-fullname=What shall the FileVault user'\''s full name be? # '"${defaultFullnameHint}" + 'i: filevault-username=What shall the FileVault user'\''s username be? # '"${defaultUsernameHint}" + 'p: filevault-password=What shall the FileVault user'\''s password be?' + 's: filevault-picture=Select a picture for FileVault user or enter the path to your own picture # validator:'"${cmdPath}"',is-picture;choose from:'"${(j.,.)defaultUserPictures};" + 's: secure-token-user-username=Which user with a secure token shall be used? # choose from:'"${(j.,.)secureTokenUsers};" + 'p: secure-token-user-password=What is the secure token user'\''s password?' + ) } function preQuestionHook() { - if [[ "${is_picture}" = true ]]; then - isPathToPicture ${pathstr} - exit $? - fi + if [[ "${is_picture}" = true ]]; then + isPathToPicture ${pathstr} + exit $? + fi } function getUsage() { - local cmdName=$1 text='' varname= - local defaultUsername="`getDefaultUsername`" defaultFullname="`getDefaultFullname`" - for varname in defaultUsername defaultFullname; do - local ${varname}Str= - [ -n "${(P)varname}" ] && local ${varname}Str=" [default: ${(P)varname}]" - done - read -r -d '' text <<- USAGE + local cmdName=$1 text='' varname= + local defaultUsername="`getDefaultUsername`" defaultFullname="`getDefaultFullname`" + for varname in defaultUsername defaultFullname; do + local ${varname}Str= + [ -n "${(P)varname}" ] && local ${varname}Str=" [default: ${(P)varname}]" + done + read -r -d '' text <<- USAGE Usage: $cmdName show-questions [ ]... $cmdName is-picture $cmdName [-v] [-d FILE] --filevault-fullname NAME --filevault-username NAME --filevault-password PASSWORD --filevault-picture PATH_TO_PIC --secure-token-user-username NAME --secure-token-user-password PASSWORD - + Create a designated FileVault user who may not login to the system but is the only one able to unlock the disk. That way a secure password can be used to unlock the disk as opposed to macOS standard, where each user is allowed to unlock the disk with his password that may or may not be secure (in terms of length and randomness). - + Options: - --filevault-fullname NAME Full name of the designated FileVault user. An - existing FileVault user will be renamed to that - name${defaultFullnameStr}. - --filevault-username NAME Username of the designated FileVault user. An - existing FileVault user will be renamed to that - name${defaultUsernameStr}. - --filevault-password PASSWORD Password of the designated FileVault user. The password - an existing FileVault user will not be changed. - --filevault-picture PATH_TO_PIC The path to the picture that shall be made the FileVault - user picture. The picture of an existing FileVault user - will be updated. - --secure-token-user-username NAME The username of an user with a secure token. - --secure-token-user-password PASSWORD The password of the secure token user. - -d FILE, --logfile FILE Print log message to logfile instead of stdout. - -v, --verbose Be more verbose. + --filevault-fullname NAME Full name of the designated FileVault user. An + existing FileVault user will be renamed to that + name ${defaultFullnameStr}. + --filevault-username NAME Username of the designated FileVault user. An + existing FileVault user will be renamed to that + name ${defaultUsernameStr}. + --filevault-password PASSWORD Password of the designated FileVault user. The password + an existing FileVault user will not be changed. + --filevault-picture PATH_TO_PIC The path to the picture that shall be made the FileVault + user picture. The picture of an existing FileVault user + will be updated. + --secure-token-user-username NAME The username of an user with a secure token. + --secure-token-user-password PASSWORD The password of the secure token user. + -d FILE, --logfile FILE Print log message to logfile instead of stdout. + -v, --verbose Be more verbose. ---- $cmdName 0.1.0 Copyright (C) 2022 Rezart Qelibari, Astzweig GmbH & Co. KG License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law. USAGE - print -- ${text} + print -- ${text} } if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then - test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } - source "${ASTZWEIG_MACOS_SYSTEM_LIB}" - module_main $0 "$@" + test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } + source "${ASTZWEIG_MACOS_SYSTEM_LIB}" + module_main $0 "$@" fi diff --git a/modules/03-install-brew.sh b/modules/03-install-brew.sh index 9751e04..ba8f468 100755 --- a/modules/03-install-brew.sh +++ b/modules/03-install-brew.sh @@ -5,14 +5,14 @@ export HOMEBREW_NO_ANALYTICS_THIS_RUN=1 export HOMEBREW_NO_ANALYTICS_MESSAGE_OUTPUT=1 function doesUserExist() { - local username=$1 - dscl . -list /Users | grep "^${username}$" 2> /dev/null >&2 + local username=$1 + dscl . -list /Users | grep "^${username}$" 2> /dev/null >&2 } function runAsUser() { - local username=$1 - shift - sudo -Hu "${username}" "${@}" + local username=$1 + shift + sudo -Hu "${username}" "${@}" } function runAsHomebrewUser() { @@ -20,95 +20,95 @@ function runAsHomebrewUser() { } function ensureUserIsInAdminGroup() { - local username=$1 - dseditgroup -o edit -a "${username}" -t user admin + local username=$1 + dseditgroup -o edit -a "${username}" -t user admin } function ensureUserCanRunPasswordlessSudo() { - local username=$1 - local sudoersFile="/etc/sudoers.d/no-auth-sudo-for-${username}" - [[ -f ${sudoersFile} ]] && return - cat <<- SUDOERS > "${sudoersFile}" + local username=$1 + local sudoersFile="/etc/sudoers.d/no-auth-sudo-for-${username}" + [[ -f ${sudoersFile} ]] && return + cat <<- SUDOERS > "${sudoersFile}" Defaults:${username} !authenticate SUDOERS - chown root:wheel "${sudoersFile}" || return 10 - chmod u=rw,g=r,o= "${sudoersFile}" || return 20 + chown root:wheel "${sudoersFile}" || return 10 + chmod u=rw,g=r,o= "${sudoersFile}" || return 20 } function getFirstFreeRoleAccountID() { - dscl . -list '/Users' UniqueID | grep '_.*' | sort -n -k2 | awk -v i=401 '$2>200 && $2<401 {if(i < $2) { print i; nextfile} else i=$2+1;}' + dscl . -list '/Users' UniqueID | grep '_.*' | sort -n -k2 | awk -v i=401 '$2>200 && $2<401 {if(i < $2) { print i; nextfile} else i=$2+1;}' } function createHomebrewUser() { - local username=$1 - local userID=`getFirstFreeRoleAccountID` - sysadminctl -addUser "${username}" -fullName "Homebrew User" -shell /usr/bin/false -home '/var/empty' -roleAccount -UID "${userID}" > /dev/null 2>&1 + local username=$1 + local userID=`getFirstFreeRoleAccountID` + sysadminctl -addUser "${username}" -fullName "Homebrew User" -shell /usr/bin/false -home '/var/empty' -roleAccount -UID "${userID}" > /dev/null 2>&1 } function createHomebrewUserIfNeccessary() { - if ! doesUserExist ${homebrew_username}; then - lop -y body:warn -y body -- -i "No Homebrew user named ${homebrew_username} found." -i 'Will create user.' - indicateActivity 'Creating Homebrew user' createHomebrewUser ${homebrew_username} || return 10 - else - lop -y body:note -y body -- -i "Homebrew user named ${homebrew_username} already exists." -i 'Skipping.' - fi + if ! doesUserExist ${homebrew_username}; then + lop -y body:warn -y body -- -i "No Homebrew user named ${homebrew_username} found." -i 'Will create user.' + indicateActivity 'Creating Homebrew user' createHomebrewUser ${homebrew_username} || return 10 + else + lop -y body:note -y body -- -i "Homebrew user named ${homebrew_username} already exists." -i 'Skipping.' + fi } function ensureDirectoryWithDefaultMod() { - local itemPath=${1} - mkdir -p ${itemPath} - ensureHomebrewOwnershipAndPermission ${itemPath} + local itemPath=${1} + mkdir -p ${itemPath} + ensureHomebrewOwnershipAndPermission ${itemPath} } function ensureHomebrewOwnershipAndPermission() { - local itemPath=${1} - local username=${homebrew_username} - [[ -f ${itemPath} || -d ${itemPath} ]] || return 1 - chown -R "${username}:admin" ${itemPath} - chmod u=rwx,go=rx ${itemPath} + local itemPath=${1} + local username=${homebrew_username} + [[ -f ${itemPath} || -d ${itemPath} ]] || return 1 + chown -R "${username}:admin" ${itemPath} + chmod u=rwx,go=rx ${itemPath} } function ensureHomebrewCacheDirectory() { - ensureDirectoryWithDefaultMod "${homebrew_cache}" - runAsHomebrewUser touch "${homebrew_cache}/.cleaned" + ensureDirectoryWithDefaultMod "${homebrew_cache}" + runAsHomebrewUser touch "${homebrew_cache}/.cleaned" } function ensureHomebrewLogDirectory() { - ensureDirectoryWithDefaultMod ${homebrew_log} + ensureDirectoryWithDefaultMod ${homebrew_log} } function ensureLocalBinFolder() { - local folder="/usr/local/bin" - if [ ! -d "${folder}" ]; then - mkdir -p "${folder}" 2> /dev/null || { - lop -- -e 'Could not create directory' -e $folder - return 10 - } - chown root:admin "${folder}" - chmod ug=rwx,o=rx "${folder}" - fi + local folder="/usr/local/bin" + if [ ! -d "${folder}" ]; then + mkdir -p "${folder}" 2> /dev/null || { + lop -- -e 'Could not create directory' -e $folder + return 10 + } + chown root:admin "${folder}" + chmod ug=rwx,o=rx "${folder}" + fi } function getHomebrewRepositoryPath() { - local uname_machine=$(/usr/bin/uname -m) - if [[ ${uname_machine} == "arm64" ]]; then - print -- "/opt/homebrew" - else - print "/usr/local/Homebrew" - fi + local uname_machine=$(/usr/bin/uname -m) + if [[ ${uname_machine} == "arm64" ]]; then + print -- "/opt/homebrew" + else + print "/usr/local/Homebrew" + fi } function createBrewCallerScript() { - ensureLocalBinFolder - local username=${homebrew_username} - local brewCallerPath="/usr/local/bin/brew" - [ -f "${brewCallerPath}" ] && rm "${brewCallerPath}" - cat <<- BREWCALLER > ${brewCallerPath} + ensureLocalBinFolder + local username=${homebrew_username} + local brewCallerPath="/usr/local/bin/brew" + [ -f "${brewCallerPath}" ] && rm "${brewCallerPath}" + cat <<- BREWCALLER > ${brewCallerPath} #!/usr/bin/env zsh if [ "\$(id -un)" != "${username}" ]; then - echo 'brew will be run as ${username} user.' >&2 - sudo -E -u "${username}" "\$0" "\$@" - exit \$? + echo 'brew will be run as ${username} user.' >&2 + sudo -E -u "${username}" "\$0" "\$@" + exit \$? fi export HOMEBREW_CACHE="${homebrew_cache}" export HOMEBREW_LOGS="${homebrew_log}" @@ -120,109 +120,109 @@ function createBrewCallerScript() { umask 002 "$(getHomebrewRepositoryPath)/bin/brew" "\$@" BREWCALLER - chown ${username}:admin ${brewCallerPath} - chmod ug+x,o-x ${brewCallerPath} + chown ${username}:admin ${brewCallerPath} + chmod ug+x,o-x ${brewCallerPath} } function installHomebrewCore() { - export NONINTERACTIVE=1 - [ ! -d $(getHomebrewRepositoryPath) ] || return - sudo --preserve-env=NONINTERACTIVE -u "${homebrew_username}" /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - [ -d $(getHomebrewRepositoryPath) ] + export NONINTERACTIVE=1 + [ ! -d $(getHomebrewRepositoryPath) ] || return + sudo --preserve-env=NONINTERACTIVE -u "${homebrew_username}" /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + [ -d $(getHomebrewRepositoryPath) ] } function createLaunchDaemonsPlist() { - local username=${homebrew_username} - local launcherName="de.astzweig.macos.launchdaemons.$1" - local launcherPath="/Library/LaunchDaemons/${launcherName}.plist" - [[ -f $launcherPath ]] && return - local brewCommand="$2" - cat <<- LAUNCHDPLIST > ${launcherPath} - + local username=${homebrew_username} + local launcherName="de.astzweig.macos.launchdaemons.$1" + local launcherPath="/Library/LaunchDaemons/${launcherName}.plist" + [[ -f $launcherPath ]] && return + local brewCommand="$2" + cat <<- LAUNCHDPLIST > ${launcherPath} + - Label - ${launcherName} - Program - /usr/local/bin/brew - ProgramArguments - - ${brewCommand} - - StartInterval - 1800 - UserName - ${username} - GroupName - admin - Umask - 2 + Label + ${launcherName} + Program + /usr/local/bin/brew + ProgramArguments + + ${brewCommand} + + StartInterval + 1800 + UserName + ${username} + GroupName + admin + Umask + 2 " LAUNCHDPLIST - chown root:wheel ${launcherPath} - chmod u=rw,go=r ${launcherPath} - launchctl bootstrap system ${launcherPath} + chown root:wheel ${launcherPath} + chmod u=rw,go=r ${launcherPath} + launchctl bootstrap system ${launcherPath} } function installHomebrewUpdater() { - createLaunchDaemonsPlist brew-updater update - createLaunchDaemonsPlist brew-upgrader upgrade - return + createLaunchDaemonsPlist brew-updater update + createLaunchDaemonsPlist brew-upgrader upgrade + return } function configure_system() { - lop -y h1 -- -i 'Install System Homebrew' - createHomebrewUserIfNeccessary || return 10 - indicateActivity 'Ensure Homebrew user is in admin group' ensureUserIsInAdminGroup ${homebrew_username} || return 11 - indicateActivity 'Ensure Homebrew user can run passwordless sudo' ensureUserCanRunPasswordlessSudo ${homebrew_username} || return 12 - ensureHomebrewCacheDirectory || return 13 - ensureHomebrewLogDirectory || return 14 - indicateActivity 'Install Homebrew core' installHomebrewCore || return 15 - indicateActivity 'Create brew caller script' createBrewCallerScript || return 16 - indicateActivity 'Install Homebrew updater' installHomebrewUpdater || return 17 + lop -y h1 -- -i 'Install System Homebrew' + createHomebrewUserIfNeccessary || return 10 + indicateActivity 'Ensure Homebrew user is in admin group' ensureUserIsInAdminGroup ${homebrew_username} || return 11 + indicateActivity 'Ensure Homebrew user can run passwordless sudo' ensureUserCanRunPasswordlessSudo ${homebrew_username} || return 12 + ensureHomebrewCacheDirectory || return 13 + ensureHomebrewLogDirectory || return 14 + indicateActivity 'Install Homebrew core' installHomebrewCore || return 15 + indicateActivity 'Create brew caller script' createBrewCallerScript || return 16 + indicateActivity 'Install Homebrew updater' installHomebrewUpdater || return 17 } function getExecPrerequisites() { - cmds=( - [dscl]='' - [dseditgroup]='' - [chown]='' - [chmod]='' - [sudo]='' - [grep]='' - [git]='' - [sort]='' - [awk]='' - [launchctl]='' - [sysadminctl]='' - ) - requireRootPrivileges + cmds=( + [dscl]='' + [dseditgroup]='' + [chown]='' + [chmod]='' + [sudo]='' + [grep]='' + [git]='' + [sort]='' + [awk]='' + [launchctl]='' + [sysadminctl]='' + ) + requireRootPrivileges } function getDefaultHomebrewUsername() { - print -- _homebrew + print -- _homebrew } function getDefaultHomebrewCachePath() { - print -- /Library/Caches/Homebrew + print -- /Library/Caches/Homebrew } function getDefaultHomebrewLogPath() { - print -- /var/log/Homebrew + print -- /var/log/Homebrew } function getQuestions() { - questions=( - 'i: homebrew-username=What shall the Homebrew user'\''s username be? # default:'"$(getDefaultHomebrewUsername)" - 'i: homebrew-cache=What shall the Homebrew cache directory be? # default:'"$(getDefaultHomebrewCachePath)" - 'i: homebrew-log=What shall the Homebrew log directory be? # default:'"$(getDefaultHomebrewLogPath)" - ) + questions=( + 'i: homebrew-username=What shall the Homebrew user'\''s username be? # default:'"$(getDefaultHomebrewUsername)" + 'i: homebrew-cache=What shall the Homebrew cache directory be? # default:'"$(getDefaultHomebrewCachePath)" + 'i: homebrew-log=What shall the Homebrew log directory be? # default:'"$(getDefaultHomebrewLogPath)" + ) } function getUsage() { - read -r -d '' text <<- USAGE + read -r -d '' text <<- USAGE Usage: $cmdName show-questions [ ]... $cmdName [-v] [-d FILE] --homebrew-username NAME --homebrew-cache PATH --homebrew-log PATH @@ -232,24 +232,24 @@ function getUsage() { given PREFIX and make the new Homebrew user the owner of that. Options: - --homebrew-cache PATH Path to folder that shall be used as the - cache for Homebrew [default: $(getDefaultHomebrewCachePath)]. - --homebrew-log PATH Path to folder that shall be used as the log - directory for Homebrew [default: $(getDefaultHomebrewLogPath)]. - --homebrew-username NAME Username of the designated Homebrew user. - [default: $(getDefaultHomebrewUsername)]. - -d FILE, --logfile FILE Print log message to logfile instead of stdout. - -v, --verbose Be more verbose. + --homebrew-cache PATH Path to folder that shall be used as the + cache for Homebrew [default: $(getDefaultHomebrewCachePath)]. + --homebrew-log PATH Path to folder that shall be used as the log + directory for Homebrew [default: $(getDefaultHomebrewLogPath)]. + --homebrew-username NAME Username of the designated Homebrew user. + [default: $(getDefaultHomebrewUsername)]. + -d FILE, --logfile FILE Print log message to logfile instead of stdout. + -v, --verbose Be more verbose. ---- $cmdName 0.1.0 Copyright (C) 2022 Rezart Qelibari, Astzweig GmbH & Co. KG License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law. USAGE - print -- ${text} + print -- ${text} } if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then - test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } - source "${ASTZWEIG_MACOS_SYSTEM_LIB}" - module_main $0 "$@" + test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } + source "${ASTZWEIG_MACOS_SYSTEM_LIB}" + module_main $0 "$@" fi diff --git a/modules/04-install-brew-apps.sh b/modules/04-install-brew-apps.sh index 53d3ae9..cfd3ace 100755 --- a/modules/04-install-brew-apps.sh +++ b/modules/04-install-brew-apps.sh @@ -2,89 +2,89 @@ # vi: set ft=zsh tw=80 ts=2 function brewInstall() { - local identifier="$1" - local cask="${2:+--cask}" - indicateActivity -- "Installing ${identifier}${cask:+ (Cask)}" ${homebrew_path} install -q ${cask} ${identifier} + local identifier="$1" + local cask="${2:+--cask}" + indicateActivity -- "Installing ${identifier}${cask:+ (Cask)}" ${homebrew_path} install -q ${cask} ${identifier} } function installCask() { - brewInstall $1 cask + brewInstall $1 cask } function installBrew() { - brewInstall $1 + brewInstall $1 } function installCasks() { - lop -y body:h1 -- -i 'Installing Homebrew casks' - if ! isDebug; then - installCask sketch - installCask nova - installCask transmit - installCask automattic-texts - installCask synology-drive - installCask sf-symbols - installCask prizmo - fi + lop -y body:h1 -- -i 'Installing Homebrew casks' + if ! isDebug; then + installCask sketch + installCask nova + installCask transmit + installCask automattic-texts + installCask synology-drive + installCask sf-symbols + installCask prizmo + fi } function installFonts() { } function installBrews() { - lop -y body:h1 -- -i 'Installing Homebrew formulas' - installBrew mas - if ! isDebug; then - installBrew python - installBrew rcm - installBrew php - installBrew composer - installBrew curl - installBrew exiftool - installBrew ffmpeg - installBrew gnupg - installBrew node - installBrew nmap - installBrew tree - fi + lop -y body:h1 -- -i 'Installing Homebrew formulas' + installBrew mas + if ! isDebug; then + installBrew python + installBrew rcm + installBrew php + installBrew composer + installBrew curl + installBrew exiftool + installBrew ffmpeg + installBrew gnupg + installBrew node + installBrew nmap + installBrew tree + fi } function configure_system() { - lop -y h1 -- -i 'Install Homebrew Applications' - pushd -q / - installBrews - installCasks - installFonts - popd -q + lop -y h1 -- -i 'Install Homebrew Applications' + pushd -q / + installBrews + installCasks + installFonts + popd -q } function getExecPrerequisites() { - cmds=( - [brew]='' - [find]='' - [head]='' - [installer]='' - [hdiutil]='' - ) - id -nG | grep admin >&! /dev/null || { lop -- -e 'This module requires the user to be in admin group. Please run again as either root or an admin user.'; return 11 } - checkCommands + cmds=( + [brew]='' + [find]='' + [head]='' + [installer]='' + [hdiutil]='' + ) + id -nG | grep admin >&! /dev/null || { lop -- -e 'This module requires the user to be in admin group. Please run again as either root or an admin user.'; return 11 } + checkCommands } function getDefaultHomebrewPath() { - local moduleAnswer - local hbpath=`whence -p brew` - getModuleAnswerByKeyRegEx '_homebrew-prefix$' && hbpath=$moduleAnswer/bin/brew - print -- ${hbpath} + local moduleAnswer + local hbpath=`whence -p brew` + getModuleAnswerByKeyRegEx '_homebrew-prefix$' && hbpath=$moduleAnswer/bin/brew + print -- ${hbpath} } function getQuestions() { - questions=( - 'i: homebrew-path=Which Homebrew binary shall be used? # default:'"$(getDefaultHomebrewPath)" - ) + questions=( + 'i: homebrew-path=Which Homebrew binary shall be used? # default:'"$(getDefaultHomebrewPath)" + ) } function getUsage() { - read -r -d '' text <<- USAGE + read -r -d '' text <<- USAGE Usage: $cmdName show-questions [ ]... $cmdName [-v] [-d FILE] --homebrew-path PATH @@ -92,19 +92,19 @@ function getUsage() { Install cli tools, macOS apps and fonts via Homebrew. Options: - --homebrew-path PATH Path to Homebrew binary [default: $(getDefaultHomebrewPath)]. - -d FILE, --logfile FILE Print log message to logfile instead of stdout. - -v, --verbose Be more verbose. + --homebrew-path PATH Path to Homebrew binary [default: $(getDefaultHomebrewPath)]. + -d FILE, --logfile FILE Print log message to logfile instead of stdout. + -v, --verbose Be more verbose. ---- $cmdName 0.1.0 Copyright (C) 2022 Rezart Qelibari, Astzweig GmbH & Co. KG License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law. USAGE - print -- ${text} + print -- ${text} } if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then - test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } - source "${ASTZWEIG_MACOS_SYSTEM_LIB}" - module_main $0 "$@" + test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } + source "${ASTZWEIG_MACOS_SYSTEM_LIB}" + module_main $0 "$@" fi diff --git a/modules/05-install-remap-keys.sh b/modules/05-install-remap-keys.sh index d3939b2..677349f 100755 --- a/modules/05-install-remap-keys.sh +++ b/modules/05-install-remap-keys.sh @@ -2,166 +2,166 @@ # vi: set ft=zsh tw=80 ts=2 function ensureRightAccess() { - local filesystemItem="$1" - chown root:wheel ${filesystemItem} - chmod ugo=rx ${filesystemItem} + local filesystemItem="$1" + chown root:wheel ${filesystemItem} + chmod ugo=rx ${filesystemItem} } function getDataForMicrosoftKeyboard() { - local name="$1" - [ "$name" = "ProductID" ] && echo '0x7a5' - [ "$name" = "VendorID" ] && echo '0x45e' - [ "$name" = "LaunchdServiceName" ] && echo 'de.astzweig.macos.launchdaemons.microsoft-keymapper' - [ "$name" = "BinaryName" ] && echo 'remap-keys-microsoft' - [ "$name" = "KeyMappings" ] && cat <<- KEYMAPPINGS - {"HIDKeyboardModifierMappingSrc": 0x700000065, "HIDKeyboardModifierMappingDst": 0x7000000e7}, - {"HIDKeyboardModifierMappingSrc": 0x7000000e3, "HIDKeyboardModifierMappingDst": 0x7000000e2}, - {"HIDKeyboardModifierMappingSrc": 0x7000000e2, "HIDKeyboardModifierMappingDst": 0x7000000e3} + local name="$1" + [ "$name" = "ProductID" ] && echo '0x7a5' + [ "$name" = "VendorID" ] && echo '0x45e' + [ "$name" = "LaunchdServiceName" ] && echo 'de.astzweig.macos.launchdaemons.microsoft-keymapper' + [ "$name" = "BinaryName" ] && echo 'remap-keys-microsoft' + [ "$name" = "KeyMappings" ] && cat <<- KEYMAPPINGS + {"HIDKeyboardModifierMappingSrc": 0x700000065, "HIDKeyboardModifierMappingDst": 0x7000000e7}, + {"HIDKeyboardModifierMappingSrc": 0x7000000e3, "HIDKeyboardModifierMappingDst": 0x7000000e2}, + {"HIDKeyboardModifierMappingSrc": 0x7000000e2, "HIDKeyboardModifierMappingDst": 0x7000000e3} KEYMAPPINGS } function getDataForLogitechKeyboard() { - local name="$1" - [ "$name" = "ProductID" ] && echo '0xc52b' - [ "$name" = "VendorID" ] && echo '0x46d' - [ "$name" = "LaunchdServiceName" ] && echo 'de.astzweig.macos.launchdaemons.logitech-keymapper' - [ "$name" = "BinaryName" ] && echo 'remap-keys-logitech' - [ "$name" = "KeyMappings" ] && cat <<- KEYMAPPINGS - {"HIDKeyboardModifierMappingSrc": 0x7000000e6, "HIDKeyboardModifierMappingDst": 0x7000000e7}, - {"HIDKeyboardModifierMappingSrc": 0x7000000e7, "HIDKeyboardModifierMappingDst": 0x7000000e6} + local name="$1" + [ "$name" = "ProductID" ] && echo '0xc52b' + [ "$name" = "VendorID" ] && echo '0x46d' + [ "$name" = "LaunchdServiceName" ] && echo 'de.astzweig.macos.launchdaemons.logitech-keymapper' + [ "$name" = "BinaryName" ] && echo 'remap-keys-logitech' + [ "$name" = "KeyMappings" ] && cat <<- KEYMAPPINGS + {"HIDKeyboardModifierMappingSrc": 0x7000000e6, "HIDKeyboardModifierMappingDst": 0x7000000e7}, + {"HIDKeyboardModifierMappingSrc": 0x7000000e7, "HIDKeyboardModifierMappingDst": 0x7000000e6} KEYMAPPINGS } function createXPCConsumer() { - [[ -x ${xpcConsumerPath} ]] && return - clang -framework Foundation -x objective-c -o ${xpcConsumerPath} - <<- BINARY + [[ -x ${xpcConsumerPath} ]] && return + clang -framework Foundation -x objective-c -o ${xpcConsumerPath} - <<- BINARY #import #include int main(int argc, const char * argv[]) { - @autoreleasepool { - dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); - xpc_set_event_stream_handler("com.apple.iokit.matching", NULL, ^(xpc_object_t _Nonnull object) { - const char *event = xpc_dictionary_get_string(object, XPC_EVENT_KEY_NAME); - NSLog(@"%s", event); - dispatch_semaphore_signal(semaphore); - }); - dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); - if(argc >= 2) { - execv(argv[1], (char **)argv+1); - } - } + @autoreleasepool { + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + xpc_set_event_stream_handler("com.apple.iokit.matching", NULL, ^(xpc_object_t _Nonnull object) { + const char *event = xpc_dictionary_get_string(object, XPC_EVENT_KEY_NAME); + NSLog(@"%s", event); + dispatch_semaphore_signal(semaphore); + }); + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + if(argc >= 2) { + execv(argv[1], (char **)argv+1); + } + } } BINARY - ensureRightAccess ${xpcConsumerPath} + ensureRightAccess ${xpcConsumerPath} } function getProductPlistDict() { - cat <<- PLISTDICT + cat <<- PLISTDICT - idProduct - $(($($dataProvider ProductID))) - idVendor - $(($($dataProvider VendorID))) - IOProviderClass - IOUSBDevice - IOMatchLaunchStream - + idProduct + $(($($dataProvider ProductID))) + idVendor + $(($($dataProvider VendorID))) + IOProviderClass + IOUSBDevice + IOMatchLaunchStream + PLISTDICT } function createRemapKeysBinary() { - cat > ${binaryPath} <<- BINARY + cat > ${binaryPath} <<- BINARY #!/bin/zsh PRODUCT_MATCHER='{"ProductID":$($dataProvider ProductID),"VendorID":$($dataProvider VendorID)}' hasMappingBeenAlreadyActivated() { - local currentModifierKeyMappings="\`hidutil property --get UserKeyMapping -m "\${PRODUCT_MATCHER}" | grep HIDKeyboardModifierMappingDst | wc -l\`" - test "\${currentModifierKeyMappings}" -gt 1 + local currentModifierKeyMappings="\`hidutil property --get UserKeyMapping -m "\${PRODUCT_MATCHER}" | grep HIDKeyboardModifierMappingDst | wc -l\`" + test "\${currentModifierKeyMappings}" -gt 1 } hasMappingBeenAlreadyActivated || \ hidutil property --matching "\${PRODUCT_MATCHER}" --set '{"UserKeyMapping": [ - $($dataProvider KeyMappings) + $($dataProvider KeyMappings) ]}' > /dev/null 2>&1 BINARY - ensureRightAccess ${binaryPath} + ensureRightAccess ${binaryPath} } function createLaunchDaemon() { - cat > ${launchDaemonPath} <<- LDAEMON + cat > ${launchDaemonPath} <<- LDAEMON - - Label - $($dataProvider LaunchdServiceName) - ProgramArguments - - ${xpcConsumerPath} - ${remapKeysPath} - - LaunchEvents - - com.apple.iokit.matching - - com.apple.device-attach - $(getProductPlistDict) - - - + + Label + $($dataProvider LaunchdServiceName) + ProgramArguments + + ${xpcConsumerPath} + ${remapKeysPath} + + LaunchEvents + + com.apple.iokit.matching + + com.apple.device-attach + $(getProductPlistDict) + + + LDAEMON - ensureRightAccess ${launchDaemonPath} + ensureRightAccess ${launchDaemonPath} } function enableLaunchDaemon() { - launchctl enable system/${launchDaemonPath%.*} - launchctl bootstrap system ${launchDaemonPath} + launchctl enable system/${launchDaemonPath%.*} + launchctl bootstrap system ${launchDaemonPath} } function createLaunchdService() { - local launchDaemonPath="/Library/LaunchDaemons/$($dataProvider LaunchdServiceName).plist" - [[ -f ${launchDaemonPath} ]] || indicateActivity -- 'Create Launch Daemon' createLaunchDaemon - indicateActivity -- 'Enable Launch Daemon' enableLaunchDaemon + local launchDaemonPath="/Library/LaunchDaemons/$($dataProvider LaunchdServiceName).plist" + [[ -f ${launchDaemonPath} ]] || indicateActivity -- 'Create Launch Daemon' createLaunchDaemon + indicateActivity -- 'Enable Launch Daemon' enableLaunchDaemon } function configureKeymappers() { - local mapper= dataProvider= binaryPath= - for mapper dataProvider in ${(kv)mappers}; do - lop -y h1 -- -i "Configure ${mapper} Keymapper" - binaryPath="${dstDir}/$($dataProvider BinaryName)" - createRemapKeysBinary - createLaunchdService - done + local mapper= dataProvider= binaryPath= + for mapper dataProvider in ${(kv)mappers}; do + lop -y h1 -- -i "Configure ${mapper} Keymapper" + binaryPath="${dstDir}/$($dataProvider BinaryName)" + createRemapKeysBinary + createLaunchdService + done } function configure_system() { - typeset -A mappers=( - [Microsoft]=getDataForMicrosoftKeyboard - [Logitech]=getDataForLogitechKeyboard - ) - local dstDir='/usr/local/bin' - local xpcConsumerPath="${dstDir}/astzweig-xpc-consumer" + typeset -A mappers=( + [Microsoft]=getDataForMicrosoftKeyboard + [Logitech]=getDataForLogitechKeyboard + ) + local dstDir='/usr/local/bin' + local xpcConsumerPath="${dstDir}/astzweig-xpc-consumer" - ensurePathOrLogError ${dstDir} 'Could not create destination dir for remap-keys binary.' || return 10 - indicateActivity -- 'Create XPC event consumer' createXPCConsumer - configureKeymappers + ensurePathOrLogError ${dstDir} 'Could not create destination dir for remap-keys binary.' || return 10 + indicateActivity -- 'Create XPC event consumer' createXPCConsumer + configureKeymappers } function getExecPrerequisites() { - cmds=( - [clang]='' - [launchctl]='' - [cp]='' - [chown]='' - [chmod]='' - ) + cmds=( + [clang]='' + [launchctl]='' + [cp]='' + [chown]='' + [chmod]='' + ) } function getUsage() { - read -r -d '' text <<- USAGE + read -r -d '' text <<- USAGE Usage: $cmdName show-questions [ ]... $cmdName [-v] [-d FILE] @@ -170,18 +170,18 @@ function getUsage() { macOS nativ hidutil, in order to swap command and option key. Options: - -d FILE, --logfile FILE Print log message to logfile instead of stdout. - -v, --verbose Be more verbose. + -d FILE, --logfile FILE Print log message to logfile instead of stdout. + -v, --verbose Be more verbose. ---- $cmdName 0.1.0 Copyright (C) 2022 Rezart Qelibari, Astzweig GmbH & Co. KG License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law. USAGE - print -- ${text} + print -- ${text} } if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then - test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } - source "${ASTZWEIG_MACOS_SYSTEM_LIB}" - module_main $0 "$@" + test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } + source "${ASTZWEIG_MACOS_SYSTEM_LIB}" + module_main $0 "$@" fi diff --git a/modules/06-install-mas-apps.sh b/modules/06-install-mas-apps.sh index 72b8f9d..1f78449 100755 --- a/modules/06-install-mas-apps.sh +++ b/modules/06-install-mas-apps.sh @@ -2,47 +2,47 @@ # vi: set ft=zsh tw=80 ts=2 function installMASApp() { - local currentUser="`who am i | cut -d' ' -f1`" - local appName="$1" - local id="$2" - indicateActivity -- "Install ${appName} app" sudo -u ${currentUser} mas install ${id} + local currentUser="`who am i | cut -d' ' -f1`" + local appName="$1" + local id="$2" + indicateActivity -- "Install ${appName} app" sudo -u ${currentUser} mas install ${id} } function configure_system() { - lop -y h1 -- -i 'Install Mac AppStore Apps' - installMASApp Keka 470158793 + lop -y h1 -- -i 'Install Mac AppStore Apps' + installMASApp Keka 470158793 - if ! isDebug; then - installMASApp Pages 409201541 - installMASApp Numbers 409203825 + if ! isDebug; then + installMASApp Pages 409201541 + installMASApp Numbers 409203825 - installMASApp Outbank 1094255754 + installMASApp Outbank 1094255754 - installMASApp 'Final Cut Pro' 424389933 - installMASApp GarageBand 682658836 - installMASApp Motion 434290957 - installMASApp Compressor 424390742 - installMASApp 'Logic Pro' 634148309 - fi + installMASApp 'Final Cut Pro' 424389933 + installMASApp GarageBand 682658836 + installMASApp Motion 434290957 + installMASApp Compressor 424390742 + installMASApp 'Logic Pro' 634148309 + fi } function getExecPrerequisites() { - cmds=( - [mas]='' - [sudo]='' - [who]='' - [cut]='' - ) + cmds=( + [mas]='' + [sudo]='' + [who]='' + [cut]='' + ) } function getQuestions { - questions=( - 'c: logged-in=Have you ensured a user is logged in to the macOS App Store?' - ) + questions=( + 'c: logged-in=Have you ensured a user is logged in to the macOS App Store?' + ) } function getUsage() { - read -r -d '' text <<- USAGE + read -r -d '' text <<- USAGE Usage: $cmdName show-questions [ ]... $cmdName [-v] [-d FILE] --logged-in ANS @@ -59,11 +59,11 @@ function getUsage() { Copyright (C) 2022 Rezart Qelibari, Astzweig GmbH & Co. KG License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law. USAGE - print -- ${text} + print -- ${text} } if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then - test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } - source "${ASTZWEIG_MACOS_SYSTEM_LIB}" - module_main $0 "$@" + test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } + source "${ASTZWEIG_MACOS_SYSTEM_LIB}" + module_main $0 "$@" fi diff --git a/modules/07-install-binaries.sh b/modules/07-install-binaries.sh index 92a1e4a..bb7cb52 100755 --- a/modules/07-install-binaries.sh +++ b/modules/07-install-binaries.sh @@ -2,63 +2,63 @@ # vi: set ft=zsh tw=80 ts=2 function ensureRightAccess() { - local filesystemItem="$1" - chown root:admin "${filesystemItem}" - chmod ugo=rx "${filesystemItem}" + local filesystemItem="$1" + chown root:admin "${filesystemItem}" + chmod ugo=rx "${filesystemItem}" } function copyUtilityBinaries() { - for file in ${_DIR}/../bin/*; do - indicateActivity -- "Copying ${file##*/}" cp ${file} ${dstDir} - ensureRightAccess ${file} - done + for file in ${_DIR}/../bin/*; do + indicateActivity -- "Copying ${file##*/}" cp ${file} ${dstDir} + ensureRightAccess ${file} + done } function installDocopts() { - local destPath='/usr/local/bin/docopts' - [[ -x ${destPath} ]] && return - indicateActivity -- 'Downloading docpts' curl --output ${destPath} -fsSL ${docopts_url} || return - ensureRightAccess ${destPath} + local destPath='/usr/local/bin/docopts' + [[ -x ${destPath} ]] && return + indicateActivity -- 'Downloading docpts' curl --output ${destPath} -fsSL ${docopts_url} || return + ensureRightAccess ${destPath} } function configure_system() { - lop -y h1 -- -i 'Install Utility Binaries' - local dstDir='/usr/local/bin' - ensurePathOrLogError ${dstDir} 'Could not install binaries.' || return 10 - indicateActivity -- "Set sticky bit to ${dstDir} folder" chmod +t ${dstDir} - installDocopts - copyUtilityBinaries + lop -y h1 -- -i 'Install Utility Binaries' + local dstDir='/usr/local/bin' + ensurePathOrLogError ${dstDir} 'Could not install binaries.' || return 10 + indicateActivity -- "Set sticky bit to ${dstDir} folder" chmod +t ${dstDir} + installDocopts + copyUtilityBinaries } function getExecPrerequisites() { - cmds=( - [cp]='' - [chown]='' - [chmod]='' - [curl]='' - [install]='' - ) + cmds=( + [cp]='' + [chown]='' + [chmod]='' + [curl]='' + [install]='' + ) } function getDefaultDocoptsURL() { - local fileURL="${DOCOPTS_URL:-https://github.com/astzweig/docopts/releases/download/v.0.7.0/docopts_darwin_amd64}" - print -- ${fileURL} + local fileURL="${DOCOPTS_URL:-https://github.com/astzweig/docopts/releases/download/v.0.7.0/docopts_darwin_amd64}" + print -- ${fileURL} } function getQuestions() { - questions=( - 'i: docopts-url=From which URL shall the docopts binary be downloaded? # default:'"$(getDefaultDocoptsURL)" - ) + questions=( + 'i: docopts-url=From which URL shall the docopts binary be downloaded? # default:'"$(getDefaultDocoptsURL)" + ) } function getUsage() { - read -r -d '' text <<- USAGE + read -r -d '' text <<- USAGE Usage: $cmdName show-questions [ ]... $cmdName [-v] [-d FILE] --docopts-url URL - + Install convenient binaries for all users. - + Options: --docopts-url URL The URL from which to download the docopts binary [default: $(getDefaultDocoptsURL)]. @@ -69,12 +69,12 @@ function getUsage() { Copyright (C) 2022 Rezart Qelibari, Astzweig GmbH & Co. KG License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law. USAGE - print -- ${text} + print -- ${text} } if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then - _DIR="${0:A:h}" - test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } - source "${ASTZWEIG_MACOS_SYSTEM_LIB}" - module_main $0 "$@" + _DIR="${0:A:h}" + test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } + source "${ASTZWEIG_MACOS_SYSTEM_LIB}" + module_main $0 "$@" fi diff --git a/modules/08-install-zsh-libraries.sh b/modules/08-install-zsh-libraries.sh index e845649..2430885 100755 --- a/modules/08-install-zsh-libraries.sh +++ b/modules/08-install-zsh-libraries.sh @@ -5,48 +5,48 @@ function addLibToStartupFile() { } function installZshlib() { - local zshlibPath=${libDir}/astzweig_zshlib - if [[ -d ${ASTZWEIG_ZSHLIB} ]]; then - pushd -q ${ASTZWEIG_ZSHLIB} - zcompile -z -U ${zshlibPath} $(find . -type f -perm +u=x -maxdepth 1) - libs+=(${zshlibPath}.zwc) - popd -q - elif [[ -f ${ASTZWEIG_ZSHLIB} ]]; then - cp ${ASTZWEIG_ZSHLIB} ${zshlibPath}.zwc; - fi - chmod ugo=r ${zshlibPath}.zwc + local zshlibPath=${libDir}/astzweig_zshlib + if [[ -d ${ASTZWEIG_ZSHLIB} ]]; then + pushd -q ${ASTZWEIG_ZSHLIB} + zcompile -z -U ${zshlibPath} $(find . -type f -perm +u=x -maxdepth 1) + libs+=(${zshlibPath}.zwc) + popd -q + elif [[ -f ${ASTZWEIG_ZSHLIB} ]]; then + cp ${ASTZWEIG_ZSHLIB} ${zshlibPath}.zwc; + fi + chmod ugo=r ${zshlibPath}.zwc } function modifyGlobalFpath() { - local startupFile=/etc/zshenv - cat ${startupFile} | grep "${(q)libs}" >&! /dev/null && return - print -- "fpath+=(${(q)libs})" >> ${startupFile} - chown root:wheel ${startupFile} - chmod u=rw,go=r ${startupFile} + local startupFile=/etc/zshenv + cat ${startupFile} | grep "${(q)libs}" >&! /dev/null && return + print -- "fpath+=(${(q)libs})" >> ${startupFile} + chown root:wheel ${startupFile} + chmod u=rw,go=r ${startupFile} } function configure_system() { - lop -y h1 -- -i 'Install ZSh Libraries' - local libDir=/usr/local/share/zsh/site-functions - local libs=() - ensurePathOrLogError ${libDir} 'Could not install zsh libraries.' || return 10 - lop -- -d "ASTZWEIG_ZSHLIB is ${ASTZWEIG_ZSHLIB}" - indicateActivity 'Install zshlib' installZshlib - indicateActivity 'Modify global fpath' modifyGlobalFpath + lop -y h1 -- -i 'Install ZSh Libraries' + local libDir=/usr/local/share/zsh/site-functions + local libs=() + ensurePathOrLogError ${libDir} 'Could not install zsh libraries.' || return 10 + lop -- -d "ASTZWEIG_ZSHLIB is ${ASTZWEIG_ZSHLIB}" + indicateActivity 'Install zshlib' installZshlib + indicateActivity 'Modify global fpath' modifyGlobalFpath } function getExecPrerequisites() { - cmds=( - [cat]='' - [grep]='' - [chown]='' - [chmod]='' - [install]='' - ) + cmds=( + [cat]='' + [grep]='' + [chown]='' + [chmod]='' + [install]='' + ) } function getUsage() { - read -r -d '' text <<- USAGE + read -r -d '' text <<- USAGE Usage: $cmdName show-questions [ ]... $cmdName [-v] [-d FILE] @@ -61,12 +61,12 @@ function getUsage() { Copyright (C) 2022 Rezart Qelibari, Astzweig GmbH & Co. KG License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law. USAGE - print -- ${text} + print -- ${text} } if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then - _DIR="${0:A:h}" - test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } - source "${ASTZWEIG_MACOS_SYSTEM_LIB}" - module_main $0 "$@" + _DIR="${0:A:h}" + test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } + source "${ASTZWEIG_MACOS_SYSTEM_LIB}" + module_main $0 "$@" fi diff --git a/modules/09-install-fonts.sh b/modules/09-install-fonts.sh index fb2973e..de8f32b 100755 --- a/modules/09-install-fonts.sh +++ b/modules/09-install-fonts.sh @@ -2,41 +2,41 @@ # vi: set ft=zsh tw=80 ts=2 function installGoogleFonts() { - local fontsDir=/Library/Fonts/Google-Fonts - [[ -d ${fontsDir} ]] && return - indicateActivity 'Download Google Fonts' git clone "${git_google_fonts}" "${fontsDir}" - indicateActivity 'Fix Directory Permissions' find ${fontsDir} -type d -mindepth 1 -exec chmod g+rwx,o+rx {} \; - indicateActivity 'Fix File Permissions' find ${fontsDir} -type f -mindepth 1 -exec chmod g+rw,o+r {} \; + local fontsDir=/Library/Fonts/Google-Fonts + [[ -d ${fontsDir} ]] && return + indicateActivity 'Download Google Fonts' git clone "${git_google_fonts}" "${fontsDir}" + indicateActivity 'Fix Directory Permissions' find ${fontsDir} -type d -mindepth 1 -exec chmod g+rwx,o+rx {} \; + indicateActivity 'Fix File Permissions' find ${fontsDir} -type f -mindepth 1 -exec chmod g+rw,o+r {} \; } function configure_system() { - lop -y h1 -- -i 'Install Fonts' + lop -y h1 -- -i 'Install Fonts' } function getExecPrerequisites() { - cmds=( - [git]='' - ) + cmds=( + [git]='' + ) } function getDefaultGitGoogleFontsURL() { - print -- ${GOOGLE_FONTS_GIT_REMOTE:-https://github.com/google/fonts.git} + print -- ${GOOGLE_FONTS_GIT_REMOTE:-https://github.com/google/fonts.git} } function getQuestions() { - questions=( - 'i: git-google-fonts=Which Git repository shall be used to install Google Fonts from? # default:'"$(getDefaultGitGoogleFontsURL)" - ) + questions=( + 'i: git-google-fonts=Which Git repository shall be used to install Google Fonts from? # default:'"$(getDefaultGitGoogleFontsURL)" + ) } function getUsage() { - read -r -d '' text <<- USAGE + read -r -d '' text <<- USAGE Usage: $cmdName show-questions [ ]... $cmdName [-v] [-d FILE] --git-google-fonts URL - + Install different fonts system wide (for all users). - + Options: --git-google-fonts URL Git URL to the Google Fonts repository [default: $(getDefaultGitGoogleFontsURL)]. -d FILE, --logfile FILE Print log message to logfile instead of stdout. @@ -46,12 +46,12 @@ function getUsage() { Copyright (C) 2022 Rezart Qelibari, Astzweig GmbH & Co. KG License EUPL-1.2. There is NO WARRANTY, to the extent permitted by law. USAGE - print -- ${text} + print -- ${text} } if [[ "${ZSH_EVAL_CONTEXT}" == toplevel ]]; then - _DIR="${0:A:h}" - test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } - source "${ASTZWEIG_MACOS_SYSTEM_LIB}" - module_main $0 "$@" + _DIR="${0:A:h}" + test -f "${ASTZWEIG_MACOS_SYSTEM_LIB}" || { echo 'This module requires macos-system library. Please run again with macos-system library provieded as a path in ASTZWEIG_MACOS_SYSTEM_LIB env variable.'; return 10 } + source "${ASTZWEIG_MACOS_SYSTEM_LIB}" + module_main $0 "$@" fi diff --git a/modules/lib.sh b/modules/lib.sh index e3792dc..7cb0aeb 100644 --- a/modules/lib.sh +++ b/modules/lib.sh @@ -2,107 +2,107 @@ # vi: set ft=zsh tw=80 ts=2 function autoloadZShLib() { - test -d "${ASTZWEIG_ZSHLIB}" || { echo "This module needs astzweig/zshlib to work." >&2; return 99 } - FPATH="${ASTZWEIG_ZSHLIB}:${FPATH}" - fpath+=(${ASTZWEIG_ZSHLIB}) - if [[ -d ${ASTZWEIG_ZSHLIB} ]]; then - local funcNames=($(find "${ASTZWEIG_ZSHLIB}" -type f -perm +u=x -maxdepth 1 | awk -F/ '{ print $NF }')) - autoload -Uz ${funcNames} - elif [[ -f ${ASTZWEIG_ZSHLIB} ]]; then - autoload -Uzw ${ASTZWEIG_ZSHLIB} - fi + test -d "${ASTZWEIG_ZSHLIB}" || { echo "This module needs astzweig/zshlib to work." >&2; return 99 } + FPATH="${ASTZWEIG_ZSHLIB}:${FPATH}" + fpath+=(${ASTZWEIG_ZSHLIB}) + if [[ -d ${ASTZWEIG_ZSHLIB} ]]; then + local funcNames=($(find "${ASTZWEIG_ZSHLIB}" -type f -perm +u=x -maxdepth 1 | awk -F/ '{ print $NF }')) + autoload -Uz ${funcNames} + elif [[ -f ${ASTZWEIG_ZSHLIB} ]]; then + autoload -Uzw ${ASTZWEIG_ZSHLIB} + fi } function isDebug() { - test "${MACOS_SYSTEM_DEBUG}" = true -o "${MACOS_SYSTEM_DEBUG}" = 1 + test "${MACOS_SYSTEM_DEBUG}" = true -o "${MACOS_SYSTEM_DEBUG}" = 1 } function configureLogging() { - local output=tostdout level=info - [ -n "${logfile}" ] && output=${logfile} - [ "${verbose}" = true ] && level=debug - lop setoutput -l ${level} ${output} + local output=tostdout level=info + [ -n "${logfile}" ] && output=${logfile} + [ "${verbose}" = true ] && level=debug + lop setoutput -l ${level} ${output} } function getModuleAnswerByKeyRegEx() { - local key value - local searchRegEx=$1 - for key moduleAnswer in ${modkey:^modans}; do - [[ $key =~ $searchRegEx ]] && return 0 - done - return 1 + local key value + local searchRegEx=$1 + for key moduleAnswer in ${modkey:^modans}; do + [[ $key =~ $searchRegEx ]] && return 0 + done + return 1 } function ensurePathOrLogError() { - local dir=$1 msg=$2 - [[ -d ${dir} ]] || install -m $(umask -S) -d $(getMissingPaths ${dir}) || { - lop -- -e "$msg" -e "Directory ${dir} does not exist and could not be created." - return 10 - } + local dir=$1 msg=$2 + [[ -d ${dir} ]] || install -m $(umask -S) -d $(getMissingPaths ${dir}) || { + lop -- -e "$msg" -e "Directory ${dir} does not exist and could not be created." + return 10 + } } function checkHelpPrerequisites() { - local -A cmds - getHelpPrerequisites || return - checkCommands ${(k)cmds} + local -A cmds + getHelpPrerequisites || return + checkCommands ${(k)cmds} } function addDocoptsToCmds() { - cmds+=(docopts '(with -f option supported)') + cmds+=(docopts '(with -f option supported)') } function requireRootPrivileges() { - test "`id -u`" -eq 0 || { lop -- -e 'This module requires root access. Please run as root.'; return 11 } + test "`id -u`" -eq 0 || { lop -- -e 'This module requires root access. Please run as root.'; return 11 } } whence getHelpPrerequisites >&! /dev/null || function $_() { - addDocoptsToCmds + addDocoptsToCmds } function checkQuestionsPrerequisites() { - local -A cmds - getQuestionsPrerequisites || return - checkCommands ${(k)cmds} + local -A cmds + getQuestionsPrerequisites || return + checkCommands ${(k)cmds} } function checkExecPrerequisites() { - local -A cmds - getExecPrerequisites || return - checkCommands ${(k)cmds} + local -A cmds + getExecPrerequisites || return + checkCommands ${(k)cmds} } function showQuestions() { - local questions=() - getQuestions - for question in ${questions}; do - hio -- body "${question}" - done + local questions=() + getQuestions + for question in ${questions}; do + hio -- body "${question}" + done } function module_main() { - local cmdPath=${1} cmdName=${1:t} hookBag=() - local -A traps=() - preCommandNameHook "$@" || return - shift - autoloadZShLib || return - preHelpHook "$@" || return - checkHelpPrerequisites || return - configureLogging - trap 'traps call int; return 70' INT - trap 'traps call term; return 80' TERM - trap 'traps call exit' EXIT - eval "`getUsage $cmdName | docopts -f -V - -h - : "$@"`" - preQuestionHook "$@" || return - checkQuestionsPrerequisites || return - [ "${show_questions}" = true ] && { showQuestions; return } - preExecHook "$@" || return - checkExecPrerequisites || return - configure_system + local cmdPath=${1} cmdName=${1:t} hookBag=() + local -A traps=() + preCommandNameHook "$@" || return + shift + autoloadZShLib || return + preHelpHook "$@" || return + checkHelpPrerequisites || return + configureLogging + trap 'traps call int; return 70' INT + trap 'traps call term; return 80' TERM + trap 'traps call exit' EXIT + eval "`getUsage $cmdName | docopts -f -V - -h - : "$@"`" + preQuestionHook "$@" || return + checkQuestionsPrerequisites || return + [ "${show_questions}" = true ] && { showQuestions; return } + preExecHook "$@" || return + checkExecPrerequisites || return + configure_system } function { - local name - for name in preCommandNameHook preHelpHook preQuestionHook preExecHook getQuestionsPrerequisites getExecPrerequisites getQuestions getUsage; do - whence ${name} >&! /dev/null || function $_() {} - done + local name + for name in preCommandNameHook preHelpHook preQuestionHook preExecHook getQuestionsPrerequisites getExecPrerequisites getQuestions getUsage; do + whence ${name} >&! /dev/null || function $_() {} + done }