#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
#include "lisp.h"
#include "commands.h"
#include "buffer.h"
+#include "charset.h"
+#include "coding.h"
#include <paths.h>
#include "process.h"
#include "syssignal.h"
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;
#if 0
int mask;
#endif
+ struct coding_system process_coding; /* coding-system of process output */
+ struct coding_system argument_coding; /* coding-system of arguments */
+
CHECK_STRING (args[0], 0);
error_file = Qt;
error ("Operating system cannot handle asynchronous subprocesses");
#endif /* subprocesses */
+ /* Decide the coding-system for giving arguments and reading process
+ output. */
+ {
+ Lisp_Object val, *args2;
+ /* Qt denotes we have not yet called Ffind_operation_coding_system. */
+ Lisp_Object coding_systems = Qt;
+ int i;
+
+ /* If arguments are supplied, we may have to encode them. */
+ if (nargs >= 5)
+ {
+ 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;
+ 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 = XCONS (coding_systems)->cdr;
+ else if (CONSP (Vdefault_process_coding_system))
+ val = XCONS (Vdefault_process_coding_system)->cdr;
+ else
+ val = Qnil;
+ }
+ setup_coding_system (Fcheck_coding_system (val), &argument_coding);
+ }
+
+ /* If BUFFER is nil, we must read process output once and then
+ discard it, so setup coding system but with nil. If BUFFER is
+ an integer, we can discard it without reading. */
+ if (nargs < 3 || NILP (args[2]))
+ setup_coding_system (Qnil, &process_coding);
+ else if (!INTEGERP (args[2]))
+ {
+ val = Qnil;
+ if (!NILP (Vcoding_system_for_read))
+ val = Vcoding_system_for_read;
+ else if (NILP (current_buffer->enable_multibyte_characters))
+ val = Qemacs_mule;
+ else
+ {
+ if (!EQ (coding_systems, Qt))
+ {
+ 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 = XCONS (coding_systems)->car;
+ else if (CONSP (Vdefault_process_coding_system))
+ val = XCONS (Vdefault_process_coding_system)->car;
+ else
+ val = Qnil;
+ }
+ setup_coding_system (Fcheck_coding_system (val), &process_coding);
+ }
+ }
+
if (nargs >= 2 && ! NILP (args[1]))
{
infile = Fexpand_file_name (args[1], current_buffer->directory);
if (CONSP (buffer))
{
if (CONSP (XCONS (buffer)->cdr))
- error_file = Fexpand_file_name (XCONS (XCONS (buffer)->cdr)->car,
- Qnil);
+ {
+ Lisp_Object stderr_file;
+ stderr_file = XCONS (XCONS (buffer)->cdr)->car;
+
+ if (NILP (stderr_file) || EQ (Qt, stderr_file))
+ error_file = stderr_file;
+ else
+ error_file = Fexpand_file_name (stderr_file, Qnil);
+ }
+
buffer = XCONS (buffer)->car;
}
for (i = 4; i < nargs; i++)
{
CHECK_STRING (args[i], i);
- new_argv[i - 3] = XSTRING (args[i])->data;
+ if (argument_coding.type == coding_type_no_conversion)
+ new_argv[i - 3] = XSTRING (args[i])->data;
+ else
+ {
+ /* We must encode the arguments. */
+ int size = encoding_buffer_size (&argument_coding,
+ XSTRING (args[i])->size);
+ int produced, dummy;
+ unsigned char *dummy1 = (unsigned char *) alloca (size);
+
+ /* The Irix 4.0 compiler barfs if we eliminate dummy. */
+ new_argv[i - 3] = dummy1;
+ produced = encode_coding (&argument_coding,
+ XSTRING (args[i])->data, new_argv[i - 3],
+ XSTRING (args[i])->size, size, &dummy);
+ new_argv[i - 3][produced] = 0;
+ }
}
new_argv[i - 3] = 0;
}
if (outfilefd < 0)
{
close (filefd);
- report_file_error ("Opening process output file", Fcons (tempfile, Qnil));
+ report_file_error ("Opening process output file",
+ Fcons (build_string (tempfile), Qnil));
}
+ fd[0] = filefd;
fd[1] = outfilefd;
-#endif
+#endif /* MSDOS */
if (INTEGERP (buffer))
fd[1] = open (NULL_DEVICE, O_WRONLY), fd[0] = -1;
if (fd_error < 0)
{
close (filefd);
- close (fd[0]);
+ if (fd[0] != filefd)
+ close (fd[0]);
if (fd1 >= 0)
close (fd1);
- report_file_error ("Cannot open", error_file);
+#ifdef MSDOS
+ unlink (tempfile);
+#endif
+ report_file_error ("Cannot redirect stderr",
+ Fcons ((NILP (error_file)
+ ? build_string (NULL_DEVICE) : error_file),
+ Qnil));
}
#ifdef MSDOS /* MW, July 1993 */
/* ??? Someone who knows MSDOG needs to check whether this properly
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);
{
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);
of the buffer size we have. But don't read
less than 1024--save that for the next bufferful. */
- nread = 0;
+ nread = process_coding.carryover_size; /* This value is initially 0. */
while (nread < bufsize - 1024)
{
int this_read
/* Now NREAD is the total amount of data in the buffer. */
if (nread == 0)
- break;
+ /* Here, just tell decode_coding that we are processing the
+ last block. We break the loop after decoding. */
+ process_coding.last_block = 1;
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, bufsize);
+ char *decoding_buf = get_conversion_buffer (size);
+ int dummy;
+
+ nread = decode_coding (&process_coding, bufptr, decoding_buf,
+ nread, size, &dummy);
+ if (nread > 0)
+ insert (decoding_buf, nread);
+ }
+ }
+
+ if (process_coding.last_block)
+ break;
/* Make the buffer bigger as we continue to read more data,
but not past 64k. */
bufptr = (char *) alloca (bufsize);
}
+ if (!NILP (buffer) && process_coding.carryover_size > 0)
+ /* We have carryover in the last decoding. It should be
+ processed again after reading more data. */
+ bcopy (process_coding.carryover, bufptr,
+ process_coding.carryover_size);
+
if (!NILP (display) && INTERACTIVE)
{
if (first)
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 = Qt;
+ Lisp_Object val, *args2;
+ int i;
#ifdef DOS_NT
+ char *tempfile;
char *outf = '\0';
if ((outf = egetenv ("TMP")) || (outf = egetenv ("TEMP")))
}
if (!IS_DIRECTORY_SEP (tempfile[strlen (tempfile) - 1]))
strcat (tempfile, "/");
-#ifdef WINDOWSNT
- strcat (tempfile, "emXXXXXX");
-#else
- strcat (tempfile, "detmp.XXX");
-#endif
if ('/' == DIRECTORY_SEP)
dostounix_filename (tempfile);
else
unixtodos_filename (tempfile);
-#else /* not DOS_NT */
-
-#ifdef VMS
- strcpy (tempfile, "tmp:emacsXXXXXX.");
+#ifdef WINDOWSNT
+ strcat (tempfile, "emXXXXXX");
#else
- strcpy (tempfile, "/tmp/emacsXXXXXX");
+ strcat (tempfile, "detmp.XXX");
#endif
+#else /* not DOS_NT */
+ char *tempfile = (char *) alloca (XSTRING (Vtemp_file_name_pattern)->size + 1);
+ bcopy (XSTRING (Vtemp_file_name_pattern)->data, tempfile,
+ XSTRING (Vtemp_file_name_pattern)->size + 1);
#endif /* not DOS_NT */
mktemp (tempfile);
GCPRO1 (filename_string);
start = args[0];
end = args[1];
+ /* Decide coding-system of the contents of the temporary file. */
#ifdef DOS_NT
specbind (Qbuffer_file_type, Vbinary_process_input);
+ if (NILP (Vbinary_process_input))
+ val = Qnil;
+ else
+#endif
+ {
+ 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 = XCONS (coding_systems)->cdr;
+ else if (CONSP (Vdefault_process_coding_system))
+ val = XCONS (Vdefault_process_coding_system)->car;
+ else
+ val = Qnil;
+ }
+ }
+ specbind (intern ("coding-system-for-write"), val);
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 */
+
+#ifdef DOS_NT
+ if (NILP (Vbinary_process_input))
+ val = Qnil;
+ else
+#endif
+ {
+ if (!NILP (Vcoding_system_for_read))
+ val = Vcoding_system_for_read;
+ else if (NILP (current_buffer->enable_multibyte_characters))
+ val = Qemacs_mule;
+ else
+ {
+ if (EQ (coding_systems, Qt))
+ {
+ 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);
+ }
+ val = CONSP (coding_systems) ? XCONS (coding_systems)->car : Qnil;
+ }
+ }
+ specbind (intern ("coding-system-for-read"), val);
record_unwind_protect (delete_temp_file, filename_string);
tempdir = Fdirectory_file_name (Vexec_directory);
if (access (XSTRING (tempdir)->data, 0) < 0)
- {
- fprintf (stderr,
- "Warning: arch-dependent data dir (%s) does not exist.\n",
- XSTRING (Vexec_directory)->data);
- sleep (2);
- }
+ 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)
- {
- fprintf (stderr,
- "Warning: arch-independent data dir (%s) does not exist.\n",
- XSTRING (Vdata_directory)->data);
- sleep (2);
- }
+ dir_warning ("Warning: arch-independent data dir (%s) does not exist.\n",
+ Vdata_directory);
#ifdef VMS
Vshell_file_name = build_string ("*dcl*");
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
}
set_process_environment ()
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'.");
+ /* The real initialization is when we start again. */
+ Vtemp_file_name_pattern = Qnil;
+
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\