Next
Previous
Contents
Suppose you want to run a graphical configuration tool that requires
root privileges. However, your X session is running under your usual
account. It may seem strange at first, but the X server will not
allow the tool to access your display. How is this possible when root
can normally do anything? And how do you work around this problem?
Let's generalise to the situation where you want to an X appliation
under a user-id clientuser , but the X session was started
by serveruser . If you have read the section on cookies,
it is clear why clientuser cannot access your display:
~clientuser/.Xauthority does not contain the right magic
cookie for accessing the display. The right cookie is found in
~serveruser/.Xauthority .
Of course, anything that works for remote X also works for X from
a different user-id as well (particularly slogin localhost -l
clientuser ). It's just that the client host and the server host happen
to be the same. However, when both hosts are the same, there are some
shortcuts for transferring the magic cookie.
We'll assume that you use su to switch user-ids. Basically, what
you have to do is write a script that will call su , but wraps the
command that su executes with some code that does the necessary
things for remote X. These necessary things are setting the DISPLAY
variable and transferring the magic cookie.
Setting DISPLAY is relatively easy; it just means defining
DISPLAY="$DISPLAY" before running the su command argument. So you
could just do:
su - clientuser -c "env DISPLAY=$DISPLAY clientprogram &"
This doesn't work yet, because we still have to transfer the cookie.
We can retrieve the cookie using xauth list "$DISPLAY" . This command
happens to list the cookie in a format that's suitable for feeding back
to the xauth add command; just what we need!
We shall want to pass the cookie through a pipe. Unfortunately, it
isn't easy to pass something through a pipe to the su command,
because su wants to read the password from its standard input.
Fortunately again, in a shell script we can joggle some file descriptors
around, and get it done.
So we write a script around this, parameterizing by clientuser
and clientprogram . Let's improve the script a little while we're
at it, making it less readable but more robust. It looks like this:
#!/bin/sh
if [ $# -lt 2 ]
then echo "usage: `basename $0` clientuser command" >&2
exit 2
fi
CLIENTUSER="$1"
shift
# FD 4 becomes stdin too
exec 4>&0
xauth list "$DISPLAY" | sed -e 's/^/add /' | {
# FD 3 becomes xauth output
# FD 0 becomes stdin again
# FD 4 is closed
exec 3>&0 0>&4 4>&-
exec su - "$CLIENTUSER" -c \
"xauth -q <&3
exec env DISPLAY='$DISPLAY' "'"$SHELL"'" -c '$*' 3>&-"
}
I think this is portable and works well enough in most circumstances.
The only shortcoming I can think of right now is that, due to using
'$*' , single quotes in command will mess up quoting in the
su command argument ('$*' ). If there's anything else seriously
wrong with it, please drop me an email.
Call the script /usr/local/bin/xsu , and you can do:
xsu clientuser 'command &'
Can't be much easier, unless you get rid of the password. Yes, there
are ways for that too (sudo ), but this is not the place for that.
Obviously, anything that works for non-root client users is going to
work for root as well. However, with root you can make it even easier,
because root can read anyone's ~/.Xauthority file. There's no
need to transfer the cookie. All you have to do is set DISPLAY , and
point XAUTHORITY to ~serveruser/.Xauthority . So you can do:
su - -c "exec env DISPLAY='$DISPLAY' \
XAUTHORITY='${XAUTHORITY-$HOME/.Xauthority}' \
command"
Putting it into a script would give something like:
#!/bin/sh
if [ $# -lt 1 ]
then echo "usage: `basename $0` command" >&2
exit 2
fi
su - -c "exec env DISPLAY='$DISPLAY' \
XAUTHORITY='${XAUTHORITY-$HOME/.Xauthority}' \
"'"$SHELL"'" -c '$*'"
Call the script /usr/local/bin/xroot , and you can do:
xroot 'control-panel &'
Although, if you've set up xsu already, there's no real reason to
do this.
Next
Previous
Contents
|