comparison src/process-nt.c @ 412:697ef44129c6 r21-2-14

Import from CVS: tag r21-2-14
author cvs
date Mon, 13 Aug 2007 11:20:41 +0200
parents de805c49cfc1
children 11054d720c21
comparison
equal deleted inserted replaced
411:12e008d41344 412:697ef44129c6
1 /* Asynchronous subprocess implementation for Win32 1 /* Asynchronous subprocess implementation for Win32
2 Copyright (C) 1985, 1986, 1987, 1988, 1992, 1993, 1994, 1995 2 Copyright (C) 1985, 1986, 1987, 1988, 1992, 1993, 1994, 1995
3 Free Software Foundation, Inc. 3 Free Software Foundation, Inc.
4 Copyright (C) 1995 Sun Microsystems, Inc. 4 Copyright (C) 1995 Sun Microsystems, Inc.
5 Copyright (C) 1995, 1996, 2000 Ben Wing. 5 Copyright (C) 1995, 1996 Ben Wing.
6 6
7 This file is part of XEmacs. 7 This file is part of XEmacs.
8 8
9 XEmacs is free software; you can redistribute it and/or modify it 9 XEmacs is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the 10 under the terms of the GNU General Public License as published by the
24 /* Written by Kirill M. Katsnelson <kkm@kis.ru>, April 1998 */ 24 /* Written by Kirill M. Katsnelson <kkm@kis.ru>, April 1998 */
25 25
26 #include <config.h> 26 #include <config.h>
27 #include "lisp.h" 27 #include "lisp.h"
28 28
29 #include "buffer.h"
30 #include "console-msw.h"
31 #include "hash.h" 29 #include "hash.h"
32 #include "lstream.h" 30 #include "lstream.h"
33 #include "nt.h"
34 #include "process.h" 31 #include "process.h"
35 #include "procimpl.h" 32 #include "procimpl.h"
36 #include "sysdep.h" 33 #include "sysdep.h"
37 34
35 #include <windows.h>
36 #ifndef __MINGW32__
38 #include <shellapi.h> 37 #include <shellapi.h>
38 #else
39 #include <errno.h> 39 #include <errno.h>
40 #endif
40 #include <signal.h> 41 #include <signal.h>
41 #ifdef HAVE_SOCKETS 42 #ifdef HAVE_SOCKETS
42 #include <winsock.h> 43 #include <winsock.h>
43 #endif 44 #endif
44 45
45 /* Arbitrary size limit for code fragments passed to run_in_other_process */ 46 /* Arbitrary size limit for code fragments passed to run_in_other_process */
46 #define FRAGMENT_CODE_SIZE 32 47 #define FRAGMENT_CODE_SIZE 32
47 48
49 /* Bound by winnt.el */
50 Lisp_Object Qnt_quote_process_args;
51
48 /* Implementation-specific data. Pointed to by Lisp_Process->process_data */ 52 /* Implementation-specific data. Pointed to by Lisp_Process->process_data */
49 struct nt_process_data 53 struct nt_process_data
50 { 54 {
51 HANDLE h_process; 55 HANDLE h_process;
52 DWORD dwProcessId;
53 HWND hwnd; /* console window */
54 }; 56 };
55
56 /* Control how args are quoted to ensure correct parsing by child
57 process. */
58 Lisp_Object Vmswindows_quote_process_args;
59
60 /* Control whether create_child causes the process to inherit Emacs'
61 console window, or be given a new one of its own. The default is
62 nil, to allow multiple DOS programs to run on Win95. Having separate
63 consoles also allows Emacs to cleanly terminate process groups. */
64 Lisp_Object Vmswindows_start_process_share_console;
65
66 /* Control whether create_child cause the process to inherit Emacs'
67 error mode setting. The default is t, to minimize the possibility of
68 subprocesses blocking when accessing unmounted drives. */
69 Lisp_Object Vmswindows_start_process_inherit_error_mode;
70 57
71 #define NT_DATA(p) ((struct nt_process_data*)((p)->process_data)) 58 #define NT_DATA(p) ((struct nt_process_data*)((p)->process_data))
72 59
73 /*-----------------------------------------------------------------------*/ 60 /*-----------------------------------------------------------------------*/
74 /* Process helpers */ 61 /* Process helpers */
75 /*-----------------------------------------------------------------------*/ 62 /*-----------------------------------------------------------------------*/
76 63
77 /* This one breaks process abstraction. Prototype is in console-msw.h, 64 /* This one breaks process abstraction. Prototype is in console-msw.h,
78 used by select_process method in event-msw.c */ 65 used by select_process method in event-msw.c */
79 HANDLE 66 HANDLE
80 get_nt_process_handle (Lisp_Process *p) 67 get_nt_process_handle (struct Lisp_Process *p)
81 { 68 {
82 return (NT_DATA (p)->h_process); 69 return (NT_DATA (p)->h_process);
83 } 70 }
84
85 static struct Lisp_Process *
86 find_process_from_pid (DWORD pid)
87 {
88 Lisp_Object tail, proc;
89
90 for (tail = Vprocess_list; CONSP (tail); tail = XCDR (tail))
91 {
92 proc = XCAR (tail);
93 if (NT_DATA (XPROCESS (proc))->dwProcessId == pid)
94 return XPROCESS (proc);
95 }
96 return 0;
97 }
98
99 71
100 /*-----------------------------------------------------------------------*/ 72 /*-----------------------------------------------------------------------*/
101 /* Running remote threads. See Microsoft Systems Journal 1994 Number 5 */ 73 /* Running remote threads. See Microsoft Systems Journal 1994 Number 5 */
102 /* Jeffrey Richter, Load Your 32-bit DLL into Another Process's Address..*/ 74 /* Jeffrey Richter, Load Your 32-bit DLL into Another Process's Address..*/
103 /*-----------------------------------------------------------------------*/ 75 /*-----------------------------------------------------------------------*/
194 run_in_other_process (HANDLE h_process, 166 run_in_other_process (HANDLE h_process,
195 LPTHREAD_START_ROUTINE routine, 167 LPTHREAD_START_ROUTINE routine,
196 LPVOID data, size_t data_size) 168 LPVOID data, size_t data_size)
197 { 169 {
198 process_memory pm; 170 process_memory pm;
199 const size_t code_size = FRAGMENT_CODE_SIZE; 171 CONST size_t code_size = FRAGMENT_CODE_SIZE;
200 /* Need at most 3 extra bytes of memory, for data alignment */ 172 /* Need at most 3 extra bytes of memory, for data alignment */
201 size_t total_size = code_size + data_size + 3; 173 size_t total_size = code_size + data_size + 3;
202 LPVOID remote_data; 174 LPVOID remote_data;
203 HANDLE h_thread; 175 HANDLE h_thread;
204 DWORD dw_unused; 176 DWORD dw_unused;
249 } 221 }
250 222
251 /*-----------------------------------------------------------------------*/ 223 /*-----------------------------------------------------------------------*/
252 /* Sending signals */ 224 /* Sending signals */
253 /*-----------------------------------------------------------------------*/ 225 /*-----------------------------------------------------------------------*/
254
255 /* ---------------------------- the NT way ------------------------------- */
256 226
257 /* 227 /*
258 * We handle the following signals: 228 * We handle the following signals:
259 * 229 *
260 * SIGKILL, SIGTERM, SIGQUIT, SIGHUP - These four translate to ExitProcess 230 * SIGKILL, SIGTERM, SIGQUIT, SIGHUP - These four translate to ExitProcess
315 /* 285 /*
316 * Send signal SIGNO to process H_PROCESS. 286 * Send signal SIGNO to process H_PROCESS.
317 * Return nonzero if successful. 287 * Return nonzero if successful.
318 */ 288 */
319 289
290 /* This code assigns a return value of GetProcAddress to function pointers
291 of many different types. Instead of heavy obscure casts, we just disable
292 warnings about assignments to different function pointer types. */
293 #pragma warning (disable : 4113)
294
320 static int 295 static int
321 send_signal_the_nt_way (struct nt_process_data *cp, int pid, int signo) 296 send_signal (HANDLE h_process, int signo)
322 { 297 {
323 HANDLE h_process;
324 HMODULE h_kernel = GetModuleHandle ("kernel32"); 298 HMODULE h_kernel = GetModuleHandle ("kernel32");
325 int close_process = 0;
326 DWORD retval; 299 DWORD retval;
327 300
328 assert (h_kernel != NULL); 301 assert (h_kernel != NULL);
329 302
330 if (cp)
331 {
332 pid = cp->dwProcessId;
333 h_process = cp->h_process;
334 }
335 else
336 {
337 close_process = 1;
338 /* Try to open the process with required privileges */
339 h_process = OpenProcess (PROCESS_CREATE_THREAD
340 | PROCESS_QUERY_INFORMATION
341 | PROCESS_VM_OPERATION
342 | PROCESS_VM_WRITE,
343 FALSE, pid);
344 if (!h_process)
345 return 0;
346 }
347
348 switch (signo) 303 switch (signo)
349 { 304 {
350 case SIGKILL: 305 case SIGKILL:
351 case SIGTERM: 306 case SIGTERM:
352 case SIGQUIT: 307 case SIGQUIT:
353 case SIGHUP: 308 case SIGHUP:
354 { 309 {
355 sigkill_data d; 310 sigkill_data d;
356 311 d.adr_ExitProcess = GetProcAddress (h_kernel, "ExitProcess");
357 d.adr_ExitProcess =
358 (void (WINAPI *) (UINT)) GetProcAddress (h_kernel, "ExitProcess");
359 assert (d.adr_ExitProcess); 312 assert (d.adr_ExitProcess);
360 retval = run_in_other_process (h_process, 313 retval = run_in_other_process (h_process,
361 (LPTHREAD_START_ROUTINE)sigkill_proc, 314 (LPTHREAD_START_ROUTINE)sigkill_proc,
362 &d, sizeof (d)); 315 &d, sizeof (d));
363 break; 316 break;
364 } 317 }
365 case SIGINT: 318 case SIGINT:
366 { 319 {
367 sigint_data d; 320 sigint_data d;
368 d.adr_GenerateConsoleCtrlEvent = 321 d.adr_GenerateConsoleCtrlEvent =
369 (BOOL (WINAPI *) (DWORD, DWORD))
370 GetProcAddress (h_kernel, "GenerateConsoleCtrlEvent"); 322 GetProcAddress (h_kernel, "GenerateConsoleCtrlEvent");
371 assert (d.adr_GenerateConsoleCtrlEvent); 323 assert (d.adr_GenerateConsoleCtrlEvent);
372 d.event = CTRL_C_EVENT; 324 d.event = CTRL_C_EVENT;
373 retval = run_in_other_process (h_process, 325 retval = run_in_other_process (h_process,
374 (LPTHREAD_START_ROUTINE)sigint_proc, 326 (LPTHREAD_START_ROUTINE)sigint_proc,
377 } 329 }
378 default: 330 default:
379 assert (0); 331 assert (0);
380 } 332 }
381 333
382 if (close_process)
383 CloseHandle (h_process);
384 return (int)retval > 0 ? 1 : 0; 334 return (int)retval > 0 ? 1 : 0;
385 } 335 }
386 336
387 /* 337 /*
388 * Enable CTRL_C_EVENT handling in a new child process 338 * Enable CTRL_C_EVENT handling in a new child process
393 HMODULE h_kernel = GetModuleHandle ("kernel32"); 343 HMODULE h_kernel = GetModuleHandle ("kernel32");
394 sig_enable_data d; 344 sig_enable_data d;
395 345
396 assert (h_kernel != NULL); 346 assert (h_kernel != NULL);
397 d.adr_SetConsoleCtrlHandler = 347 d.adr_SetConsoleCtrlHandler =
398 (BOOL (WINAPI *) (LPVOID, BOOL))
399 GetProcAddress (h_kernel, "SetConsoleCtrlHandler"); 348 GetProcAddress (h_kernel, "SetConsoleCtrlHandler");
400 assert (d.adr_SetConsoleCtrlHandler); 349 assert (d.adr_SetConsoleCtrlHandler);
401 run_in_other_process (h_process, (LPTHREAD_START_ROUTINE)sig_enable_proc, 350 run_in_other_process (h_process, (LPTHREAD_START_ROUTINE)sig_enable_proc,
402 &d, sizeof (d)); 351 &d, sizeof (d));
403 } 352 }
404 353
405 #pragma warning (default : 4113) 354 #pragma warning (default : 4113)
406 355
407 /* ---------------------------- the 95 way ------------------------------- */
408
409 static BOOL CALLBACK
410 find_child_console (HWND hwnd, struct nt_process_data *cp)
411 {
412 DWORD thread_id;
413 DWORD process_id;
414
415 thread_id = GetWindowThreadProcessId (hwnd, &process_id);
416 if (process_id == cp->dwProcessId)
417 {
418 char window_class[32];
419
420 GetClassName (hwnd, window_class, sizeof (window_class));
421 if (strcmp (window_class,
422 mswindows_windows9x_p ()
423 ? "tty"
424 : "ConsoleWindowClass") == 0)
425 {
426 cp->hwnd = hwnd;
427 return FALSE;
428 }
429 }
430 /* keep looking */
431 return TRUE;
432 }
433
434 static int
435 send_signal_the_95_way (struct nt_process_data *cp, int pid, int signo)
436 {
437 HANDLE h_process;
438 int close_process = 0;
439 int rc = 1;
440
441 if (cp)
442 {
443 pid = cp->dwProcessId;
444 h_process = cp->h_process;
445
446 /* Try to locate console window for process. */
447 EnumWindows (find_child_console, (LPARAM) cp);
448 }
449 else
450 {
451 close_process = 1;
452 /* Try to open the process with required privileges */
453 h_process = OpenProcess (PROCESS_TERMINATE, FALSE, pid);
454 if (!h_process)
455 return 0;
456 }
457
458 if (signo == SIGINT)
459 {
460 if (NILP (Vmswindows_start_process_share_console) && cp && cp->hwnd)
461 {
462 BYTE control_scan_code = (BYTE) MapVirtualKey (VK_CONTROL, 0);
463 BYTE vk_break_code = VK_CANCEL;
464 BYTE break_scan_code = (BYTE) MapVirtualKey (vk_break_code, 0);
465 HWND foreground_window;
466
467 if (break_scan_code == 0)
468 {
469 /* Fake Ctrl-C if we can't manage Ctrl-Break. */
470 vk_break_code = 'C';
471 break_scan_code = (BYTE) MapVirtualKey (vk_break_code, 0);
472 }
473
474 foreground_window = GetForegroundWindow ();
475 if (foreground_window)
476 {
477 /* NT 5.0, and apparently also Windows 98, will not allow
478 a Window to be set to foreground directly without the
479 user's involvement. The workaround is to attach
480 ourselves to the thread that owns the foreground
481 window, since that is the only thread that can set the
482 foreground window. */
483 DWORD foreground_thread, child_thread;
484 foreground_thread =
485 GetWindowThreadProcessId (foreground_window, NULL);
486 if (foreground_thread == GetCurrentThreadId ()
487 || !AttachThreadInput (GetCurrentThreadId (),
488 foreground_thread, TRUE))
489 foreground_thread = 0;
490
491 child_thread = GetWindowThreadProcessId (cp->hwnd, NULL);
492 if (child_thread == GetCurrentThreadId ()
493 || !AttachThreadInput (GetCurrentThreadId (),
494 child_thread, TRUE))
495 child_thread = 0;
496
497 /* Set the foreground window to the child. */
498 if (SetForegroundWindow (cp->hwnd))
499 {
500 /* Generate keystrokes as if user had typed Ctrl-Break or
501 Ctrl-C. */
502 keybd_event (VK_CONTROL, control_scan_code, 0, 0);
503 keybd_event (vk_break_code, break_scan_code,
504 (vk_break_code == 'C' ? 0 : KEYEVENTF_EXTENDEDKEY), 0);
505 keybd_event (vk_break_code, break_scan_code,
506 (vk_break_code == 'C' ? 0 : KEYEVENTF_EXTENDEDKEY)
507 | KEYEVENTF_KEYUP, 0);
508 keybd_event (VK_CONTROL, control_scan_code,
509 KEYEVENTF_KEYUP, 0);
510
511 /* Sleep for a bit to give time for Emacs frame to respond
512 to focus change events (if Emacs was active app). */
513 Sleep (100);
514
515 SetForegroundWindow (foreground_window);
516 }
517 /* Detach from the foreground and child threads now that
518 the foreground switching is over. */
519 if (foreground_thread)
520 AttachThreadInput (GetCurrentThreadId (),
521 foreground_thread, FALSE);
522 if (child_thread)
523 AttachThreadInput (GetCurrentThreadId (),
524 child_thread, FALSE);
525 }
526 }
527 /* Ctrl-Break is NT equivalent of SIGINT. */
528 else if (!GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid))
529 {
530 #if 0 /* FSF Emacs */
531 DebPrint (("sys_kill.GenerateConsoleCtrlEvent return %d "
532 "for pid %lu\n", GetLastError (), pid));
533 errno = EINVAL;
534 #endif
535 rc = 0;
536 }
537 }
538 else
539 {
540 if (NILP (Vmswindows_start_process_share_console) && cp && cp->hwnd)
541 {
542 #if 1
543 if (mswindows_windows9x_p ())
544 {
545 /*
546 Another possibility is to try terminating the VDM out-right by
547 calling the Shell VxD (id 0x17) V86 interface, function #4
548 "SHELL_Destroy_VM", ie.
549
550 mov edx,4
551 mov ebx,vm_handle
552 call shellapi
553
554 First need to determine the current VM handle, and then arrange for
555 the shellapi call to be made from the system vm (by using
556 Switch_VM_and_callback).
557
558 Could try to invoke DestroyVM through CallVxD.
559
560 */
561 #if 0
562 /* On Win95, posting WM_QUIT causes the 16-bit subsystem
563 to hang when cmdproxy is used in conjunction with
564 command.com for an interactive shell. Posting
565 WM_CLOSE pops up a dialog that, when Yes is selected,
566 does the same thing. TerminateProcess is also less
567 than ideal in that subprocesses tend to stick around
568 until the machine is shutdown, but at least it
569 doesn't freeze the 16-bit subsystem. */
570 PostMessage (cp->hwnd, WM_QUIT, 0xff, 0);
571 #endif
572 if (!TerminateProcess (h_process, 0xff))
573 {
574 #if 0 /* FSF Emacs */
575 DebPrint (("sys_kill.TerminateProcess returned %d "
576 "for pid %lu\n", GetLastError (), pid));
577 errno = EINVAL;
578 #endif
579 rc = 0;
580 }
581 }
582 else
583 #endif
584 PostMessage (cp->hwnd, WM_CLOSE, 0, 0);
585 }
586 /* Kill the process. On W32 this doesn't kill child processes
587 so it doesn't work very well for shells which is why it's not
588 used in every case. */
589 else if (!TerminateProcess (h_process, 0xff))
590 {
591 #if 0 /* FSF Emacs */
592 DebPrint (("sys_kill.TerminateProcess returned %d "
593 "for pid %lu\n", GetLastError (), pid));
594 errno = EINVAL;
595 #endif
596 rc = 0;
597 }
598 }
599
600 if (close_process)
601 CloseHandle (h_process);
602
603 return rc;
604 }
605
606 /* -------------------------- all-OS functions ---------------------------- */
607
608 static int
609 send_signal (struct nt_process_data *cp, int pid, int signo)
610 {
611 return send_signal_the_nt_way (cp, pid, signo)
612 || send_signal_the_95_way (cp, pid, signo);
613 }
614
615 /* 356 /*
616 * Signal error if SIGNO is not supported 357 * Signal error if SIGNO is not supported
617 */ 358 */
618 static void 359 static void
619 validate_signal_number (int signo) 360 validate_signal_number (int signo)
631 /* 372 /*
632 * Allocate and initialize Lisp_Process->process_data 373 * Allocate and initialize Lisp_Process->process_data
633 */ 374 */
634 375
635 static void 376 static void
636 nt_alloc_process_data (Lisp_Process *p) 377 nt_alloc_process_data (struct Lisp_Process *p)
637 { 378 {
638 p->process_data = xnew_and_zero (struct nt_process_data); 379 p->process_data = xnew_and_zero (struct nt_process_data);
639 } 380 }
640 381
641 static void 382 static void
642 nt_finalize_process_data (Lisp_Process *p, int for_disksave) 383 nt_finalize_process_data (struct Lisp_Process *p, int for_disksave)
643 { 384 {
644 assert (!for_disksave); 385 assert (!for_disksave);
645 if (NT_DATA (p)->h_process) 386 if (NT_DATA(p)->h_process)
646 CloseHandle (NT_DATA (p)->h_process); 387 CloseHandle (NT_DATA(p)->h_process);
647 } 388 }
648 389
649 /* 390 /*
650 * Initialize XEmacs process implementation once 391 * Initialize XEmacs process implementation once
651 */ 392 */
666 * 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
667 * 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
668 * must signal an error instead. 409 * must signal an error instead.
669 */ 410 */
670 411
412 /* #### This function completely ignores Vprocess_environment */
413
671 static void 414 static void
672 signal_cannot_launch (Lisp_Object image_file, DWORD err) 415 signal_cannot_launch (Lisp_Object image_file, DWORD err)
673 { 416 {
674 mswindows_set_errno (err); 417 mswindows_set_errno (err);
675 signal_simple_error_2 ("Error starting", image_file, lisp_strerror (errno)); 418 signal_simple_error_2 ("Error starting", image_file, lisp_strerror (errno));
676 } 419 }
677 420
678 static void
679 ensure_console_window_exists (void)
680 {
681 if (mswindows_windows9x_p ())
682 mswindows_hide_console ();
683 }
684
685 int
686 compare_env (const void *strp1, const void *strp2)
687 {
688 const char *str1 = *(const char**)strp1, *str2 = *(const char**)strp2;
689
690 while (*str1 && *str2 && *str1 != '=' && *str2 != '=')
691 {
692 if ((*str1) > (*str2))
693 return 1;
694 else if ((*str1) < (*str2))
695 return -1;
696 str1++, str2++;
697 }
698
699 if (*str1 == '=' && *str2 == '=')
700 return 0;
701 else if (*str1 == '=')
702 return -1;
703 else
704 return 1;
705 }
706
707 static int 421 static int
708 nt_create_process (Lisp_Process *p, 422 nt_create_process (struct Lisp_Process *p,
709 Lisp_Object *argv, int nargv, 423 Lisp_Object *argv, int nargv,
710 Lisp_Object program, Lisp_Object cur_dir) 424 Lisp_Object program, Lisp_Object cur_dir)
711 { 425 {
712 /* Synched up with sys_spawnve in FSF 20.6. Significantly different 426 HANDLE hmyshove, hmyslurp, hprocin, hprocout;
713 but still synchable. */ 427 LPTSTR command_line;
714 HANDLE hmyshove, hmyslurp, hprocin, hprocout, hprocerr;
715 Extbyte *command_line;
716 BOOL do_io, windowed; 428 BOOL do_io, windowed;
717 char *proc_env;
718
719 /* No need to DOS-ize the filename; expand-file-name (called prior)
720 already does this. */
721 429
722 /* Find out whether the application is windowed or not */ 430 /* Find out whether the application is windowed or not */
723 { 431 {
724 /* SHGetFileInfo tends to return ERROR_FILE_NOT_FOUND on most 432 /* SHGetFileInfo tends to return ERROR_FILE_NOT_FOUND on most
725 errors. This leads to bogus error message. */ 433 errors. This leads to bogus error message. */
763 sa.lpSecurityDescriptor = NULL; 471 sa.lpSecurityDescriptor = NULL;
764 472
765 CreatePipe (&hprocin, &hmyshove, &sa, 0); 473 CreatePipe (&hprocin, &hmyshove, &sa, 0);
766 CreatePipe (&hmyslurp, &hprocout, &sa, 0); 474 CreatePipe (&hmyslurp, &hprocout, &sa, 0);
767 475
768 /* Duplicate the stdout handle for use as stderr */
769 DuplicateHandle(GetCurrentProcess(), hprocout, GetCurrentProcess(),
770 &hprocerr, 0, TRUE, DUPLICATE_SAME_ACCESS);
771
772 /* Stupid Win32 allows to create a pipe with *both* ends either 476 /* Stupid Win32 allows to create a pipe with *both* ends either
773 inheritable or not. We need process ends inheritable, and local 477 inheritable or not. We need process ends inheritable, and local
774 ends not inheritable. */ 478 ends not inheritable. */
775 DuplicateHandle (GetCurrentProcess(), hmyshove, GetCurrentProcess(), 479 DuplicateHandle (GetCurrentProcess(), hmyshove, GetCurrentProcess(), &htmp,
776 &htmp, 0, FALSE, 480 0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS);
777 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS);
778 hmyshove = htmp; 481 hmyshove = htmp;
779 DuplicateHandle (GetCurrentProcess(), hmyslurp, GetCurrentProcess(), 482 DuplicateHandle (GetCurrentProcess(), hmyslurp, GetCurrentProcess(), &htmp,
780 &htmp, 0, FALSE, 483 0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS);
781 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS);
782 hmyslurp = htmp; 484 hmyslurp = htmp;
783 } 485 }
784 486
785 /* Convert an argv vector into Win32 style command line. */ 487 /* Convert an argv vector into Win32 style command line by a call to
488 lisp function `nt-quote-process-args' which see (in winnt.el)*/
786 { 489 {
787 int i; 490 int i;
788 Bufbyte **quoted_args; 491 Lisp_Object args_or_ret = Qnil;
789 int is_dos_app, is_cygnus_app; 492 struct gcpro gcpro1;
790 int is_command_shell; 493
791 int do_quoting = 0; 494 GCPRO1 (args_or_ret);
792 char escape_char = 0; 495
793
794 nargv++; /* include program; we access argv offset by 1 below */
795 quoted_args = alloca_array (Bufbyte *, nargv);
796
797 /* Determine whether program is a 16-bit DOS executable, or a Win32
798 executable that is implicitly linked to the Cygnus dll (implying it
799 was compiled with the Cygnus GNU toolchain and hence relies on
800 cygwin.dll to parse the command line - we use this to decide how to
801 escape quote chars in command line args that must be quoted). */
802 mswindows_executable_type (XSTRING_DATA (program),
803 &is_dos_app, &is_cygnus_app);
804
805 {
806 /* #### Bleeeeeeeeeeeeeeeeech!!!! The command shells appear to
807 use '^' as a quote character, at least under NT. #### I haven't
808 tested 95. If it allows no quoting conventions at all, set
809 escape_char to 0 and the code below will work. (e.g. NT tolerates
810 no quoting -- this command
811
812 cmd /c "ls "/Program Files""
813
814 actually works.) */
815
816 struct gcpro gcpro1, gcpro2;
817 Lisp_Object progname = Qnil;
818
819 GCPRO2 (program, progname);
820 progname = Ffile_name_nondirectory (program);
821 progname = Fdowncase (progname, Qnil);
822
823 is_command_shell =
824 internal_equal (progname, build_string ("command.com"), 0)
825 || internal_equal (progname, build_string ("cmd.exe"), 0);
826 UNGCPRO;
827 }
828
829 #if 0
830 /* #### we need to port this. */
831 /* On Windows 95, if cmdname is a DOS app, we invoke a helper
832 application to start it by specifying the helper app as cmdname,
833 while leaving the real app name as argv[0]. */
834 if (is_dos_app)
835 {
836 cmdname = (char*) alloca (MAXPATHLEN);
837 if (egetenv ("CMDPROXY"))
838 strcpy ((char*)cmdname, egetenv ("CMDPROXY"));
839 else
840 {
841 strcpy ((char*)cmdname, XSTRING_DATA (Vinvocation_directory));
842 strcat ((char*)cmdname, "cmdproxy.exe");
843 }
844 }
845 #endif
846
847 /* we have to do some conjuring here to put argv and envp into the
848 form CreateProcess wants... argv needs to be a space separated/null
849 terminated list of parameters, and envp is a null
850 separated/double-null terminated list of parameters.
851
852 Additionally, zero-length args and args containing whitespace or
853 quote chars need to be wrapped in double quotes - for this to work,
854 embedded quotes need to be escaped as well. The aim is to ensure
855 the child process reconstructs the argv array we start with
856 exactly, so we treat quotes at the beginning and end of arguments
857 as embedded quotes.
858
859 The Win32 GNU-based library from Cygnus doubles quotes to escape
860 them, while MSVC uses backslash for escaping. (Actually the MSVC
861 startup code does attempt to recognize doubled quotes and accept
862 them, but gets it wrong and ends up requiring three quotes to get a
863 single embedded quote!) So by default we decide whether to use
864 quote or backslash as the escape character based on whether the
865 binary is apparently a Cygnus compiled app.
866
867 Note that using backslash to escape embedded quotes requires
868 additional special handling if an embedded quote is already
869 preceded by backslash, or if an arg requiring quoting ends with
870 backslash. In such cases, the run of escape characters needs to be
871 doubled. For consistency, we apply this special handling as long
872 as the escape character is not quote.
873
874 Since we have no idea how large argv and envp are likely to be we
875 figure out list lengths on the fly and allocate them. */
876
877 if (!NILP (Vmswindows_quote_process_args))
878 {
879 do_quoting = 1;
880 /* Override escape char by binding mswindows-quote-process-args to
881 desired character, or use t for auto-selection. */
882 if (INTP (Vmswindows_quote_process_args))
883 escape_char = (char) XINT (Vmswindows_quote_process_args);
884 else
885 escape_char = is_command_shell ? '^' : is_cygnus_app ? '"' : '\\';
886 }
887
888 /* do argv... */
889 for (i = 0; i < nargv; ++i) 496 for (i = 0; i < nargv; ++i)
890 { 497 args_or_ret = Fcons (*argv++, args_or_ret);
891 Bufbyte *targ = XSTRING_DATA (i == 0 ? program : argv[i - 1]); 498 args_or_ret = Fnreverse (args_or_ret);
892 Bufbyte *p = targ; 499 args_or_ret = Fcons (program, args_or_ret);
893 int need_quotes = 0; 500
894 int escape_char_run = 0; 501 args_or_ret = call1 (Qnt_quote_process_args, args_or_ret);
895 int arglen = 0; 502
896 503 if (!STRINGP (args_or_ret))
897 if (*p == 0) 504 /* Luser wrote his/her own clever version */
898 need_quotes = 1; 505 error ("Bogus return value from `nt-quote-process-args'");
899 for ( ; *p; p++) 506
900 { 507 command_line = alloca_array (char, (XSTRING_LENGTH (program)
901 if (*p == '"') 508 + XSTRING_LENGTH (args_or_ret) + 2));
902 { 509 strcpy (command_line, XSTRING_DATA (program));
903 /* allow for embedded quotes to be escaped */ 510 strcat (command_line, " ");
904 if (escape_char) 511 strcat (command_line, XSTRING_DATA (args_or_ret));
905 arglen++; 512
906 need_quotes = 1; 513 UNGCPRO; /* args_or_ret */
907 /* handle the case where the embedded quote is already escaped */
908 if (escape_char_run > 0)
909 {
910 /* To preserve the arg exactly, we need to double the
911 preceding escape characters (plus adding one to
912 escape the quote character itself). */
913 arglen += escape_char_run;
914 }
915 }
916 else if (*p == ' ' || *p == '\t')
917 {
918 need_quotes = 1;
919 }
920
921 if (escape_char && *p == escape_char && escape_char != '"')
922 escape_char_run++;
923 else
924 escape_char_run = 0;
925 }
926 if (need_quotes)
927 {
928 arglen += 2;
929 /* handle the case where the arg ends with an escape char - we
930 must not let the enclosing quote be escaped. */
931 if (escape_char_run > 0)
932 arglen += escape_char_run;
933 }
934 arglen += strlen (targ) + 1;
935
936 quoted_args[i] = alloca_array (Bufbyte, arglen);
937 }
938
939 for (i = 0; i < nargv; ++i)
940 {
941 Bufbyte *targ = XSTRING_DATA (i == 0 ? program : argv[i - 1]);
942 Bufbyte *p = targ;
943 int need_quotes = 0;
944 Bufbyte *parg = quoted_args[i];
945
946 if (*p == 0)
947 need_quotes = 1;
948
949 if (do_quoting)
950 {
951 for ( ; *p; p++)
952 if (*p == ' ' || *p == '\t' || *p == '"')
953 need_quotes = 1;
954 }
955 if (need_quotes)
956 {
957 int escape_char_run = 0;
958 Bufbyte * first;
959 Bufbyte * last;
960
961 p = targ;
962 first = p;
963 last = p + strlen (p) - 1;
964 *parg++ = '"';
965 #if 0
966 /* This version does not escape quotes if they occur at the
967 beginning or end of the arg - this could lead to incorrect
968 behavior when the arg itself represents a command line
969 containing quoted args. I believe this was originally done
970 as a hack to make some things work, before
971 `mswindows-quote-process-args' was added. */
972 while (*p)
973 {
974 if (*p == '"' && p > first && p < last)
975 *parg++ = escape_char; /* escape embedded quotes */
976 *parg++ = *p++;
977 }
978 #else
979 for ( ; *p; p++)
980 {
981 if (escape_char && *p == '"')
982 {
983 /* double preceding escape chars if any */
984 while (escape_char_run > 0)
985 {
986 *parg++ = escape_char;
987 escape_char_run--;
988 }
989 /* escape all quote chars, even at beginning or end */
990 *parg++ = escape_char;
991 }
992 *parg++ = *p;
993
994 if (escape_char && *p == escape_char && escape_char != '"')
995 escape_char_run++;
996 else
997 escape_char_run = 0;
998 }
999 /* double escape chars before enclosing quote */
1000 while (escape_char_run > 0)
1001 {
1002 *parg++ = escape_char;
1003 escape_char_run--;
1004 }
1005 #endif
1006 *parg++ = '"';
1007 }
1008 else
1009 {
1010 strcpy (parg, targ);
1011 parg += strlen (targ);
1012 }
1013 *parg = '\0';
1014 }
1015
1016 {
1017 int total_cmdline_len = 0;
1018 Extcount *extargcount = (Extcount *) alloca_array (Extcount, nargv);
1019 Extbyte **extarg = (Extbyte **) alloca_array (Extbyte *, nargv);
1020 Extbyte *command_ptr;
1021
1022 for (i = 0; i < nargv; ++i)
1023 {
1024 TO_EXTERNAL_FORMAT (C_STRING, quoted_args[i], ALLOCA,
1025 (extarg[i], extargcount[i]), Qmswindows_tstr);
1026 /* account for space and terminating null */
1027 total_cmdline_len += extargcount[i] + EITCHAR_SIZE;
1028 }
1029
1030 command_line = alloca_array (char, total_cmdline_len);
1031 command_ptr = command_line;
1032 for (i = 0; i < nargv; ++i)
1033 {
1034 memcpy (command_ptr, extarg[i], extargcount[i]);
1035 command_ptr += extargcount[i];
1036 EICOPY_TCHAR (command_ptr, ' ');
1037 command_ptr += EITCHAR_SIZE;
1038 }
1039 EICOPY_TCHAR (command_ptr, '\0');
1040 command_ptr += EITCHAR_SIZE;
1041 }
1042 } 514 }
1043 /* Set `proc_env' to a nul-separated array of the strings in 515
1044 Vprocess_environment terminated by 2 nuls. */
1045
1046 {
1047 char **env;
1048 REGISTER Lisp_Object tem;
1049 REGISTER char **new_env;
1050 REGISTER int new_length = 0, i, new_space;
1051 char *penv;
1052
1053 for (tem = Vprocess_environment;
1054 (CONSP (tem)
1055 && STRINGP (XCAR (tem)));
1056 tem = XCDR (tem))
1057 new_length++;
1058
1059 /* FSF adds an extra env var to hold the current process ID of the
1060 Emacs process. Apparently this is used only by emacsserver.c,
1061 which we have superseded to gnuserv.c. (#### Does it work under
1062 MS Windows?)
1063
1064 sprintf (ppid_env_var_buffer, "EM_PARENT_PROCESS_ID=%d",
1065 GetCurrentProcessId ());
1066 arglen += strlen (ppid_env_var_buffer) + 1;
1067 numenv++;
1068 */
1069
1070 /* new_length + 1 to include terminating 0. */
1071 env = new_env = alloca_array (char *, new_length + 1);
1072
1073 /* Copy the Vprocess_environment strings into new_env. */
1074 for (tem = Vprocess_environment;
1075 (CONSP (tem)
1076 && STRINGP (XCAR (tem)));
1077 tem = XCDR (tem))
1078 {
1079 char **ep = env;
1080 char *string = (char *) XSTRING_DATA (XCAR (tem));
1081 /* See if this string duplicates any string already in the env.
1082 If so, don't put it in.
1083 When an env var has multiple definitions,
1084 we keep the definition that comes first in process-environment. */
1085 for (; ep != new_env; ep++)
1086 {
1087 char *p = *ep, *q = string;
1088 while (1)
1089 {
1090 if (*q == 0)
1091 /* The string is malformed; might as well drop it. */
1092 goto duplicate;
1093 if (*q != *p)
1094 break;
1095 if (*q == '=')
1096 goto duplicate;
1097 p++, q++;
1098 }
1099 }
1100 *new_env++ = string;
1101 duplicate: ;
1102 }
1103 *new_env = 0;
1104
1105 /* Sort the environment variables */
1106 new_length = new_env - env;
1107 qsort (env, new_length, sizeof (char *), compare_env);
1108
1109 /* Work out how much space to allocate */
1110 new_space = 0;
1111 for (i = 0; i < new_length; i++)
1112 {
1113 new_space += strlen(env[i]) + 1;
1114 }
1115 new_space++;
1116
1117 /* Allocate space and copy variables into it */
1118 penv = proc_env = (char*) alloca(new_space);
1119 for (i = 0; i < new_length; i++)
1120 {
1121 strcpy(penv, env[i]);
1122 penv += strlen(env[i]) + 1;
1123 }
1124 *penv = 0;
1125 }
1126
1127 /* Create process */ 516 /* Create process */
1128 { 517 {
1129 STARTUPINFO si; 518 STARTUPINFO si;
1130 PROCESS_INFORMATION pi; 519 PROCESS_INFORMATION pi;
1131 DWORD err; 520 DWORD err;
1132 DWORD flags;
1133 521
1134 xzero (si); 522 xzero (si);
1135 si.dwFlags = STARTF_USESHOWWINDOW; 523 si.dwFlags = STARTF_USESHOWWINDOW;
1136 si.wShowWindow = windowed ? SW_SHOWNORMAL : SW_HIDE; 524 si.wShowWindow = windowed ? SW_SHOWNORMAL : SW_HIDE;
1137 if (do_io) 525 if (do_io)
1138 { 526 {
1139 si.hStdInput = hprocin; 527 si.hStdInput = hprocin;
1140 si.hStdOutput = hprocout; 528 si.hStdOutput = hprocout;
1141 si.hStdError = hprocerr; 529 si.hStdError = hprocout;
1142 si.dwFlags |= STARTF_USESTDHANDLES; 530 si.dwFlags |= STARTF_USESTDHANDLES;
1143 } 531 }
1144 532
1145 flags = CREATE_SUSPENDED; 533 err = (CreateProcess (NULL, command_line, NULL, NULL, TRUE,
1146 if (mswindows_windows9x_p ()) 534 CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP
1147 flags |= (!NILP (Vmswindows_start_process_share_console) 535 | CREATE_SUSPENDED,
1148 ? CREATE_NEW_PROCESS_GROUP 536 NULL, (char *) XSTRING_DATA (cur_dir), &si, &pi)
1149 : CREATE_NEW_CONSOLE);
1150 else
1151 flags |= CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP;
1152 if (NILP (Vmswindows_start_process_inherit_error_mode))
1153 flags |= CREATE_DEFAULT_ERROR_MODE;
1154
1155 ensure_console_window_exists ();
1156
1157 err = (CreateProcess (NULL, command_line, NULL, NULL, TRUE, flags,
1158 proc_env, (char *) XSTRING_DATA (cur_dir), &si, &pi)
1159 ? 0 : GetLastError ()); 537 ? 0 : GetLastError ());
1160 538
1161 if (do_io) 539 if (do_io)
1162 { 540 {
1163 /* These just have been inherited; we do not need a copy */ 541 /* These just have been inherited; we do not need a copy */
1164 CloseHandle (hprocin); 542 CloseHandle (hprocin);
1165 CloseHandle (hprocout); 543 CloseHandle (hprocout);
1166 CloseHandle (hprocerr);
1167 } 544 }
1168 545
1169 /* Handle process creation failure */ 546 /* Handle process creation failure */
1170 if (err) 547 if (err)
1171 { 548 {
1179 556
1180 /* The process started successfully */ 557 /* The process started successfully */
1181 if (do_io) 558 if (do_io)
1182 { 559 {
1183 NT_DATA(p)->h_process = pi.hProcess; 560 NT_DATA(p)->h_process = pi.hProcess;
1184 NT_DATA(p)->dwProcessId = pi.dwProcessId;
1185 init_process_io_handles (p, (void*)hmyslurp, (void*)hmyshove, 0); 561 init_process_io_handles (p, (void*)hmyslurp, (void*)hmyshove, 0);
1186 } 562 }
1187 else 563 else
1188 { 564 {
1189 /* Indicate as if the process has exited immediately. */ 565 /* Indicate as if the process has exited immediately. */
1195 enable_child_signals (pi.hProcess); 571 enable_child_signals (pi.hProcess);
1196 572
1197 ResumeThread (pi.hThread); 573 ResumeThread (pi.hThread);
1198 CloseHandle (pi.hThread); 574 CloseHandle (pi.hThread);
1199 575
1200 return ((int)pi.dwProcessId); 576 /* Hack to support Windows 95 negative pids */
577 return ((int)pi.dwProcessId < 0
578 ? -(int)pi.dwProcessId : (int)pi.dwProcessId);
1201 } 579 }
1202 } 580 }
1203 581
1204 /* 582 /*
1205 * This method is called to update status fields of the process 583 * This method is called to update status fields of the process
1208 * 586 *
1209 * The method is called only for real child processes. 587 * The method is called only for real child processes.
1210 */ 588 */
1211 589
1212 static void 590 static void
1213 nt_update_status_if_terminated (Lisp_Process* p) 591 nt_update_status_if_terminated (struct Lisp_Process* p)
1214 { 592 {
1215 DWORD exit_code; 593 DWORD exit_code;
1216 if (GetExitCodeProcess (NT_DATA(p)->h_process, &exit_code) 594 if (GetExitCodeProcess (NT_DATA(p)->h_process, &exit_code)
1217 && exit_code != STILL_ACTIVE) 595 && exit_code != STILL_ACTIVE)
1218 { 596 {
1242 unix_send_process... */ 620 unix_send_process... */
1243 621
1244 static void 622 static void
1245 nt_send_process (Lisp_Object proc, struct lstream* lstream) 623 nt_send_process (Lisp_Object proc, struct lstream* lstream)
1246 { 624 {
1247 volatile Lisp_Object vol_proc = proc; 625 struct Lisp_Process *p = XPROCESS (proc);
1248 Lisp_Process *volatile p = XPROCESS (proc);
1249 626
1250 /* use a reasonable-sized buffer (somewhere around the size of the 627 /* use a reasonable-sized buffer (somewhere around the size of the
1251 stream buffer) so as to avoid inundating the stream with blocked 628 stream buffer) so as to avoid inundating the stream with blocked
1252 data. */ 629 data. */
1253 Bufbyte chunkbuf[512]; 630 Bufbyte chunkbuf[128];
1254 Bytecount chunklen; 631 Bytecount chunklen;
1255 632
1256 while (1) 633 while (1)
1257 { 634 {
1258 ssize_t writeret; 635 int writeret;
1259 636
1260 chunklen = Lstream_read (lstream, chunkbuf, 512); 637 chunklen = Lstream_read (lstream, chunkbuf, 128);
1261 if (chunklen <= 0) 638 if (chunklen <= 0)
1262 break; /* perhaps should abort() if < 0? 639 break; /* perhaps should abort() if < 0?
1263 This should never happen. */ 640 This should never happen. */
1264 641
1265 /* Lstream_write() will never successfully write less than the 642 /* Lstream_write() will never successfully write less than the
1273 p->status_symbol = Qexit; 650 p->status_symbol = Qexit;
1274 p->exit_code = ERROR_BROKEN_PIPE; 651 p->exit_code = ERROR_BROKEN_PIPE;
1275 p->core_dumped = 0; 652 p->core_dumped = 0;
1276 p->tick++; 653 p->tick++;
1277 process_tick++; 654 process_tick++;
1278 deactivate_process (*((Lisp_Object *) (&vol_proc))); 655 deactivate_process (proc);
1279 error ("Broken pipe error sending to process %s; closed it", 656 error ("Broken pipe error sending to process %s; closed it",
1280 XSTRING_DATA (p->name)); 657 XSTRING_DATA (p->name));
1281 } 658 }
1282 659
1283 { 660 {
1311 688
1312 static void 689 static void
1313 nt_kill_child_process (Lisp_Object proc, int signo, 690 nt_kill_child_process (Lisp_Object proc, int signo,
1314 int current_group, int nomsg) 691 int current_group, int nomsg)
1315 { 692 {
1316 Lisp_Process *p = XPROCESS (proc); 693 struct Lisp_Process *p = XPROCESS (proc);
1317 694
1318 /* Signal error if SIGNO cannot be sent */ 695 /* Signal error if SIGNO cannot be sent */
1319 validate_signal_number (signo); 696 validate_signal_number (signo);
1320 697
1321 /* Send signal */ 698 /* Send signal */
1322 if (!send_signal (NT_DATA (p), 0, signo)) 699 if (!send_signal (NT_DATA(p)->h_process, signo))
1323 signal_simple_error ("Cannot send signal to process", proc); 700 error ("Cannot send signal to process");
1324 } 701 }
1325 702
1326 /* 703 /*
1327 * Kill any process in the system given its PID 704 * Kill any process in the system given its PID.
1328 * 705 *
1329 * Returns zero if a signal successfully sent, or 706 * Returns zero if a signal successfully sent, or
1330 * negative number upon failure 707 * negative number upon failure
1331 */ 708 */
1332 static int 709 static int
1333 nt_kill_process_by_pid (int pid, int signo) 710 nt_kill_process_by_pid (int pid, int signo)
1334 { 711 {
1335 struct Lisp_Process *p; 712 HANDLE h_process;
1336 713 int send_result;
714
1337 /* Signal error if SIGNO cannot be sent */ 715 /* Signal error if SIGNO cannot be sent */
1338 validate_signal_number (signo); 716 validate_signal_number (signo);
1339 717
1340 p = find_process_from_pid (pid); 718 /* Try to open the process with required privileges */
1341 return send_signal (p ? NT_DATA (p) : 0, pid, signo) ? 0 : -1; 719 h_process = OpenProcess (PROCESS_CREATE_THREAD
720 | PROCESS_QUERY_INFORMATION
721 | PROCESS_VM_OPERATION
722 | PROCESS_VM_WRITE,
723 FALSE, pid);
724 if (h_process == NULL)
725 return -1;
726
727 send_result = send_signal (h_process, signo);
728
729 CloseHandle (h_process);
730
731 return send_result ? 0 : -1;
1342 } 732 }
1343 733
1344 /*-----------------------------------------------------------------------*/ 734 /*-----------------------------------------------------------------------*/
1345 /* Sockets connections */ 735 /* Sockets connections */
1346 /*-----------------------------------------------------------------------*/ 736 /*-----------------------------------------------------------------------*/
1393 if (msg.message == XM_SOCKREPLY) 783 if (msg.message == XM_SOCKREPLY)
1394 { 784 {
1395 /* Ok, got an answer */ 785 /* Ok, got an answer */
1396 if (WSAGETASYNCERROR(msg.lParam) == NO_ERROR) 786 if (WSAGETASYNCERROR(msg.lParam) == NO_ERROR)
1397 success = 1; 787 success = 1;
1398 else
1399 {
1400 warn_when_safe(Qstream, Qwarning,
1401 "cannot get IP address for host \"%s\"",
1402 XSTRING_DATA (host));
1403 }
1404 goto done; 788 goto done;
1405 } 789 }
1406 else if (msg.message == WM_TIMER && msg.wParam == SOCK_TIMER_ID) 790 else if (msg.message == WM_TIMER && msg.wParam == SOCK_TIMER_ID)
1407 { 791 {
1408 if (QUITP) 792 if (QUITP)
1447 differences are in status display and process deletion. A network 831 differences are in status display and process deletion. A network
1448 connection has no PID; you cannot signal it. All you can do is 832 connection has no PID; you cannot signal it. All you can do is
1449 deactivate and close it via delete-process */ 833 deactivate and close it via delete-process */
1450 834
1451 static void 835 static void
1452 nt_open_network_stream (Lisp_Object name, Lisp_Object host, 836 nt_open_network_stream (Lisp_Object name, Lisp_Object host, Lisp_Object service,
1453 Lisp_Object service, 837 Lisp_Object family, void** vinfd, void** voutfd)
1454 Lisp_Object protocol, void** vinfd, void** voutfd) 838 {
1455 {
1456 /* !!#### not Mule-ized */
1457 struct sockaddr_in address; 839 struct sockaddr_in address;
1458 SOCKET s; 840 SOCKET s;
1459 int port; 841 int port;
1460 int retval; 842 int retval;
1461 843
1462 CHECK_STRING (host); 844 CHECK_STRING (host);
1463 845
1464 if (!EQ (protocol, Qtcp)) 846 if (!EQ (family, Qtcpip))
1465 signal_simple_error ("Unsupported protocol", protocol); 847 error ("Unsupported protocol family \"%s\"",
848 string_data (symbol_name (XSYMBOL (family))));
1466 849
1467 if (INTP (service)) 850 if (INTP (service))
1468 port = htons ((unsigned short) XINT (service)); 851 port = htons ((unsigned short) XINT (service));
1469 else 852 else
1470 { 853 {
1471 struct servent *svc_info; 854 struct servent *svc_info;
1472 CHECK_STRING (service); 855 CHECK_STRING (service);
1473 svc_info = getservbyname ((char *) XSTRING_DATA (service), "tcp"); 856 svc_info = getservbyname ((char *) XSTRING_DATA (service), "tcp");
1474 if (svc_info == 0) 857 if (svc_info == 0)
1475 signal_simple_error ("Unknown service", service); 858 error ("Unknown service \"%s\"", XSTRING_DATA (service));
1476 port = svc_info->s_port; 859 port = svc_info->s_port;
1477 } 860 }
1478 861
1479 get_internet_address (host, &address, ERROR_ME); 862 get_internet_address (host, &address, ERROR_ME);
1480 address.sin_port = port; 863 address.sin_port = port;
1490 } 873 }
1491 874
1492 retval = connect (s, (struct sockaddr *) &address, sizeof (address)); 875 retval = connect (s, (struct sockaddr *) &address, sizeof (address));
1493 if (retval != NO_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) 876 if (retval != NO_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
1494 goto connect_failed; 877 goto connect_failed;
878
1495 /* Wait while connection is established */ 879 /* Wait while connection is established */
1496 while (1) 880 while (1)
1497 { 881 {
1498 fd_set fdset; 882 fd_set fdset;
1499 struct timeval tv; 883 struct timeval tv;
1532 0, FALSE, DUPLICATE_SAME_ACCESS); 916 0, FALSE, DUPLICATE_SAME_ACCESS);
1533 return; 917 return;
1534 918
1535 connect_failed: 919 connect_failed:
1536 closesocket (s); 920 closesocket (s);
1537 if (INTP (service))
1538 {
1539 warn_when_safe (Qstream, Qwarning,
1540 "failure to open network stream to host \"%s\" for service \"%d\"",
1541 XSTRING_DATA (host),
1542 (unsigned short) XINT (service));
1543 }
1544 else
1545 {
1546 warn_when_safe (Qstream, Qwarning,
1547 "failure to open network stream to host \"%s\" for service \"%s\"",
1548 XSTRING_DATA (host),
1549 XSTRING_DATA (service));
1550 }
1551 report_file_error ("connection failed", list2 (host, name)); 921 report_file_error ("connection failed", list2 (host, name));
1552 } 922 }
1553 923
1554 #endif 924 #endif
1555 925
1579 } 949 }
1580 950
1581 void 951 void
1582 syms_of_process_nt (void) 952 syms_of_process_nt (void)
1583 { 953 {
954 defsymbol (&Qnt_quote_process_args, "nt-quote-process-args");
1584 } 955 }
1585 956
1586 void 957 void
1587 vars_of_process_nt (void) 958 vars_of_process_nt (void)
1588 { 959 {
1589 DEFVAR_LISP ("mswindows-quote-process-args", 960 }
1590 &Vmswindows_quote_process_args /*
1591 Non-nil enables quoting of process arguments to ensure correct parsing.
1592 Because Windows does not directly pass argv arrays to child processes,
1593 programs have to reconstruct the argv array by parsing the command
1594 line string. For an argument to contain a space, it must be enclosed
1595 in double quotes or it will be parsed as multiple arguments.
1596
1597 If the value is a character, that character will be used to escape any
1598 quote characters that appear, otherwise a suitable escape character
1599 will be chosen based on the type of the program (normal or Cygwin).
1600 */ );
1601 Vmswindows_quote_process_args = Qt;
1602
1603 DEFVAR_LISP ("mswindows-start-process-share-console",
1604 &Vmswindows_start_process_share_console /*
1605 When nil, new child processes are given a new console.
1606 When non-nil, they share the Emacs console; this has the limitation of
1607 allowing only only DOS subprocess to run at a time (whether started directly
1608 or indirectly by Emacs), and preventing Emacs from cleanly terminating the
1609 subprocess group, but may allow Emacs to interrupt a subprocess that doesn't
1610 otherwise respond to interrupts from Emacs.
1611 */ );
1612 Vmswindows_start_process_share_console = Qnil;
1613
1614 DEFVAR_LISP ("mswindows-start-process-inherit-error-mode",
1615 &Vmswindows_start_process_inherit_error_mode /*
1616 "When nil, new child processes revert to the default error mode.
1617 When non-nil, they inherit their error mode setting from Emacs, which stops
1618 them blocking when trying to access unmounted drives etc.
1619 */ );
1620 Vmswindows_start_process_inherit_error_mode = Qt;
1621 }