getaddrinfo_a(3) Library Functions Manual getaddrinfo_a(3) getaddrinfo_a, gai_suspend, gai_error, gai_cancel - (libanl, -lanl) #define _GNU_SOURCE /* feature_test_macros(7) */ #include int getaddrinfo_a(int mode, struct gaicb *list[restrict n], int n, struct sigevent *restrict sevp); int gai_suspend(const struct gaicb *const list[n], int n, const struct timespec *timeout); int gai_error(struct gaicb *req); int gai_cancel(struct gaicb *req); getaddrinfo_a() getaddrinfo(3) . mode : GAI_WAIT . . GAI_NOWAIT . . sevp . list . n list. . NULL list. gaicb : struct gaicb { const char *ar_name; const char *ar_service; const struct addrinfo *ar_request; struct addrinfo *ar_result; }; getaddrinfo(3). ar_name node ar_service service . ar_request hints . ar_result res . addrinfo getaddrinfo(3). mode GAI_NOWAIT sigevent sevp. sigevent(3type). sevp->sigev_notify : SIGEV_NONE . SIGEV_SIGNAL sigev_signo . sigevent(3type) . si_code siginfo_t SI_ASYNCNL. SIGEV_THREAD sigev_notify_function . sigevent(3type) . SIGEV_SIGNAL SIGEV_THREAD sevp->sigev_value.sival_ptr list. gai_suspend() list. n list. : o list. o . o timeout. ( nanosleep(2) timespec). timeout NULL ( ). gai_error() . gai_error() req: EAI_INPROGRESS 0 . gai_cancel() req. EAI_CANCELED . gai_cancel() . req NULL . getaddrinfo_a() 0 : EAI_AGAIN . . EAI_MEMORY . EAI_SYSTEM mode . gai_suspend() 0 . : EAI_AGAIN . EAI_ALLDONE . EAI_INTR . . gai_error() EAI_INPROGRESS 0 ( ) getaddrinfo(3) EAI_CANCELED . gai_cancel() : EAI_CANCELED . EAI_NOTCANCELED . EAI_ALLDONE . gai_strerror(3) . attributes(7). +------------+------------------------------------+--------------------+ || | | +------------+------------------------------------+--------------------+ |getaddrinfo_a(),| | MT-Safe | |gai_suspend(),| | | |gai_error(),| | | |gai_cancel()| | | +------------+------------------------------------+--------------------+ GNU. glibc 2.2.3. getaddrinfo_a() lio_listio(3). : . getaddrinfo(3). : $ ./a.out mirrors.kernel.org enoent.linuxfoundation.org gnu.org; mirrors.kernel.org: 139.178.88.99 enoent.linuxfoundation.org: Name or service not known gnu.org: 209.51.188.116 #define _GNU_SOURCE #include #include #include #include #include #define MALLOC(n, type) ((type *) reallocarray(NULL, n, sizeof(type))) int main(int argc, char *argv[]) { int ret; struct gaicb *reqs[argc - 1]; char host[NI_MAXHOST]; struct addrinfo *res; if (argc < 2) { fprintf(stderr, "Usage: %s HOST...\n", argv[0]); exit(EXIT_FAILURE); } for (size_t i = 0; i < argc - 1; i++) { reqs[i] = MALLOC(1, struct gaicb); if (reqs[i] == NULL) err(EXIT_FAILURE, "malloc"); memset(reqs[i], 0, sizeof(*reqs[0])); reqs[i]->ar_name = argv[i + 1]; } ret = getaddrinfo_a(GAI_WAIT, reqs, argc - 1, NULL); if (ret != 0) { fprintf(stderr, "getaddrinfo_a() failed: %s\n", gai_strerror(ret)); exit(EXIT_FAILURE); } for (size_t i = 0; i < argc - 1; i++) { printf("%s: ", reqs[i]->ar_name); ret = gai_error(reqs[i]); if (ret == 0) { res = reqs[i]->ar_result; ret = getnameinfo(res->ai_addr, res->ai_addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST); if (ret != 0) { fprintf(stderr, "getnameinfo() failed: %s\n", gai_strerror(ret)); exit(EXIT_FAILURE); } puts(host); } else { puts(gai_strerror(ret)); } } exit(EXIT_SUCCESS); } getaddrinfo_a(). . : $ ./a.out; > a mirrors.kernel.org enoent.linuxfoundation.org gnu.org > c 2 [2] gnu.org: Request not canceled > w 0 1 [00] mirrors.kernel.org: Finished > l [00] mirrors.kernel.org: 139.178.88.99 [01] enoent.linuxfoundation.org: Processing request in progress [02] gnu.org: 209.51.188.116 > l [00] mirrors.kernel.org: 139.178.88.99 [01] enoent.linuxfoundation.org: Name or service not known [02] gnu.org: 209.51.188.116 : #define _GNU_SOURCE #include #include #include #include #include #include #define CALLOC(n, type) ((type *) calloc(n, sizeof(type))) #define REALLOCF(ptr, n, type) \ ({ \ static_assert(__builtin_types_compatible_p(typeof(ptr), type *)); \ \ (type *) reallocarrayf(ptr, n, sizeof(type)); \ }) static struct gaicb **reqs = NULL; static size_t nreqs = 0; static inline void * reallocarrayf(void *p, size_t n, size_t size) { void *q; q = reallocarray(p, n, size); if (q == NULL && n != 0 && size != 0) free(p); return q; } static char * getcmd(void) { static char buf[256]; fputs("> ", stdout); fflush(stdout); if (fgets(buf, sizeof(buf), stdin) == NULL) return NULL; if (buf[strlen(buf) - 1] == '\n') buf[strlen(buf) - 1] = 0; return buf; } /* Add requests for specified hostnames. */ static void add_requests(void) { size_t nreqs_base = nreqs; char *host; int ret; while ((host = strtok(NULL, " "))) { nreqs++; reqs = REALLOCF(reqs, nreqs, struct gaicb *); if (reqs == NULL) err(EXIT_FAILURE, "reallocf"); reqs[nreqs - 1] = CALLOC(1, struct gaicb); if (reqs[nreqs - 1] == NULL) err(EXIT_FAILURE, "calloc"); reqs[nreqs - 1]->ar_name = strdup(host); } /* Queue nreqs_base..nreqs requests. */ ret = getaddrinfo_a(GAI_NOWAIT, &reqs[nreqs_base], nreqs - nreqs_base, NULL); if (ret) { fprintf(stderr, "getaddrinfo_a() failed: %s\n", gai_strerror(ret)); exit(EXIT_FAILURE); } } /* Wait until at least one of specified requests completes. */ static void wait_requests(void) { char *id; int ret; size_t n; struct gaicb const **wait_reqs; wait_reqs = CALLOC(nreqs, const struct gaicb *); if (wait_reqs == NULL) err(EXIT_FAILURE, "calloc"); /* NULL elements are ignored by gai_suspend(). */ while ((id = strtok(NULL, " ")) != NULL) { n = atoi(id); if (n >= nreqs) { printf("Bad request number: %s\n", id); return; } wait_reqs[n] = reqs[n]; } ret = gai_suspend(wait_reqs, nreqs, NULL); if (ret) { printf("gai_suspend(): %s\n", gai_strerror(ret)); return; } for (size_t i = 0; i < nreqs; i++) { if (wait_reqs[i] == NULL) continue; ret = gai_error(reqs[i]); if (ret == EAI_INPROGRESS) continue; printf("[%02zu] %s: %s\n", i, reqs[i]->ar_name, ret == 0 ? "Finished" : gai_strerror(ret)); } } /* Cancel specified requests. */ static void cancel_requests(void) { char *id; int ret; size_t n; while ((id = strtok(NULL, " ")) != NULL) { n = atoi(id); if (n >= nreqs) { printf("Bad request number: %s\n", id); return; } ret = gai_cancel(reqs[n]); printf("[%s] %s: %s\n", id, reqs[atoi(id)]->ar_name, gai_strerror(ret)); } } /* List all requests. */ static void list_requests(void) { int ret; char host[NI_MAXHOST]; struct addrinfo *res; for (size_t i = 0; i < nreqs; i++) { printf("[%02zu] %s: ", i, reqs[i]->ar_name); ret = gai_error(reqs[i]); if (!ret) { res = reqs[i]->ar_result; ret = getnameinfo(res->ai_addr, res->ai_addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST); if (ret) { fprintf(stderr, "getnameinfo() failed: %s\n", gai_strerror(ret)); exit(EXIT_FAILURE); } puts(host); } else { puts(gai_strerror(ret)); } } } int main(void) { char *cmdline; char *cmd; while ((cmdline = getcmd()) != NULL) { cmd = strtok(cmdline, " "); if (cmd == NULL) { list_requests(); } else { switch (cmd[0]) { case 'a': add_requests(); break; case 'w': wait_requests(); break; case 'c': cancel_requests(); break; case 'l': list_requests(); break; default: fprintf(stderr, "Bad command: %c\n", cmd[0]); break; } } } exit(EXIT_SUCCESS); } getaddrinfo(3), inet(3), lio_listio(3), hostname(7), ip(7), sigevent(3type) 3 . . : . 6.18 8 2026 getaddrinfo_a(3)