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