В спецификацию структуры utmpx из состава SUSv3 не входят поля ut_host, ut_exit, ut_session и ut_addr_v6. Первые два из них присутствуют в большинстве других реализаций; поле ut_session тоже доступно в некоторых системах; а поле ut_addr_v6 поддерживается только в Linux. Стандарт SUSv3 описывает поля ut_line и ut_user, но не уточняет их длину.
Тип данных int32_t, с помощью которого в структуре utmpx определено поле ut_addr_v6, представляет собой 32-разрядное целое число.
Листинг 40.1. Определение структуры utmpx
#define _GNU_SOURCE
/* Без макроса _GNU_SOURCE эти два поля начинаются с "__" */
struct exit_status {
short e_termination; /* Код принудительного завершения процесса (сигнал) */
short e_exit; /* Код завершения процесса */
};
#define __UT_LINESIZE 32
#define __UT_NAMESIZE 32
#define __UT_HOSTSIZE 256
struct utmpx {
short ut_type; /* Тип записи */
pid_t ut_pid; /* Идентификатор процесса, отвечающего
за вход в систему */
char ut_line[__UT_LINESIZE]; /* Имя терминального устройства */
char ut_id[4]; /* Суффикс, состоящий из имени терминала
или поля ID в выводе команды inittab(5) */
char ut_user[__UT_NAMESIZE]; /* Имя пользователя */
char ut_host[__UT_HOSTSIZE]; /* Имя компьютера для удаленного входа или версия
ядра для сообщений уровня выполнения */
struct exit_status ut_exit; /* Код завершения процесса, помеченного DEAD_PROCESS
(В Linux init(8) оставляет его пустым) */
long ut_session; /* Идентификатор сессии */
struct timeval ut_tv; /* Время создания записи */
int32_t ut_addr_v6[4]; /* IP-адрес удаленного компьютера (в случае с IPv4
используется только ut_addr_v6[0], а остальные
элементы заполняются нулями) */
char __unused[20]; /* Зарезервировано для будущего применения */
};
Каждое из стоковых полей в структуре utmpx завершается значением NULL (если только оно не занимает весь отведенный ему массив).
Что касается процессов, выполняющих вход в систему, содержимое полей ut_line и ut_id основывается на имени терминального устройства; поле ut_line хранит полное имя файла, а ut_id — только суффикс (то, что следует за tty, pts или pty; последние два используются для псевдотерминалов в стиле соответственно System V и BSD). Например, в случае с терминалом /dev/tty2 поле ut_line будет равно tty2, а поле ut_id будет содержать 2.
В оконной среде некоторые эмуляторы терминалов используют поле ut_session для записи идентификатора сессии своего окна (подробности об идентификаторах сессии см. в разделе 34.3).
Поле ut_type представляет собой целое число, описывающее тип записи, добавляемой в файл. Значения, которые ему можно присваивать, представлены в виде следующих констант (их числовое представление указано в скобках):
• EMPTY (0) — запись не содержит корректной учетной информации;
• RUN_LVL (1) — запись указывает на то, что во время загрузки или выключения системы ее уровень выполнения изменился (информацию о данном уровне можно найти на странице init(8) руководства). Чтобы получить определение этой константы из заголовочного файла
• OOT_TIME (2) — поле ut_tv данной записи содержит время загрузки системы. Обычно автором записей типа RUN_LVL и BOOT_TIME является процесс init. Он добавляет их в оба файла — utmp и wtmp;
• NEW_TIME (3) — поле ut_tv данной записи содержит обновленное время после изменения системных часов;
• OLD_TIME (4) — поле ut_tv данной записи содержит старое время, которое было актуально до изменения системных часов. Записи типа OLD_TIME и NEW_TIME записываются в файлы utmp и wtmp демоном NTP (или аналогичным), когда тот меняет системное время;
• INIT_PROCESS (5) — запись относится к потомку процесса init — например, getty. Подробности можно найти на странице inittab(5) руководства;
• LOGIN_PROCESS (6) — запись относится к лидеру сессии входа в систему — например, к процессу login(1);
• USER_PROCESS (7) — запись относится к пользовательскому процессу (обычно это сессия входа в систему); имя пользователя попадает в поле ut_user. Сессия может быть запущена командой login(1) или каким-нибудь другим приложением, предоставляющим удаленный вход в систему (например, ftp или ssh);
• DEAD_PROCESS (8) — запись относится к процессу, выполнившему выход из системы.
Указываются числовые значения этих констант, поскольку различные приложения написаны из расчета на тот порядок, в котором они указаны выше. Например, в исходном коде программы agetty можно найти проверки следующего вида:
utp->ut_type >= INIT_PROCESS && utp->ut_type <= DEAD_PROCESS