GETSERVENT_R(3)

ИМЯ
getservent_r, getservbyname_r, getservbyport_r - возвращает запись о службе (реентерабельные версии)

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

int getservent_r(struct servent *result_buf, char *buf,
                size_t buflen, struct servent **result);

int getservbyname_r(const char *name, const char *proto,
                struct servent *result_buf, char *buf,
                size_t buflen, struct servent **result);

int getservbyport_r(int port, const char *proto,
                struct servent *result_buf, char *buf,
                size_t buflen, struct servent **result);

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

getservent_r(), getservbyname_r(), getservbyport_r():
    начиная с glibc 2.19:
        _DEFAULT_SOURCE
    в glibc 2.19 и старее:
        _BSD_SOURCE || _SVID_SOURCE

ОПИСАНИЕ
Функции getservent_r(), getservbyname_r() и getservbyport_r() являются реентерабельными эквивалентами getservent(3), getservbyname(3) и getservbyport(3), соответственно. Они отличаются способом возврата структуры servent и списком параметров и типом возвращаемого значения. В этой справочной странице описаны только различия с нереентерабельными функциями.

Вместо возврата указателя на статически выделенную структуру servent в качестве результата эти функции копируют структуру в расположение, указанное result_buf.

Массив buf используется для хранения строковых полей из возвращаемой структуры servent (нереентерабельные функции выделяют эти строки из статического хранилища). Размер данного массива задаётся в buflen. Если buf слишком мал, то вызов завершается с ошибкой ERANGE, вызывающий должен его повторить с большим буфером (для большинства приложений должно быть достаточно буфера длиной 1024 байт).

Если вызов получил запись о службе, то *result указывает на result_buf; в противном случае *result устанавливается в NULL.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении эти функции возвращают 0. При ошибке возвращается одно из положительных значений ошибок.

При ошибке, отсутствии записи (getservbyname_r(), getservbyport_r()) или конце данных (getservent_r()) значение result равно NULL.

ОШИБКИ

ENOENT
    (getservent_r()) Больше нет записей в базе данных.

ERANGE
    Размер buf слишком мал. Попробуйте ещё раз с большим буфером (и увеличенным значением buflen).

АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).
Интерфейс | Атрибут | Значение
getservent_r(), getservbyname_r(), getservbyport_r() | Безвредность в нитях | MT-Safe locale

СООТВЕТСТВИЕ СТАНДАРТАМ
Эти функции являются расширениями GNU. Функции с похожими именами есть и в других системах, хотя и с другим набором параметров.

ПРИМЕР
Программа, представленная ниже, использует getservbyport_r() для получения записи о службе для заданного порта и протокола, указанных в командной строке. Если задан и третий параметр (целое), то он используется как начальное значение buflen; если getservbyport_r() завершается с ошибкой ERANGE, то программа повторяет попытки с большими значениями буфера. Пара примеров работы в сеансовой оболочке:

    $ ./a.out 7 tcp 1
    ERANGE! Повтор с большим буфером
    getservbyport_r() returned: 0 (success)  (buflen=87)
    s_name=echo; s_proto=tcp; s_port=7; aliases=
    $ ./a.out 77777 tcp
    getservbyport_r() returned: 0 (success)  (buflen=1024)
    Ошибка вызова/запись не найдена

  Исходный код программы
    #define _GNU_SOURCE
    #include <ctype.h>
    #include <netdb.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #define MAX_BUF 10000
    int
    main(int argc, char *argv[])
    {
        int buflen, erange_cnt, port, s;
        struct servent result_buf;
        struct servent *result;
        char buf[MAX_BUF];
        char *protop;
        char **p;
        if (argc < 3) {
            printf("Использование: %s ном-порта имя-прото [длина-буф]\n", argv[0]);
            exit(EXIT_FAILURE);
        }
        port = htons(atoi(argv[1]));
        protop = (strcmp(argv[2], "null") == 0 ||
                  strcmp(argv[2], "NULL") == 0) ?  NULL : argv[2];
        buflen = 1024;
        if (argc > 3)
            buflen = atoi(argv[3]);
        if (buflen > MAX_BUF) {
            printf("Превышен размер буфера (%d)\n", MAX_BUF);
            exit(EXIT_FAILURE);
        }
        erange_cnt = 0;
        do {
            s = getservbyport_r(port, protop, &result_buf,
                         buf, buflen, &result);
            if (s == ERANGE) {
                if (erange_cnt == 0)
                    printf("ERANGE! Повтор с большим буфером\n");
                erange_cnt++;
                /* Увеличиваем по байту за раз для того, чтобы мы могли
                   точно узнать какой размер буфера требуется */
                buflen++;
                if (buflen > MAX_BUF) {
                    printf("Превышен размер буфера (%d)\n", MAX_BUF);
                    exit(EXIT_FAILURE);
                }
            }
        } while (s == ERANGE);
        printf("getservbyport_r() returned: %s  (buflen=%d)\n",
                (s == 0) ? "0 (success)" : (s == ENOENT) ? "ENOENT" :
                strerror(s), buflen);
        if (s != 0 || result == NULL) {
            printf("Ошибка вызова/запись не найдена\n");
            exit(EXIT_FAILURE);
        }
        printf("s_name=%s; s_proto=%s; s_port=%d; aliases=",
                    result_buf.s_name, result_buf.s_proto,
                    ntohs(result_buf.s_port));
        for (p = result_buf.s_aliases; *p != NULL; p++)
            printf("%s ", *p);
        printf("\n");
        exit(EXIT_SUCCESS);
    }

СМОТРИТЕ ТАКЖЕ
getservent(3), services(5)