Записи типа INIT_PROCESS обычно являются результатом вызова getty(8) (или похожей программы, такой как agetty(8) или mingetty(8)). Во время загрузки системы процесс init создает по одному потомку для каждой строчки в виртуальной консоли, и все они запускают программу getty. Та, в свою очередь, открывает терминал, запрашивает у пользователя его имя и затем выполняет команду login(1). Аутентифицировав пользователя и выполнив ряд других действий, команда login создает дочерний процесс, запускающий командную оболочку. Жизненный цикл подобной сессии входа в систему представлен четырьмя записями, которые добавляются в файл wtmp в следующем порядке:
• запись INIT_PROCESS, добавленная процессом init;
• запись LOGIN_PROCESS, добавленная процессом getty;
• запись USER_PROCESS, добавленная процессом login;
• запись DEAD_PROCESS, добавленная процессом init, когда тот обнаружил завершение дочернего процесса команды login (при выходе пользователя из системы).
Больше подробностей о поведении программ getty и login во время входа в систему можно найти в главе 9 книги [Stevens & Rago, 2005].
Некоторые версии init создают процесс getty до обновления файла wtmp. Как следствие, оба процесса соперничают друг с другом за возможность обновить этот файл, и в итоге порядок добавления записей INIT_PROCESS и LOGIN_PROCESS может быть противоположным тому, что описан выше.
Функции, описанные в данном разделе, предназначены для извлечения записей формата utmpx. По умолчанию в качестве источника информации выступает файл utmp, но это можно изменить с помощью функции utmpxname() (рассмотренной ниже).
Во время извлечения записей данные функции оперируют понятием
Функция setutxent() позволяет перейти в начало файла utmp.
#include
void setutxent(void);
Обычно вызов setutxent() следует выполнять перед использованием любой функции вида getutx*() (см. ниже). Это позволяет избежать недопонимания в случаях, когда функции были задействованы каким-нибудь сторонним кодом, который мы выполнили ранее. В зависимости от задачи функция setutxent() может понадобиться и на последующих этапах работы программы.
Функции setutxent() и getutx*() открывают файл utmp, только если он не открыт кем-то другим. Закончив с ним работать, можно его закрыть, воспользовавшись функцией endutxent().
#include
void endutxent(void);
Функции getutxent(), getutxid() и getutxline() считывают запись из файла utmp и возвращают указатель на структуру utmpx (выделенный статически).
#include
struct utmpx *getutxent(void);
struct utmpx *getutxid(const struct utmpx *
struct utmpx *getutxline(const struct utmpx *
Все три возвращают либо указатель на статически выделенную структуру utmpx, либо NULL, если не нашлось подходящей записи или был достигнут конец файла
Функция getutxent() извлекает из файла utmp следующую по порядку запись. Функции getutxid() и getutxline() выполняют поиск записей, соответствующих заданным критериям, начиная с текущей позиции (критерии задаются в виде структуры utmpx, на которую указывает аргумент ut).
Функция getutxid() ищет запись, основываясь на полях ut_type и ut_id аргумента ut:
• если поле ut_type равно RUN_LVL, BOOT_TIME, NEW_TIME или OLD_TIME, то getutxid() возвращает следующую запись, тип которой совпадает с заданным значением (записи этих типов не относятся к входу в систему). Данное обстоятельство позволяет искать сведения об изменениях системного времени и уровня выполнения;
• если поле ut_type содержит любое другое допустимое значение (INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS или DEAD_PROCESS), то getutxent() возвращает следующую запись, чей тип совпадает с любым из указанных значений и поле ut_id которой равно одноименному полю в аргументе ut. Это позволяет перебирать файл в поиске записей, относящихся к определенному терминалу.
Функция ищет следующую запись, у которой либо поле ut_type равно LOGIN_PROCESS или USER_PROCESS, либо поле ut_line совпадает с тем, что указано в аргументе ut. Это помогает находить записи, связанные со входом в систему.
Если поиск не дает результатов (то есть если достигается конец файла, а подходящих записей не найдено), то функции getutxid() и getutxline() возвращают NULL.
В ряде UNIX-систем функции getutxline() и getutxid() задействуют статическое пространство, в которое записывается итоговая структура utmpx, в качестве кэша. Если запись, помещенная в этот кэш предыдущим вызовом getutx*(), соответствует критериям, заданным в аргументе ut, то чтение файла не выполняется; вызов просто еще раз возвращает ту же запись (стандарт SUSv3 допускает такое поведение). Следовательно, чтобы не возвращать одну и ту же запись много раз подряд, когда функции getutxline() и getutxid() вызываются внутри цикла, нужно обнулять эту статическую структуру данных, используя код следующего вида:
struct utmpx *res = NULL;
/* Остальной код опущен */