firestarter/firestarter

442 lines
9.2 KiB
Bash
Executable File

#! /bin/bash
#
# firestarter
# A desktop environment startup script
# Copyright (C) 2019 Vintage Salt <rehashedsalt@cock.li>
#
# Distributed under terms of the MIT license.
#
# "Globals"
_name="firestarter"
_configdir="${XDG_CONFIG_HOME:-$HOME/.config}/$_name"
_logdir="${XDG_DATA_HOME:-$HOME/.local/share}/$_name/logs"
# Basic functions
print() {
# Write a message to STDOUT without a name attached
[ -z "$1" ] && return 1
printf "%s\\n" \
"$1"
}
log() {
# Write a message to STDOUT
[ -z "$1" ] && return 1
printf "%s log: %s\\n" \
"$_name" \
"$1" >&1
}
err() {
# Write a message to STDERR, also exit if arg 2 is specified
[ -z "$1" ] && return 1
printf "%s err: %s\\n" \
"$_name" \
"$1" >&2
[ -z "$2" ] && return 0
if ! [ "$2" -ge "0" ] > /dev/null 2>&1; then
err "Attempted to exit with malformed exit code \"$2\"" 10
else
exit "$2"
fi
}
startfile() {
# Start a program using an alternatives list
[ -z "$1" ] && return 1
! [ -r "$1" ] && return 2
if [ -x "$1" ]; then
# File is a script
"$1" &
disown "$!"
else
# File is a defaults file
while read line; do
echo "$line"
done < "$1"
fi
}
# Steps in execution
step_generate() {
log "Creating default config setup in \"$_configdir\""
log "See firestarter -h for more information"
# Audio daemon
cat << EOF > "$_configdir/audio-daemon"
command -v pulseaudio
pulseaudio
EOF
# Information bars
cat << EOF > "$_configdir/bar"
command -v tint2
tint2
command -v polybar && [ -f "$HOME/.config/polybar/launch.sh" ]
"$HOME/.config/polybar/launch.sh"
command -v lxpanel
lxpanel
command -v lxqt-panel
lxqt-panel
command -v mate-panel
mate-panel
command -v xfce4-panel
xfce4-panel
EOF
# Blue light filter
cat << EOF > "$_configdir/blue-light-filter"
command -v redshift-gtk
redshift-gtk
command -v redshift
redshift
EOF
# Compositor
cat << EOF > "$_configdir/compositor"
[ -z "\$DISPLAY" ]
:
command -v unagi
unagi
command -v compton
compton
command -v xcompmgr
xcompmgr
EOF
# Polkit authentication agents
cat << EOF > "$_configdir/polkit-agent"
command -v lxqt-policykit-agent
lxqt-policykit-agent
command -v lxpolkit
lxpolkit
command -v mate-polkit
mate-polkit
command -v polkit-efl-authentication-agent-1
polkit-efl-authentication-agent-1
EOF
# Hotkey daemon
cat << EOF > "$_configdir/hotkey-daemon"
[ -z "\$DISPLAY" ]
:
command -v sxhkd
sxhkd
EOF
# Notification daemon
cat << EOF > "$_configdir/notification-daemon"
[ -z "\$DISPLAY" ]
:
command -v dunst
dunst
command -v lxqt-notificationd
notificationd
EOF
# Power daemons
cat << EOF > "$_configdir/power-daemon"
command -v batterymon
batterymon
command -v cbatticon
cbatticon
command -v lxqt-powermangement
lxqt-powermanagement
command -v xfce4-power-manager
xfce4-power-manager
command -v mate-power-manager
mate-power-manager
command -v gnome-power-manager
gnome-power-manager
EOF
# Runners
# Note that rofi is not a daemon and is not included here
cat << EOF > "$_configdir/runner"
command -v krunner
krunner
EOF
# Settings daemons
cat << EOF > "$_configdir/settings-daemon"
command -v xsettingsd
xsettingsd
command -v xsettings-kde
xsettingskde
command -v xfsettingsd
xfsettingsd
command -v mate-settings-daemon
mate-settings-daemon
command -v gnome-settings-daemon
gnome-settings-daemon
EOF
# System statistics glances
cat << EOF > "$_configdir/stat-glances"
[ -z "\$DISPLAY" ]
:
command -v conky && [ -f "\${XDG_CONFIG_HOME:-$HOME/.config}/conky/conky.conf" ]
conky
EOF
# Window managers
cat << EOF > "$_configdir/wm"
[ -z "\$DISPLAY" ]
:
command -v 2bwm
2bwm
command -v aewm
aewm
command -v awesome
awesome
command -v bspwm
bspwm
command -v catwm
catwm
command -v cwm
cwm
command -v dwm
dwm
command -v evilwm
evilwm
command -v exwm
exwm
command -v fluxbox
fluxbox
command -v flwm
flwm
command -v fvwm
fvwm
command -v herbstluftwm
herbstluftwm
command -v i3
i3
command -v icewm
icewm
command -v jbwm
jbwm
command -v jwm
jwm
command -v lwm
lwm
command -v openbox
openbox
command -v pawm
pawm
command -v ratpoison
ratpoison
command -v twm
twm
command -v windowmaker
windowmaker
command -v wmii
wmii
command -v xmonad
xmonad
command -v xfwm4
xfwm4
command -v metacity
metacity
command -v mutter
mutter
command -v kwin
kwin
command -v tinywm
tinywm
EOF
# XDG autostarter
cat << EOF > "$_configdir/xdg-autostart"
command -v dex
dex -a
command -v fbautostart
fbautostart
command -v xdg-autostart
xdg-autostart "\${XDG_CURRENT_DESKTOP:-firestarter}"
EOF
}
step_printhelp() {
cat << EOF
Usage: $(basename -- "$0") [OPTION...]
Start or generate a desktop environment configuration
-h Show this help text
-g Generate a default configuration. This will clobber
-d Perform a dry run. This will print the results of all decisions
without executing them.
Additionally, firestarter responds to the following environment variables:
FS_NOLOG If nonempty, create no log files
Copyright (c) 2019 rehashedsalt@cock.li
Licensed under the MIT License
https://gitlab.com/rehashedsalt/firestarter
EOF
}
step_check() {
if pgrep firestarter > /dev/null 2>&1 && [ -z "$dryrun" ]; then
err "Firestarter is already running" 61
fi
return 0
}
step_preexecute() {
# Special things that can't use simple configuration files
[ "$dryrun" = "1" ] && return 0
# dbus
if \
[ -z "$DBUS_SESSION_BUS_ADDRESS" ] && \
[ -n "$XDG_RUNTIME_DIR" ] && \
[ "$XDG_RUNTIME_DIR" = "/run/user/$(id -u)" ] && \
[ -S "$XDG_RUNTIME_DIR/bus" ]; then
# We already have a bus started, use it
export DBUS_SESSION_BUS_ADDRESS="unix:path=$XDG_RUNTIME_DIR/bus"
hasdbus=1
elif \
[ -z "$DBUS_SESSION_BUS_ADDRESS" ] && \
command -v dbus-launch > /dev/null 2>&1; then
# We have dbus but haven't started up a bus yet
eval "$(dbus-launch --exit-with-session --sh-syntax)"
hasdbus=1
else
log "Did not start dbus; some applications may misbehave"
fi
if [ -n "$hasdbus" ]; then
if command -v dbus-update-activation-environment > /dev/null 2>&1; then
dbus-update-activation-environment --verbose --systemd --all > /dev/null 2>&1
fi
fi
unset hasdbus
# kcminit/Qt settings
if command -v kcminit > /dev/null 2>&1; then
log "Initializing KDE Control Module settings"
kcminit > /dev/null 2>&1
elif command -v qt5ct > /dev/null 2>&1; then
log "Integrating qt5ct"
if [ -z "$QT_QPA_PLATFORMTHEME" ]; then
export QT_QPA_PLATFORMTHEME="qt5ct"
log "Exporting QT_QPA_PLATFORMTHEME as \"$QT_QPA_PLATFORMTHEME\""
else
log "Using existing theme setting \"$QT_QPA_PLATFORMTHEME\""
fi
if [ -z "$QT_AUTO_SCREEN_SCALE_FACTOR" ]; then
export QT_AUTO_SCREEN_SCALE_FACTOR="0"
log "Exporting QT_AUTO_SCREEN_SCALE_FACTOR as $QT_AUTO_SCREEN_SCALE_FACTOR"
else
log "Using existing scale setting \"$QT_AUTO_SCREEN_SCALE_FACTOR\""
fi
fi
# xhost
if command -v xhost > /dev/null 2>&1; then
if xhost +si:localuser:"$(id -un)" > /dev/null 2>&1; then
log "Session can be accessed in other sessions by this user"
else
log "Failed to open session up via xhost"
fi
fi
# xresources
if [ -n "$DISPLAY" ] && command -v xrdb && [ -f "$HOME/.Xresources" ]; then
if xrdb "$HOME/.Xresources" > /dev/null 2>&1; then
log "Loaded in .Xresources"
else
log "Failed to load .Xresources"
fi
fi
# xset
if command -v xset > /dev/null 2>&1; then
log "Disabling bell"
xset -b
fi
}
step_execute() {
if ! [ -d "$_configdir" ]; then
if ! mkdir -p "$_configdir" > /dev/null 2>&1; then
err "Failed to create configuration directory \"$_configdir\"" 52
fi
fi
if [ -n "$FS_NOLOG" ]; then
log "No logs will be created per FS_NOLOG"
elif ! [ -d "$_logdir" ]; then
if ! mkdir -p "$_logdir" > /dev/null 2>&1; then
err "Failed to create log directory \"$_logdir\"" 53
fi
fi
for file in "$_configdir"/*; do
if ! [ -f "$file" ]; then
log "No configuration files found; generating defaults"
step_generate
step_execute
break
fi
local filename="$(basename -- "$file")"
local logfile="$_logdir/$filename"
[ -n "$FS_NOLOG" ] && logfile="/dev/null"
# Every odd line is the check line
# Every even one is the exec line
while read -r checkline; do
read -r execline
if bash -c "$checkline" > /dev/null 2>&1; then
log "Found target for \"$filename\": \"$execline\""
if [ -f "$logfile" ]; then
[ -f "$logfile.old" ] && rm "$logfile.old"
mv "$logfile" "$logfile.old"
fi
if ! [ "$dryrun" = "1" ]; then
bash -c "$execline" > "$logfile" &
fi
break
else
continue
fi
done < "$file"
done
}
step_wait() {
[ "$dryrun" = "1" ] && exit 0
log "Waiting for programs to exit"
log "Send any termination signal to firestarter to log out"
trap step_logout EXIT
wait
exit 0
}
step_logout() {
log "Logging out"
if command -v loginctl > /dev/null 2>&1; then
# Use loginctl if possible
local sessionid="$(< /proc/self/sessionid)"
if [ -n "$sessionid" ]; then
loginctl terminate-session "$sessionid"
fi
else
# Otherwise just brute it
kill $(jobs -p)
fi
return 0
}
# Main
main() {
while getopts ":dgh" opt; do
case $opt in
d)
if ! [ "$dryrun" = "1" ]; then
log "Performing a dry run"
dryrun=1
fi
;;
g)
step_generate
exit $?
;;
h)
step_printhelp
exit $?
;;
*)
err "Unrecognized argument: \"$OPTARG\"" 50
;;
:)
err "Invalid option: \"$OPTARG\"" 51
;;
esac
done
step_check
step_preexecute
step_execute
step_wait
return 0
}
main "$@"