-/* Synchronous subprocess invocation for XEmacs.
+/* Old synchronous subprocess invocation for XEmacs.
Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
This file is part of XEmacs.
/* Synched up with: Mule 2.0, FSF 19.30. */
/* Partly sync'ed with 19.36.4 */
+
+/* #### This ENTIRE file is only used in batch mode.
+
+ We only need two things to get rid of both this and ntproc.c:
+
+ -- my `stderr-proc' ws, which adds support for a separate stderr
+ in asynch. subprocesses. (it's a feature in `old-call-process-internal'.)
+ -- a noninteractive event loop that supports processes.
+*/
+
#include <config.h>
#include "lisp.h"
#include "systime.h"
#include "sysproc.h"
+#include "sysdir.h"
#include "sysfile.h" /* Always include after sysproc.h */
+#include "sysdir.h"
#include "syssignal.h" /* Always include before systty.h */
#include "systty.h"
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
#define _P_NOWAIT 1 /* from process.h */
#include "nt.h"
#endif
-#ifdef DOS_NT
+#ifdef WIN32_NATIVE
/* When we are starting external processes we need to know whether they
take binary input (no conversion) or text input (\n is converted to
\r\n). Similarly for output: if newlines are written as \r\n then it's
text process output, otherwise it's binary. */
Lisp_Object Vbinary_process_input;
Lisp_Object Vbinary_process_output;
-#endif /* DOS_NT */
+#endif /* WIN32_NATIVE */
Lisp_Object Vshell_file_name;
int synch_process_retcode;
\f
/* Clean up when exiting Fcall_process_internal.
- On MSDOS, delete the temporary file on any kind of termination.
+ On Windows, delete the temporary file on any kind of termination.
On Unix, kill the process and any children on termination by signal. */
/* Nonzero if this is termination due to exit. */
/* #### "c-G" -- need non-consing Single-key-description */
message ("Waiting for process to die...(type C-g again to kill it instantly)");
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
{
HANDLE pHandle = OpenProcess (PROCESS_ALL_ACCESS, 0, pid);
if (pHandle == NULL)
The program's input comes from file INFILE (nil means `/dev/null').
Insert output in BUFFER before point; t means current buffer;
nil for BUFFER means discard it; 0 means discard and don't wait.
+If BUFFER is a string, then find or create a buffer with that name,
+then insert the output in that buffer, before point.
BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case,
REAL-BUFFER says what to do with standard output, as above,
while STDERR-FILE says what to do with standard error in the child.
Lisp_Object infile, buffer, current_dir, display, path;
int fd[2];
int filefd;
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
HANDLE pHandle;
#endif
int pid;
buffer's current directory. We can't just have the child check
for an error when it does the chdir, since it's in a vfork. */
- NGCPRO2 (current_dir, path); /* Caller gcprotects args[] */
current_dir = current_buffer->directory;
+ NGCPRO2 (current_dir, path); /* Caller gcprotects args[] */
current_dir = Funhandled_file_name_directory (current_dir);
current_dir = expand_and_dir_to_file (current_dir, Qnil);
#if 0
|| ZEROP (buffer)))
{
Lisp_Object spec_buffer = buffer;
- buffer = Fget_buffer (buffer);
+ buffer = Fget_buffer_create (buffer);
/* Mention the buffer name for a better error message. */
if (NILP (buffer))
CHECK_BUFFER (spec_buffer);
REGISTER char **save_environ = environ;
REGISTER int fd1 = fd[1];
int fd_error = fd1;
- char **env;
-
- env = environ;
/* Record that we're about to create a synchronous process. */
synch_process_alive = 1;
else if (STRINGP (error_file))
{
fd_error = open ((const char *) XSTRING_DATA (error_file),
-#ifdef DOS_NT
+#ifdef WIN32_NATIVE
O_WRONLY | O_TRUNC | O_CREAT | O_TEXT,
S_IREAD | S_IWRITE
-#else /* not DOS_NT */
+#else /* not WIN32_NATIVE */
O_WRONLY | O_TRUNC | O_CREAT | OPEN_BINARY,
CREAT_MODE
-#endif /* not DOS_NT */
+#endif /* not WIN32_NATIVE */
);
}
if (fd_error < 0)
{
+ int save_errno = errno;
close (filefd);
close (fd[0]);
if (fd1 >= 0)
close (fd1);
+ errno = save_errno;
report_file_error ("Cannot open", Fcons(error_file, Qnil));
}
fork_error = Qnil;
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
pid = child_setup (filefd, fd1, fd_error, new_argv,
(char *) XSTRING_DATA (current_dir));
if (!INTP (buffer))
}
#endif
}
- /* Close STDERR into the parent process. We no longer need it. */
- if (fd_error >= 0)
- close (fd_error);
-#else /* not WINDOWSNT */
+#else /* not WIN32_NATIVE */
pid = fork ();
if (pid == 0)
child_setup (filefd, fd1, fd_error, new_argv,
(char *) XSTRING_DATA (current_dir));
}
- if (fd_error >= 0)
- close (fd_error);
-
-#endif /* not WINDOWSNT */
+#endif /* not WIN32_NATIVE */
environ = save_environ;
+ /* Close STDERR into the parent process. We no longer need it. */
+ if (fd_error >= 0)
+ close (fd_error);
+
/* Close most of our fd's, but not fd[0]
since we will use that to read input from. */
close (filefd);
- if (fd1 >= 0)
+ if ((fd1 >= 0) && (fd1 != fd_error))
close (fd1);
}
if (!NILP (fork_error))
signal_error (Qfile_error, fork_error);
-#ifndef WINDOWSNT
+#ifndef WIN32_NATIVE
if (pid < 0)
{
+ int save_errno = errno;
if (fd[0] >= 0)
close (fd[0]);
+ errno = save_errno;
report_file_error ("Doing fork", Qnil);
}
#endif
{
int nread;
- int first = 1;
int total_read = 0;
Lisp_Object instream;
struct gcpro ngcpro1;
nread = 0;
while (nread < bufsize - 1024)
{
- ssize_t this_read
+ Lstream_data_count this_read
= Lstream_read (XLSTREAM (instream), bufptr + nread,
bufsize - nread);
break;
#if 0
-#ifdef DOS_NT
+#ifdef WIN32_NATIVE
/* Until we pull out of MULE things like
make_decoding_input_stream(), we do the following which is
less elegant. --marcpa */
if (!NILP (display) && INTERACTIVE)
{
- first = 0;
redisplay ();
}
}
QUIT;
/* Wait for it to terminate, unless it already has. */
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
wait_for_termination (pHandle);
#else
wait_for_termination (pid);
a decent error from within the child, this should be verified as an
executable directory by the parent. */
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
int
#else
void
{
char **env;
char *pwd;
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
int cpid;
HANDLE handles[4];
-#endif /* WINDOWSNT */
+#endif /* WIN32_NATIVE */
#ifdef SET_EMACS_PRIORITY
if (emacs_priority != 0)
nice (- emacs_priority);
#endif
-#if !defined (NO_SUBPROCESSES) && !defined (WINDOWSNT)
+ /* Under Windows, we are not in a child process at all, so we should
+ not close handles inherited from the parent -- we are the parent
+ and doing so will screw up all manner of things! Similarly, most
+ of the rest of the cleanup done in this function is not done
+ under Windows.
+
+ #### This entire child_setup() function is an utter and complete
+ piece of shit. I would rewrite it, at the very least splitting
+ out the Windows and non-Windows stuff into two completely
+ different functions; but instead I'm trying to make it go away
+ entirely, using the Lisp definition in process.el. What's left
+ is to fix up the routines in event-msw.c (and in event-Xt.c and
+ event-tty.c) to allow for stream devices to be handled correctly.
+ There isn't much to do, in fact, and I'll fix it shortly. That
+ way, the Lisp definition can be used non-interactively too. */
+#if !defined (NO_SUBPROCESSES) && !defined (WIN32_NATIVE)
/* Close Emacs's descriptors that this process should not have. */
close_process_descs ();
#endif /* not NO_SUBPROCESSES */
+#ifndef WIN32_NATIVE
close_load_descs ();
+#endif
/* Note that use of alloca is always safe here. It's obvious for systems
that do not have true vfork or that have true (stack) alloca.
*new_env = 0;
}
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
prepare_standard_handles (in, out, err, handles);
set_process_dir (current_dir);
-#else /* not WINDOWSNT */
+#else /* not WIN32_NATIVE */
/* Make sure that in, out, and err are not actually already in
descriptors zero, one, or two; this could happen if Emacs is
started with its standard in, out, or error closed, as might
close (out);
close (err);
- /* I can't think of any reason why child processes need any more
- than the standard 3 file descriptors. It would be cleaner to
+ /* Close non-process-related file descriptors. It would be cleaner to
close just the ones that need to be, but the following brute
force approach is certainly effective, and not too slow. */
+
{
int fd;
- for (fd=3; fd<=64; fd++)
+
+ for (fd = 3; fd < MAXDESC; fd++)
close (fd);
}
-#endif /* not WINDOWSNT */
+#endif /* not WIN32_NATIVE */
#ifdef vipc
something missing here;
#endif /* vipc */
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
/* Spawn the child. (See ntproc.c:Spawnve). */
cpid = spawnve (_P_NOWAIT, new_argv[0], (const char* const*)new_argv,
(const char* const*)env);
report_file_error ("Spawning child process", Qnil);
reset_standard_handles (in, out, err, handles);
return cpid;
-#else /* not WINDOWSNT */
+#else /* not WIN32_NATIVE */
/* execvp does not accept an environment arg so the only way
to pass this environment is to set environ. Our caller
is responsible for restoring the ambient value of environ. */
stdout_out ("Can't exec program %s\n", new_argv[0]);
_exit (1);
-#endif /* not WINDOWSNT */
+#endif /* not WIN32_NATIVE */
}
static int
if (STRINGP (entry)
&& XSTRING_LENGTH (entry) > varlen
&& XSTRING_BYTE (entry, varlen) == '='
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
/* NT environment variables are case insensitive. */
&& ! memicmp (XSTRING_DATA (entry), var, varlen)
-#else /* not WINDOWSNT */
+#else /* not WIN32_NATIVE */
&& ! memcmp (XSTRING_DATA (entry), var, varlen)
-#endif /* not WINDOWSNT */
+#endif /* not WIN32_NATIVE */
)
{
*value = XSTRING_DATA (entry) + (varlen + 1);
char *
egetenv (const char *var)
{
+ /* This cannot GC -- 7-28-00 ben */
Bufbyte *value;
Bytecount valuelen;
{
/* Initialize shell-file-name from environment variables or best guess. */
-#ifdef WINDOWSNT
- const char *shell = egetenv ("COMSPEC");
- if (!shell) shell = "\\WINNT\\system32\\cmd.exe";
-#else /* not WINDOWSNT */
+#ifdef WIN32_NATIVE
+ const char *shell = egetenv ("SHELL");
+ if (!shell) shell = egetenv ("COMSPEC");
+ /* Should never happen! */
+ if (!shell) shell = (GetVersion () & 0x80000000 ? "command" : "cmd");
+#else /* not WIN32_NATIVE */
const char *shell = egetenv ("SHELL");
if (!shell) shell = "/bin/sh";
#endif
+#if 0 /* defined (WIN32_NATIVE) */
+ /* BAD BAD BAD. We do not wanting to be passing an XEmacs-created
+ SHELL var down to some inferior Cygwin process, which might get
+ screwed up.
+
+ There are a few broken apps (eterm/term.el, eterm/tshell.el,
+ os-utils/terminal.el, texinfo/tex-mode.el) where this will
+ cause problems. Those broken apps don't look at
+ shell-file-name, instead just at explicit-shell-file-name,
+ ESHELL and SHELL. They are apparently attempting to borrow
+ what `M-x shell' uses, but that latter also looks at
+ shell-file-name. What we want is for all of these apps to look
+ at shell-file-name, so that the user can change the value of
+ shell-file-name and everything will work out hunky-dorey.
+ */
+
+ if (!egetenv ("SHELL"))
+ {
+ CBufbyte *faux_var = alloca_array (CBufbyte, 7 + strlen (shell));
+ sprintf (faux_var, "SHELL=%s", shell);
+ Vprocess_environment = Fcons (build_string (faux_var),
+ Vprocess_environment);
+ }
+#endif /* 0 */
+
Vshell_file_name = build_string (shell);
}
}
vars_of_callproc (void)
{
/* This function can GC */
-#ifdef DOS_NT
+#ifdef WIN32_NATIVE
DEFVAR_LISP ("binary-process-input", &Vbinary_process_input /*
*If non-nil then new subprocesses are assumed to take binary input.
*/ );
*If non-nil then new subprocesses are assumed to produce binary output.
*/ );
Vbinary_process_output = Qnil;
-#endif /* DOS_NT */
+#endif /* WIN32_NATIVE */
DEFVAR_LISP ("shell-file-name", &Vshell_file_name /*
*File name to load inferior shells from.