11.3.2. Отображение версии Linux

11.3.2. Отображение версии Linux

Модуль issue.so (исходный текст приведен в листинге 11.7) выводит информацию о дистрибутиве Linux, с которым работает сервер. Традиционно эта информация хранится в файле /etc/issue. Модель посылает клиенту Web-страницу с содержимым файла, заключенным в тэге <pre></pre>.

Листинг 11.7. (issue.c) Серверный модуль, отображающий информацию о дистрибутиве Linux

#include <fcntl.h>

#include <string.h>

#include <sys/sendfile.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <unistd.h>

#include "server.h"

/* HTML-код начала генерируемой страницы. */

static char* page_start =

 "<html> "

 " <body> "

 "  <pre> ";

/* HTML-код конца генерируемой страницы. */

static char* page_end =

 "  </pre> "

 " </body> "

 "</html> ";

/* HTML-код страницы, сообщающей о том, что

   при открытии файла /etc/issue произошла ошибка. */

static char* error_page =

 "<html> "

 " <body> "

 "  <p>Error: Could not open /etc/issue.</p> "

 " </body> "

 "</html> ";

/* Сообщение об ошибке. */

static char* error_message =

 "Error reading /etc/issue.";

void module_generate(int fd) {

 int input_fd;

 struct stat file_info;

 int rval;

 /* Открытие файла /etc/issue */

 input_fd = open("/etc/issue", O_RDONLY);

 if (input_fd == -1)

  system_error("open");

 /* Получение информации о файле. */

 rval = fstat(input_fd, &file_info);

 if (rval == -1)

  /* не удалось открыть файл или прочитать данные из него. */

  write(fd, error_page, strlen(error_page));

 else {

  int rval;

  off_t offset = 0;

  /* Запись начала страницы */

  write(fd, page_start, strlen(page_start));

  /* Копирование данных из файла /etc/issue

     в клиентский сокет. */

  rval = sendfile(fd, input_fd, &offset, file_info.st_size);

  if (rval == -1)

   /* При отправке файла /etc/issue произошла ошибка.

      Выводим соответствующее сообщение. */

   write(fd, error_message, strlen(error_message));

  /* Конец страницы. */

  write(fd, page_end, strlen(page_end));

 }

 close(input_fd);

}

Сначала модуль пытается открыть файл /etc/issue. Если это не удалось, клиенту возвращается сообщение об ошибке. В противном случае посылается начальный код HTML-страницы, содержащийся в переменной page_start, затем — содержимое файла /etc/issue (это делается с помощью функции sendfile(), о которой рассказывалось в разделе 8.12. "Функция sendfile(): быстрая передача данных") и, наконец конечный код HTML-страницы, содержащийся в переменной page_end.

Этот модуль можно легко настроить на отправку любого другого файла. Если файл содержит HTML-страницу, переменные page_start и page_end будут не нужны.