#!/usr/bin/env bash print_help() { cat </dev/null; then rustc -C opt-level=3 "$src" -o "$exe" fi if ! [[ -x "$exe" ]]; then printf "ERR: Uncompiled sway_tree.rs script\n" printf "\tInstall a rust compiler and rerun this script\n" return 1 fi return 0 } check_sway_sounds() { local return_code=0 local -ra a=(\ ~/.configs_pointer/sway screenshot_sound.mp3 'screenshot sound' ~/.configs_pointer/sway volume_change_sound.mp3 'volume change sound' ~/.configs_pointer/sway error_sound.mp3 'error sound' ) for ((i=0; i < ${#a[@]}; i += 3)); do if ! [[ -r "${a[i]}/${a[i+1]}" ]]; then printf "ERR: Missing %s for sway\n" "${a[i+2]}" printf '\tAdd a playable sound file to %s\n' "${a[i]}/${a[i+1]}" printf "\tIt doesn't have to be an mp3 file, just make the extension .mp3\n" return_code=1 fi done return $return_code } #################### # Tmux #################### tmux_check() { check_tmux_plugins } check_tmux_plugins() { local return_code=0 if ! [[ -d ~/.configs_pointer/tmux/plugins ]]; then printf "ERR: Missing tmux plugins\n" cat <R Press: I Press: R HELP return_code=1 fi return $return_code } #################### # Xremap #################### xremap_checks() { check_xremap_config check_xremap_etc check_xremap_executable check_xremap_systemd check_xremap_sudoer check_ydotool_sudoer } check_xremap_config() { local return_code=0 if ! [[ -r ~/.configs_pointer/xremap/config.yml ]]; then printf "ERR: Missing config.yml for xremap\n" printf "\tTry ln -s ./xremap/config{_console,}.yml\n" return_code=1 fi return $return_code } check_xremap_etc() { local return_code=0 if ! [[ -e /etc/xremap/config.yml ]]; then printf "ERR: Missing config.yml for xremap in /etc\n" printf "\t $ please ln -s ~/.configs_pointer/xremap/config.yml /etc/xremap/config.yml\n" return_code=1 fi if ! [[ -e /etc/systemd/system/xremap.service ]]; then printf "ERR: Missing service file for xremap\n" printf "\t $ please cp ~/.configs_pointer/systemd/system/xremap.service /etc/systemd/system/xremap.service\n" return_code=1 fi return $return_code } check_xremap_executable() { local return_code=0 if ! [[ -x /usr/local/bin/xremap ]]; then printf "ERR: Missing systemd binary for xremap\n" printf "\t $ please cp ~/.cargo/bin/xremap /usr/local/bin/xremap\n" return_code=1 fi return $return_code } check_xremap_systemd() { local return_code=0 if ! systemctl is-enabled --quiet xremap &>/dev/null; then printf "ERR: xremap.service not enabled in systemd\n" printf "\t $ systemctl enable xremap\n" return_code=1 fi if ! systemctl is-active --quiet xremap &>/dev/null; then printf "ERR: systemd is not running xremap.service\n" printf "\t $ systemctl start xremap\n" return_code=1 fi return $return_code } check_xremap_sudoer() { local return_code=0 if ! sudo -l | grep -Eq 'NOPASSWD:[[:space:]]+/usr/bin/systemctl restart xremap.service'; then printf "ERR: xremap.service not passwordless for sudoers\n" printf '\t $ please bash -c "cp $HOME/.configs_pointer/sudoers.d/xremap /etc/sudoers.d/xremap"\n' return_code=1 fi return $return_code } check_ydotool_sudoer() { local return_code=0 if ! sudo -l | grep -Eq 'NOPASSWD:[[:space:]]+/usr/bin/ydotool \*'; then printf "ERR: ydotool not passwordless for sudoers\n" printf '\t $ please bash -c "cp $HOME/.configs_pointer/sudoers.d/ydotool /etc/sudoers.d/ydotool"\n' return_code=1 fi return $return_code } #################### # Browsers #################### browser_checks() { check_firefox_wayland } check_firefox_wayland() { local return_code=0 if ! grep 'MOZ_ENABLE_WAYLAND=1' /etc/environment &>/dev/null; then printf "ERR: Missing wayland envvar for firefox\n" printf '\t $ please echo "MOZ_ENABLE_WAYLAND=1" >> /etc/environment\n' return_code=1 fi return $return_code } #################### # Backlight #################### backlight_checks() { if pacman -Qi ddcutil &>/dev/null; then # Check if it's a laptop printf "All good" &>/dev/null else check_backlight_rules fi } check_backlight_rules() { local return_code=0 if ! [[ -e /usr/lib/udev/rules.d/90-backlight.rules ]]; then printf "ERR: Missing rules for backlight\n" printf "\tFollow the instructions for haikarainen/light on github, at the bottom of the README\n" return_code=1 fi if ! id | grep 'video' &>/dev/null; then printf "ERR: Your user is not in the video group\n" printf "\t $ please usermod -aG video %s\n" "$USER" return_code=1 fi return $return_code } #################### # Fcitx #################### fcitx_checks() { check_fcitx_envvars } check_fcitx_envvars() { local return_code=0 if ! grep -E '^GTK_IM_MODULE=fcitx$' /etc/environment &>/dev/null; then printf "ERR: Missing GTK envvar for fcitx\n" printf '\t $ please echo "GTK_IM_MODULE=fcitx" >> /etc/environment\n' return_code=1 fi if ! grep -E '^QT_IM_MODULE=fcitx$' /etc/environment &>/dev/null; then printf "ERR: Missing QT envvar for fcitx\n" printf '\t $ please echo "QT_IM_MODULE=fcitx" >> /etc/environment\n' return_code=1 fi if ! grep -E '^XMODIFIERS=@im=fcitx$' /etc/environment &>/dev/null; then printf "ERR: Missing XMODIFIERS envvar for fcitx\n" printf '\t $ please echo "XMODIFIERS=@im=fcitx" >> /etc/environment\n' return_code=1 fi return $return_code } #################### # Av1 / vimiv #################### av1_checks() { check_vimiv_plugin check_libavif } check_vimiv_plugin() { local return_code=0 if ! [[ -e /usr/lib/qt/plugins/imageformats/libqavif.so ]]; then printf "ERR: Missing avif support for vimiv\n" cat </dev/null; then printf "ERR: Missing system-wide avif support\n" printf "\t $ please pacman -S libavif\n" return_code=1 fi return $return_code } #################### # Aerc #################### aerc_checks() { check_aerc_accounts } check_aerc_accounts() { local return_code=0 if [[ "$(stat -c "%a" ~/.configs_pointer/aerc/accounts.conf)" != "600" ]]; then printf "ERR: Aerc's accounts.conf is missing permissions 600\n" return_code=1 fi return $return_code } #################### # Git #################### git_checks() { check_gitconfig } check_gitconfig() { local return_code=0 if ! [[ -r ~/.gitconfig ]]; then printf 'ERR: Missing global gitconfig at ~/.gitconfig\n' return_code=1 fi return $return_code } #################### # SSH #################### ssh_checks() { check_sshconfig check_sshdconfig } check_sshconfig() { local return_code=0 if ! [[ -r ~/.ssh/config ]]; then printf 'ERR: Missing ssh config at ~/.ssh/config\n' printf '\tSee ./ssh/template.config for an example\n' return_code=1 elif ! grep -Eq 'Host (codeberg.org|github.com|\*sr.ht)' ~/.ssh/config; then printf 'ERR: No hosts in ~/.ssh/config\n' printf '\tSee ./ssh/template.config for an example\n' return_code=1 fi return $return_code } check_sshdconfig() { local return_code=0 if ! grep -q 'PasswordAuthentication no' /etc/ssh/sshd_config; then printf 'ERR: Password authentication permitted in /etc/ssh/sshd_config\n' printf '\tSee ./ssh/template.sshd_config for an example\n' return_code=1 fi if ! grep -q 'PermitRootLogin no' /etc/ssh/sshd_config; then printf 'ERR: Root login permitted in /etc/ssh/sshd_config\n' printf '\tSee ./ssh/template.sshd_config for an example\n' return_code=1 fi if grep -q 'Port 22' /etc/ssh/sshd_config || ! grep -q 'Port' /etc/ssh/sshd_config; then printf 'ERR: Still using port 22 for sshd\n' printf '\tSee ./ssh/template.sshd_config for an example\n' return_code=1 fi return $return_code } #################### # Docker configs #################### docker_checks() { check_for_docker_detach_keys } check_for_docker_detach_keys() { local return_code=0 if ! grep -q 'detachKeys' ~/.docker/config.json; then printf 'ERR: Docker detach keys are not defined. Default is ^p^q\n' printf '\tAdd "detachKeys": "ctrl-q,ctrl-q" to ~/.docker/config.json\n' return_code=1 fi if ! grep -q 'PermitRootLogin no' /etc/ssh/sshd_config; then printf 'ERR: Root login permitted in /etc/ssh/sshd_config\n' printf '\tSee ./ssh/template.sshd_config for an example\n' return_code=1 fi if grep -q 'Port 22' /etc/ssh/sshd_config || ! grep -q 'Port' /etc/ssh/sshd_config; then printf 'ERR: Still using port 22 for sshd\n' printf '\tSee ./ssh/template.sshd_config for an example\n' return_code=1 fi return $return_code } #################### # Rust binaries #################### russy_checks() { check_for_russy_bins } check_for_russy_bins() { local -i return_code=0 local -a bin_names while IFS='' read -r line; do bin_names+=("$line") done < <(awk '/name =/ { split($0, a, "\""); print a[2] }' ~/.configs_pointer/bin/rewritten_in_rust/Cargo.toml) if [[ $? -eq 0 ]]; then for (( i = 1; i < "${#bin_names[@]}"; i++ )); do local name="${bin_names[i]}" if ! [[ -L "${HOME}/.configs_pointer/bin/${name}" ]] && [[ -e "${HOME}/.configs_pointer/bin/${name}" ]]; then printf 'ERR: Conflicting file with rust binary `%s` in bin\n' "$name" printf '\tRemove the conflicting file and rerun this script with `build`\n' return_code=1 elif ! [[ -L "${HOME}/.configs_pointer/bin/${name}" ]]; then printf 'ERR: Missing rust binary `%s` in bin\n' "$name" printf '\tInstall rust and rerun this script with the `build` argument\n' return_code=1 fi done fi return $return_code } russy_build() { if command -v cargo &>/dev/null; then if cargo build --release --manifest-path="$HOME/.configs_pointer/bin/rewritten_in_rust/Cargo.toml"; then local -a bin_names while IFS='' read -r line; do bin_names+=("$line") done < <(awk '/name =/ { split($0, a, "\""); print a[2] }' ~/.configs_pointer/bin/rewritten_in_rust/Cargo.toml) local name for (( i = 1; i < "${#bin_names[@]}"; i++ )); do name="$(basename "${bin_names[i]}")" ( cd ~/.configs_pointer/bin || return 1 if ! [[ -e "$name" ]]; then ln -s "./rewritten_in_rust/target/release/$name" "./$name" echo "$name" >> ~/.configs_pointer/bin/.gitignore elif ! [[ -L "$name" ]]; then printf 'ERR: Failed to link rust binary \`%s\`\n' "$name" printf '\tRemove the conflicting file\n' fi ) done else printf 'ERR: Failed to compile rust binaries\n' printf '\tInstall rust to compile additional scripts\n' return 1 fi else printf 'ERR: No rust compiler found\n' printf '\tInstall rust to compile additional scripts\n' return 1 fi } #################### # Vim #################### vim_checks() { check_for_tsserver } check_for_tsserver() { local return_code=0 if ! command -v tsserver &>/dev/null; then printf 'ERR: tsserver vim lsp not found!\n' printf '\tInstall using `npm install --user typescript typescript-language-server vscode-langservers-extracted flow-bin`\n' return_code=1 fi return $return_code } #################### # Main #################### if [[ "$1" == 'build' ]]; then russy_build || exit 1 fi if [[ "$(uname -s)" == 'Linux' ]] && [[ "$1" == 'status' || "$1" == 'build' ]]; then configs_pointer_is_setup || exit 1 swayland_checks xremap_checks browser_checks backlight_checks fcitx_checks av1_checks tmux_check aerc_checks git_checks ssh_checks docker_checks russy_checks vim_checks else print_help fi