]>
Commit | Line | Data |
---|---|---|
a1eaacb1 | 1 | '\" t |
e11d63b9 | 2 | .\" Copyright (c) 2009 Petr Baudis <pasky@suse.cz> |
bfb9c7c0 | 3 | .\" and clean-ups and additions (C) Copyright 2010 Michael Kerrisk |
67c7e1d5 | 4 | .\" <mtk.manpages@gmail.com> |
e11d63b9 | 5 | .\" |
5fbde956 | 6 | .\" SPDX-License-Identifier: Linux-man-pages-copyleft |
e11d63b9 PB |
7 | .\" |
8 | .\" References: http://people.redhat.com/drepper/asynchnl.pdf, | |
9 | .\" http://www.imperialviolet.org/2005/06/01/asynchronous-dns-lookups-with-glibc.html | |
10 | .\" | |
4c1c5274 | 11 | .TH getaddrinfo_a 3 (date) "Linux man-pages (unreleased)" |
e11d63b9 PB |
12 | .SH NAME |
13 | getaddrinfo_a, gai_suspend, gai_error, gai_cancel \- asynchronous | |
14 | network address and service translation | |
af56ce56 AC |
15 | .SH LIBRARY |
16 | Asynchronous name lookup library | |
17 | .RI ( libanl ", " \-lanl ) | |
e11d63b9 PB |
18 | .SH SYNOPSIS |
19 | .nf | |
b80f966b | 20 | .BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */" |
e11d63b9 | 21 | .B #include <netdb.h> |
68e4db0a | 22 | .PP |
79201b69 AC |
23 | .BI "int getaddrinfo_a(int " mode ", struct gaicb *" list [restrict], |
24 | .BI " int " nitems ", struct sigevent *restrict " sevp ); | |
25 | .BI "int gai_suspend(const struct gaicb *const " list "[], int " nitems , | |
26 | .BI " const struct timespec *" timeout ); | |
68e4db0a | 27 | .PP |
79201b69 AC |
28 | .BI "int gai_error(struct gaicb *" req ); |
29 | .BI "int gai_cancel(struct gaicb *" req ); | |
e11d63b9 PB |
30 | .fi |
31 | .SH DESCRIPTION | |
32 | The | |
33 | .BR getaddrinfo_a () | |
34 | function performs the same task as | |
35 | .BR getaddrinfo (3), | |
36 | but allows multiple name look-ups to be performed asynchronously, | |
37 | with optional notification on completion of look-up operations. | |
847e0d88 | 38 | .PP |
e11d63b9 PB |
39 | The |
40 | .I mode | |
41 | argument has one of the following values: | |
42 | .TP | |
43 | .B GAI_WAIT | |
af15dfab SP |
44 | Perform the look-ups synchronously. |
45 | The call blocks until the look-ups have completed. | |
e11d63b9 PB |
46 | .TP |
47 | .B GAI_NOWAIT | |
48 | Perform the look-ups asynchronously. | |
49 | The call returns immediately, | |
50 | and the requests are resolved in the background. | |
51 | See the discussion of the | |
52 | .I sevp | |
53 | argument below. | |
54 | .PP | |
55 | The array | |
56 | .I list | |
57 | specifies the look-up requests to process. | |
58 | The | |
59 | .I nitems | |
60 | argument specifies the number of elements in | |
61 | .IR list . | |
62 | The requested look-up operations are started in parallel. | |
63 | NULL elements in | |
64 | .I list | |
65 | are ignored. | |
66 | Each request is described by a | |
67 | .I gaicb | |
68 | structure, defined as follows: | |
51f5698d | 69 | .PP |
e11d63b9 | 70 | .in +4n |
b8302363 | 71 | .EX |
e11d63b9 PB |
72 | struct gaicb { |
73 | const char *ar_name; | |
74 | const char *ar_service; | |
75 | const struct addrinfo *ar_request; | |
76 | struct addrinfo *ar_result; | |
77 | }; | |
b8302363 | 78 | .EE |
e11d63b9 | 79 | .in |
847e0d88 | 80 | .PP |
e11d63b9 PB |
81 | The elements of this structure correspond to the arguments of |
82 | .BR getaddrinfo (3). | |
83 | Thus, | |
84 | .I ar_name | |
85 | corresponds to the | |
86 | .I node | |
87 | argument and | |
88 | .I ar_service | |
89 | to the | |
90 | .I service | |
91 | argument, identifying an Internet host and a service. | |
92 | The | |
93 | .I ar_request | |
94 | element corresponds to the | |
95 | .I hints | |
96 | argument, specifying the criteria for selecting | |
97 | the returned socket address structures. | |
98 | Finally, | |
99 | .I ar_result | |
100 | corresponds to the | |
101 | .I res | |
102 | argument; you do not need to initialize this element, | |
103 | it will be automatically set when the request | |
104 | is resolved. | |
105 | The | |
106 | .I addrinfo | |
107 | structure referenced by the last two elements is described in | |
108 | .BR getaddrinfo (3). | |
847e0d88 | 109 | .PP |
e11d63b9 PB |
110 | When |
111 | .I mode | |
112 | is specified as | |
5238ea2c | 113 | .BR GAI_NOWAIT , |
e11d63b9 PB |
114 | notifications about resolved requests |
115 | can be obtained by employing the | |
116 | .I sigevent | |
117 | structure pointed to by the | |
118 | .I sevp | |
119 | argument. | |
120 | For the definition and general details of this structure, see | |
121 | .BR sigevent (7). | |
122 | The | |
123 | .I sevp\->sigev_notify | |
124 | field can have the following values: | |
125 | .TP | |
1ae6b2c7 | 126 | .B SIGEV_NONE |
e11d63b9 PB |
127 | Don't provide any notification. |
128 | .TP | |
1ae6b2c7 | 129 | .B SIGEV_SIGNAL |
e11d63b9 PB |
130 | When a look-up completes, generate the signal |
131 | .I sigev_signo | |
132 | for the process. | |
133 | See | |
134 | .BR sigevent (7) | |
135 | for general details. | |
136 | The | |
137 | .I si_code | |
138 | field of the | |
139 | .I siginfo_t | |
140 | structure will be set to | |
141 | .BR SI_ASYNCNL . | |
142 | .\" si_pid and si_uid are also set, to the values of the calling process, | |
143 | .\" which doesn't provide useful information, so we'll skip mentioning it. | |
144 | .TP | |
1ae6b2c7 | 145 | .B SIGEV_THREAD |
e11d63b9 PB |
146 | When a look-up completes, invoke |
147 | .I sigev_notify_function | |
148 | as if it were the start function of a new thread. | |
149 | See | |
150 | .BR sigevent (7) | |
151 | for details. | |
152 | .PP | |
59e9285d | 153 | For |
1ae6b2c7 | 154 | .B SIGEV_SIGNAL |
e11d63b9 PB |
155 | and |
156 | .BR SIGEV_THREAD , | |
157 | it may be useful to point | |
1ae6b2c7 | 158 | .I sevp\->sigev_value.sival_ptr |
e11d63b9 PB |
159 | to |
160 | .IR list . | |
847e0d88 | 161 | .PP |
e11d63b9 PB |
162 | The |
163 | .BR gai_suspend () | |
164 | function suspends execution of the calling thread, | |
165 | waiting for the completion of one or more requests in the array | |
1f2a5c64 | 166 | .IR list . |
e11d63b9 PB |
167 | The |
168 | .I nitems | |
169 | argument specifies the size of the array | |
170 | .IR list . | |
171 | The call blocks until one of the following occurs: | |
cdede5cd | 172 | .IP \[bu] 3 |
e11d63b9 PB |
173 | One or more of the operations in |
174 | .I list | |
175 | completes. | |
cdede5cd | 176 | .IP \[bu] |
e11d63b9 | 177 | The call is interrupted by a signal that is caught. |
cdede5cd | 178 | .IP \[bu] |
e11d63b9 PB |
179 | The time interval specified in |
180 | .I timeout | |
181 | elapses. | |
182 | This argument specifies a timeout in seconds plus nanoseconds (see | |
183 | .BR nanosleep (2) | |
184 | for details of the | |
185 | .I timespec | |
186 | structure). | |
187 | If | |
188 | .I timeout | |
189 | is NULL, then the call blocks indefinitely | |
190 | (until one of the events above occurs). | |
191 | .PP | |
192 | No explicit indication of which request was completed is given; | |
193 | you must determine which request(s) have completed by iterating with | |
194 | .BR gai_error () | |
195 | over the list of requests. | |
847e0d88 | 196 | .PP |
e11d63b9 PB |
197 | The |
198 | .BR gai_error () | |
199 | function returns the status of the request | |
200 | .IR req : | |
201 | either | |
202 | .B EAI_INPROGRESS | |
203 | if the request was not completed yet, | |
204 | 0 if it was handled successfully, | |
205 | or an error code if the request could not be resolved. | |
847e0d88 | 206 | .PP |
e11d63b9 PB |
207 | The |
208 | .BR gai_cancel () | |
209 | function cancels the request | |
210 | .IR req . | |
211 | If the request has been canceled successfully, | |
212 | the error status of the request will be set to | |
819eeff4 | 213 | .B EAI_CANCELED |
e11d63b9 PB |
214 | and normal asynchronous notification will be performed. |
215 | The request cannot be canceled if it is currently being processed; | |
216 | in that case, it will be handled as if | |
217 | .BR gai_cancel () | |
218 | has never been called. | |
219 | If | |
220 | .I req | |
221 | is NULL, an attempt is made to cancel all outstanding requests | |
222 | that the process has made. | |
47297adb | 223 | .SH RETURN VALUE |
e11d63b9 PB |
224 | The |
225 | .BR getaddrinfo_a () | |
226 | function returns 0 if all of the requests have been enqueued successfully, | |
227 | or one of the following nonzero error codes: | |
228 | .TP | |
229 | .B EAI_AGAIN | |
230 | The resources necessary to enqueue the look-up requests were not available. | |
231 | The application may check the error status of each | |
232 | request to determine which ones failed. | |
233 | .TP | |
234 | .B EAI_MEMORY | |
235 | Out of memory. | |
236 | .TP | |
237 | .B EAI_SYSTEM | |
238 | .I mode | |
239 | is invalid. | |
240 | .PP | |
241 | The | |
242 | .BR gai_suspend () | |
243 | function returns 0 if at least one of the listed requests has been completed. | |
244 | Otherwise, it returns one of the following nonzero error codes: | |
245 | .TP | |
246 | .B EAI_AGAIN | |
247 | The given timeout expired before any of the requests could be completed. | |
248 | .TP | |
249 | .B EAI_ALLDONE | |
250 | There were no actual requests given to the function. | |
251 | .TP | |
252 | .B EAI_INTR | |
253 | A signal has interrupted the function. | |
254 | Note that this interruption might have been | |
255 | caused by signal notification of some completed look-up request. | |
256 | .PP | |
257 | The | |
258 | .BR gai_error () | |
259 | function can return | |
260 | .B EAI_INPROGRESS | |
261 | for an unfinished look-up request, | |
262 | 0 for a successfully completed look-up | |
263 | (as described above), one of the error codes that could be returned by | |
264 | .BR getaddrinfo (3), | |
265 | or the error code | |
819eeff4 | 266 | .B EAI_CANCELED |
e11d63b9 | 267 | if the request has been canceled explicitly before it could be finished. |
847e0d88 | 268 | .PP |
e11d63b9 PB |
269 | The |
270 | .BR gai_cancel () | |
271 | function can return one of these values: | |
272 | .TP | |
819eeff4 | 273 | .B EAI_CANCELED |
e11d63b9 PB |
274 | The request has been canceled successfully. |
275 | .TP | |
819eeff4 | 276 | .B EAI_NOTCANCELED |
e11d63b9 PB |
277 | The request has not been canceled. |
278 | .TP | |
279 | .B EAI_ALLDONE | |
280 | The request has already completed. | |
281 | .PP | |
282 | The | |
283 | .BR gai_strerror (3) | |
284 | function translates these error codes to a human readable string, | |
285 | suitable for error reporting. | |
9038b7f6 ZL |
286 | .SH ATTRIBUTES |
287 | For an explanation of the terms used in this section, see | |
288 | .BR attributes (7). | |
289 | .TS | |
290 | allbox; | |
c466875e | 291 | lbx lb lb |
9038b7f6 ZL |
292 | l l l. |
293 | Interface Attribute Value | |
294 | T{ | |
9e54434e BR |
295 | .na |
296 | .nh | |
9038b7f6 ZL |
297 | .BR getaddrinfo_a (), |
298 | .BR gai_suspend (), | |
299 | .BR gai_error (), | |
300 | .BR gai_cancel () | |
301 | T} Thread safety MT-Safe | |
302 | .TE | |
847e0d88 | 303 | .sp 1 |
3113c7f3 | 304 | .SH STANDARDS |
4131356c AC |
305 | GNU. |
306 | .SH HISTORY | |
307 | glibc 2.2.3. | |
308 | .PP | |
e11d63b9 PB |
309 | The interface of |
310 | .BR getaddrinfo_a () | |
311 | was modeled after the | |
312 | .BR lio_listio (3) | |
313 | interface. | |
a14af333 | 314 | .SH EXAMPLES |
e11d63b9 PB |
315 | Two examples are provided: a simple example that resolves |
316 | several requests in parallel synchronously, and a complex example | |
317 | showing some of the asynchronous capabilities. | |
c634028a | 318 | .SS Synchronous example |
e11d63b9 PB |
319 | The program below simply resolves several hostnames in parallel, |
320 | giving a speed-up compared to resolving the hostnames sequentially using | |
321 | .BR getaddrinfo (3). | |
322 | The program might be used like this: | |
e646a1ba | 323 | .PP |
e11d63b9 | 324 | .in +4n |
e646a1ba | 325 | .EX |
7f516900 | 326 | $ \fB./a.out mirrors.kernel.org enoent.linuxfoundation.org gnu.org\fP |
6de1d3a9 | 327 | mirrors.kernel.org: 139.178.88.99 |
e11d63b9 | 328 | enoent.linuxfoundation.org: Name or service not known |
a2feb3e1 | 329 | gnu.org: 209.51.188.116 |
b8302363 | 330 | .EE |
e11d63b9 PB |
331 | .in |
332 | .PP | |
333 | Here is the program source code | |
207050fa | 334 | .PP |
b0b6ab4e | 335 | .\" SRC BEGIN (sync.c) |
207050fa | 336 | .EX |
e11d63b9 PB |
337 | #define _GNU_SOURCE |
338 | #include <netdb.h> | |
339 | #include <stdio.h> | |
340 | #include <stdlib.h> | |
341 | #include <string.h> | |
fe5dba13 | 342 | \& |
e11d63b9 PB |
343 | int |
344 | main(int argc, char *argv[]) | |
345 | { | |
88893a77 | 346 | int ret; |
e11d63b9 PB |
347 | struct gaicb *reqs[argc \- 1]; |
348 | char host[NI_MAXHOST]; | |
349 | struct addrinfo *res; | |
fe5dba13 | 350 | \& |
e11d63b9 | 351 | if (argc < 2) { |
d1a71985 | 352 | fprintf(stderr, "Usage: %s HOST...\en", argv[0]); |
e11d63b9 PB |
353 | exit(EXIT_FAILURE); |
354 | } | |
fe5dba13 | 355 | \& |
b42296e4 | 356 | for (size_t i = 0; i < argc \- 1; i++) { |
e11d63b9 PB |
357 | reqs[i] = malloc(sizeof(*reqs[0])); |
358 | if (reqs[i] == NULL) { | |
359 | perror("malloc"); | |
360 | exit(EXIT_FAILURE); | |
361 | } | |
362 | memset(reqs[i], 0, sizeof(*reqs[0])); | |
363 | reqs[i]\->ar_name = argv[i + 1]; | |
364 | } | |
fe5dba13 | 365 | \& |
e11d63b9 PB |
366 | ret = getaddrinfo_a(GAI_WAIT, reqs, argc \- 1, NULL); |
367 | if (ret != 0) { | |
d1a71985 | 368 | fprintf(stderr, "getaddrinfo_a() failed: %s\en", |
e11d63b9 PB |
369 | gai_strerror(ret)); |
370 | exit(EXIT_FAILURE); | |
371 | } | |
fe5dba13 | 372 | \& |
b42296e4 | 373 | for (size_t i = 0; i < argc \- 1; i++) { |
e11d63b9 PB |
374 | printf("%s: ", reqs[i]\->ar_name); |
375 | ret = gai_error(reqs[i]); | |
376 | if (ret == 0) { | |
377 | res = reqs[i]\->ar_result; | |
fe5dba13 | 378 | \& |
e11d63b9 | 379 | ret = getnameinfo(res\->ai_addr, res\->ai_addrlen, |
d917c31d AC |
380 | host, sizeof(host), |
381 | NULL, 0, NI_NUMERICHOST); | |
e11d63b9 | 382 | if (ret != 0) { |
d1a71985 | 383 | fprintf(stderr, "getnameinfo() failed: %s\en", |
e11d63b9 PB |
384 | gai_strerror(ret)); |
385 | exit(EXIT_FAILURE); | |
386 | } | |
387 | puts(host); | |
fe5dba13 | 388 | \& |
e11d63b9 PB |
389 | } else { |
390 | puts(gai_strerror(ret)); | |
391 | } | |
392 | } | |
393 | exit(EXIT_SUCCESS); | |
394 | } | |
207050fa | 395 | .EE |
b0b6ab4e | 396 | .\" SRC END |
c634028a | 397 | .SS Asynchronous example |
e11d63b9 PB |
398 | This example shows a simple interactive |
399 | .BR getaddrinfo_a () | |
400 | front-end. | |
401 | The notification facility is not demonstrated. | |
402 | .PP | |
b084fc29 | 403 | An example session might look like this: |
e646a1ba | 404 | .PP |
e11d63b9 | 405 | .in +4n |
e646a1ba | 406 | .EX |
e11d63b9 | 407 | $ \fB./a.out\fP |
7f516900 | 408 | > a mirrors.kernel.org enoent.linuxfoundation.org gnu.org |
e11d63b9 | 409 | > c 2 |
a2feb3e1 | 410 | [2] gnu.org: Request not canceled |
e11d63b9 | 411 | > w 0 1 |
6de1d3a9 | 412 | [00] mirrors.kernel.org: Finished |
e11d63b9 | 413 | > l |
6de1d3a9 | 414 | [00] mirrors.kernel.org: 139.178.88.99 |
e11d63b9 | 415 | [01] enoent.linuxfoundation.org: Processing request in progress |
a2feb3e1 | 416 | [02] gnu.org: 209.51.188.116 |
e11d63b9 | 417 | > l |
6de1d3a9 | 418 | [00] mirrors.kernel.org: 139.178.88.99 |
e11d63b9 | 419 | [01] enoent.linuxfoundation.org: Name or service not known |
a2feb3e1 | 420 | [02] gnu.org: 209.51.188.116 |
b8302363 | 421 | .EE |
e11d63b9 PB |
422 | .in |
423 | .PP | |
71af708f | 424 | The program source is as follows: |
847e0d88 | 425 | .PP |
b0b6ab4e | 426 | .\" SRC BEGIN (async.c) |
207050fa | 427 | .EX |
e11d63b9 PB |
428 | #define _GNU_SOURCE |
429 | #include <netdb.h> | |
430 | #include <stdio.h> | |
431 | #include <stdlib.h> | |
432 | #include <string.h> | |
fe5dba13 | 433 | \& |
e11d63b9 | 434 | static struct gaicb **reqs = NULL; |
b42296e4 | 435 | static size_t nreqs = 0; |
fe5dba13 | 436 | \& |
e11d63b9 PB |
437 | static char * |
438 | getcmd(void) | |
439 | { | |
440 | static char buf[256]; | |
fe5dba13 | 441 | \& |
e11d63b9 PB |
442 | fputs("> ", stdout); fflush(stdout); |
443 | if (fgets(buf, sizeof(buf), stdin) == NULL) | |
444 | return NULL; | |
fe5dba13 | 445 | \& |
b957f81f | 446 | if (buf[strlen(buf) \- 1] == \[aq]\en\[aq]) |
e11d63b9 | 447 | buf[strlen(buf) \- 1] = 0; |
fe5dba13 | 448 | \& |
e11d63b9 PB |
449 | return buf; |
450 | } | |
fe5dba13 | 451 | \& |
c6beb8a1 | 452 | /* Add requests for specified hostnames. */ |
e11d63b9 PB |
453 | static void |
454 | add_requests(void) | |
455 | { | |
b42296e4 | 456 | size_t nreqs_base = nreqs; |
e11d63b9 PB |
457 | char *host; |
458 | int ret; | |
fe5dba13 | 459 | \& |
e11d63b9 PB |
460 | while ((host = strtok(NULL, " "))) { |
461 | nreqs++; | |
26499b04 | 462 | reqs = realloc(reqs, sizeof(reqs[0]) * nreqs); |
fe5dba13 | 463 | \& |
e11d63b9 PB |
464 | reqs[nreqs \- 1] = calloc(1, sizeof(*reqs[0])); |
465 | reqs[nreqs \- 1]\->ar_name = strdup(host); | |
466 | } | |
fe5dba13 | 467 | \& |
e11d63b9 | 468 | /* Queue nreqs_base..nreqs requests. */ |
fe5dba13 | 469 | \& |
e11d63b9 PB |
470 | ret = getaddrinfo_a(GAI_NOWAIT, &reqs[nreqs_base], |
471 | nreqs \- nreqs_base, NULL); | |
472 | if (ret) { | |
d1a71985 | 473 | fprintf(stderr, "getaddrinfo_a() failed: %s\en", |
e11d63b9 PB |
474 | gai_strerror(ret)); |
475 | exit(EXIT_FAILURE); | |
476 | } | |
477 | } | |
fe5dba13 | 478 | \& |
c6beb8a1 | 479 | /* Wait until at least one of specified requests completes. */ |
e11d63b9 PB |
480 | static void |
481 | wait_requests(void) | |
482 | { | |
483 | char *id; | |
b42296e4 AC |
484 | int ret; |
485 | size_t n; | |
e11d63b9 PB |
486 | struct gaicb const **wait_reqs = calloc(nreqs, sizeof(*wait_reqs)); |
487 | /* NULL elements are ignored by gai_suspend(). */ | |
fe5dba13 | 488 | \& |
e11d63b9 PB |
489 | while ((id = strtok(NULL, " ")) != NULL) { |
490 | n = atoi(id); | |
fe5dba13 | 491 | \& |
e11d63b9 | 492 | if (n >= nreqs) { |
d1a71985 | 493 | printf("Bad request number: %s\en", id); |
e11d63b9 PB |
494 | return; |
495 | } | |
fe5dba13 | 496 | \& |
e11d63b9 PB |
497 | wait_reqs[n] = reqs[n]; |
498 | } | |
fe5dba13 | 499 | \& |
e11d63b9 PB |
500 | ret = gai_suspend(wait_reqs, nreqs, NULL); |
501 | if (ret) { | |
d1a71985 | 502 | printf("gai_suspend(): %s\en", gai_strerror(ret)); |
e11d63b9 PB |
503 | return; |
504 | } | |
fe5dba13 | 505 | \& |
b42296e4 | 506 | for (size_t i = 0; i < nreqs; i++) { |
e11d63b9 PB |
507 | if (wait_reqs[i] == NULL) |
508 | continue; | |
fe5dba13 | 509 | \& |
e11d63b9 PB |
510 | ret = gai_error(reqs[i]); |
511 | if (ret == EAI_INPROGRESS) | |
512 | continue; | |
fe5dba13 | 513 | \& |
b42296e4 | 514 | printf("[%02zu] %s: %s\en", i, reqs[i]\->ar_name, |
e11d63b9 PB |
515 | ret == 0 ? "Finished" : gai_strerror(ret)); |
516 | } | |
517 | } | |
fe5dba13 | 518 | \& |
c6beb8a1 | 519 | /* Cancel specified requests. */ |
e11d63b9 PB |
520 | static void |
521 | cancel_requests(void) | |
522 | { | |
523 | char *id; | |
b42296e4 AC |
524 | int ret; |
525 | size_t n; | |
fe5dba13 | 526 | \& |
e11d63b9 PB |
527 | while ((id = strtok(NULL, " ")) != NULL) { |
528 | n = atoi(id); | |
fe5dba13 | 529 | \& |
e11d63b9 | 530 | if (n >= nreqs) { |
d1a71985 | 531 | printf("Bad request number: %s\en", id); |
e11d63b9 PB |
532 | return; |
533 | } | |
fe5dba13 | 534 | \& |
e11d63b9 | 535 | ret = gai_cancel(reqs[n]); |
d1a71985 | 536 | printf("[%s] %s: %s\en", id, reqs[atoi(id)]\->ar_name, |
e11d63b9 PB |
537 | gai_strerror(ret)); |
538 | } | |
539 | } | |
fe5dba13 | 540 | \& |
c6beb8a1 | 541 | /* List all requests. */ |
e11d63b9 PB |
542 | static void |
543 | list_requests(void) | |
544 | { | |
ec8b0003 | 545 | int ret; |
e11d63b9 PB |
546 | char host[NI_MAXHOST]; |
547 | struct addrinfo *res; | |
fe5dba13 | 548 | \& |
b42296e4 AC |
549 | for (size_t i = 0; i < nreqs; i++) { |
550 | printf("[%02zu] %s: ", i, reqs[i]\->ar_name); | |
e11d63b9 | 551 | ret = gai_error(reqs[i]); |
fe5dba13 | 552 | \& |
e11d63b9 PB |
553 | if (!ret) { |
554 | res = reqs[i]\->ar_result; | |
fe5dba13 | 555 | \& |
e11d63b9 PB |
556 | ret = getnameinfo(res\->ai_addr, res\->ai_addrlen, |
557 | host, sizeof(host), | |
558 | NULL, 0, NI_NUMERICHOST); | |
559 | if (ret) { | |
d1a71985 | 560 | fprintf(stderr, "getnameinfo() failed: %s\en", |
e11d63b9 PB |
561 | gai_strerror(ret)); |
562 | exit(EXIT_FAILURE); | |
563 | } | |
564 | puts(host); | |
565 | } else { | |
566 | puts(gai_strerror(ret)); | |
567 | } | |
568 | } | |
569 | } | |
fe5dba13 | 570 | \& |
e11d63b9 | 571 | int |
b32ffdf2 | 572 | main(void) |
e11d63b9 PB |
573 | { |
574 | char *cmdline; | |
575 | char *cmd; | |
fe5dba13 | 576 | \& |
e11d63b9 PB |
577 | while ((cmdline = getcmd()) != NULL) { |
578 | cmd = strtok(cmdline, " "); | |
fe5dba13 | 579 | \& |
e11d63b9 PB |
580 | if (cmd == NULL) { |
581 | list_requests(); | |
582 | } else { | |
583 | switch (cmd[0]) { | |
b957f81f | 584 | case \[aq]a\[aq]: |
e11d63b9 PB |
585 | add_requests(); |
586 | break; | |
b957f81f | 587 | case \[aq]w\[aq]: |
e11d63b9 PB |
588 | wait_requests(); |
589 | break; | |
b957f81f | 590 | case \[aq]c\[aq]: |
e11d63b9 PB |
591 | cancel_requests(); |
592 | break; | |
b957f81f | 593 | case \[aq]l\[aq]: |
e11d63b9 PB |
594 | list_requests(); |
595 | break; | |
596 | default: | |
d1a71985 | 597 | fprintf(stderr, "Bad command: %c\en", cmd[0]); |
e11d63b9 PB |
598 | break; |
599 | } | |
600 | } | |
601 | } | |
602 | exit(EXIT_SUCCESS); | |
603 | } | |
207050fa | 604 | .EE |
b0b6ab4e | 605 | .\" SRC END |
47297adb | 606 | .SH SEE ALSO |
e11d63b9 PB |
607 | .BR getaddrinfo (3), |
608 | .BR inet (3), | |
609 | .BR lio_listio (3), | |
610 | .BR hostname (7), | |
611 | .BR ip (7), | |
612 | .BR sigevent (7) |