struct timespec *, void *);
#endif
-/* Work around GCC 4.7.0 bug with strict overflow checking; see
+/* Work around GCC 4.3.0 bug with strict overflow checking; see
<http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>.
This bug appears to be fixed in GCC 5.1, so don't work around it there. */
-#if __GNUC__ == 4 && __GNUC_MINOR__ >= 3
+#if GNUC_PREREQ (4, 3, 0) && ! GNUC_PREREQ (5, 1, 0)
# pragma GCC diagnostic ignored "-Wstrict-overflow"
#endif
\f
#ifndef SOCK_CLOEXEC
# define SOCK_CLOEXEC 0
#endif
+#ifndef SOCK_NONBLOCK
+# define SOCK_NONBLOCK 0
+#endif
/* True if ERRNUM represents an error where the system call would
block if a blocking variant were used. */
XPROCESS (proc)->infd >= 0 && \
datagram_address[XPROCESS (proc)->infd].sa != 0)
#else
-#define DATAGRAM_CHAN_P(chan) (0)
#define DATAGRAM_CONN_P(proc) (0)
#endif
and store them individually through the three pointers. */
static void
-decode_status (Lisp_Object l, Lisp_Object *symbol, int *code, bool *coredump)
+decode_status (Lisp_Object l, Lisp_Object *symbol, Lisp_Object *code,
+ bool *coredump)
{
Lisp_Object tem;
if (SYMBOLP (l))
{
*symbol = l;
- *code = 0;
+ *code = make_number (0);
*coredump = 0;
}
else
{
*symbol = XCAR (l);
tem = XCDR (l);
- *code = XFASTINT (XCAR (tem));
+ *code = XCAR (tem);
tem = XCDR (tem);
*coredump = !NILP (tem);
}
status_message (struct Lisp_Process *p)
{
Lisp_Object status = p->status;
- Lisp_Object symbol;
- int code;
+ Lisp_Object symbol, code;
bool coredump;
Lisp_Object string;
{
char const *signame;
synchronize_system_messages_locale ();
- signame = strsignal (code);
+ signame = strsignal (XFASTINT (code));
if (signame == 0)
string = build_string ("unknown");
else
else if (EQ (symbol, Qexit))
{
if (NETCONN1_P (p))
- return build_string (code == 0 ? "deleted\n" : "connection broken by remote peer\n");
- if (code == 0)
+ return build_string (XFASTINT (code) == 0
+ ? "deleted\n"
+ : "connection broken by remote peer\n");
+ if (XFASTINT (code) == 0)
return build_string ("finished\n");
AUTO_STRING (prefix, "exited abnormally with code ");
- string = Fnumber_to_string (make_number (code));
+ string = Fnumber_to_string (code);
AUTO_STRING (suffix, coredump ? " (core dumped)\n" : "\n");
return concat3 (prefix, string, suffix);
}
else if (EQ (symbol, Qfailed))
{
- AUTO_STRING (prefix, "failed with code ");
- string = Fnumber_to_string (make_number (code));
- AUTO_STRING (suffix, "\n");
- return concat3 (prefix, string, suffix);
+ AUTO_STRING (format, "failed with code %s\n");
+ return CALLN (Fformat, format, code);
}
else
return Fcopy_sequence (Fsymbol_name (symbol));
return address;
}
+/* Convert an internal struct addrinfo to a Lisp object. */
+
+static Lisp_Object
+conv_addrinfo_to_lisp (struct addrinfo *res)
+{
+ Lisp_Object protocol = make_number (res->ai_protocol);
+ eassert (XINT (protocol) == res->ai_protocol);
+ return Fcons (protocol, conv_sockaddr_to_lisp (res->ai_addr, res->ai_addrlen));
+}
+
/* Get family and required size for sockaddr structure to hold ADDRESS. */
#endif
static void
-connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses,
+connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
Lisp_Object use_external_socket_p)
{
ptrdiff_t count = SPECPDL_INDEX ();
ptrdiff_t count1;
int s = -1, outch, inch;
int xerrno = 0;
- Lisp_Object ip_address;
int family;
struct sockaddr *sa = NULL;
int ret;
count1 = SPECPDL_INDEX ();
s = -1;
- while (!NILP (ip_addresses))
+ while (!NILP (addrinfos))
{
- ip_address = XCAR (ip_addresses);
- ip_addresses = XCDR (ip_addresses);
+ Lisp_Object addrinfo = XCAR (addrinfos);
+ addrinfos = XCDR (addrinfos);
+ int protocol = XINT (XCAR (addrinfo));
+ Lisp_Object ip_address = XCDR (addrinfo);
#ifdef WINDOWSNT
retry_connect:
s = socket_to_use;
if (s < 0)
{
- s = socket (family, p->socktype | SOCK_CLOEXEC, p->ai_protocol);
+ int socktype = p->socktype | SOCK_CLOEXEC;
+ if (p->is_non_blocking_client)
+ socktype |= SOCK_NONBLOCK;
+ s = socket (family, socktype, protocol);
if (s < 0)
{
xerrno = errno;
}
}
-#ifdef DATAGRAM_SOCKETS
- if (!p->is_server && p->socktype == SOCK_DGRAM)
- break;
-#endif /* DATAGRAM_SOCKETS */
-
- if (p->is_non_blocking_client)
+ if (p->is_non_blocking_client && ! (SOCK_NONBLOCK && socket_to_use < 0))
{
ret = fcntl (s, F_SETFL, O_NONBLOCK);
if (ret < 0)
}
}
+#ifdef DATAGRAM_SOCKETS
+ if (!p->is_server && p->socktype == SOCK_DGRAM)
+ break;
+#endif /* DATAGRAM_SOCKETS */
+
/* Make us close S if quit. */
record_unwind_protect_int (close_file_unwind, s);
Lisp_Object tem;
Lisp_Object name, buffer, host, service, address;
Lisp_Object filter, sentinel, use_external_socket_p;
- Lisp_Object ip_addresses = Qnil;
+ Lisp_Object addrinfos = Qnil;
int socktype;
int family = -1;
- int ai_protocol = 0;
+ enum { any_protocol = 0 };
#ifdef HAVE_GETADDRINFO_A
struct gaicb *dns_request = NULL;
#endif
if (!get_lisp_to_sockaddr_size (address, &family))
error ("Malformed :address");
- ip_addresses = list1 (address);
+ addrinfos = list1 (Fcons (make_number (any_protocol), address));
goto open_socket;
}
CHECK_STRING (service);
if (sizeof address_un.sun_path <= SBYTES (service))
error ("Service name too long");
- ip_addresses = list1 (service);
+ addrinfos = list1 (Fcons (make_number (any_protocol), service));
goto open_socket;
}
#endif
immediate_quit = 0;
for (lres = res; lres; lres = lres->ai_next)
- {
- ip_addresses = Fcons (conv_sockaddr_to_lisp
- (lres->ai_addr, lres->ai_addrlen),
- ip_addresses);
- ai_protocol = lres->ai_protocol;
- }
+ addrinfos = Fcons (conv_addrinfo_to_lisp (lres), addrinfos);
- ip_addresses = Fnreverse (ip_addresses);
+ addrinfos = Fnreverse (addrinfos);
freeaddrinfo (res);
p->is_server = false;
p->port = port;
p->socktype = socktype;
- p->ai_protocol = ai_protocol;
#ifdef HAVE_GETADDRINFO_A
p->dns_request = NULL;
#endif
#ifdef HAVE_GETADDRINFO_A
/* With async address resolution, the list of addresses is empty, so
postpone connecting to the server. */
- if (!p->is_server && NILP (ip_addresses))
+ if (!p->is_server && NILP (addrinfos))
{
p->dns_request = dns_request;
p->status = Qconnect;
}
#endif
- connect_network_socket (proc, ip_addresses, use_external_socket_p);
+ connect_network_socket (proc, addrinfos, use_external_socket_p);
return proc;
}
check_for_dns (Lisp_Object proc)
{
struct Lisp_Process *p = XPROCESS (proc);
- Lisp_Object ip_addresses = Qnil;
+ Lisp_Object addrinfos = Qnil;
/* Sanity check. */
if (! p->dns_request)
struct addrinfo *res;
for (res = p->dns_request->ar_result; res; res = res->ai_next)
- {
- ip_addresses = Fcons (conv_sockaddr_to_lisp
- (res->ai_addr, res->ai_addrlen),
- ip_addresses);
- }
+ addrinfos = Fcons (conv_addrinfo_to_lisp (res), addrinfos);
- ip_addresses = Fnreverse (ip_addresses);
+ addrinfos = Fnreverse (addrinfos);
}
/* The DNS lookup failed. */
else if (EQ (p->status, Qconnect))
if (!EQ (p->status, Qconnect))
return Qnil;
- return ip_addresses;
+ return addrinfos;
}
#endif /* HAVE_GETADDRINFO_A */
/* Check for pending DNS requests. */
if (p->dns_request)
{
- Lisp_Object ip_addresses = check_for_dns (aproc);
- if (!NILP (ip_addresses) && !EQ (ip_addresses, Qt))
- connect_network_socket (aproc, ip_addresses, Qnil);
+ Lisp_Object addrinfos = check_for_dns (aproc);
+ if (!NILP (addrinfos) && !EQ (addrinfos, Qt))
+ connect_network_socket (aproc, addrinfos, Qnil);
else
retry_for_async = true;
}
p = XPROCESS (proc);
-#ifdef GNU_LINUX
- /* getsockopt(,,SO_ERROR,,) is said to hang on some systems.
- So only use it on systems where it is known to work. */
+#ifndef WINDOWSNT
{
socklen_t xlen = sizeof (xerrno);
if (getsockopt (channel, SOL_SOCKET, SO_ERROR, &xerrno, &xlen))
xerrno = errno;
}
#else
+ /* On MS-Windows, getsockopt clears the error for the
+ entire process, which may not be the right thing; see
+ w32.c. Use getpeername instead. */
{
struct sockaddr pname;
socklen_t pnamelen = sizeof (pname);