ВНИМАНИЕ: utmp не должен быть записываемым, так как многие системные программы (что очень глупо) зависят от его целостности. Вы рискуете спутать системные файлы статистики и внести изменения в системные файлы, если предоставите любому пользователю возможность написать файл utmp.
Этот файл представляет собой последовательность элементов со следующей структурой (заметим, что в данном случае указано только одно из нескольких определений; детали зависят от версии libc):
#define UT_UNKNOWN 0 #define RUN_LVL 1 #define BOOT_TIME 2 #define NEW_TIME 3 #define OLD_TIME 4 #define INIT_PROCESS 5 #define LOGIN_PROCESS 6 #define USER_PROCESS 7 #define DEAD_PROCESS 8 #define ACCOUNTING 9 #define UT_LINESIZE 12 #define UT_NAMESIZE 32 #define UT_HOSTSIZE 256 struct exit_status { short int e_termination; /* статус завершения процесса. */ short int e_exit; /* статус выхода из процесса. */ }; struct utmp { short ut_type; /* тип входа */ pid_t ut_pid; /* идентификатор pid входного процесса */ char ut_line[UT_LINESIZE]; /* имя устройства tty - "/dev/" */ char ut_id[4]; /* начальный id или сокращенное ttyname */ char ut_user[UT_NAMESIZE]; /* имя пользователя */ char ut_host[UT_HOSTSIZE]; /* имя узла для удаленного доступа */ struct exit_status ut_exit; /* статус выхода процесса, отмеченного как DEAD_PROCESS. */ long ut_session; /* ID сессии, используемый для управления окнами */ struct timeval ut_tv; /* был создан элемент времени. */ int32_t ut_addr_v6[4]; /* IP-адрес удаленного хоста. */ char pad[20]; /* Зарезервировано для будущего использования. */ }; /* Оставлено для совместимости со старыми версиями. */ #define ut_name ut_user #ifndef _NO_UT_TIME #define ut_time ut_tv.tv_sec #endif #define ut_xtime ut_tv.tv_sec #define ut_addr ut_addr_v6[0]
Первые элементы, когда-либо созданные, заставят init(8) запустить inittab(5). Хотя перед тем, как элемент обрабатывается, init(8) очищает utmp, устанавливая ut_type равным DEAD_PROCESS и заполняя ut_user, ut_host и ut_time нулевыми байтами в записях, в которых ut_type не является DEAD_PROCESS или RUN_LVL, и где нет существующих процессов с PID, равным ut_pid. Если не найдено ни одной пустой записи с нужным ut_id, то init создает новый. Устанавливаемые значения ut_id из inittab, ut_pid и ut_time равны текущим значениям, и ut_type равно INIT_PROCESS.
getty(8) находит элементы по их идентификатору pid, меняет ut_type на LOGIN_PROCESS, меняет ut_time, устанавливает ut_line и ожидает установки соединения. login(8) после того, как пользователь был идентифицирован, меняет ut_type на USER_PROCESS, меняет ut_time и устанавливает ut_host и ut_addr. В зависимости от getty(8) и login(8), записи могут быть расположены согласно ut_line вместо предпочитаемого расположения согласно ut_pid.
Когда init(8) находит, что процесс завершился, он определяет, осуществлен ли вход процесса в utmp по ut_pid; меняет ut_type на DEAD_PROCESS и заполняет ut_user, ut_host и ut_time нулевыми байтами.
xterm(1) и другие эмуляторы терминала непосредственно создают запись USER_PROCESS и генерируют ut_id, используя последние две буквы /dev/ttyp%c или используя p%d для /dev/pts/%d. Если они обнаруживают флаг DEAD_PROCESS для этого идентификатора, то они удаляют его или создают новый элемент. Если допускается, то они пометят его как DEAD_PROCESS при выходе; предполагается, что они также обнуляют ut_line, ut_time, ut_user и ut_host.
xdm(8) не должно создавать записи в utmp, так как нет назначенного ему терминала. Если позволить ему создавать их, то это приведет примерно к такому результату: `finger: can not stat /dev/machine.dom'. Данный аргумент должен создавать элементы в wtmp, так, как это делает ftpd(8).
telnetd(8) устанавливает элемент LOGIN_PROCESS и оставляет остальное, как это обычно бывает, аргументу для login(8). После того, как закончится telnet-сессия, telnetd(8) очищает utmp вышеописанным путем.
Файл wtmp записывает все входы и выходы в систему. Его формат в точности похож на формат utmp (за исключением того, что "пустое" имя пользователя означает выход из системы через связанный терминал). Кроме того, название терминала "~" с именем пользователя "shutdown" или "reboot" означает отключение системы или ее перезагрузку, а пара названий терминала "|"/"}" означает старое/новое системное время в случае, когда date(1) меняет их. wtmp поддерживается login(1), init(1) и некоторыми версиями getty(1). Ни одна из этих программ не создает файл, поэтому если он удален, то ведение записей заканчивается.
SYSV использует только типовые поля для отметок и регистрирует информационные сообщения (такие, как "new time") в поле строк. UT_UNKNOWN, похоже, является нововведением Linux. SYSV не имеет полей ut_host и ut_addr_v6.
В отличие от других систем, где регистрация сообщений utmp может быть снята при помощи удаления файла, utmp всегда должен находиться в Linux. Если Вы хотите отключить who(1), то просто сделайте чтение utmp недоступным всем.
Заметим, что структура utmp, описанная в libc5, изменилась в libc6. Из-за этого бинарные файлы, использующие старую структуру версии libc5, будут повреждать /var/run/utmp и/или /var/log/wtmp. Система Debian включает в себя исправленные libc5, которые используют новый формат utmp. Но проблема с wtmp все еще существует, так как обращения к нему идут непосредственно из libc5.
Закладки на сайте Проследить за страницей |
Created 1996-2024 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |