#include <signal.h>
#include <errno.h>
+#include <stdio.h>
#include <config.h>
#include <sys/file.h>
#ifdef USG5
+#define INCLUDED_FCNTL
#include <fcntl.h>
#endif
#ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
+#define INCLUDED_FCNTL
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/param.h>
#define max(a, b) ((a) > (b) ? (a) : (b))
#ifdef MSDOS
-Lisp_Object Vbinary_process;
+/* 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). Similar 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
-Lisp_Object Vexec_path, Vexec_directory, Vdata_directory;
+Lisp_Object Vexec_path, Vexec_directory, Vdata_directory, Vdoc_directory;
Lisp_Object Vconfigure_info_directory;
Lisp_Object Vshell_file_name;
Lisp_Object Vprocess_environment;
+#ifdef MSDOS
+Lisp_Object Qbuffer_file_type;
+#endif
+
/* True iff we are about to fork off a synchronous process or if we
are waiting for it. */
int synch_process_alive;
extern Lisp_Object Vdoc_file_name;
\f
+/* Clean up when exiting Fcall_process.
+ On MSDOS, 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. */
+static int call_process_exited;
+
#ifndef VMS /* VMS version is in vmsproc.c. */
static Lisp_Object
{
#ifdef MSDOS
/* for MSDOS fdpid is really (fd . tempfile) */
- register Lisp_Object file = Fcdr (fdpid);
+ register Lisp_Object file;
+ file = Fcdr (fdpid);
close (XFASTINT (Fcar (fdpid)));
if (strcmp (XSTRING (file)-> data, NULL_DEVICE) != 0)
unlink (XSTRING (file)->data);
#else /* not MSDOS */
register int pid = XFASTINT (Fcdr (fdpid));
+
+ if (call_process_exited)
+ {
+ close (XFASTINT (Fcar (fdpid)));
+ return Qnil;
+ }
+
if (EMACS_KILLPG (pid, SIGINT) == 0)
{
int count = specpdl_ptr - specpdl;
GCPRO3 (infile, buffer, current_dir);
- current_dir =
- expand_and_dir_to_file
- (Funhandled_file_name_directory (current_dir), Qnil);
+ current_dir
+ = expand_and_dir_to_file (Funhandled_file_name_directory (current_dir),
+ Qnil);
if (NILP (Ffile_accessible_directory_p (current_dir)))
report_file_error ("Setting current directory",
Fcons (current_buffer->directory, Qnil));
display = nargs >= 4 ? args[3] : Qnil;
- {
- register int i;
- for (i = 4; i < nargs; i++)
- {
- CHECK_STRING (args[i], i);
- new_argv[i - 3] = XSTRING (args[i])->data;
- }
- /* Program name is first command arg */
- new_argv[0] = XSTRING (args[0])->data;
- new_argv[i - 3] = 0;
- }
-
filefd = open (XSTRING (infile)->data, O_RDONLY, 0);
if (filefd < 0)
{
report_file_error ("Opening process input file", Fcons (infile, Qnil));
}
/* Search for program; barf if not found. */
- openp (Vexec_path, args[0], EXEC_SUFFIXES, &path, 1);
+ {
+ struct gcpro gcpro1;
+
+ GCPRO1 (current_dir);
+ openp (Vexec_path, args[0], EXEC_SUFFIXES, &path, 1);
+ UNGCPRO;
+ }
if (NILP (path))
{
close (filefd);
report_file_error ("Searching for program", Fcons (args[0], Qnil));
}
new_argv[0] = XSTRING (path)->data;
+ {
+ register int i;
+ for (i = 4; i < nargs; i++)
+ {
+ CHECK_STRING (args[i], i);
+ new_argv[i - 3] = XSTRING (args[i])->data;
+ }
+ new_argv[i - 3] = 0;
+ }
#ifdef MSDOS /* MW, July 1993 */
/* These vars record information from process termination.
synch_process_retcode = 0;
#ifdef MSDOS /* MW, July 1993 */
+ /* ??? Someone who knows MSDOG needs to check whether this properly
+ closes all descriptors that it opens. */
pid = run_msdos_command (new_argv, current_dir, filefd, outfilefd);
close (outfilefd);
fd1 = -1; /* No harm in closing that one! */
- fd[0] = open (tempfile, NILP (Vbinary_process) ? O_TEXT : O_BINARY);
+ fd[0] = open (tempfile, NILP (Vbinary_process_output) ? O_TEXT : O_BINARY);
if (fd[0] < 0)
{
unlink (tempfile);
+ close (filefd);
report_file_error ("Cannot re-open temporary file", Qnil);
}
#else /* not MSDOS */
}
#endif /* not MSDOS */
-#if 0
- /* Tell SIGCHLD handler to look for this pid. */
- synch_process_pid = pid;
- /* Now let SIGCHLD come through. */
- sigsetmask (mask);
-#endif
-
environ = save_environ;
+ /* Close most of our fd's, but not fd[0]
+ since we will use that to read input from. */
close (filefd);
if (fd1 >= 0)
close (fd1);
if (pid < 0)
{
- close (fd[0]);
+ if (fd[0] >= 0)
+ close (fd[0]);
report_file_error ("Doing vfork", Qnil);
}
if (XTYPE (buffer) == Lisp_Int)
{
+ if (fd[0] >= 0)
+ close (fd[0]);
#ifndef subprocesses
/* If Emacs has been built with asynchronous subprocess support,
we don't need to do this, I think because it will then have
return Qnil;
}
+ /* Enable sending signal if user quits below. */
+ call_process_exited = 0;
+
#ifdef MSDOS
/* MSDOS needs different cleanup information. */
record_unwind_protect (call_process_cleanup,
set_buffer_internal (old);
+ /* Don't kill any children that the subprocess may have left behind
+ when exiting. */
+ call_process_exited = 1;
+
unbind_to (count, Qnil);
if (synch_process_death)
filename_string = build_string (tempfile);
start = args[0];
end = args[1];
+#ifdef MSDOS
+ specbind (Qbuffer_file_type, Vbinary_process_input);
+ Fwrite_region (start, end, filename_string, Qnil, Qlambda);
+ unbind_to (count, Qnil);
+#else
Fwrite_region (start, end, filename_string, Qnil, Qlambda);
+#endif
+
record_unwind_protect (delete_temp_file, filename_string);
if (!NILP (args[3]))
int pid = getpid ();
+#ifdef SET_EMACS_PRIORITY
{
extern int emacs_priority;
- nice (- emacs_priority);
+ if (emacs_priority < 0)
+ nice (- emacs_priority);
}
+#endif
#ifdef subprocesses
/* Close Emacs's descriptors that this process should not have. */
started with its standard in, out, or error closed, as might
happen under X. */
in = relocate_fd (in, 3);
- out = relocate_fd (out, 3);
- err = relocate_fd (err, 3);
+ if (out == err)
+ err = out = relocate_fd (out, 3);
+ else
+ {
+ out = relocate_fd (out, 3);
+ err = relocate_fd (err, 3);
+ }
close (0);
close (1);
for (scan = Vprocess_environment; CONSP (scan); scan = XCONS (scan)->cdr)
{
- Lisp_Object entry = XCONS (scan)->car;
-
+ Lisp_Object entry;
+
+ entry = XCONS (scan)->car;
if (XTYPE (entry) == Lisp_String
&& XSTRING (entry)->size > varlen
&& XSTRING (entry)->data[varlen] == '='
init_callproc_1 ()
{
char *data_dir = egetenv ("EMACSDATA");
-
+ char *doc_dir = egetenv ("EMACSDOC");
+
Vdata_directory
= Ffile_name_as_directory (build_string (data_dir ? data_dir
: PATH_DATA));
+ Vdoc_directory
+ = Ffile_name_as_directory (build_string (doc_dir ? doc_dir
+ : PATH_DOC));
/* Check the EMACSPATH environment variable, defaulting to the
PATH_EXEC path from paths.h. */
register char * sh;
Lisp_Object tempdir;
- if (initialized && !NILP (Vinvocation_directory))
+#ifndef MSDOS
+ if (initialized && !NILP (Vinstallation_directory))
{
- /* Add to the path the ../lib-src dir of the Emacs executable,
- if that dir exists. */
- Lisp_Object tem, tem1;
- tem = Fexpand_file_name (build_string ("../lib-src"),
- Vinvocation_directory);
- tem1 = Ffile_exists_p (tem);
- if (!NILP (tem1) && NILP (Fmember (tem, Vexec_path)))
+ /* Add to the path the lib-src subdir of the installation dir. */
+ Lisp_Object tem;
+ tem = Fexpand_file_name (build_string ("lib-src"),
+ Vinstallation_directory);
+ if (NILP (Fmember (tem, Vexec_path)))
{
Vexec_path = nconc2 (Vexec_path, Fcons (tem, Qnil));
Vexec_directory = Ffile_name_as_directory (tem);
Do so if ../etc exists and has our DOC-... file in it. */
if (data_dir == 0)
{
- Lisp_Object tem, tem2, tem3;
- tem = Fexpand_file_name (build_string ("../etc"),
- Vinvocation_directory);
- tem2 = Fexpand_file_name (Vdoc_file_name, tem);
- tem3 = Ffile_exists_p (tem2);
- if (!NILP (tem3))
- Vdata_directory = Ffile_name_as_directory (tem);
+ tem = Fexpand_file_name (build_string ("etc"),
+ Vinstallation_directory);
+ Vdoc_directory = Ffile_name_as_directory (tem);
}
}
}
+ /* Look for the files that should be in etc. We don't use
+ Vinstallation_directory, because these files are never installed
+ in /bin near the executable, and they are never in the build
+ directory when that's different from the source directory.
+
+ Instead, if these files are not in the nominal place, we try the
+ source directory. */
+ if (data_dir == 0)
+ {
+ Lisp_Object tem, tem1, newdir;
+
+ tem = Fexpand_file_name (build_string ("GNU"), Vdata_directory);
+ tem1 = Ffile_exists_p (tem);
+ if (NILP (tem1))
+ {
+ newdir = Fexpand_file_name (build_string ("../etc/"),
+ build_string (PATH_DUMPLOADSEARCH));
+ tem = Fexpand_file_name (build_string ("GNU"), newdir);
+ tem1 = Ffile_exists_p (tem);
+ if (!NILP (tem1))
+ Vdata_directory = newdir;
+ }
+ }
+#endif
+
tempdir = Fdirectory_file_name (Vexec_directory);
if (access (XSTRING (tempdir)->data, 0) < 0)
{
- printf ("Warning: arch-dependent data dir (%s) does not exist.\n",
- XSTRING (Vexec_directory)->data);
+ fprintf (stderr,
+ "Warning: arch-dependent data dir (%s) does not exist.\n",
+ XSTRING (Vexec_directory)->data);
sleep (2);
}
tempdir = Fdirectory_file_name (Vdata_directory);
if (access (XSTRING (tempdir)->data, 0) < 0)
{
- printf ("Warning: arch-independent data dir (%s) does not exist.\n",
- XSTRING (Vdata_directory)->data);
+ fprintf (stderr,
+ "Warning: arch-independent data dir (%s) does not exist.\n",
+ XSTRING (Vdata_directory)->data);
sleep (2);
}
syms_of_callproc ()
{
#ifdef MSDOS
- DEFVAR_LISP ("binary-process", &Vbinary_process,
+ Qbuffer_file_type = intern ("buffer-file-type");
+ staticpro (&Qbuffer_file_type);
+
+ DEFVAR_LISP ("binary-process-input", &Vbinary_process_input,
+ "*If non-nil then new subprocesses are assumed to take binary input.");
+ Vbinary_process_input = Qnil;
+
+ DEFVAR_LISP ("binary-process-output", &Vbinary_process_output,
"*If non-nil then new subprocesses are assumed to produce binary output.");
- Vbinary_process = Qnil;
+ Vbinary_process_output = Qnil;
#endif
DEFVAR_LISP ("shell-file-name", &Vshell_file_name,
"Directory of architecture-independent files that come with GNU Emacs,\n\
intended for Emacs to use.");
+ DEFVAR_LISP ("doc-directory", &Vdoc_directory,
+ "Directory containing the DOC file that comes with GNU Emacs.\n\
+This is usually the same as data-directory.");
+
DEFVAR_LISP ("configure-info-directory", &Vconfigure_info_directory,
"For internal use by the build procedure only.\n\
This is the name of the directory in which the build procedure installed\n\