GETUTENT(3)

ИМЯ
getutent, getutid, getutline, pututline, setutent, endutent, utmpname - доступ к записям файла utmp

ОБЗОР
#include <utmp.h>

struct utmp *getutent(void);
struct utmp *getutid(const struct utmp *ut);
struct utmp *getutline(const struct utmp *ut);

struct utmp *pututline(const struct utmp *ut);

void setutent(void);
void endutent(void);

int utmpname(const char *file);

ОПИСАНИЕ
В новых приложениях нужно использовать определённые в POSIX.1 «utmpx» версии этих функций; смотрите СООТВЕТСТВИЕ СТАНДАРТАМ.

Функция utmpname() задаёт имя файла в формате utmp для других функций utmp. Если utmpname() не используется для указания имени файла перед работой с другими функциями, то они будут использовать имя из _PATH_UTMP, определённое в <paths.h>.

Функция setutent() переносит указатель начало файла utmp. Вообще, оптимальным вариантом считается вызывать эту функцию перед вызовом остальных.

Функция endutent() закрывает файл utmp. Она должна быть вызвана, когда будет завершена работа с файлом посредством других функций.

Функция getutent() считывает строку, начиная с текущей позиции файла в файле utmp. Она возвращает указатель на структуру, содержащую поля этой строки. Определение структуры приведено в utmp(5).

Функция getutid() производит прямой поиск, начиная с текущей позиции файла в файле utmp, основываясь на данных ut. Если значение ut->ut_type равно RUN_LVL, BOOT_TIME, NEW_TIME или OLD_TIME, то getutid() найдёт первую запись, поле ut_type которой совпадает с ut->ut_type. Если ut->ut_type равно INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS или DEAD_PROCESS, то getutid() найдёт первую запись, поле ut_id которой совпадает с ut->ut_id.

Функция getutline() производит прямой поиск, начиная с текущей позиции файла в файле utmp. Она просматривает записи, у которых поле ut_type совпадает с USER_PROCESS или LOGIN_PROCESS, и возвращает первую запись, поле ut_line которой совпадает с ut->ut_line.

Функция pututline() записывает структуру utmp ut в файл utmp. Для поиска места в файле, необходимого для вставки новой записи, используется getutid() . Если такое место не найдено, то pututline() добавит запись в конец файла.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении функции getutent(), getutid() и getutline() возвращают указатель на struct utmp и NULL при ошибке (к ним относится и случай «запись не найдена»). Структура struct utmp располагается в статическом хранилище и может быть изменена последующими вызовами.

При успешном выполнении pututline() возвращает ut; при ошибке возвращается NULL.

При успешном назначении нового имени функция utmpname() возвращает 0 и -1 при ошибке.

В случае ошибки эти функции изменяют значение errno соответствующим образом.

ОШИБКИ

ENOMEM
    Не хватает памяти.

ESRCH
    Запись не найдена.

Функции setutent(), pututline() и getut*() также могут завершиться с ошибкой по причинам, описанным в open(2).

ФАЙЛЫ

/var/run/utmp
    база данных пользователей, находящихся в системе в данный момент

/var/log/wtmp
    база данных предыдущих пользовательских входов в систему

АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).
Интерфейс | Атрибут | Значение
getutent() | Безвредность в нитях | MT-Unsafe init race:utent race:utentbuf sig:ALRM timer
getutid(), getutline() | Безвредность в нитях | MT-Unsafe init race:utent sig:ALRM timer
pututline() | Безвредность в нитях | MT-Unsafe race:utent sig:ALRM timer
setutent(), endutent(), utmpname() | Безвредность в нитях | MT-Unsafe race:utent

В приведённой выше таблице utent в race:utent означает, что если в нескольких нитях программы одновременно используются функции setutent(), getutent(), getutid(), getutline(), pututline(), utmpname() или endutent(), то может возникнуть состязательность по данным.

СООТВЕТСТВИЕ СТАНДАРТАМ
XPG2, SVr4.

Согласно XPG2 и SVID 2 функция pututline() возвращает тип void и такое поведение можно встретить во многих системах (AIX, HP-UX). В HP-UX представлена новая функция _pututline() с прототипом приведённым выше для pututline().

Эти функции являются устаревшими в не Linux системах. POSIX.1-2001 и POSIX.1-2008, следуя SUSv1, не содержит эти функции, вместо них используются

    #include <utmpx.h>

struct utmpx *getutxent(void);
struct utmpx *getutxid(const struct utmpx *);
struct utmpx *getutxline(const struct utmpx *);
struct utmpx *pututxline(const struct utmpx *);
void setutxent(void);
void endutxent(void);

Эти функции предоставляются glibc и выполняют те же задачи что и их аналоги без «x»", но используют struct utmpx, определённую в Linux подобно struct utmp. Для завершённости, в glibc также есть utmpxname(), хотя эта функция отсутствует в POSIX.1.

В некоторых других системах структура utmpx представляет собой utmp с дополнительными полями и увеличенными размерами одинаковых полей, а также параллельно обслуживаются обе версии файлов, часто /var/*/utmpx и /var/*/wtmpx.

С другой стороны, в Linux glibc не используется второй файл utmpx, так как её структура utmp имеет достаточный размер. Функции с «x», перечисленные выше, являются просто псевдонимами их аналогов без «x» (например, getutxent() псевдоним getutent()).

ЗАМЕЧАНИЯ

  Замечания по glibc
Перечисленные выше функции нельзя использовать в нескольких нитях одновременно. В glibc добавлены реентерабельные версии.

    #include <utmp.h>

int getutent_r(struct utmp *ubuf, struct utmp **ubufp);

int getutid_r(struct utmp *ut,
              struct utmp *ubuf, struct utmp **ubufp);

int getutline_r(struct utmp *ut,
                struct utmp *ubuf, struct utmp **ubufp);

Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):

getutent_r(), getutid_r(), getutline_r():
    _GNU_SOURCE
    || /* начиная с glibc 2.19: */ _DEFAULT_SOURCE
    || /* glibc <= 2.19: */    _SVID_SOURCE || _BSD_SOURCE

Эти функции являются расширениями GNU, они аналогичны функциям с тем же именем без суффикса _r. В аргумент ubuf, передаваемый этим функциям, помещается результат. При успешном выполнении они возвращают 0 и указатель на результат записывается в *ubufp. При ошибке эти функции возвращают -1. Среди этих функций отсутствует эквиваленты utmpx (в POSIX.1 такие функции отсутствуют).

ПРИМЕР
Нижеследующий пример добавляет и удаляет запись utmp, предполагается, что программа запущена с псевдотерминала. Для использования в реальном приложении необходимо проверять значения, возвращаемые getpwuid(3) и ttyname(3).

    #include <string.h>
    #include <stdlib.h>
    #include <pwd.h>
    #include <unistd.h>
    #include <utmp.h>
    int
    main(int argc, char *argv[])
    {
        struct utmp entry;
        system("echo перед добавлением записи:;who");
        entry.ut_type = USER_PROCESS;
        entry.ut_pid = getpid();
        strcpy(entry.ut_line, ttyname(STDIN_FILENO) + strlen("/dev/"));
        /* правильные имена ptys только /dev/tty[pqr][0-9a-z] */
        strcpy(entry.ut_id, ttyname(STDIN_FILENO) + strlen("/dev/tty"));
        time(&entry.ut_time);
        strcpy(entry.ut_user, getpwuid(getuid())->pw_name);
        memset(entry.ut_host, 0, UT_HOSTSIZE);
        entry.ut_addr = 0;
        setutent();
        pututline(&entry);
        system("echo после добавления записи:;who");
        entry.ut_type = DEAD_PROCESS;
        memset(entry.ut_line, 0, UT_LINESIZE);
        entry.ut_time = 0;
        memset(entry.ut_user, 0, UT_NAMESIZE);
        setutent();
        pututline(&entry);
        system("echo после удаления записи:;who");
        endutent();
        exit(EXIT_SUCCESS);
    }

СМОТРИТЕ ТАКЖЕ
getutmp(3), utmp(5)