42

Following are other questions which I think I need to know:

  • From a non X Session? (meaning root isn't logged into X)

  • If multiple people were logged in on X, could I auto-detect who was on which screen, and thus programmatically detect which screen I need to launch the app on?

  • Can I launch the app as the user? ( ok I'm 99.999% sure this is a yes )

  • Can I detect if users of group X are logged in to X?

2
  • Take care that the naga_plugged.pl script finishes (or forks into background), because udev will be waiting for it to exit. Oct 3, 2011 at 13:13
  • thanks I made it a daemon by calling daemon(0,0) in the c code that naga_plugged.pl calls last. I never new they had unix forums here. They should make it be all one site instead of the new domains. Oct 4, 2011 at 3:59

5 Answers 5

26

To launch a graphical program on a user's desktop, you need to find two things: what display the user's desktop is on (the address) and what authorization cookie to use (the password).

The following command should list the local displays that the user is logged on (one per line) on most unices:

who | awk -v user="$target_user" '$1 == user && $2 ~ "^:" {print $2}'

Finding the authorization cookie is a little harder. You have to look for the user's cookie file, which is ~/.Xauthority by default (all you need is the location of the cookie file, you don't need to extract the cookie from it). That works on many systems, but not all; it depends on the display manager and how it's set up, and in particular Gdm (the default on Ubuntu) did not use the default location last I looked. I can't think of a portable way to find out the actual X cookie file. The most accurate way to find out is to find out the pid of the X process and look for the argument to the -auth option. Another way is to find a process running on that X server and grab its XAUTHORITY environment variable. If you have trouble finding the cookie file, see Open a window on a remote X display (why "Cannot open display")?

Once you have both pieces of information, put the chosen display in the DISPLAY environment variable, the chosen X authority cookie file in the XAUTHORITY environment variable, and you're set. It doesn't matter what user the program runs as; combine with su if you like.

8
  • How do your "look for the argument to the -auth option"?
    – rubo77
    Oct 16, 2014 at 15:59
  • @rubo77 With ps or htop or … Oct 16, 2014 at 16:01
  • OK, so pids=$(pgrep -u $target_user nautilus) gets the pid, and where do I have to put an -auth option?
    – rubo77
    Oct 16, 2014 at 16:08
  • 1
    @rubo77 You don't put a -auth option anywhere. You may need to look for it in the X server process's command line to figure out what to put in the XAUTHORITY environment variable. If you have the process of a client, what you need is not anything about -auth but the value of that client's XAUTHORITY variable. I don't understand what you're trying to do. You may want to ask a new question. Oct 16, 2014 at 16:12
  • I try to use your information here to solve how to Create a notification on the screen initiated by root
    – rubo77
    Oct 16, 2014 at 16:21
12

I can't completely try this since all my machines have root disabled.

To find which display a user is on, you can use the who command. The last column of output is usually the DISPLAY that the user is logged in on. Something like this could be used to grab just the display (there is likely a far more efficient way to do this, feel free to offer edits):

who | grep -m1 ^username.*\( | awk '{print $5}' | sed 's/[(|)]//g'

Then to launch a graphical X command on that display:

DISPLAY=:0 firefox &

where :0 would be replaced with whatever display you found in the first command and firefox would be replaced with whatever command you want to run. You could put this in a shell script and just use a variable.

The next part is the part I haven't tested, but I don't see why it shouldn't be possible to do:

su username -c "DISPLAY=:0 firefox"

to launch the X command as that user.

6
  • 1
    Just because root is disabled doesn't mean stuff doesn't get run as root ;) I actually need to run this as a script that's running as root. Sep 4, 2010 at 22:18
  • @xenoterracide, right. All I meant was that I couldn't test it under all possible circumstances. That is, I only tested it as root using sudo -i and couldn't be sure if the results would be different than running it after logging in as root directly. :-)
    – Steven D
    Sep 4, 2010 at 22:21
  • I had to modify the who a bit. This who | grep xeno| awk '{print $5}' | sed 's/[(|)]//g' | grep -v ^$ seems to work... Sep 4, 2010 at 22:38
  • why anyone uses grep and sed when there is already awk in the chain is beyond me.
    – user601
    Sep 5, 2010 at 8:40
  • 1
    su username -c "DISPLAY=:0 firefox" works perfectly!
    – lepe
    Aug 29, 2017 at 6:44
4

You could look at how acpid does it. E.g. when it issues xscreensaver commands or blanks the screen for each user running X or X-session.

For example under Ubuntu this file contains related stuff:

/etc/acpi/lid.sh

Contains this loop:

for x in /tmp/.X11-unix/*; do
    displaynum=`echo $x | sed s#/tmp/.X11-unix/X##`
    getXuser;
    if [ x"$XAUTHORITY" != x"" ]; then
        export DISPLAY=":$displaynum"
        grep -q off-line /proc/acpi/ac_adapter/*/state
        if [ $? = 1 ]
            then
            if pidof xscreensaver > /dev/null; then 
                su $user -c "xscreensaver-command -unthrottle"
            fi
        fi
        if [ x$RADEON_LIGHT = xtrue ]; then
            [ -x /usr/sbin/radeontool ] && radeontool light on
        fi
        if [ `pidof xscreensaver` ]; then
            su $user -c "xscreensaver-command -deactivate"
        fi
        su $user -c "xset dpms force on"
    fi
done
3
  • Specifically, the code is in /usr/share/acpi-support/power-funcs. It calls fgconsole to find the active Linux vt, then looks for an X server displaying on this console, and finds out the user from there. Then it uses ~/.Xauthority as the X cookie, which unless there's something I'm missing means that it won't actually be able to connect to the X server (Ubuntu's default setup, using gdm, doesn't store the X cookies in the user's home directory). Sep 4, 2010 at 23:06
  • @Gilles lid.sh for example does not call getXconsole. Thus, fgconsole is not used. I updated the answer with the snippet I've had in mind. And it actually works on Ubuntu. Screen is blanked when I close the lid. Sep 5, 2010 at 7:57
  • 1
    In ubuntu 14.04 I get the error getXuser: command not found
    – rubo77
    Oct 16, 2014 at 16:15
1

An extension to Gilles answer is how to find the cookie file. One way to do it may be after you set the DISPLAY environment variable (as described by Gilles), use strace to find the files xhost access. I can think of something like this in BASH:

# Set the DISPLAY variable first
DISPLAY = :0.0
# Use strace on xhost
strace xhost 2>&1 | grep access

The output from the code above will look like:

access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
access("/home/someuser/.Xauthority", R_OK) = 0

As you can clearly see, the cookie file will directly appear here.

0

In my research of finding an elegant way to display GUI or X task from limited environment such as udev rules or from the super-user, I recently created a tool to fit with it (for more details).

xpub is a shell script to get X display environment's variables regarding the current or a given TTY.

This is an example with an udev rule:

IMPORT{program}="/usr/bin/xpub", \
RUN+="/bin/su $env{XUSER} -c '/usr/bin/notify-send Hello'"

$env{ENV}: if the current-tty-user starts X, otherwise remove it.

The principle is the same for a command-line using export:

export $(xpub) ; su ${XUSER} -c 'notify-send Hello'
1
  • 1
    I suggest you make it crystal-clear that you're the author of this xpub script. Feb 2, 2017 at 14:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .