ONC+ 開発ガイド

ディレクトリリストプログラムとその補助ルーチン (rpcgen)


例 D–1 rpcgen プログラム: dir.x

/*
 * 	dir.x: リモートディレクトリリストのプロトコル
 *	このソースモジュールは rpcgen ツールの機能を説明するために使用する
 *      rpcgen ソースモジュールです。ヘッダーファイル (.h) と
 *      付属するデータ構造体の両方を生成するため、
 * 	rpcgen -h -T スイッチを付けてコンパイルします。
 */
const MAXNAMELEN = 255;	/*ディレクトリエントリの長さの最大値*/

typedef string nametype<MAXNAMELEN>; /* ディレクトリエントリ */
typedef struct namenode *namelist;   /*リスト内のリンク*/
/*
 * ディレクトリリスト内のノード
 */
struct namenode {
 	nametype name;       /* ディレクトリエントリの名前 */
 	namelist next;       /* 次のエントリ */
 };

/*
 * READDIR 操作の戻り値:
 *	真に移植性の高いアプリケーションでは、
 *      このサンプルプログラムのように UNIX の 
 * 	errno を返す方法に頼るのではなく、決められたエラーコードの
 *      リストを使用する。
 * 	この例では、成功したリモート呼び出しと
 *      失敗したリモート呼び出しを区別するために共用体が使用されている。
 */
union readdir_res switch (int errno) {
	case 0:
		namelist list; /*エラーなし: ディレクトリリストを返す*/
	default:
		void;      /*エラー発生: 他には何も返さない*/
};

/*
 * ディレクトリプログラムの定義
 */
program DIRPROG {
 	version DIRVERS {
 		readdir_res
 		READDIR(nametype) = 1;
 	} = 1;
 } = 0x20000076;


例 D–2 リモート dir_proc.c

/*
 * dir_proc.c: リモート readdir の実装
 */
#include <rpc/rpc.h>      /* 必ず必要 */
#include <dirent.h>
#include "dir.h"          /* rpcgen が作成 */

extern int errno;
extern char *malloc();
extern char *strdup();

/* ARGSUSED1*/
readdir_res *
readdir_1(dirname,req)
 	nametype *dirname;
 	struct svc_req *req;
{
 	DIR *dirp;
 	struct dirent *d;
 	namelist nl;
 	namelist *nlp;
 	static readdir_res res; /* 必ず static で宣言 */

	/*
	 * ディレクトリのオープン
	 */
	dirp = opendir(*dirname);
	if (dirp == (DIR *)NULL) {
 		res.errno = errno;
 		return (&res);
 	}
	/*
	 * 以前の戻り値を解放
	 */
	xdr_free(xdr_readdir_res, &res);
	/*
	 * ディレクトリエントリを収集する。ここで割り当てられたメモリーは、
	 * 次に readdir_1 が呼び出されたときに xdr_free によって解放されます。
	 */

 	nlp = &res.readdir_res_u.list;
 	while (d = readdir(dirp)) {
 		nl = *nlp = (namenode *) malloc(sizeof(namenode));
 		if (nl == (namenode *) NULL) {
 			res.errno = EAGAIN;
 			closedir(dirp);
 			return(&res);
 		}
 		nl->name = strdup(d->d_name);
 		nlp = &nl->next;
 	}
 	*nlp = (namelist)NULL;
 	/* 戻り値を返す */
 	res.errno = 0;
 	closedir(dirp);
 	return (&res);
}


例 D–3 rls.c クライアント

/*
 * rls.c: リモートディレクトリリストクライアント
 */

#include <stdio.h>
#include <rpc/rpc.h>	/* 必ず必要 */
#include "dir.h"	    /* rpcgen が生成 */

extern int errno;

main(argc, argv)
 	int argc;
 	char *argv[];
{
 	CLIENT *cl;
 	char *server;
 	char *dir;
 	readdir_res *result;
 	namelist nl;

	if (argc != 3) {
		fprintf(stderr, "usage: %s host directory\n",
		argv[0]);
		exit(1);
	}
	server = argv[1];
	 dir = argv[2];
/*
 * コマンド行で指定したサーバー上の MESSAGEPROG を呼び出す際に使用する
 * クライアント「ハンドル」を作成。
 */
	cl = clnt_create(server, DIRPROG, DIRVERS, "visible");
 	if (cl == (CLIENT *)NULL) {
 		clnt_pcreateerror(server);
 		exit(1);
 	}

 	result = readdir_1(&dir, cl);
 	if (result == (readdir_res *)NULL) {
 		clnt_perror(cl, server);
 		exit(1);
 	}

/* リモートプロシージャの呼び出しに成功 */

	if (result->errno != 0) {
	/*
	 * リモートシステムのエラーが発生。エラーメッセージを出力し、終了
	 */
	}
	if (result->errno < sys_nerr)
 		fprintf (stderr, "%s : %s\n", dir,
 		sys_enlist[result->errno]);
 		errno = result->errno;
 		perror(dir);
 		exit(1);
 	}

/* ディレクトリリストの取得に成功。リストを出力 */
	for(nl = result->readdir_res_u.list; nl != NULL; nl = nl-
>next) {
		printf("%s\n", nl->name);
	}
exit(0);