入り口に戻る

原文はこちら。翻訳にあたって、オープンソースグループ・ジャパンの MIT ライセンスの訳を参考にした。

# X Session Management Library(日本語訳)

## X Consortium Standard

### Ralph Mor

X Consortium

X Version 11, Release 7.7

Version 1.0

Copyright © 1993, 1994 X Consortium

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium.

X Window System is a trademark of The Open Group.

(訳)

(本ソフトウェアおよび関連する文書のファイル（以下「ソフトウェア」）の複製を取得した全ての人物に対し、以下の条件に従うことを前提に、ソフトウェアを無制限に扱うことを無償で許可する。これには、ソフトウェアの複製を使用、複製、改変、結合、公開、頒布、再許諾、および/または販売する権利、およびソフトウェアを提供する人物に同様の行為を許可する権利が含まれるが、これらに限定されない。)

(上記の著作権表示および本許諾表示を、ソフトウェアの全ての複製または実質的な部分に記載するものとする。)

(ソフトウェアは「現状有姿」で提供され、明示的であるか黙示的であるかを問わず、いかなる種類の保証も行われない。ここでいう保証には、商品性、特定目的への適合性、および権利の非侵害性に関する保証も含まれるが、これらに限定されるものではない。THE X CONSORTIUM は、契約、不法行為、またはその他の行為であるかを問わず、ソフトウェアまたはソフトウェアの使用もしくはその他に取り扱いに起因または関連して生じるいかなる請求、損害賠償、その他の責任について、一切の責任を負わない。)

(X Consortium の名称は、この表示に記載されている場合を除き、X Consortium の事前の書面による承認を得ずに、宣伝であろうとその他の形であろうと、ソフトウェアの販売を促進するもの、またはソフトウェアの使用その他の扱いを奨励するものに使用してはならない。)

(X Window System は The Open Group の商標である。)

## 第一章 セッション・マネジメントの概要

X Session Management Protocol (XSMP) は、利用者がセッションを保存・復元する仕組みについて、標準規格を打ち立てるために考案された。セッション(session)とは、クライアントの集合であり、一つ一つのクライアントは独自の状態を持つ。セッションの管理はセッション・マネージャ(session manager)と呼ばれるネットワーク・サービスで行う。セッション・マネージャは利用者に成り代わってクライアントに命令を発する。この命令でクライアントに状態保存を促したり、クライアントを停止したりすることができる。クライアントは次のような形で自身の状態を保存する。即ち、後々クライアントを再起動することができ、かつ、まるで一度も停止されていなかったかのようにクライアントの処理を再開できる形で保存する。クライアントの「状態」には、編輯中のファイルの情報や、ファイル中の現在の書込み位置、未処理のデータ交換の開始点に関する情報等を含めることが可能である。クライアントを再起動する手段については、本プロトコルでは定めない。

本プロトコルでは都合上、セッション・マネージャのクライアント(client)を「セッション・マネージャに対する接続」と定義している。クライアントは大抵、単一の X ディスプレイ(display) に接続されたアプリケーション・プログラムを実行するプロセスであるが、必ずしもこのような形態を採らなければいけない訳ではない。複数の X ディスプレイに接続されたクライアントも、接続される X ディスプレイを持たないクライアントも存在する。

## 第二章 セッション・マネジメント・ライブラリ

Session Management Library(セッション・マネジメント・ライブラリ、SMlib)は、XSMP の低水準 C 言語インターフェイスである。Xt のような、より高水準のツールキット(toolkits)によって、セッション管理の細部の多くがクライアントから隠蔽されることを予定している。セッション・マネージャ側が用いる高水準ツールキットの開発も行われるかもしれないが、今のところそのような取組みは存在しない。

SMlib は大まかに二つの部分に分けられる。

- 一つは、セッションに参加するクライアントが呼び出す関数群。

- 一つは、セッション・マネージャが呼び出す関数群。

両方の関数群を用いて入れ籠型セッション・マネージャ(nested session manager)として振舞うアプリケーションもあり得る。これは、アプリケーションがセッション・マネージャであるとともに、他のセッションのクライアントでもあるということである。一例を挙げれば、メール文の編輯のためのテキスト・エディタを起動するメール・プログラムがある。このメール・プログラムは正規のセッションの一員でありながら、同時にテキスト・エディタに対してセッション・マネージャとして振舞う。

クライアントの初期化作業は、セッション・マネージャへの接続とクライアント ID(client-ID) の取得から成る。このクライアント ID によって、セッション中のクライアントを一意に同定する(uniquely identifies)ことができる。セッション・マネージャは、セッション中の各クライアントのプロパティ群一覧を保持している。これらのプロパティ群には、クライアントの環境と、格別に重要である、クライアントの再起動の仕方とを記載する(後者はプロパティ SmRestartCommand に記す)。クライアントが自身の状態を保存する際、クライアントの複数の実体(instantiation)を一つ一つ独立に管理し得るような形で保存作業を行うことが期待される。例えば、クライアントが特定の実体の状態を記録する際、そのファイル名の一部にこの識別子を含めても良い。また、クライアント ID はクライアントを再起動するための命令文( SmRestartCommand)の中にも記録する。こうすることでクライアントは再開後も同じ識別子を保持できるようになる。

一度クライアントがセッション・マネージャに対して初期化された後は、同クライアントはそのセッション・マネージャから来るメッセージに応答可能でなければならない。例えば、クライアントは状態の保存や終了作業を行うよう求められるかもしれない。終了する場合、セッション・マネージャは各クライアントに対して、利用者とやり取りして終了を取り消す機会を与えても良い。

## 第三章 SMlib の ICE への依存を知る

X Session Management Protocol は、Inter-Client Exchange (ICE) Protocol を基礎にして、その上層として作られている。ICE プロトコルは、単一の接続の上で、複数プロトコルの多重通信を行う目的で設計された。結果として、SMlib を利用するには、ICE ライブラリの仕組みに関する若干の知識が求められる。

ICE ライブラリでは、メッセージを処理するためにコールバックを利用する。クライアントは、ICE 接続上で読み込むべきデータを発見した時、関数 `IceProcessMessages` を呼び出す。`IceProcessMessages` は、メッセージ・ヘッダ部分を読み込み、その中にある主たる命令コード(major opcode)を確認して、そのメッセージがどのプロトコルに基づくものなのかを判断する。次いで、対応するプロトコル・ライブラリが同メッセージを開くために駆動される。そして、そのメッセージはコールバックを通じてクライアントへ回される。

次の点を特に心得ておくべきである。即ち、SMlib を利用するアプリケーションには、ICE 接続上に読み込むべきデータが生じた時にそれを検知するコードが備わっていなければならない。これは、ICE 接続を示すファイル記述子に対して `select` を呼び出すことで実現できる。しかし、より一般的には、`XtAppAddInput` を用いて、ICE 接続上に読み込むべきデータが生じる度に `IceProcessMessages` を呼び出すコールバックを登録しておくことになろう。

さらに込み入った点を述べれば、どのファイル記述子に対して `select` を実行するべきなのかを知るには、ICE 接続がどのように生成されるのかを理解しておく必要がある。クライアント側において、セッション・マネージャとの接続を開くには、`SmcOpenConnection` を呼び出さなければならない。`SmcOpenConnection` は内部で `IceOpenConnection` を呼び出している。 `IceOpenConnection` は、クライアントとセッション・マネージャの間に既設の ICE 接続が存在しないか判断する。大抵の場合、接続は未だ存在せず、新しい ICE 接続が作られる。ここが重要な点であるが、接続は共用される可能性があるので、クライアント側では ICE 接続が何時作成・破棄されたのかは分からない。これを解決するため、ICE ライブラリでは、ICE 接続の開設・閉鎖の度に呼び出される看視手続き(watch procedures)をアプリケーションが登録できるようになっている。看視手続きを用いることで、`select` 呼出しの対象となる ICE ファイル記述子の一覧から記述子を削除し、あるいは同一覧に対して記述子を追加することができるようになる。

セッション・マネージャ側では事情が少し異なる。セッション・マネージャは、ICE 接続の生成過程を自在に制御できる。セッション・マネージャは先ず、クライアントからの接続申請の受付けを始めるために、`IceListenForConnections` を呼び出さなければならない。接続の試みがあれば、セッション・マネージャは `IceAcceptConnection` を呼び出し、次いで新しい ICE ファイル記述子を、`select` 呼出しの対象となる記述子の一覧に加える。

ICE 接続に関係するライブラリ関数について、さらに詳しく知りたければ、規格文書「Inter-Client Exchange Library」を見よ。

## 第四章 ヘッダファイルとライブラリ名

アプリケーションは(セッション・マネージャとクライアントの両者は)、ヘッダファイル <`X11/SM/SMlib.h`> を取り込む(include)ものとする。このヘッダファイルでは、SMlib の全てのデータ型と関数型を定義する。`SMlib.h` はヘッダファイル <`X11/SM/SM.h`> を取り込む(include)。SM.h では SMlib の全ての定数を定義する。

SMlib が ICE に依存しているので、アプリケーションは 、“`-lSM` `-lICE`” の指定を用いて、SMlib と ICElib の双方を結合(link)するものとする。

## 第五章 セッション・マネジメントのクライアント側関数 Smc Functions

この章では、セッション・マネジメントのクライアントが以下の動作をどのようにして行うのかを述べる。

- セッション・マネージャへの接続

- 接続の切断

- コールバックの修正

- セッション・マネージャのプロパティの設定、削除、取得

- 利用者とのやり取り

- 「Save Yourself」の要求

- 「Save Yourself Phase 2」の要求

- 「Save Yourself」の完了

- Smc の情報取得関数の利用

- エラー処理

## セッション・マネージャに接続する

セッション・マネージャに対する接続を開設するには、`SmcOpenConnection` を用いる。

`SmcConn SmcOpenConnection(`char *network_ids_list, SmPointer context, int xsmp_major_rev, int xsmp_minor_rev, unsigned long mask, SmcCallbacks *callbacks, char *previous_id, char **client_id_ret, int error_length, char *error_string_ret`)`;

`network_ids_list` | セッション・マネージャの ID(複数)を指定する。
`context` | 不透明型オブジェクトへのポインタ、もしくは `NULL`。ICE 接続の共有を許すか否かの判定に用いる(以下を参照)。
`xsmp_major_rev` | XSMP の主たる版番号(major version)。アプリケーションが対応している版の中、最も新しい版の番号。
`xsmp_minor_rev` | XSMP の従たる版番号(minor version)。アプリケーションが対応している版の中、最も新しい版の番号(上の `xsmp_major_rev` に従う範囲で)。
`mask` | どのコールバックを登録するのかを示す取捨表(mask)。(訳註：次の引数の中身を選り分ける)
`callbacks` | 登録するコールバックの群。このコールバック群は、セッション・マネージャから届いたメッセージへの応答に用いられる。
`previous_id` | 前回セッションからのクライアント ID。
`client_id_ret` | 戻り値として、今セッションで使用するクライアント ID が入る。
`error_length` | 引数 `error_string_ret` の長さ。
`error_string_ret` | エラーがあれば、ここに null 文字終端のエラー・メッセージが入る。引数 `error_string_ret` は利用者の用意した記憶領域を参照する。`error_length` で指定されたバイト数しか使われない。

引数 `network_ids_list` は、セッション・マネージャのネットワーク ID 群をコンマで区切って並べた、null 文字終端の文字列である。`network_ids_list` が `NULL` であれば、環境変数 `SESSION_MANAGER` の値を用いることになる。ネットワーク ID の一つ一つは、以下の書式で記す。

`tcp/``<hostname>``:``<portnumber>` | もしくは
`decnet/``<hostname>``::``<objname>` | もしくは
`local/``<hostname>``:``<path>` |

まず最初のネットワーク ID を用いて接続を試みる。それが失敗したら、二番目のネットワーク ID を用いて接続を試みる。以下同様に試行。

接続が確立すると、`SmcOpenConnection` は、続いてセッション・マネージャにクライアントを登録する。クライアントが前回セッションに属していて、今回再起動される場合、`previous_id` には前回セッションにおけるクライアント ID を表す null 文字終端の文字列を容れる。クライアントが初めてセッションに加わるのであれば、`previous_id` は `NULL` に設定するものとする。`previous_id` が指定されたものの、セッション・マネージャに無効であると判定された場合、SMlib は `previous_id` を `NULL` に設定して、再度クライアントの登録を試みる。

`SmcOpenConnection` が成功すれば、戻り値として `SmcConn` 型の不透明な接続ポインタが返り、引数 `client_id_ret` にそのセッションで使用するクライアント ID が入る。`client_id_ret` は用が済んだ時 `free` で解放するものとする。`SmcOpenConnection` が蹉跌した場合、同関数は戻り値として `NULL` を返し、`error_string_ret` に失敗の理由を入れる。

SMlib では、セッション・マネージャへの接続を確立するにあたって、ICE プロトコルを利用していることに注意する。クライアントとセッション・マネージャの間に既に ICE 接続が存在する場合、セッション・マネジメントでも同 ICE 接続を利用する可能性がある。

引数 context によって、他のプロトコルと ICE 接続を共有することに対するクライアント側の態度を示す。context が `NULL` であれば、当関数の呼出者は常に接続の共有を試みる。context が `NULL` でなければ、呼出方は、自身が指定したものとは異なる、NULL でない context と結びついた既設の ICE 接続を用いない。

先に述べたように(第三章、SMlib の ICE への依存を知る)、クライアントは何時 ICE 接続が生成・破棄されるのかを看視しておく必要がある(`IceAddConnectionWatch` と `IceRemoveConnectionWatch` を用いて)。そして同者は、`select` によって ICE 接続上の読み込むべきデータの存在を検知する度に、`IceProcessMessages` を呼び出さなければならない。詳しい情報は規格文書「Inter-Client Exchange Library」を参照。

引数 callbacks には、セッション・マネージャからのイベントに応答する際に用いるコールバックの一群を渡す。引数 mask によって、設定するコールバックが何れと何れなのかを指定する。この版(SMlibの)で名前が出ているコールバックは全て必須である。引数 mask は、同ライブラリの将来の版において後方互換性を保つために必要なものである。

`mask` の値を作るには、下記の値を組み合わせ、論理和をとる。

`SmcSaveYourselfProcMask`
`SmcDieProcMask`
`SmcSaveCompleteProcMask`
`SmcShutdownCancelledProcMask`

クライアントは、各コールバックに対して一つづつ、クライアント・データへのポインタを付録することができる。SMlib がコールバックを呼び出す時、同ポインタは引数としてコールバックに渡ることになる。

    typedef struct {

    	struct {
    		SmcSaveYourselfProc callback;
    		SmPointer client_data;
    	} save_yourself;

    	struct {
    		SmcDieProc callback;
    		SmPointer client_data;
    	} die;

    	struct {
    		SmcSaveCompleteProc callback;
    		SmPointer client_data;
    	} save_complete;

    	struct {
    		SmcShutdownCancelledProc callback;
    		SmPointer client_data;
    	} shutdown_cancelled;

    } SmcCallbacks;

### Save Yourself に応じるコールバック

「Save Yourself」に応じるコールバックの関数型は `SmcSaveYourselfProc` である。

`typedef void (*SmcSaveYourselfProc)(`SmcConn smc_conn, SmPointer client_data, int save_type, Bool shutdown, int interact_style, Bool fast`)`;

`smc_conn` | セッション・マネジメントの接続オブジェクト。
`client_data` | コールバック登録時に指定したクライアント・データ。
`save_type` | 保存する情報の種別(訳註：local、global、both)を記す。
`shut_down` | 終了作業中であるか否かを記す。
`interact_style` | 利用者とのやり取りの許可種別(訳註：none、errors、any)。
`fast` | True であれば、クライアントはできる限り速く自身の状態を保存する。

セッション・マネージャは、クライアントの拓本を採りたい(checkpoint)時に、あるいは終了作業の直前に、クライアントに対して「Save Yourself」メッセージを送る。これによってクライアントは自身の状態を保存できるようになる。クライアントは、同メッセージに対する応答として 0 回以上の `SmcSetProperties` を呼び出し、同クライアントの再起動方法を記すプロパティを更新する。全てのプロパティを設定し終えたら、クライアントは `SmcSaveYourselfDone` を呼び出す。

引数 `interact_style` が `SmInteractStyleNone` であれば、クライアントは状態保存の作業中に利用者とやり取りしてはいけない。`interact_style` が `SmInteractStyleErrors` であれば、クライアントは異常事態が生じた場合に限って利用者とやり取りしてもよい。`interact_style` が `SmInteractStyleAny` であれば、クライアントは自由に利用者とやり取りできる。一度に一つのクライアントしか利用者とやり取りできないため、クライアントは、`SmcInteractRequest` を呼び出した後、セッション・マネージャから「Interact」メッセージが届くのを待たなければならない。利用者とのやり取りを終えたクライアントは `SmcInteractDone` を呼び出す。クライアントが `SmcInteractRequest` を呼び出して良いのは、「Save Yourself」メッセージを受信してから `SmcSaveYourselfDone` を呼び出すまでの間に限られる。

引数 `save_type` が `SmSaveLocal` であれば、クライアントは、その時点での自身の状態を映すようにプロパティ群を更新しなければならない。踏み込んで云えば、クライアントは、同クライアントの利用者から見える状態を復元するのに十分な情報を保存するものであり、他の利用者から見える状態に影響を与えるべきではない。`save_type` が `SmSaveGlobal` であれば、利用者は、クライアントがその全てのデータを恒久的、且つ広域に利用可能な記録装置に保存することを望んでいるということである。`save_type` が `SmSaveBoth` であれば、クライアントは上記の作業の両方を行うものとする(クライアントは先ず恒久的記録装置にデータを保存し、その後に自身のプロパティ群を更新する)。

以下に例を挙げる。

- ワード・プロセッサ(word processor)に `SmSaveLocal` 型の「Save Yourself」が届いた場合、同ワード・プロセッサは一時ファイルを作成し、そこに以下の情報を書き込む。即ち、編輯中のファイルのその時点における中身、カーソルの位置、及び編輯を行っているセッションの他の情報を書き込む。同者は次いで、その一時ファイルを見つけるのに十分な情報を SmRestartCommand プロパティに記録する。

- ワード・プロセッサに `SmSaveGlobal` 型の「Save Yourself」が届いた場合、同ワード・プロセッサは単純に編輯中のファイルを保存する。

- ワード・プロセッサに `SmSaveBoth` 型の「Save Yourself」が届いた場合、同ワード・プロセッサは先ず編輯中のファイルを保存する。次に同者は一時ファイルを作成し、そこにカーソルの位置や編輯中のファイルは何れなのかといった情報を書き込む。最後に、その一時ファイルを見つけるのに十分な情報を SmRestartCommand プロパティに記録する。

引数 `shutdown` は、システムが終了作業中であるか否かを表す。この引数の値の真偽によって、利用者とのやり取りの形に異同がある。終了作業中でなければ、クライアントは自身の状態を保存し、「Save Complete」メッセージを待ち受ける。終了作業中であれば、クライアントは自身の状態を保存した後、「Die」メッセージもしくは「Shutdown Cancelled」メッセージが同者に届くまで、利用者とのやり取りを差し控えなければならない。

引数 `fast` は、クライアントができる限り速く状態保存を行うべきか否かを表す。例えば、電源が落ちそうであるとセッション・マネージャに知れた時、同セッション・マネージャは `fast` を `True` に設定するであろう。

### Die に応じるコールバック

「Die」メッセージに応じるコールバックの関数型は `SmcDieProc` である。

`typedef void (*SmcDieProc)(`SmcConn smc_conn, SmPointer client_data`)`;

`smc_conn` | セッション・マネジメントの接続オブジェクト。
`client_data` | コールバック登録時に指定したクライアント・データ。

セッション・マネージャは、停止したいクライアントに対して「Die」メッセージを送信する。同メッセージを受信したクライアントは、`SmcCloseConnection` の呼出しで応じる。上品に振舞うセッション・マネージャは、「Die」メッセージに先立って「Save Yourself」メッセージを送付するはずである。

### Save Complete に応じるコールバック

「Save Complete」に応じるコールバックの関数型は `SmcSaveCompleteProc` である。

`typedef void (*SmcSaveCompleteProc)(`SmcConn smc_conn, SmPointer client_data`)`;

`smc_conn` | セッション・マネジメントの接続オブジェクト。
`client_data` | コールバック登録時に指定したクライアント・データ。

### Shutdown Cancelled に応じるコールバック

「Shutdown Cancelled」に応じるコールバックの関数型は `SmcShutdownCancelledProc` である。

`typedef void (*SmcShutdownCancelledProc)(`SmcConn smc_conn, SmPointer client_data`)`;

`smc_conn` | セッション・マネジメントの接続オブジェクト。
`client_data` | コールバック登録時に指定したクライアント・データ。

セッション・マネージャが「Shutdown Cancelled」メッセージを送信するのは、利用者とのやり取りの中で終了処理が取り消された時である(第五章五節「利用者とやり取りする」を参照)。このメッセージを受信したクライアントは、まるで終了作業が存在しなかったかのように処理を続けることができる。クライアントがまだ `SmcSaveYourselfDone` を呼び出していないのであれば、同者は、保存作業を中断して、引数 success に `False` を付した `SmcSaveYourselfDone` を呼び出しても良いし、保存作業を続行して、その結果を引数 `success` に付して `SmcSaveYourselfDone` を呼び出しても良い。

## 接続を閉じる

セッション・マネージャとの接続を閉じるには、`SmcCloseConnection` を用いる。

`SmcCloseStatus SmcCloseConnection(`SmcConn smc_conn, int count, char **reason_msgs`)`;

`smc_conn` | セッション・マネジメントの接続オブジェクト。
`count` | 「接続を断つ理由」を構成する文字列の数。
`reason_msgs` | 接続を断つ理由。

引数 `reason_msgs` は、セッションからの退座がクライアントにとって想定内のものであれば、大抵は `NULL` である。それ以外の場合、同引数には、終了の理由を表す、null 文字終端かつ Compound Text 形式の文字列の配列が入る。セッション・マネージャは、この理由を表すメッセージを利用者に表示するものとする。

SMlib はセッション・マネージャに対する接続を確立するのに ICE プロトコルを使用しているので、セッション・マネジメント以外の様々なプロトコルが同一 ICE 接続上で運用されている可能性がある。`SmcCloseConnection` が呼び出された時、実際に ICE 接続が閉鎖されるのは、同 ICE 接続上の全てのプロトコルが終了済みの場合に限られる。ICE 接続が開閉される度に呼び出されるコールバックの設営方法を知るには、ICElib の規格文書を調べて `IceAddConnectionWatch` と `IceRemoveConnectionWatch` を見れば良い。大抵は、このコールバックを用いて、`select` の(あるいは`XtAppAddInput` 及び `XtRemoveInput`の)呼出し対象たる有効な ICE ファイル記述子群に対し、記述子の追加・削除を行う。

`SmcCloseConnection` は次の値の何れか一つを返す。

- `SmcClosedNow` - (SmcConn が使用していた)ICE 接続はこの時点で閉鎖された。看視手続き(watch procedures)が呼び出され、接続資源も解放された。

- `SmcClosedASAP` - 接続の中で入出力エラーが発生しているか、もしくは `SmcCloseConnection` が入れ籠状態の `IceProcessMessages` の中から呼び出されている(訳註：参考：X11R7.7/lib/libSM-1.2.1/src/sm_client.c、X11R7.7/lib/libICE-1.0.8/src/shutdown.c)。看視手続きがこの時点で呼び出されているものの、接続資源は「できる限り早く」解放される(入れ籠の階層が 0 に達し、`IceProcessMessages` が `IceProcessMessagesConnectionClosed` を返した時)。

- `SmcConnectionInUse` - 接続は、他の有効なプロトコルによって使用されているので、この時点では閉鎖されなかった。

## コールバックを変更する

`SmcOpenConnection` で設定したコールバックを変更するには、`SmcModifyCallbacks` を用いる。

`void SmcModifyCallbacks(`SmcConn smc_conn, unsigned long mask, SmcCallbacks *callbacks`)`;

`smc_conn` | セッション・マネジメントの接続オブジェクト。
`mask` | どのコールバックを変更するのかを示す取捨表(mask)。(訳註：次の引数の中身を選り分ける)
`callbacks` | 新しいコールバック群。

引数 `mask` の値を作るには、下記の値を組み合わせ、論理和をとる。

`SmcSaveYourselfProcMask`
`SmcDieProcMask`
`SmcSaveCompleteProcMask`
`SmcShutdownCancelledProcMask`

## セッション・マネジメントのプロパティを設定、削除、取得する

クライアントのセッション・マネジメント・プロパティを設定するには、`SmcSetProperties` を用いる。

`void SmcSetProperties(`SmcConn smc_conn, int num_props, SmProp **props`)`;

`smc_conn` | セッション・マネジメントの接続オブジェクト。
`num_props` | プロパティの数。
`props` | 設定するプロパティの配列。

設定するプロパティ群は、プロパティのポインタの配列で指定する。関数 `SmcSetProperties` によって、プロパティの元の値は上書きされる。セッションが再開された時、セッション・マネージャは必ずしもプロパティの値を復元しないということに注意する。このため、クライアントはセッション・マネージャを、アプリケーション固有の状態情報を記録するデータベースとして使うべきではない。

セッション・マネジメント・プロパティと構造体 SmProp に関する説明は、第七章、「セッション・マネジメント・プロパティ」にある。

クライアントが前に設定したプロパティを削除するには、`SmcDeleteProperties` を用いる。

`void SmcDeleteProperties(`SmcConn smc_conn, int num_props, char **prop_names`)`;

`smc_conn` | セッション・マネジメントの接続オブジェクト。
`num_props` | プロパティの数。
`prop_names` | 削除するプロパティの配列。

クライアントが前に記録したプロパティを取得するには、`SmcGetProperties` を用いる。

`Status SmcGetProperties(`SmcConn smc_conn, SmcPropReplyProc prop_reply_proc, SmPointer client_data`)`;

`smc_conn` | セッション・マネジメントの接続オブジェクト。
`prop_reply_proc` | 目的のプロパティが返ってきた時に呼び出されるコールバック。
`client_data` | コールバック `SmcPropReplyProc` の呼出し時に渡す、クライアント・データへのポインタ。

`SmcGetProperties` の戻り値は、失敗すれば 0、成功すれば正の値である。

このライブラリは目的のプロパティが返ってくるまで入力待機する(block)するわけではない、という点に注意する。`SmcPropReplyProc` 型のコールバックは、そのようなやり方ではなく、データの準備が整い次第呼び出される。(訳註：セッション・マネージャが関数 SmsReturnProperties を呼び出し、その内部で SM_PropertiesReply メッセージが発行されたら、_SmcProcessMessage がそれを拾い、コールバックを実行する(libSM-1.2.1)。)

`typedef void (*SmcPropReplyProc)(`SmcConn smc_conn, SmPointer client_data, int num_props, SmProp **props`)`;

`smc_conn` | セッション・マネジメントの接続オブジェクト。
`client_data` | `SmcGetProperties` で設定した、クライアント・データへのポインタ。
`num_props` | 取得したプロパティの数。
`props` | 取得したプロパティの配列。

一つ一つプロパティを解放するには、`SmFreeProperty` を用いる(第八章「データの解放」を参照)。ポインタの配列自体は `free` を用いて解放する。

## 利用者とやり取りする

`interact_style` に `SmInteractStyleErrors` もしくは `SmInteractStyleAny` を付した「Save Yourself」メッセージが届いた時、クライアントは利用者とやり取りすることができる。一度に一つのクライアントしか利用者とやり取りできないため、クライアントは `SmcInteractRequest` を呼び出した上で、セッション・マネージャから「Interact」メッセージが返るのを待たなければならない。

`Status SmcInteractRequest(`SmcConn smc_conn, int dialog_type, SmcInteractProc interact_proc, SmPointer client_data`)`;

`smc_conn` | セッション・マネジメントの接続オブジェクト。
`dialog_type` | クライアントが利用者に提示するダイアログ・ウィンドウの種類。
`interact_proc` | セッション・マネージャから「Interact」メッセージが届いた時に呼び出すコールバック。
`client_data` | 「Interact」メッセージが届いた時にコールバック `SmcInteractProc` に渡す、クライアント・データへのポインタ。

`SmcInteractRequest` の戻り値は、失敗すれば 0、成功すれば正の値である。

引数 `dialog_type` には、`SmDialogError` もしくは `SmDialogNormal` を指定する。クライアント側がエラー・ダイアログによる表示を望めば前者を、通常のダイアログによる表示を望めば後者を用いる。

もし終了処理(shutdown)が進行中であれば、利用者に、終了作業を中止するという選択肢が与えられる可能性もあるので注意する。終了作業が中止された場合、まだ利用者とやり取りしていないクライアントには、「Interact」メッセージの代わりに「Shutdown Cancelled」メッセージが届くことになる。

セッション・マネージャから「Interact」メッセージが届くと、コールバック `SmcInteractProc` が呼び出される。

`typedef void (*SmcInteractProc)(`SmcConn smc_conn, SmPointer client_data`)`;

`smc_conn` | セッション・マネジメントの接続オブジェクト。
`client_data` | コールバック登録時に指定したクライアント・データ。

利用者とのやり取り(「Interact」メッセージを受けた)の後には、`SmcInteractDone` を呼び出すものとする。

`void SmcInteractDone(`SmcConn smc_conn, Bool cancel_shutdown`)`;

`smc_conn` | セッション・マネジメントの接続オブジェクト。
`cancel_shutdown` | `True` であれば、利用者が終了処理全体の中止を要求していることを意味する。

引数 `cancel_shutdown` に `True` を入れて良いのは、元になった「Save Yourself」において shutdown が `True` に、`interact_style` が `SmInteractStyleErrors` もしくは `SmInteractStyleAny` に設定されていた場合に限られる。

## Save Yourself を要求する

セッション・マネージャに拓本を採るよう(checkpoint)要請するには、`SmcRequestSaveYourself` を用いる。

`void SmcRequestSaveYourself(`SmcConn smc_conn, int save_type, Bool shutdown, int interact_style, Bool fast, Bool global`)`;

`smc_conn` | セッション・マネジメントの接続オブジェクト。
`save_type` | 保存する情報の種別(訳註：local、global、both)を記す。
`shutdown` | 終了作業中であるか否かを記す。
`interact_style` | 利用者とのやり取りの許可種別(訳註：none、errors、any)。
`fast` | True であれば、クライアントはできる限り速く自身の状態を保存する。
`global` | 「Save Yourself」の受け手を決める。

引数 `save_type`、`shutdown`、`interact_style`、及び `fast` に関しては、 The `save_type`, `shutdown`,第五章一の一、「Save Yourself に応じるコールバック」 でより詳しく述べてある。

`global` が `True` に設定されている場合、結果として生じる「Save Yourself」はセッション中の全てのクライアントに送信される。例えば、無停電電源(Uninterruptible Power Supply、UPS)の開発者は、UPS の状態を監視するセッション・マネジメント・クライアントを提供し、電源が落ちそうな時に素早く終了処理を提起できるであろう。

`global` が `False` であれば、「Save Yourself」は、これを要求したクライアントにしか送信しないものとする。

## Save Yourself Phase 2 を要求する

「Save Yourself」を受け取ったクライアントは、自分以外の全クライアントの状態情報を保存するため、それらが静遊状態(quiescent)となった時に通知してもらえるよう要請することができる。そのためには、`SmcRequestSaveYourselfPhase2` を用いる。

`Status SmcRequestSaveYourselfPhase2(`SmcConn smc_conn, SmcSaveYourselfPhase2Proc save_yourself_phase2_proc, SmPointer client_data`)`;

`smc_conn` | セッション・マネジメントの接続オブジェクト。
`save_type_phase2_proc` | セッション・マネージャから「Save Yourself Phase 2」メッセージが届いた時に呼び出されるコールバック。
`client_data` | 「Save Yourself Phase 2」メッセージが届いた時にコールバック `SmcSaveYourselfPhase2Proc` に渡す、クライアント・データへのポインタ。

`SmcRequestSaveYourselfPhase2` の戻り値は、失敗すれば 0、成功すれば正の値である。

この要求関数を使用するのは、他のクライアント群を管理するクライアントである(例えば、ウィンドウ・マネージャ、ワークスペース・マネージャなど)。マネージャ(管理者)は、管理対象クライアント全てが遊転状態(idle state)となり、それらの状態情報が保存可能になったことを確かめなければならない。

## Save Yourself を完了する

「Save Yourself」メッセージを受けて状態情報を保存した後には、`SmcSaveYourselfDone` を呼び出すものとする。

`void SmcSaveYourselfDone(`SmcConn smc_conn, Bool success`)`;

`smc_conn` | セッション・マネジメントの接続オブジェクト。
`success` | 「Save Yourself」の作業を成功裡に終えた場合、`True` を入れる。

クライアントは、セッション・マネージャへの登録の後、`SmcSaveYourselfDone` を呼び出す前に、各必須プロパティ(required property)を少なくとも一回設定していなければならない。

## Smc の情報取得関数を使う

`int SmcProtocolVersion(`SmcConn smc_conn`)`;

`SmcProtocolVersion` は、引数のセッションで運用されているセッション・マネジメント・プロトコルの主たる版番号(major version)を返す。

`int SmcProtocolRevision(`SmcConn smc_conn`)`;

`SmcProtocolRevision` は、引数のセッションで運用されているセッション・マネジメント・プロトコルの従たる版番号(minor version)を返す。

`char *SmcVendor(`SmcConn smc_conn`)`;

`SmcVendor` は、セッション・マネージャの開発者(owner)を表す何らかの識別文字列を返す。この文字列は `free` を呼び出して解放するものとする。

`char *SmcRelease(`SmcConn smc_conn`)`;

`SmcRelease` は、セッション・マネージャの版番号(release number)を表す文字列を返す。この文字列は `free` で解放するものとする。

`char *SmcClientID(`SmcConn smc_conn`)`;

`SmcClientID` は、引数の接続オブジェクトのクライアント ID を表す、null 文字終端の文字列を返す。この情報は `SmcOpenConnection` でも取得できる(利便性を考えて ID 取得専用の関数も用意した)。取得したクライアント ID が不用になれば、そのポインタに対して `free` を適用する。

`IceConn SmcGetIceConnection(`SmcConn smc_conn`)`;

`SmcGetIceConnection` は、引数のセッション・マネジメント接続オブジェクトが内部に保持する ICE 接続オブジェクトを返す。ICE 接続オブジェクトを用いて、接続に関する詳しい情報を得ることができる。IceConn を付して呼び出せる有用な関数を挙げれば、`IceConnectionNumber`、`IceConnectionString`、`IceLastSentSequenceNumber`、`IceLastReceivedSequenceNumber` 及び `IcePing` がある。詳細は規格文書「Inter-Client Exchange Library」を参照。

## エラー処理

セッション・マネージャからクライアントへ予期せぬプロトコル・エラーが届けられた場合、SMlib はエラー・ハンドラ(エラー処理器)を呼び出す。標準のエラー・ハンドラが始めから用意されている。このハンドラは、単にエラー・メッセージを `stderr` に表示し、エラーの重症度(severity)が致命的(fatal)であれば、終了処理に飛ぶ(exit)。クライアントは、関数 `SmcSetErrorHandler` を呼び出すことで、このエラー・ハンドラを変更することができる。

`SmcErrorHandler SmcSetErrorHandler(`SmcErrorHandler handler`)`;

`handler` | エラー・ハンドラ(エラー処理器)。標準のハンドラに戻すには `NULL` を指定する。

`SmcSetErrorHandler` の戻り値は、これまで使用していたエラー・ハンドラである。

`SmcErrorHandler` の関数型は次の通り。

`typedef void (*SmcErrorHandler)(`SmcConn smc_conn, Bool swap, int offending_minor_opcode, unsigned long offending_sequence_num, int error_class, int severity, IcePointer values`)`;

`smc_conn` | セッション・マネジメントの接続オブジェクト。
`swap` | 指定された情報(values)のバイト順交換が必要か否かを示す印。
`offending_minor_opcode` | エラーを起こしたメッセージの従命令コード(minor opcode)。
`offending_sequence_num` | エラーを起こしたメッセージの通し番号(sequence number)。
`error_class` | エラーを起こしたメッセージのエラー・クラス(error class)。
`severity` | `IceCanContinue`、`IceFatalToProtocol` もしくは `IceFatalToConnection`。
`values` | 従命令コードとエラー・クラスに応じて必要となる、追加の情報(values)。(訳註：X11R7.7/lib/libSM-1.2.1/include/X11/SM/SMlib.h では、values は「SmPointer」である。但し同ヘッダファイルにおいて「typedef IcePointer SmPointer;」。)

このエラー・ハンドラは、プロトコルに関係したエラーを処理するものであることに注意する。入出力エラーに対応するエラー・ハンドラを設定するには、`IceSetIOErrorHandler` を用いる。詳しくは規格文書「Inter-Client Exchange Library」を見よ。

## 第六章 セッション・マネジメントのサーバ側関数 Sms Functions

この章では、セッション・マネジメントのサーバが以下の動作をどのようにして行うのかを述べる。

- ライブラリの初期化

- クライアントの登録

- 「Save Yourself」メッセージの送信

- 「Save Yourself Phase 2」メッセージの送信

- 「Interact」メッセージの送信

- 「Save Complete」メッセージの送信

- 「Die」メッセージの送信

- 終了処理(shutdown)の中止

- プロパティ関連の応答

- クライアントに対する PING 送信

- クライアントの接続切断後の片付け

- Sms 情報取得関数の利用

- エラー処理

## ライブラリを初期化する

`SmsInitialize` は、セッション・マネージャが最初に呼び出す SMlib 関数である。この関数を通じて、セッション・マネージャの情報を設定し、さらに、新たなクライアントがセッション・マネージャへの接続を試みる度に呼び出されるコールバックを登録する。

`Status SmsInitialize(`const char *vendor, const char *release, SmsNewClientProc new_client_proc, SmPointer manager_data, IceHostBasedAuthProc host_based_auth_proc, int error_length, char *error_string_ret`)`;

`vendor` | セッション・マネージャの開発者を表す文字列。
`release` | セッション・マネージャの版番号(release number)を表す文字列。
`new_client_proc` | 新たなクライアントがセッション・マネージャへの接続を試みる度に呼び出されるコールバック。
`manager_data` | コールバック `SmsNewClientProc` を呼び出す時に引数として渡す、マネージャ・データへのポインタ。
`host_based_auth_proc` | ホスト名に基づく認証を行う際、その作業を担うコールバック。
`error_length` | 次の引数 `error_string_ret` の長さ。
`error_string_ret` | null 文字終端のエラー・メッセージがここに入る(メッセージがあれば)。`error_string_ret` は利用者が用意した記憶領域を参照する。`error_length` で指定したバイト数しか使われない。

関数 `SmsInitialize` を呼び出した後、セッション・マネージャは、新たな接続を待ち受けるため、関数 `IceListenForConnections` を呼び出す。以降、クライアントが接続を試みる度に、セッション・マネージャは `IceAcceptConnection` を呼び出す。

認証について詳しく知りたければ、第九章、「クライアントの認証」」を見よ(ホスト名に基づく認証(host based authentication)も含む)。また、ICE 接続の申請の待受けと受理については、規格文書「Inter-Client Exchange Library」を見る。

新たなクライアントがセッション・マネージャへの接続を試みる度に、コールバック `SmsNewClientProc` が呼び出される。セッション・マネージャは新しい不透明な接続オブジェクトを得て、以後のクライアントとのやり取りで常にこれを使用する(訳註：libSM-1.2.1/src/sm_manager.c の中の関数 _SmsProtocolSetupProc において、SmsNewClientProc 型のコールバックを呼び出す直前に、構造体 SmsConn 型の接続オブジェクトの変数を宣言し、領域を確保し、同接続オブジェクトのメンバの設定をしている。)。この時に、セッション・マネージャは、クライアントから送られて来るであろう種々のメッセージに応じるためのコールバック群を登録しなければならない。

`typedef Status (*SmsNewClientProc)(`SmsConn sms_conn, SmPointer manager_data, unsigned long *mask_ret, SmsCallbacks *callbacks_ret, char **failure_reason_ret`)`;

`sms_conn` | 新しい不透明な接続オブジェクト。
`manager_data` | コールバック登録時に指定したマネージャ・データへのポインタ。
`mask_ret` | 戻り値が入る。セッション・マネージャで実際に設定されたコールバックは何れと何れなのかを表す。
`callbacks_ret` | 戻り値として、セッション・マネージャに登録されたコールバック群が入る。
`failure_reason_ret` | ここに失敗の理由が入る。

`SmsNewClientProc` が失敗した時は、実値 0 の Status を返し、失敗の理由を表す文字列を `failure_reason_ret` に割り当てるものとする。この記憶領域を解放するのは SMlib の仕事である。

セッション・マネージャは、クライアントが発するイベントに応答する際に用いるコールバックの一群を登録しなければならない。引数 `mask_ret` は、コールバックの中の何れと何れが設定されたのかを表す。この版(SMlibの)で名前が出ているコールバックは全て必須である。引数 `mask_ret` は、同ライブラリの将来の版において後方互換性を保つために必要なものである。

mask の値を作るには、下記の値を組み合わせ、論理和をとる。

`SmsRegisterClientProcMask`
`SmsInteractRequestProcMask`
`SmsInteractDoneProcMask`
`SmsSaveYourselfRequestProcMask`
`SmsSaveYourselfP2RequestProcMask`
`SmsSaveYourselfDoneProcMask`
`SmsCloseConnectionProcMask`
`SmsSetPropertiesProcMask`
`SmsDeletePropertiesProcMask`
`SmsGetPropertiesProcMask`

セッション・マネージャは、各コールバックに対して、そのコールバック専用のマネージャ・データへのポインタを登録することができる。このポインタは、SMlib によってコールバックが呼び出される時、引数として渡される。

    typedef struct {
    	struct {
    		SmsRegisterClientProc callback;
    		SmPointer manager_data;
    	} register_client;

    	struct {
    		SmsInteractRequestProc callback;
    		SmPointer manager_data;
    	} interact_request;

    	struct {
    		SmsInteractDoneProc callback;
    		SmPointer manager_data;
    	} interact_done;

    	struct {
    		SmsSaveYourselfRequestProc callback;
    		SmPointer manager_data;
    	} save_yourself_request;

    	struct {
    		SmsSaveYourselfPhase2RequestProc callback;
    		SmPointer manager_data;
    	} save_yourself_phase2_request;

    	struct {
    		SmsSaveYourselfDoneProc callback;
    		SmPointer manager_data;
    	} save_yourself_done;

    	struct {
    		SmsCloseConnectionProc callback;
    		SmPointer manager_data;
    	} close_connection;

    	struct {
    		SmsSetPropertiesProc callback;
    		SmPointer manager_data;
    	} set_properties;

    	struct {
    		SmsDeletePropertiesProc callback;
    		SmPointer manager_data;
    	} delete_properties;

    	struct {
    		SmsGetPropertiesProc callback;
    		SmPointer manager_data;
    	} get_properties;

    } SmsCallbacks;

### Register Client に応じるコールバック

「Register Client」に応じるコールバックは、クライアントがセッション・マネージャに接続してから最初に呼び出されるコールバックである。その関数型は `SmsRegisterClientProc` である。

`typedef Status (*SmsRegisterClientProc)(`SmsConn sms_conn, SmPointer manager_data, char *previous_id`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。
`manager_data` | コールバック登録時に指定したマネージャ・データ。
`previous_id` | 前回セッションで使用していたクライアント ID。

クライアントとの間で他のやり取りを始める前に、セッション・マネージャにクライアントを登録しなければならない。

前回セッションからのクライアントを再起動する場合、`previous_id` には前回セッションで使用していたクライアント ID を表す、null 文字終端の文字列が入る。用が済んだ時は `previous_id` のポインタに対して `free` を呼び出す。クライアントが初めてセッションに加わるのであれば、`previous_id` は `NULL` となる。

`previous_id` が無効なものであれば、この時点では、セッション・マネージャは申請してきたクライアントを登録するべきではない。当コールバックは実値 0 の Status を返すものとし、これを受けてエラー・メッセージが同クライアントに送信される。同クライアントは previous_id を `NULL` にして、再度登録を試みるものとする。

それ以外の場合、セッション・マネージャは関数 `SmsRegisterClientReply` (後述)を呼び出し、唯一無二のクライアント ID でクライアントを登録するものとする。この時、コールバック `SmsRegisterClientProc` は実値 1 の Status を返すものとする。

### Interact Request に応じるコールバック

「Interact Request」に応じるコールバックの関数型は `SmsInteractRequestProc` である。

`typedef void (*SmsInteractRequestProc)(`SmsConn sms_conn, SmPointer manager_data, int dialog_type`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。
`manager_data` | コールバック登録時に指定したマネージャ・データ。
`dialog_type` | クライアントが利用者に提示しようとするダイアログ・ウィンドウの種類。

`interact_style` を `SmInteractStyleErrors` もしくは `SmInteractStyleAny` に設定した「Save Yourself」メッセージがクライアントに届いた時、同クライアントは利用者とやり取りすることができる。一度に一つのクライアントしか利用者とやり取りできないので、クライアントは利用者とのやり取りの許可を求めなければならない。セッション・マネージャは、利用者とのやり取りを望む全てのクライアントから成る待ち行列(queue)を保持するものとする。またセッション・マネージャは、一度に一つのクライアントへ「Interact」メッセージを送信し、次のクライアントへ進む前に「Interact Done」メッセージを待ち受ける。

引数 `dialog_type` には、`SmDialogError` もしくは `SmDialogNormal` を指定する。クライアント側がエラー・ダイアログによる表示を望めば前者を、通常のダイアログによる表示を望めば後者を用いる。

もし終了処理(shutdown)が進行中であれば、利用者に終了処理を中止するという選択肢が与えられる可能性もある。終了処理が中止された場合(これは「Interact Done」メッセージで指定する)、セッション・マネージャは、利用者とのやり取りを求めていたクライアントの一つ一つに対して「Shutdown Cancelled」メッセージを送信するものとする。

### Interact Done に応じるコールバック

クライアントが利用者とのやり取りを終えた時は、コールバック `SmsInteractDoneProc` を呼び出す。

`typedef void (*SmsInteractDoneProc)(`SmsConn sms_conn, SmPointer manager_data, Bool cancel_shutdown`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。
`manager_data` | コールバック登録時に指定したマネージャ・データ。
`cancel_shutdown` | 利用者が終了処理全体の中止を要求しているのか否かを記す。

終了処理を中止できるのは、元になった「Save Yourself」において shutdown が `True` に、`interact_style` が `SmInteractStyleErrors` もしくは `SmInteractStyleAny` に設定されていた場合に限られる、ということに注意。

### Save Yourself Request に応じるコールバック

「Save Yourself Request」に応じるコールバックの関数型は `SmsSaveYourselfRequestProc` である。

`typedef void (*SmsSaveYourselfRequestProc)(`SmsConn sms_conn, SmPointer manager_data, int save_type, Bool shutdown, int interact_style, Bool fast, Bool global`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。
`manager_data` | コールバック登録時に指定したマネージャ・データ。
`save_type` | 保存する情報の種別(訳註：local、global、both)を記す。
`shutdown` | 終了作業中であるか否かを記す。
`interact_style` | 利用者とのやり取りの許可種別(訳註：none、errors、any)。
`fast` | True であれば、クライアントはできる限り速く自身の状態を保存する。
`global` | 「Save Yourself」の受け手を決める。

「Save Yourself Request」によって、セッション・マネージャにチェックポイント処理(checkpoint、保存処理)あるいは終了処理(shutdown)を始めるよう促す。引数 `save_type`、`shutdown`、`interact_style`、及び `fast` については、第六章三節、『「Save Yourself」メッセージを送信する』を参照。

`global` が `True` に設定されていれば、結果として生じる「Save Yourself」メッセージは全てのアプリケーションに送信される。`global` が `False` であれば、「Save Yourself」は、これを要求した当のクライアントにしか送信されない。

### Save Yourself Phase 2 Request に応じるコールバック

「Save Yourself Phase 2 Request」に応じるコールバックの関数型は `SmsSaveYourselfPhase2RequestProc` である。

`typedef void (*SmsSaveYourselfPhase2RequestProc)(`SmsConn sms_conn, SmPointer manager_data`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。
`manager_data` | コールバック登録時に指定したマネージャ・データ。

他のクライアント群を管理するクライアントから、この要求が送られて来る(例えば、ウィンドウ・マネージャ、ワークスペース・マネージャなど)。マネージャ(管理者)は、管理対象クライアント全てが遊転状態(idle state)となり、それらの状態情報が保存可能になったことを確かめなければならない。

### Save Yourself Done に応じるコールバック

クライアントが「Save Yourself」メッセージを受けて、自身の状態情報を保存し終えた時、 `SmsSaveYourselfDoneProc` が呼び出される。

`typedef void (*SmsSaveYourselfDoneProc)(`SmsConn sms_conn, SmPointer manager_data, Bool success`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。
`manager_data` | コールバック登録時に指定したマネージャ・データ。
`success` | `True` であれば、「Save Yourself」の作業が成功裡に終わったことを意味する。

クライアントは、セッション・マネージャへの登録の後、「Save Yourself Done」を送信する前に、各必須プロパティ(required property)を少なくとも一回設定していなければならない。

### Connection Closed に応じるコールバック

クライアントが適切に終了した場合(即ち、同者が `SmcCloseConnection` を呼び出した場合)、コールバック `SmsCloseConnectionProc` が呼び出される。

`typedef void (*SmsCloseConnectionProc)(`SmsConn sms_conn, SmPointer manager_data, int count, char **reason_msgs`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。
`manager_data` | コールバック登録時に指定したマネージャ・データ。
`count` | 「接続を断つ理由」を構成する文字列の数。
`reason_msgs` | 接続を断つ理由。

セッションからの退座が利用者にとって想定内のものであれば、引数 `reason_msgs` は、大抵は `NULL` であり、引数 `count` は零(0)である。それ以外の場合、前者の引数には、終了の理由を表す、null 文字終端かつ Compound Text 形式の文字列の配列が入る。セッション・マネージャは、この理由を表すメッセージを利用者に表示するものとする。

理由を表すメッセージ群の文字列資源を解放するには、`SmFreeReasons` を呼び出す。第八章、「データの解放」も見よ。

### Set Properties に応じるコールバック

クライアントがセッション・マネジメント・プロパティの設定を試みた時、コールバック `SmsSetPropertiesProc` が呼び出される。

`typedef void (*SmsSetPropertiesProc)(`SmsConn sms_conn, SmPointer manager_data, int num_props, SmProp **props`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。
`manager_data` | コールバック登録時に指定したマネージャ・データ。
`num_props` | 設定するプロパティの数。
`props` | 設定するプロパティの配列。

設定するプロパティ群は、プロパティのポインタの配列で指定する。セッション・マネジメント・プロパティと構造体 SmProp については、第七章、「セッション・マネジメント・プロパティ」で説明する。

元々設定されていたプロパティの値は上書きされ得る。予め意味と役割(semantics)の定義されたプロパティが存在する。セッション・マネージャは、定義されていなかったプロパティがあれば、新たに記録する必要がある。

一つ一つのプロパティを解放するには、`SmFreeProperty` を用いる。第八章、「データの解放」も参照。ポインタの配列自体は `free` で解放するものとする。

### Delete Properties に応じるコールバック

クライアントがセッション・マネジメント・プロパティの削除を試みた時は、コールバック `SmsDeletePropertiesProc` が呼び出される。

`typedef void (*SmsDeletePropertiesProc)(`SmsConn sms_conn, SmPointer manager_data, int num_props, char **prop_names`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。
`manager_data` | コールバック登録時に指定したマネージャ・データ。
`num_props` | 次の引数におけるプロパティの数
`prop_names` | 削除するプロパティの配列。

削除するプロパティは文字列の配列で指定する。セッション・マネジメント・プロパティと構造体 SmProp については、第七章、「セッション・マネジメント・プロパティ」で説明する。

### Get Properties に応じるコールバック

クライアントが自分の設定したプロパティの群を取り出そうとした時、コールバック `SmsGetPropertiesProc` が呼び出される。

`typedef void (*SmsGetPropertiesProc)(`SmsConn sms_conn, SmPointer manager_data`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。
`manager_data` | コールバック登録時に指定したマネージャ・データ。

セッション・マネージャは、`SmsReturnProperties` で応え、相手のクライアントが設定したプロパティ全てを返すものとする。

## クライアントを登録する

コールバック `SmsRegisterClientProc` を受けて、クライアントを登録するには、`SmsRegisterClientReply` を用いる。

`Status SmsRegisterClientReply(`SmsConn sms_conn, char *client_id`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。
`client_id` | 唯一無二のクライアント ID を表す、null 文字終端の文字列。

`SmsRegisterClientReply` の戻り値は、失敗すれば 0、成功すれば正の値である。失敗となるのは、SMlib が、クライアント ID の複製を保持するための領域を確保できなかった時である。この複製は、SMlib の内部の用途に充てる。

クライアントが自身の登録を試みた時に、`NULL` ではない `previous_id` を指定した場合、`client_id` をその `previous_id` と一致させるものとする。

さもなければ、`client_id` には、セッション・マネージャが新たに生成した唯一無二のクライアント ID を容れる。加えて、セッション・マネージャは、クライアントの登録後直ちに `type` = `Local`、`shutdown` = `False`、`interact-style` = `None`、及び `fast` = `False` とした「Save Yourself」メッセージを送信する。

一度クライアントにクライアント ID が割り当てられると、同クライアントはその ID を恒久的に使い続けるということに注意する。クライアントが一旦終了した後に再起動した場合、再び同じ ID が割り当てられる。クライアント ID が、計算機から計算機へ、利用者から利用者へ、セッション・マネージャからセッション・マネージャへ、クライアントの同一性を保ちながら流通していくのが望ましい。これと、クライアント ID の永続性とを合わせると、クライアント ID は地球上で(globally)唯一無二である必要がある、ということになる。(訳註：？？？)

地球上で(globally)唯一無二のクライアント ID を生成するには、関数 `SmsGenerateClientID` を呼び出す。(訳註：???)

`char *SmsGenerateClientID(`SmsConn sms_conn`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。

ID を生成できなかった場合、戻り値は `NULL` である。さもなければ、クライアント ID が関数の戻り値となる。このクライアント ID は、用が済んだ時は `free` で解放するものとする。

## 「Save Yourself」メッセージを送信する

「Save Yourself」をクライアントに送信するには、`SmsSaveYourself` を用いる。

`void SmsSaveYourself(`SmsConn sms_conn, int save_type, Bool shutdown, int interact_style, Bool fast`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。
`save_type` | 保存する情報の種別(訳註：local、global、both)を記す。
`shutdown` | 終了作業中であるか否かを記す。
`interact_style` | 利用者とのやり取りの許可種別(訳註：none、errors、any)。
`fast` | True であれば、クライアントはできる限り速く自身の状態を保存する。

セッション・マネージャは、クライアントの拓本を採るため(checkpoint it)、あるいは終了処理の直前に、クライアントに「Save Yourself」メッセージを送信する。これによって、クライアントは自身の状態情報を保存できるようになる。クライアントは、0 個以上の「Set Properties」メッセージで応じ、クライアントの再起動方法を記すプロパティ群を更新する。全てのプロパティを設定し終えたら、クライアントは「Save Yourself Done」メッセージを送信する。

`interact_style` が `SmInteractStyleNone` であれば、クライアントは、状態保存の最中に利用者とやり取りしてはならない。`interact_style` が `SmInteractStyleErrors` であれば、クライアントは異状が発生した時に限って利用者とやり取りすることができる。`interact_style` が `SmInteractStyleAny` の場合、クライアントは、目的を問わず自由に利用者とやり取りして良い。クライアントは、利用者とのやり取りに先立って、「Interact Request」メッセージを送信し、且つセッション・マネージャから「Interact」メッセージが送られてくるのを待たなければならない。クライアントは、利用者とのやり取りを終えたところで、「Interact Done」メッセージを送信するものとする。「Interact Request」メッセージは、「Save Yourself」の後、且つ「Save Yourself Done」の前であれば、何時送信してもよい。

引数 `save_type` が `SmSaveLocal` であれば、クライアントは、その時点での自身の状態を映すようにプロパティ群を更新しなければならない。踏み込んで云えば、クライアントは、同クライアントの利用者から見える状態を復元するのに十分な情報を保存するべきであり、他の利用者から見える状態に影響を与えるべきではない。`save_type` が `SmSaveGlobal` であれば、利用者は、クライアントがその全てのデータを恒久的、且つ広域に利用可能な記録装置に保存することを望んでいるということである。`save_type` が `SmSaveBoth` であれば、クライアントは上記の作業の両方を行うものとする(クライアントは先ず恒久的記録装置にデータを保存し、その後に自身のプロパティ群を更新する)。

引数 `shutdown` は、システムが終了作業中であるか否かを表す。この引数の値の真偽によって、利用者とのやり取りの形に異同がある。終了作業中でなければ、クライアントは保存作業を行なって、通常の処理を再開することができる。終了作業中であれば、クライアントは自身の状態を保存した後、「Die」メッセージもしくは「Shutdown Cancelled」メッセージが同者に届くまで、利用者とのやり取りを差し控えなければならない。これは、保存作業後に利用者が行ったものは全て失われてしまうからである。

引数 `fast` は、クライアントができる限り速く状態保存を行うべきか否かを表す。例えば、電源が落ちそうであるとセッション・マネージャに知れた時、同セッション・マネージャは `fast` を `True` に設定する。

## 「Save Yourself Phase 2」メッセージを送信する

クライアントに「Save Yourself Phase 2」メッセージを送信するには、`SmsSaveYourselfPhase2` を用いる。

`void SmsSaveYourselfPhase2(`SmsConn sms_conn`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。

セッション・マネージャは、前もって「Save Yourself Phase 2 Request」メッセージを送ってきていたクライアントに対して、当メッセージを送信する。このメッセージを受け取ったクライアントは次の事実を知る。即ち、同者以外の全てのクライアントの状態が定まり、これらのクライアントと結び付いた自身の状態情報を保存できるようになったことを知る。

## 「Interact」メッセージを送信する

クライアントに「Interact」メッセージを送信するには、`SmsInteract` を用いる。

`void SmsInteract(`SmsConn sms_conn`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。

「Interact」メッセージを受信したクライアントは、利用者とのやり取りを独占することができる。クライアントは、利用者とのやり取りを終えた時、セッション・マネージャに対して「Interact Done」メッセージを送信しなければならない。

## 「Save Complete」メッセージを送信する

クライアントに「Save Complete」メッセージを送信するには、`SmsSaveComplete` を用いる。

`void SmsSaveComplete(`SmsConn sms_conn`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。

セッション・マネージャは、チェックポイント処理(checkpoint、セッションの状態を保存する処理)を終えた時、このメッセージを送信する。これ以後、クライアントは自由に状態を変更することができるようになる。

## 「Die」メッセージを送信する

クライアントに「Die」メッセージを送信するには、`SmsDie` を用いる。

`void SmsDie(`SmsConn sms_conn`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。

セッション・マネージャは、終了する前に、自身が「Die」メッセージを送ったクライアントのそれぞれから、「Connection Closed」メッセージが戻って来るのを待ち受けるものとする。その際、所定の時間が過ぎれば自動的に終了する。

## 終了処理を中止する

終了処理(shutdown)を中止するには、`SmsShutdownCancelled` を用いる。

`void SmsShutdownCancelled(`SmsConn sms_conn`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。

当関数の呼出し以後、クライアントはまるで終了作業が存在しなかったかのように処理を続けることができる。クライアントは、まだ「Save Yourself Done」メッセージを送信していないのであれば、保存作業を中止した上で、引数 success に `False` を付して「Save Yourself Done」を送信してもよいし、あるいは、保存作業を続行し、その結果を引数 `success` に反映させて「Save Yourself Done」を送信してもよい。

## プロパティを返す

「Get Properties」メッセージを受けて、セッション・マネージャは `SmsReturnProperties` を呼び出す。

`void SmsReturnProperties(`SmsConn sms_conn, int num_props, SmProp **props`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。
`num_props` | プロパティの数。
`props` | クライアントに引き渡すプロパティの配列。

プロパティ群の引き渡しには、プロパティを指すポインタの配列を用いる。セッション・マネジメント・プロパティと構造体 SmProp については、第七章、「セッション・マネジメント・プロパティ」で説明する。

## クライアントに PING を送信する

クライアントが依然として健在か否かを調べるには、ICE ライブラリに備わっている関数 `IcePing` を用いる。そのためには、`SmsGetIceConnection` を用いて、ICE 接続を取得しなければならない(第六章十二節、「Sms の情報取得関数を使う」を見よ)。

`Status IcePing(`IceConn ice_conn, IcePingReplyProc ping_reply_proc, IcePointer client_data`)`;

`ice_conn` | 有効な ICE 接続オブジェクト。
`ping_reply_proc` | PING に対する返信が届いた時に呼び出すコールバック。
`client_data` | コールバック `IcePingReplyProc` を呼び出す際に、このポインタを渡す。

PING に対する返信が用意できた時は(もし返信が存在すれば)、コールバック `IcePingReplyProc` が呼び出される。セッション・マネージャは、ある種の待受け期限を備えるものとし、その期限を過ぎれば、同者はクライアントが予期せず終了したものと見做す。

`typedef void (*IcePingReplyProc)(`IceConn ice_conn, IcePointer client_data`)`;

`ice_conn` | 有効な ICE 接続オブジェクト。
`client_data` | `IcePing` の呼び出し時に指定したクライアント・データ。

## クライアントの接続切断後の片付け

セッション・マネージャに「Connection Closed」メッセージが届いた時、あるいは、他の方法を通じてクライアントの接続切断を検知した時、同セッション・マネージャは接続オブジェクトを解放するために関数 `SmsCleanUp` を呼び出すものとする。

`void SmsCleanUp(`SmsConn sms_conn`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。

## Sms の情報取得関数を使う

`int SmsProtocolVersion(`SmsConn sms_conn`)`;

`SmsProtocolVersion` は、引数のセッションで運用されているセッション・マネジメント・プロトコルの主たる版番号(major version)を返す。

`int SmsProtocolRevision(`SmsConn sms_conn`)`;

`SmsProtocolRevision` は、引数のセッションで運用されているセッション・マネジメント・プロトコルの従たる版番号(minor version)を返す。

`char *SmsClientID(`SmsConn sms_conn`)`;

`SmsClientID` は、引数の接続オブジェクトのクライアント ID を表す、null 文字終端の文字列を返す。クライアント ID が用済みになった時は、そのポインタに対して `free` を呼び出すものとする。

クライアントのホスト名(host name)を取得するには、`SmsClientHostName` を用いる。このホスト名はクライアントの再起動に必要となる。

`char *SmsClientHostName(`SmsConn sms_conn`)`;

取得した文字列は、「`protocol``/``hostname`」の書式から成る。この中の「`protocol` 」部分には、{`tcp`, `decnet`, `local`} の何れか一つが入る。取得した文字列が用済みになった時は、同文字列に対して `free` を呼び出すものとする。

`IceConn SmsGetIceConnection(`SmsConn sms_conn`)`;

`SmsGetIceConnection` は、引数のセッション・マネジメント接続オブジェクトが内部に保持する ICE 接続オブジェクトを返す。ICE 接続オブジェクトを用いて、接続に関する詳しい情報を得ることができる。IceConn を引数にして呼び出せる有用な関数を挙げれば、`IceConnectionNumber` と `IceLastSequenceNumber` がある。詳細は規格文書「Inter-Client Exchange Library」を参照。

## エラー処理

クライアントからセッション・マネージャへ予期せぬプロトコル・エラーが届けられた場合、SMlib はエラー・ハンドラ(エラー処理器)を呼び出す。標準のエラー・ハンドラが始めから用意されている。このハンドラは、単にエラー・メッセージを表示するだけである(終了 exit しない)。セッション・マネージャは、関数 `SmsSetErrorHandler` を呼び出すことで、このエラー・ハンドラを変更することができる。

`SmsErrorHandler SmsSetErrorHandler(`SmsErrorHandler handler`)`;

`handler` | エラー・ハンドラ(エラー処理器)。標準のハンドラに戻すには `NULL` を指定する。

`SmsSetErrorHandler` の戻り値は、これまで使用していたエラー・ハンドラである。`SmsErrorHandler` の関数型は次の通り。

`typedef void (*SmsErrorHandler)(`SmsConn sms_conn, Bool swap, int offending_minor_opcode, unsigned long offending_sequence_num, int error_class, int severity, IcePointer values`)`;

`sms_conn` | セッション・マネジメントの接続オブジェクト。
`swap` | 指定された情報(values)のバイト順交換が必要か否かを示す印。
`offending_minor_opcode` | エラーを起こしたメッセージの従たる命令コード(minor opcode)。
`offending_sequence_num` | エラーを起こしたメッセージの通し番号(sequence number)。
`error_class` | エラーを起こしたメッセージのエラー・クラス(error class)。
`severity` | `IceCanContinue`、`IceFatalToProtocol`、もしくは `IceFatalToConnection`
`values` | 従命令コードとエラー・クラスに応じて必要となる、追加の情報(values)。(訳註：X11R7.7/lib/libSM-1.2.1/include/X11/SM/SMlib.h では、values は「SmPointer」である。但し同ヘッダファイルにおいて「typedef IcePointer SmPointer;」。)

このエラー・ハンドラは、プロトコルに関係したエラーを処理するものであることに注意する。入出力エラーに対応するエラー・ハンドラを設定するには、`IceSetIOErrorHandler` を用いる。詳しくは規格文書「Inter-Client Exchange Library」を見よ。

## 第七章 セッション・マネジメント・プロパティ

各プロパティは、構造体 SmProp を以って記述する。

    typedef struct {
    	char *name;	/* プロパティの名前 */
    	char *type;	/* プロパティの型 */
    	int num_vals;	/* 値(values)の数 */
    	SmPropValue *vals;	/* 値(values)の配列 */
    } SmProp;

    typedef struct {
    	int length;	/* 値(value)の長さ*/
    	SmPointer value;	/* 値(value) */
    } SmPropValue;

X セッション・マネジメント・プロトコルでは、予め定義してあるプロパティの目録を用意しており、そのプロパティの中のいくつかはクライアントによる設定が必要である。下記の表で、予め定義してあるプロパティを挙げ、どのプロパティが必須なのかを明らかにする。各プロパティには固有の型がある。

SmCARD8 型は、1 バイトの値一つから成る。SmARRAY8 型は、バイトの配列一つから成る。SmLISTofARRAY8 は、バイトの配列の配列一つから成る。

Name | Type | POSIX Type | Required
--- | --- | --- | ---
SmCloneCommand | OS-specific | SmLISTofARRAY8 | Yes
SmCurrentDirectory | OS-specific | SmARRAY8 | No
SmDiscardCommand | OS-specific | SmLISTofARRAY8 | No*
SmEnvironment | OS-specific | SmLISTofARRAY8 | No
SmProcessID | OS-specific | SmARRAY8 | No
SmProgram | OS-specific | SmARRAY8 | Yes
SmRestartCommand | OS-specific | SmLISTofARRAY8 | Yes
SmResignCommand | OS-specific | SmLISTofARRAY8 | No
SmRestartStyleHint | SmCARD8 | SmCARD8 | No
SmShutdownCommand | OS-specific | SmLISTofARRAY8 | No
SmUserID | SmARRAY8 | SmARRAY8 | Yes

* 外部の保管場所(例えば、状態情報ファイル state file)に記録される状態情報があれば、必須である。

- SmCloneCommand

  再起動するのがアプリケーションの複製であるという点を除けば、SmRestartCommand と同じようなものである。唯一の相違点は、アプリケーションの登録時にクライアント ID を申告しないことである。POSIX システムにおいては、型(type)は SmLISTofARRAY8 とする。

- SmCurrentDirectory

  POSIX に準拠したシステムにおいては、現在のディレクトリを表す値が入る。この値は SmProgram のプログラムを起動する前に設定する必要があり、プロパティの型は SmARRAY8 である。

- SmDiscardCommand

  このプロパティに入っている命令がクライアントの稼働しているホスト(接続から判断)に届くと、その時点の状態に関するあらゆる情報が破棄される。この命令が定められていなければ、セッション・マネージャはクライアントの状態情報の全てが SmRestartCommand に記述されているものと考える。POSIX システムでは、プロパティの型は SmLISTofARRAY8 とする。

- SmEnvironment

  POSIX に準拠したシステムにおいては、このプロパティの型は SmLISTofARRAY8 になる。配列中の ARRAY8 には、環境変数名とその値とが交互に格納される。

- SmProcessID

  ここに OS 独自のプロセス識別子を記す。POSIX システムにおいては、関数 `getpid` の戻り値を Latin-1 文字列(10進数表記)に変換したものを入れる。

- SmProgram

  実行中のプログラムの名前。POSIX システムにおいては、この名前に、関数 `execve` への第一引数の値を用いる。プロパティの型は SmARRAY8 とする。

- SmRestartCommand

  このプロパティに入っている命令がクライアントの稼働しているホスト(接続から判断)に届くと、クライアントが記録時の状態で再起動される。POSIX 準拠のシステムにおいては、プロパティの型は SmLISTofARRAY8 であり、この配列の各要素は `argv` 配列の各要素を表す。この再開命令は、クライアントが確実に指定されたクライアント ID で起動されるように記述するものとする。

- SmResignCommand

  プロパティ SmRestartStyleHint を `SmRestartAnyway` に設定したクライアントでは、このプロパティに次の命令を記述する。即ち、クライアントの動作結果を取り消し、保存された状態を消去する命令を記述する。例として以下の場合を考える。利用者が xmodmap を起動し、セッション・マネージャに登録し、プロパティ SmRestartStyleHint に `SmRestartAnyway` を設定し、そして xmodmap を終了する。利用者の要請を受けてセッション・マネージャがこの動作を取り消し得るように、xmodmap は動作結果を取り消す命令を SmResignCommand に登録する。

- SmRestartStyleHint

  プロパティ SmRestartStyleHint が設けられている場合、そこにはクライアントの好む再起動方式が入っている。もしこの方式が指定されていなければ、値は `SmRestartIfRunning` と見做される。以下がプロパティの値の候補である。

  Name | Value
  --- | ---
  `SmRestartIfRunning` | 0
  `SmRestartAnyway` | 1
  `SmRestartImmediately` | 2
  `SmRestartNever` | 3

  通常は `SmRestartIfRunning` 方式を用いる。クライアントが前回のセッションの終了時点で稼働中であった場合、次のセッションで同クライアントを再起動する。

  `SmRestartAnyway` 方式の指定をセッション・マネージャは次のように理解する。クライアントが現セッションの終了以前に停止(exit)していても、次のセッションで再起動するべきである、と。これがあくまで示唆(hint)に過ぎず、セッション・マネージャはどのアプリケーションを再起動させるかについて利用者の定めた方針に従う、ということに注意する。

  `SmRestartAnyway` を指定したクライアントにおいては、プロパティ SmResignCommand と SmShutdownCommand にも、クライアント終了後に状態情報を元に戻すための命令を設定するべきである。

  `SmRestartImmediately` 方式は `SmRestartAnyway` に似ている。しかし前者は、後者の示唆するものに加えて、クライアントが間を置かずに実行されることをも含意している。クライアントが終了したら、セッション・マネージャは現行のセッション内で同クライアントの再起動を図るものとする。

  `SmRestartNever` 方式が意味するのは、クライアント側が次のセッションで再起動されることを望んでいないということである。

- SmShutdownCommand

  この命令はセッション終了時に実行される。SmRestartStyleHint を `SmRestartAnyway` に設定したクライアントは停止した後も状態情報を持ち続けるので、そうしたクライアントの後片付けを行う。そのようなクライアントは依然としてセッションの一員なので、クライアントは保存済みの如何なる状態情報も消去してはならない。例として、起動時にカメラを立ち上げる機能を持ったクライアントを考える。起動後、直ちにクライアントは停止する。利用者はセッション終了時にカメラを切りたい。このクライアントは、SmRestartStyleHint を `SmRestartAnyway` に設定し、カメラを切るための SmShutdownCommand を登録する。

- SmUserID

  利用者の ID を記す。POSIX に準拠したシステムにおいては、ここに利用者の名前(構造体 passwd の メンバ `pw_name`)が入る。

## 第八章 データの解放

プロパティを一つ解放するには、`SmFreeProperty` を用いる。

`void SmFreeProperty(`SmProp *prop`)`;

`prop` | 解放するプロパティ。

コールバック `SmsCloseConnectionProc` で取得した、理由を表す文字列を解放するには、`SmFreeReasons` を用いる。

`void SmFreeReasons(`int count, char **reasons`)`;

`count` | 理由を表す文字列の数。
`reasons` | 理由を表す文字列の配列。解放作業の対象。

## 第九章 クライアントの認証

先にも述べた通り、セッション・マネジメント・プロトコルは ICE を基礎にして、その上層として作られている。ICE プロトコルにおいては、認証は二つの段階で実施する

- 第一段階は、ICE 接続を開設する時に行われる。

- 第二段階は、ICE 接続において「Protocol Setup」を行う時に実施する。

利用可能な認証方式(authentication methods)は、実装によって異なる(使用している ICElib と SMlib の実装による)。詳しくは規格文書「Inter-Client Exchange Library」を参照。

## 第十章 マルチ・スレッド環境での利用

一つのアプリケーションの複数のスレッドで SMlib を使うことを宣言するには、`IceInitThreads` を呼び出すものとする(これは SMlib に限らず ICElib を基層とするライブラリ全てで同じ)。詳しくは規格文書「Inter-Client Exchange Library」を参照。

## 第十一章 謝辞

X セッション・マネジメントの設計に携わってくれた方々にお礼を申し上げる。Jordan Brown 氏、Ellis Cohen 氏、Donna Converse 氏、Stephen Gildea 氏、Vania Joloboff 氏、Stuart Marks 氏、Bob Scheifler 氏、Ralph Swick 氏、そして Mike Wexler 氏に感謝する。

入り口に戻る