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