diff options
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 104 |
1 files changed, 89 insertions, 15 deletions
diff --git a/src/process.c b/src/process.c index 066edbc83d6..372277a953d 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -276,6 +276,10 @@ static int read_process_output (Lisp_Object, int); | |||
| 276 | static void create_pty (Lisp_Object); | 276 | static void create_pty (Lisp_Object); |
| 277 | static void exec_sentinel (Lisp_Object, Lisp_Object); | 277 | static void exec_sentinel (Lisp_Object, Lisp_Object); |
| 278 | 278 | ||
| 279 | static Lisp_Object | ||
| 280 | network_lookup_address_info_1 (Lisp_Object host, const char *service, | ||
| 281 | struct addrinfo *hints, struct addrinfo **res); | ||
| 282 | |||
| 279 | /* Number of bits set in connect_wait_mask. */ | 283 | /* Number of bits set in connect_wait_mask. */ |
| 280 | static int num_pending_connects; | 284 | static int num_pending_connects; |
| 281 | 285 | ||
| @@ -4106,7 +4110,7 @@ usage: (make-network-process &rest ARGS) */) | |||
| 4106 | if (!NILP (host)) | 4110 | if (!NILP (host)) |
| 4107 | { | 4111 | { |
| 4108 | struct addrinfo *res, *lres; | 4112 | struct addrinfo *res, *lres; |
| 4109 | int ret; | 4113 | Lisp_Object msg; |
| 4110 | 4114 | ||
| 4111 | maybe_quit (); | 4115 | maybe_quit (); |
| 4112 | 4116 | ||
| @@ -4115,20 +4119,9 @@ usage: (make-network-process &rest ARGS) */) | |||
| 4115 | hints.ai_family = family; | 4119 | hints.ai_family = family; |
| 4116 | hints.ai_socktype = socktype; | 4120 | hints.ai_socktype = socktype; |
| 4117 | 4121 | ||
| 4118 | ret = getaddrinfo (SSDATA (host), portstring, &hints, &res); | 4122 | msg = network_lookup_address_info_1 (host, portstring, &hints, &res); |
| 4119 | if (ret) | 4123 | if (!EQ (msg, Qt)) |
| 4120 | #ifdef HAVE_GAI_STRERROR | 4124 | error ("%s", SSDATA (msg)); |
| 4121 | { | ||
| 4122 | synchronize_system_messages_locale (); | ||
| 4123 | char const *str = gai_strerror (ret); | ||
| 4124 | if (! NILP (Vlocale_coding_system)) | ||
| 4125 | str = SSDATA (code_convert_string_norecord | ||
| 4126 | (build_string (str), Vlocale_coding_system, 0)); | ||
| 4127 | error ("%s/%s %s", SSDATA (host), portstring, str); | ||
| 4128 | } | ||
| 4129 | #else | ||
| 4130 | error ("%s/%s getaddrinfo error %d", SSDATA (host), portstring, ret); | ||
| 4131 | #endif | ||
| 4132 | 4125 | ||
| 4133 | for (lres = res; lres; lres = lres->ai_next) | 4126 | for (lres = res; lres; lres = lres->ai_next) |
| 4134 | addrinfos = Fcons (conv_addrinfo_to_lisp (lres), addrinfos); | 4127 | addrinfos = Fcons (conv_addrinfo_to_lisp (lres), addrinfos); |
| @@ -4576,6 +4569,86 @@ Data that is unavailable is returned as nil. */) | |||
| 4576 | #endif | 4569 | #endif |
| 4577 | } | 4570 | } |
| 4578 | 4571 | ||
| 4572 | static Lisp_Object | ||
| 4573 | network_lookup_address_info_1 (Lisp_Object host, const char *service, | ||
| 4574 | struct addrinfo *hints, struct addrinfo **res) | ||
| 4575 | { | ||
| 4576 | Lisp_Object msg = Qt; | ||
| 4577 | int ret; | ||
| 4578 | |||
| 4579 | if (STRING_MULTIBYTE (host) && SBYTES (host) != SCHARS (host)) | ||
| 4580 | error ("Non-ASCII hostname %s detected, please use puny-encode-domain", | ||
| 4581 | SSDATA (host)); | ||
| 4582 | ret = getaddrinfo (SSDATA (host), service, hints, res); | ||
| 4583 | if (ret) | ||
| 4584 | { | ||
| 4585 | if (service == NULL) | ||
| 4586 | service = "0"; | ||
| 4587 | #ifdef HAVE_GAI_STRERROR | ||
| 4588 | synchronize_system_messages_locale (); | ||
| 4589 | char const *str = gai_strerror (ret); | ||
| 4590 | if (! NILP (Vlocale_coding_system)) | ||
| 4591 | str = SSDATA (code_convert_string_norecord | ||
| 4592 | (build_string (str), Vlocale_coding_system, 0)); | ||
| 4593 | AUTO_STRING (format, "%s/%s %s"); | ||
| 4594 | msg = CALLN (Fformat, format, host, build_string (service), | ||
| 4595 | build_string (str)); | ||
| 4596 | #else | ||
| 4597 | AUTO_STRING (format, "%s/%s getaddrinfo error %d"); | ||
| 4598 | msg = CALLN (Fformat, format, host, build_string (service), | ||
| 4599 | make_int (ret)); | ||
| 4600 | #endif | ||
| 4601 | } | ||
| 4602 | return msg; | ||
| 4603 | } | ||
| 4604 | |||
| 4605 | DEFUN ("network-lookup-address-info", Fnetwork_lookup_address_info, | ||
| 4606 | Snetwork_lookup_address_info, 1, 2, 0, | ||
| 4607 | doc: /* Look up ip address info of NAME. | ||
| 4608 | Optional parameter FAMILY controls whether to look up IPv4 or IPv6 | ||
| 4609 | addresses. The default of nil means both, symbol `ipv4' means IPv4 | ||
| 4610 | only, symbol `ipv6' means IPv6 only. Returns a list of addresses, or | ||
| 4611 | nil if none were found. Each address is a vector of integers. */) | ||
| 4612 | (Lisp_Object name, Lisp_Object family) | ||
| 4613 | { | ||
| 4614 | Lisp_Object addresses = Qnil; | ||
| 4615 | Lisp_Object msg = Qnil; | ||
| 4616 | |||
| 4617 | struct addrinfo *res, *lres; | ||
| 4618 | struct addrinfo hints; | ||
| 4619 | |||
| 4620 | memset (&hints, 0, sizeof hints); | ||
| 4621 | if (EQ (family, Qnil)) | ||
| 4622 | hints.ai_family = AF_UNSPEC; | ||
| 4623 | else if (EQ (family, Qipv4)) | ||
| 4624 | hints.ai_family = AF_INET; | ||
| 4625 | else if (EQ (family, Qipv6)) | ||
| 4626 | #ifdef AF_INET6 | ||
| 4627 | hints.ai_family = AF_INET6; | ||
| 4628 | #else | ||
| 4629 | /* If we don't support IPv6, querying will never work anyway */ | ||
| 4630 | return addresses; | ||
| 4631 | #endif | ||
| 4632 | else | ||
| 4633 | error ("Unsupported lookup type"); | ||
| 4634 | hints.ai_socktype = SOCK_DGRAM; | ||
| 4635 | |||
| 4636 | msg = network_lookup_address_info_1 (name, NULL, &hints, &res); | ||
| 4637 | if (!EQ (msg, Qt)) | ||
| 4638 | message ("%s", SSDATA(msg)); | ||
| 4639 | else | ||
| 4640 | { | ||
| 4641 | for (lres = res; lres; lres = lres->ai_next) | ||
| 4642 | addresses = Fcons (conv_sockaddr_to_lisp (lres->ai_addr, | ||
| 4643 | lres->ai_addrlen), | ||
| 4644 | addresses); | ||
| 4645 | addresses = Fnreverse (addresses); | ||
| 4646 | |||
| 4647 | freeaddrinfo (res); | ||
| 4648 | } | ||
| 4649 | return addresses; | ||
| 4650 | } | ||
| 4651 | |||
| 4579 | /* Turn off input and output for process PROC. */ | 4652 | /* Turn off input and output for process PROC. */ |
| 4580 | 4653 | ||
| 4581 | static void | 4654 | static void |
| @@ -8345,6 +8418,7 @@ returns non-`nil'. */); | |||
| 8345 | defsubr (&Sset_network_process_option); | 8418 | defsubr (&Sset_network_process_option); |
| 8346 | defsubr (&Smake_network_process); | 8419 | defsubr (&Smake_network_process); |
| 8347 | defsubr (&Sformat_network_address); | 8420 | defsubr (&Sformat_network_address); |
| 8421 | defsubr (&Snetwork_lookup_address_info); | ||
| 8348 | defsubr (&Snetwork_interface_list); | 8422 | defsubr (&Snetwork_interface_list); |
| 8349 | defsubr (&Snetwork_interface_info); | 8423 | defsubr (&Snetwork_interface_info); |
| 8350 | #ifdef DATAGRAM_SOCKETS | 8424 | #ifdef DATAGRAM_SOCKETS |