|
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/.
|