Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
Yet another on-lid-close acpi action (for e17, tty, ...)
View unanswered posts
View posts from last 24 hours

Goto page 1, 2  Next  
Reply to topic    Gentoo Forums Forum Index Portage & Programming
View previous topic :: View next topic  
Author Message
Yminus
Tux's lil' helper
Tux's lil' helper


Joined: 06 Jan 2008
Posts: 144

PostPosted: Thu Apr 26, 2012 9:43 pm    Post subject: Yet another on-lid-close acpi action (for e17, tty, ...) Reply with quote

I've written an acpi script for the lid open/close event.

When the lid is closed, it waits for 3 seconds and exits without action if the lid has been opened again.
If the lid stayed close the script locks the screen and - on ac-power - blanks it or - on battery-power - suspends to ram.

Unlike other scripts I found here or elsewhere on the net it does not need 'xhost +local:0', as this is considered to be insecure.

It locks the screen of enlightenment sessions but can be configured to work with kde-4/kde-3/gnome/xscreensaver/xdg-screensaver.

To use it put a file with the following content into /etc/acpi/events/:
Code:
event=button[ /]lid
action=/etc/acpi/actions/my_lid.sh %e

Save the script below to /etc/acpi/actions/my_lid.sh and make it executable.
Code:
#! /bin/sh
# lid button pressed/released event handler

# default display on current host
DISPLAY=":0.0"
# time in seconds to wait after lid has been closed
TIMEOUT="3"
# your username FIXME: Is there a dynamic way to get a current X user?
XUSER="lars"
##
# your screen lock command:
# enlightenment)
SCREEN_LOCK='enlightenment_remote -desktop-lock'
# or
#SCREEN_LOCK="dbus-send --print-reply=literal --dest=org.enlightenment.wm.service /org/enlightenment/wm/RemoteObject org.enlightenment.wm.Desktop.Lock"
# kde-4)
#SCREEN_LOCK='qdbus org.freedesktop.ScreenSaver /ScreenSaver Lock'
# kde-3)
#SCREEN_LOCK='dcop kdesktop KScreensaverIface lock'
# gnome)
#SCREEN_LOCK='gnome-screensaver-command --lock'
# xscreensaver)
#SCREEN_LOCK='xscreensaver-command -lock'
# xdg-screensaver)
#SCREEN_LOCK='xdg-screensaver lock'

# to syslog
log (){
    logger -t lid-action -- "$@"
}

xsu () {
    if [[ -z "$DBUS_SESSION_BUS_ADDRESS" ]]; then
        # Looks like we are outside X
        home=$(grep $XUSER /etc/passwd)
        home=${home#*:*:*:*:*:}
        home=${home%:*}
        log "home is: $home"
        # Get the latest file in session-bus directory
        dbus_file=$(ls $home/.dbus/session-bus/ -t | head -1)
        log "dbus file is: $dbus_file"
        # and export a variable from it
        log "source $home/.dbus/session-bus/$dbus_file"
        . "$home/.dbus/session-bus/$dbus_file" && export DBUS_SESSION_BUS_ADDRESS
    fi
    log "dbus session address is: $DBUS_SESSION_BUS_ADDRESS"
    log "su -l -c \"DISPLAY=$DISPLAY $@\" $XUSER"
    ERROR=$( { su -l -c "DISPLAY=$DISPLAY $@" $XUSER; } 2>&1 )
    log "$ERROR"
}

# pass the command you want to execute on lid close to this function
execute_command () {
    # this script only cares for LID close events
    if [ "$close" == "close" ]
    then
        ## now sleep for a while and then check if the user decided
        ## to open the lid again
        #
        #acpi_listen -t $TIMEOUT
        # the above won't work since this script blocks acpid
        # so acpi_listen would not report any events while this
        # script is executed
        sleep $TIMEOUT
        STATUS=$(</proc/acpi/button/lid/LID/state)

        if [ "${STATUS##* }" == "open" ]
        then
            log "on-lid-close-action interrupted"
        else
            # lock screen
            log "locking screen"
            xsu "$SCREEN_LOCK"
            # take action
            log "$@"
            "$@"
        fi
    fi
}

log "$@"
# close or open?
close=$3
# check if we are on ac- or on battery-power
on_ac_power
if [ $? -ne 0 ]
then
    # BATTERY
    log "on battery power"
    # suspend to ram
    execute_command pm-suspend
else
    # AC
    log "on AC power"
    # switch-off screen
    execute_command xsu "xset -display $DISPLAY dpms force off"
fi


As I am not an experienced shell scripter you may help my by making suggestions for improvements.
I am not sure if the ways to bypass X-server and dbus access restrictions are secure?
And I wonder if there is a dynamic way to find the current user of the X-screen?
_________________
Göögle is evil!
To protect your privacy search the net with
https://www.ixquick.com
Back to top
View user's profile Send private message
ppurka
Advocate
Advocate


Joined: 26 Dec 2004
Posts: 3067

PostPosted: Fri Apr 27, 2012 1:02 am    Post subject: Reply with quote

I use this to get the XUSER dynamically:
Code:
X_USER="$(who | sed -ne "s/^\([^ ]*\)[ ]*:0.*/\1/p")"

_________________
emerge --quiet redefined | E17 vids: I, II
Back to top
View user's profile Send private message
Yminus
Tux's lil' helper
Tux's lil' helper


Joined: 06 Jan 2008
Posts: 144

PostPosted: Fri Apr 27, 2012 7:48 am    Post subject: Reply with quote

ppurka wrote:
I use this to get the XUSER dynamically:
Code:
X_USER="$(who | sed -ne "s/^\([^ ]*\)[ ]*:0.*/\1/p")"


I tried using who but I noticed it only reports users logged into a shell. This would work for me, because I have always at least one terminal open (yakuake) but if you have just an X session open, who does not report the user (at least not here with lxde-base/lxdm and e17.

Does it work with other Display Managers?
_________________
Göögle is evil!
To protect your privacy search the net with
https://www.ixquick.com
Back to top
View user's profile Send private message
ppurka
Advocate
Advocate


Joined: 26 Dec 2004
Posts: 3067

PostPosted: Fri Apr 27, 2012 8:36 am    Post subject: Reply with quote

It depends on whether your login manager registers the user in the utmp/wtmp file. I use slim and I think it does that. I do remember that there were some broken login managers which did not do this. This was 2y ago, when I was looking for a decent, lightweight login manager.
_________________
emerge --quiet redefined | E17 vids: I, II
Back to top
View user's profile Send private message
M
Guru
Guru


Joined: 12 Dec 2006
Posts: 427

PostPosted: Fri Apr 27, 2012 1:26 pm    Post subject: Reply with quote

Hi, your script looks nice. I will try it, I use something much simpler right now.
You can maybe get XUSER by looking at xinit user, something like this:
Code:
XUSER=$(ps aux | grep [x]init | awk '{print $1}')

This works for me, I use qingy in text mode as login manager, I believe this will work also with startx, don't know how other login managers work but I think they do start xinit?

Also, small addition to SCREEN_LOCK would be slock from suckless project, very simple screen locker. I would add also a variable for suspend command. I never had to use pm-utils, plain "echo 3 > /proc/acpi/sleep" or "echo -n mem > /sys/power/state" always worked for me.

Cheers,
M
Back to top
View user's profile Send private message
tclover
Apprentice
Apprentice


Joined: 10 Apr 2011
Posts: 295

PostPosted: Sun Apr 29, 2012 6:26 pm    Post subject: Reply with quote

@ppurka:
the simpliest, leanest login manager is:
~/.zlogin:
# $Id: ~/.zlogin, 2012/04/29 -tclover Exp $
# auto startx depending on the tty
if [[ -z $DISPLAY ]] && [[ $EUID != 0 ]] { startx &> ~/.xsession-errors & }
# start gnome-keyring
if [[ -n $DISPLAY ]] && [[ -z $GNOME_KEYRING_PID ]] {
    eval $(gnome-keyring-daemon)
    export GNOME_KEYRING_PID
    export GNOME_KEYRING_SOCKET
    export SSH_AUTH_SOCK
    export GPG_AGENT_INFO
}
# vim:fenc=utf-8:ci:pi:sts=0:sw=4:ts=4

or (for bash users)
~/.bash_login:
# $Id: ~/.bash_login, 2012/04/29 -tclover Exp $
# auto startx depending on the tty
[[ -z $DISPLAY ]] [[ $UID != 0 ]] && startx &> ~/.xsession-errors &
# start gnome-keyring
[[ -n $DISPLAY ]] && [[ -z $GNOME_KEYRING_PID ]] && {
    eval $(gnome-keyring-daemon)
    export GNOME_KEYRING_PID
    export GNOME_KEYRING_SOCKET
    export SSH_AUTH_SOCK
    export GPG_AGENT_INFO
}
# vim:fenc=utf-8:ci:pi:sts=0:sw=4:ts=4:

and...
~/.xinitrc:
# $Id: ~/.xinitrc, 2012/04/29 -tclover Exp $
eval $(gnome-keyring-daemon)
export GNOME_KEYRING_PID
export GNOME_KEYRING_SOCKET
export SSH_AUTH_SOCK
export GPG_AGENT_INFO
dbus-launch nm-applet --sm-disable &
dbus-launch gcm-session &
#xcalib -gc 1.0 -b 0.0 -co 100.0 .icc/sRGB_v4_ICC_preference.icc
laditray &> /dev/null &
/usr/libexec/polkit-gnome-authentication-agent-1 &
unclutter -idle 8 -noevents &
[ -e ~/.Xmodmap ] && xmodmap ~/.Xmodmap
xset s off
xset fp+ /usr/share/fonts/TTF-FD/
xset fp+ /usr/share/fonts/artwiz-latin1
xset fp+ /usr/share/fonts/artwiz-aleczapka-en
xset fp+ /usr/share/fonts/terminus
xset fp rehash
#xrdb -merge ~/.Xdefaults
#xrdb -merge ~/.xcolors/sj-bright
xrdb -load ~/.Xresources
/usr/bin/urxvtd -q -o -f &
case $(tty | cut -b6-) in
    tty1) exec ck-launch-session dbus-launch --sh-syntax --exit-with-session enlightenment_start.sh;;
    tty2) exec ck-launch-session dbus-launch --sh-syntax --exit-with-session lxsession             ;;
    tty3) exec ck-launch-session dbus-launch --sh-syntax --exit-with-session openbox-session       ;;
esac
# vim:fenc=utf-8:ci:pi:sts=0:sw=4:ts=4:

nothing else is more efficient than that. Extra ~/.zlogout or ~/.bash_logout are available on https://github.com/tokiclover/dotfiles/.

@M: this should work
[code]XUSER=$(ps aux | grep xinit | awk '{print $1}' | head -n1)

I'll try that script when I have some time... I was looking for one but I was lazy enough to not write one myself.
_________________
mkinitramfs-ll:topic 879125::(bar-)overlay:topic 889918
Back to top
View user's profile Send private message
Yminus
Tux's lil' helper
Tux's lil' helper


Joined: 06 Jan 2008
Posts: 144

PostPosted: Mon Apr 30, 2012 8:25 am    Post subject: Reply with quote

ppurka wrote:
It depends on whether your login manager registers the user in the utmp/wtmp file. I use slim and I think it does that.

Yes, indeed your method to get the X user dynamically works with slim and presumably other "non-broken" login managers.
I switched to slim. How did you configure it to start e17?
I put a small script into /etc/X11/Sessions/
/etc/X11/Sessions/e17:
Code:
#!/bin/sh
/usr/bin/enlightenment_start

and told slim in /etc/slim.conf to read from Session directory:
Code:
sessiondir           /etc/X11/Sessions


M wrote:
You can maybe get XUSER by looking at xinit user, something like this:
Code:
XUSER=$(ps aux | grep [x]init | awk '{print $1}')

On my machine this returns nothing.

tclover wrote:
@M: this should work
Code:
XUSER=$(ps aux | grep xinit | awk '{print $1}' | head -n1)

On my machine this returns my user name if I call it as my user, and "root" if it is called by root. As the script is executed by root this would not work.

@M,tclover
Nice to hear that you want to try the script! Please tell me if it works on your machine - up to know it only passed the womm certificate program :)

@all:
I'm about to add your suggestions, I will post the script as soon as its finished.
_________________
Göögle is evil!
To protect your privacy search the net with
https://www.ixquick.com
Back to top
View user's profile Send private message
ppurka
Advocate
Advocate


Joined: 26 Dec 2004
Posts: 3067

PostPosted: Mon Apr 30, 2012 2:58 pm    Post subject: Reply with quote

Great! Good to know you find it (the code and slim, both) useful :)

My configuration for slim is identical to what you have done. The only difference (IMHO, not noteworthy) is that I mentioned the sessions as
Code:
sessions enlightenment,Xsession
and I have both those files in /etc/X11/Sessions
_________________
emerge --quiet redefined | E17 vids: I, II
Back to top
View user's profile Send private message
dmpogo
Advocate
Advocate


Joined: 02 Sep 2004
Posts: 2166
Location: Canada

PostPosted: Tue May 01, 2012 3:07 am    Post subject: Reply with quote

What I do on lid close is both suspend to ram and write hibernate image, so that if I forget and laptop runs out of battery why suspended to ram,
I have a hibernation image to start from.
Back to top
View user's profile Send private message
Yminus
Tux's lil' helper
Tux's lil' helper


Joined: 06 Jan 2008
Posts: 144

PostPosted: Wed May 09, 2012 9:48 pm    Post subject: Reply with quote

I added a function which tries several suspend to ram methods as suggested by M and a variable to replace this function by a custom method - for example one that writes a hibernate image as suggested by dmpogo.

For me there is no use for a hibernate image, since my whole hard drive except a small boot partition is encrypted. Even swap is encrypted with a random key. Besides I think the suspend method is out of the scope of this script, but as I said it is easy to add your own suspend script.

I also added slock. Thank you, M for pointing me to the suckless project, which is quite interesting.

Here's the script:
Code:
#! /bin/sh
# lid button pressed/released event handler

# default display on current host
DISPLAY=":0.0"
# time in seconds to wait after lid has been closed
TIMEOUT="3"
# some broken login managers (e.g. lxdm) do not register the user in the utmp/wtmp file
# if you use such a login manager put your username here
XUSER="lars"
##
# your suspend command
# pm-utils
#SUSPEND="pm-suspend"
# plain echo to /sys or /proc file
SUSPEND="suspend_to_ram"
##
# your screen lock command:
# enlightenment)
SCREEN_LOCK='enlightenment_remote -desktop-lock'
# or
#SCREEN_LOCK="dbus-send --print-reply=literal --dest=org.enlightenment.wm.service /org/enlightenment/wm/RemoteObject org.enlightenment.wm.Desktop.Lock"
# kde-4)
#SCREEN_LOCK='qdbus org.freedesktop.ScreenSaver /ScreenSaver Lock'
# kde-3)
#SCREEN_LOCK='dcop kdesktop KScreensaverIface lock'
# gnome)
#SCREEN_LOCK='gnome-screensaver-command --lock'
# xscreensaver)
#SCREEN_LOCK='xscreensaver-command -lock'
# xdg-screensaver)
#SCREEN_LOCK='xdg-screensaver lock'
# slock)
#SCREEN_LOCK='slock'

# to syslog
log (){
    logger -t lid-action -- "$@"
}

# get access to X and dBus session
xsu () {
    # get the X user dynamically
    xuser="$(who | sed -ne "s/^\([^ ]*\)[ ]*:0.*/\1/p")"
    log "detected X user is: $xuser"
    if [[ -z "$xuser" ]]; then
        # fallback to static username
        xuser=$XUSER
    fi
    if [[ -z "$DBUS_SESSION_BUS_ADDRESS" ]]; then
        # Looks like we are outside X
        home=$(grep $xuser /etc/passwd)
        home=${home#*:*:*:*:*:}
        home=${home%:*}
        log "home is: $home"
        # Get the latest file in session-bus directory
        dbus_file=$(ls $home/.dbus/session-bus/ -t | head -1)
        log "dbus file is: $dbus_file"
        # and export a variable from it
        log "source $home/.dbus/session-bus/$dbus_file"
        . "$home/.dbus/session-bus/$dbus_file" && export DBUS_SESSION_BUS_ADDRESS
    fi
    log "dbus session address is: $DBUS_SESSION_BUS_ADDRESS"
    log "su -l -c \"DISPLAY=$DISPLAY $@\" $xuser"
    su -l -c "DISPLAY=$DISPLAY $@" $xuser
}

# suspend to ram
suspend_to_ram () {
    # look for /sys file
    if [[ -e /sys/power/state ]]
    then
        log "echo -n mem > /sys/power/state"
        echo -n mem > /sys/power/state
    elif [[ -e /proc/acpi/sleep ]]
    then
        # try deprecated /proc/acpi file
        log "echo 3 > /proc/acpi/sleep"
        echo 3 > /proc/acpi/sleep
    else
        # try to invoke pm-utils
        log "pm-suspend"
        pm-suspend
    fi
}

# pass the command you want to execute on lid close to this function
execute_command () {
    # this script only cares for LID close events
    if [ "$close" == "close" ]
    then
        ## now sleep for a while and then check if the user decided
        ## to open the lid again
        #
        #acpi_listen -t $TIMEOUT
        # the above won't work since this script blocks acpid
        # so acpi_listen would not report any events while this
        # script is executed
        sleep $TIMEOUT
        STATUS=$(</proc/acpi/button/lid/LID/state)

        if [ "${STATUS##* }" == "open" ]
        then
            log "on-lid-close-action interrupted"
        else
            # lock screen
            log "locking screen"
            xsu "$SCREEN_LOCK"
            # take action
            log "$@"
            ERROR=$( { "$@"; } 2>&1 )
            log "$ERROR"

        fi
    fi
}

log "$@"
# close or open?
close=$3
# check if we are on ac- or on battery-power
on_ac_power
if [ $? -ne 0 ]
then
    # BATTERY
    log "on battery power"
    # suspend to ram
    execute_command $SUSPEND
else
    # AC
    log "on AC power"
    # switch-off screen
    execute_command xsu "xset dpms force off"
fi

_________________
Göögle is evil!
To protect your privacy search the net with
https://www.ixquick.com
Back to top
View user's profile Send private message
Yminus
Tux's lil' helper
Tux's lil' helper


Joined: 06 Jan 2008
Posts: 144

PostPosted: Thu Jun 14, 2012 11:29 pm    Post subject: Reply with quote

I had to fix the script since the dynamic user detection failed under some circumstances.

The fixed version is now on github 8)
_________________
Göögle is evil!
To protect your privacy search the net with
https://www.ixquick.com
Back to top
View user's profile Send private message
khayyam
Veteran
Veteran


Joined: 07 Jun 2012
Posts: 1307

PostPosted: Fri Jun 15, 2012 1:05 am    Post subject: Reply with quote

M wrote:
Code:
XUSER=$(ps aux | grep [x]init | awk '{print $1}')


or .. to not use any additional calls to grep ... or pipes.

Code:
XUSER=$(awk '$11 ~ /xinit/{print $1}' <(ps aux))


best ... khay
Back to top
View user's profile Send private message
khayyam
Veteran
Veteran


Joined: 07 Jun 2012
Posts: 1307

PostPosted: Fri Jun 15, 2012 1:38 am    Post subject: Reply with quote

Yminus wrote:
Code:
[...]
        home=$(grep $xuser /etc/passwd)
        home=${home#*:*:*:*:*:}
        home=${home%:*}
        log "home is: $home"
[...]

This just seems wasteful to me ... a suggestion:

Code:
home=$(awk -v user=${xuser} -F":" '{if ($1 == user) {print $6}}' /etc/passwd)


best ... khay
Back to top
View user's profile Send private message
Yminus
Tux's lil' helper
Tux's lil' helper


Joined: 06 Jan 2008
Posts: 144

PostPosted: Fri Jun 15, 2012 8:29 am    Post subject: Reply with quote

khayyam wrote:
Yminus wrote:
Code:
[...]
        home=$(grep $xuser /etc/passwd)
        home=${home#*:*:*:*:*:}
        home=${home%:*}
        log "home is: $home"
[...]

This just seems wasteful to me ... a suggestion:

Code:
home=$(awk -v user=${xuser} -F":" '{if ($1 == user) {print $6}}' /etc/passwd)


best ... khay


Thanks for the suggestion. I have to admit that my 3 lines of code look cumbersome. But one could argue that calling awk is more wasteful than using bash builtins.
_________________
Göögle is evil!
To protect your privacy search the net with
https://www.ixquick.com
Back to top
View user's profile Send private message
khayyam
Veteran
Veteran


Joined: 07 Jun 2012
Posts: 1307

PostPosted: Fri Jun 15, 2012 9:04 am    Post subject: Reply with quote

Yminus wrote:
Thanks for the suggestion. I have to admit that my 3 lines of code look cumbersome. But one could argue that calling awk is more wasteful than using bash builtins.


Your welcome ... but, no, your not simply using builtins, your calling grep. The awk does the equivelant task of grep plus extracts the value for var. Also, unlike grep awk doesn't parse the whole file for 'string', only the field, which in text parsing has greater economy.

but again ... just a suggestion

best ... khay
Back to top
View user's profile Send private message
Yminus
Tux's lil' helper
Tux's lil' helper


Joined: 06 Jan 2008
Posts: 144

PostPosted: Fri Jun 15, 2012 9:08 am    Post subject: Reply with quote

khayyam wrote:
... but, no, your not simply using builtins, your calling grep.


Oh, you're right - I have overlooked that.
_________________
Göögle is evil!
To protect your privacy search the net with
https://www.ixquick.com
Back to top
View user's profile Send private message
khayyam
Veteran
Veteran


Joined: 07 Jun 2012
Posts: 1307

PostPosted: Fri Jun 15, 2012 9:59 am    Post subject: Reply with quote

Yminus wrote:
Oh, you're right - I have overlooked that.

Well, its not a big issue, but when trying to make something more economical often you want to avoid pipes and grep (which is guite greedy).

Also ... when you "fallback to static username", rather than do this make the initial assignment cover both possible values for var

Code:
xuser=${$(awk '$11 ~ /xinit/{print $1}' <(ps aux)):-${XUSER}}


with this the subsequent test isn't necessary .. if 'xuser' is empty then the value of '${XUSER}' is used (though I would change the var names to something less confusing ... var1, var2 ... rather than case seperation).

best ...

khay
Back to top
View user's profile Send private message
Yminus
Tux's lil' helper
Tux's lil' helper


Joined: 06 Jan 2008
Posts: 144

PostPosted: Wed Jun 20, 2012 12:58 pm    Post subject: Reply with quote

khayyam wrote:
Yminus wrote:
Code:
[...]
        home=$(grep $xuser /etc/passwd)
        home=${home#*:*:*:*:*:}
        home=${home%:*}
        log "home is: $home"
[...]

This just seems wasteful to me ... a suggestion:

Code:
home=$(awk -v user=${xuser} -F":" '{if ($1 == user) {print $6}}' /etc/passwd)


This seems like a good suggestions which I will adopt.

khayyam wrote:
Code:
XUSER=$(awk '$11 ~ /xinit/{print $1}' <(ps aux))

As I already mentioned above this way of determine the X user does not work on my machine - I have no xinit process running.

But even if the above worked this one:
Code:
xuser=${$(awk '$11 ~ /xinit/{print $1}' <(ps aux)):-${XUSER}}

would give a "bad substitution" error in bash.
_________________
Göögle is evil!
To protect your privacy search the net with
https://www.ixquick.com
Back to top
View user's profile Send private message
khayyam
Veteran
Veteran


Joined: 07 Jun 2012
Posts: 1307

PostPosted: Wed Jun 20, 2012 4:26 pm    Post subject: Reply with quote

Yminus wrote:
khayyam wrote:
Code:
XUSER=$(awk '$11 ~ /xinit/{print $1}' <(ps aux))

As I already mentioned above this way of determine the X user does not work on my machine - I have no xinit process running.

OK .. but the 'who | sed' doesn't return anything either, which is the only reason I suggested using 'xinit'.

Code:
% if [[ -z $(who | sed -ne "s/^\([^ ]*\)[ ]*:0.*/\1/p") ]] ; then echo 'the subsitution is empty!' ; fi
the subsitution is empty!

The script "works" as it'll "fallback to static username", and so the asignment is essencially useless. So:

Code:
xuser=$(awk '{print $1}' <(who))

Yminus wrote:
But even if the above worked this one:
Code:
xuser=${$(awk '$11 ~ /xinit/{print $1}' <(ps aux)):-${XUSER}}

would give a "bad substitution" error in bash.

hehe ... well too bad for bash, as the syntax is correct:

Code:
% echo $SHELL
/bin/zsh
% echo $USERNAME
khayyam
% USERNAME=${$(awk '$11 ~ /xinit/{print $1}' <(ps aux)):-${USERNAME}}
% echo $USERNAME
khayyam
% exec bash -l
$ if [[ -z $USERNAME ]] ; then echo "USERNAME is empty" ; fi
USERNAME is empty
$ USERNAME=$(awk '$11 ~ /xinit/{print $1}' <(ps aux))
$ if [[ -n $USERNAME ]] ; then echo 'whats all this talk about "bad substitution"' ${USERNAME}'?' ; fi
whats all this talk about "bad substitution" khayyam?
$ export TEST_PARAM_EXPANSION=${TEST_PARAM_EXPANSION:-foo}
$ echo $TEST_PARAM_EXPANSION
foo
$ export TEST_PARAM_EXPANSION=${TEST_PARAM_EXPANSION:-ba}
$ echo $TEST_PARAM_EXPANSION
foo
$ export VAR=${$(echo ${TEST_PARAM_EXPANSION}):-ba}
bash: VAR=${$(echo ${TEST_PARAM_EXPANSION}):-ba}: bad substitution

So, bash doesn't allow the use of a substitution within a parameter expansion .. doh! I guess with bash you have to go the extra mile:

Code:
xuser=$(awk '$11 ~ /xinit/{print $1}' <(ps aux))
xuser=${xuser:-$XUSER}

... and no obvious reason why.

best ... khay
Back to top
View user's profile Send private message
Yminus
Tux's lil' helper
Tux's lil' helper


Joined: 06 Jan 2008
Posts: 144

PostPosted: Wed Jun 20, 2012 7:52 pm    Post subject: Reply with quote

khayyam wrote:
OK .. but the 'who | sed' doesn't return anything either, which is the only reason I suggested using 'xinit'.
Code:
% if [[ -z $(who | sed -ne "s/^\([^ ]*\)[ ]*:0.*/\1/p") ]] ; then echo 'the subsitution is empty!' ; fi
the subsitution is empty!

The script "works" as it'll "fallback to static username", and so the asignment is essencially useless.

That's not true - at least not on my machine. Here it returns the user that is logged in at the X-session, also in zsh. And the recent version of the regexp only reports the first occurrence of the user logged into X:
Code:
echo "$(who | sed -ne "0,/^\([^ ]*\)[ ]*:0.*/s//\1/p")"
lars


What is your output of who?

khayyam wrote:
So:

Code:
xuser=$(awk '{print $1}' <(who))



Given this output of who:
Code:
who
root     tty1         2012-06-20 21:47
lars     :0.0         2012-06-17 04:06
lars     pts/0        2012-06-17 09:10 (:0.0)
lars     pts/1        2012-06-20 10:30 (:0.0)
lars     pts/2        2012-06-17 20:03 (:0.0)
lars     pts/3        2012-06-20 11:17 (:0.0)

The above would return:
Code:
awk '{print $1}' <(who)
root
lars
lars
lars
lars
lars
or
Code:
echo $xuser
root lars lars lars lars lars

This is not what I want.
_________________
Göögle is evil!
To protect your privacy search the net with
https://www.ixquick.com
Back to top
View user's profile Send private message
khayyam
Veteran
Veteran


Joined: 07 Jun 2012
Posts: 1307

PostPosted: Wed Jun 20, 2012 10:00 pm    Post subject: Reply with quote

Yminus wrote:
khayyam wrote:
OK .. but the 'who | sed' doesn't return anything either, which is the only reason I suggested using 'xinit'.
Code:
% if [[ -z $(who | sed -ne "s/^\([^ ]*\)[ ]*:0.*/\1/p") ]] ; then echo 'the subsitution is empty!' ; fi
the subsitution is empty!

The script "works" as it'll "fallback to static username", and so the asignment is essencially useless.

That's not true - at least not on my machine. Here it returns the user that is logged in at the X-session, also in zsh. And the recent version of the regexp only reports the first occurrence of the user logged into X:
Code:
echo "$(who | sed -ne "0,/^\([^ ]*\)[ ]*:0.*/s//\1/p")"
lars

What is your output of who?

Code:
% who
khayyam tty1         2012-06-20 20:12
% awk '/bin\/X/' <(ps aux)
root      1658  0.9  0.3  15176  7656 tty7     S<s+ 20:12   1:36 /usr/bin/X -nolisten tcp :0 -auth /home/khayyam/.serverauth.1640
% who | sed -ne "s/^\([^ ]*\)[ ]*:0.*/\1/p"
[EMPTY]

As 'who' uses /var/log/wtmp it means that if something other than login writes to it then of course there will be confusion ... I suspect that either your terminal application is creating your shells as 'login shells' or your using 'screen' and it likewise isn't configure not to write to wtmp. Essencially you should only see one per tty (login), unless you explicitly create login shells ... 'who' has no relation to X11 sessions.

Yminus wrote:
khayyam wrote:
Code:
xuser=$(awk '{print $1}' <(who))

Given this output of who:
Code:
who
root     tty1         2012-06-20 21:47
lars     :0.0         2012-06-17 04:06
lars     pts/0        2012-06-17 09:10 (:0.0)
lars     pts/1        2012-06-20 10:30 (:0.0)
lars     pts/2        2012-06-17 20:03 (:0.0)
lars     pts/3        2012-06-20 11:17 (:0.0)

The above would return:
Code:
awk '{print $1}' <(who)
root
lars
lars
lars
lars
lars

This is not what I want.

Agreed its not ideal ... but that's why I first opted for getting the user 'xuser' from xinit! The above is based on the assumption that only one user is logged in and so one string would be returned, but as 'who' simply dishes up whatevers in wtmp, it can't really be relied on. So the above "awk '{print $1}' <(who)" is as reliable as your 'who | sed'. We could make the awk more robust, but it doesn't really matter, because the input is from wtmp, and as you've seen, sometimes it'll fail ... sometimes not.

The only reliable method is to parse currently running processes, be that xinit or some other component of Xorg ...

best ... khay
Back to top
View user's profile Send private message
Yminus
Tux's lil' helper
Tux's lil' helper


Joined: 06 Jan 2008
Posts: 144

PostPosted: Wed Jun 20, 2012 10:58 pm    Post subject: Reply with quote

Yes, this script works under the assumption that the login manager registers the user in the utmp/wtmp. For any other case there is the fallback.

I think to to parse currently running processes is not feasible since it differs to much from desktop to desktop. I guess even dbus won't work as a common denominator.

I could add the parsing for the xinit process as another alternative method - but I cannot test its reliability.
_________________
Göögle is evil!
To protect your privacy search the net with
https://www.ixquick.com
Back to top
View user's profile Send private message
khayyam
Veteran
Veteran


Joined: 07 Jun 2012
Posts: 1307

PostPosted: Thu Jun 21, 2012 12:23 am    Post subject: Reply with quote

Yminus wrote:
Yes, this script works under the assumption that the login manager registers the user in the utmp/wtmp.

Well, ppurka's post is re window-managers and not login managers, the formers should not need to write to wtmp, and the later only if sees to it that its removed at logout. Anyhow, regardless, relying on wtmp is hit or miss.

Yminus wrote:
For any other case there is the fallback.

OK, but if setting a var you remove the whole need (and purpose) of any auto asignment. I wouldn't have a fallback at all, I'd have it fail, but only after all possible methods have been exhausted.

Yminus wrote:
I think to to parse currently running processes is not feasible since it differs to much from desktop to desktop. I guess even dbus won't work as a common denominator.

Well, I would say they will all be running X11 and so that is a common denominator, its going to more consistant than 'who'. If I examine my own processes I can see two methods of grabbing xuser, the first xinit, and the second via the xauthority string. Neither of these may be consistant with your currently running X11 session (I assume using a login manager), but this doesn't matter because you can test until the var has some value.

Yminus wrote:
I could add the parsing for the xinit process as another alternative method - but I cannot test its reliability.

You don't need to, all you need do is add additional tests for the two common methods of starting an X11 session, 1). via startx/xinit, and 2). via a login manager. One or other of these should return a value (but again using wtmp will be unreliable).

Anyhow ... my inital reason for getting started in this thread was simply to point out some areas where code could be optimised, and now I feel I'm having to justify having comented at all, and explain why bash, or awk, do what they do ... and so I'll bow out ...

best ... khay
Back to top
View user's profile Send private message
ppurka
Advocate
Advocate


Joined: 26 Dec 2004
Posts: 3067

PostPosted: Thu Jun 21, 2012 12:54 am    Post subject: Reply with quote

khayyam wrote:
Yminus wrote:
Yes, this script works under the assumption that the login manager registers the user in the utmp/wtmp.

Well, ppurka's post is re window-managers and not login managers, the formers should not need to write to wtmp, and the later only if sees to it that its removed at logout. Anyhow, regardless, relying on wtmp is hit or miss.
No, my post was with regard to login managers. Login managers should update the utmp/wtmp on successful login. They have always done so.

And lightdm is one of the newfangled half-done login managers which doesn't write to utmp/wtmp. And yet you see it being used in popular distros nowadays. It just seems like apathy of the devs, who don't care about supporting traditional *nix methods.
_________________
emerge --quiet redefined | E17 vids: I, II
Back to top
View user's profile Send private message
khayyam
Veteran
Veteran


Joined: 07 Jun 2012
Posts: 1307

PostPosted: Thu Jun 21, 2012 6:39 am    Post subject: Reply with quote

ppurka wrote:
No, my post was with regard to login managers. Login managers should update the utmp/wtmp on successful login. They have always done so.

I stand corrected ...

best ... khay
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Portage & Programming All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum