Mercurial > hg > xemacs-beta
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 { |