#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
#include <sys/file.h>
#ifdef USG5
#define INCLUDED_FCNTL
#include <windows.h>
#include <stdlib.h> /* for proper declaration of environ */
#include <fcntl.h>
-#include "nt.h"
+#include "w32.h"
#define _P_NOWAIT 1 /* from process.h */
#endif
#ifdef MSDOS /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
-#include "msdos.h"
#define INCLUDED_FCNTL
#include <fcntl.h>
#include <sys/stat.h>
#include "lisp.h"
#include "commands.h"
#include "buffer.h"
-#include <paths.h>
+#include "charset.h"
+#include "ccl.h"
+#include "coding.h"
+#include <epaths.h>
#include "process.h"
#include "syssignal.h"
#include "systty.h"
+#ifdef MSDOS
+#include "msdos.h"
+#endif
+
#ifdef VMS
extern noshare char **environ;
#else
#define max(a, b) ((a) > (b) ? (a) : (b))
-#ifdef DOS_NT
-/* 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 /* DOS_NT */
-
Lisp_Object Vexec_path, Vexec_directory, Vdata_directory, Vdoc_directory;
Lisp_Object Vconfigure_info_directory;
+Lisp_Object Vtemp_file_name_pattern;
Lisp_Object Vshell_file_name;
int synch_process_retcode;
extern Lisp_Object Vdoc_file_name;
+
+extern Lisp_Object Vfile_name_coding_system, Vdefault_file_name_coding_system;
\f
/* Clean up when exiting Fcall_process.
On MSDOS, delete the temporary file on any kind of termination.
call_process_cleanup (fdpid)
Lisp_Object fdpid;
{
-#ifdef MSDOS
+#if defined (MSDOS) || defined (macintosh)
/* for MSDOS fdpid is really (fd . tempfile) */
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 */
+#else /* not MSDOS and not macintosh */
register int pid = XFASTINT (Fcdr (fdpid));
-
if (call_process_exited)
{
close (XFASTINT (Fcar (fdpid)));
DEFUN ("call-process", Fcall_process, Scall_process, 1, MANY, 0,
"Call PROGRAM synchronously in separate process.\n\
+The remaining arguments are optional.\n\
The program's input comes from file INFILE (nil means `/dev/null').\n\
Insert output in BUFFER before point; t means current buffer;\n\
nil for BUFFER means discard it; 0 means discard and don't wait.\n\
char *bufptr = buf;
int bufsize = 16384;
int count = specpdl_ptr - specpdl;
+
register unsigned char **new_argv
= (unsigned char **) alloca ((max (2, nargs - 2)) * sizeof (char *));
struct buffer *old = current_buffer;
char *outf, *tempfile;
int outfilefd;
#endif
+#ifdef macintosh
+ char *tempfile;
+ int outfilefd;
+#endif
#if 0
int mask;
#endif
+ struct coding_system process_coding; /* coding-system of process output */
+ struct coding_system argument_coding; /* coding-system of arguments */
+ /* Set to the return value of Ffind_operation_coding_system. */
+ Lisp_Object coding_systems;
+
+ /* Qt denotes that Ffind_operation_coding_system is not yet called. */
+ coding_systems = Qt;
+
CHECK_STRING (args[0], 0);
error_file = Qt;
#ifndef subprocesses
/* Without asynchronous processes we cannot have BUFFER == 0. */
- if (nargs >= 3 && INTEGERP (args[2]))
+ if (nargs >= 3
+ && (INTEGERP (CONSP (args[2]) ? XCAR (args[2]) : args[2])))
error ("Operating system cannot handle asynchronous subprocesses");
#endif /* subprocesses */
+ /* Decide the coding-system for giving arguments. */
+ {
+ Lisp_Object val, *args2;
+ int i;
+
+ /* If arguments are supplied, we may have to encode them. */
+ if (nargs >= 5)
+ {
+ int must_encode = 0;
+
+ for (i = 4; i < nargs; i++)
+ CHECK_STRING (args[i], i);
+
+ for (i = 4; i < nargs; i++)
+ if (STRING_MULTIBYTE (args[i]))
+ must_encode = 1;
+
+ if (!NILP (Vcoding_system_for_write))
+ val = Vcoding_system_for_write;
+ else if (! must_encode)
+ val = Qnil;
+ else
+ {
+ args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2);
+ args2[0] = Qcall_process;
+ for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
+ coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
+ if (CONSP (coding_systems))
+ val = XCDR (coding_systems);
+ else if (CONSP (Vdefault_process_coding_system))
+ val = XCDR (Vdefault_process_coding_system);
+ else
+ val = Qnil;
+ }
+ setup_coding_system (Fcheck_coding_system (val), &argument_coding);
+ }
+ }
+
if (nargs >= 2 && ! NILP (args[1]))
{
infile = Fexpand_file_name (args[1], current_buffer->directory);
(BUFFER-FOR-STDOUT FILE-FOR-STDERR). */
if (CONSP (buffer))
{
- if (CONSP (XCONS (buffer)->cdr))
+ if (CONSP (XCDR (buffer)))
{
Lisp_Object stderr_file;
- stderr_file = XCONS (XCONS (buffer)->cdr)->car;
+ stderr_file = XCAR (XCDR (buffer));
if (NILP (stderr_file) || EQ (Qt, stderr_file))
error_file = stderr_file;
error_file = Fexpand_file_name (stderr_file, Qnil);
}
- buffer = XCONS (buffer)->car;
+ buffer = XCAR (buffer);
}
if (!(EQ (buffer, Qnil)
|| EQ (buffer, Qt)
- || XFASTINT (buffer) == 0))
+ || INTEGERP (buffer)))
{
Lisp_Object spec_buffer;
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, 2);
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;
- }
+ if (nargs > 4)
+ {
+ register int i;
+
+ if (! CODING_REQUIRE_ENCODING (&argument_coding))
+ {
+ for (i = 4; i < nargs; i++)
+ new_argv[i - 3] = XSTRING (args[i])->data;
+ }
+ else
+ {
+ /* We must encode the arguments. */
+ struct gcpro gcpro1, gcpro2, gcpro3;
+
+ GCPRO3 (infile, buffer, current_dir);
+ for (i = 4; i < nargs; i++)
+ {
+ int size = encoding_buffer_size (&argument_coding,
+ STRING_BYTES (XSTRING (args[i])));
+ unsigned char *dummy1 = (unsigned char *) alloca (size);
+
+ /* The Irix 4.0 compiler barfs if we eliminate dummy. */
+ new_argv[i - 3] = dummy1;
+ argument_coding.mode |= CODING_MODE_LAST_BLOCK;
+ encode_coding (&argument_coding,
+ XSTRING (args[i])->data,
+ new_argv[i - 3],
+ STRING_BYTES (XSTRING (args[i])),
+ size);
+ new_argv[i - 3][argument_coding.produced] = 0;
+ /* We have to initialize CCL program status again. */
+ if (argument_coding.type == coding_type_ccl)
+ setup_ccl_program (&(argument_coding.spec.ccl.encoder), Qnil);
+ }
+ UNGCPRO;
+ }
+ new_argv[nargs - 3] = 0;
+ }
+ else
+ new_argv[1] = 0;
#ifdef MSDOS /* MW, July 1993 */
- if ((outf = egetenv ("TMP")) || (outf = egetenv ("TEMP")))
+ if ((outf = egetenv ("TMPDIR")))
strcpy (tempfile = alloca (strlen (outf) + 20), outf);
else
{
fd[1] = outfilefd;
#endif /* MSDOS */
+#ifdef macintosh
+ /* Since we don't have pipes on the Mac, create a temporary file to
+ hold the output of the subprocess. */
+ tempfile = (char *) alloca (STRING_BYTES (XSTRING (Vtemp_file_name_pattern)) + 1);
+ bcopy (XSTRING (Vtemp_file_name_pattern)->data, tempfile,
+ STRING_BYTES (XSTRING (Vtemp_file_name_pattern)) + 1);
+
+ mktemp (tempfile);
+
+ outfilefd = creat (tempfile, S_IREAD | S_IWRITE);
+ if (outfilefd < 0)
+ {
+ close (filefd);
+ report_file_error ("Opening process output file",
+ Fcons (build_string (tempfile), Qnil));
+ }
+ fd[0] = filefd;
+ fd[1] = outfilefd;
+#endif /* macintosh */
+
if (INTEGERP (buffer))
fd[1] = open (NULL_DEVICE, O_WRONLY), fd[0] = -1;
else
{
#ifndef MSDOS
+#ifndef macintosh
pipe (fd);
#endif
+#endif
#if 0
/* Replaced by close_process_descs */
set_exclusive_use (fd[0]);
? build_string (NULL_DEVICE) : error_file),
Qnil));
}
-#ifdef MSDOS /* MW, July 1993 */
- /* ??? Someone who knows MSDOG needs to check whether this properly
- closes all descriptors that it opens.
- Note that run_msdos_command() actually returns the child process
+ current_dir = ENCODE_FILE (current_dir);
+
+#ifdef macintosh
+ {
+ /* Call run_mac_command in sysdep.c here directly instead of doing
+ a child_setup as for MSDOS and other platforms. Note that this
+ code does not handle passing the environment to the synchronous
+ Mac subprocess. */
+ char *infn, *outfn, *errfn, *currdn;
+
+ /* close these files so subprocess can write to them */
+ close (outfilefd);
+ if (fd_error != outfilefd)
+ close (fd_error);
+ fd1 = -1; /* No harm in closing that one! */
+
+ infn = XSTRING (infile)->data;
+ outfn = tempfile;
+ if (NILP (error_file))
+ errfn = NULL_DEVICE;
+ else if (EQ (Qt, error_file))
+ errfn = outfn;
+ else
+ errfn = XSTRING (error_file)->data;
+ currdn = XSTRING (current_dir)->data;
+ pid = run_mac_command (new_argv, currdn, infn, outfn, errfn);
+
+ /* Record that the synchronous process exited and note its
+ termination status. */
+ synch_process_alive = 0;
+ synch_process_retcode = pid;
+ if (synch_process_retcode < 0) /* means it couldn't be exec'ed */
+ synch_process_death = strerror (errno);
+
+ /* Since CRLF is converted to LF within `decode_coding', we can
+ always open a file with binary mode. */
+ fd[0] = open (tempfile, O_BINARY);
+ if (fd[0] < 0)
+ {
+ unlink (tempfile);
+ close (filefd);
+ report_file_error ("Cannot re-open temporary file", Qnil);
+ }
+ }
+#else /* not macintosh */
+#ifdef MSDOS /* MW, July 1993 */
+ /* Note that on MSDOS `child_setup' actually returns the child process
exit status, not its PID, so we assign it to `synch_process_retcode'
below. */
- pid = run_msdos_command (new_argv, current_dir,
- filefd, outfilefd, fd_error);
+ pid = child_setup (filefd, outfilefd, fd_error, (char **) new_argv,
+ 0, current_dir);
/* Record that the synchronous process exited and note its
termination status. */
synch_process_alive = 0;
synch_process_retcode = pid;
if (synch_process_retcode < 0) /* means it couldn't be exec'ed */
- synch_process_death = strerror(errno);
+ synch_process_death = strerror (errno);
close (outfilefd);
if (fd_error != outfilefd)
close (fd_error);
fd1 = -1; /* No harm in closing that one! */
- fd[0] = open (tempfile, NILP (Vbinary_process_output) ? O_TEXT : O_BINARY);
+ /* Since CRLF is converted to LF within `decode_coding', we can
+ always open a file with binary mode. */
+ fd[0] = open (tempfile, O_BINARY);
if (fd[0] < 0)
{
unlink (tempfile);
}
#else /* not MSDOS */
#ifdef WINDOWSNT
- pid = child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir);
+ pid = child_setup (filefd, fd1, fd_error, (char **) new_argv,
+ 0, current_dir);
#else /* not WINDOWSNT */
pid = vfork ();
{
if (fd[0] >= 0)
close (fd[0]);
-#if defined(USG) && !defined(BSD_PGRPS)
+#ifdef HAVE_SETSID
+ setsid ();
+#endif
+#if defined (USG) && !defined (BSD_PGRPS)
setpgrp ();
#else
setpgrp (pid, pid);
#endif /* USG */
- child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir);
+ child_setup (filefd, fd1, fd_error, (char **) new_argv,
+ 0, current_dir);
}
#endif /* not WINDOWSNT */
if (fd_error >= 0)
close (fd_error);
#endif /* not MSDOS */
+#endif /* not macintosh */
environ = save_environ;
/* Enable sending signal if user quits below. */
call_process_exited = 0;
-#ifdef MSDOS
+#if defined(MSDOS) || defined(macintosh)
/* MSDOS needs different cleanup information. */
record_unwind_protect (call_process_cleanup,
Fcons (make_number (fd[0]), build_string (tempfile)));
#else
record_unwind_protect (call_process_cleanup,
Fcons (make_number (fd[0]), make_number (pid)));
-#endif /* not MSDOS */
+#endif /* not MSDOS and not macintosh */
if (BUFFERP (buffer))
Fset_buffer (buffer);
+ if (NILP (buffer))
+ {
+ /* If BUFFER is nil, we must read process output once and then
+ discard it, so setup coding system but with nil. */
+ setup_coding_system (Qnil, &process_coding);
+ }
+ else
+ {
+ Lisp_Object val, *args2;
+
+ val = Qnil;
+ if (!NILP (Vcoding_system_for_read))
+ val = Vcoding_system_for_read;
+ else
+ {
+ if (EQ (coding_systems, Qt))
+ {
+ int i;
+
+ args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2);
+ args2[0] = Qcall_process;
+ for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
+ coding_systems
+ = Ffind_operation_coding_system (nargs + 1, args2);
+ }
+ if (CONSP (coding_systems))
+ val = XCAR (coding_systems);
+ else if (CONSP (Vdefault_process_coding_system))
+ val = XCAR (Vdefault_process_coding_system);
+ else
+ val = Qnil;
+ }
+ setup_coding_system (Fcheck_coding_system (val), &process_coding);
+ /* In unibyte mode, character code conversion should not take
+ place but EOL conversion should. So, setup raw-text or one
+ of the subsidiary according to the information just setup. */
+ if (NILP (current_buffer->enable_multibyte_characters)
+ && !NILP (val))
+ setup_raw_text_coding_system (&process_coding);
+ }
+
immediate_quit = 1;
QUIT;
register int nread;
int first = 1;
int total_read = 0;
+ int carryover = 0;
+ int display_on_the_fly = !NILP (display) && INTERACTIVE;
+ struct coding_system saved_coding;
+
+ saved_coding = process_coding;
while (1)
{
/* Repeatedly read until we've filled as much as possible
of the buffer size we have. But don't read
less than 1024--save that for the next bufferful. */
-
- nread = 0;
+ nread = carryover;
while (nread < bufsize - 1024)
{
- int this_read
- = read (fd[0], bufptr + nread, bufsize - nread);
+ int this_read = read (fd[0], bufptr + nread, bufsize - nread);
if (this_read < 0)
goto give_up;
if (this_read == 0)
- goto give_up_1;
+ {
+ process_coding.mode |= CODING_MODE_LAST_BLOCK;
+ break;
+ }
nread += this_read;
- }
+ total_read += this_read;
- give_up_1:
+ if (display_on_the_fly)
+ break;
+ }
/* Now NREAD is the total amount of data in the buffer. */
- if (nread == 0)
- break;
-
immediate_quit = 0;
- total_read += nread;
if (!NILP (buffer))
- insert (bufptr, nread);
+ {
+ if (process_coding.type == coding_type_no_conversion)
+ insert (bufptr, nread);
+ else
+ { /* We have to decode the input. */
+ int size = decoding_buffer_size (&process_coding, nread);
+ char *decoding_buf = (char *) xmalloc (size);
+
+ decode_coding (&process_coding, bufptr, decoding_buf,
+ nread, size);
+ if (display_on_the_fly
+ && saved_coding.type == coding_type_undecided
+ && process_coding.type != coding_type_undecided)
+ {
+ /* We have detected some coding system. But,
+ there's a possibility that the detection was
+ done by insufficient data. So, we give up
+ displaying on the fly. */
+ xfree (decoding_buf);
+ display_on_the_fly = 0;
+ process_coding = saved_coding;
+ carryover = nread;
+ continue;
+ }
+ if (process_coding.produced > 0)
+ insert (decoding_buf, process_coding.produced);
+ xfree (decoding_buf);
+ carryover = nread - process_coding.consumed;
+ if (carryover > 0)
+ {
+ /* As CARRYOVER should not be that large, we had
+ better avoid overhead of bcopy. */
+ char *p = bufptr + process_coding.consumed;
+ char *pend = p + carryover;
+ char *dst = bufptr;
+
+ while (p < pend) *dst++ = *p++;
+ }
+ }
+ }
+ if (process_coding.mode & CODING_MODE_LAST_BLOCK)
+ {
+ if (carryover > 0)
+ insert (bufptr, carryover);
+ break;
+ }
/* Make the buffer bigger as we continue to read more data,
but not past 64k. */
QUIT;
}
give_up: ;
+
+ Vlast_coding_system_used = process_coding.symbol;
+
+ /* If the caller required, let the buffer inherit the
+ coding-system used to decode the process output. */
+ if (inherit_process_coding_system)
+ call1 (intern ("after-insert-file-set-buffer-file-coding-system"),
+ make_number (total_read));
}
/* Wait for it to terminate, unless it already has. */
DEFUN ("call-process-region", Fcall_process_region, Scall_process_region,
3, MANY, 0,
"Send text from START to END to a synchronous process running PROGRAM.\n\
+The remaining arguments are optional.\n\
Delete the text if fourth arg DELETE is non-nil.\n\
\n\
Insert output in BUFFER before point; t means current buffer;\n\
struct gcpro gcpro1;
Lisp_Object filename_string;
register Lisp_Object start, end;
-#ifdef DOS_NT
- char *tempfile;
-#else
- char tempfile[20];
-#endif
int count = specpdl_ptr - specpdl;
+ /* Qt denotes we have not yet called Ffind_operation_coding_system. */
+ Lisp_Object coding_systems;
+ Lisp_Object val, *args2;
+ int i;
#ifdef DOS_NT
+ char *tempfile;
char *outf = '\0';
- if ((outf = egetenv ("TMP")) || (outf = egetenv ("TEMP")))
+ if ((outf = egetenv ("TMPDIR"))
+ || (outf = egetenv ("TMP"))
+ || (outf = egetenv ("TEMP")))
strcpy (tempfile = alloca (strlen (outf) + 20), outf);
else
{
strcat (tempfile, "detmp.XXX");
#endif
#else /* not DOS_NT */
-
-#ifdef VMS
- strcpy (tempfile, "tmp:emacsXXXXXX.");
-#else
- strcpy (tempfile, "/tmp/emacsXXXXXX");
-#endif
+ char *tempfile = (char *) alloca (STRING_BYTES (XSTRING (Vtemp_file_name_pattern)) + 1);
+ bcopy (XSTRING (Vtemp_file_name_pattern)->data, tempfile,
+ STRING_BYTES (XSTRING (Vtemp_file_name_pattern)) + 1);
#endif /* not DOS_NT */
+ coding_systems = Qt;
+
mktemp (tempfile);
filename_string = build_string (tempfile);
GCPRO1 (filename_string);
start = args[0];
end = args[1];
-#ifdef DOS_NT
- specbind (Qbuffer_file_type, Vbinary_process_input);
- Fwrite_region (start, end, filename_string, Qnil, Qlambda, Qnil);
- unbind_to (count, Qnil);
-#else /* not DOS_NT */
- Fwrite_region (start, end, filename_string, Qnil, Qlambda, Qnil);
-#endif /* not DOS_NT */
+ /* Decide coding-system of the contents of the temporary file. */
+ if (!NILP (Vcoding_system_for_write))
+ val = Vcoding_system_for_write;
+ else if (NILP (current_buffer->enable_multibyte_characters))
+ val = Qnil;
+ else
+ {
+ args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2);
+ args2[0] = Qcall_process_region;
+ for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
+ coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
+ if (CONSP (coding_systems))
+ val = XCDR (coding_systems);
+ else if (CONSP (Vdefault_process_coding_system))
+ val = XCDR (Vdefault_process_coding_system);
+ else
+ val = Qnil;
+ }
+
+ {
+ int count1 = specpdl_ptr - specpdl;
+
+ specbind (intern ("coding-system-for-write"), val);
+ Fwrite_region (start, end, filename_string, Qnil, Qlambda, Qnil, Qnil);
+
+ unbind_to (count1, Qnil);
+ }
+
+ /* Note that Fcall_process takes care of binding
+ coding-system-for-read. */
record_unwind_protect (delete_temp_file, filename_string);
- if (!NILP (args[3]))
+ if (nargs > 3 && !NILP (args[3]))
Fdelete_region (start, end);
- args[3] = filename_string;
+ if (nargs > 3)
+ {
+ args += 2;
+ nargs -= 2;
+ }
+ else
+ {
+ args[0] = args[2];
+ nargs = 2;
+ }
+ args[1] = filename_string;
- RETURN_UNGCPRO (unbind_to (count, Fcall_process (nargs - 2, args + 2)));
+ RETURN_UNGCPRO (unbind_to (count, Fcall_process (nargs, args)));
}
\f
#ifndef VMS /* VMS version is in vmsproc.c. */
+static int relocate_fd ();
+
/* This is the last thing run in a newly forked inferior
either synchronous or asynchronous.
Copy descriptors IN, OUT and ERR as descriptors 0, 1 and 2.
Therefore, the superior process must save and restore the value
of environ around the vfork and the call to this function.
- ENV is the environment for the subprocess.
-
SET_PGRP is nonzero if we should put the subprocess into a separate
process group.
a decent error from within the child, this should be verified as an
executable directory by the parent. */
+int
child_setup (in, out, err, new_argv, set_pgrp, current_dir)
int in, out, err;
register char **new_argv;
int set_pgrp;
Lisp_Object current_dir;
{
-#ifdef MSDOS
- /* The MSDOS port of gcc cannot fork, vfork, ... so we must call system
- instead. */
-#else /* not MSDOS */
char **env;
char *pwd_var;
#ifdef WINDOWSNT
/* Close Emacs's descriptors that this process should not have. */
close_process_descs ();
#endif
+ /* DOS_NT isn't in a vfork, so if we are in the middle of load-file,
+ we will lose if we call close_load_descs here. */
+#ifndef DOS_NT
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.
register char *temp;
register int i;
- i = XSTRING (current_dir)->size;
+ i = STRING_BYTES (XSTRING (current_dir));
pwd_var = (char *) alloca (i + 6);
temp = pwd_var + 4;
bcopy ("PWD=", pwd_var, 4);
if (!IS_DIRECTORY_SEP (temp[i - 1])) temp[i++] = DIRECTORY_SEP;
temp[i] = 0;
+#ifndef DOS_NT
/* We can't signal an Elisp error here; we're in a vfork. Since
the callers check the current directory before forking, this
should only return an error if the directory's permissions
at least check. */
if (chdir (temp) < 0)
_exit (errno);
+#endif
+
+#ifdef DOS_NT
+ /* Get past the drive letter, so that d:/ is left alone. */
+ if (i > 2 && IS_DEVICE_SEP (temp[1]) && IS_DIRECTORY_SEP (temp[2]))
+ {
+ temp += 2;
+ i -= 2;
+ }
+#endif
/* Strip trailing slashes for PWD, but leave "/" and "//" alone. */
while (i > 2 && IS_DIRECTORY_SEP (temp[i - 1]))
new_length = 0;
for (tem = Vprocess_environment;
- CONSP (tem) && STRINGP (XCONS (tem)->car);
- tem = XCONS (tem)->cdr)
+ CONSP (tem) && STRINGP (XCAR (tem));
+ tem = XCDR (tem))
new_length++;
/* new_length + 2 to include PWD and terminating 0. */
/* Copy the Vprocess_environment strings into new_env. */
for (tem = Vprocess_environment;
- CONSP (tem) && STRINGP (XCONS (tem)->car);
- tem = XCONS (tem)->cdr)
+ CONSP (tem) && STRINGP (XCAR (tem));
+ tem = XCDR (tem))
{
char **ep = env;
- char *string = (char *) XSTRING (XCONS (tem)->car)->data;
+ char *string = (char *) XSTRING (XCAR (tem))->data;
/* See if this string duplicates any string already in the env.
If so, don't put it in.
When an env var has multiple definitions,
}
#ifdef WINDOWSNT
prepare_standard_handles (in, out, err, handles);
+ set_process_dir (XSTRING (current_dir)->data);
#else /* not WINDOWSNT */
/* Make sure that in, out, and err are not actually already in
descriptors zero, one, or two; this could happen if Emacs is
err = relocate_fd (err, 3);
}
+#ifndef MSDOS
close (0);
close (1);
close (2);
close (in);
close (out);
close (err);
+#endif /* not MSDOS */
#endif /* not WINDOWSNT */
#if defined(USG) && !defined(BSD_PGRPS)
something missing here;
#endif /* vipc */
+#ifdef MSDOS
+ pid = run_msdos_command (new_argv, pwd_var + 4, in, out, err, env);
+ if (pid == -1)
+ /* An error occurred while trying to run the subprocess. */
+ report_file_error ("Spawning child process", Qnil);
+ return pid;
+#else /* not MSDOS */
#ifdef WINDOWSNT
/* Spawn the child. (See ntproc.c:Spawnve). */
cpid = spawnve (_P_NOWAIT, new_argv[0], new_argv, env);
+ reset_standard_handles (in, out, err, handles);
if (cpid == -1)
/* An error occurred while trying to spawn the process. */
report_file_error ("Spawning child process", Qnil);
- reset_standard_handles (in, out, err, handles);
return cpid;
#else /* not WINDOWSNT */
/* execvp does not accept an environment arg so the only way
#endif /* not MSDOS */
}
-/* Move the file descriptor FD so that its number is not less than MIN.
+/* Move the file descriptor FD so that its number is not less than MINFD.
If the file descriptor is moved at all, the original is freed. */
-int
-relocate_fd (fd, min)
- int fd, min;
+static int
+relocate_fd (fd, minfd)
+ int fd, minfd;
{
- if (fd >= min)
+ if (fd >= minfd)
return fd;
else
{
}
/* Note that we hold the original FD open while we recurse,
to guarantee we'll get a new FD if we need it. */
- new = relocate_fd (new, min);
+ new = relocate_fd (new, minfd);
close (fd);
return new;
}
{
Lisp_Object scan;
- for (scan = Vprocess_environment; CONSP (scan); scan = XCONS (scan)->cdr)
+ for (scan = Vprocess_environment; CONSP (scan); scan = XCDR (scan))
{
Lisp_Object entry;
- entry = XCONS (scan)->car;
+ entry = XCAR (scan);
if (STRINGP (entry)
- && XSTRING (entry)->size > varlen
+ && STRING_BYTES (XSTRING (entry)) > varlen
&& XSTRING (entry)->data[varlen] == '='
#ifdef WINDOWSNT
/* NT environment variables are case insensitive. */
)
{
*value = (char *) XSTRING (entry)->data + (varlen + 1);
- *valuelen = XSTRING (entry)->size - (varlen + 1);
+ *valuelen = STRING_BYTES (XSTRING (entry)) - (varlen + 1);
return 1;
}
}
int valuelen;
CHECK_STRING (var, 0);
- if (getenv_internal (XSTRING (var)->data, XSTRING (var)->size,
+ if (getenv_internal (XSTRING (var)->data, STRING_BYTES (XSTRING (var)),
&value, &valuelen))
return make_string (value, valuelen);
else
\f
/* This is run before init_cmdargs. */
+void
init_callproc_1 ()
{
char *data_dir = egetenv ("EMACSDATA");
: PATH_DOC));
/* Check the EMACSPATH environment variable, defaulting to the
- PATH_EXEC path from paths.h. */
+ PATH_EXEC path from epaths.h. */
Vexec_path = decode_env_path ("EMACSPATH", PATH_EXEC);
Vexec_directory = Ffile_name_as_directory (Fcar (Vexec_path));
Vexec_path = nconc2 (decode_env_path ("PATH", ""), Vexec_path);
/* This is run after init_cmdargs, when Vinstallation_directory is valid. */
+void
init_callproc ()
{
char *data_dir = egetenv ("EMACSDATA");
register char * sh;
Lisp_Object tempdir;
- if (initialized && !NILP (Vinstallation_directory))
+ if (!NILP (Vinstallation_directory))
{
/* 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)))
- {
#ifndef DOS_NT
/* MSDOS uses wrapped binaries, so don't do this. */
- Vexec_path = nconc2 (Vexec_path, Fcons (tem, Qnil));
- Vexec_directory = Ffile_name_as_directory (tem);
+ if (NILP (Fmember (tem, Vexec_path)))
+ Vexec_path = nconc2 (Vexec_path, Fcons (tem, Qnil));
+
+ Vexec_directory = Ffile_name_as_directory (tem);
#endif /* not DOS_NT */
- }
/* Maybe use ../etc as well as ../lib-src. */
if (data_dir == 0)
}
}
- tempdir = Fdirectory_file_name (Vexec_directory);
- if (access (XSTRING (tempdir)->data, 0) < 0)
- dir_warning ("Warning: arch-dependent data dir (%s) does not exist.\n",
- Vexec_directory);
+#ifndef CANNOT_DUMP
+ if (initialized)
+#endif
+ {
+ tempdir = Fdirectory_file_name (Vexec_directory);
+ if (access (XSTRING (tempdir)->data, 0) < 0)
+ dir_warning ("Warning: arch-dependent data dir (%s) does not exist.\n",
+ Vexec_directory);
+ }
tempdir = Fdirectory_file_name (Vdata_directory);
if (access (XSTRING (tempdir)->data, 0) < 0)
sh = (char *) getenv ("SHELL");
Vshell_file_name = build_string (sh ? sh : "/bin/sh");
#endif
+
+#ifdef VMS
+ Vtemp_file_name_pattern = build_string ("tmp:emacsXXXXXX.");
+#else
+ if (getenv ("TMPDIR"))
+ {
+ char *dir = getenv ("TMPDIR");
+ Vtemp_file_name_pattern
+ = Fexpand_file_name (build_string ("emacsXXXXXX"),
+ build_string (dir));
+ }
+ else
+ Vtemp_file_name_pattern = build_string ("/tmp/emacsXXXXXX");
+#endif
}
+void
set_process_environment ()
{
register char **envp;
Vprocess_environment);
}
+void
syms_of_callproc ()
{
#ifdef DOS_NT
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_output = Qnil;
#endif /* DOS_NT */
DEFVAR_LISP ("shell-file-name", &Vshell_file_name,
Each element is a string (directory name) or nil (try default directory).");
DEFVAR_LISP ("exec-directory", &Vexec_directory,
- "Directory of architecture-dependent files that come with GNU Emacs,\n\
-especially executable programs intended for Emacs to invoke.");
+ "Directory for executables for Emacs to invoke.\n\
+More generally, this includes any architecture-dependent files\n\
+that are built and installed from the Emacs distribution.");
DEFVAR_LISP ("data-directory", &Vdata_directory,
- "Directory of architecture-independent files that come with GNU Emacs,\n\
-intended for Emacs to use.");
+ "Directory of machine-independent files that come with GNU Emacs.\n\
+These are files intended for Emacs to use while it runs.");
DEFVAR_LISP ("doc-directory", &Vdoc_directory,
"Directory containing the DOC file that comes with GNU Emacs.\n\
includes this.");
Vconfigure_info_directory = build_string (PATH_INFO);
+ DEFVAR_LISP ("temp-file-name-pattern", &Vtemp_file_name_pattern,
+ "Pattern for making names for temporary files.\n\
+This is used by `call-process-region'.");
+ /* This variable is initialized in init_callproc. */
+
DEFVAR_LISP ("process-environment", &Vprocess_environment,
"List of environment variables for subprocesses to inherit.\n\
Each element should be a string of the form ENVVARNAME=VALUE.\n\