Mercurial > hg > xemacs-beta
diff src/process-nt.c @ 282:c42ec1d1cded r21-0b39
Import from CVS: tag r21-0b39
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:33:18 +0200 |
parents | 7df0dd720c89 |
children | 57709be46d1b |
line wrap: on
line diff
--- a/src/process-nt.c Mon Aug 13 10:32:23 2007 +0200 +++ b/src/process-nt.c Mon Aug 13 10:33:18 2007 +0200 @@ -35,6 +35,9 @@ #include <windows.h> #include <shellapi.h> #include <signal.h> +#ifdef HAVE_SOCKETS +#include <winsock.h> +#endif /* Implemenation-specific data. Pointed to by Lisp_Process->process_data */ struct nt_process_data @@ -375,21 +378,9 @@ static void nt_alloc_process_data (struct Lisp_Process *p) { - p->process_data = xnew (struct nt_process_data); + p->process_data = xnew_and_zero (struct nt_process_data); } -#if 0 /* #### Need this method? */ -/* - * Mark any Lisp objects in Lisp_Process->process_data - */ - -static void -nt_mark_process_data (struct Lisp_Process *proc, - void (*markobj) (Lisp_Object)) -{ -} -#endif - static void nt_finalize_process_data (struct Lisp_Process *p, int for_disksave) { @@ -398,30 +389,17 @@ CloseHandle (NT_DATA(p)->h_process); } -#if 0 /* #### Need this method? */ /* * Initialize XEmacs process implemenation once */ - static void nt_init_process (void) { + /* Initialize winsock */ + WSADATA wsa_data; + /* Request Winsock v1.1 Note the order: (minor=1, major=1) */ + WSAStartup (MAKEWORD (1,1), &wsa_data); } -#endif - -#if 0 /* #### Need this method? */ -/* - * Initialize any process local data. This is called when newly - * created process is connected to real OS file handles. The - * handles are generally represented by void* type, but are - * of type HANDLE for Win32 - */ - -static void -nt_init_process_io_handles (struct Lisp_Process *p, void* in, void* out, int flags) -{ -} -#endif /* * Fork off a subprocess. P is a pointer to newly created subprocess @@ -730,7 +708,198 @@ return send_result ? 0 : -1; } + +/*-----------------------------------------------------------------------*/ +/* Sockets connections */ +/*-----------------------------------------------------------------------*/ +#ifdef HAVE_SOCKETS +/* #### Hey MS, how long Winsock 2 for '95 will be in beta? */ + +#define SOCK_TIMER_ID 666 +#define XM_SOCKREPLY (WM_USER + 666) + +static int +get_internet_address (Lisp_Object host, struct sockaddr_in *address, + Error_behavior errb) +{ + char buf [MAXGETHOSTSTRUCT]; + HWND hwnd; + HANDLE hasync; + int success = 0; + + address->sin_family = AF_INET; + + /* First check if HOST is already a numeric address */ + { + unsigned long inaddr = inet_addr (XSTRING_DATA (host)); + if (inaddr != INADDR_NONE) + { + address->sin_addr.s_addr = inaddr; + return 1; + } + } + + /* Create a window which will receive completion messages */ + hwnd = CreateWindow ("STATIC", NULL, WS_OVERLAPPED, 0, 0, 1, 1, + NULL, NULL, NULL, NULL); + assert (hwnd); + + /* Post name resolution request */ + hasync = WSAAsyncGetHostByName (hwnd, XM_SOCKREPLY, XSTRING_DATA (host), + buf, sizeof (buf)); + if (hasync == NULL) + goto done; + + /* Set a timer to poll for quit every 250 ms */ + SetTimer (hwnd, SOCK_TIMER_ID, 250, NULL); + + while (1) + { + MSG msg; + GetMessage (&msg, hwnd, 0, 0); + if (msg.message == XM_SOCKREPLY) + { + /* Ok, got an answer */ + if (WSAGETASYNCERROR(msg.lParam) == NO_ERROR) + success = 1; + goto done; + } + else if (msg.message == WM_TIMER && msg.wParam == SOCK_TIMER_ID) + { + if (QUITP) + { + WSACancelAsyncRequest (hasync); + KillTimer (hwnd, SOCK_TIMER_ID); + DestroyWindow (hwnd); + REALLY_QUIT; + } + } + DispatchMessage (&msg); + } + + done: + KillTimer (hwnd, SOCK_TIMER_ID); + DestroyWindow (hwnd); + if (success) + { + /* BUF starts with struct hostent */ + struct hostent* he = (struct hostent*) buf; + address->sin_addr.s_addr = *(unsigned long*)he->h_addr_list[0]; + } + return success; +} + +static Lisp_Object +nt_canonicalize_host_name (Lisp_Object host) +{ + struct sockaddr_in address; + + if (!get_internet_address (host, &address, ERROR_ME_NOT)) + return host; + + if (address.sin_family == AF_INET) + return build_string (inet_ntoa (address.sin_addr)); + else + return host; +} + +/* open a TCP network connection to a given HOST/SERVICE. Treated + exactly like a normal process when reading and writing. Only + differences are in status display and process deletion. A network + connection has no PID; you cannot signal it. All you can do is + deactivate and close it via delete-process */ + +static void +nt_open_network_stream (Lisp_Object name, Lisp_Object host, Lisp_Object service, + Lisp_Object family, void** vinfd, void** voutfd) +{ + struct sockaddr_in address; + SOCKET s; + int port; + int retval; + + CHECK_STRING (host); + + if (!EQ (family, Qtcpip)) + error ("Unsupported protocol family \"%s\"", + string_data (symbol_name (XSYMBOL (family)))); + + if (INTP (service)) + port = htons ((unsigned short) XINT (service)); + else + { + struct servent *svc_info; + CHECK_STRING (service); + svc_info = getservbyname ((char *) XSTRING_DATA (service), "tcp"); + if (svc_info == 0) + error ("Unknown service \"%s\"", XSTRING_DATA (service)); + port = svc_info->s_port; + } + + get_internet_address (host, &address, ERROR_ME); + address.sin_port = port; + + s = socket (address.sin_family, SOCK_STREAM, 0); + if (s < 0) + report_file_error ("error creating socket", list1 (name)); + + /* We don't want to be blocked on connect */ + { + unsigned int nonblock = 1; + ioctlsocket (s, FIONBIO, &nonblock); + } + + retval = connect (s, (struct sockaddr *) &address, sizeof (address)); + if (retval != NO_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) + goto connect_failed; + + /* Wait while connection is established */ + while (1) + { + fd_set fdset; + struct timeval tv; + int nsel; + + if (QUITP) + { + closesocket (s); + REALLY_QUIT; + } + + /* Poll for quit every 250 ms */ + tv.tv_sec = 0; + tv.tv_usec = 250 * 1000; + + FD_ZERO (&fdset); + FD_SET (s, &fdset); + nsel = select (0, NULL, &fdset, &fdset, &tv); + + if (nsel > 0) + { + /* Check was connnection successful or not */ + tv.tv_usec = 0; + nsel = select (0, NULL, NULL, &fdset, &tv); + if (nsel > 0) + goto connect_failed; + else + break; + } + } + + /* We are connected at this point */ + *vinfd = (void*)s; + DuplicateHandle (GetCurrentProcess(), (HANDLE)s, + GetCurrentProcess(), (LPHANDLE)voutfd, + 0, FALSE, DUPLICATE_SAME_ACCESS); + return; + + connect_failed: + closesocket (s); + report_file_error ("connection failed", list2 (host, name)); +} + +#endif /*-----------------------------------------------------------------------*/ /* Initialization */ @@ -741,23 +910,20 @@ { PROCESS_HAS_METHOD (nt, alloc_process_data); PROCESS_HAS_METHOD (nt, finalize_process_data); - /* PROCESS_HAS_METHOD (nt, mark_process_data); */ - /* PROCESS_HAS_METHOD (nt, init_process); */ - /* PROCESS_HAS_METHOD (nt, init_process_io_handles); */ + PROCESS_HAS_METHOD (nt, init_process); PROCESS_HAS_METHOD (nt, create_process); PROCESS_HAS_METHOD (nt, update_status_if_terminated); PROCESS_HAS_METHOD (nt, send_process); PROCESS_HAS_METHOD (nt, kill_child_process); PROCESS_HAS_METHOD (nt, kill_process_by_pid); -#if 0 /* Yet todo */ #ifdef HAVE_SOCKETS PROCESS_HAS_METHOD (nt, canonicalize_host_name); PROCESS_HAS_METHOD (nt, open_network_stream); #ifdef HAVE_MULTICAST +#error I won't do this until '95 has winsock2 PROCESS_HAS_METHOD (nt, open_multicast_group); #endif #endif -#endif } void