getservent_r - возвращает запись о службе
getservent_r(3)
возвращает запись о службе
Other Alias
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():
_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);
}