次のページ 前のページ 目次へ

7. 別のユーザ ID からの X アプリケーション

root 特権の必要な、グラフィカルな設定ツールを実行したいとしましょう。しかし、 X セッションは普通のアカウントで実行しています。始めは奇妙に思うかも しれませんが、X サーバはツールがディスプレイにアクセスすることを許しません。 root で普通に何かしたい時に、どうすれば可能ですか? そしてどうすればこの問題を回避できますか?

ユーザ ID clientuser で X アプリケーションを起動したいが X セッションは serveruser で起動されているという、一般的な状況にしましょう。クッキーの セクションを読んでいれば、なぜ clientuser がディスプレイに アクセスできないのか分かるはずです。

~clientuser/.Xauthority はディスプレイにアクセスするための 正しいマジッククッキーを含んでいません。正しいクッキーは ~serveruser/.Xauthority にあります。

7.1 同一ホスト上の異なるユーザ

もちろん、リモート X で動作するものは、異なるユーザ ID の X でも同じように 動作します (端的には slogin localhost -l clientuser)。 クライアントホストとサーバホストがたまたま同じだというだけです。しかし、 両方のホストが同じ時、マジッククッキーの転送には近道があります。

ユーザ ID の切り替えに su を使うと仮定します。 基本的に、行わなければならないことは、su を呼ぶスクリプトを書き、 そこで su の行うコマンドを、リモート X に必要な処理を行う 適切なコードでラップすることです。 必要な処理とは DISPLAY 変数の設定とマジッククッキーの転送です。

DISPLAY の設定は比較的簡単です――su コマンドを実行する前に、 その引数として DISPLAY="$DISPLAY" を定義するだけです。 以下のようにします。

su - clientuser -c "env DISPLAY=$DISPLAY clientprogram &"

これだけでは動作しません。さらにクッキーの転送を行う必要があります。 クッキーの取得は xauth list "$DISPLAY" を使えば可能です。 このコマンドがクッキーのリストに用いる書式は、たまたま xauth add コマンドに与える際の書式に合致しています ――ちょうど必要としていたものです。

当然パイプでクッキーを渡したいところです。残念ながら、su は その標準入力からパスワードを読もうとするので、su コマンドにパイプで渡す ことは簡単ではありません。ここでも都合のいいことには、 シェルスクリプトの内部では ファイル記述子をいじり回すことができますので、これが可能になります。

clientuserclientprogram をパラメータ化し汎用化したスクリプトを 書きます。読みやすさは少し犠牲にして頑強になるように、スクリプトを改善 しましょう。以下のようになります。

#!/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>&-"

}

ほとんどの状況で、移植性と動作に十分だと考えます。 現在著者が考えうる欠点は、'$*' を使っているため、 command 内部でシングルクォートを用いると su コマンドの引数 ('$*') が壊れてしまうことです。 もし他にもなにか深刻な間違いがあったら、著者に email を書き送って ください。

スクリプトを /usr/local/bin/xsu とすれば

xsu clientuser 'command &'

とできます。

パスワードを使う限り、これ以上そう簡単にはできません。 ええ、(sudo) を使う方法もありますね。でもここでは扱いません。

7.2 クライアントユーザが root

当然、root ではないクライアントユーザが root で動作することも同様にできます。 しかし、root はすべての人の ~/.Xauthority ファイルを読むことが できるので、root の場合はより簡単です。クッキーを送る必要がありません。 DISPLAY 環境変数を設定し、XAUTHORITY~serveruser/.Xauthority を見るように設定するだけです。つまり:

su - -c "exec env DISPLAY='$DISPLAY' \
                  XAUTHORITY='${XAUTHORITY-$HOME/.Xauthority}' \
                  command"

これをスクリプト中に書くと以下のようになるでしょう。

#!/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 '$*'"

スクリプトを /usr/local/bin/xroot とすれば

xroot 'control-panel &'

とできます。

でも、もし xsu をすでに設定してあれば、 このようにしなければならない理由はありません。


次のページ 前のページ 目次へ