getaddrinfo

title: getaddrinfo(3)

summary: трансляция сетевого адреса и

text:
# getaddrinfo(3)

## ИМЯ
getaddrinfo, freeaddrinfo, gai_strerror - трансляция сетевого адреса и службы

## ОБЗОР

```
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
```

```
int getaddrinfo(const char *node, const char *service,
                const struct addrinfo *hints,
                struct addrinfo **res);
```

```
void freeaddrinfo(struct addrinfo *res);
```

```
const char *gai_strerror(int errcode);
```

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

getaddrinfo(), freeaddrinfo(), gai_strerror():

начиная c glibc 2.22: _POSIX_C_SOURCE >= 200112L

в glibc 2.21 и старее: _POSIX_C_SOURCE

## ОПИСАНИЕ
По заданным node и service, определяющим узел и службу Интернета, getaddrinfo() возвращает одну или несколько структур addrinfo, каждая из которых содержит Интернет-адрес, который можно передавать в вызов bind(2) или connect(2). Функция getaddrinfo() объединяет возможности, предоставляемые функциями gethostbyname(3) и getservbyname(3) в одном интерфейсе, но в отличие от этих функций, getaddrinfo() реентерабельна и позволяет программам не зависеть от IPv4 или IPv6.

Структура addrinfo, используемая в getaddrinfo(), содержит следующие поля:

```
struct addrinfo {

    int              ai_flags;

    int              ai_family;

    int              ai_socktype;

    int              ai_protocol;

    socklen_t        ai_addrlen;

    struct sockaddr *ai_addr;

    char            *ai_canonname;

    struct addrinfo *ai_next;
};
```

Аргумент hints указывает на структуру addrinfo, которая определяет критерии выбора структур адреса сокета, возвращаемых в списке, указанном в res. Если hints не является NULL, то он указывает на структуру addrinfo. В ней с помощью ai_family, ai_socktype и ai_protocol определяются критерии, ограничивающие набор адресов сокета, возвращаемых getaddrinfo():

ai_family

Это поле определяет предпочитаемое семейство адресов для возвращаемых адресов. Правильными значениями для данного поля могут быть AF_INET и AF_INET6. Значение AF_UNSPEC отображает, что getaddrinfo() должна возвращать адреса сокета для любого семейства адресов (например, либо IPv4, либо IPv6), которые в дальнейшем могут быть использованы вместе с node и service.

ai_socktype

Это поле определяет предпочитаемы тип сокета, например, SOCK_STREAM или SOCK_DGRAM. Если в этом поле указан 0, то это означает, что getaddrinfo() может вернуть адреса сокета любого типа.

ai_protocol

Это поле определяет протокол для возвращаемых адресов сокета. Если в этом поле указан 0, то это означает, что getaddrinfo() может вернуть адрес сокета с любым протоколом.

ai_flags

В этом поле задаются дополнительные параметры, описываемые ниже. Несколько флагов указываются с логическим ИЛИ.

Все остальные поля структуры, указываемой hints, должны содержать 0 или указатель null, соответственно.

Указание в hints значения NULL эквивалентно установке ai_socktype и ai_protocol равными 0; ai_family присваивается AF_UNSPEC; ai_flags присваивается (AI_V4MAPPED | AI_ADDRCONFIG) (в POSIX указаны другие значения по умолчанию для ai_flags; смотрите ЗАМЕЧАНИЯ). В node задаётся либо числовой сетевой адрес (для IPv4 это цифро-точечная нотация, которую поддерживает inet_aton(3); для IPv6 это строка в шестнадцатеричном формате, который поддерживает inet_pton(3)), либо сетевое имя узла, для которого в дальнейшем определяется адрес. Если в hints.ai_flags содержится флаг AI_NUMERICHOST, тогда node должен иметь цифровой формат сетевого адреса. При AI_NUMERICHOST любые возможные преобразования сетевого адреса узла подавляются.

Если в hints.ai_flags указан флаг AI_PASSIVE и node равно NULL, то возвращаемые адреса сокета будут пригодны для bind(2) сокета, который принимает соединение с помощью accept(2). Возвращаемый адрес сокета будет содержать «шаблонный адрес» (INADDR_ANY для адресов IPv4, IN6ADDR_ANY_INIT для адреса IPv6). Шаблонный адрес используется в приложениях (обычно, серверах), которым нужно принимать подключения с любых сетевых адресов узлов. Если node не равно NULL, то флаг AI_PASSIVE игнорируется.

Если флаг AI_PASSIVE отсутствует в hints.ai_flags, то возвращаемые адреса сокета будут пригодны для использоваться в connect(2), sendto(2), или sendmsg(2). Если node равно NULL, то сетевому адресу будет назначен адрес кольцевого интерфейса (loopback) (INADDR_LOOPBACK для адресов IPv4, IN6ADDR_LOOPBACK_INIT для адреса IPv6); это используется в приложениях, которым нужно связываться с партнёрами, запущенными на том же узле.

В service задаётся порт для каждой возвращаемой адресной структуры. Если этот аргумент — имя службы (смотрите services(5)), то он транслируется в соответствующий номер порта. Также, данный параметр может быть указан в виде десятичного числа, которое просто преобразуется в двоичную форму. Если service равно NULL, то номер порта возвращаемых сокетных адресов остаётся неинициализированным. Если в hints.ai_flags указан флаг AI_NUMERICSERV и service не равно NULL, то значение service должно указывать на строку с числовым номером порта. Данный флаг используется для запрета вызова службы определения имён, если известно, что она не требуется.

Либо node, либо service (но не оба одновременно) могут быть равны NULL.

Функция getaddrinfo() выделяет место и инициализирует связный список структур addrinfo, по одной на каждый сетевой адрес, который совпадает с node и service, в соответствии с любыми ограничениями, наложенными hints, и возвращает указатель на начало списка в res. Элементы в связном списке связаны через поле ai_next.

Существует несколько причин того, почему связный список может содержать более одной структуры addrinfo: сетевой узел имеет несколько адресов, доступен по нескольким протоколам (например, AF_INET и AF_INET6); служба доступна через несколько типов сокетов (например, один её адрес — SOCK_STREAM, а второй — SOCK_DGRAM). Обычно, приложение должно стараться использовать адреса в том порядке, в котором они получены. Функция сортировки, используемая в getaddrinfo(), определена в RFC 3484; в системе порядок может быть изменён через файл /etc/gai.conf (доступен, начиная с glibc 2.5).

Если в hints.ai_flags выставлен флаг AI_CANONNAME, то в поле ai_canonname первой из структур addrinfo возвращаемого списка задаётся указатель официального имени узла.

Остальные поля каждой возвращаемой структуры addrinfo инициализируются следующим образом:

- В полях ai_family, ai_socktype и ai_protocol возвращаются параметры создания сокета (т. е., эти поля имеют те же значения, что и соответствующие аргументы в socket(2)). Например, в ai_family может вернуться AF_INET или AF_INET6; в ai_socktype может вернуться SOCK_DGRAM или SOCK_STREAM; в ai_protocol возвращается протокол сокета.

- Указатель на адрес сокета помещается в поле ai_addr, а длина адреса сокета (в байтах) помещается в поле ai_addrlen.

Если в hints.ai_flags содержится флаг AI_ADDRCONFIG, то адреса IPv4, возвращаются в списке, на который указывает res, только, если в локальной системе настроен, как минимум, один адрес IPv4, и адреса IPv6 возвращаются только, если в локальной системе настроен, как минимум, один адрес IPv6. Кольцевой (loopback) адрес в этом случае не учитывается как настроенный. Этот флаг полезен, например в только IPv4-системах, чтобы getaddrinfo() не возвращал сокетные адреса IPv6, с которыми невозможно выполнить connect(2) или bind(2).

Если в hints.ai_flags содержится флаг AI_V4MAPPED и в hints.ai_family задан AF_INET6, и не найдено подходящих адресов IPv6, то в списке, на который указывает res, возвращаются IPv6 адреса отображённых адресов IPv4. Если в hints.ai_flags указаны и AI_V4MAPPED, и AI_ALL, то в списке, на который указывает res, возвращаются и адреса IPv6 и IPv6 адреса отображённых адресов IPv4. Флаг AI_ALL игнорируется, если с ним не задан AI_V4MAPPED.

Функция freeaddrinfo() освобождает память, которая была выделена для динамического связного списка res.

### Расширения getaddrinfo() для интернациональных доменных имён
Начиная с glibc 2.3.4, getaddrinfo() был расширен для выборочного прозрачного разрешения исходящих и входящих адресов в формате интернациональных доменных имен (IDN, см. RFC 3490, Internationalizing Domain Names in Applications (IDNA)). Было определено четыре новых флага:

AI_IDN

Если указан этот флаг, то, в случае необходимости, имя узла, указанного в node, будет преобразовано в IDN-формат. Исходной кодировкой будет текущая локаль.

Если имя на входе содержит символы не-ASCII, то будет задействовано кодирование IDN. Части имени узла (разделенные точками), которые содержат символы не-ASCII, будут закодированы с помощью ASCII Compatible Encoding (ACE) прежде, чем будут переданы функциям преобразования имен

AI_CANONIDN

При указанном флаге AI_CANONNAME после успешного преобразования имени getaddrinfo() вернет каноничное имя узла согласно значению структуры addrinfo. Возвращаемое значение будет точной копией значения, возвращенного функцией разрешения имени.

Если имя закодировано с помощью ACE, то оно будет содержать префикс xn-- для каждого из закодированных компонентов имени. Чтобы преобразовать эти компоненты в читаемый вид, вместе с флагом AI_CANONNAME следует передать AI_CANONIDN. Итоговая строка будет кодирована при помощи текущей локали.

AI_IDN_ALLOW_UNASSIGNED, AI_IDN_USE_STD3_ASCII_RULES

Установка этих флагов включает IDNA_ALLOW_UNASSIGNED (разрешать не назначенные кодовые точки Юникода) и IDNA_USE_STD3_ASCII_RULES (проверять вывод на соответствие имени узла STD3) соответственно для возможности работы с IDNA.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
В случае успеха getaddrinfo() возвращает 0, либо один из следующие ненулевых кодов ошибки:

EAI_ADDRFAMILY

У указанного сетевого узла нет сетевых адресов в запрашиваемом семействе адресов.

EAI_AGAIN

Сервер имен вернул временную ошибку. Попробуйте позднее.

EAI_BADFLAGS

В hints.ai_flags содержатся неправильные флаги, либо hints.ai_flags содержит AI_CANONNAME, а name - NULL.

EAI_FAIL

Сервер имен вернул постоянную ошибку.

EAI_FAMILY

Запрашиваемое семейство адресов не поддерживается.

EAI_MEMORY

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

EAI_NODATA

Указанный сетевой узел существует, однако не имеет ни одного определенного сетевого адреса.

EAI_NONAME

node или service неизвестно; либо и node, и service равны NULL; либо в hints.ai_flags указан флаг AI_NUMERICSERV, а service не является числовой строкой порта.

EAI_SERVICE

Запрошенная служба не доступна для запрошенного типа сокета. Она может быть доступна через другой тип сокета. Например, эта ошибка может возникнуть, если в service указан «shell» (служба, доступная только для потоковых сокетов) при указанном в hints.ai_protocol IPPROTO_UDP, либо указанном в hints.ai_socktype SOCK_DGRAM. Также ошибка может возникнуть, если service не равно NULL, а в hints.ai_socktype указано значение SOCK_RAW (тип сокета, для которого концепция служб неприменима).

EAI_SOCKTYPE

Запрашиваемый тип сокетов не поддерживается. Такая ошибка может возникнуть, если hints.ai_socktype и hints.ai_protocol противоречат друг другу (например, SOCK_DGRAM и IPPROTO_TCP соответственно).

EAI_SYSTEM

Для других системных ошибок следует проверять errno.

Функция gai_strerror() транслирует эти коды ошибок в читаемый формат, подходящий для сообщений об ошибке.

## ФАЙЛЫ
/etc/gai.conf

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

getaddrinfo()

Безвредность в нитях

MT-Safe env locale

freeaddrinfo(), gai_strerror()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008. Функция getaddrinfo() описана в RFC 2553.

## ЗАМЕЧАНИЯ
getaddrinfo() поддерживает нотацию address%scope-id для указания IPv6 scope-ID.

AI_ADDRCONFIG, AI_ALL и AI_V4MAPPED доступны, начиная с glibc 2.3.3. AI_NUMERICSERV доступен, начиная с glibc 2.3.4.

Согласно POSIX.1, при указании hints в NULL ai_flags должен предполагаться как равный 0. Вместо этого библиотека GNU C в данном случае предполагает значение (AI_V4MAPPED | AI_ADDRCONFIG), так как данное значение было принято в качестве улучшения спецификации.

## ПРИМЕР
Следующие программы демонстрируют использование getaddrinfo(), gai_strerror(), freeaddrinfo() и getnameinfo(3). Это программы эхо-сервера и клиента UDP-дейтаграмм.

### Серверная программа

```
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#define BUF_SIZE 500
int
main(int argc, char *argv[])
{

    struct addrinfo hints;

    struct addrinfo *result, *rp;

    int sfd, s;

    struct sockaddr_storage peer_addr;

    socklen_t peer_addr_len;

    ssize_t nread;

    char buf[BUF_SIZE];

    if (argc != 2) {

        fprintf(stderr, "Usage: %s port\n", argv[0]);

        exit(EXIT_FAILURE);

    }

    memset(&hints, 0, sizeof(struct addrinfo));

    hints.ai_family = AF_UNSPEC;    /* Разрешены IPv4 и IPv6 */

    hints.ai_socktype = SOCK_DGRAM; /* Сокет для дейтаграмм */

    hints.ai_flags = AI_PASSIVE;    /* Для wildcard IP-адреса */

    hints.ai_protocol = 0;          /* Любой протокол */

    hints.ai_canonname = NULL;

    hints.ai_addr = NULL;

    hints.ai_next = NULL;

    s = getaddrinfo(NULL, argv[1], &hints, &result);

    if (s != 0) {

        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));

        exit(EXIT_FAILURE);

    }

    /* getaddrinfo() возвращает список структур адресов.

       Идет проверка каждого адреса до успешного bind(2).

       Если socket(2) (или bind(2)) терпит неудачу, мы (закрываем

       сокет и) пробуем следующий. */

    for (rp = result; rp != NULL; rp = rp->ai_next) {

        sfd = socket(rp->ai_family, rp->ai_socktype,

                rp->ai_protocol);

        if (sfd == -1)

            continue;

        if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)

            break;                  /* Успех */

        close(sfd);

    }

    if (rp == NULL) {               /* Нет успешных адресов */

        fprintf(stderr, "Could not bind\n");

        exit(EXIT_FAILURE);

    }

    freeaddrinfo(result);           /* Больше не нужен */

    /* Читаем дейтаграмму и пересылаем ее назад отправителю */

    for (;;) {

        peer_addr_len = sizeof(struct sockaddr_storage);

        nread = recvfrom(sfd, buf, BUF_SIZE, 0,

                (struct sockaddr *) &peer_addr, &peer_addr_len);

        if (nread == -1)

            continue;               /* Игнорируем запрос с ошибкой */

        char host[NI_MAXHOST], service[NI_MAXSERV];

        s = getnameinfo((struct sockaddr *) &peer_addr,

                        peer_addr_len, host, NI_MAXHOST,

                        service, NI_MAXSERV, NI_NUMERICSERV);

       if (s == 0)

            printf("Получено %zd байт из %s:%s\n",

                    nread, host, service);

        else

            fprintf(stderr, "getnameinfo: %s\n", gai_strerror(s));

        if (sendto(sfd, buf, nread, 0,

                    (struct sockaddr *) &peer_addr,

                    peer_addr_len) != nread)

            fprintf(stderr, "Ошибка отправки ответа\n");

    }
}
```

### Клиентская программа

```
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define BUF_SIZE 500
int
main(int argc, char *argv[])
{

    struct addrinfo hints;

    struct addrinfo *result, *rp;

    int sfd, s, j;

    size_t len;

    ssize_t nread;

    char buf[BUF_SIZE];

    if (argc < 3) {

        fprintf(stderr, "Usage: %s host port msg...\n", argv[0]);

        exit(EXIT_FAILURE);

    }

    /* Получаем адрес(а), соответствующие узлу/порту */

    memset(&hints, 0, sizeof(struct addrinfo));

    hints.ai_family = AF_UNSPEC;    /* Разрешены IPv4 и IPv6 */

    hints.ai_socktype = SOCK_DGRAM; /* Сокет дейтаграмм */

    hints.ai_flags = 0;

    hints.ai_protocol = 0;          /* Любой протокол */

    s = getaddrinfo(argv[1], argv[2], &hints, &result);

    if (s != 0) {

        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));

        exit(EXIT_FAILURE);

    }

    /* getaddrinfo() возвращает список структур адресов.

       Идет проверка каждого адреса до успешного connect(2).

       Если socket(2) (или connect(2)) терпит неудачу, мы (закрываем

       сокет и) пробуем следующий. */

    for (rp = result; rp != NULL; rp = rp->ai_next) {

        sfd = socket(rp->ai_family, rp->ai_socktype,

                     rp->ai_protocol);

        if (sfd == -1)

            continue;

        if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)

            break;                  /* Успех */

        close(sfd);

    }

    if (rp == NULL) {               /* Нет успешных адресов */

        fprintf(stderr, "Could not connect\n");

        exit(EXIT_FAILURE);

    }

    freeaddrinfo(result);           /* Больше не нужен */

    /* Отправляем оставшиеся аргументы командной строки

       в виде отдельных дейтаграмм и ждем ответа от сервера */

    for (j = 3; j < argc; j++) {

        len = strlen(argv[j]) + 1;

                /* +1 для завершающего null-байта */

        if (len > BUF_SIZE) {

            fprintf(stderr,

                    "Игнорируем длинное сообщение в аргументе %d\n", j);

            continue;

        }

        if (write(sfd, argv[j], len) != len) {

            fprintf(stderr, "partial/failed write\n");

            exit(EXIT_FAILURE);

        }

        nread = read(sfd, buf, BUF_SIZE);

        if (nread == -1) {

            perror("read");

            exit(EXIT_FAILURE);

        }

        printf("Получено %zd байт: %s\n", nread, buf);

    }

    exit(EXIT_SUCCESS);
}
```

## СМОТРИТЕ ТАКЖЕ
getaddrinfo_a(3), gethostbyname(3), getnameinfo(3), inet(3), gai.conf(5), hostname(7), ip(7)


package: man-pages-ru

title: getaddrinfo_a(3)

summary: асинхронная трансляция

text:
# getaddrinfo_a(3)

## ИМЯ
getaddrinfo_a, gai_suspend, gai_error, gai_cancel - асинхронная трансляция сетевого адреса и службы

## ОБЗОР

```
#define _GNU_SOURCE         /* См. feature_test_macros(7) */
#include <netdb.h>
```

```
int getaddrinfo_a(int mode, struct gaicb *list[],
                int nitems, struct sigevent *sevp);
```

```
int gai_suspend(const struct gaicb * const list[], int nitems,
                const struct timespec *timeout);
```

```
int gai_error(struct gaicb *req);
```

```
int gai_cancel(struct gaicb *req);
```

```
Компонуется при указании параметра -lanl.
```

## ОПИСАНИЕ
Функция getaddrinfo_a() выполняет ту же задачу что и getaddrinfo(3), но позволяет выполнять поиск нескольких имён асинхронно, с дополнительным уведомлением о завершении операций поиска.

В аргументе mode указывается одно из следующих значений:

GAI_WAIT

Выполнять поиск синхронно. Вызов блокирует выполнение пока поиск не завершится.

GAI_NOWAIT

Выполнять поиск асинхронно. Вызов сразу завершается и запросы обрабатываются в фоновом режиме. Смотрите далее описание параметра sevp.

В массиве list задаются запросы на обработку. В аргументе nitems задаётся количество элементов в list. Запрашиваемые операции поиска начинаются параллельно. Элементы NULL в списке list игнорируются. Каждый запрос описывается структурой gaicb, которая определена следующим образом:

```
struct gaicb {

    const char            *ar_name;

    const char            *ar_service;

    const struct addrinfo *ar_request;

    struct addrinfo       *ar_result;
};
```

Элементы данной структуры совпадают с аргументами getaddrinfo(3). То есть ar_name соответствует аргументу node, а ar_service аргументу service (определяют узел Интернета и службу). Элемент ar_request соответствует аргументу hints; им задаётся критерий выбора структуры возвращаемого адреса сокета. И, наконец, ar_result соответствует аргументу res; вам не нужно инициализировать этот элемент, он будет заполнен автоматически в результате запроса. Структура addrinfo, на которую ссылаются последние два элемента, описана в getaddrinfo(3).

Если значение mode равно GAI_NOWAIT, то уведомления о обработанных запросах можно получить из структуры sigevent, на которую указывает аргумент sevp. Определение и описание данной структуры приведено в sigevent(7). Поле sevp->sigev_notify может иметь следующие значения:

SIGEV_NONE

Отключить уведомление.

SIGEV_SIGNAL

При завершении поиска послать процессу сигнал sigev_signo. Подробности смотрите в sigevent(7). Полю si_code структуры siginfo_t присваивается значение SI_ASYNCNL.

SIGEV_THREAD

При завершении поиска вызвать sigev_notify_function, как если бы с этой функции начиналась бы новая нить. Подробности смотрите в sigevent(7).

При SIGEV_SIGNAL и SIGEV_THREAD, может быть полезно, чтобы sevp->sigev_value.sival_ptr указывала на list.

Функция gai_suspend() приостанавливает выполнение вызывающей нити, ожидая завершения поиска одного или более запросов из массива list. В аргументе nitems задаётся размер массива list. Вызов блокирует выполнение пока не произойдёт одно из следующего:

- Завершится операция для одного или более запросов из list.

- Вызов прервётся пойманным сигналом.

- Временной интервал ожидания задаётся в timeout. В данном аргумента указывается промежуток в секундах плюс наносекундах (о структуре timespec смотрите nanosleep(2)). Если timeout равно NULL, то вызов блокирует выполнение навсегда (пока не произойдёт одно из событий выше).

При выполнении явно не указывается какие запросы завершены; для определения вам нужно обойти весь список запросов с помощью gai_error().

Функция gai_error() возвращает состояние запроса req: EAI_INPROGRESS — запрос пока не выполнен, 0 — обработан успешно, код ошибки — запрос невозможно обработать.

Функция gai_cancel() отменяет запрос req. При успешной отмене состояние ошибки устанавливается в EAI_CANCELED и выполняется обычное асинхронное уведомление. Запрос не может быть отменён, если он начал обрабатываться; в этом случае действие будет доведено до конца, как если бы вызова gai_cancel() не происходило. Если req равно NULL, то будет предпринята попытка отменить все имеющиеся запросы.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Функция getaddrinfo_a() возвращает 0, если все запросы были успешно обработаны или один из следующих ненулевых кодов ошибки:

EAI_AGAIN

Недоступны ресурсы, необходимые, чтобы постановки запросов поиска в очередь. Для нахождения проблемного приложение может проверить состояние ошибки каждого запроса.

EAI_MEMORY

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

EAI_SYSTEM

Неверное значение mode.

Функция gai_suspend() возвращает 0, если завершён хотя бы один из запросов. В противном случае возвращается один из следующих ненулевых кодов ошибки:

EAI_AGAIN

Указанный интервал истёк до завершения хотят бы одного из запросов.

EAI_ALLDONE

В функцию не было передано никаких фактических запросов.

EAI_INTR

Функция прервана сигналом. Заметим, что такое прерывание может быть вызвано сигналом уведомления о каком-то выполненном запросе.

Функция gai_error() может вернуть EAI_INPROGRESS для незаконченных запросов поиска, 0 при успешном поиске (как описано выше), один из кодов ошибок, которые может вернуть getaddrinfo(3) или код ошибки EAI_CANCELED, если запрос был отменён явно до завершения.

Функция gai_cancel() может вернуть одно из следующих значений:

EAI_CANCELED

Запрос успешно отменён.

EAI_NOTCANCELED

Запрос не был отменён.

EAI_ALLDONE

Запрос уже выполнен.

Функция gai_strerror(3) транслирует эти коды ошибок в читаемый формат, подходящий для сообщений об ошибке.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

getaddrinfo_a(), gai_suspend(), gai_error(), gai_cancel()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
Эти функции являются расширениями GNU, доступными в glibc начиная с версии 2.2.3.

## ЗАМЕЧАНИЯ
Интерфейс getaddrinfo_a() был создан после интерфейса lio_listio(3).

## ПРИМЕР
Вот два примера: простой пример выполнения нескольких запросов синхронно одновременно, и сложный пример, показывающий асинхронные возможности.

### Синхронный пример
Эта программа определяет несколько имён узлов параллельно, что быстрее по сравнению с определением имён последовательно с помощью getaddrinfo(3). Результат работы программы:

```
$ ./a.out ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz
ftp.us.kernel.org: 128.30.2.36
enoent.linuxfoundation.org: Name or service not known
gnu.cz: 87.236.197.13
```

Исходный код программы

```
#define _GNU_SOURCE
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char *argv[])
{

    int i, ret;

    struct gaicb *reqs[argc - 1];

    char host[NI_MAXHOST];

    struct addrinfo *res;

    if (argc < 2) {

        fprintf(stderr, "Использование: %s УЗЕЛ...\n", argv[0]);

        exit(EXIT_FAILURE);

    }

    for (i = 0; i < argc - 1; i++) {

        reqs[i] = malloc(sizeof(*reqs[0]));

        if (reqs[i] == NULL) {

            perror("malloc");

            exit(EXIT_FAILURE);

        }

        memset(reqs[i], 0, sizeof(*reqs[0]));

        reqs[i]->ar_name = argv[i + 1];

    }

    ret = getaddrinfo_a(GAI_WAIT, reqs, argc - 1, NULL);

    if (ret != 0) {

        fprintf(stderr, "ошибка getaddrinfo_a(): %s\n",

                gai_strerror(ret));

        exit(EXIT_FAILURE);

    }

    for (i = 0; i < argc - 1; i++) {

        printf("%s: ", reqs[i]->ar_name);

        ret = gai_error(reqs[i]);

        if (ret == 0) {

            res = reqs[i]->ar_result;

            ret = getnameinfo(res->ai_addr, res->ai_addrlen,

                    host, sizeof(host),

                    NULL, 0, NI_NUMERICHOST);

            if (ret != 0) {

                fprintf(stderr, "ошибка getnameinfo(): %s\n",

                        gai_strerror(ret));

                exit(EXIT_FAILURE);

            }

            puts(host);

        } else {

            puts(gai_strerror(ret));

        }

    }

    exit(EXIT_SUCCESS);
}
```

### Асинхронный пример
Данный пример — простая интерактивная оболочка к getaddrinfo_a(). Возможности уведомления не используются.

Результат работы программы:

```
$ ./a.out
> a ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz
> c 2
[2] gnu.cz: Request not canceled
> w 0 1
[00] ftp.us.kernel.org: Выполнено
> l
[00] ftp.us.kernel.org: 216.165.129.139
[01] enoent.linuxfoundation.org: Processing request in progress
[02] gnu.cz: 87.236.197.13
> l
[00] ftp.us.kernel.org: 216.165.129.139
[01] enoent.linuxfoundation.org: Name or service not known
[02] gnu.cz: 87.236.197.13
```

Исходный код программы:

```
#define _GNU_SOURCE
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static struct gaicb **reqs = NULL;
static int nreqs = 0;
static char *
getcmd(void)
{

    static char buf[256];

    fputs("> ", stdout); fflush(stdout);

    if (fgets(buf, sizeof(buf), stdin) == NULL)

        return NULL;

    if (buf[strlen(buf) - 1] == '\n')

        buf[strlen(buf) - 1] = 0;

    return buf;
}
/* добавление запросов задаваемых имён */
static void
add_requests(void)
{

    int nreqs_base = nreqs;

    char *host;

    int ret;

    while ((host = strtok(NULL, " "))) {

        nreqs++;

        reqs = realloc(reqs, nreqs * sizeof(reqs[0]));

        reqs[nreqs - 1] = calloc(1, sizeof(*reqs[0]));

        reqs[nreqs - 1]->ar_name = strdup(host);

    }

    /* очередь запросов nreqs_base..nreqs. */

    ret = getaddrinfo_a(GAI_NOWAIT, &reqs[nreqs_base],

                        nreqs - nreqs_base, NULL);

    if (ret) {

        fprintf(stderr, "ошибка getaddrinfo_a(): %s\n",

                gai_strerror(ret));

        exit(EXIT_FAILURE);

    }
}
/* ждём, пока один из запросов не выполнится */
static void
wait_requests(void)
{

    char *id;

    int i, ret, n;

    struct gaicb const **wait_reqs = calloc(nreqs, sizeof(*wait_reqs));

                /* элементы NULL игнорируются gai_suspend(). */

    while ((id = strtok(NULL, " ")) != NULL) {

        n = atoi(id);

        if (n >= nreqs) {

            printf("Неправильный номер запроса: %s\n", id);

            return;

        }

        wait_reqs[n] = reqs[n];

    }

    ret = gai_suspend(wait_reqs, nreqs, NULL);

    if (ret) {

        printf("gai_suspend(): %s\n", gai_strerror(ret));

        return;

    }

    for (i = 0; i < nreqs; i++) {

        if (wait_reqs[i] == NULL)

            continue;

        ret = gai_error(reqs[i]);

        if (ret == EAI_INPROGRESS)

            continue;

        printf("[%02d] %s: %s\n", i, reqs[i]->ar_name,

               ret == 0 ? "Выполнено" : gai_strerror(ret));

    }
}
/* отменяет заданные запросы */
static void
cancel_requests(void)
{

    char *id;

    int ret, n;

    while ((id = strtok(NULL, " ")) != NULL) {

        n = atoi(id);

        if (n >= nreqs) {

            printf("Неправильный номер запроса: %s\n", id);

            return;

        }

        ret = gai_cancel(reqs[n]);

        printf("[%s] %s: %s\n", id, reqs[atoi(id)]->ar_name,

               gai_strerror(ret));

    }
}
/* перечислим все запросы */
static void
list_requests(void)
{

    int i, ret;

    char host[NI_MAXHOST];

    struct addrinfo *res;

    for (i = 0; i < nreqs; i++) {

        printf("[%02d] %s: ", i, reqs[i]->ar_name);

        ret = gai_error(reqs[i]);

        if (!ret) {

            res = reqs[i]->ar_result;

            ret = getnameinfo(res->ai_addr, res->ai_addrlen,

                              host, sizeof(host),

                              NULL, 0, NI_NUMERICHOST);

            if (ret) {

                fprintf(stderr, "ошибка getnameinfo(): %s\n",

                        gai_strerror(ret));

                exit(EXIT_FAILURE);

            }

            puts(host);

        } else {

            puts(gai_strerror(ret));

        }

    }
}
int
main(int argc, char *argv[])
{

    char *cmdline;

    char *cmd;

    while ((cmdline = getcmd()) != NULL) {

        cmd = strtok(cmdline, " ");

        if (cmd == NULL) {

            list_requests();

        } else {

            switch (cmd[0]) {

            case 'a':

                add_requests();

                break;

            case 'w':

                wait_requests();

                break;

            case 'c':

                cancel_requests();

                break;

            case 'l':

                list_requests();

                break;

            default:

                fprintf(stderr, "Неверная команда: %c\n", cmd[0]);

                break;

            }

        }

    }

    exit(EXIT_SUCCESS);
}
```

## СМОТРИТЕ ТАКЖЕ
getaddrinfo(3), inet(3), lio_listio(3), hostname(7), ip(7), sigevent(7)


getauxval

title: getauxval(3)

text:
# getauxval(3)

## ИМЯ
getauxval - возвращает значение из вспомогательного вектора

## ОБЗОР

```
#include <sys/auxv.h>
```

```
unsigned long getauxval(unsigned long type);
```

## ОПИСАНИЕ
Функция getauxval() возвращает значения из вспомогательного вектора — механизма, с помощью которого ядерный загрузчик двоичных файлов ELF передаёт информацию в пользовательское пространство при выполнении программы.

Каждая запись в вспомогательном векторе состоит из пары значений: типа — которым определяется смысл записи и значением этого типа. Согласно аргументу type, getauxval() возвращает соответствующее значение.

Значения для типов для type представлены в списке далее. Не все значения type есть для всех архитектур.

AT_BASE

Основной (base) адрес программного интерпретатора (обычно, динамического компоновщика).

AT_BASE_PLATFORM

Строка, определяющая реальную платформу; может отличаться от AT_PLATFORM (только для PowerPC).

AT_CLKTCK

Частота, с которой считает times(2). Это значение также может быть получено с помощью sysconf(_SC_CLK_TCK).

AT_DCACHEBSIZE

Размер блока кэша данных.

AT_EGID

Эффективный идентификатор группы нити.

AT_ENTRY

Адрес точки старта (entry address) исполняемого файла.

AT_EUID

Эффективный идентификатор пользователя нити.

AT_EXECFD

Файловый дескриптор программы.

AT_EXECFN

Путь, использованный для запуска программы.

AT_FLAGS

Флаги (не используется).

AT_FPUCW

Используемое слово управления FPU (только для SuperH). Оно даёт некоторую информацию о нагрузке FPU, выполняемой ядром.

AT_GID

Реальный идентификатор группы нити.

AT_HWCAP

Битовая маска, зависящая от архитектуры и двоичного программного интерфейса, подробно описывает возможности процессора. Содержимое битовой маски зависит от аппаратуры (например, в файле исходного кода ядра arch/x86/include/asm/cpufeature.h описана маска для архитектуры Intel x86; возвращаемое значение — первое 32-битное слово описываемого здесь массива). Эта же информация в формате, понятном человеку, доступна в файле /proc/cpuinfo.

AT_HWCAP2 (начиная с glibc 2.18)

Дополнительные упоминания о возможностях процессора.

AT_ICACHEBSIZE

Размер блока кэша инструкций.

AT_L1D_CACHEGEOMETRY

Структура кэша данных L1, в которой закодирован размер строки кэша в байтах в младших 16 битах и ассоциативность кэша в следующих 16 битах. Значение ассоциативности N выражается 16-битным числом, указывающим на N-канальную ассоциативность.

AT_L1D_CACHESIZE

Размер кэша данных L1.

AT_L1I_CACHEGEOMETRY

Структура кэша инструкций L1, кодируется также как AT_L1D_CACHEGEOMETRY.

AT_L1I_CACHESIZE

Размер кэша инструкций L1.

AT_L2_CACHEGEOMETRY

Структура кэша L2, кодируется также как AT_L1D_CACHEGEOMETRY.

AT_L2_CACHESIZE

Размер кэша L2.

AT_L3_CACHEGEOMETRY

Структура кэша L3, кодируется также как AT_L1D_CACHEGEOMETRY.

AT_L3_CACHESIZE

Размер кэша L3.

AT_PAGESZ

Размер системной страницы (это же значение возвращается sysconf(_SC_PAGESIZE)).

AT_PHDR

Адрес заголовков программы исполняемого файла.

AT_PHENT

Размер элемента заголовка программы.

AT_PHNUM

Количество заголовков программы.

AT_PLATFORM

Указатель на строку, описывающую аппаратную платформу, на которой выполняется программа. Динамический компоновщик использует её при рассмотрении значений rpath.

AT_RANDOM

Адрес 16 байт, содержащих произвольное значение.

AT_SECURE

Содержит ненулевое значение, если исполняемый файл должен считаться безопасным. Чаще всего, ненулевое значение означает, что процесс выполняет программу с установленным set-user-ID или set-group-ID битом (то есть его реальный и эффективный UID или GID отличаются от начального) или же он получает мандаты, запуская двоичный файл с другими мандатами (смотрите capabilities(7)). Также ненулевое значение может выставляться Linux Security Module. Если значение не ноль, то динамический компоновщик прекращает использовать определённые переменные окружения (смотрите ld-linux.so(8)) и изменяется некоторое поведение glibc (также смотрите secure_getenv(3)).

AT_SYSINFO

Точка входа в функцию системного вызова в vDSO. Отсутствует/не нужна для всех архитектур (например, отсутствует на x86-64).

AT_SYSINFO_EHDR

Адрес страницы, содержащий виртуальный Динамический Общий Объект (Dynamic Shared Object, vDSO), который ядро создаёт для предоставления более быстрой реализации некоторых системных вызовов.

AT_UCACHEBSIZE

Размер блока универсального кэша.

AT_UID

Реальный идентификатор пользователя нити.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении getauxval() возвращает значение, соответствующее type.Если type не найден, то возвращается 0.

## ОШИБКИ
ENOENT (начиная с glibc 2.19)

В вспомогательном векторе не найдено значение, соответствующее type.

## ВЕРСИИ
Функция getauxval() впервые появилась в glibc 2.16.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

getauxval()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
Эта функция является нестандартным расширением glibc.

## ЗАМЕЧАНИЯ
Основным пользователем информации из вспомогательного вектора является динамический компоновщик ld-linux.so(8). Вспомогательный вектор удобное и эффективное средство для предоставления ядром некоторого набора стандартной информации, которая обычно или всегда требуется динамическому компоновщику. В некоторых случаях эта информация может быть получена через системные вызовы, но использование вспомогательного вектора экономичней.

Вспомогательный вектор располагается выше списка аргументов и окружения в адресном пространстве процесса. Переданный программе вектор можно просмотреть установив переменную окружения LD_SHOW_AUXV и запустив программу:

```
$ LD_SHOW_AUXV=1 sleep 1
```

Вспомогательный вектор любого процесса может быть получен (при наличии прав доступа) через /proc/[pid]/auxv; подробней смотрите в proc(5).

## ДЕФЕКТЫ
До того как ошибка ENOENT не была добавлена в glibc 2.19, не было способа достоверно определить, что type не найден, если значение type равно нулю.

## СМОТРИТЕ ТАКЖЕ
secure_getenv(3), vdso(7), ld-linux.so(8)


getcontext

title: getcontext(3)

text:
# getcontext(3)

## ИМЯ
getcontext, setcontext - получить или установить пользовательский контекст

## ОБЗОР
\#include <ucontext.h>

int getcontext(ucontext_t *ucp);

int setcontext(const ucontext_t *ucp);

## ОПИСАНИЕ
В окружении, подобном SysV, существует два типа данных —mcontext_t и ucontext_t, которые определены в файле <ucontext.h> и четыре функции — getcontext(), setcontext(), makecontext(3) и swapcontext(3), которые позволяют контексту пользовательского уровня переключаться между несколькими нитями внутри одного процесса.

Тип mcontext_t является машинно-зависимым и примитивным типом данных. Тип ucontext_t является структурой, которая по крайней мере имеет следующие поля:

```
typedef struct ucontext_t {

    struct ucontext_t *uc_link;

    sigset_t          uc_sigmask;

    stack_t           uc_stack;

    mcontext_t        uc_mcontext;

    ...
} ucontext_t;
```

где sigset_t и stack_t определены в файле <signal.h>. В этой структуре uc_link указывает на контекст, к которому будет осуществлён переход, когда завершается текущий контекст (в случае, если текущий контекст был создан с помощью makecontext(3)), в uc_sigmask задаётся список сигналов, которые блокируются в этом контексте (см. sigprocmask(2)), uc_stack — это стек, который используется этим контекстом (см. sigaltstack(2)), а uc_mcontext является машинно-зависимым представлением сохранённого контекста, который содержит регистры вызываемой нити.

Функция getcontext() инициализирует вышеописанную структуру, указывая через ucp на текущий активный контекст.

Функция setcontext() восстанавливает пользовательский контекст, на который указывает ucp. При успешном вызове управление не возвращается обратно. Контекст должен быть получен с помощью вызова getcontext() или makecontext(3) или передан как третий аргумент обработчика сигнала.

Если контекст был получен через вызов getcontext(), то выполнение программы продолжается как если бы этот вызов завершился простым возвратом.

Если контекст был получен через вызов makecontext(3), выполнение программы продолжается с помощью вызова функции func, которая задаётся как второй аргумент вызова makecontext(3). Когда происходит возврат из функции func, выполнение продолжается с поля uc_link структуры ucp, которая задаётся как первый аргумент вызова makecontext(3). Если это поле равно NULL, осуществляется выход из нити.

Если контекст был получен с помощью вызова обработчика сигнала, то старый текст стандарта говорит, что "выполнение программы продолжается с инструкции программы, которая следует за инструкцией, прерванной сигналом". Однако, этот текст был удалён в SUSv2 с вердиктом "результат не определён".

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
В случае успеха getcontext() возвращает 0, а setcontext() не возвращает ничего. В случае ошибки, возвращается -1 и значение errno устанавливается соответствующим образом.

## ОШИБКИ
Не определены.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

getcontext(), setcontext()

Безвредность в нитях

MT-Safe race:ucp

## СООТВЕТСТВИЕ СТАНДАРТАМ
SUSv2, POSIX.1-2001. В POSIX.1-2008 удалено определение getcontext() со ссылкой на проблемы с переносимостью и рекомендацией переписать приложение с использование нитей POSIX.

## ЗАМЕЧАНИЯ
В ранних версиях этого механизма использовался механизм setjmp(3)/longjmp(3). Так как в нём нет обработки контекста сигнала, было решено использовать следующий вариант пары sigsetjmp(3)/siglongjmp(3). Текущий механизм даёт много больше контроля. С другой стороны, не существует лёгкого способа определить какое из двух значений возвращает при первом запуске вызов getcontext() или вызов setcontext(). Пользователь должен придумать собственный способ и через регистровую переменную это сделать нельзя, так как значения регистров восстанавливаются.

Если возникнет сигнал, текущий пользовательский контекст сохраняется и для обработчика сигнала ядром создаётся новый контекст. Не выходите из этого обработчика, используя longjmp(3) — неизвестно, что может случиться с контекстами. Вместо этого используйте вызовы siglongjmp(3) или setcontext().

## СМОТРИТЕ ТАКЖЕ
sigaction(2), sigaltstack(2), sigprocmask(2), longjmp(3), makecontext(3), sigsetjmp(3)


getcwd

title: getcwd(3)

summary: возвращают текущий рабочий каталог

text:
# getcwd(3)

## ИМЯ
getcwd, getwd, get_current_dir_name - возвращают текущий рабочий каталог

## ОБЗОР

```
#include <unistd.h>
```

```
char *getcwd(char *buf, size_t size);
```

```
char *getwd(char *buf);
```

```
char *get_current_dir_name(void);
```

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

get_current_dir_name():

_GNU_SOURCE

getwd():

Начиная с glibc 2.12:

```
(_XOPEN_SOURCE >= 500) && ! (_POSIX_C_SOURCE >= 200809L)

    || /* начиная с glibc 2.19: */ _DEFAULT_SOURCE

    || /* версии glibc <= 2.19: */ _BSD_SOURCE
```

До glibc 2.12: _BSD_SOURCE || _XOPEN_SOURCE >= 500

## ОПИСАНИЕ
Данные функции возвращают строку (с null в конце), содержащую абсолютный путь текущего рабочего каталога вызывающего процесса. Путь возвращается как результат функции или в аргументе buf, если он есть.

Функция getcwd() копирует абсолютный путь текущего рабочего каталога в массив, на который указывает buf, имеющий длину size.

Если длина абсолютного пути, включая конечный байт null, превышает size байт, то возвращается NULL, а errno принимает значение ERANGE; приложение должно проверить, возникла эта ошибка или нет и, если необходимо, выделить буфер большего размера.

Согласно расширению стандарта POSIX.1-2001 в glibc предусмотрено следующее: если buf равно NULL, то при вызове getcwd() буфер выделяется динамически с помощью функции malloc(3). В этом случае выделенный буфер имеет размер size; если size равно нулю, то выделяется buf необходимого размера. Вызывающий после использования должен освободить выделенный буфер с помощью free(3).

Функция get_current_dir_name() выделит с помощью malloc(3) массив, достаточно большой для помещения в него абсолютного пути имени текущего каталога. Если существует и имеет правильное значение переменная окружения PWD, то будет возвращено её значение. Вызывающий после использования должен освободить выделенный буфер с помощью free(3).

Функция getwd() не выделяет память с помощью malloc(3). Аргумент buf должен быть указателем на массив длиной не менее PATH_MAX байтов. Если длина абсолютного пути текущего рабочего каталога, включая конечный байт null, превышает PATH_MAX байт, то возвращается NULL и errno присваивается значение ENAMETOOLONG (заметим, что в некоторых системах PATH_MAX может не являться константой времени компиляции; более того, её значение может зависеть от файловой системы, смотрите pathconf(3)). Для переносимости и безопасности использование getwd() не рекомендуется.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении эти функции возвращают указатель на строку, содержащую пути текущего рабочего каталога. У getcwd() и getwd() это значение совпадает с buf.

При ошибках эти функции возвращают NULL и в errno помещают причину ошибки. Содержимое массива buf в этом случае не определено.

## ОШИБКИ
EACCES

Нет прав на чтение или поиск одного из компонентов пути файла.

EFAULT

Значение buf указывает на неправильный адрес.

EINVAL

Аргумент size равен нулю, а buf не является указателем null.

EINVAL

getwd(): buf равно NULL.

ENAMETOOLONG

getwd(): Размер строки абсолютного пути, включая конечный null, превышает PATH_MAX байт.

ENOENT

Текущий рабочий каталог был удалён.

ENOMEM

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

ERANGE

Аргумент size меньше длины абсолютного пути рабочего каталога, включая конечный байт null. Вам нужно выделить массив большего размера попробовать ещё раз.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

getcwd(), getwd()

Безвредность в нитях

MT-Safe

get_current_dir_name()

Безвредность в нитях

MT-Safe env

## СООТВЕТСТВИЕ СТАНДАРТАМ
Функция getcwd() соответствует POSIX.1-2001. Однако заметим, что в POSIX.1-2001 не описано поведение getcwd(), если buf равно NULL.

Функция getwd() описана в POSIX.1-2001, но помечена как УСТАРЕВШАЯ. В POSIX.1-2008 getwd() удалена. Вместо неё используйте getcwd(). В POSIX.1-2001 не определены ошибки, возвращаемые getwd().

Функция get_current_dir_name() является расширением GNU.

## ЗАМЕЧАНИЯ
В Linux, эти функции используют системный вызов getcwd() (доступен в Linux, начиная с версии 2.1.92). В старых системах они опрашивают /proc/self/cwd. Если в системе отсутствует системный вызов и файловая система proc, то задействуется обобщённая реализация. Только в этом случает данные вызовы в Linux могут завершиться с ошибкой EACCES.

Данные функции часто используются для сохранения расположения текущего рабочего каталога с целью возврата в него позднее. Открытие текущего каталога («.») и вызов fchdir(2) для возврата, обычно, более быстрая и надёжная альтернатива при наличии достаточного количества файловых дескрипторов, особенно на платформах, отличных от Linux.

### Отличия между библиотекой C и ядром
Ядро Linux предоставляет системный вызов getcwd(), который, если возможно, будут использовать описываемые на этой страницы функции. Системный вызов имеет такие же параметры как и библиотечная функция с тем же именем, но возвращает не более PATH_MAX байт (до Linux 3.12 размер возвращаемого пути ограничивался размером системной страницы. На многих архитектурах PATH_MAX и размер системной страницы равны 4096 байтам, но у некоторых архитектур размер страницы больше этого значения). Если длина пути текущего рабочего каталога превышает это ограничение, то системный вызов возвращает ошибку ENAMETOOLONG. В этом случае библиотечные функции переходят к использованию альтернативной (медленной) реализации, которая возвращает полный путь.

После внесения изменения в Linux 2.6.36, путь, возвращаемый системным вызовом getcwd(), будет начинаться со строки «(unreachable)», если текущий каталог не ниже корневого каталога текущего процесса (например, из-за того, что процесс установил новую корневую файловую систему с помощью chroot(2) без изменения своего текущего каталога в новый корень). Такое поведение также проявляется у непривилегированного пользователя текущий каталог переводится в другое пространство имён монтирования. При работе с путём из недоверенных источников вызывающие описанные на этой странице функции должны учитывать, что возвращаемый путь может начинаться с «/» или «(», и не принимать недоступный путь за относительный.

## ДЕФЕКТЫ
Так как изменения в Linux 2.6.36 добавляет при описанных выше определённых обстоятельствах «(unreachable)», реализация getcwd() в glibc нарушает POSIX и возвращает относительный путь, в то время как по соглашению API требуется абсолютный путь. В glibc 2.27 и новее это исправлено; вызов getcwd() из такого пути приводит к ошибке ENOENT.

## СМОТРИТЕ ТАКЖЕ
pwd(1), chdir(2), fchdir(2), open(2), unlink(2), free(3), malloc(3)


getdate

title: getdate(3)

text:
# getdate(3)

## ИМЯ
getdate, getdate_r - разделяет строку дата+время на отдельные части

## ОБЗОР
\#include <time.h>

struct tm *getdate(const char *string);

extern int getdate_err;

\#include <time.h>

int getdate_r(const char *string, struct tm *res);

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

getdate():

_XOPEN_SOURCE >= 500

getdate_r(): _GNU_SOURCE

## ОПИСАНИЕ
Функция getdate() преобразует строковое представление даты и времени из буфера, на который указывает string в разделённое на компоненты время. Разделённое время сохраняется в структуре tm и указатель на неё возвращается в качестве результата. Структура tm находится в статической области и, таким образом, будет перезаписана при следующих вызовах getdate().

В отличие от strptime(3), (которая имеет аргумент format), функция getdate() использует форматы, содержащиеся в файле, полный путь к которому содержится в переменной окружения DATEMSK. Первая строка файла, которая совпадает с полученной входной строкой, будет использована для преобразования.

Проверка на совпадение производится без учета регистра. Лишние пробелы как в шаблоне, так и в преобразуемой строке игнорируются.

Описатели преобразования, которые могут быть указаны в шаблоне, соответствуют используемым в strptime(3). Кроме того, понимается ещё один описатель POSIX.1-2001:

%Z

Имя часового пояса. Не реализован в glibc.

Если указан %Z, то структура с разделённым временем инициализируется значениями в соответствие с текущим временем указанного часового пояса. В противном случае, структура инициализируется разделённым временем в соответствии с текущим местным временем (как при вызове localtime(3)).

Если указан только день недели, то берётся ближайший день или завтрашний.

Если указан только месяц (и не указан год), то берётся первый месяц, эквивалентный заданному, или следующий. Если не указан день, то это будет первый день месяца.

Если не указаны часы, минуты и секунды, то берётся текущий час, минута и секунда.

Если не указана дата, но мы знаем час, то будет взят первый час, равный заданному, начиная с текущего часа.

Функция getdate_r() является расширением GNU и предоставляет реентерабельную версию getdate(). Она не использует глобальную переменную для сообщения об ошибках и статический буфер для возвращаемого разделённого времени, она возвращает ошибки как результат функции, а разделённое время возвращается в выделенном вызывающем буфере, на который указывает аргумент res.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении getdate() возвращает указатель на struct tm. В противном случае возвращается NULL, а глобальная переменная getdate_err содержит один из номеров ошибок, перечисленных ниже. Изменения errno не определены.

При успешном выполнении getdate_r() возвращает 0; при ошибке возвращается одно из значений ошибки, перечисленных далее.

## ОШИБКИ
Следующие ошибки возвращаются в getdate_err (для getdate()) или как результат функции (для getdate_r()):

1

Переменная окружения DATEMSK не определена или её значение — пустая строка.

2

Файл шаблонов, заданный DATEMSK, не может быть открыт на чтение.

3

Не удалось получить информацию о состоянии файла.

4

Файл шаблонов не является обычным файлом.

5

Произошла ошибка при чтении файла шаблонов.

6

Не удалось выделить память (недостаточно памяти).

7

В файле нет строки, совпавшей с входной.

8

Неверный формат входной строки.

## ОКРУЖЕНИЕ
DATEMSK

Файл, содержащий шаблоны форматирования.

TZ, LC_TIME

Переменные, используемые strptime(3).

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

getdate()

Безвредность в нитях

MT-Unsafe race:getdate env locale

getdate_r()

Безвредность в нитях

MT-Safe env locale

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008.

## ЗАМЕЧАНИЯ
В описании POSIX.1 для strptime(3) содержится преобразуемые описатели использующие модификатор %E или %O, хотя эти описатели не указаны для getdate(). В glibc, getdate() реализована посредством strptime(3), таким образом поддерживаются все возможные описатели.

## ПРИМЕР
Программа, представленная далее, вызывает getdate() для каждого своего аргумента командной строки и при каждом вызове печатаются значения полей полученной структуры tm. Следующий сеанс показывает работу программы:

```
$ TFILE=$PWD/tfile
$ echo '%A' > $TFILE       # полное название дня недели
$ echo '%T' >> $TFILE      # дата ISO (YYYY-MM-DD)
$ echo '%F' >> $TFILE      # время (HH:MM:SS)
$ date
$ export DATEMSK=$TFILE
$ ./a.out Tuesday '2009-12-28' '12:22:33'
Sun Sep  7 06:03:36 CEST 2008
Call 1 ("Tuesday"):

    tm_sec   = 36

    tm_min   = 3

    tm_hour  = 6

    tm_mday  = 9

    tm_mon   = 8

    tm_year  = 108

    tm_wday  = 2

    tm_yday  = 252

    tm_isdst = 1
Call 2 ("2009-12-28"):

    tm_sec   = 36

    tm_min   = 3

    tm_hour  = 6

    tm_mday  = 28

    tm_mon   = 11

    tm_year  = 109

    tm_wday  = 1

    tm_yday  = 361

    tm_isdst = 0
Call 3 ("12:22:33"):

    tm_sec   = 33

    tm_min   = 22

    tm_hour  = 12

    tm_mday  = 7

    tm_mon   = 8

    tm_year  = 108

    tm_wday  = 0

    tm_yday  = 250

    tm_isdst = 1
```

### Исходный код программы

```
#define _GNU_SOURCE
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{

    struct tm *tmp;

    int j;

    for (j = 1; j < argc; j++) {

        tmp = getdate(argv[j]);

        if (tmp == NULL) {

            printf("Ошибка вызова %d; getdate_err = %d\n",

                   j, getdate_err);

            continue;

        }

        printf("Вызов %d (\"%s\"):\n", j, argv[j]);

        printf("    tm_sec   = %d\n", tmp->tm_sec);

        printf("    tm_min   = %d\n", tmp->tm_min);

        printf("    tm_hour  = %d\n", tmp->tm_hour);

        printf("    tm_mday  = %d\n", tmp->tm_mday);

        printf("    tm_mon   = %d\n", tmp->tm_mon);

        printf("    tm_year  = %d\n", tmp->tm_year);

        printf("    tm_wday  = %d\n", tmp->tm_wday);

        printf("    tm_yday  = %d\n", tmp->tm_yday);

        printf("    tm_isdst = %d\n", tmp->tm_isdst);

    }

    exit(EXIT_SUCCESS);
}
```

## СМОТРИТЕ ТАКЖЕ
time(2), localtime(3), setlocale(3), strftime(3), strptime(3)


getdirentries

title: getdirentries(3)

text:
# getdirentries(3)

## ИМЯ
getdirentries - возвращает элементы каталога в формате, не зависящем от файловой системы

## ОБЗОР
\#include <dirent.h>

ssize_t getdirentries(int fd, char *buf, size_t nbytes , off_t *basep);

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

getdirentries(),

начиная с glibc 2.19:

_DEFAULT_SOURCE

в glibc 2.19 и старее:

_BSD_SOURCE || _SVID_SOURCE

## ОПИСАНИЕ
Данная функция считывает (не более nbytes байтов) элементы каталога, указанного в fd, в buf. Чтение начинается со смещения *basep и после чтения *basep обновляется в соответствии с новой позицией.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Функция getdirentries() возвращает количество считанных байтов или ноль, если достигнут конец каталога. Если произошла ошибка, возвращается -1, и устанавливается, соответствующим образом, переменная errno.

## ОШИБКИ
Дополнительную информацию смотрите в исходном коде библиотеки Linux.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

getdirentries()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
Нет в POSIX.1. Присутствует в BSD и многих других системах. Используйте вместо нее opendir(3) и readdir(3).

## СМОТРИТЕ ТАКЖЕ
lseek(2), open(2)


getdtablesize

title: getdtablesize(3)

text:
# getdtablesize(3)

## ИМЯ
getdtablesize - возвращает размер таблицы файловых дескрипторов

## ОБЗОР
\#include <unistd.h>

int getdtablesize(void);

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

getdtablesize():

Начиная с glibc 2.12:

```
/* начиная с glibc 2.19: */ _DEFAULT_SOURCE

    || /* версии glibc <= 2.19: */ _BSD_SOURCE

    || ! (_POSIX_C_SOURCE >= 200112L)
```

До glibc 2.12: _BSD_SOURCE || _XOPEN_SOURCE >= 500

## ОПИСАНИЕ
getdtablesize() возвращает максимальное количество файлов, которое может быть открыто в процессе, на единицу больше, чем наибольшее возможное значение для дескриптора файла.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Текущее ограничение на количество открытых файлов для процесса.

## ОШИБКИ
В Linux, getdtablesize() может вернуть любую ошибку из описанных в getrlimit(2); см. ЗАМЕЧАНИЯ далее.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

getdtablesize()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
SVr4, 4.4BSD (функция getdtablesize() впервые появилась в 4.2BSD). Она отсутствует в POSIX.1; переносимые приложения вместо неё должны применять sysconf(_SC_OPEN_MAX).

## ЗАМЕЧАНИЯ
Функция getdtablesize() реализована в виде библиотечной функции libc. Версия glibc вызывает getrlimit(2) и возвращает текущее ограничение RLIMIT_NOFILE; при ошибке возвращается OPEN_MAX.

## СМОТРИТЕ ТАКЖЕ
close(2), dup(2), getrlimit(2), open(2)


getentropy

title: getentropy(3)

summary: заполнение буфера случайными байтами

text:
# getentropy(3)

## ИМЯ
getentropy - заполнение буфера случайными байтами

## ОБЗОР
\#include <unistd.h>

int getentropy(void *buffer, size_t length);

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

getentropy():

_DEFAULT_SOURCE

## ОПИСАНИЕ
Функция getentropy() записывает length байт высококачественных случайных данных в буфер, начинающийся в области, указанной в buffer. Максимально разрешенное значение аргумента length равно 256.

Успешный вызов getentropy() всегда предоставляет затребованное число байт энтропии.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
В случае успеха функция возвращает 0. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.

## ОШИБКИ
EFAULT

Часть или весь буфер, указанный в buffer и length, не является валидной адресуемой памятью.

EIO

Значение length больше 256.

EIO

При попытке перезаписать buffer случайными данными произошла ошибка.

ENOSYS

Данная версия ядра не имеет реализации системного вызова getrandom(2), необходимого для реализации данной функции.

## ВЕРСИИ
Функция getentropy() впервые появилась в glibc 2.25.

## СООТВЕТСТВИЕ СТАНДАРТАМ
Эта функция является нестандартной. Она также присутствует в OpenBSD.

## ЗАМЕЧАНИЯ
Функция getentropy() реализована через вызов getrandom(2).

Следует учитывать, что в glibc обертка делает getrandom(2) точкой отмены, а точкой отмены getentropy() не является.

Функция getentropy() также объявлена в <sys/random.h> (для получения этого объявления из заголовочного файла макроса тестирования свойств не требуется).

Вызов getentropy() может блокировать работу, если система только что загрузилась и ядро ещё не успело набрать достаточно случайных событий для инициализации пула энтропии. В этом случае getentropy() продолжает блокировать работу даже при обработке сигнала и вернёт управление только после завершения инициализации пула энтропии.

## СМОТРИТЕ ТАКЖЕ
getrandom(2), urandom(4), random(7)


getenv

title: getenv(3)

text:
# getenv(3)

## ИМЯ
getenv, secure_getenv - возвращают значения переменной окружения

## ОБЗОР

```
#include <stdlib.h>
```

```
char *getenv(const char *name);
```

```
char *secure_getenv(const char *name);
```

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

secure_getenv(): _GNU_SOURCE

## ОПИСАНИЕ
Функция getenv() ищет в списке окружения переменную окружения name и возвращает указатель на соответствующую строку value.

Специальная функция GNU secure_getenv() работает также как getenv(), но возвращает NULL, если требуется «безопасное выполнение». Безопасное выполнение требуется, если верно одно из следующих условий на момент загрузки программы вызывающего процесса:

- эффективный пользовательский ID процесса не совпадает с реальным пользовательским ID или эффективный групповой ID процесса не совпадает с реальным групповым ID (обычно в результате выполнения программы с установленным битом set-user-ID или set-group-ID);

- у исполняемого файла установлен эффективный мандатный бит; или

- у процесса имеется непустой ограничивающий набор мандатов.

Безопасное выполнение также может требоваться некоторыми модулями безопасности Linux.

Функция secure_getenv() предназначена для библиотек общего назначения с целью недопущения уязвимостей, которые могли бы возникнуть, если программы с битом set-user-ID или set-group-ID ненамеренно доверяли бы окружению.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Функция getenv() возвращает указатель на значение в окружении или NULL, если ничего не найдено.

## ВЕРСИИ
Функция secure_getenv() впервые появилась в glibc версии 2.17.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

getenv(), secure_getenv()

Безвредность в нитях

MT-Safe env

## СООТВЕТСТВИЕ СТАНДАРТАМ
getenv(): POSIX.1-2001, POSIX.1-2008, C89, C99, SVr4, 4.3BSD.

Функция secure_getenv() является расширением GNU.

## ЗАМЕЧАНИЯ
Строки в списке окружения имеют вид имя=значение.

В типичной реализации getenv() возвращает указатель на строку в списке окружения. Вызывающий не должен изменять эту строку, так как это изменить окружение процесса.

Реализации getenv() не требуется быть реентерабельной. Строка, указанная в возвращаемом значение getenv(), может быть выделена статически и может изменяться после вызова getenv() с помощью putenv(3), setenv(3) или unsetenv(3).

Режим «безопасного выполнения» в secure_getenv() управляется флагом AT_SECURE вспомогательного вектора, передаваемого из ядра в пользовательское пространство.

## СМОТРИТЕ ТАКЖЕ
clearenv(3), getauxval(3), putenv(3), setenv(3), unsetenv(3), capabilities(7), environ(7)


getfsent

title: getfsent(3)

summary: для работы с записями

text:
# getfsent(3)

## ИМЯ
getfsent, getfsspec, getfsfile, setfsent, endfsent - для работы с записями fstab

## ОБЗОР
\#include <fstab.h>

void endfsent(void);

struct fstab *getfsent(void);

struct fstab *getfsfile(const char *mount_point);

struct fstab *getfsspec(const char *special_file);

int setfsent(void);

## ОПИСАНИЕ
Эти функции читают файл /etc/fstab. Структура struct fstab определена следующим образом:

```
struct fstab {

    char       *fs_spec;       /* имя блочного устройства */

    char       *fs_file;       /* точка монтирования */

    char       *fs_vfstype;    /* тип файловой системы */

    char       *fs_mntops;     /* параметры монтирования */

    const char *fs_type;       /* параметр rw/rq/ro/sw/xx */

    int         fs_freq;       /* периодичность запуска dump, в днях */

    int         fs_passno;     /* номер прохода при параллельном dump */
};
```

Здесь поле fs_type содержит (в системах *BSD) одну из пяти строк: «rw», «rq», «ro», «sw», «xx» (чтение-запись, чтение-запись с квотами, только-чтение, подкачка, игнорировать).

Функция setfsent() открывает файл при необходимости и устанавливает указатель на первую строку.

Функция getfsent() обрабатывает следующую строку из файла (открыв файл, если требуется).

Функция endfsent() закрывает файл, если требуется.

Функция getfsspec() ищет с начала файла запись, для которой поле fs_spec соответствует аргументу special_file и возвращает её.

Функция getfsfile() ищет с начала файла запись, для которой поле fs_file соответствует аргументу mount_point и возвращает её.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении функции getfsent(), getfsfile() и getfsspec() возвращают указатель на структуру struct fstab, а setfsent() возвращает 1. При ошибке или обнаружении конца файла эти функции возвращают, соответственно, NULL или 0.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

endfsent(), setfsent()

Безвредность в нитях

MT-Unsafe race:fsent

getfsent(), getfsspec(), getfsfile()

Безвредность в нитях

MT-Unsafe race:fsent locale

## СООТВЕТСТВИЕ СТАНДАРТАМ
Эти функции не включены в POSIX.1. Они имеются в некоторых операционных системах, например *BSD, SunOS, Digital UNIX, AIX (в котором также есть getfstype()). В HP-UX есть функции с тем же именем, но вместо структуры struct fstab они используют структуру struct checklist, и вызовы этих функций устарели, они заменены на getmntent(3).

## ЗАМЕЧАНИЯ
Эти функции нельзя использовать в нескольких нитях одновременно.

Так как Linux позволяет монтировать специальное блочное устройство в несколько разных точек, а также так как несколько устройств могут иметь одну точку монтирования, то неясно, будет ли результат (первая запись), возвращенный функциями getfsfile() и getfsspec() именно тем, что и ожидался. Поэтому эти две функции не подходят для использования под Linux.

## СМОТРИТЕ ТАКЖЕ
getmntent(3), fstab(5)


getgrent

title: getgrent(3)

summary: возвращает запись из файла групп

text:
# getgrent(3)

## ИМЯ
getgrent, setgrent, endgrent - возвращает запись из файла групп

## ОБЗОР

```
#include <sys/types.h>
#include <grp.h>
```

```
struct group *getgrent(void);
```

```
void setgrent(void);
```

```
void endgrent(void);
```

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

setgrent():

_XOPEN_SOURCE >= 500

|| /* начиная с glibc 2.19: */ _DEFAULT_SOURCE

|| /* версии gibc <= 2.19: */ _BSD_SOURCE || _SVID_SOURCE

getgrent(), endgrent():

начиная с glibc 2.22:

_XOPEN_SOURCE >= 500 ||

_DEFAULT_SOURCE

в glibc 2.21 и старее

_XOPEN_SOURCE >= 500

|| /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200809L

|| /* Glibc versions <= 2.19: */ _BSD_SOURCE || _SVID_SOURCE

## ОПИСАНИЕ
Функция getgrent() возвращает указатель на структуру, содержащую разделённую на поля запись базы данных групп (например, локального файла групп /etc/group, NIS и LDAP). При первом вызове getgrent() возвращает первую запись; при следующих последовательно возвращаются остальные записи.

Функция setgrent() возвращается к началу базы данных групп, позволяя выполнять повторное сканирование.

Функция endgrent() используется для закрытия базы данных групп при завершении процесса обработки.

Структура group определена в <grp.h> следующим образом:

```
struct group {

    char   *gr_name;        /* имя группы */

    char   *gr_passwd;      /* пароль группы */

    gid_t   gr_gid;         /* ID группы */

    char  **gr_mem;         /* массив, указателей

                               имён членов группы, оканчивающийся NULL */
};
```

Подробней о полях этой структуры смотрите в group(5).

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Функция getgrent() возвращает указатель на структуру group или NULL, если записи закончились или произошла ошибка.

При ошибке может измениться значение errno. Если нужно проверять переменную errno после вызова, то перед этим нужно присвоить ей нулевое значение.

Возвращаемое значение может указывать на статическую область и может быть перезаписано при последующих вызовах getgrent(), getgrgid(3) или getgrnam(3) (не передавайте полученный указатель free(3)).

## ОШИБКИ
EAGAIN

Служба временно недоступна; попробуйте позднее. Для NSS из glibc это указывает на временную ошибку обмена с сервером. Ошибка может исчезнуть самостоятельно, предлагается попробовать повторить вызов позднее.

EINTR

Поступил сигнал; смотрите signal(7).

EIO

Ошибка ввода-вывода.

EMFILE

Было достигнуто ограничение по количеству открытых файловых дескрипторов на процесс.

ENFILE

Достигнуто максимальное количество открытых файлов в системе.

ENOENT

Необходимый входной файл не найден. Для NSS в glibc это указывает на то, что служба некорректно настроена.

ENOMEM

Недостаточно памяти для структуры group.

ERANGE

Недостаточно места в буфере.

## ФАЙЛЫ
/etc/group

локальный файл базы данных групп

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

getgrent()

Безвредность в нитях

MT-Unsafe race:grent race:grentbuf locale

setgrent(), endgrent()

Безвредность в нитях

MT-Unsafe race:grent locale

В приведённой выше таблице grent в race:grent означает, что если в нескольких нитях программы одновременно используются функции setgrent(), getgrent() или endgrent(), то может возникнуть состязательность по данным.

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.

## СМОТРИТЕ ТАКЖЕ
fgetgrent(3), getgrent_r(3), getgrgid(3), getgrnam(3), getgrouplist(3), putgrent(3), group(5)


title: getgrent_r(3)

text:
# getgrent_r(3)

## ИМЯ
getgrent_r, fgetgrent_r - возвращает запись из файла групп (реентерабельные версии)

## ОБЗОР

```
#include <grp.h>
```

```
int getgrent_r(struct group *gbuf, char *buf,
               size_t buflen, struct group **gbufp);
```

```
int fgetgrent_r(FILE *stream, struct group *gbuf, char *buf,
                size_t buflen, struct group **gbufp);
```

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

getgrent_r(): _GNU_SOURCE

fgetgrent_r():

начиная с glibc 2.19:

_DEFAULT_SOURCE

в glibc 2.19 и старее:

_SVID_SOURCE

## ОПИСАНИЕ
Функции getgrent_r() и fgetgrent_r() являются реентерабельными версиями getgrent(3) и fgetgrent(3). Первая читает следующую запись группы из потока, инициализированного setgrent(3). Последняя читает следующую запись группы из stream.

Структура group определена в <grp.h> следующим образом:

```
struct group {

    char   *gr_name;        /* имя группы */

    char   *gr_passwd;      /* пароль группы */

    gid_t   gr_gid;         /* ID группы */

    char  **gr_mem;         /* массив, указателей

                               имён членов группы, оканчивающийся NULL */
};
```

Подробней о полях этой структуры смотрите в group(5).

Нереентерабельные версии возвращают указатель на статическое хранилище, в котором хранятся другие указатели на имя группы, пароль и список членов. Реентерабельные функции, описанные здесь, возвращают всю информацию в буферах, предоставленных вызывающим. Основным буфером является gbuf, в котором может храниться struct group. В дополнительном буфере buf размера buflen могут храниться дополнительные строки. Результат этих функций, прочитанная из потока struct group, сохраняется в предоставляемый буфер *gbuf, и указатель на эту struct group возвращается в *gbufp.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении эти функции возвращают 0 и *gbufp указывает на struct group. При ошибке возвращается значение ошибки и *gbufp равен NULL.

## ОШИБКИ
ENOENT

Больше записей нет.

ERANGE

Недостаточно места в буфере. Попробуйте ещё раз с большим буфером.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

getgrent_r()

Безвредность в нитях

MT-Unsafe race:grent locale

fgetgrent_r()

Безвредность в нитях

MT-Safe

В приведённой выше таблице grent в race:grent означает, что если в нескольких нитях программы одновременно используются функции setgrent(), getgrent(), endgrent() или getgrent_r(), то может возникнуть состязательность по данным.

## СООТВЕТСТВИЕ СТАНДАРТАМ
Эти функции являются расширениями GNU; они выполнены похожими на POSIX-версию функции getpwnam_r(3). В других системах используется прототип

```
struct group *getgrent_r(struct group *grp, char *buf,

                         int buflen);
```

или, лучше,

```
int getgrent_r(struct group *grp, char *buf, int buflen,

               FILE **gr_fp);
```

## ЗАМЕЧАНИЯ
Функция getgrent_r() не совсем реентерабельна, так как она использует общую позицию чтения в потоке с другими нитями.

## ПРИМЕР

```
#define _GNU_SOURCE
#include <grp.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFLEN 4096
int
main(void)
{

    struct group grp, *grpp;

    char buf[BUFLEN];

    int i;

    setgrent();

    while (1) {

        i = getgrent_r(&grp, buf, BUFLEN, &grpp);

        if (i)

            break;

        printf("%s (%d):", grpp->gr_name, grpp->gr_gid);

        for (i = 0; ; i++) {

            if (grpp->gr_mem[i] == NULL)

                break;

            printf(" %s", grpp->gr_mem[i]);

        }

        printf("\n");

    }

    endgrent();

    exit(EXIT_SUCCESS);
}
```

## СМОТРИТЕ ТАКЖЕ
fgetgrent(3), getgrent(3), getgrgid(3), getgrnam(3), putgrent(3), group(5)


getgrnam

title: getgrnam(3)

summary: возвращают запись файла групп

text:
# getgrnam(3)

## ИМЯ
getgrnam, getgrnam_r, getgrgid, getgrgid_r - возвращают запись файла групп

## ОБЗОР

```
#include <sys/types.h>
#include <grp.h>
```

```
struct group *getgrnam(const char *name);
```

```
struct group *getgrgid(gid_t gid);
```

```
int getgrnam_r(const char *name, struct group *grp,
          char *buf, size_t buflen, struct group **result);
```

```
int getgrgid_r(gid_t gid, struct group *grp,
          char *buf, size_t buflen, struct group **result);
```

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

getgrnam_r(), getgrgid_r():

_POSIX_C_SOURCE

|| /* версии glibc <= 2.19: */ _BSD_SOURCE || _SVID_SOURCE

## ОПИСАНИЕ
Функция getgrnam() возвращает указатель на структуру, содержащую разделённую на поля запись из базы данных групп (например, из локального файла групп /etc/group, NIS и LDAP), которая соответствует имени группы name.

Функция getgrgid() возвращает указатель на структуру, содержащую разделённую на поля запись из базы данных групп, которая соответствует идентификатору группы gid.

Структура group определена в <grp.h> следующим образом:

```
struct group {

    char   *gr_name;        /* имя группы */

    char   *gr_passwd;      /* пароль группы */

    gid_t   gr_gid;         /* ID группы */

    char  **gr_mem;         /* массив, указателей

                               имён членов группы, оканчивающийся NULL */
};
```

Подробней о полях этой структуры смотрите в group(5).

Функции getgrnam_r() и getgrgid_r() принимают ту же информацию что и getgrnam() и getgrgid(), но сохраняют полученную структуру group в пространство, указанное grp. Строковые поля членов структуры group сохраняются в буфере buf размера buflen. Указатель на результат (при успешном выполнении) или NULL (если записи отсутствуют или произошла ошибка) сохраняется в *result.

Вызов

sysconf(_SC_GETGR_R_SIZE_MAX)

возвращает или -1 без изменения errno или начальный предполагаемый размер buf (если этот размер мал, то вызов завершается ERANGE; в этом случае вызывающий может повторить вызов с большим буфером).

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Функции getgrnam() и getgrgid() возвращают указатель на структуру group или NULL, если подходящих записей не найдено или возникла ошибка. При ошибке errno устанавливается в соответствующее значение. Если нужно проверять переменную errno после вызова, то перед этим нужно присвоить ей нулевое значение.

Возвращаемое значение может указывать на статическую область и может быть перезаписано при последующих вызовах getgrent(3), getgrnam() или getgrgid() (не передавайте полученный указатель free(3)).

При успешном выполнении getgrnam_r() и getgrgid_r() возвращают ноль, и устанавливают *result в pwd. Если совпадений не найдено, то эти функции возвращают 0 и сохраняют NULL в *result. При ошибке возвращается её номер и в *result сохраняется NULL.

## ОШИБКИ
0 или ENOENT или ESRCH или EBADF или EPERM или …

Указанное значение name или gid не найдено.

EINTR

Поступил сигнал; смотрите signal(7).

EIO

Ошибка ввода-вывода.

EMFILE

Было достигнуто ограничение по количеству открытых файловых дескрипторов на процесс.

ENFILE

Достигнуто максимальное количество открытых файлов в системе.

ENOMEM

Недостаточно памяти для структуры group.

ERANGE

Недостаточно места в буфере.

## ФАЙЛЫ
/etc/group

локальный файл базы данных групп

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

getgrnam()

Безвредность в нитях

MT-Unsafe race:grnam locale

getgrgid()

Безвредность в нитях

MT-Unsafe race:grgid locale

getgrnam_r(), getgrgid_r()

Безвредность в нитях

MT-Safe locale

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.

## ЗАМЕЧАНИЯ
Описание «ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ», приведённое выше, взято из POSIX.1. В нём «не найдено» не считается ошибкой и поэтому не указано, каким может быть значение errno в этом случае. Но это делает невозможным определить тип ошибки. Из описание POSIX можно посчитать, что errno не должно измениться, если запись не найдена. Эксперименты в различных UNIX-подобных системах показывают, что в этой ситуации возвращается много разных значений: 0, ENOENT, EBADF, ESRCH, EWOULDBLOCK, EPERM и, возможно, другие.

## СМОТРИТЕ ТАКЖЕ
endgrent(3), fgetgrent(3), getgrent(3), getpwnam(3), setgrent(3), group(5)


getgrouplist

title: getgrouplist(3)

text:
# getgrouplist(3)

## ИМЯ
getgrouplist - возвращает список групп, в которые входит пользователь

## ОБЗОР
\#include <grp.h>

int getgrouplist(const char *user, gid_t group,

gid_t *groups, int *ngroups);

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

getgrouplist():

начиная с glibc 2.19:

_DEFAULT_SOURCE

в glibc 2.19 и старее:

_BSD_SOURCE

## ОПИСАНИЕ
Функция getgrouplist() просматривает базу данных групп (смотрите group(5)) для составления списка групп, в которые входит пользователь user. В возвращаемом массиве groups может быть до *ngroups групп.

Если в базе данных групп отсутствуют группы, определённые для user, то в список групп, возвращаемый getgrouplist(), включается group; обычно, это аргумент задаётся в виде ID группы из записи пароля user.

Аргумент ngroups является аргументом-результатом: при возврате в нём всегда содержится количество группы, найденных для user включая group; данное значение может быть больше, чем количество групп, хранящихся в groups.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Если количество групп, в которых user является членом, меньше или равно *ngroups, то возвращается значение *ngroups.

Если пользователь является членом более чем *ngroups групп, то getgrouplist() возвращает -1. В этом случае значение, возвращаемое в *ngroups, можно использовать для подстройки размера буфера, передаваемого в последующий вызов getgrouplist().

## ВЕРСИИ
Эта функция доступна в glibc с версии 2.2.4.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

getgrouplist()

Безвредность в нитях

MT-Safe locale

## СООТВЕТСТВИЕ СТАНДАРТАМ
Эта функция является нестандартной; она присутствует в большинстве BSD.

## ДЕФЕКТЫ
В glibc до версии 2.3.3 в реализации этой функции содержится ошибка переполнения буфера: она возвращает полный список групп для user в массиве groups даже когда количество групп превышает *ngroups.

## ПРИМЕР
Программа, показанная далее, печатает список групп для пользователя из первого аргумента командной строки. Во втором аргументе задаётся значение ngroups, передаваемое getgrouplist(). Вот примеры работы этой программы:

```
$ ./a.out cecilia 0
getgrouplist() вернула -1; ngroups = 3
$ ./a.out cecilia 3
ngroups = 3
16 (dialout)
33 (video)
100 (users)
```

### Исходный код программы

```
#include <stdio.h>
#include <stdlib.h>
#include <grp.h>
#include <pwd.h>
int
main(int argc, char *argv[])
{

    int j, ngroups;

    gid_t *groups;

    struct passwd *pw;

    struct group *gr;

    if (argc != 3) {

        fprintf(stderr, "Использование: %s <пользователь> <ngroups>\n", argv[0]);

        exit(EXIT_FAILURE);

    }

    ngroups = atoi(argv[2]);

    groups = malloc(ngroups * sizeof (gid_t));

    if (groups == NULL) {

        perror("malloc");

        exit(EXIT_FAILURE);

    }

    /* получаем структуру passwd (содержит ID первичной группы

       пользователя) */

    pw = getpwnam(argv[1]);

    if (pw == NULL) {

        perror("getpwnam");

        exit(EXIT_SUCCESS);

    }

    /* получаем список групп */

    if (getgrouplist(argv[1], pw->pw_gid, groups, &ngroups) == -1) {

        fprintf(stderr, "getgrouplist() вернула -1; ngroups = %d\n",

                ngroups);

        exit(EXIT_FAILURE);

    }

    /* печатаем список полученных групп вместе с именами групп */

    fprintf(stderr, "ngroups = %d\n", ngroups);

    for (j = 0; j < ngroups; j++) {

        printf("%d", groups[j]);

        gr = getgrgid(groups[j]);

        if (gr != NULL)

            printf(" (%s)", gr->gr_name);

        printf("\n");

    }

    exit(EXIT_SUCCESS);
}
```

## СМОТРИТЕ ТАКЖЕ
getgroups(2), setgroups(2), getgrent(3), group_member(3), group(5), passwd(5)


gethostbyname

title: gethostbyname(3)

summary: получение записи о сетевом узле

text:
# gethostbyname(3)

## ИМЯ
gethostbyname, gethostbyaddr, sethostent, gethostent, endhostent, h_errno, herror, hstrerror, gethostbyaddr_r, gethostbyname2, gethostbyname2_r, gethostbyname_r, gethostent_r - получение записи о сетевом узле

## ОБЗОР

```
#include <netdb.h>
extern int h_errno;
```

```
struct hostent *gethostbyname(const char *name);
#include <sys/socket.h>       /* для AF_INET */
struct hostent *gethostbyaddr(const void *addr,
                              socklen_t len, int type);
```

```
void sethostent(int stayopen);
```

```
void endhostent(void);
```

```
void herror(const char *s);
```

```
const char *hstrerror(int err);
```

```
/* расширение System V/POSIX */
struct hostent *gethostent(void);
```

```
/* расширения GNU */
struct hostent *gethostbyname2(const char *name, int af);
```

```
int gethostent_r(
        struct hostent *ret, char *buf, size_t buflen,
        struct hostent **result, int *h_errnop);
```

```
int gethostbyaddr_r(const void *addr, socklen_t len, int type,
        struct hostent *ret, char *buf, size_t buflen,
        struct hostent **result, int *h_errnop);
```

```
int gethostbyname_r(const char *name,
        struct hostent *ret, char *buf, size_t buflen,
        struct hostent **result, int *h_errnop);
```

```
int gethostbyname2_r(const char *name, int af,
        struct hostent *ret, char *buf, size_t buflen,
        struct hostent **result, int *h_errnop);
```

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

gethostbyname2(), gethostent_r(), gethostbyaddr_r(), gethostbyname_r(), gethostbyname2_r():

Начиная с glibc 2.19:

_DEFAULT_SOURCE

Версии glibc по 2.19 включительно:

_BSD_SOURCE || _SVID_SOURCE

herror(), hstrerror():

Начиная с glibc 2.19:

_DEFAULT_SOURCE

Версии glibc с 2.8 по 2.19:

_BSD_SOURCE || _SVID_SOURCE

До glibc 2.8:

ни одного

h_errno:

Начиная с glibc 2.19

_DEFAULT_SOURCE || _POSIX_C_SOURCE < 200809L

Версии glibc с 2.12 по 2.19:

_BSD_SOURCE || _SVID_SOURCE || _POSIX_C_SOURCE < 200809L

До glibc 2.12:

ни одного

## ОПИСАНИЕ
Функции gethostbyname*(), gethostbyaddr*(), herror() и hstrerror() являются устаревшими. Вместо них в приложениях следует использовать getaddrinfo(3), getnameinfo(3) и gai_strerror(3).

Функция gethostbyname() возвращает структуру типа hostent для узла name. Значением name может быть или имя узла, или адрес IPv4 в стандартной точечной записи (как в inet_addr(3)). Если name — адрес IPv4, то поиск не выполняется и gethostbyname() просто копирует name в поле h_name, а его эквивалент struct in_addr — в поле h_addr_list[0] возвращаемой структуры hostent Если name не оканчивается точкой и установлена переменная окружения HOSTALIASES, то name сначала ищется в файле псевдонимов, указанном в HOSTALIASES (формат файла описан в hostname(7)). Если name не оканчивается точкой, то поиск производится с текущем доменом и его предками.

Функция gethostbyaddr() возвращает структуру типа hostent для адреса узла addr длинной len и типом адреса type. Допустимые типы адресов — AF_INET и AF_INET6. Аргумент адреса узла — указатель на структуру с типом, зависящим от типа адреса, например для типа адреса AF_INET используется struct in_addr * (возможно, полученная из вызова inet_addr(3)).

Функция sethostent() задаёт (при stayopen равным истине (1)), что для опроса сервера имён должен использоваться подключённый сокет TCP и что соединение должно остаться открытым для последующих запросов. В противном случае для опроса сервера имён будут использоваться дейтаграммы UDP.

Функция endhostent() закрывает использованное для опросов сервера имён соединение TCP.

Функция herror() (устарела) печатает в stderr сообщение об ошибке в соответствии с текущим значением h_errno.

Функция hstrerror() (устарела) принимает номер ошибки (обычно, h_errno) и возвращает соответствующую строку с сообщением об ошибке.

Запросы доменного имени, выполняемые gethostbyname() и gethostbyaddr(), полагаются на настроенные источники диспетчера службы имён (nsswitch.conf(5)) или локальный сервер имён (named(8)). Действием по умолчанию является запрос к настроенным источникам диспетчера службы имён (nsswitch.conf(5)), при ошибке — к локальному серверу имён (named(8)).

### Историческая справка
Современным способом управления порядком поиска узлов является файл nsswitch.conf(5).

В glibc 2.4 и старее, ключевое слово order использовалось для управления порядком поиска узла в /etc/host.conf (host.conf(5)).

Структура hostent определена в <netdb.h> таким образом:

```
struct hostent {

    char  *h_name;            /* официальное имя узла */

    char **h_aliases;         /* список псевдонимов */

    int    h_addrtype;        /* тип адреса узла */

    int    h_length;          /* длина адреса */

    char **h_addr_list;       /* список адресов */
}
#define h_addr h_addr_list[0] /* для обратной совместимости */
```

Члены структуры hostent:

h_name

Официальное имя узла.

h_aliases

Массив альтернативных имён узла, заканчивается указателем null.

h_addrtype

Тип адреса; AF_INET или AF_INET6.

h_length

Длина адреса в байтах.

h_addr_list

Массив указателей сетевых адресов узла (в сетевом порядке байт), заканчивается указателем null.

h_addr

Первый адрес из h_addr_list, для обратной совместимости.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Функции gethostbyname() и gethostbyaddr() возвращают структуру hostent или указатель null при ошибке. При ошибке переменная h_errno содержит номер ошибки. Если получен не NULL, то возвращаемое значение может указывать на статические данные, смотрите замечание далее.

## ОШИБКИ
Переменная h_errno может содержать следующие значения:

HOST_NOT_FOUND

Заданный узел неизвестен.

NO_DATA

Запрашиваемое имя корректно, но не имеет IP-адреса. При другом типе запроса для этого домена сервер имён может вернуть ответ. Синонимом NO_DATA является константа NO_ADDRESS.

NO_RECOVERY

Произошла неисправимая ошибка сервера имён.

TRY_AGAIN

Произошла временная ошибка у авторитативного сервера имён. Попробуйте позже.

## ФАЙЛЫ
/etc/host.conf

файл с настройками резолвера

/etc/hosts

файл базы данных узлов

/etc/nsswitch.conf

настройки диспетчера службы имён

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

gethostbyname()

Безвредность в нитях

MT-Unsafe race:hostbyname env locale

gethostbyaddr()

Безвредность в нитях

MT-Unsafe race:hostbyaddr env locale

sethostent(), endhostent(), gethostent_r()

Безвредность в нитях

MT-Unsafe race:hostent env locale

herror(), hstrerror()

Безвредность в нитях

MT-Safe

gethostent()

Безвредность в нитях

MT-Unsafe race:hostent race:hostentbuf env locale

gethostbyname2()

Безвредность в нитях

MT-Unsafe race:hostbyname2 env locale

gethostbyaddr_r(), gethostbyname_r(), gethostbyname2_r()

Безвредность в нитях

MT-Safe env locale

В приведённой выше таблице hostent в race:hostent означает, что если в нескольких нитях программы одновременно используются функции sethostent(), gethostent(), gethostent_r() или endhostent(), то может возникнуть состязательность по данным.

## СООТВЕТСТВИЕ СТАНДАРТАМ
В POSIX.1-2001 определены gethostbyname(), gethostbyaddr(), sethostent(), endhostent(), gethostent() и h_errno; функции gethostbyname(), gethostbyaddr() и h_errno помечены как устаревшие. В POSIX.1-2008 удалены определения gethostbyname(), gethostbyaddr() и h_errno; вместо них рекомендуется использовать getaddrinfo(3) и getnameinfo(3).

## ЗАМЕЧАНИЯ
Функции gethostbyname() и gethostbyaddr() могут возвращать указатели на статические данные, которые могут быть перезаписаны при последующих вызовах. Копирования struct hostent недостаточно, так как она содержит указатели; требуется глубокое копирование.

В первой реализации BSD аргумент len у gethostbyname() имел тип int. Стандарт SUSv2 содержит ошибку и объявляет аргумент len у gethostbyaddr() с типом size_t (это неправильно, так как он должен быть int, а не size_t. В POSIX.1-2001 указанный тип — socklen_t, который подходит). Смотрите также accept(2).

У прототипа BSD gethostbyaddr() первый аргумент имеет тип const char *.

### Расширение System V/POSIX
В POSIX требуется вызов gethostent(), который должен возвращать следующий элемент из базы данных узлов. При использовании DNS/BIND это не имеет смысла, но допустимо, если база данных узлов — файл, который можно читать строку за строкой. На многих системах процедура с таким именем выполняет чтение из файла /etc/hosts. Она может быть доступна только когда библиотека собрана без поддержки DNS. Версия glibc игнорирует записи ipv6. Эта функция не реентерабельна; в glibc добавлена реентерабельная версия gethostent_r().

### Расширения GNU
В glibc2 также имеется gethostbyname2(), работающая подобно gethostbyname(), но позволяющая задать адресное семейство, которому должен принадлежать адрес.

В glibc2 также имеются реентерабельные версии gethostent_r(), gethostbyaddr_r(), gethostbyname_r() и gethostbyname2_r(). Вызывающий передаёт структуру hostent ret, которая будет заполнена, и временный рабочий буфер buf размера buflen. После вызова result будет указывать на результат. В случае ошибки или при отсутствии записи result будет NULL. При успешном выполнении функция возвращает 0 и ненулевой номер ошибки при сбое. Если buf слишком мал, то кроме ошибок, возвращаемых нереентерабельными версиями этих функций, возвращается ERANGE, и вызов нужно повторить с большим буфером. Глобальная переменная h_errno не изменяется, но адрес переменной, в которой хранятся номера ошибок, передаётся в h_errnop.

## ДЕФЕКТЫ
Функция gethostbyname() не работает с частями строки адреса IPv4 в точечном формате, если они записаны шестнадцатеричными числами.

## СМОТРИТЕ ТАКЖЕ
getaddrinfo(3), getnameinfo(3), inet(3), inet_ntop(3), inet_pton(3), resolver(3), hosts(5), nsswitch.conf(5), hostname(7), named(8)


gethostid

title: gethostid(3)

text:
# gethostid(3)

## ИМЯ
gethostid, sethostid - возвращает или назначает уникальный идентификатор текущего узла

## ОБЗОР
\#include <unistd.h>

long gethostid(void);

int sethostid(long hostid);

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

gethostid():

_BSD_SOURCE || _XOPEN_SOURCE >= 500

sethostid():

```
    начиная с glibc 2.21:

        _DEFAULT_SOURCE

    в glibc 2.19 и 2.20:

        _DEFAULT_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE < 500)

    до glibc 2.19, включительно:

        _BSD_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE < 500)
```

## ОПИСАНИЕ
Функции gethostid() и sethostid(), соответственно, возвращают и устанавливают уникальный 32-битный идентификатор текущей машины. Данный 32-битный идентификатор считается уникальным среди всех существующих систем UNIX. Обычно это напоминает Интернет-адрес локальной машины, возвращаемый gethostbyname(3), и поэтому, как правило, его не нужно изменять.

Только суперпользователь может вызывать sethostid().

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Функция gethostid() возвращает 32-битный идентификатор текущего узла, установленный sethostid().

При успешном выполнении sethostid() возвращает 0; при ошибке — -1, а в errno задаётся код ошибки.

## ОШИБКИ
Вызов sethostid() может завершиться со следующими ошибками:

EACCES

Вызывающий не имеет прав на запись в файл, используемый для хранения ID узла.

EPERM

Эффективный идентификатор пользователя или группы вызывающего процесса не совпадает с его соответствующим реальным идентификатором.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

gethostid()

Безвредность в нитях

MT-Safe hostid env locale

sethostid()

Безвредность в нитях

MT-Unsafe const:hostid

## СООТВЕТСТВИЕ СТАНДАРТАМ
42BSD; эти функции удалены в 4.4BSD. В SVr4 содержится gethostid(), но отсутствует sethostid().

В POSIX.1-2001 и POSIX.1-2008 определена gethostid(), но отсутствует sethostid().

## ЗАМЕЧАНИЯ
В реализации glibc hostid сохраняет значение в файле /etc/hostid (в glibc до версии 2.2 используется файл /var/adm/hostid).

В реализации glibc, если gethostid() не может открыть файл, содержащий ID узла, она получает имя узла с помощью gethostname(2), передаёт это имя gethostbyname_r(3) для получения адреса IPv4 узла, и возвращает значение, получаемое преобразованием битов полученного адреса IPv4 (такое значение может быть не уникально).

## ДЕФЕКТЫ
Невозможно достоверно сказать, что идентификатор является глобально уникальным.

## СМОТРИТЕ ТАКЖЕ
hostid(1), gethostbyname(3)


getifaddrs

title: getifaddrs(3)

summary: возвращают адреса интерфейса

text:
# getifaddrs(3)

## ИМЯ
getifaddrs, freeifaddrs - возвращают адреса интерфейса

## ОБЗОР

```
#include <sys/types.h>
#include <ifaddrs.h>
```

```
int getifaddrs(struct ifaddrs **ifap);
```

```
void freeifaddrs(struct ifaddrs *ifa);
```

## ОПИСАНИЕ
Функция getifaddrs() создаёт связный список структур, описывающих сетевые интерфейсы локальной системы, и сохраняет адрес первого элемента списка в *ifap. Список состоит из структур ifaddrs:

```
struct ifaddrs {

    struct ifaddrs  *ifa_next;    /* след. элемент в списке */

    char            *ifa_name;    /* имя интерфейса */

    unsigned int     ifa_flags;   /* флаги из SIOCGIFFLAGS */

    struct sockaddr *ifa_addr;    /* адрес интерфейса */

    struct sockaddr *ifa_netmask; /* сетевая маска интерфейса */

    union {

        struct sockaddr *ifu_broadaddr;

                         /* широковещательный адрес интерфейса */

        struct sockaddr *ifu_dstaddr;

                         /* адрес назначения точка-точка */

    } ifa_ifu;
#define              ifa_broadaddr ifa_ifu.ifu_broadaddr
#define              ifa_dstaddr   ifa_ifu.ifu_dstaddr

    void            *ifa_data;    /* спец. данные для адреса */
};
```

В поле ifa_next содержится указатель на следующую структуру в списке или NULL, если это последний элемент в списке.

Поле ifa_name указывает на имя интерфейса (заканчивающееся null).

В поле ifa_flags содержатся флаги интерфейса, полученные операцией SIOCGIFFLAGS ioctl(2) (список флагов приведён в netdevice(7)).

Поле ifa_addr указывает на структуру, содержащую адрес интерфейса (для определения формата структуры адреса обратитесь к подполю sa_family). Это поле может содержать указатель null.

Поле ifa_netmask указывает на структуру, содержащую маску сети для ifa_addr (если она используется в адресном семействе). Это поле может содержать указатель null.

В зависимости от наличия флага IFF_BROADCAST или IFF_POINTOPOINT в ifa_flags (может быть установлен какой-то один), в ifa_broadaddr будет содержаться широковещательный адрес ifa_addr (если он используется в адресном семействе) или ifa_dstaddr будет содержать адрес назначения интерфейса типа точка-точка.

Поле ifa_data указывает на буфер, содержащий данные, присущие адресному семейству; это поле может быть равно NULL, если данных для этого интерфейса нет.

Память под структуру данных, возвращаемая getifaddrs(), выделяется динамически и должна освобождаться с помощью freeifaddrs(), когда больше не нужна.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении getifaddrs() возвращается 0. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.

## ОШИБКИ
Функция getifaddrs() может завершиться с ошибками и назначить переменной errno значения, перечисленные в socket(2), bind(2), getsockname(2), recvmsg(2), sendto(2), malloc(3) или realloc(3).

## ВЕРСИИ
Впервые функция getifaddrs() появилась в glibc 2.3, но до glibc 2.3.3 реализация поддерживала только интерфейсы с адресами IPv4; поддержка IPv6 добавлена в glibc 2.3.3. Поддержка семейств адресов не IPv4 доступна только в ядрах, поддерживающих netlink.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

getifaddrs(), freeifaddrs()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
Нет в POSIX.1. Данная функция впервые появилась в BSDi и существует в системах BSD, но со слегка другой семантикой — возвращается одна запись на интерфейс, а не на адрес. Это означает, что ifa_addr и другие поля могут быть равны NULL, если интерфейс не имеет адресов, и адрес канального уровня не возвращается, если интерфейсу назначен IP-адрес. Также в разных системах различается способ выбора между ifa_broadaddr и ifa_dstaddr.

## ЗАМЕЧАНИЯ
Адреса, возвращаемые в Linux, обычно, являются адресами IPv4 и IPv6, назначенными интерфейсу, но также есть один адрес AF_PACKET на интерфейс, содержащий канальные настройки интерфейса и его физический уровень. В этом случае поле ifa_data может содержать указатель на struct rtnl_link_stats, определённую в <linux/if_link.h> (в Linux 2.4 и ранее — struct net_device_stats, определена в <linux/netdevice.h>), которая содержит различные атрибуты интерфейса и статистику.

## ПРИМЕР
В программе, показанной далее, демонстрируется использование getifaddrs(), freeifaddrs(), и getnameinfo(3). Вот результат запуска этой программы:

```
$ ./a.out
lo       AF_PACKET (17)

                tx_packets =        524; rx_packets =        524

                tx_bytes   =      38788; rx_bytes   =      38788
wlp3s0   AF_PACKET (17)

                tx_packets =     108391; rx_packets =     130245

                tx_bytes   =   30420659; rx_bytes   =   94230014
em1      AF_PACKET (17)

                tx_packets =          0; rx_packets =          0

                tx_bytes   =          0; rx_bytes   =          0
lo       AF_INET (2)

                адрес: <127.0.0.1>
wlp3s0   AF_INET (2)

                адрес: <192.168.235.137>
lo       AF_INET6 (10)

                адрес: <::1>
wlp3s0   AF_INET6 (10)

                адрес: <fe80::7ee9:d3ff:fef5:1a91%wlp3s0>
```

### Исходный код программы

```
#define _GNU_SOURCE     /* чтобы получить NI_MAXSERV и NI_MAXHOST */
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/if_link.h>
int main(int argc, char *argv[])
{

    struct ifaddrs *ifaddr, *ifa;

    int family, s, n;

    char host[NI_MAXHOST];

    if (getifaddrs(&ifaddr) == -1) {

        perror("getifaddrs");

        exit(EXIT_FAILURE);

    }

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

       освободить список позже */

    for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {

        if (ifa->ifa_addr == NULL)

            continue;

        family = ifa->ifa_addr->sa_family;

        /* вывод имени интерфейса и семейства (включая символический

           вид для общих семейств) */

        printf("%-8s %s (%d)\n",

               ifa->ifa_name,

               (family == AF_PACKET) ? "AF_PACKET" :

               (family == AF_INET) ? "AF_INET" :

               (family == AF_INET6) ? "AF_INET6" : "???",

               family);

        /* для адресов интерфейса AF_INET* показываем адрес */

        if (family == AF_INET || family == AF_INET6) {

            s = getnameinfo(ifa->ifa_addr,

                    (family == AF_INET) ? sizeof(struct sockaddr_in) :

                                          sizeof(struct sockaddr_in6),

                    host, NI_MAXHOST,

                    NULL, 0, NI_NUMERICHOST);

            if (s != 0) {

                printf("ошибка getnameinfo(): %s\n", gai_strerror(s));

                exit(EXIT_FAILURE);

            }

            printf("\t\tадрес: <%s>\n", host);

        } else if (family == AF_PACKET && ifa->ifa_data != NULL) {

            struct rtnl_link_stats *stats = ifa->ifa_data;

            printf("\t\ttx_packets = %10u; rx_packets = %10u\n"

                   "\t\ttx_bytes   = %10u; rx_bytes   = %10u\n",

                   stats->tx_packets, stats->rx_packets,

                   stats->tx_bytes, stats->rx_bytes);

        }

    }

    freeifaddrs(ifaddr);

    exit(EXIT_SUCCESS);
}
```

## СМОТРИТЕ ТАКЖЕ
bind(2), getsockname(2), socket(2), packet(7), ifconfig(8)