łendif /* DEBOG */
)
main(int argc, char *argv[J) { char *host;
static char directory[DIR_1]; /* Nazwa katalogu */ if (argc < 2) {
fprintf(stderr, "Składnia %s serwer [katalog]\n", argv[0]); exit(1);
}
host « argv[l]; /* przypis serwer */
if (argc > 2)
strcpy(directory, argv[2]); else
Strcpy(directory ,
tree_l(host, directory); /* dalej! */
Główny trzon programu tree_client. c stanowi kod, który albo jest podobny w swej naturze do poprzednich przykładów, albo jest tak napisany, że nie wymaga komentarza. Jedyna instrukcja, która może wymagać bliższych wyjaśnień, to printf. Służy ona do wyświetlania danych o strukturze katalogów na ekranie. Jak wspomniano, zdalna procedura zwraca wskaźnik na string. Jest to gotowy do wyświetlenia napis zawierający odpowiednie spacjowe wcięcie, nazwę katalogu i na końcu znak nowej linii. Wskaźnik do tego napisu jest zapisany w postaci result->dir_result_u.line_ptr. Jego właściwą składnię uzyskano po odczytaniu zawartości pliku tree.h wygenerowanego programem rpcgen.
/*
««#»# |
łłłłł |
****** |
****** |
**** |
****** |
***** |
* |
* |
****** |
***** | |||
t |
♦ |
* |
f |
* |
* |
# |
# |
ł |
* |
* |
* |
f |
t |
t |
ł |
* |
***** |
***** |
**** |
***** |
* |
# |
» |
* |
***** |
* |
* |
f |
***** |
* |
* |
* |
ł |
***** |
* |
# |
* |
***** | |||
# |
* |
* |
* |
* |
ł ł |
* |
f |
* |
* |
ł |
* |
ł |
* |
ł |
* |
* |
****** |
****** |
**** |
****** |
* |
* |
** |
****** |
* |
* |
*/
♦include "local.h" łlnclude "tree.h"
static int cur = 0, /* indeks do tablicy wynikowej */
been_allocated = 0, /* czy zarezerwowane miejsce na tablicę? *,
depth = 0; /* poziom wcięcia */
struct stat DIR
struct dirent
char
int
static char
dir_result *
do_dir_l_svc( char **f, struct svc_req static dir result result;
statbuff;
*dp;
*dentry;
♦current;
length;
buffer[DIR_l];
* rqstp) (
/* tablica albo void */
/* na sprawdzanie statusu pozycji */ /* pozycja katalogowa */
/* wskaźnik na bieżąca pozycję */
/* pozycja w tablicy wynikowej */
/* długość bieżącej pozycji */
/* położenie tymczasowe */
* zapisz pozycję w buforze, potem skopiuj bufor do większej tablicy
sprintf(buffer, "%*s %-10s\n", depth, " ", dentry->d_name); length = strlen(buffer) ;
memcpy((char *)result.dir_result_u.line_ptr + cur, buffer, length); cur += length; /* zmień wskaźnik na nast. poł. */
current = dentry->d_name; /* nowy katalog */
(dir_result *)do_dir_l_svc(scurrent, rqstp); /* wywołaj się */
chdir(".."); /* wróć jeden poziom */
deDth -= INDENT: /* zmień poziom wcięcia */
dentry = -“addir(dp);
)
closedir(dp);
)
return (Sresult);
if (!been allocated)
if ((result.dir_result_u.line_ptr=(line return (Sresult); else{
been_allocated - 1;
) else if ( depth == 0 ) {
memset(result.dir_result_u.line_ptr, cur = 0;
}
if ((dp - opendir(*f)) != NULL) ( chdir(xf);
dentry - readdir(dp); while (dentry != N(JLL) (
if (stat(dentry->d_name, Sstatbuff) != -1)
if ((statbuff.st_mode s S_IFMT) == S_IFDIR SS dentry->d_name[0] !=«.») { depth += INDENT;
/*
/* jeśli nie, zarezerwuj */
)malloc(sizeof(linę))) == NULL)
rezerwowanie miejsca OK */ zeruj «starą» zawartość */ sizeof(linę));
/* jeśli skutecznie otwarty */
/* przejdź do katalogu */
/* odczytaj pierwsza pozycję */
/* jeśli dostępna */
/* i jest katalogiem */ /* i nie zawiera kropek */ /* zmień wcięcie */
/* odczytaj kolejna pozycję */ /* temu panu już dziękujemy */ /* oddaj wyniki */
W programie tree_server. c występuje kilka statycznych zmiennych typu całkowito-liczbowego. Są one używane w roli liczników i znaczników. Identyfikator cur wskazuje bieżące miejsce (przesunięcie) w tablicy danych wynikowych. Od tego miejsca mogą być zapisywane kolejne odczytane dane. Początkowo przesunięcie to jest równe 0. Identyfikator been_allocated funkcjonuje jako znacznik sygnalizujący, czy bufor wyjściowy został już zarezerwowany. Początkowo znacznik ten jest ustawiany na 0 (FALSE, czyli „nie został zarezerwowany"). Ostatni statyczny identyfikator, depth, zawiera aktualny w każdej chwili numer poziomu zagnieżdżenia. On również początkowo ma wartość 0. Procedura do_dir_l_svc otrzymuje wskaźnik na łańcuch znaków (konkretnie na tablicę znaków) oraz wskaźnik na uchwyt klienta RPC. W procedurze tej rezerwowane jest miejsce na kilka zmiennych lokalnych, które ułatwiają manipulowanie i pozyskiwanie informacji o katalogach. Następnie pojawia się instrukcja if. Ta służy do testowania znacznika been_allocated. Jeżeli bufor wynikowy nie został jeszcze zarezerwowany, wywołana jest funkcja malloc, która go zarezerwuje. Na pozyskiwany obszar pamięci jest rzutowany odpowiedni typ, a wskaźnik do tego obszaru trafia do pola line_ptr struktury dir_result_u. Po zarezerwowaniu miejsca na bufor znacznik been_allocated
283