Выбрать главу

 char file_name[64];

 int fd;

 char mem_info[128];

 int rval;

 int rss;

 /* Генерируем имя файла "statm", находящегося в каталоге

    данного процесса в файловой системе proc. */

 snprintf(file_name, sizeof(file_name), "/proc/%d/statm",

  (int)pid);

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

 fd = open(file_name, O_RDONLY);

 if (fd == -1)

  /* Файл не удалось открыть. Возможно, процесс больше не

     существует. */

  return -1;

 /* Чтение содержимого файла. */

 rval = read(fd, mem_info, sizeof(mem_info) — 1);

 close(fd);

 if (rval <= 0)

  /* Файл не удалось прочитать, завершаем работу. */

  return -1;

 /* Завершаем прочитанный текст нулевым символом. */

 mem_infо[rval] = '\0';

 /* Определяем размер резидентной части процесса. Это второй

    элемент файла. */

 rval = sscanf(mem_info, "%*d %d", &rss);

 if (rval != 1)

  /* Содержимое файла statm отформатировано непонятным

     образом. */

  return -1;

 /* Значения в файле statm приведены в единицах, кратных размеру

    системной страницы. Преобразуем в килобайты. */

 return rss * getpagesize() / 1024;

}

/* Эта функция генерирует строку таблицы для процесса

   с заданным идентификатором. Возвращаемый буфер должен

   удаляться в вызывающей функции, в случае ошибки

   возвращается NULL. */

static char* format_process_info(pid_t pid) {

 int rval;

 uid_t uid;

 gid_t gid;

 char* user_name;

 char* group_name;

 int rss;

 char* program_name;

 size_t result_length;

 char* result;

 /* Определяем идентификаторы пользователя и группы, которым

    принадлежит процесс. */

 rval = get_uid_gid(pid, &uid, &gid);

 if (rval != 0)

  return NULL;

 /* Определяем размер резидентной части процесса. */

 rss = get_rss(pid);

 if (rss == -1)

  return NULL;

 /* Определяем имя исполняемого файла процесса. */

 program_name = get_program_name(pid);

 if (program_name == NULL)

  return NULL;

 /* Преобразуем идентификаторы пользователя и группы в имена. */

 user_name = get_user_name(uid);

 group_name = get_group_name(gid);

 /* Вычисляем длину строки, в которую будет помещен результат,

    и выделяем для нее буфер. */

 result_length =

  strlen(program_name) + strlen(user_name) +

  strlen(group_name) + 128;

 result = (char*)xmalloc(result_length);

 /* Форматирование результата. */

 snprintf(result, result_length,

  "<tr><td align=\" right\">%d</td><td><tt>%s</tt></td><td>%s</td>"

  "<td>%s</td><td align= \"right\">%d</td></tr>\n",

  (int)pid, program_name, user_name, group_name, rss);

 /* Очистка памяти. */

 free(program_name);

 free(user_name);

 free(group_name);

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

 return result;

}

/* HTML-код начала страницы, содержащей таблицу процессов. */

static char* page_start =

 "<html>\n"

 " <body>\n"

 "  <table cellpadding=\"4\" cellspacing=\"0\" border=\"1\">\n"

 "   <thead>\n"

 "    <tr>\n"

 "     <th>PID</th>\n"

 "     <th>Program</th>\n"

 "     <th>User</th>\n"

 "     <th>Group</th>\n"

 "     <th>RSS&nbsp;(KB)</th>\n"

 "    </tr>\n"

 "   </thead>\n"

 "   <tbody>\n";

/* HTML-код конца страницы, содержащей таблицу процессов. */

static char* page_end =

 "   </tbody>\n"

 "  </table>\n"

 " </body>\n"

 "</html>\n";

void module_generate(int fd) {

 size_t i;

 DIR* proc_listing;

 /* Создание массива iovec. В этот массив помещается выходная

    информации, причем массив может увеличиваться динамически. */

 /* Число используемых элементов массива */

 size_t vec_length = 0;

 /* выделенный размер массива */

 size_t vec_size = 16;

 /* Массив элементов iovec. */

 struct iovec* vec =

  (struct iovec*)xmalloc(vec_size *

  sizeof(struct iovec));