-/* Process support for GNU Emacs on the Microsoft W32 API.
- Copyright (C) 1992, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+/* Process support for GNU Emacs on the Microsoft Windows API.
+ Copyright (C) 1992, 1995, 1999-2012 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <fcntl.h>
#include <signal.h>
#include <sys/file.h>
-#include <setjmp.h>
/* must include CRT headers *before* config.h */
-
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#undef signal
#undef wait
#include <windows.h>
#ifdef __GNUC__
/* This definition is missing from mingw32 headers. */
-extern BOOL WINAPI IsValidLocale(LCID, DWORD);
+extern BOOL WINAPI IsValidLocale (LCID, DWORD);
#endif
#ifdef HAVE_LANGINFO_CODESET
#endif
#include "lisp.h"
-#include "character.h"
#include "w32.h"
#include "w32heap.h"
#include "systime.h"
+ ((DWORD)(var) - (section)->VirtualAddress) \
+ (filedata).file_base))
-/* Control whether spawnve quotes arguments as necessary to ensure
- correct parsing by child process. Because not all uses of spawnve
- are careful about constructing argv arrays, we make this behavior
- conditional (off by default). */
-Lisp_Object Vw32_quote_process_args;
-
-/* Control whether create_child causes the process' window to be
- hidden. The default is nil. */
-Lisp_Object Vw32_start_process_show_window;
-
-/* Control whether create_child causes the process to inherit Emacs'
- console window, or be given a new one of its own. The default is
- nil, to allow multiple DOS programs to run on Win95. Having separate
- consoles also allows Emacs to cleanly terminate process groups. */
-Lisp_Object Vw32_start_process_share_console;
-
-/* Control whether create_child cause the process to inherit Emacs'
- error mode setting. The default is t, to minimize the possibility of
- subprocesses blocking when accessing unmounted drives. */
-Lisp_Object Vw32_start_process_inherit_error_mode;
-
-/* Time to sleep before reading from a subprocess output pipe - this
- avoids the inefficiency of frequently reading small amounts of data.
- This is primarily necessary for handling DOS processes on Windows 95,
- but is useful for W32 processes on both Windows 95 and NT as well. */
-int w32_pipe_read_delay;
-
-/* Control conversion of upper case file names to lower case.
- nil means no, t means yes. */
-Lisp_Object Vw32_downcase_file_names;
-
-/* Control whether stat() attempts to generate fake but hopefully
- "accurate" inode values, by hashing the absolute truenames of files.
- This should detect aliasing between long and short names, but still
- allows the possibility of hash collisions. */
-Lisp_Object Vw32_generate_fake_inodes;
-
-/* Control whether stat() attempts to determine file type and link count
- exactly, at the expense of slower operation. Since true hard links
- are supported on NTFS volumes, this is only relevant on NT. */
-Lisp_Object Vw32_get_true_file_attributes;
-extern Lisp_Object Qlocal;
-
Lisp_Object Qhigh, Qlow;
#ifdef EMACSDEBUG
-void _DebPrint (const char *fmt, ...)
+void
+_DebPrint (const char *fmt, ...)
{
char buf[1024];
va_list args;
}
#endif
-typedef void (_CALLBACK_ *signal_handler)(int);
+typedef void (_CALLBACK_ *signal_handler) (int);
/* Signal handlers...SIG_DFL == 0 so this is initialized correctly. */
static signal_handler sig_handlers[NSIG];
-/* Fake signal implementation to record the SIGCHLD handler. */
+static sigset_t sig_mask;
+
+static CRITICAL_SECTION crit_sig;
+
+/* Improve on the CRT 'signal' implementation so that we could record
+ the SIGCHLD handler and fake interval timers. */
signal_handler
sys_signal (int sig, signal_handler handler)
{
signal_handler old;
- if (sig != SIGCHLD)
+ /* SIGCHLD is needed for supporting subprocesses, see sys_kill
+ below. SIGALRM and SIGPROF are used by setitimer. All the
+ others are the only ones supported by the MS runtime. */
+ if (!(sig == SIGCHLD || sig == SIGSEGV || sig == SIGILL
+ || sig == SIGFPE || sig == SIGABRT || sig == SIGTERM
+ || sig == SIGALRM || sig == SIGPROF))
{
errno = EINVAL;
return SIG_ERR;
}
old = sig_handlers[sig];
- sig_handlers[sig] = handler;
+ /* SIGABRT is treated specially because w32.c installs term_ntproc
+ as its handler, so we don't want to override that afterwards.
+ Aborting Emacs works specially anyway: either by calling
+ emacs_abort directly or through terminate_due_to_signal, which
+ calls emacs_abort through emacs_raise. */
+ if (!(sig == SIGABRT && old == term_ntproc))
+ {
+ sig_handlers[sig] = handler;
+ if (!(sig == SIGCHLD || sig == SIGALRM || sig == SIGPROF))
+ signal (sig, handler);
+ }
return old;
}
+/* Emulate sigaction. */
+int
+sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
+{
+ signal_handler old = SIG_DFL;
+ int retval = 0;
+
+ if (act)
+ old = sys_signal (sig, act->sa_handler);
+ else if (oact)
+ old = sig_handlers[sig];
+
+ if (old == SIG_ERR)
+ {
+ errno = EINVAL;
+ retval = -1;
+ }
+ if (oact)
+ {
+ oact->sa_handler = old;
+ oact->sa_flags = 0;
+ oact->sa_mask = empty_mask;
+ }
+ return retval;
+}
+
+/* Emulate signal sets and blocking of signals used by timers. */
+
+int
+sigemptyset (sigset_t *set)
+{
+ *set = 0;
+ return 0;
+}
+
+int
+sigaddset (sigset_t *set, int signo)
+{
+ if (!set)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ if (signo < 0 || signo >= NSIG)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ *set |= (1U << signo);
+
+ return 0;
+}
+
+int
+sigfillset (sigset_t *set)
+{
+ if (!set)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ *set = 0xFFFFFFFF;
+ return 0;
+}
+
+int
+sigprocmask (int how, const sigset_t *set, sigset_t *oset)
+{
+ if (!(how == SIG_BLOCK || how == SIG_UNBLOCK || how == SIG_SETMASK))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (oset)
+ *oset = sig_mask;
+
+ if (!set)
+ return 0;
+
+ switch (how)
+ {
+ case SIG_BLOCK:
+ sig_mask |= *set;
+ break;
+ case SIG_SETMASK:
+ sig_mask = *set;
+ break;
+ case SIG_UNBLOCK:
+ /* FIXME: Catch signals that are blocked and reissue them when
+ they are unblocked. Important for SIGALRM and SIGPROF only. */
+ sig_mask &= ~(*set);
+ break;
+ }
+
+ return 0;
+}
+
+int
+pthread_sigmask (int how, const sigset_t *set, sigset_t *oset)
+{
+ if (sigprocmask (how, set, oset) == -1)
+ return EINVAL;
+ return 0;
+}
+
+int
+sigismember (const sigset_t *set, int signo)
+{
+ if (signo < 0 || signo >= NSIG)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ if (signo > sizeof (*set) * BITS_PER_CHAR)
+ emacs_abort ();
+
+ return (*set & (1U << signo)) != 0;
+}
+
+int
+setpgrp (int pid, int gid)
+{
+ return 0;
+}
+
+/* Emulations of interval timers.
+
+ Limitations: only ITIMER_REAL and ITIMER_PROF are supported.
+
+ Implementation: a separate thread is started for each timer type,
+ the thread calls the appropriate signal handler when the timer
+ expires, after stopping the thread which installed the timer. */
+
+/* FIXME: clock_t counts overflow after 49 days, need to handle the
+ wrap-around. */
+struct itimer_data {
+ clock_t expire;
+ clock_t reload;
+ int terminate;
+ int type;
+ HANDLE caller_thread;
+ HANDLE timer_thread;
+};
+
+static clock_t ticks_now;
+static struct itimer_data real_itimer, prof_itimer;
+static clock_t clocks_min;
+
+static CRITICAL_SECTION crit_real, crit_prof;
+
+#define MAX_SINGLE_SLEEP 30
+
+static DWORD WINAPI
+timer_loop (LPVOID arg)
+{
+ struct itimer_data *itimer = (struct itimer_data *)arg;
+ int which = itimer->type;
+ int sig = (which == ITIMER_REAL) ? SIGALRM : SIGPROF;
+ CRITICAL_SECTION *crit = (which == ITIMER_REAL) ? &crit_real : &crit_prof;
+ const DWORD max_sleep = MAX_SINGLE_SLEEP * 1000 / CLOCKS_PER_SEC;
+ int new_count = 0;
+
+ while (1)
+ {
+ DWORD sleep_time;
+ signal_handler handler;
+ clock_t now, expire, reload;
+
+ /* Load new values if requested by setitimer. */
+ EnterCriticalSection (crit);
+ expire = itimer->expire;
+ reload = itimer->reload;
+ LeaveCriticalSection (crit);
+ if (itimer->terminate)
+ return 0;
+
+ if (itimer->expire == 0)
+ {
+ /* We are idle. */
+ Sleep (max_sleep);
+ continue;
+ }
+
+ expire = itimer->expire;
+ if (expire > (now = clock ()))
+ sleep_time = expire - now;
+ else
+ sleep_time = 0;
+ /* Don't sleep too long at a time, to be able to see the
+ termination flag without too long a delay. */
+ while (sleep_time > max_sleep)
+ {
+ if (itimer->terminate)
+ return 0;
+ Sleep (max_sleep);
+ expire = itimer->expire;
+ sleep_time = (expire > (now = clock ())) ? expire - now : 0;
+ }
+ if (itimer->terminate)
+ return 0;
+ if (sleep_time > 0)
+ {
+ Sleep (sleep_time * 1000 / CLOCKS_PER_SEC);
+ /* Always sleep past the expiration time, to make sure we
+ never call the handler _before_ the expiration time,
+ always slightly after it. Sleep(0) relinquishes the rest
+ of the scheduled slot, so that we let other threads
+ work. */
+ while (clock () < expire)
+ Sleep (0);
+ }
+
+ if (itimer->expire == 0)
+ continue;
+
+ /* Time's up. */
+ handler = sig_handlers[sig];
+ if (!(handler == SIG_DFL || handler == SIG_IGN || handler == SIG_ERR)
+ /* FIXME: Don't ignore masked signals. Instead, record that
+ they happened and reissue them when the signal is
+ unblocked. */
+ && !sigismember (&sig_mask, sig)
+ /* Simulate masking of SIGALRM and SIGPROF when processing
+ fatal signals. */
+ && !fatal_error_in_progress
+ && itimer->caller_thread)
+ {
+ /* Simulate a signal delivered to the thread which installed
+ the timer, by suspending that thread while the handler
+ runs. */
+ DWORD result = SuspendThread (itimer->caller_thread);
+
+ if (result == (DWORD)-1)
+ {
+ DebPrint (("Thread %d exiting with status 2\n", which));
+ return 2;
+ }
+ handler (sig);
+ ResumeThread (itimer->caller_thread);
+ }
+
+ if (itimer->expire == 0)
+ continue;
+
+ /* Update expiration time and loop. */
+ EnterCriticalSection (crit);
+ expire = itimer->expire;
+ reload = itimer->reload;
+ if (reload > 0)
+ {
+ now = clock ();
+ if (expire <= now)
+ {
+ clock_t lag = now - expire;
+
+ /* If we missed some opportunities (presumably while
+ sleeping or while the signal handler ran), skip
+ them. */
+ if (lag > reload)
+ expire = now - (lag % reload);
+
+ expire += reload;
+ }
+ }
+ else
+ expire = 0; /* become idle */
+ itimer->expire = expire;
+ LeaveCriticalSection (crit);
+ }
+ return 0;
+}
+
+static void
+stop_timer_thread (int which)
+{
+ struct itimer_data *itimer =
+ (which == ITIMER_REAL) ? &real_itimer : &prof_itimer;
+ int i;
+ DWORD exit_code = 255;
+ BOOL status, err;
+
+ /* Signal the thread that it should terminate. */
+ itimer->terminate = 1;
+
+ if (itimer->timer_thread == NULL)
+ return;
+
+ /* Wait for the timer thread to terminate voluntarily, then kill it
+ if it doesn't. This loop waits twice more than the maximum
+ amount of time a timer thread sleeps, see above. */
+ for (i = 0; i < MAX_SINGLE_SLEEP / 5; i++)
+ {
+ if (!((status = GetExitCodeThread (itimer->timer_thread, &exit_code))
+ && exit_code == STILL_ACTIVE))
+ break;
+ Sleep (10);
+ }
+ if ((status == FALSE && (err = GetLastError ()) == ERROR_INVALID_HANDLE)
+ || exit_code == STILL_ACTIVE)
+ {
+ if (!(status == FALSE && err == ERROR_INVALID_HANDLE))
+ TerminateThread (itimer->timer_thread, 0);
+ }
+
+ /* Clean up. */
+ CloseHandle (itimer->timer_thread);
+ itimer->timer_thread = NULL;
+ if (itimer->caller_thread)
+ {
+ CloseHandle (itimer->caller_thread);
+ itimer->caller_thread = NULL;
+ }
+}
+
+/* This is called at shutdown time from term_ntproc. */
+void
+term_timers (void)
+{
+ if (real_itimer.timer_thread)
+ stop_timer_thread (ITIMER_REAL);
+ if (prof_itimer.timer_thread)
+ stop_timer_thread (ITIMER_PROF);
+
+ DeleteCriticalSection (&crit_real);
+ DeleteCriticalSection (&crit_prof);
+ DeleteCriticalSection (&crit_sig);
+}
+
+/* This is called at initialization time from init_ntproc. */
+void
+init_timers (void)
+{
+ /* Make sure we start with zeroed out itimer structures, since
+ dumping may have left there traces of threads long dead. */
+ memset (&real_itimer, 0, sizeof real_itimer);
+ memset (&prof_itimer, 0, sizeof prof_itimer);
+
+ InitializeCriticalSection (&crit_real);
+ InitializeCriticalSection (&crit_prof);
+ InitializeCriticalSection (&crit_sig);
+}
+
+static int
+start_timer_thread (int which)
+{
+ DWORD exit_code;
+ struct itimer_data *itimer =
+ (which == ITIMER_REAL) ? &real_itimer : &prof_itimer;
+
+ if (itimer->timer_thread
+ && GetExitCodeThread (itimer->timer_thread, &exit_code)
+ && exit_code == STILL_ACTIVE)
+ return 0;
+
+ /* Start a new thread. */
+ if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
+ GetCurrentProcess (), &itimer->caller_thread, 0,
+ FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ errno = ESRCH;
+ return -1;
+ }
+
+ itimer->terminate = 0;
+ itimer->type = which;
+ /* Request that no more than 64KB of stack be reserved for this
+ thread, to avoid reserving too much memory, which would get in
+ the way of threads we start to wait for subprocesses. See also
+ new_child below. */
+ itimer->timer_thread = CreateThread (NULL, 64 * 1024, timer_loop,
+ (void *)itimer, 0x00010000, NULL);
+
+ if (!itimer->timer_thread)
+ {
+ CloseHandle (itimer->caller_thread);
+ itimer->caller_thread = NULL;
+ errno = EAGAIN;
+ return -1;
+ }
+
+ /* This is needed to make sure that the timer thread running for
+ profiling gets CPU as soon as the Sleep call terminates. */
+ if (which == ITIMER_PROF)
+ SetThreadPriority (itimer->caller_thread, THREAD_PRIORITY_TIME_CRITICAL);
+
+ return 0;
+}
+
+/* Most of the code of getitimer and setitimer (but not of their
+ subroutines) was shamelessly stolen from itimer.c in the DJGPP
+ library, see www.delorie.com/djgpp. */
+int
+getitimer (int which, struct itimerval *value)
+{
+ volatile clock_t *t_expire;
+ volatile clock_t *t_reload;
+ clock_t expire, reload;
+ __int64 usecs;
+ CRITICAL_SECTION *crit;
+
+ ticks_now = clock ();
+
+ if (!value)
+ {
+ errno = EFAULT;
+ return -1;
+ }
+
+ if (which != ITIMER_REAL && which != ITIMER_PROF)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ t_expire = (which == ITIMER_REAL) ? &real_itimer.expire: &prof_itimer.expire;
+ t_reload = (which == ITIMER_REAL) ? &real_itimer.reload: &prof_itimer.reload;
+ crit = (which == ITIMER_REAL) ? &crit_real : &crit_prof;
+
+ EnterCriticalSection (crit);
+ reload = *t_reload;
+ expire = *t_expire;
+ LeaveCriticalSection (crit);
+
+ if (expire)
+ expire -= ticks_now;
+
+ value->it_value.tv_sec = expire / CLOCKS_PER_SEC;
+ usecs = (expire % CLOCKS_PER_SEC) * (__int64)1000000 / CLOCKS_PER_SEC;
+ value->it_value.tv_usec = usecs;
+ value->it_interval.tv_sec = reload / CLOCKS_PER_SEC;
+ usecs = (reload % CLOCKS_PER_SEC) * (__int64)1000000 / CLOCKS_PER_SEC;
+ value->it_interval.tv_usec= usecs;
+
+ return 0;
+}
+
+int
+setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
+{
+ volatile clock_t *t_expire, *t_reload;
+ clock_t expire, reload, expire_old, reload_old;
+ __int64 usecs;
+ CRITICAL_SECTION *crit;
+
+ /* Posix systems expect timer values smaller than the resolution of
+ the system clock be rounded up to the clock resolution. First
+ time we are called, measure the clock tick resolution. */
+ if (!clocks_min)
+ {
+ clock_t t1, t2;
+
+ for (t1 = clock (); (t2 = clock ()) == t1; )
+ ;
+ clocks_min = t2 - t1;
+ }
+
+ if (ovalue)
+ {
+ if (getitimer (which, ovalue)) /* also sets ticks_now */
+ return -1; /* errno already set */
+ }
+ else
+ ticks_now = clock ();
+
+ if (which != ITIMER_REAL && which != ITIMER_PROF)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ t_expire =
+ (which == ITIMER_REAL) ? &real_itimer.expire : &prof_itimer.expire;
+ t_reload =
+ (which == ITIMER_REAL) ? &real_itimer.reload : &prof_itimer.reload;
+
+ crit = (which == ITIMER_REAL) ? &crit_real : &crit_prof;
+
+ if (!value
+ || (value->it_value.tv_sec == 0 && value->it_value.tv_usec == 0))
+ {
+ EnterCriticalSection (crit);
+ /* Disable the timer. */
+ *t_expire = 0;
+ *t_reload = 0;
+ LeaveCriticalSection (crit);
+ return 0;
+ }
+
+ reload = value->it_interval.tv_sec * CLOCKS_PER_SEC;
+
+ usecs = value->it_interval.tv_usec;
+ if (value->it_interval.tv_sec == 0
+ && usecs && usecs * CLOCKS_PER_SEC < clocks_min * 1000000)
+ reload = clocks_min;
+ else
+ {
+ usecs *= CLOCKS_PER_SEC;
+ reload += usecs / 1000000;
+ }
+
+ expire = value->it_value.tv_sec * CLOCKS_PER_SEC;
+ usecs = value->it_value.tv_usec;
+ if (value->it_value.tv_sec == 0
+ && usecs * CLOCKS_PER_SEC < clocks_min * 1000000)
+ expire = clocks_min;
+ else
+ {
+ usecs *= CLOCKS_PER_SEC;
+ expire += usecs / 1000000;
+ }
+
+ expire += ticks_now;
+
+ EnterCriticalSection (crit);
+ expire_old = *t_expire;
+ reload_old = *t_reload;
+ if (!(expire == expire_old && reload == reload_old))
+ {
+ *t_reload = reload;
+ *t_expire = expire;
+ }
+ LeaveCriticalSection (crit);
+
+ return start_timer_thread (which);
+}
+
+int
+alarm (int seconds)
+{
+ struct itimerval new_values;
+
+ new_values.it_value.tv_sec = seconds;
+ new_values.it_value.tv_usec = 0;
+ new_values.it_interval.tv_sec = new_values.it_interval.tv_usec = 0;
+
+ setitimer (ITIMER_REAL, &new_values, NULL);
+
+ return seconds;
+}
+
/* Defined in <process.h> which conflicts with the local copy */
#define _P_NOWAIT 1
child_process child_procs[ MAX_CHILDREN ];
child_process *dead_child = NULL;
-DWORD WINAPI reader_thread (void *arg);
+static DWORD WINAPI reader_thread (void *arg);
/* Find an unused process slot. */
child_process *
child_process *cp;
DWORD id;
- for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
+ for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
if (!CHILD_ACTIVE (cp))
- goto Initialise;
+ goto Initialize;
if (child_proc_count == MAX_CHILDREN)
return NULL;
cp = &child_procs[child_proc_count++];
- Initialise:
- memset (cp, 0, sizeof(*cp));
+ Initialize:
+ memset (cp, 0, sizeof (*cp));
cp->fd = -1;
cp->pid = -1;
cp->procinfo.hProcess = NULL;
cp->char_consumed = CreateEvent (NULL, FALSE, FALSE, NULL);
if (cp->char_consumed)
{
- cp->thrd = CreateThread (NULL, 1024, reader_thread, cp, 0, &id);
+ /* The 0x00010000 flag is STACK_SIZE_PARAM_IS_A_RESERVATION.
+ It means that the 64K stack we are requesting in the 2nd
+ argument is how much memory should be reserved for the
+ stack. If we don't use this flag, the memory requested
+ by the 2nd argument is the amount actually _committed_,
+ but Windows reserves 8MB of memory for each thread's
+ stack. (The 8MB figure comes from the -stack
+ command-line argument we pass to the linker when building
+ Emacs, but that's because we need a large stack for
+ Emacs's main thread.) Since we request 2GB of reserved
+ memory at startup (see w32heap.c), which is close to the
+ maximum memory available for a 32-bit process on Windows,
+ the 8MB reservation for each thread causes failures in
+ starting subprocesses, because we create a thread running
+ reader_thread for each subprocess. As 8MB of stack is
+ way too much for reader_thread, forcing Windows to
+ reserve less wins the day. */
+ cp->thrd = CreateThread (NULL, 64 * 1024, reader_thread, cp,
+ 0x00010000, &id);
if (cp->thrd)
return cp;
}
/* Should not be deleting a child that is still needed. */
for (i = 0; i < MAXDESC; i++)
if (fd_info[i].cp == cp)
- abort ();
+ emacs_abort ();
if (!CHILD_ACTIVE (cp))
return;
cp->status = STATUS_READ_ERROR;
SetEvent (cp->char_consumed);
#if 0
- /* We used to forceably terminate the thread here, but it
+ /* We used to forcibly terminate the thread here, but it
is normally unnecessary, and in abnormal cases, the worst that
will happen is we have an extra idle thread hanging around
waiting for the zombie process. */
{
child_process *cp;
- for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
+ for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
if (CHILD_ACTIVE (cp) && pid == cp->pid)
return cp;
return NULL;
is normally blocked until woken by select() to check for input by
reading one char. When the read completes, char_avail is signaled
to wake up the select emulator and the thread blocks itself again. */
-DWORD WINAPI
+static DWORD WINAPI
reader_thread (void *arg)
{
child_process *cp;
/* We have to wait for the go-ahead before we can start */
if (cp == NULL
- || WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
+ || WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0
+ || cp->fd < 0)
return 1;
for (;;)
DWORD flags;
char dir[ MAXPATHLEN ];
- if (cp == NULL) abort ();
+ if (cp == NULL) emacs_abort ();
memset (&start, 0, sizeof (start));
start.cb = sizeof (start);
return TRUE;
EH_Fail:
- DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError()););
+ DebPrint (("create_child.CreateProcess failed: %ld\n", GetLastError ()););
return FALSE;
}
if (fd_info[fd].cp != NULL)
{
DebPrint (("register_child: fd_info[%d] apparently in use!\n", fd));
- abort ();
+ emacs_abort ();
}
fd_info[fd].cp = cp;
/* We want to wait for a specific child */
wait_hnd[nh] = dead_child->procinfo.hProcess;
cps[nh] = dead_child;
- if (!wait_hnd[nh]) abort ();
+ if (!wait_hnd[nh]) emacs_abort ();
nh++;
active = 0;
goto get_result;
}
else
{
- for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
+ for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
/* some child_procs might be sockets; ignore them */
if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess
&& (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0))
active -= WAIT_ABANDONED_0;
}
else
- abort ();
+ emacs_abort ();
get_result:
if (!GetExitCodeProcess (wait_hnd[active], &retval))
/* Report the status of the synchronous process. */
if (WIFEXITED (retval))
- synch_process_retcode = WRETCODE (retval);
+ synch_process_retcode = WEXITSTATUS (retval);
else if (WIFSIGNALED (retval))
{
int code = WTERMSIG (retval);
# define IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER
#endif
-void
-w32_executable_type (char * filename, int * is_dos_app, int * is_cygnus_app, int * is_gui_app)
+static void
+w32_executable_type (char * filename,
+ int * is_dos_app,
+ int * is_cygnus_app,
+ int * is_gui_app)
{
file_data executable;
char * p;
close_file_data (&executable);
}
-int
+static int
compare_env (const void *strp1, const void *strp2)
{
const char *str1 = *(const char **)strp1, *str2 = *(const char **)strp2;
return 1;
}
-void
+static void
merge_and_sort_env (char **envp1, char **envp2, char **new_envp)
{
char **optr, **nptr;
}
/* Handle executable names without an executable suffix. */
- program = make_string (cmdname, strlen (cmdname));
+ program = build_string (cmdname);
if (NILP (Ffile_executable_p (program)))
{
struct gcpro gcpro1;
unixtodos_filename (cmdname);
argv[0] = cmdname;
- /* Determine whether program is a 16-bit DOS executable, or a w32
+ /* Determine whether program is a 16-bit DOS executable, or a 32-bit Windows
executable that is implicitly linked to the Cygnus dll (implying it
was compiled with the Cygnus GNU toolchain and hence relies on
cygwin.dll to parse the command line - we use this to decide how to
The w32 GNU-based library from Cygnus doubles quotes to escape
them, while MSVC uses backslash for escaping. (Actually the MSVC
- startup code does attempt to recognise doubled quotes and accept
+ startup code does attempt to recognize doubled quotes and accept
them, but gets it wrong and ends up requiring three quotes to get a
single embedded quote!) So by default we decide whether to use
quote or backslash as the escape character based on whether the
Note that using backslash to escape embedded quotes requires
additional special handling if an embedded quote is already
- preceeded by backslash, or if an arg requiring quoting ends with
+ preceded by backslash, or if an arg requiring quoting ends with
backslash. In such cases, the run of escape characters needs to be
doubled. For consistency, we apply this special handling as long
as the escape character is not quote.
escape_char = is_cygnus_app ? '"' : '\\';
}
- /* Cygwin apps needs quoting a bit more often */
+ /* Cygwin apps needs quoting a bit more often. */
if (escape_char == '"')
sepchars = "\r\n\t\f '";
detect that we were woken up by C-g, we return -1 with errno set to
EINTR as on Unix. */
-/* From ntterm.c */
+/* From w32console.c */
extern HANDLE keyboard_handle;
/* From w32xfns.c */
int
sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
- EMACS_TIME *timeout)
+ EMACS_TIME *timeout, void *ignored)
{
SELECT_TYPE orfds;
DWORD timeout_ms, start_time;
HANDLE wait_hnd[MAXDESC + MAX_CHILDREN];
int fdindex[MAXDESC]; /* mapping from wait handles back to descriptors */
- timeout_ms = timeout ? (timeout->tv_sec * 1000 + timeout->tv_usec / 1000) : INFINITE;
+ timeout_ms =
+ timeout ? (timeout->tv_sec * 1000 + timeout->tv_nsec / 1000000) : INFINITE;
/* If the descriptor sets are NULL but timeout isn't, then just Sleep. */
if (rfds == NULL && wfds == NULL && efds == NULL && timeout != NULL)
#endif
wait_hnd[nh] = cp->char_avail;
fdindex[nh] = i;
- if (!wait_hnd[nh]) abort ();
+ if (!wait_hnd[nh]) emacs_abort ();
nh++;
#ifdef FULL_DEBUG
DebPrint (("select waiting on child %d fd %d\n",
count_children:
/* Add handles of child processes. */
nc = 0;
- for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
+ for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
/* Some child_procs might be sockets; ignore them. Also some
children may have died already, but we haven't finished reading
the process output; ignore them too. */
active -= WAIT_ABANDONED_0;
}
else
- abort ();
+ emacs_abort ();
/* Loop over all handles after active (now officially documented as
being the first signaled handle in the array). We do this to
GetClassName (hwnd, window_class, sizeof (window_class));
if (strcmp (window_class,
- (os_subtype == OS_WIN95)
+ (os_subtype == OS_9X)
? "tty"
: "ConsoleWindowClass") == 0)
{
return TRUE;
}
+/* Emulate 'kill', but only for other processes. */
int
sys_kill (int pid, int sig)
{
cp = find_child_pid (pid);
if (cp == NULL)
{
+ /* We were passed a PID of something other than our subprocess.
+ If that is our own PID, we will send to ourself a message to
+ close the selected frame, which does not necessarily
+ terminates Emacs. But then we are not supposed to call
+ sys_kill with our own PID. */
proc_hand = OpenProcess (PROCESS_TERMINATE, 0, pid);
if (proc_hand == NULL)
{
if (NILP (Vw32_start_process_share_console) && cp && cp->hwnd)
{
#if 1
- if (os_subtype == OS_WIN95)
+ if (os_subtype == OS_9X)
{
/*
Another possibility is to try terminating the VDM out-right by
*/
#if 0
- /* On Win95, posting WM_QUIT causes the 16-bit subsystem
+ /* On Windows 95, posting WM_QUIT causes the 16-bit subsystem
to hang when cmdproxy is used in conjunction with
command.com for an interactive shell. Posting
WM_CLOSE pops up a dialog that, when Yes is selected,
return rc;
}
-/* extern int report_file_error (char *, Lisp_Object); */
-
/* The following two routines are used to manipulate stdin, stdout, and
stderr of our child processes.
process_dir = dir;
}
-#ifdef HAVE_SOCKETS
-
/* To avoid problems with winsock implementations that work over dial-up
connections causing or requiring a connection to exist while Emacs is
running, Emacs no longer automatically loads winsock on startup if it
dial-up users to only be connected when they actually need to use
socket services. */
-/* From nt.c */
+/* From w32.c */
extern HANDLE winsock_lib;
extern BOOL term_winsock (void);
extern BOOL init_winsock (int load_now);
-extern Lisp_Object Vsystem_name;
-
DEFUN ("w32-has-winsock", Fw32_has_winsock, Sw32_has_winsock, 0, 1, 0,
doc: /* Test for presence of the Windows socket library `winsock'.
Returns non-nil if winsock support is present, nil otherwise.
the winsock local hostname is returned (since this may be different from
the value of `system-name' and should supplant it), otherwise t is
returned to indicate winsock support is present. */)
- (load_now)
- Lisp_Object load_now;
+ (Lisp_Object load_now)
{
int have_winsock;
This is provided to allow dial-up socket connections to be disconnected
when no longer needed. Returns nil without unloading winsock if any
socket connections still exist. */)
- ()
+ (void)
{
return term_winsock () ? Qt : Qnil;
}
-#endif /* HAVE_SOCKETS */
-
\f
/* Some miscellaneous functions that are Windows specific, but not GUI
specific (ie. are applicable in terminal or batch mode as well). */
doc: /* Return the short file name version (8.3) of the full path of FILENAME.
If FILENAME does not exist, return nil.
All path elements in FILENAME are converted to their short names. */)
- (filename)
- Lisp_Object filename;
+ (Lisp_Object filename)
{
char shortname[MAX_PATH];
doc: /* Return the long file name version of the full path of FILENAME.
If FILENAME does not exist, return nil.
All path elements in FILENAME are converted to their long names. */)
- (filename)
- Lisp_Object filename;
+ (Lisp_Object filename)
{
char longname[ MAX_PATH ];
int drive_only = 0;
any other symbol will be interpreted as normal.
If successful, the return value is t, otherwise nil. */)
- (process, priority)
- Lisp_Object process, priority;
+ (Lisp_Object process, Lisp_Object priority)
{
HANDLE proc_handle = GetCurrentProcess ();
DWORD priority_class = NORMAL_PRIORITY_CLASS;
CHECK_NUMBER (process);
/* Allow pid to be an internally generated one, or one obtained
- externally. This is necessary because real pids on Win95 are
+ externally. This is necessary because real pids on Windows 95 are
negative. */
pid = XINT (process);
#ifdef HAVE_LANGINFO_CODESET
/* Emulation of nl_langinfo. Used in fns.c:Flocale_info. */
-char *nl_langinfo (nl_item item)
+char *
+nl_langinfo (nl_item item)
{
/* Conversion of Posix item numbers to their Windows equivalents. */
static const LCTYPE w32item[] = {
locale information is returned.
If LCID (a 16-bit number) is not a valid locale, the result is nil. */)
- (lcid, longform)
- Lisp_Object lcid, longform;
+ (Lisp_Object lcid, Lisp_Object longform)
{
int got_abbrev;
int got_full;
got_full = GetLocaleInfo (XINT (lcid),
XINT (longform),
full_name, sizeof (full_name));
+ /* GetLocaleInfo's return value includes the terminating null
+ character, when the returned information is a string, whereas
+ make_unibyte_string needs the string length without the
+ terminating null. */
if (got_full)
- return make_unibyte_string (full_name, got_full);
+ return make_unibyte_string (full_name, got_full - 1);
}
return Qnil;
doc: /* Return Windows locale id for current locale setting.
This is a numerical value; use `w32-get-locale-info' to convert to a
human-readable form. */)
- ()
+ (void)
{
return make_number (GetThreadLocale ());
}
-DWORD int_from_hex (char * s)
+static DWORD
+int_from_hex (char * s)
{
DWORD val = 0;
static char hex[] = "0123456789abcdefABCDEF";
char * p;
- while (*s && (p = strchr(hex, *s)) != NULL)
+ while (*s && (p = strchr (hex, *s)) != NULL)
{
unsigned digit = p - hex;
if (digit > 15)
function isn't given a context pointer. */
Lisp_Object Vw32_valid_locale_ids;
-BOOL CALLBACK enum_locale_fn (LPTSTR localeNum)
+static BOOL CALLBACK
+enum_locale_fn (LPTSTR localeNum)
{
DWORD id = int_from_hex (localeNum);
Vw32_valid_locale_ids = Fcons (make_number (id), Vw32_valid_locale_ids);
doc: /* Return list of all valid Windows locale ids.
Each id is a numerical value; use `w32-get-locale-info' to convert to a
human-readable form. */)
- ()
+ (void)
{
Vw32_valid_locale_ids = Qnil;
parameter USERP is non-nil, the user default locale setting is returned.
This is a numerical value; use `w32-get-locale-info' to convert to a
human-readable form. */)
- (userp)
- Lisp_Object userp;
+ (Lisp_Object userp)
{
if (NILP (userp))
return make_number (GetSystemDefaultLCID ());
DEFUN ("w32-set-current-locale", Fw32_set_current_locale, Sw32_set_current_locale, 1, 1, 0,
doc: /* Make Windows locale LCID be the current locale setting for Emacs.
If successful, the new locale id is returned, otherwise nil. */)
- (lcid)
- Lisp_Object lcid;
+ (Lisp_Object lcid)
{
CHECK_NUMBER (lcid);
function isn't given a context pointer. */
Lisp_Object Vw32_valid_codepages;
-BOOL CALLBACK enum_codepage_fn (LPTSTR codepageNum)
+static BOOL CALLBACK
+enum_codepage_fn (LPTSTR codepageNum)
{
DWORD id = atoi (codepageNum);
Vw32_valid_codepages = Fcons (make_number (id), Vw32_valid_codepages);
DEFUN ("w32-get-valid-codepages", Fw32_get_valid_codepages,
Sw32_get_valid_codepages, 0, 0, 0,
doc: /* Return list of all valid Windows codepages. */)
- ()
+ (void)
{
Vw32_valid_codepages = Qnil;
DEFUN ("w32-get-console-codepage", Fw32_get_console_codepage,
Sw32_get_console_codepage, 0, 0, 0,
doc: /* Return current Windows codepage for console input. */)
- ()
+ (void)
{
return make_number (GetConsoleCP ());
}
DEFUN ("w32-set-console-codepage", Fw32_set_console_codepage,
Sw32_set_console_codepage, 1, 1, 0,
- doc: /* Make Windows codepage CP be the current codepage setting for Emacs.
-The codepage setting affects keyboard input and display in tty mode.
+ doc: /* Make Windows codepage CP be the codepage for Emacs tty keyboard input.
+This codepage setting affects keyboard input in tty mode.
If successful, the new CP is returned, otherwise nil. */)
- (cp)
- Lisp_Object cp;
+ (Lisp_Object cp)
{
CHECK_NUMBER (cp);
DEFUN ("w32-get-console-output-codepage", Fw32_get_console_output_codepage,
Sw32_get_console_output_codepage, 0, 0, 0,
doc: /* Return current Windows codepage for console output. */)
- ()
+ (void)
{
return make_number (GetConsoleOutputCP ());
}
DEFUN ("w32-set-console-output-codepage", Fw32_set_console_output_codepage,
Sw32_set_console_output_codepage, 1, 1, 0,
- doc: /* Make Windows codepage CP be the current codepage setting for Emacs.
-The codepage setting affects keyboard input and display in tty mode.
+ doc: /* Make Windows codepage CP be the codepage for Emacs console output.
+This codepage setting affects display in tty mode.
If successful, the new CP is returned, otherwise nil. */)
- (cp)
- Lisp_Object cp;
+ (Lisp_Object cp)
{
CHECK_NUMBER (cp);
DEFUN ("w32-get-codepage-charset", Fw32_get_codepage_charset,
Sw32_get_codepage_charset, 1, 1, 0,
- doc: /* Return charset of codepage CP.
+ doc: /* Return charset ID corresponding to codepage CP.
Returns nil if the codepage is not valid. */)
- (cp)
- Lisp_Object cp;
+ (Lisp_Object cp)
{
CHARSETINFO info;
Sw32_get_valid_keyboard_layouts, 0, 0, 0,
doc: /* Return list of Windows keyboard languages and layouts.
The return value is a list of pairs of language id and layout id. */)
- ()
+ (void)
{
int num_layouts = GetKeyboardLayoutList (0, NULL);
HKL * layouts = (HKL *) alloca (num_layouts * sizeof (HKL));
Sw32_get_keyboard_layout, 0, 0, 0,
doc: /* Return current Windows keyboard language and layout.
The return value is the cons of the language id and the layout id. */)
- ()
+ (void)
{
DWORD kl = (DWORD) GetKeyboardLayout (dwWindowsThreadId);
doc: /* Make LAYOUT be the current keyboard layout for Emacs.
The keyboard layout setting affects interpretation of keyboard input.
If successful, the new layout id is returned, otherwise nil. */)
- (layout)
- Lisp_Object layout;
+ (Lisp_Object layout)
{
DWORD kl;
}
\f
-syms_of_ntproc ()
+void
+syms_of_ntproc (void)
{
DEFSYM (Qhigh, "high");
DEFSYM (Qlow, "low");
-#ifdef HAVE_SOCKETS
defsubr (&Sw32_has_winsock);
defsubr (&Sw32_unload_winsock);
-#endif
+
defsubr (&Sw32_short_file_name);
defsubr (&Sw32_long_file_name);
defsubr (&Sw32_set_process_priority);
defsubr (&Sw32_get_keyboard_layout);
defsubr (&Sw32_set_keyboard_layout);
- DEFVAR_LISP ("w32-quote-process-args", &Vw32_quote_process_args,
+ DEFVAR_LISP ("w32-quote-process-args", Vw32_quote_process_args,
doc: /* Non-nil enables quoting of process arguments to ensure correct parsing.
Because Windows does not directly pass argv arrays to child processes,
programs have to reconstruct the argv array by parsing the command
Vw32_quote_process_args = Qt;
DEFVAR_LISP ("w32-start-process-show-window",
- &Vw32_start_process_show_window,
+ Vw32_start_process_show_window,
doc: /* When nil, new child processes hide their windows.
When non-nil, they show their window in the method of their choice.
This variable doesn't affect GUI applications, which will never be hidden. */);
Vw32_start_process_show_window = Qnil;
DEFVAR_LISP ("w32-start-process-share-console",
- &Vw32_start_process_share_console,
+ Vw32_start_process_share_console,
doc: /* When nil, new child processes are given a new console.
When non-nil, they share the Emacs console; this has the limitation of
allowing only one DOS subprocess to run at a time (whether started directly
Vw32_start_process_share_console = Qnil;
DEFVAR_LISP ("w32-start-process-inherit-error-mode",
- &Vw32_start_process_inherit_error_mode,
+ Vw32_start_process_inherit_error_mode,
doc: /* When nil, new child processes revert to the default error mode.
When non-nil, they inherit their error mode setting from Emacs, which stops
them blocking when trying to access unmounted drives etc. */);
Vw32_start_process_inherit_error_mode = Qt;
- DEFVAR_INT ("w32-pipe-read-delay", &w32_pipe_read_delay,
+ DEFVAR_INT ("w32-pipe-read-delay", w32_pipe_read_delay,
doc: /* Forced delay before reading subprocess output.
This is done to improve the buffering of subprocess output, by
avoiding the inefficiency of frequently reading small amounts of data.
process temporarily). A value of zero disables waiting entirely. */);
w32_pipe_read_delay = 50;
- DEFVAR_LISP ("w32-downcase-file-names", &Vw32_downcase_file_names,
+ DEFVAR_LISP ("w32-downcase-file-names", Vw32_downcase_file_names,
doc: /* Non-nil means convert all-upper case file names to lower case.
This applies when performing completions and file name expansion.
Note that the value of this setting also affects remote file names,
Vw32_downcase_file_names = Qnil;
#if 0
- DEFVAR_LISP ("w32-generate-fake-inodes", &Vw32_generate_fake_inodes,
+ DEFVAR_LISP ("w32-generate-fake-inodes", Vw32_generate_fake_inodes,
doc: /* Non-nil means attempt to fake realistic inode values.
This works by hashing the truename of files, and should detect
aliasing between long and short (8.3 DOS) names, but can have
-false positives because of hash collisions. Note that determing
+false positives because of hash collisions. Note that determining
the truename of a file can be slow. */);
Vw32_generate_fake_inodes = Qnil;
#endif
- DEFVAR_LISP ("w32-get-true-file-attributes", &Vw32_get_true_file_attributes,
+ DEFVAR_LISP ("w32-get-true-file-attributes", Vw32_get_true_file_attributes,
doc: /* Non-nil means determine accurate file attributes in `file-attributes'.
This option controls whether to issue additional system calls to determine
accurate link counts, file type, and ownership information. It is more
staticpro (&Vw32_valid_locale_ids);
staticpro (&Vw32_valid_codepages);
}
-/* end of ntproc.c */
-
-/* arch-tag: 23d3a34c-06d2-48a1-833b-ac7609aa5250
- (do not change this comment) */
+/* end of w32proc.c */