Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions data/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ dist_init_DATA = init/lightdm.conf
confdir = $(sysconfdir)/lightdm
dist_conf_DATA = lightdm.conf users.conf keys.conf

# Default session-wrapper (see Seat:* session-wrapper / src/lightdm.c).
dist_sbin_SCRIPTS = lightdm-session

dbusconfdir = $(datadir)/dbus-1/system.d
dist_dbusconf_DATA = org.freedesktop.DisplayManager.conf

Expand Down
124 changes: 124 additions & 0 deletions data/lightdm-session
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#!/bin/bash
#
# LightDM wrapper to run around X sessions.
#
# Profile stderr is logged (typically into ~/.xsession-errors) but must not
# block session startup with a modal warning dialog. Non-empty stderr is not a
# reliable signal of fatal profile syntax errors (see issue #482).

echo "Running X session wrapper"

message () {
# pretty-print messages of arbitrary length; use xmessage if it
# is available and $DISPLAY is set
MESSAGE="$PROGNAME: $*"
echo "$MESSAGE" | fold -s -w ${COLUMNS:-80} >&2
if [ -n "$DISPLAY" ] && which xmessage > /dev/null 2>&1; then
echo "$MESSAGE" | fold -s -w ${COLUMNS:-80} | xmessage -center -file -
fi
}

errormsg () {
# exit script with error
message "$*"
exit 1
}

# temporary storage of error messages
ERR=$(mktemp --tmpdir config-err-XXXXXX)
trap 'rm -f "$ERR"' EXIT

source_with_error_check () {
CONFIG_FILE="$1"
echo "Loading $CONFIG_FILE"
# Unset BASH_VERSION while sourcing so ~/.profile does not pull in bashrc.
BASH_VERSION= . "$CONFIG_FILE" 2>"$ERR"
# Keep stderr from profiles in the session log; do not present a blocking
# GUI dialog - stderr is not a reliable indicator of fatal syntax errors.
if [ -s "$ERR" ]; then
cat "$ERR" >&2
fi
truncate -s 0 "$ERR"
}

# Load profile
for file in "/etc/profile" "$HOME/.profile" "/etc/xprofile" "$HOME/.xprofile"; do
if [ -f "$file" ]; then
source_with_error_check "$file"
fi
done

# Load resources
if type xrdb >/dev/null 2>&1; then
xresourcedir="/etc/X11/Xresources"
if [ -d "$xresourcedir" ]; then
for file in $xresourcedir/*; do
echo "Loading resource: $file"
xrdb -merge "$file"
done
fi
xresourcefile="$HOME/.Xresources"
if [ -f "$xresourcefile" ]; then
echo "Loading resource: $xresourcefile"
xrdb -merge "$xresourcefile"
fi
fi

# Load keymaps
if type setxkbmap >/dev/null 2>&1; then
for file in "/etc/X11/Xkbmap" "$HOME/.Xkbmap"; do
if [ -f "$file" ]; then
echo "Loading keymap: $file"
setxkbmap `cat "$file"`
XKB_IN_USE=yes
fi
done
fi

# Load xmodmap if not using XKB
if type xmodmap >/dev/null 2>&1; then
if [ -z "$XKB_IN_USE" ]; then
for file in "/etc/X11/Xmodmap" "$HOME/.Xmodmap"; do
if [ -f "$file" ]; then
echo "Loading modmap: $file"
xmodmap "$file"
fi
done
fi
fi

unset XKB_IN_USE

# Run all system xinitrc shell scripts.
xinitdir="/etc/X11/xinit/xinitrc.d"
if [ -d "$xinitdir" ]; then
for script in $xinitdir/*; do
echo "Loading xinit script $script"
if [ -x "$script" -a ! -d "$script" ]; then
. "$script"
fi
done
fi

# Load Xsession scripts
# OPTIONFILE, USERXSESSION, USERXSESSIONRC and ALTUSERXSESSION are required
# by the scripts to work
xsessionddir="/etc/X11/Xsession.d"
OPTIONFILE=/etc/X11/Xsession.options
USERXSESSION=$HOME/.xsession
USERXSESSIONRC=$HOME/.xsessionrc
ALTUSERXSESSION=$HOME/.Xsession

if [ -d "$xsessionddir" ]; then
for i in `ls $xsessionddir`; do
script="$xsessionddir/$i"
echo "Loading X session script $script"
if [ -r "$script" -a -f "$script" ] && expr "$i" : '^[[:alnum:]_-]\+$' > /dev/null; then
. "$script"
fi
done
fi

echo "X session wrapper complete, running session $@"

exec $@
1 change: 1 addition & 0 deletions tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ TESTS = \
test-session-stderr \
test-session-stderr-multi-write \
test-session-stderr-backup \
test-lightdm-session-stderr \
test-xauthority \
test-corrupt-xauthority \
test-system-xauthority \
Expand Down
91 changes: 91 additions & 0 deletions tests/test-lightdm-session-stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#!/bin/sh
# Regression test for https://github.com/ubuntu/lightdm/issues/482
#
# Profile scripts often write non-fatal messages to stderr. The session wrapper
# must log that output without invoking a blocking zenity/kdialog warning.

set -eu

if [ -n "${srcdir:-}" ]; then
ROOT="${srcdir}/.."
else
ROOT=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)
fi
WRAPPER="${ROOT}/data/lightdm-session"

if [ ! -f "$WRAPPER" ]; then
echo "lightdm-session not found at $WRAPPER" >&2
exit 1
fi

# Guard: shipped wrapper must not invoke the old blocking dialog helpers.
if grep -E '(^|[[:space:]])(\.|source)[[:space:]]+/usr/lib/lightdm/config-error-dialog\.sh|(^|[[:space:]])(zenity|kdialog)([[:space:]]|$)' "$WRAPPER" >/dev/null; then
echo "data/lightdm-session must not invoke config-error-dialog.sh, zenity, or kdialog" >&2
exit 1
fi

TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT

export HOME="${TMP}/home"
mkdir -p "$HOME" "${TMP}/bin"

cat > "${HOME}/.profile" <<'EOF'
echo "harmless profile noise" >&2
EOF

cat > "${TMP}/bin/zenity" <<EOF
#!/bin/sh
echo "zenity must not be invoked during session start" >&2
echo called > "${TMP}/dialog-called"
exit 1
EOF
cat > "${TMP}/bin/kdialog" <<EOF
#!/bin/sh
echo "kdialog must not be invoked during session start" >&2
echo called > "${TMP}/dialog-called"
exit 1
EOF
chmod +x "${TMP}/bin/zenity" "${TMP}/bin/kdialog"

for cmd in xrdb setxkbmap xmodmap; do
cat > "${TMP}/bin/${cmd}" <<'EOF'
#!/bin/sh
exit 0
EOF
chmod +x "${TMP}/bin/${cmd}"
done

cat > "${TMP}/bin/test-session" <<EOF
#!/bin/sh
touch "${TMP}/session-ran"
EOF
chmod +x "${TMP}/bin/test-session"

export PATH="${TMP}/bin:/usr/bin:/bin"

# Capture wrapper stderr (includes forwarded profile noise).
if ! "$WRAPPER" "${TMP}/bin/test-session" >"${TMP}/wrapper-out" 2>"${TMP}/wrapper-err"; then
echo "lightdm-session exited non-zero" >&2
cat "${TMP}/wrapper-err" >&2
exit 1
fi

if [ -f "${TMP}/dialog-called" ]; then
echo "blocking dialog helper was invoked" >&2
exit 1
fi

if [ ! -f "${TMP}/session-ran" ]; then
echo "session command was not executed" >&2
cat "${TMP}/wrapper-err" >&2
exit 1
fi

if ! grep -F "harmless profile noise" "${TMP}/wrapper-err" >/dev/null; then
echo "profile stderr was not forwarded to the session log stream" >&2
cat "${TMP}/wrapper-err" >&2
exit 1
fi

exit 0