ONC+ 開発ガイド

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


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

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

typedef string nametype<MAXNAMELEN>; /* ディレクトリエントリ */
typedef struct namenode *namelist;   /* リスト内のリンク */
/*
 * ディレクトリリスト内のノード struct namenode
 */
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();

/* 使用する引数 */
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);