8694b3867b660f14315b228cecadd896efb4677b
[chise/xemacs-chise.git.1] / src / callproc.c
1 /* Synchronous subprocess invocation for XEmacs.
2    Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
3
4 This file is part of XEmacs.
5
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING.  If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21 /* Synched up with: Mule 2.0, FSF 19.30. */
22 /* Partly sync'ed with 19.36.4 */
23
24 #include <config.h>
25 #include "lisp.h"
26
27 #include "buffer.h"
28 #include "commands.h"
29 #include "insdel.h"
30 #include "lstream.h"
31 #include "process.h"
32 #include "sysdep.h"
33 #include "window.h"
34 #ifdef FILE_CODING
35 #include "file-coding.h"
36 #endif
37
38 #include "systime.h"
39 #include "sysproc.h"
40 #include "sysfile.h" /* Always include after sysproc.h */
41 #include "syssignal.h" /* Always include before systty.h */
42 #include "systty.h"
43
44 #ifdef WINDOWSNT
45 #define _P_NOWAIT 1     /* from process.h */
46 #include <windows.h>
47 #include "nt.h"
48 #endif
49
50 #ifdef DOS_NT
51 /* When we are starting external processes we need to know whether they
52    take binary input (no conversion) or text input (\n is converted to
53    \r\n).  Similarly for output: if newlines are written as \r\n then it's
54    text process output, otherwise it's binary.  */
55 Lisp_Object Vbinary_process_input;
56 Lisp_Object Vbinary_process_output;
57 #endif /* DOS_NT */
58
59 Lisp_Object Vshell_file_name;
60
61 /* The environment to pass to all subprocesses when they are started.
62    This is in the semi-bogus format of ("VAR=VAL" "VAR2=VAL2" ... )
63  */
64 Lisp_Object Vprocess_environment;
65
66 /* True iff we are about to fork off a synchronous process or if we
67    are waiting for it.  */
68 volatile int synch_process_alive;
69
70 /* Nonzero => this is a string explaining death of synchronous subprocess.  */
71 CONST char *synch_process_death;
72
73 /* If synch_process_death is zero,
74    this is exit code of synchronous subprocess.  */
75 int synch_process_retcode;
76 \f
77 /* Clean up when exiting Fcall_process_internal.
78    On MSDOS, delete the temporary file on any kind of termination.
79    On Unix, kill the process and any children on termination by signal.  */
80
81 /* Nonzero if this is termination due to exit.  */
82 static int call_process_exited;
83
84 Lisp_Object Vlisp_EXEC_SUFFIXES;
85
86 static Lisp_Object
87 call_process_kill (Lisp_Object fdpid)
88 {
89   Lisp_Object fd = Fcar (fdpid);
90   Lisp_Object pid = Fcdr (fdpid);
91
92   if (!NILP (fd))
93     close (XINT (fd));
94
95   if (!NILP (pid))
96     EMACS_KILLPG (XINT (pid), SIGKILL);
97
98   synch_process_alive = 0;
99   return Qnil;
100 }
101
102 static Lisp_Object
103 call_process_cleanup (Lisp_Object fdpid)
104 {
105   int fd = XINT (Fcar (fdpid));
106   int pid = XINT (Fcdr (fdpid));
107 #ifdef WINDOWSNT
108   HANDLE pHandle;
109 #endif
110
111   if (!call_process_exited &&
112       EMACS_KILLPG (pid, SIGINT) == 0)
113   {
114     int speccount = specpdl_depth ();
115
116     record_unwind_protect (call_process_kill, fdpid);
117     /* #### "c-G" -- need non-consing Single-key-description */
118     message ("Waiting for process to die...(type C-g again to kill it instantly)");
119
120 #ifdef WINDOWSNT
121     pHandle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
122     if (pHandle == NULL)
123       {
124         warn_when_safe (Qprocess, Qwarning,
125                         "cannot open process (PID %d) for cleanup", pid);
126       }
127     wait_for_termination (pHandle);
128 #else
129     wait_for_termination (pid);
130 #endif
131
132     /* "Discard" the unwind protect.  */
133     XCAR (fdpid) = Qnil;
134     XCDR (fdpid) = Qnil;
135     unbind_to (speccount, Qnil);
136
137     message ("Waiting for process to die... done");
138   }
139   synch_process_alive = 0;
140   close (fd);
141   return Qnil;
142 }
143
144 static Lisp_Object fork_error;
145 #if 0 /* UNUSED */
146 static void
147 report_fork_error (char *string, Lisp_Object data)
148 {
149   Lisp_Object errstring = lisp_strerror (errno);
150
151   fork_error = Fcons (build_string (string), Fcons (errstring, data));
152
153   /* terminate this branch of the fork, without closing stdin/out/etc. */
154   _exit (1);
155 }
156 #endif /* unused */
157
158 DEFUN ("call-process-internal", Fcall_process_internal, 1, MANY, 0, /*
159 Call PROGRAM synchronously in separate process, with coding-system specified.
160 Arguments are
161  (PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS).
162 The program's input comes from file INFILE (nil means `/dev/null').
163 Insert output in BUFFER before point; t means current buffer;
164  nil for BUFFER means discard it; 0 means discard and don't wait.
165 BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case,
166 REAL-BUFFER says what to do with standard output, as above,
167 while STDERR-FILE says what to do with standard error in the child.
168 STDERR-FILE may be nil (discard standard error output),
169 t (mix it with ordinary output), or a file name string.
170
171 Fourth arg DISPLAY non-nil means redisplay buffer as output is inserted.
172 Remaining arguments are strings passed as command arguments to PROGRAM.
173
174 If BUFFER is 0, `call-process' returns immediately with value nil.
175 Otherwise it waits for PROGRAM to terminate and returns a numeric exit status
176  or a signal description string.
177 If you quit, the process is killed with SIGINT, or SIGKILL if you
178  quit again.
179 */
180        (int nargs, Lisp_Object *args))
181 {
182   /* This function can GC */
183   Lisp_Object infile, buffer, current_dir, display, path;
184   int fd[2];
185   int filefd;
186 #ifdef WINDOWSNT
187   HANDLE pHandle;
188 #endif
189   int pid;
190   char buf[16384];
191   char *bufptr = buf;
192   int bufsize = 16384;
193   int speccount = specpdl_depth ();
194   struct gcpro gcpro1, gcpro2;
195   char **new_argv = alloca_array (char *, max (2, nargs - 2));
196
197   /* File to use for stderr in the child.
198      t means use same as standard output.  */
199   Lisp_Object error_file;
200
201   CHECK_STRING (args[0]);
202
203   error_file = Qt;
204
205 #if defined (NO_SUBPROCESSES)
206   /* Without asynchronous processes we cannot have BUFFER == 0.  */
207   if (nargs >= 3 && !INTP (args[2]))
208     error ("Operating system cannot handle asynchronous subprocesses");
209 #endif /* NO_SUBPROCESSES */
210
211   /* Do this before building new_argv because GC in Lisp code
212    *  called by various filename-hacking routines might relocate strings */
213   locate_file (Vexec_path, args[0], Vlisp_EXEC_SUFFIXES, &path, X_OK);
214
215   /* Make sure that the child will be able to chdir to the current
216      buffer's current directory, or its unhandled equivalent.  We
217      can't just have the child check for an error when it does the
218      chdir, since it's in a vfork. */
219   {
220     struct gcpro ngcpro1, ngcpro2;
221     /* Do this test before building new_argv because GC in Lisp code
222      *  called by various filename-hacking routines might relocate strings */
223     /* Make sure that the child will be able to chdir to the current
224        buffer's current directory.  We can't just have the child check
225        for an error when it does the chdir, since it's in a vfork.  */
226
227     NGCPRO2 (current_dir, path);   /* Caller gcprotects args[] */
228     current_dir = current_buffer->directory;
229     current_dir = Funhandled_file_name_directory (current_dir);
230     current_dir = expand_and_dir_to_file (current_dir, Qnil);
231 #if 0
232     /* This is in FSF, but it breaks everything in the presence of
233        ange-ftp-visited files, so away with it.  */
234     if (NILP (Ffile_accessible_directory_p (current_dir)))
235       report_file_error ("Setting current directory",
236                          Fcons (current_buffer->directory, Qnil));
237 #endif /* 0 */
238     NUNGCPRO;
239   }
240
241   GCPRO1 (current_dir);
242
243   if (nargs >= 2 && ! NILP (args[1]))
244     {
245       struct gcpro ngcpro1;
246       NGCPRO1 (current_buffer->directory);
247       infile = Fexpand_file_name (args[1], current_buffer->directory);
248       NUNGCPRO;
249       CHECK_STRING (infile);
250     }
251   else
252     infile = build_string (NULL_DEVICE);
253
254   UNGCPRO;
255
256   GCPRO2 (infile, current_dir);         /* Fexpand_file_name might trash it */
257
258   if (nargs >= 3)
259     {
260       buffer = args[2];
261
262       /* If BUFFER is a list, its meaning is
263          (BUFFER-FOR-STDOUT FILE-FOR-STDERR).  */
264       if (CONSP (buffer))
265         {
266           if (CONSP (XCDR (buffer)))
267             {
268               Lisp_Object file_for_stderr = XCAR (XCDR (buffer));
269
270               if (NILP (file_for_stderr) || EQ (Qt, file_for_stderr))
271                 error_file = file_for_stderr;
272               else
273                 error_file = Fexpand_file_name (file_for_stderr, Qnil);
274             }
275
276           buffer = XCAR (buffer);
277         }
278
279       if (!(EQ (buffer, Qnil)
280             || EQ (buffer, Qt)
281             || ZEROP (buffer)))
282         {
283           Lisp_Object spec_buffer = buffer;
284           buffer = Fget_buffer (buffer);
285           /* Mention the buffer name for a better error message.  */
286           if (NILP (buffer))
287             CHECK_BUFFER (spec_buffer);
288           CHECK_BUFFER (buffer);
289         }
290     }
291   else
292     buffer = Qnil;
293
294   UNGCPRO;
295
296   display = ((nargs >= 4) ? args[3] : Qnil);
297
298   /* From here we assume we won't GC (unless an error is signaled). */
299   {
300     REGISTER int i;
301     for (i = 4; i < nargs; i++)
302       {
303         CHECK_STRING (args[i]);
304         new_argv[i - 3] = (char *) XSTRING_DATA (args[i]);
305       }
306   }
307   new_argv[max(nargs - 3,1)] = 0;
308
309   if (NILP (path))
310     report_file_error ("Searching for program", Fcons (args[0], Qnil));
311   new_argv[0] = (char *) XSTRING_DATA (path);
312
313   filefd = open ((char *) XSTRING_DATA (infile), O_RDONLY | OPEN_BINARY, 0);
314   if (filefd < 0)
315     report_file_error ("Opening process input file", Fcons (infile, Qnil));
316
317   if (INTP (buffer))
318     {
319       fd[1] = open (NULL_DEVICE, O_WRONLY | OPEN_BINARY, 0);
320       fd[0] = -1;
321     }
322   else
323     {
324       pipe (fd);
325 #if 0
326       /* Replaced by close_process_descs */
327       set_exclusive_use (fd[0]);
328 #endif
329     }
330
331   {
332     /* child_setup must clobber environ in systems with true vfork.
333        Protect it from permanent change.  */
334     REGISTER char **save_environ = environ;
335     REGISTER int fd1 = fd[1];
336     int fd_error = fd1;
337     char **env;
338
339     env = environ;
340
341     /* Record that we're about to create a synchronous process.  */
342     synch_process_alive = 1;
343
344     /* These vars record information from process termination.
345        Clear them now before process can possibly terminate,
346        to avoid timing error if process terminates soon.  */
347     synch_process_death = 0;
348     synch_process_retcode = 0;
349
350     if (NILP (error_file))
351       fd_error = open (NULL_DEVICE, O_WRONLY | OPEN_BINARY);
352     else if (STRINGP (error_file))
353       {
354         fd_error = open ((CONST char *) XSTRING_DATA (error_file),
355 #ifdef DOS_NT
356                          O_WRONLY | O_TRUNC | O_CREAT | O_TEXT,
357                          S_IREAD | S_IWRITE
358 #else  /* not DOS_NT */
359                          O_WRONLY | O_TRUNC | O_CREAT | OPEN_BINARY,
360                          CREAT_MODE
361 #endif /* not DOS_NT */
362                          );
363       }
364
365     if (fd_error < 0)
366       {
367         close (filefd);
368         close (fd[0]);
369         if (fd1 >= 0)
370           close (fd1);
371         report_file_error ("Cannot open", Fcons(error_file, Qnil));
372       }
373
374     fork_error = Qnil;
375 #ifdef WINDOWSNT
376     pid = child_setup (filefd, fd1, fd_error, new_argv,
377                        (char *) XSTRING_DATA (current_dir));
378     if (!INTP (buffer))
379       {
380         /* OpenProcess() as soon after child_setup as possible.  It's too
381            late once the process terminated. */
382         pHandle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
383 #if 0
384         if (pHandle == NULL)
385           {
386             /* #### seems to cause crash in unbind_to(...) below. APA */
387             warn_when_safe (Qprocess, Qwarning,
388                             "cannot open process to wait for");
389           }
390 #endif
391       }
392     /* Close STDERR into the parent process.  We no longer need it. */
393     if (fd_error >= 0)
394       close (fd_error);
395 #else  /* not WINDOWSNT */
396     pid = fork ();
397
398     if (pid == 0)
399       {
400         if (fd[0] >= 0)
401           close (fd[0]);
402         /* This is necessary because some shells may attempt to
403            access the current controlling terminal and will hang
404            if they are run in the background, as will be the case
405            when XEmacs is started in the background.  Martin
406            Buchholz observed this problem running a subprocess
407            that used zsh to call gzip to uncompress an info
408            file. */
409         disconnect_controlling_terminal ();
410         child_setup (filefd, fd1, fd_error, new_argv,
411                      (char *) XSTRING_DATA (current_dir));
412       }
413     if (fd_error >= 0)
414       close (fd_error);
415
416 #endif /* not WINDOWSNT */
417
418     environ = save_environ;
419
420     /* Close most of our fd's, but not fd[0]
421        since we will use that to read input from.  */
422     close (filefd);
423     if (fd1 >= 0)
424       close (fd1);
425   }
426
427   if (!NILP (fork_error))
428     signal_error (Qfile_error, fork_error);
429
430 #ifndef WINDOWSNT
431   if (pid < 0)
432     {
433       if (fd[0] >= 0)
434         close (fd[0]);
435       report_file_error ("Doing fork", Qnil);
436     }
437 #endif
438
439   if (INTP (buffer))
440     {
441       if (fd[0] >= 0)
442         close (fd[0]);
443 #if defined (NO_SUBPROCESSES)
444       /* If Emacs has been built with asynchronous subprocess support,
445          we don't need to do this, I think because it will then have
446          the facilities for handling SIGCHLD.  */
447       wait_without_blocking ();
448 #endif /* NO_SUBPROCESSES */
449       return Qnil;
450     }
451
452   {
453     int nread;
454     int first = 1;
455     int total_read = 0;
456     Lisp_Object instream;
457     struct gcpro ngcpro1;
458
459     /* Enable sending signal if user quits below.  */
460     call_process_exited = 0;
461
462     record_unwind_protect (call_process_cleanup,
463                            Fcons (make_int (fd[0]), make_int (pid)));
464
465     /* FSFmacs calls Fset_buffer() here.  We don't have to because
466        we can insert into buffers other than the current one. */
467     if (EQ (buffer, Qt))
468       XSETBUFFER (buffer, current_buffer);
469     instream = make_filedesc_input_stream (fd[0], 0, -1, LSTR_ALLOW_QUIT);
470 #ifdef FILE_CODING
471     instream =
472       make_decoding_input_stream
473         (XLSTREAM (instream),
474          Fget_coding_system (Vcoding_system_for_read));
475     Lstream_set_character_mode (XLSTREAM (instream));
476 #endif
477     NGCPRO1 (instream);
478     while (1)
479       {
480         QUIT;
481         /* Repeatedly read until we've filled as much as possible
482            of the buffer size we have.  But don't read
483            less than 1024--save that for the next bufferfull.  */
484
485         nread = 0;
486         while (nread < bufsize - 1024)
487           {
488             ssize_t this_read
489               = Lstream_read (XLSTREAM (instream), bufptr + nread,
490                               bufsize - nread);
491
492             if (this_read < 0)
493               goto give_up;
494
495             if (this_read == 0)
496               goto give_up_1;
497
498             nread += this_read;
499           }
500
501       give_up_1:
502
503         /* Now NREAD is the total amount of data in the buffer.  */
504         if (nread == 0)
505           break;
506
507 #ifdef DOS_NT
508        /* Until we pull out of MULE things like
509           make_decoding_input_stream(), we do the following which is
510           less elegant. --marcpa */
511        {
512          int lf_count = 0;
513          if (NILP (Vbinary_process_output)) {
514            nread = crlf_to_lf(nread, bufptr, &lf_count);
515          }
516        }
517 #endif
518
519         total_read += nread;
520
521         if (!NILP (buffer))
522           buffer_insert_raw_string (XBUFFER (buffer), (Bufbyte *) bufptr,
523                                     nread);
524
525         /* Make the buffer bigger as we continue to read more data,
526            but not past 64k.  */
527         if (bufsize < 64 * 1024 && total_read > 32 * bufsize)
528           {
529             bufsize *= 2;
530             bufptr = (char *) alloca (bufsize);
531           }
532
533         if (!NILP (display) && INTERACTIVE)
534           {
535             first = 0;
536             redisplay ();
537           }
538       }
539   give_up:
540     Lstream_close (XLSTREAM (instream));
541     NUNGCPRO;
542
543     QUIT;
544     /* Wait for it to terminate, unless it already has.  */
545 #ifdef WINDOWSNT
546     wait_for_termination (pHandle);
547 #else
548     wait_for_termination (pid);
549 #endif
550
551     /* Don't kill any children that the subprocess may have left behind
552        when exiting.  */
553     call_process_exited = 1;
554     unbind_to (speccount, Qnil);
555
556     if (synch_process_death)
557       return build_string (synch_process_death);
558     return make_int (synch_process_retcode);
559   }
560 }
561
562 \f
563
564 /* Move the file descriptor FD so that its number is not less than MIN. *
565    The original file descriptor remains open.  */
566 static int
567 relocate_fd (int fd, int min)
568 {
569   if (fd >= min)
570     return fd;
571   else
572     {
573       int newfd = dup (fd);
574       if (newfd == -1)
575         {
576           stderr_out ("Error while setting up child: %s\n",
577                       strerror (errno));
578           _exit (1);
579         }
580       return relocate_fd (newfd, min);
581     }
582 }
583
584 /* This is the last thing run in a newly forked inferior
585    either synchronous or asynchronous.
586    Copy descriptors IN, OUT and ERR
587    as descriptors STDIN_FILENO, STDOUT_FILENO, and STDERR_FILENO.
588    Initialize inferior's priority, pgrp, connected dir and environment.
589    then exec another program based on new_argv.
590
591    This function may change environ for the superior process.
592    Therefore, the superior process must save and restore the value
593    of environ around the fork and the call to this function.
594
595    ENV is the environment for the subprocess.
596
597    XEmacs: We've removed the SET_PGRP argument because it's already
598    done by the callers of child_setup.
599
600    CURRENT_DIR is an elisp string giving the path of the current
601    directory the subprocess should have.  Since we can't really signal
602    a decent error from within the child, this should be verified as an
603    executable directory by the parent.  */
604
605 #ifdef WINDOWSNT
606 int
607 #else
608 void
609 #endif
610 child_setup (int in, int out, int err, char **new_argv,
611              CONST char *current_dir)
612 {
613   char **env;
614   char *pwd;
615 #ifdef WINDOWSNT
616   int cpid;
617   HANDLE handles[4];
618 #endif /* WINDOWSNT */
619
620 #ifdef SET_EMACS_PRIORITY
621   if (emacs_priority != 0)
622     nice (- emacs_priority);
623 #endif
624
625 #if !defined (NO_SUBPROCESSES) && !defined (WINDOWSNT)
626   /* Close Emacs's descriptors that this process should not have.  */
627   close_process_descs ();
628 #endif /* not NO_SUBPROCESSES */
629   close_load_descs ();
630
631   /* Note that use of alloca is always safe here.  It's obvious for systems
632      that do not have true vfork or that have true (stack) alloca.
633      If using vfork and C_ALLOCA it is safe because that changes
634      the superior's static variables as if the superior had done alloca
635      and will be cleaned up in the usual way.  */
636   {
637     REGISTER int i;
638
639     i = strlen (current_dir);
640     pwd = alloca_array (char, i + 6);
641     memcpy (pwd, "PWD=", 4);
642     memcpy (pwd + 4, current_dir, i);
643     i += 4;
644     if (!IS_DIRECTORY_SEP (pwd[i - 1]))
645       pwd[i++] = DIRECTORY_SEP;
646     pwd[i] = 0;
647
648     /* We can't signal an Elisp error here; we're in a vfork.  Since
649        the callers check the current directory before forking, this
650        should only return an error if the directory's permissions
651        are changed between the check and this chdir, but we should
652        at least check.  */
653     if (chdir (pwd + 4) < 0)
654       {
655         /* Don't report the chdir error, or ange-ftp.el doesn't work. */
656         /* (FSFmacs does _exit (errno) here.) */
657         pwd = 0;
658       }
659     else
660       {
661         /* Strip trailing "/".  Cretinous *[]&@$#^%@#$% Un*x */
662         /* leave "//" (from FSF) */
663         while (i > 6 && IS_DIRECTORY_SEP (pwd[i - 1]))
664           pwd[--i] = 0;
665       }
666   }
667
668   /* Set `env' to a vector of the strings in Vprocess_environment.  */
669   /* + 2 to include PWD and terminating 0.  */
670   env = alloca_array (char *, XINT (Flength (Vprocess_environment)) + 2);
671   {
672     REGISTER Lisp_Object tail;
673     char **new_env = env;
674
675     /* If we have a PWD envvar and we know the real current directory,
676        pass one down, but with corrected value.  */
677     if (pwd && getenv ("PWD"))
678       *new_env++ = pwd;
679
680     /* Copy the Vprocess_environment strings into new_env.  */
681     for (tail = Vprocess_environment;
682          CONSP (tail) && STRINGP (XCAR (tail));
683          tail = XCDR (tail))
684     {
685       char **ep = env;
686       char *envvar_external;
687       Bufbyte *envvar_internal = XSTRING_DATA (XCAR (tail));
688
689       GET_C_CHARPTR_EXT_FILENAME_DATA_ALLOCA (envvar_internal, envvar_external);
690
691       /* See if envvar_external duplicates any string already in the env.
692          If so, don't put it in.
693          When an env var has multiple definitions,
694          we keep the definition that comes first in process-environment.  */
695       for (; ep != new_env; ep++)
696         {
697           char *p = *ep, *q = envvar_external;
698           while (1)
699             {
700               if (*q == 0)
701                 /* The string is malformed; might as well drop it.  */
702                 goto duplicate;
703               if (*q != *p)
704                 break;
705               if (*q == '=')
706                 goto duplicate;
707               p++, q++;
708             }
709         }
710       if (pwd && !strncmp ("PWD=", envvar_external, 4))
711         {
712           *new_env++ = pwd;
713           pwd = 0;
714         }
715       else
716         *new_env++ = envvar_external;
717
718     duplicate: ;
719     }
720     *new_env = 0;
721   }
722
723 #ifdef WINDOWSNT
724   prepare_standard_handles (in, out, err, handles);
725   set_process_dir (current_dir);
726 #else  /* not WINDOWSNT */
727   /* Make sure that in, out, and err are not actually already in
728      descriptors zero, one, or two; this could happen if Emacs is
729      started with its standard in, out, or error closed, as might
730      happen under X.  */
731   in  = relocate_fd (in,  3);
732   out = relocate_fd (out, 3);
733   err = relocate_fd (err, 3);
734
735   /* Set the standard input/output channels of the new process.  */
736   close (STDIN_FILENO);
737   close (STDOUT_FILENO);
738   close (STDERR_FILENO);
739
740   dup2 (in,  STDIN_FILENO);
741   dup2 (out, STDOUT_FILENO);
742   dup2 (err, STDERR_FILENO);
743
744   close (in);
745   close (out);
746   close (err);
747
748   /* I can't think of any reason why child processes need any more
749      than the standard 3 file descriptors.  It would be cleaner to
750      close just the ones that need to be, but the following brute
751      force approach is certainly effective, and not too slow. */
752   {
753     int fd;
754     for (fd=3; fd<=64; fd++)
755       close (fd);
756   }
757 #endif /* not WINDOWSNT */
758
759 #ifdef vipc
760   something missing here;
761 #endif /* vipc */
762
763 #ifdef WINDOWSNT
764   /* Spawn the child.  (See ntproc.c:Spawnve).  */
765   cpid = spawnve (_P_NOWAIT, new_argv[0], (CONST char* CONST*)new_argv,
766                   (CONST char* CONST*)env);
767   if (cpid == -1)
768     /* An error occurred while trying to spawn the process.  */
769     report_file_error ("Spawning child process", Qnil);
770   reset_standard_handles (in, out, err, handles);
771   return cpid;
772 #else /* not WINDOWSNT */
773   /* execvp does not accept an environment arg so the only way
774      to pass this environment is to set environ.  Our caller
775      is responsible for restoring the ambient value of environ.  */
776   environ = env;
777   execvp (new_argv[0], new_argv);
778
779   stdout_out ("Can't exec program %s\n", new_argv[0]);
780   _exit (1);
781 #endif /* not WINDOWSNT */
782 }
783
784 static int
785 getenv_internal (CONST Bufbyte *var,
786                  Bytecount varlen,
787                  Bufbyte **value,
788                  Bytecount *valuelen)
789 {
790   Lisp_Object scan;
791
792   for (scan = Vprocess_environment; CONSP (scan); scan = XCDR (scan))
793     {
794       Lisp_Object entry = XCAR (scan);
795
796       if (STRINGP (entry)
797           && XSTRING_LENGTH (entry) > varlen
798           && XSTRING_BYTE (entry, varlen) == '='
799 #ifdef WINDOWSNT
800           /* NT environment variables are case insensitive.  */
801           && ! memicmp (XSTRING_DATA (entry), var, varlen)
802 #else  /* not WINDOWSNT */
803           && ! memcmp (XSTRING_DATA (entry), var, varlen)
804 #endif /* not WINDOWSNT */
805           )
806         {
807           *value    = XSTRING_DATA   (entry) + (varlen + 1);
808           *valuelen = XSTRING_LENGTH (entry) - (varlen + 1);
809           return 1;
810         }
811     }
812
813   return 0;
814 }
815
816 DEFUN ("getenv", Fgetenv, 1, 2, "sEnvironment variable: \np", /*
817 Return the value of environment variable VAR, as a string.
818 VAR is a string, the name of the variable.
819 When invoked interactively, prints the value in the echo area.
820 */
821        (var, interactivep))
822 {
823   Bufbyte *value;
824   Bytecount valuelen;
825   Lisp_Object v = Qnil;
826   struct gcpro gcpro1;
827
828   CHECK_STRING (var);
829   GCPRO1 (v);
830   if (getenv_internal (XSTRING_DATA (var), XSTRING_LENGTH (var),
831                        &value, &valuelen))
832     v = make_string (value, valuelen);
833   if (!NILP (interactivep))
834     {
835       if (NILP (v))
836         message ("%s not defined in environment", XSTRING_DATA (var));
837       else
838         /* #### Should use Fprin1_to_string or Fprin1 to handle string
839            containing quotes correctly.  */
840         message ("\"%s\"", value);
841     }
842   RETURN_UNGCPRO (v);
843 }
844
845 /* A version of getenv that consults process_environment, easily
846    callable from C.  */
847 char *
848 egetenv (CONST char *var)
849 {
850   Bufbyte *value;
851   Bytecount valuelen;
852
853   if (getenv_internal ((CONST Bufbyte *) var, strlen (var), &value, &valuelen))
854     return (char *) value;
855   else
856     return 0;
857 }
858
859 \f
860 void
861 init_callproc (void)
862 {
863   /* This function can GC */
864
865   {
866     /* jwz: always initialize Vprocess_environment, so that egetenv()
867        works in temacs. */
868     char **envp;
869     Vprocess_environment = Qnil;
870     for (envp = environ; envp && *envp; envp++)
871       {
872         Vprocess_environment = Fcons (build_ext_string (*envp, FORMAT_OS),
873                                       Vprocess_environment);
874       }
875   }
876
877   {
878     /* Initialize shell-file-name from environment variables or best guess. */
879 #ifdef WINDOWSNT
880     CONST char *shell = egetenv ("COMSPEC");
881     if (!shell) shell = "\\WINNT\\system32\\cmd.exe";
882 #else /* not WINDOWSNT */
883     CONST char *shell = egetenv ("SHELL");
884     if (!shell) shell = "/bin/sh";
885 #endif
886
887     Vshell_file_name = build_string (shell);
888   }
889 }
890
891 #if 0
892 void
893 set_process_environment (void)
894 {
895   REGISTER char **envp;
896
897   Vprocess_environment = Qnil;
898 #ifndef CANNOT_DUMP
899   if (initialized)
900 #endif
901     for (envp = environ; *envp; envp++)
902       Vprocess_environment = Fcons (build_string (*envp),
903                                     Vprocess_environment);
904 }
905 #endif /* unused */
906
907 void
908 syms_of_callproc (void)
909 {
910   DEFSUBR (Fcall_process_internal);
911   DEFSUBR (Fgetenv);
912 }
913
914 void
915 vars_of_callproc (void)
916 {
917   /* This function can GC */
918 #ifdef DOS_NT
919   DEFVAR_LISP ("binary-process-input", &Vbinary_process_input /*
920 *If non-nil then new subprocesses are assumed to take binary input.
921 */ );
922   Vbinary_process_input = Qnil;
923
924   DEFVAR_LISP ("binary-process-output", &Vbinary_process_output /*
925 *If non-nil then new subprocesses are assumed to produce binary output.
926 */ );
927   Vbinary_process_output = Qnil;
928 #endif /* DOS_NT */
929
930   DEFVAR_LISP ("shell-file-name", &Vshell_file_name /*
931 *File name to load inferior shells from.
932 Initialized from the SHELL environment variable.
933 */ );
934
935   DEFVAR_LISP ("process-environment", &Vprocess_environment /*
936 List of environment variables for subprocesses to inherit.
937 Each element should be a string of the form ENVVARNAME=VALUE.
938 The environment which Emacs inherits is placed in this variable
939 when Emacs starts.
940 */ );
941
942   Vlisp_EXEC_SUFFIXES = build_string (EXEC_SUFFIXES);
943   staticpro (&Vlisp_EXEC_SUFFIXES);
944 }