galliumos-distro
galliumos-distro copied to clipboard
hdmi-change script (getXuser function) is broken
Acer Chromebook 14 (Edgar) with MrChromeBox Legacy firmware.
NAME="GalliumOS" VERSION="3.1 (Bismuth)" ID=galliumos ID_LIKE="ubuntu debian" PRETTY_NAME="GalliumOS 3.1" VERSION_ID="3.1" HOME_URL="https://galliumos.org/" SUPPORT_URL="https://galliumos.org/" BUG_REPORT_URL="https://https://github.com/GalliumOS/galliumos-distro/issues" VERSION_CODENAME=bismuth UBUNTU_CODENAME=bionic
Problem: /usr/bin/hdmi-change is broken. Or, more accurately, the 'getXuser' function fails because $user variable does not get populated. This script is provided by "galliumos-base" package.
This script is executed after every "resume from sleep" by the script in "/lib/systemd/system-sleep/hdmi-change.sh". On my system, I see an error message after each resume:
Jan 18 11:58:34 gally-51F9 systemd-sleep[14357]: sudo: unknown user: env
Jan 18 11:58:34 gally-51F9 systemd-sleep[14357]: sudo: unable to initialize policy plugin
This error is produced by /usr/bin/hdmi-change. You can see this error if you run the script manually:
]$ sudo /usr/bin/hdmi-change
sudo: unknown user: env
sudo: unable to initialize policy plugin
This happens because the 'getXuser' function no longer works correctly; the '$user' variable does not get populated:
# getXuser gets the X user belonging to the display in $displaynum.
getXuser() {
export user=`pinky -fw | awk '{ if ($2 == "pts/'$displaynum'" || $2 == ":'$displaynum'" ) { print $1; exit; } }'`
}
for x in /tmp/.X11-unix/*; do
displaynum=`echo $x | sed s#/tmp/.X11-unix/X##`
getXuser;
sudo -u $user env DISPLAY=":$displaynum" XAUTHORITY=/home/$user/.Xauthority /usr/bin/xrandr --auto
done
You can see the problem if you run each part separately:
]$ for x in /tmp/.X11-unix/*; do displaynum=`echo $x | sed s#/tmp/.X11-unix/X##` ; echo $displaynum ; done
0
(...we are using DISPLAY 0...)
]$ pinky -fw | awk '{ if ($2 == "pts/0" || $2 == ":0" ) { print $1; exit; } }'
(...we get NO value returned, which means that the variable '$user' is not getting populated...)
What is happening? 'pinky' never returns anything we look for:
]$ pinky -fw
kinggrowler pts/1 2020-02-13 22:46 :pts/0:S.1
kinggrowler pts/2 00:06 2020-02-15 05:27 :pts/0:S.0
kinggrowler pts/3 2020-02-15 10:05 :pts/0:S.2
We see above that 'getXuser' is searching for "pts/0" however pinky never returns this value. The '$user' variable remains empty; the function is run with a null user:
sudo -u $user env...
is run with empty variable instead:
sudo -u env
...thus the error message in syslog about 'sudo: unknown user: env '.
This empty variable prevents the /usr/bin/hdmi-change script from ever running correctly.
Possible solution:
We need to tweak the 'getXuser' function. This is more difficult than expected; some possible solutions:
https://unix.stackexchange.com/a/542430
https://superuser.com/a/1122517
I have tested the following replacement for the 'getXuser' function and it works correctly for me. Disclosure: I have not tested expensively, or on hardware other than my Edgar.
# getXuser gets the X user belonging to the display in $displaynum.
getXuser() {
export user=`loginctl --no-legend list-sessions | awk '{print $1}' | while read sessionid; do [ $(loginctl --property Type --value show-session $sessionid) = 'x11' ] && loginctl --property Name --value show-session $sessionid; done`
}
When run manually we see the correct user for the X DISPLAY:
]$ sudo loginctl --no-legend list-sessions | awk '{print $1}' | while read sessionid; do [ $(loginctl --property Type --value show-session $sessionid) = 'x11' ] && loginctl --property Name --value show-session $sessionid; done
kinggrowler
This accurately populates '$user' variable and the script /usr/bin/hdmi-change executes without error, and the mysterious messages in syslog goes away.
Here is a proposed patch for this solution:
--- ./hdmi-change.old 2018-05-11 22:26:13.000000000 -0700
+++ hdmi-change.new 2020-02-15 10:32:21.241707443 -0800
@@ -2,10 +2,10 @@
# Run xrandr --auto when hdmi changes are detected
-# getXuser() taken from: http://askubuntu.com/questions/20585/how-to-lock-xscreensaver-on-suspend
+# getXuser() taken from ideas at: https://unix.stackexchange.com/a/542430
# getXuser gets the X user belonging to the display in $displaynum.
getXuser() {
- export user=`pinky -fw | awk '{ if ($2 == "pts/'$displaynum'" || $2 == ":'$displaynum'" ) { print $1; exit; } }'`
+ export user=`loginctl --no-legend list-sessions | awk '{print $1}' | while read sessionid; do [ $(loginctl --property Type --value show-session $sessionid) = 'x11' ] && loginctl --property Name --value show-session $sessionid; done`
}
for x in /tmp/.X11-unix/*; do
Hope this helps some folks!