typedef linę *line_ptr; /* wskaźnik na "dużo miejsca" */
/* w przypadku braku błędów zwraca wskaźnik, w przeciwnym razie void */ union dir_result
switch(int errno) ( case 0:
linę *line_ptr; default: void;
) ;
/*
* Procedura dodir wymaga wskaźnika na katalog, a oddaje
* wskaźnik na tablicę zawierającą drzewo katalogów.
*/ .
progcam TREE ( version one <
dir_result do_dir( string ) - 1;
) = 1;
} - 0x20000001;
W pliku definicji protokołu znajduje się szereg stałych. Są one odpowiednio kodowane instrukqami fdefine przez kompilator rpcgen. Po części ze stałymi następują dwie deklaracje typów. Pierwsza, typedef char linę [MAK], definiuje nowy typ o nazwie linę, który jest tablicą MAX elementów znakowych. Aby dokonać konwersji takiego typu danych, rpcgen tworzy procedurę o nazwie xdr_line, umieszczoną w pliku tree_xdr. c. Zawartość tej procedury pokazano na ilustracji 9.32.
xdr_line(register XDR *xdrs, linę objp) { register long *buf;
if (!xdr_vector(xdrs, (char *)objp, MAX, sizeof (char), (xdrproc_t) xdr_char)) return (FALSE); return (TRUE);
Wygenerowana automatycznie procedura xdr_line wywołuje predefiniowaną procedurę xdr_vector, która z kolei uruchamia funkcję podstawową xdr_char. To właśnie ta ostatnia (występująca w procedurze wejścia zarówno klienta, jak i serwera) dokonuje rzeczywistej translaq'i. Podobny zestaw procedur jest tworzony również dla deklaracji wskaźnika na linię (line_ptr), a także dla deklaracji ograniczonej unii wykorzystywanej w definiowanej przez użytkownika funkcji do_dir. Jeśli przyjrzymy się plikowi tree. h, wygenerowanemu z pliku tree. x, stwierdzimy, iż unia ta jest odwzorowywana w strukturę zawierającą unię (pokazaną na ilustraq'i 9.33). Jedyny argument do_dir to string — łańcuch znaków, specjalny typ danych XDR. Jest on odwzorowywany we wskaźnik na wskaźnik na znak. Argumentem do_dir jest nazwa katalogu, który ma zostać poddany analizie.
struct dir_resul^ ( int errno; union {
linę *line_ptr;
} dir_result_uj
typedef struct dir_result dir_result;
Kod części klienckiej (tree client. c) programu odczytującego drzewo katalogów pokazano w ramach programu 9.6, a kod części serwerowej (tree_server. c) — w programie 9.7.
łłłłł |
łłłłł |
łłłłłł |
łłłłłł |
łłłł |
ł |
ł |
łłłłłł |
ł |
ł |
ł |
ł ł |
ł |
ł |
ł ł |
ł |
ł |
ł |
łł |
ł |
ł |
ł ł |
łłłłł |
łłłłł |
ł |
ł |
ł |
łłłłł |
ł ł |
ł |
ł |
łłłłł |
ł |
ł |
ł |
ł |
ł |
s |
ł |
ł ł |
ł |
ł ł |
ł |
ł |
ł # |
ł |
ł |
ł |
ł |
łł |
ł ł ł */ łinclude "local |
łłłłłł ■ h" |
łłłłłł |
łłłł |
łłłłł* |
# |
łłłłłł |
ł |
ł |
łinclude "tree.h"
void tree_l(char ‘host, char *the_dir) {
CLIENT ‘client;
dirresult ‘result;
łifndef DEBUG
Client = clnt_create(host, TREE, one, "tcp") if (Client «« (CLIENT *) NULL) { clnt_pcreateerror(host); exit(2);
>
result *■ do_dir_l(sthedir, client);
#else
result - do_dir_l_svc(Sthedir, (svc_req *) client); łendif /* DEBUG */
if (result >== (dir_result *) NULL) { łifndef DEBUG
clnt_perror(Client, "cali failed"); łelse
perror("Call failed"); łendif /* DEBUG */
exit(3);
) else /* pokaż całą tablice */
printf("%s:\n\n%s\n",the_dir,result->dir_result_u.linę ptr) łifndef DEBUG
clnt_destroy(client) ;
281