Mercurial > hg > xemacs-beta
comparison src/process-nt.c @ 398:74fd4e045ea6 r21-2-29
Import from CVS: tag r21-2-29
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:13:30 +0200 |
parents | c6012109f545 |
children | a86b2b5e0111 |
comparison
equal
deleted
inserted
replaced
397:f4aeb21a5bad | 398:74fd4e045ea6 |
---|---|
30 #include "lstream.h" | 30 #include "lstream.h" |
31 #include "process.h" | 31 #include "process.h" |
32 #include "procimpl.h" | 32 #include "procimpl.h" |
33 #include "sysdep.h" | 33 #include "sysdep.h" |
34 | 34 |
35 #include <windows.h> | 35 #ifndef __MINGW32__ |
36 #include <shellapi.h> | 36 #include <shellapi.h> |
37 #else | |
38 #include <errno.h> | |
39 #endif | |
37 #include <signal.h> | 40 #include <signal.h> |
38 #ifdef HAVE_SOCKETS | 41 #ifdef HAVE_SOCKETS |
39 #include <winsock.h> | 42 #include <winsock.h> |
40 #endif | 43 #endif |
41 | 44 |
47 | 50 |
48 /* Implementation-specific data. Pointed to by Lisp_Process->process_data */ | 51 /* Implementation-specific data. Pointed to by Lisp_Process->process_data */ |
49 struct nt_process_data | 52 struct nt_process_data |
50 { | 53 { |
51 HANDLE h_process; | 54 HANDLE h_process; |
55 int need_enable_child_signals; | |
52 }; | 56 }; |
53 | 57 |
54 #define NT_DATA(p) ((struct nt_process_data*)((p)->process_data)) | 58 #define NT_DATA(p) ((struct nt_process_data*)((p)->process_data)) |
55 | 59 |
56 /*-----------------------------------------------------------------------*/ | 60 /*-----------------------------------------------------------------------*/ |
58 /*-----------------------------------------------------------------------*/ | 62 /*-----------------------------------------------------------------------*/ |
59 | 63 |
60 /* This one breaks process abstraction. Prototype is in console-msw.h, | 64 /* This one breaks process abstraction. Prototype is in console-msw.h, |
61 used by select_process method in event-msw.c */ | 65 used by select_process method in event-msw.c */ |
62 HANDLE | 66 HANDLE |
63 get_nt_process_handle (struct Lisp_Process *p) | 67 get_nt_process_handle (Lisp_Process *p) |
64 { | 68 { |
65 return (NT_DATA (p)->h_process); | 69 return (NT_DATA (p)->h_process); |
66 } | 70 } |
67 | 71 |
68 /*-----------------------------------------------------------------------*/ | 72 /*-----------------------------------------------------------------------*/ |
162 run_in_other_process (HANDLE h_process, | 166 run_in_other_process (HANDLE h_process, |
163 LPTHREAD_START_ROUTINE routine, | 167 LPTHREAD_START_ROUTINE routine, |
164 LPVOID data, size_t data_size) | 168 LPVOID data, size_t data_size) |
165 { | 169 { |
166 process_memory pm; | 170 process_memory pm; |
167 CONST size_t code_size = FRAGMENT_CODE_SIZE; | 171 const size_t code_size = FRAGMENT_CODE_SIZE; |
168 /* Need at most 3 extra bytes of memory, for data alignment */ | 172 /* Need at most 3 extra bytes of memory, for data alignment */ |
169 size_t total_size = code_size + data_size + 3; | 173 size_t total_size = code_size + data_size + 3; |
170 LPVOID remote_data; | 174 LPVOID remote_data; |
171 HANDLE h_thread; | 175 HANDLE h_thread; |
172 DWORD dw_unused; | 176 DWORD dw_unused; |
304 case SIGHUP: | 308 case SIGHUP: |
305 { | 309 { |
306 sigkill_data d; | 310 sigkill_data d; |
307 d.adr_ExitProcess = GetProcAddress (h_kernel, "ExitProcess"); | 311 d.adr_ExitProcess = GetProcAddress (h_kernel, "ExitProcess"); |
308 assert (d.adr_ExitProcess); | 312 assert (d.adr_ExitProcess); |
309 retval = run_in_other_process (h_process, sigkill_proc, | 313 retval = run_in_other_process (h_process, |
314 (LPTHREAD_START_ROUTINE)sigkill_proc, | |
310 &d, sizeof (d)); | 315 &d, sizeof (d)); |
311 break; | 316 break; |
312 } | 317 } |
313 case SIGINT: | 318 case SIGINT: |
314 { | 319 { |
315 sigint_data d; | 320 sigint_data d; |
316 d.adr_GenerateConsoleCtrlEvent = | 321 d.adr_GenerateConsoleCtrlEvent = |
317 GetProcAddress (h_kernel, "GenerateConsoleCtrlEvent"); | 322 GetProcAddress (h_kernel, "GenerateConsoleCtrlEvent"); |
318 assert (d.adr_GenerateConsoleCtrlEvent); | 323 assert (d.adr_GenerateConsoleCtrlEvent); |
319 d.event = CTRL_C_EVENT; | 324 d.event = CTRL_C_EVENT; |
320 retval = run_in_other_process (h_process, sigint_proc, | 325 retval = run_in_other_process (h_process, |
326 (LPTHREAD_START_ROUTINE)sigint_proc, | |
321 &d, sizeof (d)); | 327 &d, sizeof (d)); |
322 break; | 328 break; |
323 } | 329 } |
324 default: | 330 default: |
325 assert (0); | 331 assert (0); |
339 | 345 |
340 assert (h_kernel != NULL); | 346 assert (h_kernel != NULL); |
341 d.adr_SetConsoleCtrlHandler = | 347 d.adr_SetConsoleCtrlHandler = |
342 GetProcAddress (h_kernel, "SetConsoleCtrlHandler"); | 348 GetProcAddress (h_kernel, "SetConsoleCtrlHandler"); |
343 assert (d.adr_SetConsoleCtrlHandler); | 349 assert (d.adr_SetConsoleCtrlHandler); |
344 run_in_other_process (h_process, sig_enable_proc, | 350 run_in_other_process (h_process, (LPTHREAD_START_ROUTINE)sig_enable_proc, |
345 &d, sizeof (d)); | 351 &d, sizeof (d)); |
346 } | 352 } |
347 | 353 |
348 #pragma warning (default : 4113) | 354 #pragma warning (default : 4113) |
349 | 355 |
366 /* | 372 /* |
367 * Allocate and initialize Lisp_Process->process_data | 373 * Allocate and initialize Lisp_Process->process_data |
368 */ | 374 */ |
369 | 375 |
370 static void | 376 static void |
371 nt_alloc_process_data (struct Lisp_Process *p) | 377 nt_alloc_process_data (Lisp_Process *p) |
372 { | 378 { |
373 p->process_data = xnew_and_zero (struct nt_process_data); | 379 p->process_data = xnew_and_zero (struct nt_process_data); |
374 } | 380 } |
375 | 381 |
376 static void | 382 static void |
377 nt_finalize_process_data (struct Lisp_Process *p, int for_disksave) | 383 nt_finalize_process_data (Lisp_Process *p, int for_disksave) |
378 { | 384 { |
379 assert (!for_disksave); | 385 assert (!for_disksave); |
380 if (NT_DATA(p)->h_process) | 386 if (NT_DATA(p)->h_process) |
381 CloseHandle (NT_DATA(p)->h_process); | 387 CloseHandle (NT_DATA(p)->h_process); |
382 } | 388 } |
401 * The method must return PID of the new process, a (positive??? ####) number | 407 * The method must return PID of the new process, a (positive??? ####) number |
402 * which fits into Lisp_Int. No return value indicates an error, the method | 408 * which fits into Lisp_Int. No return value indicates an error, the method |
403 * must signal an error instead. | 409 * must signal an error instead. |
404 */ | 410 */ |
405 | 411 |
406 /* #### This function completely ignores Vprocess_environment */ | |
407 | |
408 static void | 412 static void |
409 signal_cannot_launch (Lisp_Object image_file, DWORD err) | 413 signal_cannot_launch (Lisp_Object image_file, DWORD err) |
410 { | 414 { |
411 mswindows_set_errno (err); | 415 mswindows_set_errno (err); |
412 signal_simple_error_2 ("Error starting", image_file, lisp_strerror (errno)); | 416 signal_simple_error_2 ("Error starting", image_file, lisp_strerror (errno)); |
413 } | 417 } |
414 | 418 |
415 static int | 419 static int |
416 nt_create_process (struct Lisp_Process *p, | 420 nt_create_process (Lisp_Process *p, |
417 Lisp_Object *argv, int nargv, | 421 Lisp_Object *argv, int nargv, |
418 Lisp_Object program, Lisp_Object cur_dir) | 422 Lisp_Object program, Lisp_Object cur_dir) |
419 { | 423 { |
420 HANDLE hmyshove, hmyslurp, hprocin, hprocout; | 424 HANDLE hmyshove, hmyslurp, hprocin, hprocout, hprocerr; |
421 LPTSTR command_line; | 425 LPTSTR command_line; |
422 BOOL do_io, windowed; | 426 BOOL do_io, windowed; |
427 char *proc_env; | |
423 | 428 |
424 /* Find out whether the application is windowed or not */ | 429 /* Find out whether the application is windowed or not */ |
425 { | 430 { |
426 /* SHGetFileInfo tends to return ERROR_FILE_NOT_FOUND on most | 431 /* SHGetFileInfo tends to return ERROR_FILE_NOT_FOUND on most |
427 errors. This leads to bogus error message. */ | 432 errors. This leads to bogus error message. */ |
465 sa.lpSecurityDescriptor = NULL; | 470 sa.lpSecurityDescriptor = NULL; |
466 | 471 |
467 CreatePipe (&hprocin, &hmyshove, &sa, 0); | 472 CreatePipe (&hprocin, &hmyshove, &sa, 0); |
468 CreatePipe (&hmyslurp, &hprocout, &sa, 0); | 473 CreatePipe (&hmyslurp, &hprocout, &sa, 0); |
469 | 474 |
475 /* Duplicate the stdout handle for use as stderr */ | |
476 DuplicateHandle(GetCurrentProcess(), hprocout, GetCurrentProcess(), &hprocerr, | |
477 0, TRUE, DUPLICATE_SAME_ACCESS); | |
478 | |
470 /* Stupid Win32 allows to create a pipe with *both* ends either | 479 /* Stupid Win32 allows to create a pipe with *both* ends either |
471 inheritable or not. We need process ends inheritable, and local | 480 inheritable or not. We need process ends inheritable, and local |
472 ends not inheritable. */ | 481 ends not inheritable. */ |
473 DuplicateHandle (GetCurrentProcess(), hmyshove, GetCurrentProcess(), &htmp, | 482 DuplicateHandle (GetCurrentProcess(), hmyshove, GetCurrentProcess(), &htmp, |
474 0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS); | 483 0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS); |
505 strcat (command_line, XSTRING_DATA (args_or_ret)); | 514 strcat (command_line, XSTRING_DATA (args_or_ret)); |
506 | 515 |
507 UNGCPRO; /* args_or_ret */ | 516 UNGCPRO; /* args_or_ret */ |
508 } | 517 } |
509 | 518 |
519 /* Set `proc_env' to a nul-separated array of the strings in | |
520 Vprocess_environment terminated by 2 nuls. */ | |
521 | |
522 { | |
523 extern int compare_env (const char **strp1, const char **strp2); | |
524 char **env; | |
525 REGISTER Lisp_Object tem; | |
526 REGISTER char **new_env; | |
527 REGISTER int new_length = 0, i, new_space; | |
528 char *penv; | |
529 | |
530 for (tem = Vprocess_environment; | |
531 (CONSP (tem) | |
532 && STRINGP (XCAR (tem))); | |
533 tem = XCDR (tem)) | |
534 new_length++; | |
535 | |
536 /* new_length + 1 to include terminating 0. */ | |
537 env = new_env = alloca_array (char *, new_length + 1); | |
538 | |
539 /* Copy the Vprocess_environment strings into new_env. */ | |
540 for (tem = Vprocess_environment; | |
541 (CONSP (tem) | |
542 && STRINGP (XCAR (tem))); | |
543 tem = XCDR (tem)) | |
544 { | |
545 char **ep = env; | |
546 char *string = (char *) XSTRING_DATA (XCAR (tem)); | |
547 /* See if this string duplicates any string already in the env. | |
548 If so, don't put it in. | |
549 When an env var has multiple definitions, | |
550 we keep the definition that comes first in process-environment. */ | |
551 for (; ep != new_env; ep++) | |
552 { | |
553 char *p = *ep, *q = string; | |
554 while (1) | |
555 { | |
556 if (*q == 0) | |
557 /* The string is malformed; might as well drop it. */ | |
558 goto duplicate; | |
559 if (*q != *p) | |
560 break; | |
561 if (*q == '=') | |
562 goto duplicate; | |
563 p++, q++; | |
564 } | |
565 } | |
566 *new_env++ = string; | |
567 duplicate: ; | |
568 } | |
569 *new_env = 0; | |
570 | |
571 /* Sort the environment variables */ | |
572 new_length = new_env - env; | |
573 qsort (env, new_length, sizeof (char *), compare_env); | |
574 | |
575 /* Work out how much space to allocate */ | |
576 new_space = 0; | |
577 for (i = 0; i < new_length; i++) | |
578 { | |
579 new_space += strlen(env[i]) + 1; | |
580 } | |
581 new_space++; | |
582 | |
583 /* Allocate space and copy variables into it */ | |
584 penv = proc_env = alloca(new_space); | |
585 for (i = 0; i < new_length; i++) | |
586 { | |
587 strcpy(penv, env[i]); | |
588 penv += strlen(env[i]) + 1; | |
589 } | |
590 *penv = 0; | |
591 } | |
592 | |
510 /* Create process */ | 593 /* Create process */ |
511 { | 594 { |
512 STARTUPINFO si; | 595 STARTUPINFO si; |
513 PROCESS_INFORMATION pi; | 596 PROCESS_INFORMATION pi; |
514 DWORD err; | 597 DWORD err; |
518 si.wShowWindow = windowed ? SW_SHOWNORMAL : SW_HIDE; | 601 si.wShowWindow = windowed ? SW_SHOWNORMAL : SW_HIDE; |
519 if (do_io) | 602 if (do_io) |
520 { | 603 { |
521 si.hStdInput = hprocin; | 604 si.hStdInput = hprocin; |
522 si.hStdOutput = hprocout; | 605 si.hStdOutput = hprocout; |
523 si.hStdError = hprocout; | 606 si.hStdError = hprocerr; |
524 si.dwFlags |= STARTF_USESTDHANDLES; | 607 si.dwFlags |= STARTF_USESTDHANDLES; |
525 } | 608 } |
526 | 609 |
527 err = (CreateProcess (NULL, command_line, NULL, NULL, TRUE, | 610 err = (CreateProcess (NULL, command_line, NULL, NULL, TRUE, |
528 CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP | 611 CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP |
529 | CREATE_SUSPENDED, | 612 | CREATE_SUSPENDED, |
530 NULL, (char *) XSTRING_DATA (cur_dir), &si, &pi) | 613 proc_env, (char *) XSTRING_DATA (cur_dir), &si, &pi) |
531 ? 0 : GetLastError ()); | 614 ? 0 : GetLastError ()); |
532 | 615 |
533 if (do_io) | 616 if (do_io) |
534 { | 617 { |
535 /* These just have been inherited; we do not need a copy */ | 618 /* These just have been inherited; we do not need a copy */ |
536 CloseHandle (hprocin); | 619 CloseHandle (hprocin); |
537 CloseHandle (hprocout); | 620 CloseHandle (hprocout); |
621 CloseHandle (hprocerr); | |
538 } | 622 } |
539 | 623 |
540 /* Handle process creation failure */ | 624 /* Handle process creation failure */ |
541 if (err) | 625 if (err) |
542 { | 626 { |
559 /* Indicate as if the process has exited immediately. */ | 643 /* Indicate as if the process has exited immediately. */ |
560 p->status_symbol = Qexit; | 644 p->status_symbol = Qexit; |
561 CloseHandle (pi.hProcess); | 645 CloseHandle (pi.hProcess); |
562 } | 646 } |
563 | 647 |
564 if (!windowed) | |
565 enable_child_signals (pi.hProcess); | |
566 | |
567 ResumeThread (pi.hThread); | 648 ResumeThread (pi.hThread); |
568 CloseHandle (pi.hThread); | 649 CloseHandle (pi.hThread); |
569 | 650 |
570 /* Hack to support Windows 95 negative pids */ | 651 /* Remember to enable child signals later if this is not a windowed |
571 return ((int)pi.dwProcessId < 0 | 652 app. Can't do it right now because that screws up the MKS Toolkit |
572 ? -(int)pi.dwProcessId : (int)pi.dwProcessId); | 653 shell. */ |
654 if (!windowed) | |
655 { | |
656 NT_DATA(p)->need_enable_child_signals = 10; | |
657 kick_status_notify (); | |
658 } | |
659 | |
660 return ((int)pi.dwProcessId); | |
573 } | 661 } |
574 } | 662 } |
575 | 663 |
576 /* | 664 /* |
577 * This method is called to update status fields of the process | 665 * This method is called to update status fields of the process |
580 * | 668 * |
581 * The method is called only for real child processes. | 669 * The method is called only for real child processes. |
582 */ | 670 */ |
583 | 671 |
584 static void | 672 static void |
585 nt_update_status_if_terminated (struct Lisp_Process* p) | 673 nt_update_status_if_terminated (Lisp_Process* p) |
586 { | 674 { |
587 DWORD exit_code; | 675 DWORD exit_code; |
676 | |
677 if (NT_DATA(p)->need_enable_child_signals > 1) | |
678 { | |
679 NT_DATA(p)->need_enable_child_signals -= 1; | |
680 kick_status_notify (); | |
681 } | |
682 else if (NT_DATA(p)->need_enable_child_signals == 1) | |
683 { | |
684 enable_child_signals(NT_DATA(p)->h_process); | |
685 NT_DATA(p)->need_enable_child_signals = 0; | |
686 } | |
687 | |
588 if (GetExitCodeProcess (NT_DATA(p)->h_process, &exit_code) | 688 if (GetExitCodeProcess (NT_DATA(p)->h_process, &exit_code) |
589 && exit_code != STILL_ACTIVE) | 689 && exit_code != STILL_ACTIVE) |
590 { | 690 { |
591 p->tick++; | 691 p->tick++; |
592 p->core_dumped = 0; | 692 p->core_dumped = 0; |
614 unix_send_process... */ | 714 unix_send_process... */ |
615 | 715 |
616 static void | 716 static void |
617 nt_send_process (Lisp_Object proc, struct lstream* lstream) | 717 nt_send_process (Lisp_Object proc, struct lstream* lstream) |
618 { | 718 { |
619 struct Lisp_Process *p = XPROCESS (proc); | 719 volatile Lisp_Object vol_proc = proc; |
720 Lisp_Process *volatile p = XPROCESS (proc); | |
620 | 721 |
621 /* use a reasonable-sized buffer (somewhere around the size of the | 722 /* use a reasonable-sized buffer (somewhere around the size of the |
622 stream buffer) so as to avoid inundating the stream with blocked | 723 stream buffer) so as to avoid inundating the stream with blocked |
623 data. */ | 724 data. */ |
624 Bufbyte chunkbuf[128]; | 725 Bufbyte chunkbuf[128]; |
625 Bytecount chunklen; | 726 Bytecount chunklen; |
626 | 727 |
627 while (1) | 728 while (1) |
628 { | 729 { |
629 int writeret; | 730 ssize_t writeret; |
630 | 731 |
631 chunklen = Lstream_read (lstream, chunkbuf, 128); | 732 chunklen = Lstream_read (lstream, chunkbuf, 128); |
632 if (chunklen <= 0) | 733 if (chunklen <= 0) |
633 break; /* perhaps should abort() if < 0? | 734 break; /* perhaps should abort() if < 0? |
634 This should never happen. */ | 735 This should never happen. */ |
644 p->status_symbol = Qexit; | 745 p->status_symbol = Qexit; |
645 p->exit_code = ERROR_BROKEN_PIPE; | 746 p->exit_code = ERROR_BROKEN_PIPE; |
646 p->core_dumped = 0; | 747 p->core_dumped = 0; |
647 p->tick++; | 748 p->tick++; |
648 process_tick++; | 749 process_tick++; |
649 deactivate_process (proc); | 750 deactivate_process (*((Lisp_Object *) (&vol_proc))); |
650 error ("Broken pipe error sending to process %s; closed it", | 751 error ("Broken pipe error sending to process %s; closed it", |
651 XSTRING_DATA (p->name)); | 752 XSTRING_DATA (p->name)); |
652 } | 753 } |
653 | 754 |
654 { | 755 { |
682 | 783 |
683 static void | 784 static void |
684 nt_kill_child_process (Lisp_Object proc, int signo, | 785 nt_kill_child_process (Lisp_Object proc, int signo, |
685 int current_group, int nomsg) | 786 int current_group, int nomsg) |
686 { | 787 { |
687 struct Lisp_Process *p = XPROCESS (proc); | 788 Lisp_Process *p = XPROCESS (proc); |
789 | |
790 /* Enable child signals if necessary. This may lose the first | |
791 but it's better than nothing. */ | |
792 if (NT_DATA(p)->need_enable_child_signals > 0) | |
793 { | |
794 enable_child_signals(NT_DATA(p)->h_process); | |
795 NT_DATA(p)->need_enable_child_signals = 0; | |
796 } | |
688 | 797 |
689 /* Signal error if SIGNO cannot be sent */ | 798 /* Signal error if SIGNO cannot be sent */ |
690 validate_signal_number (signo); | 799 validate_signal_number (signo); |
691 | 800 |
692 /* Send signal */ | 801 /* Send signal */ |
777 if (msg.message == XM_SOCKREPLY) | 886 if (msg.message == XM_SOCKREPLY) |
778 { | 887 { |
779 /* Ok, got an answer */ | 888 /* Ok, got an answer */ |
780 if (WSAGETASYNCERROR(msg.lParam) == NO_ERROR) | 889 if (WSAGETASYNCERROR(msg.lParam) == NO_ERROR) |
781 success = 1; | 890 success = 1; |
891 else | |
892 { | |
893 warn_when_safe(Qstream, Qwarning, | |
894 "cannot get IP address for host \"%s\"", | |
895 XSTRING_DATA (host)); | |
896 } | |
782 goto done; | 897 goto done; |
783 } | 898 } |
784 else if (msg.message == WM_TIMER && msg.wParam == SOCK_TIMER_ID) | 899 else if (msg.message == WM_TIMER && msg.wParam == SOCK_TIMER_ID) |
785 { | 900 { |
786 if (QUITP) | 901 if (QUITP) |
826 connection has no PID; you cannot signal it. All you can do is | 941 connection has no PID; you cannot signal it. All you can do is |
827 deactivate and close it via delete-process */ | 942 deactivate and close it via delete-process */ |
828 | 943 |
829 static void | 944 static void |
830 nt_open_network_stream (Lisp_Object name, Lisp_Object host, Lisp_Object service, | 945 nt_open_network_stream (Lisp_Object name, Lisp_Object host, Lisp_Object service, |
831 Lisp_Object family, void** vinfd, void** voutfd) | 946 Lisp_Object protocol, void** vinfd, void** voutfd) |
832 { | 947 { |
833 struct sockaddr_in address; | 948 struct sockaddr_in address; |
834 SOCKET s; | 949 SOCKET s; |
835 int port; | 950 int port; |
836 int retval; | 951 int retval; |
837 | 952 |
838 CHECK_STRING (host); | 953 CHECK_STRING (host); |
839 | 954 |
840 if (!EQ (family, Qtcpip)) | 955 if (!EQ (protocol, Qtcp)) |
841 error ("Unsupported protocol family \"%s\"", | 956 error ("Unsupported protocol \"%s\"", |
842 string_data (symbol_name (XSYMBOL (family)))); | 957 string_data (symbol_name (XSYMBOL (protocol)))); |
843 | 958 |
844 if (INTP (service)) | 959 if (INTP (service)) |
845 port = htons ((unsigned short) XINT (service)); | 960 port = htons ((unsigned short) XINT (service)); |
846 else | 961 else |
847 { | 962 { |
860 if (s < 0) | 975 if (s < 0) |
861 report_file_error ("error creating socket", list1 (name)); | 976 report_file_error ("error creating socket", list1 (name)); |
862 | 977 |
863 /* We don't want to be blocked on connect */ | 978 /* We don't want to be blocked on connect */ |
864 { | 979 { |
865 unsigned int nonblock = 1; | 980 unsigned long nonblock = 1; |
866 ioctlsocket (s, FIONBIO, &nonblock); | 981 ioctlsocket (s, FIONBIO, &nonblock); |
867 } | 982 } |
868 | 983 |
869 retval = connect (s, (struct sockaddr *) &address, sizeof (address)); | 984 retval = connect (s, (struct sockaddr *) &address, sizeof (address)); |
870 if (retval != NO_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) | 985 if (retval != NO_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) |
871 goto connect_failed; | 986 goto connect_failed; |
872 | |
873 /* Wait while connection is established */ | 987 /* Wait while connection is established */ |
874 while (1) | 988 while (1) |
875 { | 989 { |
876 fd_set fdset; | 990 fd_set fdset; |
877 struct timeval tv; | 991 struct timeval tv; |
910 0, FALSE, DUPLICATE_SAME_ACCESS); | 1024 0, FALSE, DUPLICATE_SAME_ACCESS); |
911 return; | 1025 return; |
912 | 1026 |
913 connect_failed: | 1027 connect_failed: |
914 closesocket (s); | 1028 closesocket (s); |
1029 if (INTP (service)) { | |
1030 warn_when_safe(Qstream, Qwarning, | |
1031 "failure to open network stream to host \"%s\" for service \"%d\"", | |
1032 XSTRING_DATA (host), | |
1033 (unsigned short) XINT (service)); | |
1034 } | |
1035 else { | |
1036 warn_when_safe(Qstream, Qwarning, | |
1037 "failure to open network stream to host \"%s\" for service \"%s\"", | |
1038 XSTRING_DATA (host), | |
1039 XSTRING_DATA (service)); | |
1040 } | |
915 report_file_error ("connection failed", list2 (host, name)); | 1041 report_file_error ("connection failed", list2 (host, name)); |
916 } | 1042 } |
917 | 1043 |
918 #endif | 1044 #endif |
919 | 1045 |