GETSERVENT_R - Linux手册页

时间:2019-08-20 18:00:32  来源:igfitidea点击:

Linux程序员手册 第3部分
更新日期: 2020-06-09

名称

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);

Feature Test Macro Requirements for glibc (see
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)的可重入等效项。它们的不同之处在于返回servant结构的方式以及调用签名和返回值的函数。本手册页仅介绍与不可重入功能的区别。

这些函数没有将指向静态分配的服务端结构的指针作为函数结果返回,而是将结构复制到result_buf指向的位置。

buf数组用于存储返回的servant结构所指向的字符串字段。 (nonreentrant函数在静态存储中分配这些字符串。)此数组的大小在buflen中指定。如果buf太小,则调用将失败,并显示错误ERANGE,并且调用方必须使用更大的缓冲区再次尝试。 (对于大多数应用程序,长度为1024字节的缓冲区应该足够了。)

如果函数调用成功获取服务记录,则将* result设置为指向result_buf;否则,* result设置为NULL。

返回值

成功时,这些函数返回0。错误时,它们返回错误中列出的正错误号之一。

错误时,未找到记录(getservbyname_r(),getservbyport_r())或输入结束(getservent_r())结果设置为NULL。

错误说明

ENOENT
(getservent_r())数据库中没有更多记录。
ERANGE
buf太小。使用更大的缓冲区(并增加buflen)再试一次。

属性

有关本节中使用的术语的说明,请参见attribute(7)。

InterfaceAttributeValue
getservent_r(),getservbyname_r(),getservbyport_r()Thread safetyMT-Safe locale

遵循规范

这些功能是GNU扩展。具有相同名称的功能在其他一些系统上也存在,尽管通常具有不同的调用签名。

示例

下面的程序使用getservbyport_r()来检索在其第一个命令行参数中命名的端口和协议的服务记录。如果提供了第三个(整数)命令行参数,它将用作buflen的初始值;否则,它将用作buflen的初始值。如果getservbyport_r()失败并显示错误ERANGE,则程序将使用更大的缓冲区重试。以下shell会话显示了几个示例运行:

$ ./a.out 7 tcp 1
ERANGE! Retrying with larger buffer
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)
Call failed/record not found

Program source

#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("Usage: %s port-num proto-name [buflen]\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("Exceeded buffer limit (%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! Retrying with larger buffer\n");
            erange_cnt++;

            /* Increment a byte at a time so we can see exactly
               what size buffer was required */

            buflen++;

            if (buflen > MAX_BUF) {
                printf("Exceeded buffer limit (%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("Call failed/record not found\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),服务(5)

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/