Blame man3/getaddrinfo_a.3

Packit 7cfc04
.\" Copyright (c) 2009 Petr Baudis <pasky@suse.cz>
Packit 7cfc04
.\" and clean-ups and additions (C) Copyright 2010 Michael Kerrisk
Packit 7cfc04
.\"                                 <mtk.manpages@gmail.com>
Packit 7cfc04
.\"
Packit 7cfc04
.\" %%%LICENSE_START(VERBATIM)
Packit 7cfc04
.\" Permission is granted to make and distribute verbatim copies of this
Packit 7cfc04
.\" manual provided the copyright notice and this permission notice are
Packit 7cfc04
.\" preserved on all copies.
Packit 7cfc04
.\"
Packit 7cfc04
.\" Permission is granted to copy and distribute modified versions of this
Packit 7cfc04
.\" manual under the conditions for verbatim copying, provided that the
Packit 7cfc04
.\" entire resulting derived work is distributed under the terms of a
Packit 7cfc04
.\" permission notice identical to this one.
Packit 7cfc04
.\"
Packit 7cfc04
.\" Since the Linux kernel and libraries are constantly changing, this
Packit 7cfc04
.\" manual page may be incorrect or out-of-date.  The author(s) assume no
Packit 7cfc04
.\" responsibility for errors or omissions, or for damages resulting from
Packit 7cfc04
.\" the use of the information contained herein.  The author(s) may not
Packit 7cfc04
.\" have taken the same level of care in the production of this manual,
Packit 7cfc04
.\" which is licensed free of charge, as they might when working
Packit 7cfc04
.\" professionally.
Packit 7cfc04
.\"
Packit 7cfc04
.\" Formatted or processed versions of this manual, if unaccompanied by
Packit 7cfc04
.\" the source, must acknowledge the copyright and authors of this work.
Packit 7cfc04
.\" %%%LICENSE_END
Packit 7cfc04
.\"
Packit 7cfc04
.\" References: http://people.redhat.com/drepper/asynchnl.pdf,
Packit 7cfc04
.\"     http://www.imperialviolet.org/2005/06/01/asynchronous-dns-lookups-with-glibc.html
Packit 7cfc04
.\"
Packit 7cfc04
.TH GETADDRINFO_A 3 2017-09-15 "GNU" "Linux Programmer's Manual"
Packit 7cfc04
.SH NAME
Packit 7cfc04
getaddrinfo_a, gai_suspend, gai_error, gai_cancel \- asynchronous
Packit 7cfc04
network address and service translation
Packit 7cfc04
.SH SYNOPSIS
Packit 7cfc04
.nf
Packit 7cfc04
.BR "#define _GNU_SOURCE" "         /* See feature_test_macros(7) */"
Packit 7cfc04
.B #include <netdb.h>
Packit 7cfc04
.PP
Packit 7cfc04
.BI "int getaddrinfo_a(int " "mode" ", struct gaicb *" "list[]" ,
Packit 7cfc04
.BI "                int " "nitems" ", struct sigevent *" "sevp" );
Packit 7cfc04
.PP
Packit 7cfc04
.BI "int gai_suspend(const struct gaicb * const " "list[]" ", int " "nitems" ,
Packit 7cfc04
.BI "                const struct timespec *" "timeout" );
Packit 7cfc04
.PP
Packit 7cfc04
.BI "int gai_error(struct gaicb *" "req" );
Packit 7cfc04
.PP
Packit 7cfc04
.BI "int gai_cancel(struct gaicb *" "req" );
Packit 7cfc04
.PP
Packit 7cfc04
Link with \fI\-lanl\fP.
Packit 7cfc04
.fi
Packit 7cfc04
.SH DESCRIPTION
Packit 7cfc04
The
Packit 7cfc04
.BR getaddrinfo_a ()
Packit 7cfc04
function performs the same task as
Packit 7cfc04
.BR getaddrinfo (3),
Packit 7cfc04
but allows multiple name look-ups to be performed asynchronously,
Packit 7cfc04
with optional notification on completion of look-up operations.
Packit 7cfc04
.PP
Packit 7cfc04
The
Packit 7cfc04
.I mode
Packit 7cfc04
argument has one of the following values:
Packit 7cfc04
.TP
Packit 7cfc04
.B GAI_WAIT
Packit 7cfc04
Perform the look-ups synchronously.
Packit 7cfc04
The call blocks until the look-ups have completed.
Packit 7cfc04
.TP
Packit 7cfc04
.B GAI_NOWAIT
Packit 7cfc04
Perform the look-ups asynchronously.
Packit 7cfc04
The call returns immediately,
Packit 7cfc04
and the requests are resolved in the background.
Packit 7cfc04
See the discussion of the
Packit 7cfc04
.I sevp
Packit 7cfc04
argument below.
Packit 7cfc04
.PP
Packit 7cfc04
The array
Packit 7cfc04
.I list
Packit 7cfc04
specifies the look-up requests to process.
Packit 7cfc04
The
Packit 7cfc04
.I nitems
Packit 7cfc04
argument specifies the number of elements in
Packit 7cfc04
.IR list .
Packit 7cfc04
The requested look-up operations are started in parallel.
Packit 7cfc04
NULL elements in
Packit 7cfc04
.I list
Packit 7cfc04
are ignored.
Packit 7cfc04
Each request is described by a
Packit 7cfc04
.I gaicb
Packit 7cfc04
structure, defined as follows:
Packit 7cfc04
.PP
Packit 7cfc04
.in +4n
Packit 7cfc04
.EX
Packit 7cfc04
struct gaicb {
Packit 7cfc04
    const char            *ar_name;
Packit 7cfc04
    const char            *ar_service;
Packit 7cfc04
    const struct addrinfo *ar_request;
Packit 7cfc04
    struct addrinfo       *ar_result;
Packit 7cfc04
};
Packit 7cfc04
.EE
Packit 7cfc04
.in
Packit 7cfc04
.PP
Packit 7cfc04
The elements of this structure correspond to the arguments of
Packit 7cfc04
.BR getaddrinfo (3).
Packit 7cfc04
Thus,
Packit 7cfc04
.I ar_name
Packit 7cfc04
corresponds to the
Packit 7cfc04
.I node
Packit 7cfc04
argument and
Packit 7cfc04
.I ar_service
Packit 7cfc04
to the
Packit 7cfc04
.I service
Packit 7cfc04
argument, identifying an Internet host and a service.
Packit 7cfc04
The
Packit 7cfc04
.I ar_request
Packit 7cfc04
element corresponds to the
Packit 7cfc04
.I hints
Packit 7cfc04
argument, specifying the criteria for selecting
Packit 7cfc04
the returned socket address structures.
Packit 7cfc04
Finally,
Packit 7cfc04
.I ar_result
Packit 7cfc04
corresponds to the
Packit 7cfc04
.I res
Packit 7cfc04
argument; you do not need to initialize this element,
Packit 7cfc04
it will be automatically set when the request
Packit 7cfc04
is resolved.
Packit 7cfc04
The
Packit 7cfc04
.I addrinfo
Packit 7cfc04
structure referenced by the last two elements is described in
Packit 7cfc04
.BR getaddrinfo (3).
Packit 7cfc04
.PP
Packit 7cfc04
When
Packit 7cfc04
.I mode
Packit 7cfc04
is specified as
Packit 7cfc04
.BR GAI_NOWAIT ,
Packit 7cfc04
notifications about resolved requests
Packit 7cfc04
can be obtained by employing the
Packit 7cfc04
.I sigevent
Packit 7cfc04
structure pointed to by the
Packit 7cfc04
.I sevp
Packit 7cfc04
argument.
Packit 7cfc04
For the definition and general details of this structure, see
Packit 7cfc04
.BR sigevent (7).
Packit 7cfc04
The
Packit 7cfc04
.I sevp\->sigev_notify
Packit 7cfc04
field can have the following values:
Packit 7cfc04
.TP
Packit 7cfc04
.BR SIGEV_NONE
Packit 7cfc04
Don't provide any notification.
Packit 7cfc04
.TP
Packit 7cfc04
.BR SIGEV_SIGNAL
Packit 7cfc04
When a look-up completes, generate the signal
Packit 7cfc04
.I sigev_signo
Packit 7cfc04
for the process.
Packit 7cfc04
See
Packit 7cfc04
.BR sigevent (7)
Packit 7cfc04
for general details.
Packit 7cfc04
The
Packit 7cfc04
.I si_code
Packit 7cfc04
field of the
Packit 7cfc04
.I siginfo_t
Packit 7cfc04
structure will be set to
Packit 7cfc04
.BR SI_ASYNCNL .
Packit 7cfc04
.\" si_pid and si_uid are also set, to the values of the calling process,
Packit 7cfc04
.\" which doesn't provide useful information, so we'll skip mentioning it.
Packit 7cfc04
.TP
Packit 7cfc04
.BR SIGEV_THREAD
Packit 7cfc04
When a look-up completes, invoke
Packit 7cfc04
.I sigev_notify_function
Packit 7cfc04
as if it were the start function of a new thread.
Packit 7cfc04
See
Packit 7cfc04
.BR sigevent (7)
Packit 7cfc04
for details.
Packit 7cfc04
.PP
Packit 7cfc04
For
Packit 7cfc04
.BR SIGEV_SIGNAL
Packit 7cfc04
and
Packit 7cfc04
.BR SIGEV_THREAD ,
Packit 7cfc04
it may be useful to point
Packit 7cfc04
.IR sevp\->sigev_value.sival_ptr
Packit 7cfc04
to
Packit 7cfc04
.IR list .
Packit 7cfc04
.PP
Packit 7cfc04
The
Packit 7cfc04
.BR gai_suspend ()
Packit 7cfc04
function suspends execution of the calling thread,
Packit 7cfc04
waiting for the completion of one or more requests in the array
Packit 7cfc04
.IR list .
Packit 7cfc04
The
Packit 7cfc04
.I nitems
Packit 7cfc04
argument specifies the size of the array
Packit 7cfc04
.IR list .
Packit 7cfc04
The call blocks until one of the following occurs:
Packit 7cfc04
.IP * 3
Packit 7cfc04
One or more of the operations in
Packit 7cfc04
.I list
Packit 7cfc04
completes.
Packit 7cfc04
.IP *
Packit 7cfc04
The call is interrupted by a signal that is caught.
Packit 7cfc04
.IP *
Packit 7cfc04
The time interval specified in
Packit 7cfc04
.I timeout
Packit 7cfc04
elapses.
Packit 7cfc04
This argument specifies a timeout in seconds plus nanoseconds (see
Packit 7cfc04
.BR nanosleep (2)
Packit 7cfc04
for details of the
Packit 7cfc04
.I timespec
Packit 7cfc04
structure).
Packit 7cfc04
If
Packit 7cfc04
.I timeout
Packit 7cfc04
is NULL, then the call blocks indefinitely
Packit 7cfc04
(until one of the events above occurs).
Packit 7cfc04
.PP
Packit 7cfc04
No explicit indication of which request was completed is given;
Packit 7cfc04
you must determine which request(s) have completed by iterating with
Packit 7cfc04
.BR gai_error ()
Packit 7cfc04
over the list of requests.
Packit 7cfc04
.PP
Packit 7cfc04
The
Packit 7cfc04
.BR gai_error ()
Packit 7cfc04
function returns the status of the request
Packit 7cfc04
.IR req :
Packit 7cfc04
either
Packit 7cfc04
.B EAI_INPROGRESS
Packit 7cfc04
if the request was not completed yet,
Packit 7cfc04
0 if it was handled successfully,
Packit 7cfc04
or an error code if the request could not be resolved.
Packit 7cfc04
.PP
Packit 7cfc04
The
Packit 7cfc04
.BR gai_cancel ()
Packit 7cfc04
function cancels the request
Packit 7cfc04
.IR req .
Packit 7cfc04
If the request has been canceled successfully,
Packit 7cfc04
the error status of the request will be set to
Packit 7cfc04
.B EAI_CANCELED
Packit 7cfc04
and normal asynchronous notification will be performed.
Packit 7cfc04
The request cannot be canceled if it is currently being processed;
Packit 7cfc04
in that case, it will be handled as if
Packit 7cfc04
.BR gai_cancel ()
Packit 7cfc04
has never been called.
Packit 7cfc04
If
Packit 7cfc04
.I req
Packit 7cfc04
is NULL, an attempt is made to cancel all outstanding requests
Packit 7cfc04
that the process has made.
Packit 7cfc04
.SH RETURN VALUE
Packit 7cfc04
The
Packit 7cfc04
.BR getaddrinfo_a ()
Packit 7cfc04
function returns 0 if all of the requests have been enqueued successfully,
Packit 7cfc04
or one of the following nonzero error codes:
Packit 7cfc04
.TP
Packit 7cfc04
.B EAI_AGAIN
Packit 7cfc04
The resources necessary to enqueue the look-up requests were not available.
Packit 7cfc04
The application may check the error status of each
Packit 7cfc04
request to determine which ones failed.
Packit 7cfc04
.TP
Packit 7cfc04
.B EAI_MEMORY
Packit 7cfc04
Out of memory.
Packit 7cfc04
.TP
Packit 7cfc04
.B EAI_SYSTEM
Packit 7cfc04
.I mode
Packit 7cfc04
is invalid.
Packit 7cfc04
.PP
Packit 7cfc04
The
Packit 7cfc04
.BR gai_suspend ()
Packit 7cfc04
function returns 0 if at least one of the listed requests has been completed.
Packit 7cfc04
Otherwise, it returns one of the following nonzero error codes:
Packit 7cfc04
.TP
Packit 7cfc04
.B EAI_AGAIN
Packit 7cfc04
The given timeout expired before any of the requests could be completed.
Packit 7cfc04
.TP
Packit 7cfc04
.B EAI_ALLDONE
Packit 7cfc04
There were no actual requests given to the function.
Packit 7cfc04
.TP
Packit 7cfc04
.B EAI_INTR
Packit 7cfc04
A signal has interrupted the function.
Packit 7cfc04
Note that this interruption might have been
Packit 7cfc04
caused by signal notification of some completed look-up request.
Packit 7cfc04
.PP
Packit 7cfc04
The
Packit 7cfc04
.BR gai_error ()
Packit 7cfc04
function can return
Packit 7cfc04
.B EAI_INPROGRESS
Packit 7cfc04
for an unfinished look-up request,
Packit 7cfc04
0 for a successfully completed look-up
Packit 7cfc04
(as described above), one of the error codes that could be returned by
Packit 7cfc04
.BR getaddrinfo (3),
Packit 7cfc04
or the error code
Packit 7cfc04
.B EAI_CANCELED
Packit 7cfc04
if the request has been canceled explicitly before it could be finished.
Packit 7cfc04
.PP
Packit 7cfc04
The
Packit 7cfc04
.BR gai_cancel ()
Packit 7cfc04
function can return one of these values:
Packit 7cfc04
.TP
Packit 7cfc04
.B EAI_CANCELED
Packit 7cfc04
The request has been canceled successfully.
Packit 7cfc04
.TP
Packit 7cfc04
.B EAI_NOTCANCELED
Packit 7cfc04
The request has not been canceled.
Packit 7cfc04
.TP
Packit 7cfc04
.B EAI_ALLDONE
Packit 7cfc04
The request has already completed.
Packit 7cfc04
.PP
Packit 7cfc04
The
Packit 7cfc04
.BR gai_strerror (3)
Packit 7cfc04
function translates these error codes to a human readable string,
Packit 7cfc04
suitable for error reporting.
Packit 7cfc04
.SH ATTRIBUTES
Packit 7cfc04
For an explanation of the terms used in this section, see
Packit 7cfc04
.BR attributes (7).
Packit 7cfc04
.TS
Packit 7cfc04
allbox;
Packit 7cfc04
lbw31 lb lb
Packit 7cfc04
l l l.
Packit 7cfc04
Interface	Attribute	Value
Packit 7cfc04
T{
Packit 7cfc04
.BR getaddrinfo_a (),
Packit 7cfc04
.BR gai_suspend (),
Packit 7cfc04
.BR gai_error (),
Packit 7cfc04
.BR gai_cancel ()
Packit 7cfc04
T}	Thread safety	MT-Safe
Packit 7cfc04
.TE
Packit 7cfc04
.sp 1
Packit 7cfc04
.SH CONFORMING TO
Packit 7cfc04
These functions are GNU extensions;
Packit 7cfc04
they first appeared in glibc in version 2.2.3.
Packit 7cfc04
.SH NOTES
Packit 7cfc04
The interface of
Packit 7cfc04
.BR getaddrinfo_a ()
Packit 7cfc04
was modeled after the
Packit 7cfc04
.BR lio_listio (3)
Packit 7cfc04
interface.
Packit 7cfc04
.SH EXAMPLE
Packit 7cfc04
Two examples are provided: a simple example that resolves
Packit 7cfc04
several requests in parallel synchronously, and a complex example
Packit 7cfc04
showing some of the asynchronous capabilities.
Packit 7cfc04
.SS Synchronous example
Packit 7cfc04
The program below simply resolves several hostnames in parallel,
Packit 7cfc04
giving a speed-up compared to resolving the hostnames sequentially using
Packit 7cfc04
.BR getaddrinfo (3).
Packit 7cfc04
The program might be used like this:
Packit 7cfc04
.PP
Packit 7cfc04
.in +4n
Packit 7cfc04
.EX
Packit 7cfc04
$ \fB./a.out ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz\fP
Packit 7cfc04
ftp.us.kernel.org: 128.30.2.36
Packit 7cfc04
enoent.linuxfoundation.org: Name or service not known
Packit 7cfc04
gnu.cz: 87.236.197.13
Packit 7cfc04
.EE
Packit 7cfc04
.in
Packit 7cfc04
.PP
Packit 7cfc04
Here is the program source code
Packit 7cfc04
.PP
Packit 7cfc04
.EX
Packit 7cfc04
#define _GNU_SOURCE
Packit 7cfc04
#include <netdb.h>
Packit 7cfc04
#include <stdio.h>
Packit 7cfc04
#include <stdlib.h>
Packit 7cfc04
#include <string.h>
Packit 7cfc04
Packit 7cfc04
int
Packit 7cfc04
main(int argc, char *argv[])
Packit 7cfc04
{
Packit 7cfc04
    int i, ret;
Packit 7cfc04
    struct gaicb *reqs[argc \- 1];
Packit 7cfc04
    char host[NI_MAXHOST];
Packit 7cfc04
    struct addrinfo *res;
Packit 7cfc04
Packit 7cfc04
    if (argc < 2) {
Packit 7cfc04
        fprintf(stderr, "Usage: %s HOST...\\n", argv[0]);
Packit 7cfc04
        exit(EXIT_FAILURE);
Packit 7cfc04
    }
Packit 7cfc04
Packit 7cfc04
    for (i = 0; i < argc \- 1; i++) {
Packit 7cfc04
        reqs[i] = malloc(sizeof(*reqs[0]));
Packit 7cfc04
        if (reqs[i] == NULL) {
Packit 7cfc04
            perror("malloc");
Packit 7cfc04
            exit(EXIT_FAILURE);
Packit 7cfc04
        }
Packit 7cfc04
        memset(reqs[i], 0, sizeof(*reqs[0]));
Packit 7cfc04
        reqs[i]\->ar_name = argv[i + 1];
Packit 7cfc04
    }
Packit 7cfc04
Packit 7cfc04
    ret = getaddrinfo_a(GAI_WAIT, reqs, argc \- 1, NULL);
Packit 7cfc04
    if (ret != 0) {
Packit 7cfc04
        fprintf(stderr, "getaddrinfo_a() failed: %s\\n",
Packit 7cfc04
                gai_strerror(ret));
Packit 7cfc04
        exit(EXIT_FAILURE);
Packit 7cfc04
    }
Packit 7cfc04
Packit 7cfc04
    for (i = 0; i < argc \- 1; i++) {
Packit 7cfc04
        printf("%s: ", reqs[i]\->ar_name);
Packit 7cfc04
        ret = gai_error(reqs[i]);
Packit 7cfc04
        if (ret == 0) {
Packit 7cfc04
            res = reqs[i]\->ar_result;
Packit 7cfc04
Packit 7cfc04
            ret = getnameinfo(res\->ai_addr, res\->ai_addrlen,
Packit 7cfc04
                    host, sizeof(host),
Packit 7cfc04
                    NULL, 0, NI_NUMERICHOST);
Packit 7cfc04
            if (ret != 0) {
Packit 7cfc04
                fprintf(stderr, "getnameinfo() failed: %s\\n",
Packit 7cfc04
                        gai_strerror(ret));
Packit 7cfc04
                exit(EXIT_FAILURE);
Packit 7cfc04
            }
Packit 7cfc04
            puts(host);
Packit 7cfc04
Packit 7cfc04
        } else {
Packit 7cfc04
            puts(gai_strerror(ret));
Packit 7cfc04
        }
Packit 7cfc04
    }
Packit 7cfc04
    exit(EXIT_SUCCESS);
Packit 7cfc04
}
Packit 7cfc04
.EE
Packit 7cfc04
.SS Asynchronous example
Packit 7cfc04
This example shows a simple interactive
Packit 7cfc04
.BR getaddrinfo_a ()
Packit 7cfc04
front-end.
Packit 7cfc04
The notification facility is not demonstrated.
Packit 7cfc04
.PP
Packit 7cfc04
An example session might look like this:
Packit 7cfc04
.PP
Packit 7cfc04
.in +4n
Packit 7cfc04
.EX
Packit 7cfc04
$ \fB./a.out\fP
Packit 7cfc04
> a ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz
Packit 7cfc04
> c 2
Packit 7cfc04
[2] gnu.cz: Request not canceled
Packit 7cfc04
> w 0 1
Packit 7cfc04
[00] ftp.us.kernel.org: Finished
Packit 7cfc04
> l
Packit 7cfc04
[00] ftp.us.kernel.org: 216.165.129.139
Packit 7cfc04
[01] enoent.linuxfoundation.org: Processing request in progress
Packit 7cfc04
[02] gnu.cz: 87.236.197.13
Packit 7cfc04
> l
Packit 7cfc04
[00] ftp.us.kernel.org: 216.165.129.139
Packit 7cfc04
[01] enoent.linuxfoundation.org: Name or service not known
Packit 7cfc04
[02] gnu.cz: 87.236.197.13
Packit 7cfc04
.EE
Packit 7cfc04
.in
Packit 7cfc04
.PP
Packit 7cfc04
The program source is as follows:
Packit 7cfc04
.PP
Packit 7cfc04
.EX
Packit 7cfc04
#define _GNU_SOURCE
Packit 7cfc04
#include <netdb.h>
Packit 7cfc04
#include <stdio.h>
Packit 7cfc04
#include <stdlib.h>
Packit 7cfc04
#include <string.h>
Packit 7cfc04
Packit 7cfc04
static struct gaicb **reqs = NULL;
Packit 7cfc04
static int nreqs = 0;
Packit 7cfc04
Packit 7cfc04
static char *
Packit 7cfc04
getcmd(void)
Packit 7cfc04
{
Packit 7cfc04
    static char buf[256];
Packit 7cfc04
Packit 7cfc04
    fputs("> ", stdout); fflush(stdout);
Packit 7cfc04
    if (fgets(buf, sizeof(buf), stdin) == NULL)
Packit 7cfc04
        return NULL;
Packit 7cfc04
Packit 7cfc04
    if (buf[strlen(buf) \- 1] == \(aq\\n\(aq)
Packit 7cfc04
        buf[strlen(buf) \- 1] = 0;
Packit 7cfc04
Packit 7cfc04
    return buf;
Packit 7cfc04
}
Packit 7cfc04
Packit 7cfc04
/* Add requests for specified hostnames */
Packit 7cfc04
static void
Packit 7cfc04
add_requests(void)
Packit 7cfc04
{
Packit 7cfc04
    int nreqs_base = nreqs;
Packit 7cfc04
    char *host;
Packit 7cfc04
    int ret;
Packit 7cfc04
Packit 7cfc04
    while ((host = strtok(NULL, " "))) {
Packit 7cfc04
        nreqs++;
Packit 7cfc04
        reqs = realloc(reqs, nreqs * sizeof(reqs[0]));
Packit 7cfc04
Packit 7cfc04
        reqs[nreqs \- 1] = calloc(1, sizeof(*reqs[0]));
Packit 7cfc04
        reqs[nreqs \- 1]\->ar_name = strdup(host);
Packit 7cfc04
    }
Packit 7cfc04
Packit 7cfc04
    /* Queue nreqs_base..nreqs requests. */
Packit 7cfc04
Packit 7cfc04
    ret = getaddrinfo_a(GAI_NOWAIT, &reqs[nreqs_base],
Packit 7cfc04
                        nreqs \- nreqs_base, NULL);
Packit 7cfc04
    if (ret) {
Packit 7cfc04
        fprintf(stderr, "getaddrinfo_a() failed: %s\\n",
Packit 7cfc04
                gai_strerror(ret));
Packit 7cfc04
        exit(EXIT_FAILURE);
Packit 7cfc04
    }
Packit 7cfc04
}
Packit 7cfc04
Packit 7cfc04
/* Wait until at least one of specified requests completes */
Packit 7cfc04
static void
Packit 7cfc04
wait_requests(void)
Packit 7cfc04
{
Packit 7cfc04
    char *id;
Packit 7cfc04
    int i, ret, n;
Packit 7cfc04
    struct gaicb const **wait_reqs = calloc(nreqs, sizeof(*wait_reqs));
Packit 7cfc04
                /* NULL elements are ignored by gai_suspend(). */
Packit 7cfc04
Packit 7cfc04
    while ((id = strtok(NULL, " ")) != NULL) {
Packit 7cfc04
        n = atoi(id);
Packit 7cfc04
Packit 7cfc04
        if (n >= nreqs) {
Packit 7cfc04
            printf("Bad request number: %s\\n", id);
Packit 7cfc04
            return;
Packit 7cfc04
        }
Packit 7cfc04
Packit 7cfc04
        wait_reqs[n] = reqs[n];
Packit 7cfc04
    }
Packit 7cfc04
Packit 7cfc04
    ret = gai_suspend(wait_reqs, nreqs, NULL);
Packit 7cfc04
    if (ret) {
Packit 7cfc04
        printf("gai_suspend(): %s\\n", gai_strerror(ret));
Packit 7cfc04
        return;
Packit 7cfc04
    }
Packit 7cfc04
Packit 7cfc04
    for (i = 0; i < nreqs; i++) {
Packit 7cfc04
        if (wait_reqs[i] == NULL)
Packit 7cfc04
            continue;
Packit 7cfc04
Packit 7cfc04
        ret = gai_error(reqs[i]);
Packit 7cfc04
        if (ret == EAI_INPROGRESS)
Packit 7cfc04
            continue;
Packit 7cfc04
Packit 7cfc04
        printf("[%02d] %s: %s\\n", i, reqs[i]\->ar_name,
Packit 7cfc04
               ret == 0 ? "Finished" : gai_strerror(ret));
Packit 7cfc04
    }
Packit 7cfc04
}
Packit 7cfc04
Packit 7cfc04
/* Cancel specified requests */
Packit 7cfc04
static void
Packit 7cfc04
cancel_requests(void)
Packit 7cfc04
{
Packit 7cfc04
    char *id;
Packit 7cfc04
    int ret, n;
Packit 7cfc04
Packit 7cfc04
    while ((id = strtok(NULL, " ")) != NULL) {
Packit 7cfc04
        n = atoi(id);
Packit 7cfc04
Packit 7cfc04
        if (n >= nreqs) {
Packit 7cfc04
            printf("Bad request number: %s\\n", id);
Packit 7cfc04
            return;
Packit 7cfc04
        }
Packit 7cfc04
Packit 7cfc04
        ret = gai_cancel(reqs[n]);
Packit 7cfc04
        printf("[%s] %s: %s\\n", id, reqs[atoi(id)]\->ar_name,
Packit 7cfc04
               gai_strerror(ret));
Packit 7cfc04
    }
Packit 7cfc04
}
Packit 7cfc04
Packit 7cfc04
/* List all requests */
Packit 7cfc04
static void
Packit 7cfc04
list_requests(void)
Packit 7cfc04
{
Packit 7cfc04
    int i, ret;
Packit 7cfc04
    char host[NI_MAXHOST];
Packit 7cfc04
    struct addrinfo *res;
Packit 7cfc04
Packit 7cfc04
    for (i = 0; i < nreqs; i++) {
Packit 7cfc04
        printf("[%02d] %s: ", i, reqs[i]\->ar_name);
Packit 7cfc04
        ret = gai_error(reqs[i]);
Packit 7cfc04
Packit 7cfc04
        if (!ret) {
Packit 7cfc04
            res = reqs[i]\->ar_result;
Packit 7cfc04
Packit 7cfc04
            ret = getnameinfo(res\->ai_addr, res\->ai_addrlen,
Packit 7cfc04
                              host, sizeof(host),
Packit 7cfc04
                              NULL, 0, NI_NUMERICHOST);
Packit 7cfc04
            if (ret) {
Packit 7cfc04
                fprintf(stderr, "getnameinfo() failed: %s\\n",
Packit 7cfc04
                        gai_strerror(ret));
Packit 7cfc04
                exit(EXIT_FAILURE);
Packit 7cfc04
            }
Packit 7cfc04
            puts(host);
Packit 7cfc04
        } else {
Packit 7cfc04
            puts(gai_strerror(ret));
Packit 7cfc04
        }
Packit 7cfc04
    }
Packit 7cfc04
}
Packit 7cfc04
Packit 7cfc04
int
Packit 7cfc04
main(int argc, char *argv[])
Packit 7cfc04
{
Packit 7cfc04
    char *cmdline;
Packit 7cfc04
    char *cmd;
Packit 7cfc04
Packit 7cfc04
    while ((cmdline = getcmd()) != NULL) {
Packit 7cfc04
        cmd = strtok(cmdline, " ");
Packit 7cfc04
Packit 7cfc04
        if (cmd == NULL) {
Packit 7cfc04
            list_requests();
Packit 7cfc04
        } else {
Packit 7cfc04
            switch (cmd[0]) {
Packit 7cfc04
            case \(aqa\(aq:
Packit 7cfc04
                add_requests();
Packit 7cfc04
                break;
Packit 7cfc04
            case \(aqw\(aq:
Packit 7cfc04
                wait_requests();
Packit 7cfc04
                break;
Packit 7cfc04
            case \(aqc\(aq:
Packit 7cfc04
                cancel_requests();
Packit 7cfc04
                break;
Packit 7cfc04
            case \(aql\(aq:
Packit 7cfc04
                list_requests();
Packit 7cfc04
                break;
Packit 7cfc04
            default:
Packit 7cfc04
                fprintf(stderr, "Bad command: %c\\n", cmd[0]);
Packit 7cfc04
                break;
Packit 7cfc04
            }
Packit 7cfc04
        }
Packit 7cfc04
    }
Packit 7cfc04
    exit(EXIT_SUCCESS);
Packit 7cfc04
}
Packit 7cfc04
.EE
Packit 7cfc04
.SH SEE ALSO
Packit 7cfc04
.BR getaddrinfo (3),
Packit 7cfc04
.BR inet (3),
Packit 7cfc04
.BR lio_listio (3),
Packit 7cfc04
.BR hostname (7),
Packit 7cfc04
.BR ip (7),
Packit 7cfc04
.BR sigevent (7)
Packit 7cfc04
.SH COLOPHON
Packit 7cfc04
This page is part of release 4.15 of the Linux
Packit 7cfc04
.I man-pages
Packit 7cfc04
project.
Packit 7cfc04
A description of the project,
Packit 7cfc04
information about reporting bugs,
Packit 7cfc04
and the latest version of this page,
Packit 7cfc04
can be found at
Packit 7cfc04
\%https://www.kernel.org/doc/man\-pages/.