man-pages/man3/getaddrinfo_a.3.html
2021-03-31 01:06:50 +01:00

788 lines
27 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML><HEAD><TITLE>Man page of GETADDRINFO_A</TITLE>
</HEAD><BODY>
<H1>GETADDRINFO_A</H1>
Section: Linux Programmer's Manual (3)<BR>Updated: 2019-03-06<BR><A HREF="#index">Index</A>
<A HREF="/cgi-bin/man/man2html">Return to Main Contents</A><HR>
<A NAME="lbAB">&nbsp;</A>
<H2>NAME</H2>
getaddrinfo_a, gai_suspend, gai_error, gai_cancel - asynchronous
network address and service translation
<A NAME="lbAC">&nbsp;</A>
<H2>SYNOPSIS</H2>
<PRE>
<B>#define _GNU_SOURCE</B> /* See <A HREF="/cgi-bin/man/man2html?7+feature_test_macros">feature_test_macros</A>(7) */
<B>#include &lt;<A HREF="file:///usr/include/netdb.h">netdb.h</A>&gt;</B>
<B>int getaddrinfo_a(int </B><I>mode</I><B>, struct gaicb *</B><I>list[]</I><B>,</B>
<B> int </B><I>nitems</I><B>, struct sigevent *</B><I>sevp</I><B>);</B>
<B>int gai_suspend(const struct gaicb * const </B><I>list[]</I><B>, int </B><I>nitems</I><B>,</B>
<B> const struct timespec *</B><I>timeout</I><B>);</B>
<B>int gai_error(struct gaicb *</B><I>req</I><B>);</B>
<B>int gai_cancel(struct gaicb *</B><I>req</I><B>);</B>
Link with <I>-lanl</I>.
</PRE>
<A NAME="lbAD">&nbsp;</A>
<H2>DESCRIPTION</H2>
The
<B>getaddrinfo_a</B>()
function performs the same task as
<B><A HREF="/cgi-bin/man/man2html?3+getaddrinfo">getaddrinfo</A></B>(3),
but allows multiple name look-ups to be performed asynchronously,
with optional notification on completion of look-up operations.
<P>
The
<I>mode</I>
argument has one of the following values:
<DL COMPACT>
<DT id="1"><B>GAI_WAIT</B>
<DD>
Perform the look-ups synchronously.
The call blocks until the look-ups have completed.
<DT id="2"><B>GAI_NOWAIT</B>
<DD>
Perform the look-ups asynchronously.
The call returns immediately,
and the requests are resolved in the background.
See the discussion of the
<I>sevp</I>
argument below.
</DL>
<P>
The array
<I>list</I>
specifies the look-up requests to process.
The
<I>nitems</I>
argument specifies the number of elements in
<I>list</I>.
The requested look-up operations are started in parallel.
NULL elements in
<I>list</I>
are ignored.
Each request is described by a
<I>gaicb</I>
structure, defined as follows:
<P>
struct gaicb {
<BR>&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;char&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*ar_name;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;char&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*ar_service;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;struct&nbsp;addrinfo&nbsp;*ar_request;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;addrinfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*ar_result;
};
<P>
The elements of this structure correspond to the arguments of
<B><A HREF="/cgi-bin/man/man2html?3+getaddrinfo">getaddrinfo</A></B>(3).
Thus,
<I>ar_name</I>
corresponds to the
<I>node</I>
argument and
<I>ar_service</I>
to the
<I>service</I>
argument, identifying an Internet host and a service.
The
<I>ar_request</I>
element corresponds to the
<I>hints</I>
argument, specifying the criteria for selecting
the returned socket address structures.
Finally,
<I>ar_result</I>
corresponds to the
<I>res</I>
argument; you do not need to initialize this element,
it will be automatically set when the request
is resolved.
The
<I>addrinfo</I>
structure referenced by the last two elements is described in
<B><A HREF="/cgi-bin/man/man2html?3+getaddrinfo">getaddrinfo</A></B>(3).
<P>
When
<I>mode</I>
is specified as
<B>GAI_NOWAIT</B>,
notifications about resolved requests
can be obtained by employing the
<I>sigevent</I>
structure pointed to by the
<I>sevp</I>
argument.
For the definition and general details of this structure, see
<B><A HREF="/cgi-bin/man/man2html?7+sigevent">sigevent</A></B>(7).
The
<I>sevp-&gt;sigev_notify</I>
field can have the following values:
<DL COMPACT>
<DT id="3"><B>SIGEV_NONE</B>
<DD>
Don't provide any notification.
<DT id="4"><B>SIGEV_SIGNAL</B>
<DD>
When a look-up completes, generate the signal
<I>sigev_signo</I>
for the process.
See
<B><A HREF="/cgi-bin/man/man2html?7+sigevent">sigevent</A></B>(7)
for general details.
The
<I>si_code</I>
field of the
<I>siginfo_t</I>
structure will be set to
<B>SI_ASYNCNL</B>.
<DT id="5"><B>SIGEV_THREAD</B>
<DD>
When a look-up completes, invoke
<I>sigev_notify_function</I>
as if it were the start function of a new thread.
See
<B><A HREF="/cgi-bin/man/man2html?7+sigevent">sigevent</A></B>(7)
for details.
</DL>
<P>
For
<B>SIGEV_SIGNAL</B>
and
<B>SIGEV_THREAD</B>,
it may be useful to point
<I>sevp-&gt;sigev_value.sival_ptr</I>
to
<I>list</I>.
<P>
The
<B>gai_suspend</B>()
function suspends execution of the calling thread,
waiting for the completion of one or more requests in the array
<I>list</I>.
The
<I>nitems</I>
argument specifies the size of the array
<I>list</I>.
The call blocks until one of the following occurs:
<DL COMPACT>
<DT id="6">*<DD>
One or more of the operations in
<I>list</I>
completes.
<DT id="7">*<DD>
The call is interrupted by a signal that is caught.
<DT id="8">*<DD>
The time interval specified in
<I>timeout</I>
elapses.
This argument specifies a timeout in seconds plus nanoseconds (see
<B><A HREF="/cgi-bin/man/man2html?2+nanosleep">nanosleep</A></B>(2)
for details of the
<I>timespec</I>
structure).
If
<I>timeout</I>
is NULL, then the call blocks indefinitely
(until one of the events above occurs).
</DL>
<P>
No explicit indication of which request was completed is given;
you must determine which request(s) have completed by iterating with
<B>gai_error</B>()
over the list of requests.
<P>
The
<B>gai_error</B>()
function returns the status of the request
<I>req</I>:
either
<B>EAI_INPROGRESS</B>
if the request was not completed yet,
0 if it was handled successfully,
or an error code if the request could not be resolved.
<P>
The
<B>gai_cancel</B>()
function cancels the request
<I>req</I>.
If the request has been canceled successfully,
the error status of the request will be set to
<B>EAI_CANCELED</B>
and normal asynchronous notification will be performed.
The request cannot be canceled if it is currently being processed;
in that case, it will be handled as if
<B>gai_cancel</B>()
has never been called.
If
<I>req</I>
is NULL, an attempt is made to cancel all outstanding requests
that the process has made.
<A NAME="lbAE">&nbsp;</A>
<H2>RETURN VALUE</H2>
The
<B>getaddrinfo_a</B>()
function returns 0 if all of the requests have been enqueued successfully,
or one of the following nonzero error codes:
<DL COMPACT>
<DT id="9"><B>EAI_AGAIN</B>
<DD>
The resources necessary to enqueue the look-up requests were not available.
The application may check the error status of each
request to determine which ones failed.
<DT id="10"><B>EAI_MEMORY</B>
<DD>
Out of memory.
<DT id="11"><B>EAI_SYSTEM</B>
<DD>
<I>mode</I>
is invalid.
</DL>
<P>
The
<B>gai_suspend</B>()
function returns 0 if at least one of the listed requests has been completed.
Otherwise, it returns one of the following nonzero error codes:
<DL COMPACT>
<DT id="12"><B>EAI_AGAIN</B>
<DD>
The given timeout expired before any of the requests could be completed.
<DT id="13"><B>EAI_ALLDONE</B>
<DD>
There were no actual requests given to the function.
<DT id="14"><B>EAI_INTR</B>
<DD>
A signal has interrupted the function.
Note that this interruption might have been
caused by signal notification of some completed look-up request.
</DL>
<P>
The
<B>gai_error</B>()
function can return
<B>EAI_INPROGRESS</B>
for an unfinished look-up request,
0 for a successfully completed look-up
(as described above), one of the error codes that could be returned by
<B><A HREF="/cgi-bin/man/man2html?3+getaddrinfo">getaddrinfo</A></B>(3),
or the error code
<B>EAI_CANCELED</B>
if the request has been canceled explicitly before it could be finished.
<P>
The
<B>gai_cancel</B>()
function can return one of these values:
<DL COMPACT>
<DT id="15"><B>EAI_CANCELED</B>
<DD>
The request has been canceled successfully.
<DT id="16"><B>EAI_NOTCANCELED</B>
<DD>
The request has not been canceled.
<DT id="17"><B>EAI_ALLDONE</B>
<DD>
The request has already completed.
</DL>
<P>
The
<B><A HREF="/cgi-bin/man/man2html?3+gai_strerror">gai_strerror</A></B>(3)
function translates these error codes to a human readable string,
suitable for error reporting.
<A NAME="lbAF">&nbsp;</A>
<H2>ATTRIBUTES</H2>
For an explanation of the terms used in this section, see
<B><A HREF="/cgi-bin/man/man2html?7+attributes">attributes</A></B>(7).
<TABLE BORDER>
<TR VALIGN=top><TD><B>Interface</B></TD><TD><B>Attribute</B></TD><TD><B>Value</B><BR></TD></TR>
<TR VALIGN=top><TD>
<B>getaddrinfo_a</B>(),
<B>gai_suspend</B>(),
<B>gai_error</B>(),
<B>gai_cancel</B>()
</TD><TD>Thread safety</TD><TD>MT-Safe<BR></TD></TR>
</TABLE>
<P>
<A NAME="lbAG">&nbsp;</A>
<H2>CONFORMING TO</H2>
These functions are GNU extensions;
they first appeared in glibc in version 2.2.3.
<A NAME="lbAH">&nbsp;</A>
<H2>NOTES</H2>
The interface of
<B>getaddrinfo_a</B>()
was modeled after the
<B><A HREF="/cgi-bin/man/man2html?3+lio_listio">lio_listio</A></B>(3)
interface.
<A NAME="lbAI">&nbsp;</A>
<H2>EXAMPLE</H2>
Two examples are provided: a simple example that resolves
several requests in parallel synchronously, and a complex example
showing some of the asynchronous capabilities.
<A NAME="lbAJ">&nbsp;</A>
<H3>Synchronous example</H3>
The program below simply resolves several hostnames in parallel,
giving a speed-up compared to resolving the hostnames sequentially using
<B><A HREF="/cgi-bin/man/man2html?3+getaddrinfo">getaddrinfo</A></B>(3).
The program might be used like this:
<P>
$ <B>./a.out <A HREF="ftp://ftp.us.kernel.org">ftp.us.kernel.org</A> enoent.linuxfoundation.org gnu.cz</B>
<A HREF="ftp://ftp.us.kernel.org">ftp.us.kernel.org</A>: 128.30.2.36
enoent.linuxfoundation.org: Name or service not known
gnu.cz: 87.236.197.13
<P>
Here is the program source code
<P>
#define _GNU_SOURCE
#include &lt;<A HREF="file:///usr/include/netdb.h">netdb.h</A>&gt;
#include &lt;<A HREF="file:///usr/include/stdio.h">stdio.h</A>&gt;
#include &lt;<A HREF="file:///usr/include/stdlib.h">stdlib.h</A>&gt;
#include &lt;<A HREF="file:///usr/include/string.h">string.h</A>&gt;
<P>
int
main(int argc, char *argv[])
{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i,&nbsp;ret;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;gaicb&nbsp;*reqs[argc&nbsp;-&nbsp;1];
<BR>&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;host[NI_MAXHOST];
<BR>&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;addrinfo&nbsp;*res;
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(argc&nbsp;&lt;&nbsp;2)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,&nbsp;&quot;Usage:&nbsp;%s&nbsp;HOST...\n&quot;,&nbsp;argv[0]);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_FAILURE);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;}
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;argc&nbsp;-&nbsp;1;&nbsp;i++)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reqs[i]&nbsp;=&nbsp;malloc(sizeof(*reqs[0]));
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(reqs[i]&nbsp;==&nbsp;NULL)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror(&quot;malloc&quot;);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_FAILURE);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memset(reqs[i],&nbsp;0,&nbsp;sizeof(*reqs[0]));
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reqs[i]-&gt;ar_name&nbsp;=&nbsp;argv[i&nbsp;+&nbsp;1];
<BR>&nbsp;&nbsp;&nbsp;&nbsp;}
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;=&nbsp;getaddrinfo_a(GAI_WAIT,&nbsp;reqs,&nbsp;argc&nbsp;-&nbsp;1,&nbsp;NULL);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(ret&nbsp;!=&nbsp;0)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,&nbsp;&quot;getaddrinfo_a()&nbsp;failed:&nbsp;%s\n&quot;,
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gai_strerror(ret));
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_FAILURE);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;}
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;argc&nbsp;-&nbsp;1;&nbsp;i++)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;%s:&nbsp;&quot;,&nbsp;reqs[i]-&gt;ar_name);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;=&nbsp;gai_error(reqs[i]);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(ret&nbsp;==&nbsp;0)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res&nbsp;=&nbsp;reqs[i]-&gt;ar_result;
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;=&nbsp;getnameinfo(res-&gt;ai_addr,&nbsp;res-&gt;ai_addrlen,
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host,&nbsp;sizeof(host),
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL,&nbsp;0,&nbsp;NI_NUMERICHOST);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(ret&nbsp;!=&nbsp;0)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,&nbsp;&quot;getnameinfo()&nbsp;failed:&nbsp;%s\n&quot;,
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gai_strerror(ret));
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_FAILURE);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts(host);
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts(gai_strerror(ret));
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<BR>&nbsp;&nbsp;&nbsp;&nbsp;}
<BR>&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_SUCCESS);
}
<A NAME="lbAK">&nbsp;</A>
<H3>Asynchronous example</H3>
This example shows a simple interactive
<B>getaddrinfo_a</B>()
front-end.
The notification facility is not demonstrated.
<P>
An example session might look like this:
<P>
$ <B>./a.out</B>
&gt; a <A HREF="ftp://ftp.us.kernel.org">ftp.us.kernel.org</A> enoent.linuxfoundation.org gnu.cz
&gt; c 2
[2] gnu.cz: Request not canceled
&gt; w 0 1
[00] <A HREF="ftp://ftp.us.kernel.org">ftp.us.kernel.org</A>: Finished
&gt; l
[00] <A HREF="ftp://ftp.us.kernel.org">ftp.us.kernel.org</A>: 216.165.129.139
[01] enoent.linuxfoundation.org: Processing request in progress
[02] gnu.cz: 87.236.197.13
&gt; l
[00] <A HREF="ftp://ftp.us.kernel.org">ftp.us.kernel.org</A>: 216.165.129.139
[01] enoent.linuxfoundation.org: Name or service not known
[02] gnu.cz: 87.236.197.13
<P>
The program source is as follows:
<P>
#define _GNU_SOURCE
#include &lt;<A HREF="file:///usr/include/netdb.h">netdb.h</A>&gt;
#include &lt;<A HREF="file:///usr/include/stdio.h">stdio.h</A>&gt;
#include &lt;<A HREF="file:///usr/include/stdlib.h">stdlib.h</A>&gt;
#include &lt;<A HREF="file:///usr/include/string.h">string.h</A>&gt;
<P>
static struct gaicb **reqs = NULL;
static int nreqs = 0;
<P>
static char *
getcmd(void)
{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;char&nbsp;buf[256];
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;fputs(&quot;&gt;&nbsp;&quot;,&nbsp;stdout);&nbsp;fflush(stdout);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(fgets(buf,&nbsp;sizeof(buf),&nbsp;stdin)&nbsp;==&nbsp;NULL)
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;NULL;
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(buf[strlen(buf)&nbsp;-&nbsp;1]&nbsp;==&nbsp;'\n')
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buf[strlen(buf)&nbsp;-&nbsp;1]&nbsp;=&nbsp;0;
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;buf;
}
<P>
/* Add requests for specified hostnames */
static void
add_requests(void)
{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;nreqs_base&nbsp;=&nbsp;nreqs;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;*host;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;ret;
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;((host&nbsp;=&nbsp;strtok(NULL,&nbsp;&quot;&nbsp;&quot;)))&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nreqs++;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reqs&nbsp;=&nbsp;realloc(reqs,&nbsp;nreqs&nbsp;*&nbsp;sizeof(reqs[0]));
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reqs[nreqs&nbsp;-&nbsp;1]&nbsp;=&nbsp;calloc(1,&nbsp;sizeof(*reqs[0]));
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reqs[nreqs&nbsp;-&nbsp;1]-&gt;ar_name&nbsp;=&nbsp;strdup(host);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;}
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;Queue&nbsp;nreqs_base..nreqs&nbsp;requests.&nbsp;*/
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;=&nbsp;getaddrinfo_a(GAI_NOWAIT,&nbsp;&amp;reqs[nreqs_base],
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nreqs&nbsp;-&nbsp;nreqs_base,&nbsp;NULL);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(ret)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,&nbsp;&quot;getaddrinfo_a()&nbsp;failed:&nbsp;%s\n&quot;,
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gai_strerror(ret));
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_FAILURE);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;}
}
<P>
/* Wait until at least one of specified requests completes */
static void
wait_requests(void)
{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;*id;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i,&nbsp;ret,&nbsp;n;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;gaicb&nbsp;const&nbsp;**wait_reqs&nbsp;=&nbsp;calloc(nreqs,&nbsp;sizeof(*wait_reqs));
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;NULL&nbsp;elements&nbsp;are&nbsp;ignored&nbsp;by&nbsp;gai_suspend().&nbsp;*/
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;((id&nbsp;=&nbsp;strtok(NULL,&nbsp;&quot;&nbsp;&quot;))&nbsp;!=&nbsp;NULL)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n&nbsp;=&nbsp;atoi(id);
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(n&nbsp;&gt;=&nbsp;nreqs)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;Bad&nbsp;request&nbsp;number:&nbsp;%s\n&quot;,&nbsp;id);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wait_reqs[n]&nbsp;=&nbsp;reqs[n];
<BR>&nbsp;&nbsp;&nbsp;&nbsp;}
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;=&nbsp;gai_suspend(wait_reqs,&nbsp;nreqs,&nbsp;NULL);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(ret)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;gai_suspend():&nbsp;%s\n&quot;,&nbsp;gai_strerror(ret));
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;}
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;nreqs;&nbsp;i++)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(wait_reqs[i]&nbsp;==&nbsp;NULL)
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue;
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;=&nbsp;gai_error(reqs[i]);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(ret&nbsp;==&nbsp;EAI_INPROGRESS)
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue;
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;[%02d]&nbsp;%s:&nbsp;%s\n&quot;,&nbsp;i,&nbsp;reqs[i]-&gt;ar_name,
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;==&nbsp;0&nbsp;?&nbsp;&quot;Finished&quot;&nbsp;:&nbsp;gai_strerror(ret));
<BR>&nbsp;&nbsp;&nbsp;&nbsp;}
}
<P>
/* Cancel specified requests */
static void
cancel_requests(void)
{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;*id;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;ret,&nbsp;n;
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;((id&nbsp;=&nbsp;strtok(NULL,&nbsp;&quot;&nbsp;&quot;))&nbsp;!=&nbsp;NULL)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n&nbsp;=&nbsp;atoi(id);
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(n&nbsp;&gt;=&nbsp;nreqs)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;Bad&nbsp;request&nbsp;number:&nbsp;%s\n&quot;,&nbsp;id);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;=&nbsp;gai_cancel(reqs[n]);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;[%s]&nbsp;%s:&nbsp;%s\n&quot;,&nbsp;id,&nbsp;reqs[atoi(id)]-&gt;ar_name,
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gai_strerror(ret));
<BR>&nbsp;&nbsp;&nbsp;&nbsp;}
}
<P>
/* List all requests */
static void
list_requests(void)
{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;i,&nbsp;ret;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;host[NI_MAXHOST];
<BR>&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;addrinfo&nbsp;*res;
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;nreqs;&nbsp;i++)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;[%02d]&nbsp;%s:&nbsp;&quot;,&nbsp;i,&nbsp;reqs[i]-&gt;ar_name);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;=&nbsp;gai_error(reqs[i]);
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!ret)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res&nbsp;=&nbsp;reqs[i]-&gt;ar_result;
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;=&nbsp;getnameinfo(res-&gt;ai_addr,&nbsp;res-&gt;ai_addrlen,
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host,&nbsp;sizeof(host),
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL,&nbsp;0,&nbsp;NI_NUMERICHOST);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(ret)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,&nbsp;&quot;getnameinfo()&nbsp;failed:&nbsp;%s\n&quot;,
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gai_strerror(ret));
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_FAILURE);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts(host);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts(gai_strerror(ret));
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<BR>&nbsp;&nbsp;&nbsp;&nbsp;}
}
<P>
int
main(int argc, char *argv[])
{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;*cmdline;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;*cmd;
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;((cmdline&nbsp;=&nbsp;getcmd())&nbsp;!=&nbsp;NULL)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmd&nbsp;=&nbsp;strtok(cmdline,&nbsp;&quot;&nbsp;&quot;);
<P>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(cmd&nbsp;==&nbsp;NULL)&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list_requests();
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switch&nbsp;(cmd[0])&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;'a':
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add_requests();
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;'w':
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wait_requests();
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;'c':
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cancel_requests();
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;'l':
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list_requests();
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default:
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,&nbsp;&quot;Bad&nbsp;command:&nbsp;%c\n&quot;,&nbsp;cmd[0]);
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<BR>&nbsp;&nbsp;&nbsp;&nbsp;}
<BR>&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_SUCCESS);
}
<A NAME="lbAL">&nbsp;</A>
<H2>SEE ALSO</H2>
<B><A HREF="/cgi-bin/man/man2html?3+getaddrinfo">getaddrinfo</A></B>(3),
<B><A HREF="/cgi-bin/man/man2html?3+inet">inet</A></B>(3),
<B><A HREF="/cgi-bin/man/man2html?3+lio_listio">lio_listio</A></B>(3),
<B><A HREF="/cgi-bin/man/man2html?7+hostname">hostname</A></B>(7),
<B><A HREF="/cgi-bin/man/man2html?7+ip">ip</A></B>(7),
<B><A HREF="/cgi-bin/man/man2html?7+sigevent">sigevent</A></B>(7)
<A NAME="lbAM">&nbsp;</A>
<H2>COLOPHON</H2>
This page is part of release 5.05 of the Linux
<I>man-pages</I>
project.
A description of the project,
information about reporting bugs,
and the latest version of this page,
can be found at
<A HREF="https://www.kernel.org/doc/man-pages/.">https://www.kernel.org/doc/man-pages/.</A>
<P>
<HR>
<A NAME="index">&nbsp;</A><H2>Index</H2>
<DL>
<DT id="18"><A HREF="#lbAB">NAME</A><DD>
<DT id="19"><A HREF="#lbAC">SYNOPSIS</A><DD>
<DT id="20"><A HREF="#lbAD">DESCRIPTION</A><DD>
<DT id="21"><A HREF="#lbAE">RETURN VALUE</A><DD>
<DT id="22"><A HREF="#lbAF">ATTRIBUTES</A><DD>
<DT id="23"><A HREF="#lbAG">CONFORMING TO</A><DD>
<DT id="24"><A HREF="#lbAH">NOTES</A><DD>
<DT id="25"><A HREF="#lbAI">EXAMPLE</A><DD>
<DL>
<DT id="26"><A HREF="#lbAJ">Synchronous example</A><DD>
<DT id="27"><A HREF="#lbAK">Asynchronous example</A><DD>
</DL>
<DT id="28"><A HREF="#lbAL">SEE ALSO</A><DD>
<DT id="29"><A HREF="#lbAM">COLOPHON</A><DD>
</DL>
<HR>
This document was created by
<A HREF="/cgi-bin/man/man2html">man2html</A>,
using the manual pages.<BR>
Time: 00:05:44 GMT, March 31, 2021
</BODY>
</HTML>