ONC+ 開発ガイド

第 9 章 NIS+ プログラミングガイド

この章では NIS+ アプリケーションプログラミングインタフェースの基本原理を説明し、詳細なサンプルプログラムを提示します。 NIS+ API は、Solaris ネットワーク用のアプリケーションを構築するプログラマを対象としています。NIS+ API には、アプリケーションをサポートするための基本的な機能が用意されています。

この章の内容は、次のとおりです。

NIS+ ネットワークネームサービスが対象とするクライアント/サーバーネットワークは、数個のサーバーが 10 個のクライアントをサポートする程度のローカルエリアネットワークから、全世界のさまざまなサイトに位置する 20 〜 100 個の専用サーバーが 10,000 個ものマルチベンダークライアントをサポートし、さまざまな公衆ネットワークで連結された大規模なものまであります。

NIS+ の概要

このセクションでは、NIS+ ネットワークネームサービスのさまざまな面について説明します。

NIS+ のドメイン

NIS+ は次の図のような階層型ドメインをサポートします。

図 9–1 NIS+ のドメイン

Graphic

NIS+ の各ドメインは、組織の各部分のワークステーション、ユーザー、ネットワークサービスを記述するデータの集合です。NIS+ の各ドメインは、他のドメインとは独立に管理できます。この独立性により NIS+ は、小規模から大規模まで、広い範囲のネットワークで使用できます。

NIS+ とサーバー

各ドメインは複数のサーバーによってサポートされます。このうち中心となるサーバーをマスターサーバー、バックアップサーバーを複製サーバーといいます。マスターサーバーと複製サーバーの両方で NIS+ プログラムを実行します。オリジナルテーブルはマスターサーバーが保管し、複製サーバーはそのコピーを保存します。

NIS+ は、複製サーバーの増分更新を行います。最初にマスターサーバーを変更すると、次にその変更が自動的に複製サーバーに伝達され、名前空間全体で有効となります。

NIS+ テーブル

NIS+ では、情報がマップやゾーンファイルではなくテーブルに保存されます。NIS+ には次の図のような、16 種類の事前定義されたシステムテーブルがあります。

図 9–2 NIS+ のテーブル

Graphic

各テーブルにはそれぞれ違う種類の情報が保存されます。たとえば、Hosts テーブルには、ホスト名とインターネットアドレスのペアが保存され、Password テーブルにはネットワークユーザーに関する情報が保存されます。

NIS+ テーブルは、次の 2 つの点で NIS マップから大きく改善されています。1 つは、NIS+ テーブルでは第 1 カラム (「キー」ともいう) だけでなく任意のカラムにアクセスできる点です。このアクセスにより、NIS では必要であった hosts.byname hosts.byaddr などの複製マップが不要になりました。もう 1 つは、NIS+ テーブルの情報には、テーブルレベル、エントリレベル、カラムレベルの 3 つのレベルでアクセスできる点です。

NIS+ のセキュリティ

NIS+ のセキュリティモデルには、承認と認証の 2 つの機能があります。承認については、名前空間上の各オブジェクトごとに、どのような主体にどの種類の操作を承認するかを指定します。名前空間へのアクセスが要求されると、NIS+ はその要求を出した主体の認証を試みます。NIS+ は、要求の発信元を特定後、その特定の主体に対する特定の操作をオブジェクトが承認しているか判定します。NIS+ はこのように、認証情報とオブジェクトごとの承認情報に基づいて、アクセス要求を許すか拒否するかを決定します。

ネームサービススイッチ

NIS+ はネームサービススイッチと呼ばれる別の機能と連係して動作します。ネームサービススイッチ (単に「スイッチ」ともいう) を使用すると、Solaris ベースのワークステーションで、複数のネットワーク情報サービスから情報を得ることができます。ローカルファイル、/etc ファイル、NIS マップ、DNS ゾーンファイル、NIS+ テーブルから情報が得られます。ネームサービススイッチを使用すると、単にソースを選択するだけでなく、ワークステーションで情報の種類別に異なるソースを使用できます。ネームサービスの設定は、/etc/nsswitch.conf ファイルで行います。

NIS+ の管理コマンド

NIS+ は次の表に一覧表示した名前空間を管理するため、全種類のコマンドを提供します。

表 9–1 NIS+ 名前空間管理コマンド

コマンド 

説明 

nischgrp

NIS+ オブジェクトのグループ所有者を変更する 

nischmod

オブジェクトのアクセス権を変更する 

nischown

NIS+ オブジェクトの所有者を変更する 

nisgrpadm

NIS+ グループの作成と削除、グループメンバーリストの表示を行う。また、グループにメンバーを追加または削除したり、グループメンバーかどうかのテストを行う 

niscat

NIS+ テーブルの内容を表示する 

nisgrep

NIS+ テーブルのエントリを検索する  

nisls

NIS+ ディレクトリの内容をリストする 

nismatch

NIS+ テーブルのエントリを検索する  

nisaddent

/etc ファイル、または、NIS マップの情報を NIS+ テーブルに追加する

nistbladm

NIS+ テーブルの作成や削除を行う。また、NIS+ テーブルのエントリを追加、変更、削除する 

nisaddcred

NIS+ 主体の資格を作成し、それを Cred テーブルに保存する

nispasswd

NIS+ パスワードテーブルに保管されているパスワード情報を変更する。 

nisupdkeys

NIS+ オブジェクトに保存されている公開鍵を更新する 

nisinit

NIS+ のクライアントまたはサーバーを初期化する 

nismkdir

NIS+ ディレクトリを作成し、そのマスターサーバーと複製サーバーを指定する 

nisrmdir

名前空間から、NIS+ ディレクトリとその複製を削除する 

nissetup

org_dirgroups_dir の 2 つのディレクトリを作成し、NIS+ ドメインに対する全種類の NIS+ テーブル (空のテーブル) を作成する。

rpc.nisd

NIS+ のサーバープロセス 

nis_cachemgr

NIS+ クライアントの NIS+ キャッシュマネージャを起動する 

nischttl

NIS+ オブジェクトの生存期間の値を変更する 

nisdefaults

NIS+ オブジェクトのデフォルト値 (ドメイン名、グループ名、ワークステーション名、NIS+ 主体名、アクセス権、ディレクトリ検索パス、生存期間) を一覧表示する 

nisln

2 つの NIS+ オブジェクト間のシンボリックリンクを作成する 

nisrm

ディレクトリ以外の NIS+ オブジェクトを名前空間から削除する 

nisshowcache

NIS+ キャッシュマネージャによって管理される NIS+ 共有キャッシュの内容を一覧表示する

NIS+ の API

NIS+ の アプリケーションプログラマーズインタフェース (API) は関数の集合です。アプリケーションでは、これらの関数を呼び出して NIS+ オブジェクトにアクセスしたり変更したりできます。NIS+ の API には 54 個の関数があり、それらは次の 9 つのグループに分類されます。

各グループの関数について次の表で簡単に説明します。グループ名は、NIS+ のマニュアルページのグループ名と同じです。

表 9–2 NIS+ の API 関数

機能 

説明 

nis_names()

オブジェクトの検出と操作を行う 

nis_lookup()

NIS+ オブジェクトのコピーを返す。リンクをたどることができる。エントリオブジェクトの検索はできないが、リンクがエントリオブジェクトを指している場合は、それを返すことができる 

nis_add()

NIS+ オブジェクトを名前空間に追加する 

nis_remove()

NIS+ オブジェクトを名前空間から削除する 

nis_modify()

名前空間の NIS+ オブジェクトを変更する 

nis_tables

テーブルの検索と更新を行う 

nis_list()

NIS+ 名前空間内のテーブルを検索して、検索条件に一致するエントリオブジェクトを返す。テーブル間のリンクと検索パスをたどることができる  

nis_add_entry()

NIS+ テーブルにエントリオブジェクトを追加する。既存オブジェクトがあれば操作を中止するか上書きするかを指定できる。操作が正常終了した場合は、削除したオブジェクトのコピーが返される 

nis_freeresult()

nis_result 構造体に割り当てられたメモリーをすべて解放する

nis_remove_entry()

NIS+ テーブルからエントリオブジェクトを削除する。削除するオブジェクトは、検索条件で指定するか、キャッシュされたオブジェクトコピーへのポインタで指定できる。検索条件で指定する場合は、その条件に一致するオブジェクトをすべて削除できる。したがって、検索条件を適切に指定すれば、テーブル内の全エントリを削除することもできる。操作が正常終了した場合は、削除したオブジェクトのコピーが返される 

nis_modify_entry()

NIS+ テーブルのエントリオブジェクトを変更する。変更するオブジェクトは、検索条件で指定するか、キャッシュに書き込まれたオブジェクトコピーへのポインタで指定する 

nis_first_entry()

NIS+ テーブルの最初のエントリオブジェクトのコピーを返す 

nis_next_entry()

NIS+ テーブルの「次」のエントリオブジェクトのコピーを返す。この関数へのコールとコールの間に、テーブルの更新やエントリの追加、削除、変更が行われる可能性があるので、返されたエントリの順序が実際のテーブル内のエントリ順序と一致しない場合がある 

nis_local_names()

現在のプロセスのデフォルト名を取り出す 

nis_local_directory ()

ワークステーションの NIS+ ドメイン名を返す 

nis_local_host()

完全指定のワークステーション名を返す完全指定の名前は host-name domain-name の形式を取る

nis_local_group()

現在の NIS+ グループ名を返す。現在の NIS+ グループは、環境変数 NIS_GROUP で指定される 

nis_local_principal ()

呼び出し側プロセスに関連付けられた UID を持つ NIS+ 主体名を返す 

nis_getnames()

特定の名前に対する可能な展開形のリストを返す 

nis_freenames()

nis_getnames()が生成したリストが使用するメモリーを解放する

nis_groups()

グループ操作と承認 

nis_ismember()

ある主体がグループのメンバーかどうか調べる 

nis_addmember()

グループにメンバーを追加する。メンバーは主体、グループ、ドメインのどれか 

nis_removemember()

グループからメンバーを削除する 

nis_creategroup()

グループオブジェクトを作成する 

nis_destroygroup()

グループオブジェクトを削除する 

nis_verifygroup()

グループオブジェクトが存在しているかどうか調べる 

nis_print_group_entry ()

グループオブジェクトのメンバーになっている主体を一覧表示する 

nis_server

NIS+ アプリケーションのための種々のサービス 

nis_mkdir()

特定ホストの特定ディレクトリに対するサービスをサポートするためのデータベースを作成する 

nis_rmdir()

ホストからディレクトリを削除する 

nis_servstate()

NIS+ サーバーの状態変数の設定と読み取りを行い、内部キャッシュをフラッシュする 

nis_stats()

サーバーのパフォーマンス に関する統計情報を取り出す 

nis_getservlist()

特定のドメインをサポートするサーバーのリストを返す 

nis_freeservlist()

nis_getservlist() が返したサーバーリストが使用するメモリーを解放する

nis_freetags()

nis_servstate()nis_stats() の戻り値に割り当てられていたメモリーを解放する

nis_db

NIS+ サーバーとデータベースの間のインタフェース。NIS+ クライアントでは使用不可 

db_first_entry()

指定したテーブルの最初のエントリのコピーを返す 

db_next_entry()

指定したエントリの次のエントリのコピーを返す 

db_reset_next_entry ()

最初または次のエントリシーケンスを終了する 

db_list_entries()

指定した属性に一致するエントリのコピーを返す 

db_remove_entry()

指定した属性に一致するエントリをすべて削除する 

db_add_entry()

指定した属性に一致するテーブルエントリを、指定したオブジェクトのコピーで置き換える。または、指定したオブジェクトをテーブルに追加する 

db_checkpoint()

テーブルの内容を再編成して、テーブルのアクセス効率を改善する 

db_standby()

データベースマネージャに資源の解放を勧める 

nis_error()

NIS+ のステータス値に対応するメッセージ文字列を取り出す関数 

nis_sperrno()

メッセージ文字列定数へのポインタを返す 

nis_perror()

メッセージ文字列定数を標準出力に表示する  

nis_lerror()

メッセージ文字列定数を syslog に送信する

nis_sperror()

strdup() を使用するかまたはコピーするために静的領域に割り当てられた文字列へのポインタを返す

nis_admin

トランザクションのログを取る関数。サーバーで使用 

nis_ping

ディレクトリのマスターサーバーが、ディレクトリのタイムスタンプの作成に使用する。この関数を実行すると、ディレクトリの複製も強制的に更新される 

nis_checkpoint()

ログデータを強制的にディスク上のテーブルに保存する 

nis_subr

NIS+ の名前とオブジェクトの操作のための補助関数 

nis_leaf_of()

NIS+ の名前の最初のラベルを返す。返された名前には、末尾のピリオドは付いていない 

nis_name_of()

名前からドメイン関連のラベルをすべて削除して、固有のオブジェクト部分だけを返す。この関数に渡された名前は、ローカルドメイン、または、その子ドメインでなければならない。それ以外の場合は NULL が返される 

nis_domain_of()

オブジェクトが入っているドメイン名を返す。返されたドメイン名はピリオドで終わっている 

nis_dir_cmp()

2 つの NIS+ 名を比較する。大文字小文字の違いは無視して比較し、名前が同じか、派生関係にあるか、無関係かを返す 

nis_clone_object()

NIS+ オブジェクトの正確な複製を作成する

nis_destroy_object()

nis_clone_object() で作成したオブジェクトを削除する

nis_print_object()

NIS+ オブジェクト構造体の内容を stdout へ出力する

NIS+ サンプルプログラム

サンプルプログラムでは次のタスクを実行します。

サンプルプログラムは典型的なアプリケーションとはいえません。通常は、ディレクトリとテーブルの作成と削除はコマンド行インタフェースで行い、アプリケーションでは NIS+ エントリオブジェクトの操作だけを行います。

サポートされないマクロの使用

サンプルプログラムでは <rpcsvc/nis.h> ファイルで定義されているマクロを使用しています。ここで定義されているマクロは、サポートが保証されている正式な API ではなく、将来変更されたりなくなったりする可能性があります。ここではサンプルプログラムで使用方法を説明するために使用していますが、実際のプログラムで使用するときはユーザー自身の責任で使用してください。サンプルプログラムで使用しているマクロを次に示します。

サンプルプログラムで使用する関数

サンプルプログラムでは、次の NIS+ API 関数を C 言語で使用する方法を示します。

プログラムのコンパイル

このアプリケーションを動作させる NIS+ 主体はローカルドメイン内にディレクトリオブジェクトの作成権を持ちます。次のように入力してプログラムを編集します。


% cc -o example.c example -lnsl

次のように入力して呼び出します。


% example [dir]

ここで、dir には NIS+ ディレクトリを指定します。サンプルプログラムは、すべての NIS+ オブジェクトをそのディレクトリに作成します。引数 dir を指定しないと、ローカルドメインの親ディレクトリにオブジェクトが作成されます。nis_lookup() の呼び出しでは、ディレクトリを指定する文字列に空白とローカルドメイン名が追加されることに注意してください。引数で指定するのは、作成した NIS+ オブジェクトを入れるための NIS+ ディレクトリ名です。このプログラムを実行する主体は、そのディレクトリ内でのオブジェクト作成権を持っている必要があります。

次のサンプルコードは、ディレクトリオブジェクトを作成するため main() が呼び出すルーチンを示しています。


例 9–1 ディレクトリオブジェクトを作成する NIS+ ルーチン

void
dir_create (dir_name, dirobj)
	nis_name			dir_name;
	nis_object			*dirobj;
{
	nis_result 	*cres;
	nis_error			err;

	printf ("\n Adding Directory %s to namespace ... \n",
dir_name);
	cres = nis_add (dir_name, dirobj);

	if (cres->status != NIS_SUCCESS) {
		nis_perror (cres->status, "unable to add directory foo.");
		exit (1);
	}

	(void) nis_freeresult (cres);

	/*
	 * 注: nis_mkdir を実行して、作成するディレクトリの内容を保存する
	 * テーブルを作成する必要がある。
	 */
	err = nis_mkdir (dir_name,

						dirobj->DI_data.do_servers.do_servers_val);
	if (err != NIS_SUCCESS) {
		(void) nis_remove (dir_name, 0);

		nis_perror (err,
				"unable to create table for  directory object foo.");
		exit (1);
	}
}

次のルーチンは main() から呼び出され、グループオブジェクトを作成します。nis_creategroup() はグループオブジェクトだけを対象としているので、グループ名には groups_dir というリテラルは必要ありません。


例 9–2 グループオブジェクトを作成する NIS+ ルーチン

void
grp_create (grp_name)
	nis_name			grp_name;
{
	nis_error			err;

	printf ("\n Adding %s group to namespace ... \n", grp_name);
	err = nis_creategroup (grp_name, 0);
	if (err != NIS_SUCCESS) {
		nis_perror (err, "unable to create group.");
		exit (1);
	}
}

main () は次の例に示すルーチンを呼び出し、テーブルオブジェクトを次の表のようなレイアウトで作成します。

表 9–3 NIS+ テーブルオブジェクト

 

カラム 1 

カラム 2 

名前 

id 

name 

属性 

検索可能、テキスト 

検索可能、テキスト 

アクセス権 

----rmcdr---r---

----rmcdr---r---

定数 TA_SEARCHABLE を指定すると、サービスでカラムが検索可能となります。TEXT カラム (デフォルト属性) だけが検索可能です。TA_CASE を指定すると、サービスは、カラムの値を検索するときに大文字小文字を区別しません。


例 9–3 テーブルオブジェクトを作成する NIS+ ルーチン

#define			TABLE_MAXCOLS 2
#define			TABLE_COLSEP ':'
#define			TABLE_PATH 0

void
tbl_create (dirobj, table_name)
	nis_object 	*dirobj;		/* フィールドによっては必要 */
	nis_name			table_name;
{
	nis_result				*cres;
	static nis_object					tblobj;
	static table_col					tbl_cols[TABLE_MAXCOLS] = {
		{"Id", TA_SEARCHABLE | TA_CASE, DEFAULT_RIGHTS},
		{"Name", TA_SEARCHABLE | TA_CASE, DEFAULT_RIGHTS}
	};

	tblobj.zo_owner = dirobj->zo_owner;
	tblobj.zo_group = dirobj->zo_group;
	tblobj.zo_access = DEFAULT_RIGHTS;    /* nis.h で定義されたマクロ  */
	tblobj.zo_data.zo_type = TABLE_OBJ;   /* nis.h で定義された列挙型 */
	tblobj.TA_data.ta_type = TABLE_TYPE;
	tblobj.TA_data.ta_maxcol = TABLE_MAXCOLS;
	tblobj.TA_data.ta_sep = TABLE_COLSEP;
	tblobj.TA_data.ta_path = TABLE_PATH;
	tblobj.TA_data.ta_cols.ta_cols_len =
		tblobj.TA_data.ta_maxcol;				 /* 常にこの指定 */
	tblobj.TA_data.ta_cols.ta_cols_val = tbl_cols;

/*
 * 完全指定のテーブル名、すなわち、org_dir というリテラルが埋め込まれた
 * テーブル名を使用する。nis_add はあらゆるタイプの NIS+ オブジェクトを
 * 操作するからであり、テーブルが作成済みならばそのフルパス名も必要である。
 */
	printf ("\n Creating table %s ... \n", table_name);
	cres = nis_add (table_name, &tblobj);
	if (cres->status != NIS_SUCCESS) {
		nis_perror (cres->status, "unable to add table.");
		exit (1);
	}
	(void) nis_freeresult (cres);
}

main() は次の例のようなルーチンを呼び出し、テーブルオブジェクトへエントリオブジェクトを追加します。 2 つのエントリがテーブルオブジェクトに追加されます。どちらのエントリのカラム幅も、文字列のターミネータとしての NULL 文字を含む値で設定することに注意してください。


例 9–4 テーブルにオブジェクトを追加する NIS+ ルーチン

#define			MAXENTRIES 2
void
stuff_table(table_name)
	nis_name 	table_name;
{
	int			i;
	nis_object			entdata;
	nis_result			*cres;
	static entry_col ent_col_data[MAXENTRIES][TABLE_MAXCOLS] = {
			{0, 2, "1", 0, 5, "John"},
			{0, 2, "2", 0, 5, "Mary"}
	};

	printf ("\n Adding entries to table ... \n");

	/*
	 * テーブルに追加するエントリは、テーブルと同じ所有者、グループ所有者、
	 * アクセス権を持たなければならないので、はじめにテーブルオブジェクトを
	 * 調べる。
	 */
	cres = nis_lookup (table_name, 0);

	if (cres->status != NIS_SUCCESS) {
		nis_perror (cres->status, "Unable to lookup table");
		exit(1);
	}
	entdata.zo_owner = NIS_RES_OBJECT (cres)->zo_owner;
	entdata.zo_group = NIS_RES_OBJECT (cres)->zo_group;
	entdata.zo_access = NIS_RES_OBJECT (cres)->zo_access;
	
	/* cres を解放して再利用できるようにする。 */
	(void) nis_freeresult (cres);

	entdata.zo_data.zo_type = ENTRY_OBJ; /* nis.h で定義された列挙型 */
	entdata.EN_data.en_type = TABLE_TYPE;
	entdata.EN_data.en_cols.en_cols_len = TABLE_MAXCOLS;
	for (i = 0; i < MAXENTRIES; ++i) {
		entdata.EN_data.en_cols.en_cols_val = &ent_col_data[i][0];
		cres = nis_add_entry (table_name, &entdata, 0);

		if (cres->status != NIS_SUCCESS) {
			nis_perror (cres->status, "unable to add entry.");
			exit (1);
		}
		(void) nis_freeresult (cres);
	}
}

次の例に示すルーチンは nis_list() の呼び出しで使用する出力関数です。 list_objs()nis_list() を呼び出すときに、引数の 1 つとして print_info() へのポインタを渡します。サービスが print_info() を呼び出すたびに、エントリオブジェクトの内容が出力されます。戻り値は、ライブラリに対して、テーブルの次のエントリを呼び出すように指示します。


例 9–5 nis_list を呼び出す NIS+ ルーチン

int
print_info (name, entry, cbdata)
	nis_name			name;			/* 未使用 */
	nis_object			*entry;			/* NIS+ エントリオブジェクト */
	void			*cbdata;			/* 未使用 */
{
	static u_int				firsttime = 1;
	entry_col	*tmp;      /* ソースを読みやすくするためだけに使用 */
	u_int				i, terminal;

	if (firsttime) {
		printf ("\tId.\t\t\tName\n");
		printf ("\t---\t\t\t----\n");
		firsttime = 0;
	}
	for (i = 0; i < entry->EN_data.en_cols.en_cols_len; ++i) {
		tmp = &entry->EN_data.en_cols.en_cols_val[i];
		terminal = tmp->ec_value.ec_value_len;
		tmp->ec_value.ec_value_val[terminal] = '\0';
	}

	/*
	 * ENTRY_VAL は、指定したエントリの特定カラムの値を返すマクロ
	 */
	printf("\t%s\t\t\t%s\n", ENTRY_VAL (entry, 0),
								ENTRY_VAL (entry, 1));
	return (0); /* さらに呼出しを行う */
}

main () は次の例に示すルーチンを呼び出し、グループ、テーブル、ディレクトリオブジェクトの内容を一覧表示します。 次のルーチンで、コールバックの使用方法を示します。グループのメンバーを取り出して表示します。グループのメンバーリストは、オブジェクトの中に保存されていないので、nis_list() コールではなく、nis_lookup () で調べます。nis_lookup() は、グループだけでなくあらゆるタイプの NIS+ オブジェクトを扱うため、グループは groups_dir を付けた形式で指定しなければなりません。


例 9–6 オブジェクトを一覧表示する NIS+ ルーチン

void
list_objs(dir_name, table_name, grp_name)
         nis_name   dir_name, table_name, grp_name;
{
	group_obj	*tmp; /* ソースを読みやすくするためだけに使用 */
	u_int			i;
	char			grp_obj_name [NIS_MAXNAMELEN];
	nis_result			*cres;
	char			index_name [BUFFER_SIZE];

	sprintf (grp_obj_name, "%s.groups_dir.%s",
				nis_leaf_of (grp_name), nis_domain_of (grp_name));
	printf ("\nGroup %s membership is: \n", grp_name);

	cres = nis_lookup(grp_obj_name, 0);

	if (cres->status != NIS_SUCCESS) {
		nis_perror (cres->status, "Unable to lookup group object.");
		exit(1);
	}

	tmp = &(NIS_RES_OBJECT(cres)->GR_data);
	for (i = 0; i < tmp->gr_members.gr_members_len; ++i)
		printf ("\t %s\n", tmp->gr_members.gr_members_val[i]);
	(void) nis_freeresult (cres);

	/*
	 * ドメイン foo の内容を、コールバックを使用しないで表示する。
	 */
	printf ("\nContents of Directory %s are: \n", dir_name);
	cres = nis_list (dir_name, 0, 0, 0);
	if (cres->status != NIS_SUCCESS) {
		nis_perror (cres->status,
                                "Unable to list Contents of
Directory foo.");
		exit(1);
	}
	for (i = 0; i < NIS_RES_NUMOBJ(cres); ++i)
		printf("\t%s\n", NIS_RES_OBJECT(cres)[i].zo_name);
	(void) nis_freeresult (cres);

	/*
	 * 作成したテーブルの内容を、nis_list() でコールバックを使用してリスト
	 * する。
	 * of nis_list().
	 */
	printf ("\n Contents of Table %s are: \n", table_name);
	cres = nis_list (table_name, 0, print_info, 0);
	if(cres->status != NIS_CBRESULTS && cres->status !=
NIS_NOTFOUND){
		nis_perror (cres->status,
			"Listing entries using callback failed");
		exit(1);
	}
	(void) nis_freeresult (cres);

	/*

	 * 作成したテーブルの 1 エントリだけをリストする。
         * エントリの取り出しには、
	 * インデックスの付いた名前を使用する。
	 */

	printf("\n Entry corresponding to id 1 is:\n");
	/*
	 * 通常、カラム名はテーブルオブジェクトから抽出できるので、
	 * 始めにそれを取り出す。
	 */
	sprintf(index_name, "[Id=1],%s", table_name);
	cres = nis_list (index_name, 0, print_info, 0);
	if(cres->status != NIS_CBRESULTS && cres->status !=
NIS_NOTFOUND){
		nis_perror (cres->status,
		"Listing entry using indexed names and callback failed");
		exit(1);
	}
	(void) nis_freeresult (cres);
}

cleanup() は次の例に示すルーチンを呼び出し、名前空間からディレクトリオブジェクトを削除します。このルーチンはまた、このディレクトリを管理しているサーバーにも、名前空間から削除したことを通知します。ポインタ cres が指している戻り値の構造体が入ったメモリーは、戻り値が使用済みになってから解放しなければならないことに注意してください。


例 9–7 ディレクトリオブジェクトを削除する NIS+ ルーチン

void
dir_remove(dir_name, srv_list, numservers)
	nis_name			dir_name;
	nis_server			*srv_list;
	u_int			numservers;
{
	nis_result			*cres;
	nis_error			err;
	u_int			i;

	printf ("\nRemoving %s directory object from namespace ...
\n",
								dir_name);
	cres = nis_remove (dir_name, 0);
	if (cres->status != NIS_SUCCESS) {
		nis_perror (cres->status, "unable to remove directory");
		exit (1);
	}
	(void) nis_freeresult (cres);

	for (i = 0; i < numservers; ++i) {
		err = nis_rmdir (dir_name, &srv_list[i]);
		if (err != NIS_SUCCESS) {
			nis_perror (err,
			"unable to remove server from directory");
			exit (1);
		}
	}
}

main() が呼び出す次のルーチンは、このサンプルプログラムで作成したすべてのオブジェクトを削除します。nis_remove_entry() を呼び出すときのフラグ REM_MULTIPLE の使用法に注意してください。必ずテーブルからすべてのエントリを削除してから、テーブル自体を削除します。


例 9–8 オブジェクトをすべて削除する NIS+ ルーチン

void
cleanup(local_princip, grp_name, table_name, dir_name, dirobj)
	nis_name			local_princip, grp_name, table_name, dir_name;
	nis_object			*dirobj;
{
	char		grp_dir_name [NIS_MAXNAMELEN];
	char		org_dir_name [NIS_MAXNAMELEN];
	nis_error			err;
	nis_result			*cres;

	sprintf(grp_dir_name, "%s.%s", "groups_dir", dir_name);
	sprintf(org_dir_name, "%s.%s", "org_dir", dir_name);

	printf("\n\n\nStarting to Clean up ... \n");
	printf("\n\nRemoving principal %s from group %s \n",
						local_princip, grp_name);
	err = nis_removemember (local_princip, grp_name);

	if (err != NIS_SUCCESS) {
		nis_perror (err,
		"unable to delete local principal from group.");
		exit (1);
	}

	/*
	 * admins グループを削除する。グループ削除のAPI は、グループだけを
	 * 対象にしているので、グループ名にgroup_dir は不要。
	 * グループ名には、自動的にリテラルgroup_dir が埋め込まれる。
	 */
	printf("\nRemoving %s group from namespace ... \n",
grp_name);
	err = nis_destroygroup (grp_name);
	if (err != NIS_SUCCESS) {
		nis_perror (err, "unable to delete group.");
		exit (1);
	}


	printf("\n Deleting all entries from table %s ... \n",
table_name);

	cres = nis_remove_entry(table_name, 0, REM_MULTIPLE);
	switch (cres->status) {
		case NIS_SUCCESS:
		case NIS_NOTFOUND:
			break;
		default:
			nis_perror(cres->status, "Could not delete entries from
										table");
			exit(1);
	}
	(void) nis_freeresult (cres);

	printf("\n Deleting table %s itself ... \n", table_name);
	cres = nis_remove(table_name, 0);

	if (cres->status != NIS_SUCCESS) {
		nis_perror(cres->status, "Could not delete table.");
	exit(1);
	}
	(void) nis_freeresult (cres);

	/* groups_dir、org_dir、foo の各ディレクトリオブジェクトを削除する。
*/

	dir_remove (grp_dir_name,
						dirobj->DI_data.do_servers.do_servers_val,
						dirobj->DI_data.do_servers.do_servers_len);
	dir_remove (org_dir_name,
						dirobj->DI_data.do_servers.do_servers_val,
						dirobj->DI_data.do_servers.do_servers_len);
	dir_remove (dir_name, dirobj-
>DI_data.do_servers.do_servers_val,
						  dirobj->DI_data.do_servers.do_servers_len);
}

プログラムを実行すると、画面上に次のように表示されます。


例 9–9 NIS+ プログラムの実行

myhost% domainname  sun.com
 myhost% ./sample  
 Adding Directory foo.sun.com. to namespace ...
 Adding Directory groups_dir.foo.sun.com. to namespace ...
 Adding Directory org_dir.foo.sun.com. to namespace ...
 Adding admins.foo.sun.com. group to namespace ...
 Adding principal myhost.sun.com. to group admins.foo.sun.com. ...
 Creating table test_table.org_dir.foo.sun.com. ...
 Adding entries to table ...
 Group admins.foo.sun.com. membership is:
         myhost.sun.com.
 Contents of Directory foo.sun.com. are:
         groups_dir
         org_dir
 Contents of Table test_table.org_dir.foo.sun.com. are:
         Id.                     Name
         ---                     ----
         1                       John
         2                       Mary
 
Entry corresponding to id 1 is:
         1                       John
 
Starting to Clean up ...
 
Removing principal myhost.sun.com. from group admins.foo.sun.com.
Removing admins.foo.sun.com. group from namespace ...
Deleting all entries from table test_table.org_dir.foo.sun.com. ...
Deleting table test_table.org_dir.foo.sun.com. itself ...
Removing groups_dir.foo.sun.com. directory object from namespace ...
Removing org_dir.foo.sun.com. directory object from namespace ...
Removing foo.sun.com. directory object from namespace ...
myhost%

デバッグのために、次の一連のコマンドを入力して、これと同じ操作を実行することもできます。最初のコマンドはマスターサーバーの名前を表示します。

変数 master と表示されている部分には、マスターサーバー名を入力してください。

% niscat -o domainname .
% nismkdir -m master foo.`domainname`.
 
 # 指定されたマスターでサブディレクトリ org_dir.foo を作成します。
 % nismkdir -m master org_dir.foo.`domainname`.
 # 指定されたマスターでサブディレクトリ groups_dir.foo を作成します。
 % nismkdir -m master groups_dir.foo.`domainname`.
 # グループ admins を作成します。
 % nisgrpadm -c admins.foo.`domainname`.
 
 # 自分自身をこのグループのメンバーとして追加します。
 % nisgrpadm -a admins.foo.`domainname`. `nisdefaults -p`
 
 # Id と Name の 2 つのカラムで test_table を作成します。
 % nistbladm -c test_data id=SI Name=SI \
 test_table.org_dir.foo.`domainname`
 
 # そのテーブルにエントリを 1 つ追加します。
 % nistbladm -a id=1 Name=John test_table.org_dir.foo.`domainname`.
 # そのテーブルに別のエントリを追加します。
 % nistbladm -a id=2 Name=Mary test_table.org_dir.foo.`domainname`.
 
 # グループ admins のメンバーをリストする。
 % nisgrpadm -l admins.foo.`domainname`.
 # ディレクトリ foo の内容をリストする。 % nisls foo.`domainname`.
 # test_table の内容とヘッダーをリストする。
 % niscat -h test_table.org_dir.foo.`domainname`.
 
 # test_table から id が 1 のエントリを取り出す
 % nismatch id=1 test_table.org_dir.foo.`domainname`.
 
 # 作成したものをすべて削除する。
 # 初めに、グループ admins から自分自身を削除する。
 % nisgrpadm -r admins.foo.`domainname`. `nisdefaults -p`
 # グループ admins を削除する。
 % nisgrpadm -d admins.foo.`domainname`.
 # test_table からすべてのエントリを削除する。
 % nistbladm -r “[],test_table.org_dir.foo.`domainname`.”
 # test_table を削除する。
 % nistbladm -d test_table.org_dir.foo.`domainname`.
 # 作成した 3 つのディレクトリをすべて削除する。
 % nisrmdir groups_dir.foo.`domainname`.
 % nisrmdir org_dir.foo.`domainname`.
 % nisrmdir foo.`domainname`.