---
name: "getservent_r"
section: "3"
platform: "linux"
package: "man-pages"
version: "6.19-1"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/getservent_r"
---

# getservent\_r(3)

get service entry (reentrant)

## NAME

getservent\_r, getservbyname\_r, getservbyport\_r - get service entry (reentrant)

## LIBRARY

Standard C library (*libc*, *-lc*)

## SYNOPSIS

```
#include <netdb.h>
```

**int getservent\_r(**size\_t size;                  **struct servent \*restrict** *result\_buf***,**                  **char** *buf***\[restrict** *size***\], size\_t** *size***,**                  **struct servent \*\*restrict** *result***);** **int getservbyname\_r(**size\_t size;                  **const char \*restrict** *name***,**                  **const char \*restrict** *proto***,**                  **struct servent \*restrict** *result\_buf***,**                  **char** *buf***\[restrict** *size***\], size\_t** *size***,**                  **struct servent \*\*restrict** *result***);** **int getservbyport\_r(**size\_t size;                  **int** *port***,**                  **const char \*restrict** *proto***,**                  **struct servent \*restrict** *result\_buf***,**                  **char** *buf***\[restrict** *size***\], size\_t** *size***,**                  **struct servent \*\*restrict** *result***);**

Feature Test Macro Requirements for glibc (see [**feature\_test\_macros**(7)](/feature_test_macros/7.md)):

**getservent\_r**(), **getservbyname\_r**(), **getservbyport\_r**():

```
    Since glibc 2.19:
        _DEFAULT_SOURCE
    glibc 2.19 and earlier:
        _BSD_SOURCE || _SVID_SOURCE
```

## DESCRIPTION

The **getservent\_r**(), **getservbyname\_r**(), and **getservbyport\_r**() functions are the reentrant equivalents of, respectively, [**getservent**(3)](/getservent/3.md), [**getservbyname**(3)](/getservbyname/3.md), and [**getservbyport**(3)](/getservbyport/3.md). They differ in the way that the *servent* structure is returned, and in the function calling signature and return value. This manual page describes just the differences from the nonreentrant functions.

Instead of returning a pointer to a statically allocated *servent* structure as the function result, these functions copy the structure into the location pointed to by *result\_buf*.

The *buf* array is used to store the string fields pointed to by the returned *servent* structure. (The nonreentrant functions allocate these strings in static storage.) The size of this array is specified in *size*. If *buf* is too small, the call fails with the error **ERANGE**, and the caller must try again with a larger buffer. (A buffer of size 1024 bytes should be sufficient for most applications.)

If the function call successfully obtains a service record, then *\*result* is set pointing to *result\_buf*; otherwise, *\*result* is set to NULL.

## RETURN VALUE

On success, these functions return 0. On error, they return one of the positive error numbers listed in errors.

On error, record not found (**getservbyname\_r**(), **getservbyport\_r**()), or end of input (**getservent\_r**()) *result* is set to NULL.

## ERRORS

- **ENOENT**

  (**getservent\_r**()) No more records in database.

- **ERANGE**

  *buf* is too small. Try again with a larger buffer (and increased *size*).

## ATTRIBUTES

For an explanation of the terms used in this section, see [**attributes**(7)](/attributes/7.md).

| | | |
| --- | --- | --- |
| **Interface** | **Attribute** | **Value** |
| **getservent\_r**(), **getservbyname\_r**(), **getservbyport\_r**() | Thread safety | MT-Safe locale |

## VERSIONS

Functions with similar names exist on some other systems, though typically with different calling signatures.

## STANDARDS

GNU.

## EXAMPLES

The program below uses **getservbyport\_r**() to retrieve the service record for the port and protocol named in its first command-line argument. If a third (integer) command-line argument is supplied, it is used as the initial value for *size*; if **getservbyport\_r**() fails with the error **ERANGE**, the program retries with larger buffer sizes. The following shell session shows a couple of sample runs:

```
$ ./a.out 7 tcp 1
ERANGE! Retrying with larger buffer
getservbyport_r() returned: 0 (success)  (size=87)
s_name=echo; s_proto=tcp; s_port=7; aliases=
$ ./a.out 77777 tcp
getservbyport_r() returned: 0 (success)  (size=1024)
Call failed/record not found
```

### Program source

```
#define _GNU_SOURCE
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_BUF 10000
#define streq(...)  (strcmp(__VA_ARGS__) == 0)
int
main(int argc, char *argv[])
{
    int size, erange_cnt, port, s;
    struct servent result_buf;
    struct servent *result;
    char buf[MAX_BUF];
    char *protop;
    if (argc < 3) {
        printf("Usage: %s port-num proto-name [size]\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    port = htons(atoi(argv[1]));
    protop = (streq(argv[2], "null") ||
              streq(argv[2], "NULL")) ?  NULL : argv[2];
    size = 1024;
    if (argc > 3)
        size = atoi(argv[3]);
    if (size > 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, size, &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.  */
            size++;
            if (size > MAX_BUF) {
                printf("Exceeded buffer limit (%d)\n", MAX_BUF);
                exit(EXIT_FAILURE);
            }
        }
    } while (s == ERANGE);
    printf("getservbyport_r() returned: %s  (size=%d)\n",
           (s == 0) ? "0 (success)" : (s == ENOENT) ? "ENOENT" :
           strerror(s), size);
    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 (char **p = result_buf.s_aliases; *p != NULL; p++)
        printf("%s ", *p);
    printf("\n");
    exit(EXIT_SUCCESS);
}
```

## SEE ALSO

[**getservent**(3)](/getservent/3.md), [**services**(5)](/services/5.md)
