ディレクトリリストプログラムとその補助ルーチン (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);