UTMP(5)

名前
utmp, wtmp - ログイン記録

書式
#include <utmp.h>

説明
utmp ファイルを見ることで、現在誰がシステムを使っているかという情報 が得られる。ただすべてのプログラムがutmpファイルを 更新しているわけではないので、実際にはそれ以上のユーザーが システムを使っている可能性がある。

警告:多くのシステムプログラムがその整合性 に(愚かにも)依存しているので、 utmp ファイル は書き込み可能にしてはいけない。utmpファイルを 不特定のユーザーから書き込み可能なままにしておくと、 偽のシステムログファイルであるとかシステムファイルの 改ざんを受けるといったリスクをおかす事になる。

このファイルはインクルードファイルで宣言されている次の ような構造体を持つエントリの繰り返しからできている。 (ここに記述してあるのは幾つかの大まかな定義のみで、 詳細はlibcのバージョンにより変わる事に注意する必要がある):

    #define UT_UNKNOWN	0
    #define RUN_LVL		1
    #define BOOT_TIME	2
    #define NEW_TIME	3
    #define OLD_TIME	4
    #define INIT_PROCESS	5
    #define LOGIN_PROCESS	6
    #define USER_PROCESS	7
    #define DEAD_PROCESS	8
    #define ACCOUNTING	9
    #define UT_LINESIZE	12
    #define UT_NAMESIZE	32
    #define UT_HOSTSIZE	256
    struct exit_status {
      short int e_termination;	/* process termination status.  */
      short int e_exit;	/* process exit status.  */
    };
    struct utmp {
      short ut_type;	/* type of login */
      pid_t ut_pid;	/* pid of login process */
      char ut_line[UT_LINESIZE];	/* device name of tty - "/dev/" */
      char ut_id[4];	/* init id or abbrev. ttyname */
      char ut_user[UT_NAMESIZE];	/* user name */
      char ut_host[UT_HOSTSIZE];	/* hostname for remote login */
      struct exit_status ut_exit;	/* The exit status of a process
    	   marked as DEAD_PROCESS. */
      long ut_session;	/* session ID, used for windowing*/
      struct timeval ut_tv;	/* time entry was made.  */
      int32_t ut_addr_v6[4];	/* IP address of remote host.  */
      char pad[20];	/* Reserved for future use.  */
    };
    /* Backwards compatibility hacks.  */
    #define ut_name ut_user
    #ifndef _NO_UT_TIME
    #define ut_time ut_tv.tv_sec
    #endif
    #define ut_xtime ut_tv.tv_sec
    #define ut_addr ut_addr_v6[0]

この構造体からユーザーの使っている端末のスペシャルファイル名、 ユーザーのログイン名、そして time(2) の書式でログインした時間がわかる。文字列フィールドは、 フィールドの長さより文字列が短い場合には、'\0' によって終端される。

最初のエントリはinit(8)コマンドがinittab(5)を 処理することで作られる。エントリを処理する前に、init(8) は各レコードのut_typeがDEAD_PROCESSでもRUN_LVL でもなく、かつPIDがut_pidであるプロセスがいない場合に、 ut_typeをDEAD_PROCESSに、ut_user、 ut_host、およびut_timeをヌルバイトでクリア して utmp を初期化する。 必要なut_idを持つ空のレコードを見つけられなかった場合、 init は新しいレコードを作る。inittabからut_idを、 ut_pid および ut_timeを現在値に、そして ut_typeをINIT_PROCESSに設定する。

getty(8)はpidでエントリを特定し、ut_typeを LOGIN_PROCESSに変更し、ut_timeを更新し、ut_line を設定すると接続が確立されるのを待つ。login(8)はユーザー認証が 終了すると、ut_typeをUSER_PROCESSに変更し、ut_time を更新し、ut_hostとut_addrを設定する。 getty(8)とlogin(8)によってことなるが、 好ましいut_pidの代わりにut_lineを使いレコードは 特定されている。

init(8)はプロセスの終了を検出した場合、ut_pidを使って utmpのエントリを特定し、ut_typeにDEAD_PROCESSを設定 し、ut_user、ut_hostそしてut_timeをヌルバイトで クリアする。

xterm(1)コマンドや他の端末エミュレータは直接USER_PROCESS のレコードを作り、/dev/ttyp%cの最後の2文字を使うか、 /dev/pts/%dのp%dを使ってut_id の値をつくり出す。 この id を持つエントリがDEAD_PROCESSであった場合には再利用し、 それ以外の場合には新しいエントリが作られる。
  可能な場合にはプロセス終了時にDEAD_PROCESSと設定し、 同様にヌルバイトでut_line、ut_time、ut_user そしてut_hostをクリアすることが奨励されている。

xdm(8) では端末が割り当てられないので utmp のレコードを 作らないようにすべきである。作るようにした場合次のような 問題が起こる:finger: can not stat /dev/machine.dom。 ftpd(8)コマンドがそうしているように、wtmp のエントリを 作るようにはすべきである。

telnetd(8)はLOGIN_PROCESSのエントリを作ると、 残りは通常通りlogin(8)が行うのでそのままにしておく。 telnet のセッションが終了した後、前述のように telnetd(8)が utmp のエントリを初期化する。

wtmp ファイルにはすべてのログインとログアウトが 記録される。そのフォーマットはログアウトした端末ではユーザー名 がヌルであることを除きまったく同じである。 それに加え、ユーザー名として"shutdown" もしくは "reboot" を持っている端末名"~"はシステムの停止(shutdown)または再起動(reboot) を意味している。またその端末名が"|"と"}"の対である場合は date(1)コマンドで変更した新／旧のシステム時間を記録している。 wtmp ファイルはlogin(1)、init(1)やいくつかの バージョンのgetty(1)により維持されている。 これらのプログラムはいずれもファイルを新たに作成したりしないので、 ファイルを削除する事で情報の記録(record-keeping)を止める事ができる。

FILES
/var/run/utmp
/var/log/wtmp

準拠
Linux でのutmpのエントリは v7/BSDやSYSVのいずれにも準拠していない: その両方が混在したものである。v7/BSDではより少しの項目しかない; もっとも重要なことは、ut_typeが無いことである。そのため v7/BSD系のプログラムでは(たとえば)死んだ状態のエントリや ログイン状態のエントリまで表示されてしまうことになった。 さらにセッション用のスロットを割り当てるためのコンフィギュレーション ファイルがない。BSDにコンフィグレーションファイルがあるのは ut_idがないからである。 Linux (SYSV系)では、コンフィグレーションファイルを必要としないで セッション用のスロットを割り当てるので、一旦設定 されてしまうとレコードのut_idは決して変更されない。 ut_idをクリアすると競合状態におちいり、utmpのエントリを 壊したり、潜在的なセキュリティホールになる可能性がある。 SYSVでの取り決めでは必要とはされていないが、上記項目をヌルバイトで クリアしておくのは、BSDでの取り決めを前提としていて、かつutmpを 更新しない多くのプログラムが動くようにするためである。 Linuxではここまで記述してきたように、行内容の表示はBSDの慣例に従っている。

SYSVではut_typeを目印にしたり、たとえば "new time"のような 通知メッセージを記録するためのみに使っている。 UT_UNKNOWNはLinuxで作られたもののようである。 ACCOUNTINGという種類はLinuxには存在しない。 SYSVにはut_host もut_addr_v6も存在しない。

ファイルを削除することでutmpへの記録を止められる 他の様々なシステムとは違い、Linuxではutmpファイルを必ずおいて おく必要がある。 who(1)コマンドが機能しないようにしたい場合には、 utmpファイルの全ユーザーに対する読み取り許可を設定しないようにする。

utmp構造体はlibc5からlibc6で変更された。そのため昔のlibc5の構造体 を使ったプログラムは /var/run/utmp や /var/log/wtmpファイルを壊してしまう。 Debian システムでは新しいutmpフォーマットを扱えるように修正 されたlibc5を含んでいる。ただしlibc5から直接アクセスして いるため、wtmpでの問題がまだ残っている。

制限
ファイルのフォーマットはマシンに依存するので、ファイルが作られた マシンもしくは同一アーキテクチャのマシン上でのみ処理する事を勧める。

BUGS
このマンページは libc5 に基づいて作られていて、最新のものでは 違っているかもしれない。

関連項目
ac(1), date(1), getutent(3), init(8), last(1), login(1), updwtmp(3), who(1)