comparison 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
comparison
equal deleted inserted replaced
281:090b52736db2 282:c42ec1d1cded
33 #include "sysdep.h" 33 #include "sysdep.h"
34 34
35 #include <windows.h> 35 #include <windows.h>
36 #include <shellapi.h> 36 #include <shellapi.h>
37 #include <signal.h> 37 #include <signal.h>
38 #ifdef HAVE_SOCKETS
39 #include <winsock.h>
40 #endif
38 41
39 /* Implemenation-specific data. Pointed to by Lisp_Process->process_data */ 42 /* Implemenation-specific data. Pointed to by Lisp_Process->process_data */
40 struct nt_process_data 43 struct nt_process_data
41 { 44 {
42 HANDLE h_process; 45 HANDLE h_process;
373 */ 376 */
374 377
375 static void 378 static void
376 nt_alloc_process_data (struct Lisp_Process *p) 379 nt_alloc_process_data (struct Lisp_Process *p)
377 { 380 {
378 p->process_data = xnew (struct nt_process_data); 381 p->process_data = xnew_and_zero (struct nt_process_data);
379 } 382 }
380
381 #if 0 /* #### Need this method? */
382 /*
383 * Mark any Lisp objects in Lisp_Process->process_data
384 */
385
386 static void
387 nt_mark_process_data (struct Lisp_Process *proc,
388 void (*markobj) (Lisp_Object))
389 {
390 }
391 #endif
392 383
393 static void 384 static void
394 nt_finalize_process_data (struct Lisp_Process *p, int for_disksave) 385 nt_finalize_process_data (struct Lisp_Process *p, int for_disksave)
395 { 386 {
396 assert (!for_disksave); 387 assert (!for_disksave);
397 if (NT_DATA(p)->h_process) 388 if (NT_DATA(p)->h_process)
398 CloseHandle (NT_DATA(p)->h_process); 389 CloseHandle (NT_DATA(p)->h_process);
399 } 390 }
400 391
401 #if 0 /* #### Need this method? */
402 /* 392 /*
403 * Initialize XEmacs process implemenation once 393 * Initialize XEmacs process implemenation once
404 */ 394 */
405
406 static void 395 static void
407 nt_init_process (void) 396 nt_init_process (void)
408 { 397 {
409 } 398 /* Initialize winsock */
410 #endif 399 WSADATA wsa_data;
411 400 /* Request Winsock v1.1 Note the order: (minor=1, major=1) */
412 #if 0 /* #### Need this method? */ 401 WSAStartup (MAKEWORD (1,1), &wsa_data);
413 /* 402 }
414 * Initialize any process local data. This is called when newly
415 * created process is connected to real OS file handles. The
416 * handles are generally represented by void* type, but are
417 * of type HANDLE for Win32
418 */
419
420 static void
421 nt_init_process_io_handles (struct Lisp_Process *p, void* in, void* out, int flags)
422 {
423 }
424 #endif
425 403
426 /* 404 /*
427 * Fork off a subprocess. P is a pointer to newly created subprocess 405 * Fork off a subprocess. P is a pointer to newly created subprocess
428 * object. If this function signals, the caller is responsible for 406 * object. If this function signals, the caller is responsible for
429 * deleting (and finalizing) the process object. 407 * deleting (and finalizing) the process object.
728 706
729 CloseHandle (h_process); 707 CloseHandle (h_process);
730 708
731 return send_result ? 0 : -1; 709 return send_result ? 0 : -1;
732 } 710 }
733 711
712 /*-----------------------------------------------------------------------*/
713 /* Sockets connections */
714 /*-----------------------------------------------------------------------*/
715 #ifdef HAVE_SOCKETS
716
717 /* #### Hey MS, how long Winsock 2 for '95 will be in beta? */
718
719 #define SOCK_TIMER_ID 666
720 #define XM_SOCKREPLY (WM_USER + 666)
721
722 static int
723 get_internet_address (Lisp_Object host, struct sockaddr_in *address,
724 Error_behavior errb)
725 {
726 char buf [MAXGETHOSTSTRUCT];
727 HWND hwnd;
728 HANDLE hasync;
729 int success = 0;
730
731 address->sin_family = AF_INET;
732
733 /* First check if HOST is already a numeric address */
734 {
735 unsigned long inaddr = inet_addr (XSTRING_DATA (host));
736 if (inaddr != INADDR_NONE)
737 {
738 address->sin_addr.s_addr = inaddr;
739 return 1;
740 }
741 }
742
743 /* Create a window which will receive completion messages */
744 hwnd = CreateWindow ("STATIC", NULL, WS_OVERLAPPED, 0, 0, 1, 1,
745 NULL, NULL, NULL, NULL);
746 assert (hwnd);
747
748 /* Post name resolution request */
749 hasync = WSAAsyncGetHostByName (hwnd, XM_SOCKREPLY, XSTRING_DATA (host),
750 buf, sizeof (buf));
751 if (hasync == NULL)
752 goto done;
753
754 /* Set a timer to poll for quit every 250 ms */
755 SetTimer (hwnd, SOCK_TIMER_ID, 250, NULL);
756
757 while (1)
758 {
759 MSG msg;
760 GetMessage (&msg, hwnd, 0, 0);
761 if (msg.message == XM_SOCKREPLY)
762 {
763 /* Ok, got an answer */
764 if (WSAGETASYNCERROR(msg.lParam) == NO_ERROR)
765 success = 1;
766 goto done;
767 }
768 else if (msg.message == WM_TIMER && msg.wParam == SOCK_TIMER_ID)
769 {
770 if (QUITP)
771 {
772 WSACancelAsyncRequest (hasync);
773 KillTimer (hwnd, SOCK_TIMER_ID);
774 DestroyWindow (hwnd);
775 REALLY_QUIT;
776 }
777 }
778 DispatchMessage (&msg);
779 }
780
781 done:
782 KillTimer (hwnd, SOCK_TIMER_ID);
783 DestroyWindow (hwnd);
784 if (success)
785 {
786 /* BUF starts with struct hostent */
787 struct hostent* he = (struct hostent*) buf;
788 address->sin_addr.s_addr = *(unsigned long*)he->h_addr_list[0];
789 }
790 return success;
791 }
792
793 static Lisp_Object
794 nt_canonicalize_host_name (Lisp_Object host)
795 {
796 struct sockaddr_in address;
797
798 if (!get_internet_address (host, &address, ERROR_ME_NOT))
799 return host;
800
801 if (address.sin_family == AF_INET)
802 return build_string (inet_ntoa (address.sin_addr));
803 else
804 return host;
805 }
806
807 /* open a TCP network connection to a given HOST/SERVICE. Treated
808 exactly like a normal process when reading and writing. Only
809 differences are in status display and process deletion. A network
810 connection has no PID; you cannot signal it. All you can do is
811 deactivate and close it via delete-process */
812
813 static void
814 nt_open_network_stream (Lisp_Object name, Lisp_Object host, Lisp_Object service,
815 Lisp_Object family, void** vinfd, void** voutfd)
816 {
817 struct sockaddr_in address;
818 SOCKET s;
819 int port;
820 int retval;
821
822 CHECK_STRING (host);
823
824 if (!EQ (family, Qtcpip))
825 error ("Unsupported protocol family \"%s\"",
826 string_data (symbol_name (XSYMBOL (family))));
827
828 if (INTP (service))
829 port = htons ((unsigned short) XINT (service));
830 else
831 {
832 struct servent *svc_info;
833 CHECK_STRING (service);
834 svc_info = getservbyname ((char *) XSTRING_DATA (service), "tcp");
835 if (svc_info == 0)
836 error ("Unknown service \"%s\"", XSTRING_DATA (service));
837 port = svc_info->s_port;
838 }
839
840 get_internet_address (host, &address, ERROR_ME);
841 address.sin_port = port;
842
843 s = socket (address.sin_family, SOCK_STREAM, 0);
844 if (s < 0)
845 report_file_error ("error creating socket", list1 (name));
846
847 /* We don't want to be blocked on connect */
848 {
849 unsigned int nonblock = 1;
850 ioctlsocket (s, FIONBIO, &nonblock);
851 }
852
853 retval = connect (s, (struct sockaddr *) &address, sizeof (address));
854 if (retval != NO_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
855 goto connect_failed;
856
857 /* Wait while connection is established */
858 while (1)
859 {
860 fd_set fdset;
861 struct timeval tv;
862 int nsel;
863
864 if (QUITP)
865 {
866 closesocket (s);
867 REALLY_QUIT;
868 }
869
870 /* Poll for quit every 250 ms */
871 tv.tv_sec = 0;
872 tv.tv_usec = 250 * 1000;
873
874 FD_ZERO (&fdset);
875 FD_SET (s, &fdset);
876 nsel = select (0, NULL, &fdset, &fdset, &tv);
877
878 if (nsel > 0)
879 {
880 /* Check was connnection successful or not */
881 tv.tv_usec = 0;
882 nsel = select (0, NULL, NULL, &fdset, &tv);
883 if (nsel > 0)
884 goto connect_failed;
885 else
886 break;
887 }
888 }
889
890 /* We are connected at this point */
891 *vinfd = (void*)s;
892 DuplicateHandle (GetCurrentProcess(), (HANDLE)s,
893 GetCurrentProcess(), (LPHANDLE)voutfd,
894 0, FALSE, DUPLICATE_SAME_ACCESS);
895 return;
896
897 connect_failed:
898 closesocket (s);
899 report_file_error ("connection failed", list2 (host, name));
900 }
901
902 #endif
734 903
735 /*-----------------------------------------------------------------------*/ 904 /*-----------------------------------------------------------------------*/
736 /* Initialization */ 905 /* Initialization */
737 /*-----------------------------------------------------------------------*/ 906 /*-----------------------------------------------------------------------*/
738 907
739 void 908 void
740 process_type_create_nt (void) 909 process_type_create_nt (void)
741 { 910 {
742 PROCESS_HAS_METHOD (nt, alloc_process_data); 911 PROCESS_HAS_METHOD (nt, alloc_process_data);
743 PROCESS_HAS_METHOD (nt, finalize_process_data); 912 PROCESS_HAS_METHOD (nt, finalize_process_data);
744 /* PROCESS_HAS_METHOD (nt, mark_process_data); */ 913 PROCESS_HAS_METHOD (nt, init_process);
745 /* PROCESS_HAS_METHOD (nt, init_process); */
746 /* PROCESS_HAS_METHOD (nt, init_process_io_handles); */
747 PROCESS_HAS_METHOD (nt, create_process); 914 PROCESS_HAS_METHOD (nt, create_process);
748 PROCESS_HAS_METHOD (nt, update_status_if_terminated); 915 PROCESS_HAS_METHOD (nt, update_status_if_terminated);
749 PROCESS_HAS_METHOD (nt, send_process); 916 PROCESS_HAS_METHOD (nt, send_process);
750 PROCESS_HAS_METHOD (nt, kill_child_process); 917 PROCESS_HAS_METHOD (nt, kill_child_process);
751 PROCESS_HAS_METHOD (nt, kill_process_by_pid); 918 PROCESS_HAS_METHOD (nt, kill_process_by_pid);
752 #if 0 /* Yet todo */
753 #ifdef HAVE_SOCKETS 919 #ifdef HAVE_SOCKETS
754 PROCESS_HAS_METHOD (nt, canonicalize_host_name); 920 PROCESS_HAS_METHOD (nt, canonicalize_host_name);
755 PROCESS_HAS_METHOD (nt, open_network_stream); 921 PROCESS_HAS_METHOD (nt, open_network_stream);
756 #ifdef HAVE_MULTICAST 922 #ifdef HAVE_MULTICAST
923 #error I won't do this until '95 has winsock2
757 PROCESS_HAS_METHOD (nt, open_multicast_group); 924 PROCESS_HAS_METHOD (nt, open_multicast_group);
758 #endif 925 #endif
759 #endif 926 #endif
760 #endif
761 } 927 }
762 928
763 void 929 void
764 vars_of_process_nt (void) 930 vars_of_process_nt (void)
765 { 931 {