Out with the old, in with the new

This commit is contained in:
Salt 2020-05-15 03:21:28 -05:00
parent eb89a9343b
commit 4e65e0c71d
2 changed files with 429 additions and 429 deletions

View File

@ -6,60 +6,76 @@
#
# Distributed under terms of the MIT license.
#
set -e
# "Globals"
_name="firestarter"
_configdir="${XDG_CONFIG_HOME:-$HOME/.config}/$_name"
_logdir="${XDG_DATA_HOME:-$HOME/.local/share}/$_name/logs"
_firestarterrc="$HOME/.firestarterrc"
_sessionid="$(< /proc/self/sessionid)"
# Dummy fd for read sleeping
exec 1023<> <(:)
# Read-only set-once variables
declare -r _name="$(basename -- "$0")"
declare -r _sessionid="$(< /proc/self/sessionid)"
# Options
declare _optconfigdir="${XDG_CONFIG_HOME:-$HOME/.config}/${_name}"
declare _optdryrun
declare _optlogdir="$_optconfigdir/logs"
declare _optpregen
declare -i _opthelp
declare -i _optverbose
# Working variables
declare -a _args
declare _return
# Basic functions
print() {
# Write a message to STDOUT without a name attached
# 1: That message
[ -z "$1" ] && return 1
printf "%s\\n" \
"$1"
}
# Helper functions
log() {
# Write a message to STDOUT
# 1: That message
# Print a line to the terminal if _optverbose is greater than $2
# $2 defaults to 0
# loglevel 0: Daily-use messages
# loglevel 1: Detailed but not quite debugging
# loglevel 2: Definitely debugging
[ -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
# 1: That message
# 2: An optional exit code (will only exit if provided)
[ -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"
if (( _optverbose >= ${2:-0} )); then
printf "%s\\n" "$1"
fi
}
has() {
# See if a program exists in $PATH
# 1: A program
warn() {
# Print a yellow line to the terminal, respecting _optverbose
[ -z "$1" ] && return 1
command -v "$1" > /dev/null 2>&1
if (( _optverbose >= ${2:-0} )); then
if [ -t 1 ]; then
printf "\\e[33m%s\\e[0m\\n" "$1"
else
printf "WARN: %s\\n" "$1"
fi
fi
}
gettarget() {
# Parse a defaults file to get the target program
# 1: A defaults file
error() {
# Print a red line to the terminal, exit if $2 is specified
[ -z "$1" ] && return 1
if [ -t 2 ]; then
printf "\\e[31m%s\\e[0m\\n" "$1" 1>&2
else
printf "ERROR: %s\\n" "$1" 1>&2
fi
[ -z "$2" ] && return
exit "${2:-1}"
}
has() {
# Parse out all arguments and try to find them in path
# If an argument cannot be found, set _return and fail
for prog in "$@"; do
if ! command -v "$prog" > /dev/null 2>&1; then
_return="$prog"
return 1
fi
done
return 0
}
# Core program functions
gettarget() {
# Parse a defaults file to get a target program
[ -z "$1" ] && return 1
[ -d "$1" ] && return 1
[ -r "$1" ] || return 1
# Every odd line is the check line
# Every even one is the exec line
# Every odd line is a condition
# Every even one is a target
local firstline
while read -r checkline; do
if [ -z "$firstline" ]; then
@ -70,9 +86,7 @@ gettarget() {
return 50
fi
fi
if [ "${checkline#"#"}" != "$checkline" ]; then
continue
fi
[ "${checkline#"#"}" != "$checkline" ] && continue
read -r execline
if bash -c "$checkline" > /dev/null 2>&1; then
_return="$execline"
@ -83,19 +97,17 @@ gettarget() {
done < "$1"
return 2
}
# Steps in execution
step_generate() {
log "Creating default config setup in \"$_configdir\""
genconfigs() {
log "Creating default config setup in \"$_optconfigdir\""
log "See firestarter -h for more information"
# Audio daemon
cat << EOF > "$_configdir/audio-daemon"
cat << EOF > "$_optconfigdir/audio-daemon"
#.fsdefaults
command -v pulseaudio
pulseaudio
EOF
# Information bars
cat << EOF > "$_configdir/bar"
cat << EOF > "$_optconfigdir/bar"
#.fsdefaults
command -v polybar && [ -r "$HOME/.config/polybar/launch.sh" ]
"$HOME/.config/polybar/launch.sh"
@ -111,7 +123,7 @@ command -v xfce4-panel
xfce4-panel
EOF
# Blue light filter
cat << EOF > "$_configdir/blue-light-filter"
cat << EOF > "$_optconfigdir/blue-light-filter"
#.fsdefaults
command -v redshift-gtk
redshift-gtk
@ -119,7 +131,7 @@ command -v redshift
redshift
EOF
# Compositor
cat << EOF > "$_configdir/compositor"
cat << EOF > "$_optconfigdir/compositor"
#.fsdefaults
[ -z "\$DISPLAY" ]
:
@ -131,7 +143,7 @@ command -v xcompmgr
xcompmgr
EOF
# Polkit authentication agents
cat << EOF > "$_configdir/polkit-agent"
cat << EOF > "$_optconfigdir/polkit-agent"
#.fsdefaults
command -v lxqt-policykit-agent
lxqt-policykit-agent
@ -176,7 +188,7 @@ polkit-efl-authentication-agent-1
/usr/libexec/polkit-gnome-authentication-agent-1
EOF
# Hotkey daemon
cat << EOF > "$_configdir/hotkey-daemon"
cat << EOF > "$_optconfigdir/hotkey-daemon"
#.fsdefaults
[ -z "\$DISPLAY" ]
:
@ -186,13 +198,13 @@ command -v lxqt-globalkeysd
lxqt-globalkeysd
EOF
# Network daemon
cat << EOF > "$_configdir/network-daemon"
cat << EOF > "$_optconfigdir/network-daemon"
#.fsdefaults
command -v nm-applet
nm-applet
EOF
# Notification daemon
cat << EOF > "$_configdir/notification-daemon"
cat << EOF > "$_optconfigdir/notification-daemon"
#.fsdefaults
[ -z "\$DISPLAY" ]
:
@ -202,7 +214,7 @@ command -v lxqt-notificationd
notificationd
EOF
# Power daemons
cat << EOF > "$_configdir/power-daemon"
cat << EOF > "$_optconfigdir/power-daemon"
#.fsdefaults
command -v batterymon
batterymon
@ -219,13 +231,13 @@ gnome-power-manager
EOF
# Runners
# Note that rofi is not a daemon and is not included here
cat << EOF > "$_configdir/runner"
cat << EOF > "$_optconfigdir/runner"
#.fsdefaults
command -v krunner
krunner
EOF
# Settings daemons
cat << EOF > "$_configdir/settings-daemon"
cat << EOF > "$_optconfigdir/settings-daemon"
#.fsdefaults
command -v xsettingsd
xsettingsd
@ -241,7 +253,7 @@ command -v gnome-settings-daemon
gnome-settings-daemon
EOF
# System statistics glances
cat << EOF > "$_configdir/stat-glances"
cat << EOF > "$_optconfigdir/stat-glances"
#.fsdefaults
[ -z "\$DISPLAY" ]
:
@ -251,7 +263,7 @@ command -v conky && [ -r "\${XDG_CONFIG_HOME:-$HOME/.config}/conky/conky.conf" ]
sleep 5 && conky
EOF
# Wallpaper setters
cat << EOF > "$_configdir/wallpaper"
cat << EOF > "$_optconfigdir/wallpaper"
#.fsdefaults
[ -z "\$DISPLAY" ]
:
@ -261,7 +273,7 @@ command -v nitrogen
nitrogen --restore
EOF
# Window managers
cat << EOF > "$_configdir/wm"
cat << EOF > "$_optconfigdir/wm"
#.fsdefaults
[ -z "\$DISPLAY" ]
:
@ -327,125 +339,70 @@ command -v tinywm
tinywm
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, $(basename -- "$0") responds to the following environment variables:
FS_DIEONWM If nonempty, end the session when the WM dies. This is useful
both for preventing session lock-ins and for using built-in WM
features to log out of the session.
FS_NOLOG If nonempty, create no log files
FS_NOWAITWM If nonempty, skip waiting on the WM to initialize
Copyright (c) 2019 rehashedsalt@cock.li
Licensed under the MIT License
https://gitlab.com/rehashedsalt/firestarter
EOF
}
step_check() {
if [ -z "$_dryrun" ] && [ -z "$_generate" ]; then
for pid in $(pgrep firestarter); do
# Skip invalid PIDs
! [ -d "/proc/$pid" ] && continue
# If it's not our session then who cares
[ "$_sessionid" != "$(< "/proc/$pid/sessionid")" ] && continue
if [ "$pid" != "$BASHPID" ]; then
err "Firestarter is already running: $pid" 40
fi
done
fi
if ! [ -d "$HOME" ] || ! [ -r "$HOME" ]; then
err "Inaccessible home directory: \"$HOME\"" 54
fi
if ! [ -d "$_configdir" ]; then
if ! mkdir -p "$_configdir" > /dev/null 2>&1; then
err "Failed to create configuration directory: \"$_configdir\"" 52
fi
fi
return 0
}
step_preexecute() {
# Special things that can't use simple configuration files
[ -n "$_dryrun" ] && return 0
# Xsessionrc
[ -r "$HOME/.xsessionrc" ] && source "$HOME/.xsessionrc"
# Exports
[ -n "$_optdryrun" ] && return 0
[ -r "$HOME/.xsessionrc" ] && . "$HOME/.xsessionrc"
export XDG_CURRENT_DESKTOP="${XDG_CURRENT_DESKTOP:-firestarter}"
# 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
# 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" ] && \
has dbus-launch; then
# We have dbus but haven't started up a bus yet
eval "$(dbus-launch --exit-with-session --sh-syntax)"
# We have dbus but haven't started it yet
eval "$(dbus-laucnh --exit-with-session --sh-syntax)"
hasdbus=1
else
log "Did not start dbus; some applications may misbehave"
warn "Did not start dbus; some applications may misbehave"
fi
if [ -n "$hasdbus" ]; then
if has dbus-update-activation-environment; then
has dbus-update-activation-environment && \
dbus-update-activation-environment --verbose --systemd --all >/dev/null 2>&1
fi
fi
unset hasdbus
# kcminit/Qt settings
if has kcminit; then
log "Initializing KDE Control Module settings"
kcminit >/dev/null 2>&1
export XDG_CURRENT_DESKTOP="KDE"
elif has qt5ct; then
log "Integrating qt5ct"
log "Initializing qt5ct"
if [ -z "$QT_QPA_PLATFORMTHEME" ]; then
export QT_QPA_PLATFORMTHEME="qt5ct"
log "Exporting QT_QPA_PLATFORMTHEME as \"$QT_QPA_PLATFORMTHEME\""
log "Exporting QT_QPA_PLATFORMTHEME as \"$QT_QPA_PLATFORMTHEME\"" 2
else
log "Using existing theme setting \"$QT_QPA_PLATFORMTHEME\""
log "Using existing theme setting \"$QT_QPA_PLATFORMTHEME\"" 2
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"
log "Exporting QT_AUTO_SCREEN_SCALE_FACTOR as \"$QT_AUTO_SCREEN_SCALE_FACTOR\"" 2
else
log "Using existing scale setting \"$QT_AUTO_SCREEN_SCALE_FACTOR\""
log "Using existing scale factor \"$QT_AUTO_SCREEN_SCALE_FACTOR\"" 2
fi
fi
# xhost
if has xhost; then
if xhost +si:localuser:"$(id -un)" >/dev/null 2>&1; then
log "Session can be accessed in other sessions by this user"
log "Session open to other sessions by this user"
else
log "Failed to open session up via xhost"
warn "Failed to open session via xhost"
fi
fi
# xresources
if [ -n "$DISPLAY" ] && has xrdb && [ -r "$HOME/.Xresources" ]; then
if xrdb "$HOME/.Xresources" >/dev/null 2>&1; then
log "Loaded in .Xresources"
else
log "Failed to load .Xresources"
warn "Failed to load .Xresources"
fi
fi
# xset
if has xset; then
log "Disabling bell"
@ -453,69 +410,66 @@ step_preexecute() {
fi
}
step_execute() {
# Ensure we can log if we have to
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
# Parse out our defaults lists and execute their targets
if ! [ -d "$_optlogdir" ]; then
if ! mkdir -p "$_optlogdir" >/dev/null 2>&1; then
error "Failed to create log directory: \"$_optlogdir\"" 53
fi
fi
# Parse configs
for file in "$_configdir"/*; do
for file in "$_optconfigdir"/*; do
if ! [ -e "$file" ]; then
log "No configuration files found; generating defaults"
step_generate
genconfigs
step_execute
break
return
fi
# Skip our logs directory
[ "$_optlogdir" == "$file" ] && continue
local filename="$(basename -- "$file")"
local logfile="$_logdir/$filename"
[ -n "$FS_NOLOG" ] && logfile="/dev/null"
local logfile="$_optlogdir/$filename.log"
if gettarget "$file"; then
# It's a defaults file with a selected target
target="$_return"
log "Found target for \"$filename\": \"$target\""
if [ -z "$_dryrun" ]; then
log "Found target for $filename: \"$target\""
[ -n "$_optdryrun" ] && continue
if [ -f "$logfile" ]; then
[ -f "$logfile.old" ] && rm "$logfile.old"
mv "$logfile" "$logfile.old"
fi
bash -c "$target" > "$logfile" 2>&1 &
fi
elif [ $? = 50 ] && [ -x "$file" ]; then
# It's a shell script or something
log "Executing file straight out: \"$filename\""
if [ -z "$_dryrun" ]; then
# It's a shell script or executable symlink
log "Executing file: \"$filename\""
[ -n "$_optdryrun" ] && continue
"$file" > "$logfile" 2>&1 &
fi
else
err "Could not execute file: \"$filename\""
warn "Could not execute file: \"$filename\""
fi
done
}
step_postexecute() {
# Wait for the WM to initialize, if one was found and we have the tools
if [ -z "$FS_NOWAITWM" ] && gettarget "$_configdir/wm" && has xprop && has grep; then
if [ -z "$FS_NOWAITWM" ] && gettarget "$_configdir/wm" && has xprop grep; then
log "Waiting for WM to initialize: \"$_return\""
for (( i=0; i<10; i++ )); do
line="$(xprop -root | grep ^_NET_WM_NAME | grep -o '"\S*"$')"
if [ -n "$line" ]; then
log "WM has intiailized, _NET_WM_NAME atom reads: $line"
log "WM has initialized, _NET_WM_NAME atom reads: $line"
break
fi
read -t 1 -u 1023
done
fi
# Dumb Polybar workaround
# Dumb polybar workaround
killall polybar -SIGUSR1
# Execute a user script if it exists
if [ -r "$_firestarterrc" ] && [ -z "$_dryrun" ]; then
log "Executing .firestarterrc"
"$_firestarterrc"
# Execute a user rc if it exists
local firestarterrc="$HOME/.firestarterrc"
if [ -r "$firestarterrc" ] && [ -z "$dryrun" ]; then
log "Executing rc script: $firestarterrc"
"$firestarterrc"
fi
# Start XDG autostarters, if they exist
if [ -z "$_dryrun" ]; then
if [ -z "$_optdryrun" ]; then
if has dex; then
dex -a >/dev/null 2>&1
elif has fbautostart; then
@ -523,14 +477,14 @@ step_postexecute() {
elif has xdg-autostart; then
xdg-autostart ${XDG_CURRENT_DESKTOP:-firestarter}
else
err "Could not find an XDG autostarter"
warn "Could not find an XDG autostarter"
fi
fi
}
step_wait() {
[ -n "$_dryrun" ] && exit 0
[ -n "$_optdryrun" ] && exit 0
trap step_logout EXIT
if [ -n "$FS_DIEONWM" ] && gettarget "$_configdir/wm" && has readlink && has "$_return"; then
if [ -n "$FS_DIEONWM" ] && gettarget "$_configdir/wm" && has readlink "$_return"; then
target="$(command -v "$_return")"
for job in $(jobs -p); do
if [ "$target" = "$(readlink /proc/$job/exe)" ]; then
@ -539,7 +493,7 @@ step_wait() {
exit 0
fi
done
err "Could not find WM: \"$target\""
warn "Could not find WM: \"$target\""
fi
log "Waiting for programs to exit"
wait
@ -553,45 +507,108 @@ step_logout() {
loginctl terminate-session "$_sessionid"
fi
else
# Otherwise just brute it
# Otherwise just brute it out
kill $(jobs -p)
fi
return 0
}
printhelp() {
cat << EOF
Usage: $_name [OPTION]...
-d Perform a dry run; print what programs would have been
executed instead of doing so
-g Regenerate default configs. This will clobber
-h Print this help text
-v Print more status messages. Stacks
Environment Variables:
FS_DIEONWM If nonempty, end the session when the WM dies.
FS_NOWAITWM If nonempty, skip waiting for the WM to initialize
Copyright (c) 2019 rehashedsalt@cock.li
Licensed under the MIT license
EOF
}
# Main
main() {
while getopts ":dgh" opt; do
# Parse out arguments
while [ -n "$1" ]; do
# Parse out flags
while getopts ":dghv" opt; do
case $opt in
d)
_dryrun=1
_optdryrun=1
;;
g)
_generate=1
_optpregen=1
;;
h)
step_printhelp
exit $?
_opthelp=1
;;
*)
err "Unrecognized argument: \"$OPTARG\"" 50
v)
_optverbose+=1
;;
:)
err "Invalid option: \"$OPTARG\"" 51
error "Option requires argument: -$OPTARG" 2
;;
*)
error "Invalid option: -$OPTARG" 2
;;
esac
done
step_check
if [ -n "$_generate" ]; then
step_generate
else
[ -n "$_dryrun" ] && log "Performing a dry run"
# Store arguments
shift $((OPTIND - 1))
if [ -n "$1" ]; then
_args+=("$1")
shift
fi
unset OPTIND
done
# Early hook for help
[ -n "$_opthelp" ] && printhelp && exit 0
# Early hook for generating configs
[ -n "$_optpregen" ] && genconfigs && exit $?
# Ensure our running environment is sane and that we're not about to nest
if [ -z "$_optdryrun" ] && [ -z "$_optpregen" ]; then
for pid in $(pgrep firestarter); do
# Skip invalid PIDs
! [ -d "$/proc/$pid" ] && continue
# If it's not our session then who cares
[ "$_sessionid" != "$(< "/proc/$pid/sessionid")" ] && continue
# If it's us then who cares
[ "$pid" == "$BASHPID" ] && continue
# We care
error "Firestarter is already running: $pid" 40
done
fi
if ! [ -d "$HOME" ] || ! [ -r "$HOME" ]; then
error "Home directory not found or inaccessable: \"$HOME\"" 54
fi
if ! [ -d "$_optconfigdir" ]; then
if [ -f "$_optconfigdir" ]; then
error "Config directory is a file, should be directory: \"$_optconfigdir\"" 52
fi
if ! mkdir -p "$_optconfigdir" > /dev/null 2>&1; then
error "Failed to find or create config directory: \"$_optconfigdir\"" 52
fi
fi
# Validate core program dependencies
log "Validating dependencies" 2
if ! has basename; then
error "Failed to find program: $_return" 1
fi
# Do the do
[ -n "$_optdryrun" ] && log "Performing a dry run"
step_preexecute
step_execute
step_postexecute
step_wait
fi
return 0
step_logout
exit 0
}
main "$@"

View File

@ -6,76 +6,60 @@
#
# Distributed under terms of the MIT license.
#
set -e
# Read-only set-once variables
declare -r _name="$(basename -- "$0")"
declare -r _sessionid="$(< /proc/self/sessionid)"
# Options
declare _optconfigdir="${XDG_CONFIG_HOME:-$HOME/.config}/${_name}"
declare _optdryrun
declare _optlogdir="$_optconfigdir/logs"
declare _optpregen
declare -i _opthelp
declare -i _optverbose
# Working variables
declare -a _args
declare _return
# "Globals"
_name="firestarter"
_configdir="${XDG_CONFIG_HOME:-$HOME/.config}/$_name"
_logdir="${XDG_DATA_HOME:-$HOME/.local/share}/$_name/logs"
_firestarterrc="$HOME/.firestarterrc"
_sessionid="$(< /proc/self/sessionid)"
# Dummy fd for read sleeping
exec 1023<> <(:)
# Helper functions
# Basic functions
print() {
# Write a message to STDOUT without a name attached
# 1: That message
[ -z "$1" ] && return 1
printf "%s\\n" \
"$1"
}
log() {
# Print a line to the terminal if _optverbose is greater than $2
# $2 defaults to 0
# loglevel 0: Daily-use messages
# loglevel 1: Detailed but not quite debugging
# loglevel 2: Definitely debugging
# Write a message to STDOUT
# 1: That message
[ -z "$1" ] && return 1
if (( _optverbose >= ${2:-0} )); then
printf "%s\\n" "$1"
fi
printf "%s log: %s\\n" \
"$_name" \
"$1" >&1
}
warn() {
# Print a yellow line to the terminal, respecting _optverbose
err() {
# Write a message to STDERR, also exit if arg 2 is specified
# 1: That message
# 2: An optional exit code (will only exit if provided)
[ -z "$1" ] && return 1
if (( _optverbose >= ${2:-0} )); then
if [ -t 1 ]; then
printf "\\e[33m%s\\e[0m\\n" "$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
printf "WARN: %s\\n" "$1"
exit "$2"
fi
fi
}
error() {
# Print a red line to the terminal, exit if $2 is specified
[ -z "$1" ] && return 1
if [ -t 2 ]; then
printf "\\e[31m%s\\e[0m\\n" "$1" 1>&2
else
printf "ERROR: %s\\n" "$1" 1>&2
fi
[ -z "$2" ] && return
exit "${2:-1}"
}
has() {
# Parse out all arguments and try to find them in path
# If an argument cannot be found, set _return and fail
for prog in "$@"; do
if ! command -v "$prog" > /dev/null 2>&1; then
_return="$prog"
return 1
fi
done
return 0
}
# Core program functions
gettarget() {
# Parse a defaults file to get a target program
# See if a program exists in $PATH
# 1: A program
[ -z "$1" ] && return 1
command -v "$1" > /dev/null 2>&1
}
gettarget() {
# Parse a defaults file to get the target program
# 1: A defaults file
[ -z "$1" ] && return 1
[ -d "$1" ] && return 1
[ -r "$1" ] || return 1
# Every odd line is a condition
# Every even one is a target
# Every odd line is the check line
# Every even one is the exec line
local firstline
while read -r checkline; do
if [ -z "$firstline" ]; then
@ -86,7 +70,9 @@ gettarget() {
return 50
fi
fi
[ "${checkline#"#"}" != "$checkline" ] && continue
if [ "${checkline#"#"}" != "$checkline" ]; then
continue
fi
read -r execline
if bash -c "$checkline" > /dev/null 2>&1; then
_return="$execline"
@ -97,17 +83,19 @@ gettarget() {
done < "$1"
return 2
}
genconfigs() {
log "Creating default config setup in \"$_optconfigdir\""
# Steps in execution
step_generate() {
log "Creating default config setup in \"$_configdir\""
log "See firestarter -h for more information"
# Audio daemon
cat << EOF > "$_optconfigdir/audio-daemon"
cat << EOF > "$_configdir/audio-daemon"
#.fsdefaults
command -v pulseaudio
pulseaudio
EOF
# Information bars
cat << EOF > "$_optconfigdir/bar"
cat << EOF > "$_configdir/bar"
#.fsdefaults
command -v polybar && [ -r "$HOME/.config/polybar/launch.sh" ]
"$HOME/.config/polybar/launch.sh"
@ -123,7 +111,7 @@ command -v xfce4-panel
xfce4-panel
EOF
# Blue light filter
cat << EOF > "$_optconfigdir/blue-light-filter"
cat << EOF > "$_configdir/blue-light-filter"
#.fsdefaults
command -v redshift-gtk
redshift-gtk
@ -131,7 +119,7 @@ command -v redshift
redshift
EOF
# Compositor
cat << EOF > "$_optconfigdir/compositor"
cat << EOF > "$_configdir/compositor"
#.fsdefaults
[ -z "\$DISPLAY" ]
:
@ -143,7 +131,7 @@ command -v xcompmgr
xcompmgr
EOF
# Polkit authentication agents
cat << EOF > "$_optconfigdir/polkit-agent"
cat << EOF > "$_configdir/polkit-agent"
#.fsdefaults
command -v lxqt-policykit-agent
lxqt-policykit-agent
@ -188,7 +176,7 @@ polkit-efl-authentication-agent-1
/usr/libexec/polkit-gnome-authentication-agent-1
EOF
# Hotkey daemon
cat << EOF > "$_optconfigdir/hotkey-daemon"
cat << EOF > "$_configdir/hotkey-daemon"
#.fsdefaults
[ -z "\$DISPLAY" ]
:
@ -198,13 +186,13 @@ command -v lxqt-globalkeysd
lxqt-globalkeysd
EOF
# Network daemon
cat << EOF > "$_optconfigdir/network-daemon"
cat << EOF > "$_configdir/network-daemon"
#.fsdefaults
command -v nm-applet
nm-applet
EOF
# Notification daemon
cat << EOF > "$_optconfigdir/notification-daemon"
cat << EOF > "$_configdir/notification-daemon"
#.fsdefaults
[ -z "\$DISPLAY" ]
:
@ -214,7 +202,7 @@ command -v lxqt-notificationd
notificationd
EOF
# Power daemons
cat << EOF > "$_optconfigdir/power-daemon"
cat << EOF > "$_configdir/power-daemon"
#.fsdefaults
command -v batterymon
batterymon
@ -231,13 +219,13 @@ gnome-power-manager
EOF
# Runners
# Note that rofi is not a daemon and is not included here
cat << EOF > "$_optconfigdir/runner"
cat << EOF > "$_configdir/runner"
#.fsdefaults
command -v krunner
krunner
EOF
# Settings daemons
cat << EOF > "$_optconfigdir/settings-daemon"
cat << EOF > "$_configdir/settings-daemon"
#.fsdefaults
command -v xsettingsd
xsettingsd
@ -253,7 +241,7 @@ command -v gnome-settings-daemon
gnome-settings-daemon
EOF
# System statistics glances
cat << EOF > "$_optconfigdir/stat-glances"
cat << EOF > "$_configdir/stat-glances"
#.fsdefaults
[ -z "\$DISPLAY" ]
:
@ -263,7 +251,7 @@ command -v conky && [ -r "\${XDG_CONFIG_HOME:-$HOME/.config}/conky/conky.conf" ]
sleep 5 && conky
EOF
# Wallpaper setters
cat << EOF > "$_optconfigdir/wallpaper"
cat << EOF > "$_configdir/wallpaper"
#.fsdefaults
[ -z "\$DISPLAY" ]
:
@ -273,7 +261,7 @@ command -v nitrogen
nitrogen --restore
EOF
# Window managers
cat << EOF > "$_optconfigdir/wm"
cat << EOF > "$_configdir/wm"
#.fsdefaults
[ -z "\$DISPLAY" ]
:
@ -339,70 +327,125 @@ command -v tinywm
tinywm
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, $(basename -- "$0") responds to the following environment variables:
FS_DIEONWM If nonempty, end the session when the WM dies. This is useful
both for preventing session lock-ins and for using built-in WM
features to log out of the session.
FS_NOLOG If nonempty, create no log files
FS_NOWAITWM If nonempty, skip waiting on the WM to initialize
Copyright (c) 2019 rehashedsalt@cock.li
Licensed under the MIT License
https://gitlab.com/rehashedsalt/firestarter
EOF
}
step_check() {
if [ -z "$_dryrun" ] && [ -z "$_generate" ]; then
for pid in $(pgrep firestarter); do
# Skip invalid PIDs
! [ -d "/proc/$pid" ] && continue
# If it's not our session then who cares
[ "$_sessionid" != "$(< "/proc/$pid/sessionid")" ] && continue
if [ "$pid" != "$BASHPID" ]; then
err "Firestarter is already running: $pid" 40
fi
done
fi
if ! [ -d "$HOME" ] || ! [ -r "$HOME" ]; then
err "Inaccessible home directory: \"$HOME\"" 54
fi
if ! [ -d "$_configdir" ]; then
if ! mkdir -p "$_configdir" > /dev/null 2>&1; then
err "Failed to create configuration directory: \"$_configdir\"" 52
fi
fi
return 0
}
step_preexecute() {
# Special things that can't use simple configuration files
[ -n "$_optdryrun" ] && return 0
[ -r "$HOME/.xsessionrc" ] && . "$HOME/.xsessionrc"
[ -n "$_dryrun" ] && return 0
# Xsessionrc
[ -r "$HOME/.xsessionrc" ] && source "$HOME/.xsessionrc"
# Exports
export XDG_CURRENT_DESKTOP="${XDG_CURRENT_DESKTOP:-firestarter}"
# 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
# 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" ] && \
has dbus-launch; then
# We have dbus but haven't started it yet
eval "$(dbus-laucnh --exit-with-session --sh-syntax)"
# We have dbus but haven't started up a bus yet
eval "$(dbus-launch --exit-with-session --sh-syntax)"
hasdbus=1
else
warn "Did not start dbus; some applications may misbehave"
log "Did not start dbus; some applications may misbehave"
fi
if [ -n "$hasdbus" ]; then
has dbus-update-activation-environment && \
if has dbus-update-activation-environment; then
dbus-update-activation-environment --verbose --systemd --all > /dev/null 2>&1
fi
fi
unset hasdbus
# kcminit/Qt settings
if has kcminit; then
log "Initializing KDE Control Module settings"
kcminit > /dev/null 2>&1
export XDG_CURRENT_DESKTOP="KDE"
elif has qt5ct; then
log "Initializing qt5ct"
log "Integrating qt5ct"
if [ -z "$QT_QPA_PLATFORMTHEME" ]; then
export QT_QPA_PLATFORMTHEME="qt5ct"
log "Exporting QT_QPA_PLATFORMTHEME as \"$QT_QPA_PLATFORMTHEME\"" 2
log "Exporting QT_QPA_PLATFORMTHEME as \"$QT_QPA_PLATFORMTHEME\""
else
log "Using existing theme setting \"$QT_QPA_PLATFORMTHEME\"" 2
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\"" 2
log "Exporting QT_AUTO_SCREEN_SCALE_FACTOR as $QT_AUTO_SCREEN_SCALE_FACTOR"
else
log "Using existing scale factor \"$QT_AUTO_SCREEN_SCALE_FACTOR\"" 2
log "Using existing scale setting \"$QT_AUTO_SCREEN_SCALE_FACTOR\""
fi
fi
# xhost
if has xhost; then
if xhost +si:localuser:"$(id -un)" > /dev/null 2>&1; then
log "Session open to other sessions by this user"
log "Session can be accessed in other sessions by this user"
else
warn "Failed to open session via xhost"
log "Failed to open session up via xhost"
fi
fi
# xresources
if [ -n "$DISPLAY" ] && has xrdb && [ -r "$HOME/.Xresources" ]; then
if xrdb "$HOME/.Xresources" > /dev/null 2>&1; then
log "Loaded in .Xresources"
else
warn "Failed to load .Xresources"
log "Failed to load .Xresources"
fi
fi
# xset
if has xset; then
log "Disabling bell"
@ -410,66 +453,69 @@ step_preexecute() {
fi
}
step_execute() {
# Parse out our defaults lists and execute their targets
if ! [ -d "$_optlogdir" ]; then
if ! mkdir -p "$_optlogdir" >/dev/null 2>&1; then
error "Failed to create log directory: \"$_optlogdir\"" 53
# Ensure we can log if we have to
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 "$_optconfigdir"/*; do
# Parse configs
for file in "$_configdir"/*; do
if ! [ -e "$file" ]; then
log "No configuration files found; generating defaults"
genconfigs
step_generate
step_execute
return
break
fi
# Skip our logs directory
[ "$_optlogdir" == "$file" ] && continue
local filename="$(basename -- "$file")"
local logfile="$_optlogdir/$filename.log"
local logfile="$_logdir/$filename"
[ -n "$FS_NOLOG" ] && logfile="/dev/null"
if gettarget "$file"; then
# It's a defaults file with a selected target
target="$_return"
log "Found target for $filename: \"$target\""
[ -n "$_optdryrun" ] && continue
log "Found target for \"$filename\": \"$target\""
if [ -z "$_dryrun" ]; then
if [ -f "$logfile" ]; then
[ -f "$logfile.old" ] && rm "$logfile.old"
mv "$logfile" "$logfile.old"
fi
bash -c "$target" > "$logfile" 2>&1 &
fi
elif [ $? = 50 ] && [ -x "$file" ]; then
# It's a shell script or executable symlink
log "Executing file: \"$filename\""
[ -n "$_optdryrun" ] && continue
# It's a shell script or something
log "Executing file straight out: \"$filename\""
if [ -z "$_dryrun" ]; then
"$file" > "$logfile" 2>&1 &
fi
else
warn "Could not execute file: \"$filename\""
err "Could not execute file: \"$filename\""
fi
done
}
step_postexecute() {
# Wait for the WM to initialize, if one was found and we have the tools
if [ -z "$FS_NOWAITWM" ] && gettarget "$_configdir/wm" && has xprop grep; then
if [ -z "$FS_NOWAITWM" ] && gettarget "$_configdir/wm" && has xprop && has grep; then
log "Waiting for WM to initialize: \"$_return\""
for (( i=0; i<10; i++ )); do
line="$(xprop -root | grep ^_NET_WM_NAME | grep -o '"\S*"$')"
if [ -n "$line" ]; then
log "WM has initialized, _NET_WM_NAME atom reads: $line"
log "WM has intiailized, _NET_WM_NAME atom reads: $line"
break
fi
read -t 1 -u 1023
done
fi
# Dumb polybar workaround
# Dumb Polybar workaround
killall polybar -SIGUSR1
# Execute a user rc if it exists
local firestarterrc="$HOME/.firestarterrc"
if [ -r "$firestarterrc" ] && [ -z "$dryrun" ]; then
log "Executing rc script: $firestarterrc"
"$firestarterrc"
# Execute a user script if it exists
if [ -r "$_firestarterrc" ] && [ -z "$_dryrun" ]; then
log "Executing .firestarterrc"
"$_firestarterrc"
fi
# Start XDG autostarters, if they exist
if [ -z "$_optdryrun" ]; then
if [ -z "$_dryrun" ]; then
if has dex; then
dex -a > /dev/null 2>&1
elif has fbautostart; then
@ -477,14 +523,14 @@ step_postexecute() {
elif has xdg-autostart; then
xdg-autostart ${XDG_CURRENT_DESKTOP:-firestarter}
else
warn "Could not find an XDG autostarter"
err "Could not find an XDG autostarter"
fi
fi
}
step_wait() {
[ -n "$_optdryrun" ] && exit 0
[ -n "$_dryrun" ] && exit 0
trap step_logout EXIT
if [ -n "$FS_DIEONWM" ] && gettarget "$_configdir/wm" && has readlink "$_return"; then
if [ -n "$FS_DIEONWM" ] && gettarget "$_configdir/wm" && has readlink && has "$_return"; then
target="$(command -v "$_return")"
for job in $(jobs -p); do
if [ "$target" = "$(readlink /proc/$job/exe)" ]; then
@ -493,7 +539,7 @@ step_wait() {
exit 0
fi
done
warn "Could not find WM: \"$target\""
err "Could not find WM: \"$target\""
fi
log "Waiting for programs to exit"
wait
@ -507,108 +553,45 @@ step_logout() {
loginctl terminate-session "$_sessionid"
fi
else
# Otherwise just brute it out
# Otherwise just brute it
kill $(jobs -p)
fi
return 0
}
printhelp() {
cat << EOF
Usage: $_name [OPTION]...
-d Perform a dry run; print what programs would have been
executed instead of doing so
-g Regenerate default configs. This will clobber
-h Print this help text
-v Print more status messages. Stacks
Environment Variables:
FS_DIEONWM If nonempty, end the session when the WM dies.
FS_NOWAITWM If nonempty, skip waiting for the WM to initialize
Copyright (c) 2019 rehashedsalt@cock.li
Licensed under the MIT license
EOF
}
# Main
main() {
# Parse out arguments
while [ -n "$1" ]; do
# Parse out flags
while getopts ":dghv" opt; do
while getopts ":dgh" opt; do
case $opt in
d)
_optdryrun=1
_dryrun=1
;;
g)
_optpregen=1
_generate=1
;;
h)
_opthelp=1
;;
v)
_optverbose+=1
;;
:)
error "Option requires argument: -$OPTARG" 2
step_printhelp
exit $?
;;
*)
error "Invalid option: -$OPTARG" 2
err "Unrecognized argument: \"$OPTARG\"" 50
;;
:)
err "Invalid option: \"$OPTARG\"" 51
;;
esac
done
# Store arguments
shift $((OPTIND - 1))
if [ -n "$1" ]; then
_args+=("$1")
shift
fi
unset OPTIND
done
# Early hook for help
[ -n "$_opthelp" ] && printhelp && exit 0
# Early hook for generating configs
[ -n "$_optpregen" ] && genconfigs && exit $?
# Ensure our running environment is sane and that we're not about to nest
if [ -z "$_optdryrun" ] && [ -z "$_optpregen" ]; then
for pid in $(pgrep firestarter); do
# Skip invalid PIDs
! [ -d "$/proc/$pid" ] && continue
# If it's not our session then who cares
[ "$_sessionid" != "$(< "/proc/$pid/sessionid")" ] && continue
# If it's us then who cares
[ "$pid" == "$BASHPID" ] && continue
# We care
error "Firestarter is already running: $pid" 40
done
fi
if ! [ -d "$HOME" ] || ! [ -r "$HOME" ]; then
error "Home directory not found or inaccessable: \"$HOME\"" 54
fi
if ! [ -d "$_optconfigdir" ]; then
if [ -f "$_optconfigdir" ]; then
error "Config directory is a file, should be directory: \"$_optconfigdir\"" 52
fi
if ! mkdir -p "$_optconfigdir" > /dev/null 2>&1; then
error "Failed to find or create config directory: \"$_optconfigdir\"" 52
fi
fi
# Validate core program dependencies
log "Validating dependencies" 2
if ! has basename; then
error "Failed to find program: $_return" 1
fi
# Do the do
[ -n "$_optdryrun" ] && log "Performing a dry run"
step_check
if [ -n "$_generate" ]; then
step_generate
else
[ -n "$_dryrun" ] && log "Performing a dry run"
step_preexecute
step_execute
step_postexecute
step_wait
step_logout
exit 0
fi
return 0
}
main "$@"