diff --git a/man3/gai_cancel.3 b/man3/gai_cancel.3 index ad2b899eb..1b0f392ae 100644 --- a/man3/gai_cancel.3 +++ b/man3/gai_cancel.3 @@ -1,606 +1 @@ -.\" Copyright (c) 2009 Petr Baudis -.\" and clean-ups and additions (C) 2010 Michael Kerrisk -.\" -.\" Permission is granted to make and distribute verbatim copies of this -.\" manual provided the copyright notice and this permission notice are -.\" preserved on all copies. -.\" -.\" Permission is granted to copy and distribute modified versions of this -.\" manual under the conditions for verbatim copying, provided that the -.\" entire resulting derived work is distributed under the terms of a -.\" permission notice identical to this one. -.\" -.\" Since the Linux kernel and libraries are constantly changing, this -.\" manual page may be incorrect or out-of-date. The author(s) assume no -.\" responsibility for errors or omissions, or for damages resulting from -.\" the use of the information contained herein. The author(s) may not -.\" have taken the same level of care in the production of this manual, -.\" which is licensed free of charge, as they might when working -.\" professionally. -.\" -.\" Formatted or processed versions of this manual, if unaccompanied by -.\" the source, must acknowledge the copyright and authors of this work. -.\" -.\" References: http://people.redhat.com/drepper/asynchnl.pdf, -.\" http://www.imperialviolet.org/2005/06/01/asynchronous-dns-lookups-with-glibc.html -.\" -.TH GETADDRINFO_A 3 2010-09-27 "GNU" "Linux Programmer's Manual" -.SH NAME -getaddrinfo_a, gai_suspend, gai_error, gai_cancel \- asynchronous -network address and service translation -.SH SYNOPSIS -.nf -.B #define _GNU_SOURCE -.B #include -.sp -.BI "int getaddrinfo_a(int " "mode" ", struct gaicb *" "list[]" , -.BI " int " "nitems" ", struct sigevent *" "sevp" ); -.sp -.BI "int gai_suspend(struct gaicb *" "list[]" ", int " "nitems" , -.BI " struct timespec *" "timeout" ); -.sp -.BI "int gai_error(struct gaicb *" "req" ); -.sp -.BI "int gai_cancel(struct gaicb *" "req" ); -.sp -Link with \fI\-lanl\fP. -.fi -.SH DESCRIPTION -The -.BR getaddrinfo_a () -function performs the same task as -.BR getaddrinfo (3), -but allows multiple name look-ups to be performed asynchronously, -with optional notification on completion of look-up operations. - -The -.I mode -argument has one of the following values: -.TP -.B GAI_WAIT -Perform the look-ups synchronously; -the call blocks until the look-ups have completed. -.TP -.B GAI_NOWAIT -Perform the look-ups asynchronously. -The call returns immediately, -and the requests are resolved in the background. -See the discussion of the -.I sevp -argument below. -.PP -The array -.I list -specifies the look-up requests to process. -The -.I nitems -argument specifies the number of elements in -.IR list . -The requested look-up operations are started in parallel. -NULL elements in -.I list -are ignored. -Each request is described by a -.I gaicb -structure, defined as follows: -.sp -.in +4n -.nf -struct gaicb { - const char *ar_name; - const char *ar_service; - const struct addrinfo *ar_request; - struct addrinfo *ar_result; -}; -.fi -.in - -The elements of this structure correspond to the arguments of -.BR getaddrinfo (3). -Thus, -.I ar_name -corresponds to the -.I node -argument and -.I ar_service -to the -.I service -argument, identifying an Internet host and a service. -The -.I ar_request -element corresponds to the -.I hints -argument, specifying the criteria for selecting -the returned socket address structures. -Finally, -.I ar_result -corresponds to the -.I res -argument; you do not need to initialize this element, -it will be automatically set when the request -is resolved. -The -.I addrinfo -structure referenced by the last two elements is described in -.BR getaddrinfo (3). - -When -.I mode -is specified as -.BR GAI_NOWAIT, -notifications about resolved requests -can be obtained by employing the -.I sigevent -structure pointed to by the -.I sevp -argument. -For the definition and general details of this structure, see -.BR sigevent (7). -The -.I sevp\->sigev_notify -field can have the following values: -.TP -.BR SIGEV_NONE -Don't provide any notification. -.TP -.BR SIGEV_SIGNAL -When a look-up completes, generate the signal -.I sigev_signo -for the process. -See -.BR sigevent (7) -for general details. -The -.I si_code -field of the -.I siginfo_t -structure will be set to -.BR SI_ASYNCNL . -.\" si_pid and si_uid are also set, to the values of the calling process, -.\" which doesn't provide useful information, so we'll skip mentioning it. -.TP -.BR SIGEV_THREAD -When a look-up completes, invoke -.I sigev_notify_function -as if it were the start function of a new thread. -See -.BR sigevent (7) -for details. -.PP -For -.BR SIGEV_SIGNAL -and -.BR SIGEV_THREAD , -it may be useful to point -.IR sevp\->sigev_value.sival_ptr -to -.IR list . - -The -.BR gai_suspend () -function suspends execution of the calling thread, -waiting for the completion of one or more requests in the array -.ID list . -The -.I nitems -argument specifies the size of the array -.IR list . -The call blocks until one of the following occurs: -.IP * 3 -One or more of the operations in -.I list -completes. -.IP * -The call is interrupted by a signal that is caught. -.IP * -The time interval specified in -.I timeout -elapses. -This argument specifies a timeout in seconds plus nanoseconds (see -.BR nanosleep (2) -for details of the -.I timespec -structure). -If -.I timeout -is NULL, then the call blocks indefinitely -(until one of the events above occurs). -.PP -No explicit indication of which request was completed is given; -you must determine which request(s) have completed by iterating with -.BR gai_error () -over the list of requests. - -The -.BR gai_error () -function returns the status of the request -.IR req : -either -.B EAI_INPROGRESS -if the request was not completed yet, -0 if it was handled successfully, -or an error code if the request could not be resolved. - -The -.BR gai_cancel () -function cancels the request -.IR req . -If the request has been canceled successfully, -the error status of the request will be set to -.B EAI_CANCELLED -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 -.BR gai_cancel () -has never been called. -If -.I req -is NULL, an attempt is made to cancel all outstanding requests -that the process has made. -.SH "RETURN VALUE" -The -.BR getaddrinfo_a () -function returns 0 if all of the requests have been enqueued successfully, -or one of the following nonzero error codes: -.TP -.B EAI_AGAIN -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. -.TP -.B EAI_MEMORY -Out of memory. -.TP -.B EAI_SYSTEM -.I mode -is invalid. -.PP -The -.BR gai_suspend () -function returns 0 if at least one of the listed requests has been completed. -Otherwise, it returns one of the following nonzero error codes: -.TP -.B EAI_AGAIN -The given timeout expired before any of the requests could be completed. -.TP -.B EAI_ALLDONE -There were no actual requests given to the function. -.TP -.B EAI_INTR -A signal has interrupted the function. -Note that this interruption might have been -caused by signal notification of some completed look-up request. -.PP -The -.BR gai_error () -function can return -.B EAI_INPROGRESS -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 -.BR getaddrinfo (3), -or the error code -.B EAI_CANCELLED -if the request has been canceled explicitly before it could be finished. - -The -.BR gai_cancel () -function can return one of these values: -.TP -.B EAI_CANCELLED -The request has been canceled successfully. -.TP -.B EAI_NOTCANCELLED -The request has not been canceled. -.TP -.B EAI_ALLDONE -The request has already completed. -.PP -The -.BR gai_strerror (3) -function translates these error codes to a human readable string, -suitable for error reporting. -.SH "CONFORMING TO" -These functions are GNU extensions; -they first appeared in glibc in version 2.2.3. -.SH NOTES -The interface of -.BR getaddrinfo_a () -was modeled after the -.BR lio_listio (3) -interface. -.SH EXAMPLE -Two examples are provided: a simple example that resolves -several requests in parallel synchronously, and a complex example -showing some of the asynchronous capabilities. -.SS Synchronous Example -The program below simply resolves several hostnames in parallel, -giving a speed-up compared to resolving the hostnames sequentially using -.BR getaddrinfo (3). -The program might be used like this: -.in +4n -.nf - -$ \fB./a.out ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz\fP -ftp.us.kernel.org: 128.30.2.36 -enoent.linuxfoundation.org: Name or service not known -gnu.cz: 87.236.197.13 -.fi -.in -.PP -Here is the program source code -.nf - -#define _GNU_SOURCE -#include -#include -#include -#include - -int -main(int argc, char *argv[]) -{ - int i, 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 (i = 0; i < argc \- 1; i++) { - reqs[i] = malloc(sizeof(*reqs[0])); - if (reqs[i] == NULL) { - perror("malloc"); - exit(EXIT_FAILURE); - } - 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 (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); -} -.fi - -.SS Asynchronous Example -This example shows a simple interactive -.BR getaddrinfo_a () -front-end. -The notification facility is not demonstrated. -.PP -An example session might look like like this: -.in +4n -.nf - -$ \fB./a.out\fP -> a ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz -> c 2 -[2] gnu.cz: Request not canceled -> w 0 1 -[00] ftp.us.kernel.org: Finished -> l -[00] ftp.us.kernel.org: 216.165.129.139 -[01] enoent.linuxfoundation.org: Processing request in progress -[02] gnu.cz: 87.236.197.13 -> l -[00] ftp.us.kernel.org: 216.165.129.139 -[01] enoent.linuxfoundation.org: Name or service not known -[02] gnu.cz: 87.236.197.13 -.fi -.in -.PP -The program source goes as follows: - -\& -.nf -#define _GNU_SOURCE -#include -#include -#include -#include - -static struct gaicb **reqs = NULL; -static int nreqs = 0; - -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] == \(aq\\n\(aq) - buf[strlen(buf) \- 1] = 0; - - return buf; -} - -/* Add requests for specified hostnames */ -static void -add_requests(void) -{ - int nreqs_base = nreqs; - char *host; - int ret; - - while ((host = strtok(NULL, " "))) { - nreqs++; - reqs = realloc(reqs, nreqs * sizeof(reqs[0])); - - reqs[nreqs \- 1] = calloc(1, sizeof(*reqs[0])); - 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 i, ret, n; - struct gaicb const **wait_reqs = calloc(nreqs, sizeof(*wait_reqs)); - /* 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 (i = 0; i < nreqs; i++) { - if (wait_reqs[i] == NULL) - continue; - - ret = gai_error(reqs[i]); - if (ret == EAI_INPROGRESS) - continue; - - printf("[%02d] %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, 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 i, ret; - char host[NI_MAXHOST]; - struct addrinfo *res; - - for (i = 0; i < nreqs; i++) { - printf("[%02d] %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(int argc, char *argv[]) -{ - char *cmdline; - char *cmd; - - while ((cmdline = getcmd()) != NULL) { - cmd = strtok(cmdline, " "); - - if (cmd == NULL) { - list_requests(); - } else { - switch (cmd[0]) { - case \(aqa\(aq: - add_requests(); - break; - case \(aqw\(aq: - wait_requests(); - break; - case \(aqc\(aq: - cancel_requests(); - break; - case \(aql\(aq: - list_requests(); - break; - default: - fprintf(stderr, "Bad command: %c\\n", cmd[0]); - break; - } - } - } - exit(EXIT_SUCCESS); -} -.fi -.SH "SEE ALSO" -.BR getaddrinfo (3), -.BR inet (3), -.BR lio_listio (3), -.BR hostname (7), -.BR ip (7), -.BR sigevent (7) +.so man3/getaddrinfo_a.3 diff --git a/man3/gai_error.3 b/man3/gai_error.3 index ad2b899eb..1b0f392ae 100644 --- a/man3/gai_error.3 +++ b/man3/gai_error.3 @@ -1,606 +1 @@ -.\" Copyright (c) 2009 Petr Baudis -.\" and clean-ups and additions (C) 2010 Michael Kerrisk -.\" -.\" Permission is granted to make and distribute verbatim copies of this -.\" manual provided the copyright notice and this permission notice are -.\" preserved on all copies. -.\" -.\" Permission is granted to copy and distribute modified versions of this -.\" manual under the conditions for verbatim copying, provided that the -.\" entire resulting derived work is distributed under the terms of a -.\" permission notice identical to this one. -.\" -.\" Since the Linux kernel and libraries are constantly changing, this -.\" manual page may be incorrect or out-of-date. The author(s) assume no -.\" responsibility for errors or omissions, or for damages resulting from -.\" the use of the information contained herein. The author(s) may not -.\" have taken the same level of care in the production of this manual, -.\" which is licensed free of charge, as they might when working -.\" professionally. -.\" -.\" Formatted or processed versions of this manual, if unaccompanied by -.\" the source, must acknowledge the copyright and authors of this work. -.\" -.\" References: http://people.redhat.com/drepper/asynchnl.pdf, -.\" http://www.imperialviolet.org/2005/06/01/asynchronous-dns-lookups-with-glibc.html -.\" -.TH GETADDRINFO_A 3 2010-09-27 "GNU" "Linux Programmer's Manual" -.SH NAME -getaddrinfo_a, gai_suspend, gai_error, gai_cancel \- asynchronous -network address and service translation -.SH SYNOPSIS -.nf -.B #define _GNU_SOURCE -.B #include -.sp -.BI "int getaddrinfo_a(int " "mode" ", struct gaicb *" "list[]" , -.BI " int " "nitems" ", struct sigevent *" "sevp" ); -.sp -.BI "int gai_suspend(struct gaicb *" "list[]" ", int " "nitems" , -.BI " struct timespec *" "timeout" ); -.sp -.BI "int gai_error(struct gaicb *" "req" ); -.sp -.BI "int gai_cancel(struct gaicb *" "req" ); -.sp -Link with \fI\-lanl\fP. -.fi -.SH DESCRIPTION -The -.BR getaddrinfo_a () -function performs the same task as -.BR getaddrinfo (3), -but allows multiple name look-ups to be performed asynchronously, -with optional notification on completion of look-up operations. - -The -.I mode -argument has one of the following values: -.TP -.B GAI_WAIT -Perform the look-ups synchronously; -the call blocks until the look-ups have completed. -.TP -.B GAI_NOWAIT -Perform the look-ups asynchronously. -The call returns immediately, -and the requests are resolved in the background. -See the discussion of the -.I sevp -argument below. -.PP -The array -.I list -specifies the look-up requests to process. -The -.I nitems -argument specifies the number of elements in -.IR list . -The requested look-up operations are started in parallel. -NULL elements in -.I list -are ignored. -Each request is described by a -.I gaicb -structure, defined as follows: -.sp -.in +4n -.nf -struct gaicb { - const char *ar_name; - const char *ar_service; - const struct addrinfo *ar_request; - struct addrinfo *ar_result; -}; -.fi -.in - -The elements of this structure correspond to the arguments of -.BR getaddrinfo (3). -Thus, -.I ar_name -corresponds to the -.I node -argument and -.I ar_service -to the -.I service -argument, identifying an Internet host and a service. -The -.I ar_request -element corresponds to the -.I hints -argument, specifying the criteria for selecting -the returned socket address structures. -Finally, -.I ar_result -corresponds to the -.I res -argument; you do not need to initialize this element, -it will be automatically set when the request -is resolved. -The -.I addrinfo -structure referenced by the last two elements is described in -.BR getaddrinfo (3). - -When -.I mode -is specified as -.BR GAI_NOWAIT, -notifications about resolved requests -can be obtained by employing the -.I sigevent -structure pointed to by the -.I sevp -argument. -For the definition and general details of this structure, see -.BR sigevent (7). -The -.I sevp\->sigev_notify -field can have the following values: -.TP -.BR SIGEV_NONE -Don't provide any notification. -.TP -.BR SIGEV_SIGNAL -When a look-up completes, generate the signal -.I sigev_signo -for the process. -See -.BR sigevent (7) -for general details. -The -.I si_code -field of the -.I siginfo_t -structure will be set to -.BR SI_ASYNCNL . -.\" si_pid and si_uid are also set, to the values of the calling process, -.\" which doesn't provide useful information, so we'll skip mentioning it. -.TP -.BR SIGEV_THREAD -When a look-up completes, invoke -.I sigev_notify_function -as if it were the start function of a new thread. -See -.BR sigevent (7) -for details. -.PP -For -.BR SIGEV_SIGNAL -and -.BR SIGEV_THREAD , -it may be useful to point -.IR sevp\->sigev_value.sival_ptr -to -.IR list . - -The -.BR gai_suspend () -function suspends execution of the calling thread, -waiting for the completion of one or more requests in the array -.ID list . -The -.I nitems -argument specifies the size of the array -.IR list . -The call blocks until one of the following occurs: -.IP * 3 -One or more of the operations in -.I list -completes. -.IP * -The call is interrupted by a signal that is caught. -.IP * -The time interval specified in -.I timeout -elapses. -This argument specifies a timeout in seconds plus nanoseconds (see -.BR nanosleep (2) -for details of the -.I timespec -structure). -If -.I timeout -is NULL, then the call blocks indefinitely -(until one of the events above occurs). -.PP -No explicit indication of which request was completed is given; -you must determine which request(s) have completed by iterating with -.BR gai_error () -over the list of requests. - -The -.BR gai_error () -function returns the status of the request -.IR req : -either -.B EAI_INPROGRESS -if the request was not completed yet, -0 if it was handled successfully, -or an error code if the request could not be resolved. - -The -.BR gai_cancel () -function cancels the request -.IR req . -If the request has been canceled successfully, -the error status of the request will be set to -.B EAI_CANCELLED -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 -.BR gai_cancel () -has never been called. -If -.I req -is NULL, an attempt is made to cancel all outstanding requests -that the process has made. -.SH "RETURN VALUE" -The -.BR getaddrinfo_a () -function returns 0 if all of the requests have been enqueued successfully, -or one of the following nonzero error codes: -.TP -.B EAI_AGAIN -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. -.TP -.B EAI_MEMORY -Out of memory. -.TP -.B EAI_SYSTEM -.I mode -is invalid. -.PP -The -.BR gai_suspend () -function returns 0 if at least one of the listed requests has been completed. -Otherwise, it returns one of the following nonzero error codes: -.TP -.B EAI_AGAIN -The given timeout expired before any of the requests could be completed. -.TP -.B EAI_ALLDONE -There were no actual requests given to the function. -.TP -.B EAI_INTR -A signal has interrupted the function. -Note that this interruption might have been -caused by signal notification of some completed look-up request. -.PP -The -.BR gai_error () -function can return -.B EAI_INPROGRESS -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 -.BR getaddrinfo (3), -or the error code -.B EAI_CANCELLED -if the request has been canceled explicitly before it could be finished. - -The -.BR gai_cancel () -function can return one of these values: -.TP -.B EAI_CANCELLED -The request has been canceled successfully. -.TP -.B EAI_NOTCANCELLED -The request has not been canceled. -.TP -.B EAI_ALLDONE -The request has already completed. -.PP -The -.BR gai_strerror (3) -function translates these error codes to a human readable string, -suitable for error reporting. -.SH "CONFORMING TO" -These functions are GNU extensions; -they first appeared in glibc in version 2.2.3. -.SH NOTES -The interface of -.BR getaddrinfo_a () -was modeled after the -.BR lio_listio (3) -interface. -.SH EXAMPLE -Two examples are provided: a simple example that resolves -several requests in parallel synchronously, and a complex example -showing some of the asynchronous capabilities. -.SS Synchronous Example -The program below simply resolves several hostnames in parallel, -giving a speed-up compared to resolving the hostnames sequentially using -.BR getaddrinfo (3). -The program might be used like this: -.in +4n -.nf - -$ \fB./a.out ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz\fP -ftp.us.kernel.org: 128.30.2.36 -enoent.linuxfoundation.org: Name or service not known -gnu.cz: 87.236.197.13 -.fi -.in -.PP -Here is the program source code -.nf - -#define _GNU_SOURCE -#include -#include -#include -#include - -int -main(int argc, char *argv[]) -{ - int i, 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 (i = 0; i < argc \- 1; i++) { - reqs[i] = malloc(sizeof(*reqs[0])); - if (reqs[i] == NULL) { - perror("malloc"); - exit(EXIT_FAILURE); - } - 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 (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); -} -.fi - -.SS Asynchronous Example -This example shows a simple interactive -.BR getaddrinfo_a () -front-end. -The notification facility is not demonstrated. -.PP -An example session might look like like this: -.in +4n -.nf - -$ \fB./a.out\fP -> a ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz -> c 2 -[2] gnu.cz: Request not canceled -> w 0 1 -[00] ftp.us.kernel.org: Finished -> l -[00] ftp.us.kernel.org: 216.165.129.139 -[01] enoent.linuxfoundation.org: Processing request in progress -[02] gnu.cz: 87.236.197.13 -> l -[00] ftp.us.kernel.org: 216.165.129.139 -[01] enoent.linuxfoundation.org: Name or service not known -[02] gnu.cz: 87.236.197.13 -.fi -.in -.PP -The program source goes as follows: - -\& -.nf -#define _GNU_SOURCE -#include -#include -#include -#include - -static struct gaicb **reqs = NULL; -static int nreqs = 0; - -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] == \(aq\\n\(aq) - buf[strlen(buf) \- 1] = 0; - - return buf; -} - -/* Add requests for specified hostnames */ -static void -add_requests(void) -{ - int nreqs_base = nreqs; - char *host; - int ret; - - while ((host = strtok(NULL, " "))) { - nreqs++; - reqs = realloc(reqs, nreqs * sizeof(reqs[0])); - - reqs[nreqs \- 1] = calloc(1, sizeof(*reqs[0])); - 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 i, ret, n; - struct gaicb const **wait_reqs = calloc(nreqs, sizeof(*wait_reqs)); - /* 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 (i = 0; i < nreqs; i++) { - if (wait_reqs[i] == NULL) - continue; - - ret = gai_error(reqs[i]); - if (ret == EAI_INPROGRESS) - continue; - - printf("[%02d] %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, 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 i, ret; - char host[NI_MAXHOST]; - struct addrinfo *res; - - for (i = 0; i < nreqs; i++) { - printf("[%02d] %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(int argc, char *argv[]) -{ - char *cmdline; - char *cmd; - - while ((cmdline = getcmd()) != NULL) { - cmd = strtok(cmdline, " "); - - if (cmd == NULL) { - list_requests(); - } else { - switch (cmd[0]) { - case \(aqa\(aq: - add_requests(); - break; - case \(aqw\(aq: - wait_requests(); - break; - case \(aqc\(aq: - cancel_requests(); - break; - case \(aql\(aq: - list_requests(); - break; - default: - fprintf(stderr, "Bad command: %c\\n", cmd[0]); - break; - } - } - } - exit(EXIT_SUCCESS); -} -.fi -.SH "SEE ALSO" -.BR getaddrinfo (3), -.BR inet (3), -.BR lio_listio (3), -.BR hostname (7), -.BR ip (7), -.BR sigevent (7) +.so man3/getaddrinfo_a.3 diff --git a/man3/gai_suspend.3 b/man3/gai_suspend.3 index ad2b899eb..1b0f392ae 100644 --- a/man3/gai_suspend.3 +++ b/man3/gai_suspend.3 @@ -1,606 +1 @@ -.\" Copyright (c) 2009 Petr Baudis -.\" and clean-ups and additions (C) 2010 Michael Kerrisk -.\" -.\" Permission is granted to make and distribute verbatim copies of this -.\" manual provided the copyright notice and this permission notice are -.\" preserved on all copies. -.\" -.\" Permission is granted to copy and distribute modified versions of this -.\" manual under the conditions for verbatim copying, provided that the -.\" entire resulting derived work is distributed under the terms of a -.\" permission notice identical to this one. -.\" -.\" Since the Linux kernel and libraries are constantly changing, this -.\" manual page may be incorrect or out-of-date. The author(s) assume no -.\" responsibility for errors or omissions, or for damages resulting from -.\" the use of the information contained herein. The author(s) may not -.\" have taken the same level of care in the production of this manual, -.\" which is licensed free of charge, as they might when working -.\" professionally. -.\" -.\" Formatted or processed versions of this manual, if unaccompanied by -.\" the source, must acknowledge the copyright and authors of this work. -.\" -.\" References: http://people.redhat.com/drepper/asynchnl.pdf, -.\" http://www.imperialviolet.org/2005/06/01/asynchronous-dns-lookups-with-glibc.html -.\" -.TH GETADDRINFO_A 3 2010-09-27 "GNU" "Linux Programmer's Manual" -.SH NAME -getaddrinfo_a, gai_suspend, gai_error, gai_cancel \- asynchronous -network address and service translation -.SH SYNOPSIS -.nf -.B #define _GNU_SOURCE -.B #include -.sp -.BI "int getaddrinfo_a(int " "mode" ", struct gaicb *" "list[]" , -.BI " int " "nitems" ", struct sigevent *" "sevp" ); -.sp -.BI "int gai_suspend(struct gaicb *" "list[]" ", int " "nitems" , -.BI " struct timespec *" "timeout" ); -.sp -.BI "int gai_error(struct gaicb *" "req" ); -.sp -.BI "int gai_cancel(struct gaicb *" "req" ); -.sp -Link with \fI\-lanl\fP. -.fi -.SH DESCRIPTION -The -.BR getaddrinfo_a () -function performs the same task as -.BR getaddrinfo (3), -but allows multiple name look-ups to be performed asynchronously, -with optional notification on completion of look-up operations. - -The -.I mode -argument has one of the following values: -.TP -.B GAI_WAIT -Perform the look-ups synchronously; -the call blocks until the look-ups have completed. -.TP -.B GAI_NOWAIT -Perform the look-ups asynchronously. -The call returns immediately, -and the requests are resolved in the background. -See the discussion of the -.I sevp -argument below. -.PP -The array -.I list -specifies the look-up requests to process. -The -.I nitems -argument specifies the number of elements in -.IR list . -The requested look-up operations are started in parallel. -NULL elements in -.I list -are ignored. -Each request is described by a -.I gaicb -structure, defined as follows: -.sp -.in +4n -.nf -struct gaicb { - const char *ar_name; - const char *ar_service; - const struct addrinfo *ar_request; - struct addrinfo *ar_result; -}; -.fi -.in - -The elements of this structure correspond to the arguments of -.BR getaddrinfo (3). -Thus, -.I ar_name -corresponds to the -.I node -argument and -.I ar_service -to the -.I service -argument, identifying an Internet host and a service. -The -.I ar_request -element corresponds to the -.I hints -argument, specifying the criteria for selecting -the returned socket address structures. -Finally, -.I ar_result -corresponds to the -.I res -argument; you do not need to initialize this element, -it will be automatically set when the request -is resolved. -The -.I addrinfo -structure referenced by the last two elements is described in -.BR getaddrinfo (3). - -When -.I mode -is specified as -.BR GAI_NOWAIT, -notifications about resolved requests -can be obtained by employing the -.I sigevent -structure pointed to by the -.I sevp -argument. -For the definition and general details of this structure, see -.BR sigevent (7). -The -.I sevp\->sigev_notify -field can have the following values: -.TP -.BR SIGEV_NONE -Don't provide any notification. -.TP -.BR SIGEV_SIGNAL -When a look-up completes, generate the signal -.I sigev_signo -for the process. -See -.BR sigevent (7) -for general details. -The -.I si_code -field of the -.I siginfo_t -structure will be set to -.BR SI_ASYNCNL . -.\" si_pid and si_uid are also set, to the values of the calling process, -.\" which doesn't provide useful information, so we'll skip mentioning it. -.TP -.BR SIGEV_THREAD -When a look-up completes, invoke -.I sigev_notify_function -as if it were the start function of a new thread. -See -.BR sigevent (7) -for details. -.PP -For -.BR SIGEV_SIGNAL -and -.BR SIGEV_THREAD , -it may be useful to point -.IR sevp\->sigev_value.sival_ptr -to -.IR list . - -The -.BR gai_suspend () -function suspends execution of the calling thread, -waiting for the completion of one or more requests in the array -.ID list . -The -.I nitems -argument specifies the size of the array -.IR list . -The call blocks until one of the following occurs: -.IP * 3 -One or more of the operations in -.I list -completes. -.IP * -The call is interrupted by a signal that is caught. -.IP * -The time interval specified in -.I timeout -elapses. -This argument specifies a timeout in seconds plus nanoseconds (see -.BR nanosleep (2) -for details of the -.I timespec -structure). -If -.I timeout -is NULL, then the call blocks indefinitely -(until one of the events above occurs). -.PP -No explicit indication of which request was completed is given; -you must determine which request(s) have completed by iterating with -.BR gai_error () -over the list of requests. - -The -.BR gai_error () -function returns the status of the request -.IR req : -either -.B EAI_INPROGRESS -if the request was not completed yet, -0 if it was handled successfully, -or an error code if the request could not be resolved. - -The -.BR gai_cancel () -function cancels the request -.IR req . -If the request has been canceled successfully, -the error status of the request will be set to -.B EAI_CANCELLED -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 -.BR gai_cancel () -has never been called. -If -.I req -is NULL, an attempt is made to cancel all outstanding requests -that the process has made. -.SH "RETURN VALUE" -The -.BR getaddrinfo_a () -function returns 0 if all of the requests have been enqueued successfully, -or one of the following nonzero error codes: -.TP -.B EAI_AGAIN -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. -.TP -.B EAI_MEMORY -Out of memory. -.TP -.B EAI_SYSTEM -.I mode -is invalid. -.PP -The -.BR gai_suspend () -function returns 0 if at least one of the listed requests has been completed. -Otherwise, it returns one of the following nonzero error codes: -.TP -.B EAI_AGAIN -The given timeout expired before any of the requests could be completed. -.TP -.B EAI_ALLDONE -There were no actual requests given to the function. -.TP -.B EAI_INTR -A signal has interrupted the function. -Note that this interruption might have been -caused by signal notification of some completed look-up request. -.PP -The -.BR gai_error () -function can return -.B EAI_INPROGRESS -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 -.BR getaddrinfo (3), -or the error code -.B EAI_CANCELLED -if the request has been canceled explicitly before it could be finished. - -The -.BR gai_cancel () -function can return one of these values: -.TP -.B EAI_CANCELLED -The request has been canceled successfully. -.TP -.B EAI_NOTCANCELLED -The request has not been canceled. -.TP -.B EAI_ALLDONE -The request has already completed. -.PP -The -.BR gai_strerror (3) -function translates these error codes to a human readable string, -suitable for error reporting. -.SH "CONFORMING TO" -These functions are GNU extensions; -they first appeared in glibc in version 2.2.3. -.SH NOTES -The interface of -.BR getaddrinfo_a () -was modeled after the -.BR lio_listio (3) -interface. -.SH EXAMPLE -Two examples are provided: a simple example that resolves -several requests in parallel synchronously, and a complex example -showing some of the asynchronous capabilities. -.SS Synchronous Example -The program below simply resolves several hostnames in parallel, -giving a speed-up compared to resolving the hostnames sequentially using -.BR getaddrinfo (3). -The program might be used like this: -.in +4n -.nf - -$ \fB./a.out ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz\fP -ftp.us.kernel.org: 128.30.2.36 -enoent.linuxfoundation.org: Name or service not known -gnu.cz: 87.236.197.13 -.fi -.in -.PP -Here is the program source code -.nf - -#define _GNU_SOURCE -#include -#include -#include -#include - -int -main(int argc, char *argv[]) -{ - int i, 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 (i = 0; i < argc \- 1; i++) { - reqs[i] = malloc(sizeof(*reqs[0])); - if (reqs[i] == NULL) { - perror("malloc"); - exit(EXIT_FAILURE); - } - 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 (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); -} -.fi - -.SS Asynchronous Example -This example shows a simple interactive -.BR getaddrinfo_a () -front-end. -The notification facility is not demonstrated. -.PP -An example session might look like like this: -.in +4n -.nf - -$ \fB./a.out\fP -> a ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz -> c 2 -[2] gnu.cz: Request not canceled -> w 0 1 -[00] ftp.us.kernel.org: Finished -> l -[00] ftp.us.kernel.org: 216.165.129.139 -[01] enoent.linuxfoundation.org: Processing request in progress -[02] gnu.cz: 87.236.197.13 -> l -[00] ftp.us.kernel.org: 216.165.129.139 -[01] enoent.linuxfoundation.org: Name or service not known -[02] gnu.cz: 87.236.197.13 -.fi -.in -.PP -The program source goes as follows: - -\& -.nf -#define _GNU_SOURCE -#include -#include -#include -#include - -static struct gaicb **reqs = NULL; -static int nreqs = 0; - -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] == \(aq\\n\(aq) - buf[strlen(buf) \- 1] = 0; - - return buf; -} - -/* Add requests for specified hostnames */ -static void -add_requests(void) -{ - int nreqs_base = nreqs; - char *host; - int ret; - - while ((host = strtok(NULL, " "))) { - nreqs++; - reqs = realloc(reqs, nreqs * sizeof(reqs[0])); - - reqs[nreqs \- 1] = calloc(1, sizeof(*reqs[0])); - 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 i, ret, n; - struct gaicb const **wait_reqs = calloc(nreqs, sizeof(*wait_reqs)); - /* 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 (i = 0; i < nreqs; i++) { - if (wait_reqs[i] == NULL) - continue; - - ret = gai_error(reqs[i]); - if (ret == EAI_INPROGRESS) - continue; - - printf("[%02d] %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, 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 i, ret; - char host[NI_MAXHOST]; - struct addrinfo *res; - - for (i = 0; i < nreqs; i++) { - printf("[%02d] %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(int argc, char *argv[]) -{ - char *cmdline; - char *cmd; - - while ((cmdline = getcmd()) != NULL) { - cmd = strtok(cmdline, " "); - - if (cmd == NULL) { - list_requests(); - } else { - switch (cmd[0]) { - case \(aqa\(aq: - add_requests(); - break; - case \(aqw\(aq: - wait_requests(); - break; - case \(aqc\(aq: - cancel_requests(); - break; - case \(aql\(aq: - list_requests(); - break; - default: - fprintf(stderr, "Bad command: %c\\n", cmd[0]); - break; - } - } - } - exit(EXIT_SUCCESS); -} -.fi -.SH "SEE ALSO" -.BR getaddrinfo (3), -.BR inet (3), -.BR lio_listio (3), -.BR hostname (7), -.BR ip (7), -.BR sigevent (7) +.so man3/getaddrinfo_a.3