comparison src/callproc.c @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 9ee227acff29
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
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
23 #include <config.h>
24 #include "lisp.h"
25
26 #include "buffer.h"
27 #include "commands.h"
28 #include "insdel.h"
29 #include "lstream.h"
30 #include "paths.h"
31 #include "process.h"
32 #include "sysdep.h"
33 #include "window.h"
34
35 #include "sysfile.h"
36 #include "systime.h"
37 #include "sysproc.h"
38 #include "syssignal.h" /* Always include before systty.h */
39 #include "systty.h"
40
41
42 #ifdef DOS_NT
43 /* When we are starting external processes we need to know whether they
44 take binary input (no conversion) or text input (\n is converted to
45 \r\n). Similar for output: if newlines are written as \r\n then it's
46 text process output, otherwise it's binary. */
47 Lisp_Object Vbinary_process_input;
48 Lisp_Object Vbinary_process_output;
49 #endif /* DOS_NT */
50
51 Lisp_Object Vexec_path, Vexec_directory, Vdata_directory, Vdoc_directory;
52 Lisp_Object Vconfigure_info_directory;
53
54 /* The default base directory XEmacs is installed under. */
55 Lisp_Object Vprefix_directory;
56
57 Lisp_Object Vshell_file_name;
58
59 /* The environment to pass to all subprocesses when they are started.
60 This is in the semi-bogus format of ("VAR=VAL" "VAR2=VAL2" ... )
61 */
62 Lisp_Object Vprocess_environment;
63
64 /* True iff we are about to fork off a synchronous process or if we
65 are waiting for it. */
66 volatile int synch_process_alive;
67
68 /* Nonzero => this is a string explaining death of synchronous subprocess. */
69 CONST char *synch_process_death;
70
71 /* If synch_process_death is zero,
72 this is exit code of synchronous subprocess. */
73 int synch_process_retcode;
74
75 /* Clean up when exiting Fcall_process_internal.
76 On MSDOS, delete the temporary file on any kind of termination.
77 On Unix, kill the process and any children on termination by signal. */
78
79 /* Nonzero if this is termination due to exit. */
80 static int call_process_exited;
81
82 #ifndef VMS /* VMS version is in vmsproc.c. */
83
84 static Lisp_Object
85 call_process_kill (Lisp_Object fdpid)
86 {
87 Lisp_Object fd = Fcar (fdpid);
88 Lisp_Object pid = Fcdr (fdpid);
89
90 if (!NILP (fd))
91 close (XINT (fd));
92
93 if (!NILP (pid))
94 EMACS_KILLPG (XINT (pid), SIGKILL);
95
96 synch_process_alive = 0;
97 return Qnil;
98 }
99
100 static Lisp_Object
101 call_process_cleanup (Lisp_Object fdpid)
102 {
103 #ifdef MSDOS
104 /* for MSDOS fdpid is really (fd . tempfile) */
105 Lisp_Object file = Fcdr (fdpid);
106 close (XINT (Fcar (fdpid)));
107 if (strcmp (string_data (XSTRING (file)), NULL_DEVICE) != 0)
108 unlink (string_data (XSTRING (file)));
109 #else /* not MSDOS */
110 int fd = XINT (Fcar (fdpid));
111 int pid = XINT (Fcdr (fdpid));
112
113 if (!call_process_exited &&
114 EMACS_KILLPG (pid, SIGINT) == 0)
115 {
116 int speccount = specpdl_depth ();
117
118 record_unwind_protect (call_process_kill, fdpid);
119 /* #### "c-G" -- need non-consing Single-key-description */
120 message ("Waiting for process to die...(type C-g again to kill it instantly)");
121
122 /* "Discard" the unwind protect. */
123 XCAR (fdpid) = Qnil;
124 XCDR (fdpid) = Qnil;
125 unbind_to (speccount, Qnil);
126
127 message ("Waiting for process to die... done");
128 }
129 synch_process_alive = 0;
130 close (fd);
131 #endif /* not MSDOS */
132 return Qnil;
133 }
134
135 static Lisp_Object fork_error;
136 #if 0 /* UNUSED */
137 static void
138 report_fork_error (char *string, Lisp_Object data)
139 {
140 Lisp_Object errstring = build_string (strerror (errno));
141
142 /* System error messages are capitalized. Downcase the initial. */
143 set_string_char (XSTRING (errstring), 0,
144 DOWNCASE (current_buffer,
145 string_char (XSTRING (errstring), 0)));
146
147 fork_error = Fcons (build_string (string), Fcons (errstring, data));
148
149 /* terminate this branch of the fork, without closing stdin/out/etc. */
150 _exit (1);
151 }
152 #endif /* unused */
153
154 DEFUN ("call-process-internal", Fcall_process_internal,
155 Scall_process_internal, 1, MANY, 0 /*
156 Call PROGRAM synchronously in separate process, with coding-system specified.
157 Arguments are
158 (PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS).
159 The program's input comes from file INFILE (nil means `/dev/null').
160 Insert output in BUFFER before point; t means current buffer;
161 nil for BUFFER means discard it; 0 means discard and don't wait.
162 BUFFER can also have the form (REAL-BUFFER STDERR-FILE); in that case,
163 REAL-BUFFER says what to do with standard output, as above,
164 while STDERR-FILE says what to do with standard error in the child.
165 STDERR-FILE may be nil (discard standard error output),
166 t (mix it with ordinary output), or a file name string.
167
168 Fourth arg DISPLAY non-nil means redisplay buffer as output is inserted.
169 Remaining arguments are strings passed as command arguments to PROGRAM.
170
171 If BUFFER is 0, `call-process' returns immediately with value nil.
172 Otherwise it waits for PROGRAM to terminate and returns a numeric exit status
173 or a signal description string.
174 If you quit, the process is killed with SIGINT, or SIGKILL if you
175 quit again.
176 */ )
177 (nargs, args)
178 int nargs;
179 Lisp_Object *args;
180 {
181 /* This function can GC */
182 Lisp_Object infile, buffer, current_dir, display, path;
183 int fd[2];
184 int filefd;
185 int pid;
186 char buf[16384];
187 char *bufptr = buf;
188 int bufsize = 16384;
189 int speccount = specpdl_depth ();
190 char **new_argv
191 = (char **) alloca ((max (2, nargs - 2)) * sizeof (char *));
192
193 /* File to use for stderr in the child.
194 t means use same as standard output. */
195 Lisp_Object error_file;
196 #ifdef MSDOS
197 char *outf, *tempfile;
198 int outfilefd;
199 #endif
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
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], 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 gcpro1, gcpro2;
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 GCPRO2 (current_dir, path); /* Caller gcprotects args[] */
228 current_dir = current_buffer->directory;
229 current_dir = expand_and_dir_to_file
230 (Funhandled_file_name_directory (current_dir), Qnil);
231 #if 0
232 /* I don't know how RMS intends this crock of shit to work, but it
233 breaks everything in the presence of ange-ftp-visited files, so
234 fuck it. */
235 if (NILP (Ffile_accessible_directory_p (current_dir)))
236 report_file_error ("Setting current directory",
237 Fcons (current_buffer->directory, Qnil));
238 #endif /* 0 */
239 UNGCPRO;
240 }
241
242 if (nargs >= 2 && ! NILP (args[1]))
243 {
244 infile = Fexpand_file_name (args[1],
245 current_buffer->directory);
246 CHECK_STRING (infile);
247 }
248 else
249 infile = build_string (NULL_DEVICE);
250
251 if (nargs >= 3)
252 {
253 buffer = args[2];
254
255 /* If BUFFER is a list, its meaning is
256 (BUFFER-FOR-STDOUT FILE-FOR-STDERR). */
257 if (CONSP (buffer))
258 {
259 if (CONSP (XCDR (buffer)))
260 {
261 Lisp_Object file_for_stderr = XCAR (XCDR (buffer));
262
263 if (NILP (file_for_stderr) || EQ (Qt, file_for_stderr))
264 error_file = file_for_stderr;
265 else
266 error_file = Fexpand_file_name (file_for_stderr, Qnil);
267 }
268
269 buffer = XCAR (buffer);
270 }
271
272 if (!(EQ (buffer, Qnil)
273 || EQ (buffer, Qt)
274 || ZEROP (buffer)))
275 {
276 Lisp_Object spec_buffer;
277 spec_buffer = buffer;
278 buffer = Fget_buffer (buffer);
279 /* Mention the buffer name for a better error message. */
280 if (NILP (buffer))
281 CHECK_BUFFER (spec_buffer);
282 CHECK_BUFFER (buffer);
283 }
284 }
285 else
286 buffer = Qnil;
287
288 display = ((nargs >= 4) ? args[3] : Qnil);
289
290 /* From here we assume we won't GC (unless an error is signalled). */
291 {
292 REGISTER int i;
293 for (i = 4; i < nargs; i++)
294 {
295 CHECK_STRING (args[i]);
296 new_argv[i - 3] = (char *) string_data (XSTRING (args[i]));
297 }
298 /* Program name is first command arg */
299 new_argv[0] = (char *) string_data (XSTRING (args[0]));
300 new_argv[i - 3] = 0;
301 }
302
303 filefd = open ((char *) string_data (XSTRING (infile)), O_RDONLY, 0);
304 if (filefd < 0)
305 {
306 report_file_error ("Opening process input file",
307 Fcons (infile, Qnil));
308 }
309
310 if (NILP (path))
311 {
312 close (filefd);
313 report_file_error ("Searching for program",
314 Fcons (args[0], Qnil));
315 }
316 new_argv[0] = (char *) string_data (XSTRING (path));
317
318 #ifdef MSDOS
319 /* These vars record information from process termination.
320 Clear them now before process can possibly terminate,
321 to avoid timing error if process terminates soon. */
322 synch_process_death = 0;
323 synch_process_retcode = 0;
324
325 if ((outf = egetenv ("TMP")) || (outf = egetenv ("TEMP")))
326 strcpy (tempfile = alloca (strlen (outf) + 20), outf);
327 else
328 {
329 tempfile = alloca (20);
330 *tempfile = '\0';
331 }
332 dostounix_filename (tempfile);
333 if (*tempfile == '\0' || tempfile[strlen (tempfile) - 1] != '/')
334 strcat (tempfile, "/");
335 strcat (tempfile, "detmp.XXX");
336 mktemp (tempfile);
337
338 outfilefd = creat (tempfile, S_IREAD | S_IWRITE);
339 if (outfilefd < 0)
340 {
341 close (filefd);
342 report_file_error ("Opening process output file",
343 Fcons (tempfile, Qnil));
344 }
345 #endif
346
347 #ifndef MSDOS
348 if (INTP (buffer))
349 {
350 fd[1] = open (NULL_DEVICE, O_WRONLY, 0);
351 fd[0] = -1;
352 }
353 else
354 {
355 #ifdef WINDOWSNT
356 pipe_with_inherited_out (fd);
357 #else /* not WINDOWSNT */
358 pipe (fd);
359 #endif /* not WINDOWSNT */
360 #if 0
361 /* Replaced by close_process_descs */
362 set_exclusive_use (fd[0]);
363 #endif
364 }
365 #else /* MSDOS */
366 {
367 char *outf;
368
369 if (INTP (buffer))
370 outf = NULL_DEVICE;
371 else
372 {
373 /* DOS can't create pipe for interprocess communication,
374 so redirect child process's standard output to temporary file
375 and later read the file. */
376
377 if ((outf = egetenv ("TMP")) || (outf = egetenv ("TEMP")))
378 {
379 strcpy (tempfile, outf);
380 dostounix_filename (tempfile);
381 }
382 else
383 *tempfile = '\0';
384 if (strlen (tempfile) == 0 || tempfile[strlen (tempfile) - 1] != '/')
385 strcat (tempfile, "/");
386 strcat (tempfile, "demacs.XXX");
387 mktemp (tempfile);
388 outf = tempfile;
389 }
390
391 if ((fd[1] = creat (outf, S_IREAD | S_IWRITE)) < 0)
392 report_file_error ("Can't open temporary file", Qnil);
393 fd[0] = -1;
394 }
395 #endif /* MSDOS */
396
397 {
398 /* child_setup must clobber environ in systems with true vfork.
399 Protect it from permanent change. */
400 REGISTER char **save_environ = environ;
401 REGISTER int fd1 = fd[1];
402 int fd_error = fd1;
403 char **env;
404
405 #ifdef EMACS_BTL
406 /* when performance monitoring is on, turn it off before the vfork(),
407 as the child has no handler for the signal -- when back in the
408 parent process, turn it back on if it was really on when you "turned
409 it off" */
410 int logging_on = cadillac_stop_logging ();
411 #endif
412
413 env = environ;
414
415 /* Record that we're about to create a synchronous process. */
416 synch_process_alive = 1;
417
418 /* These vars record information from process termination.
419 Clear them now before process can possibly terminate,
420 to avoid timing error if process terminates soon. */
421 synch_process_death = 0;
422 synch_process_retcode = 0;
423
424 #ifdef MSDOS
425 /* ??? Someone who knows MSDOG needs to check whether this properly
426 closes all descriptors that it opens. */
427 pid = run_msdos_command (new_argv, current_dir, filefd, outfilefd);
428 close (outfilefd);
429 fd1 = -1; /* No harm in closing that one! */
430 fd[0] = open (tempfile, NILP (Vbinary_process_output) ? O_TEXT :
431 O_BINARY);
432 if (fd[0] < 0)
433 {
434 unlink (tempfile);
435 close (filefd);
436 report_file_error ("Cannot re-open temporary file", Qnil);
437 }
438 #else /* not MSDOS */
439 if (NILP (error_file))
440 fd_error = open (NULL_DEVICE, O_WRONLY);
441 else if (STRINGP (error_file))
442 {
443 #ifdef DOS_NT
444 fd_error = open (string_data (XSTRING (error_file)),
445 O_WRONLY | O_TRUNC | O_CREAT | O_TEXT,
446 S_IREAD | S_IWRITE);
447 #else /* not DOS_NT */
448 fd_error =
449 creat ((CONST char *) string_data (XSTRING (error_file)), 0666);
450 #endif /* not DOS_NT */
451 }
452
453 if (fd_error < 0)
454 {
455 close (filefd);
456 close (fd[0]);
457 if (fd1 >= 0)
458 close (fd1);
459 report_file_error ("Cannot open", error_file);
460 }
461
462 fork_error = Qnil;
463 #ifdef WINDOWSNT
464 pid = child_setup (filefd, fd1, fd_error, new_argv, current_dir);
465 #else /* not WINDOWSNT */
466 pid = vfork ();
467
468 if (pid == 0)
469 {
470 if (fd[0] >= 0)
471 close (fd[0]);
472 /* This is necessary because some shells may attempt to
473 access the current controlling terminal and will hang
474 if they are run in the background, as will be the case
475 when XEmacs is started in the background. Martin
476 Buchholz observed this problem running a subprocess
477 that used zsh to call gzip to uncompress an info
478 file. */
479 disconnect_controlling_terminal ();
480 child_setup (filefd, fd1, fd_error, new_argv,
481 (char *) string_data (XSTRING (current_dir)));
482 }
483 #ifdef EMACS_BTL
484 else if (logging_on)
485 cadillac_start_logging ();
486 #endif
487
488 #endif /* not MSDOS */
489 #endif /* not WINDOWSNT */
490
491 environ = save_environ;
492
493 /* Close most of our fd's, but not fd[0]
494 since we will use that to read input from. */
495 close (filefd);
496 if (fd1 >= 0)
497 close (fd1);
498 }
499
500 if (!NILP (fork_error))
501 signal_error (Qfile_error, fork_error);
502
503 if (pid < 0)
504 {
505 if (fd[0] >= 0)
506 close (fd[0]);
507 report_file_error ("Doing vfork", Qnil);
508 }
509
510 if (INTP (buffer))
511 {
512 if (fd[0] >= 0)
513 close (fd[0]);
514 #if defined (NO_SUBPROCESSES)
515 /* If Emacs has been built with asynchronous subprocess support,
516 we don't need to do this, I think because it will then have
517 the facilities for handling SIGCHLD. */
518 wait_without_blocking ();
519 #endif
520 return Qnil;
521 }
522
523 {
524 int nread;
525 int first = 1;
526 int total_read = 0;
527 Lisp_Object instream;
528 struct gcpro gcpro1;
529
530 /* Enable sending signal if user quits below. */
531 call_process_exited = 0;
532
533 #ifdef MSDOS
534 /* MSDOS needs different cleanup information. */
535 record_unwind_protect (call_process_cleanup,
536 Fcons (make_int (fd[0]),
537 build_string (tempfile)));
538 #else
539 record_unwind_protect (call_process_cleanup,
540 Fcons (make_int (fd[0]), make_int (pid)));
541 #endif /* not MSDOS */
542
543 /* FSFmacs calls Fset_buffer() here. We don't have to because
544 we can insert into buffers other than the current one. */
545 if (EQ (buffer, Qt))
546 XSETBUFFER (buffer, current_buffer);
547 instream = make_filedesc_input_stream (fd[0], 0, -1, LSTR_ALLOW_QUIT);
548 GCPRO1 (instream);
549 while (1)
550 {
551 QUIT;
552 /* Repeatedly read until we've filled as much as possible
553 of the buffer size we have. But don't read
554 less than 1024--save that for the next bufferfull. */
555
556 nread = 0;
557 while (nread < bufsize - 1024)
558 {
559 int this_read
560 = Lstream_read (XLSTREAM (instream), bufptr + nread,
561 bufsize - nread);
562
563 if (this_read < 0)
564 goto give_up;
565
566 if (this_read == 0)
567 goto give_up_1;
568
569 nread += this_read;
570 }
571
572 give_up_1:
573
574 /* Now NREAD is the total amount of data in the buffer. */
575 if (nread == 0)
576 break;
577
578 total_read += nread;
579
580 if (!NILP (buffer))
581 buffer_insert_raw_string (XBUFFER (buffer), (Bufbyte *) bufptr,
582 nread);
583
584 /* Make the buffer bigger as we continue to read more data,
585 but not past 64k. */
586 if (bufsize < 64 * 1024 && total_read > 32 * bufsize)
587 {
588 bufsize *= 2;
589 bufptr = (char *) alloca (bufsize);
590 }
591
592 if (!NILP (display) && INTERACTIVE)
593 {
594 first = 0;
595 redisplay ();
596 }
597 }
598 give_up:
599 Lstream_close (XLSTREAM (instream));
600 UNGCPRO;
601
602 QUIT;
603 #ifndef MSDOS
604 /* Wait for it to terminate, unless it already has. */
605 wait_for_termination (pid);
606 #endif
607
608 /* Don't kill any children that the subprocess may have left behind
609 when exiting. */
610 call_process_exited = 1;
611 unbind_to (speccount, Qnil);
612
613 if (synch_process_death)
614 return build_string (synch_process_death);
615 return make_int (synch_process_retcode);
616 }
617 }
618
619 #endif /* VMS */
620
621 #ifndef VMS /* VMS version is in vmsproc.c. */
622
623 /* This is the last thing run in a newly forked inferior
624 either synchronous or asynchronous.
625 Copy descriptors IN, OUT and ERR as descriptors 0, 1 and 2.
626 Initialize inferior's priority, pgrp, connected dir and environment.
627 then exec another program based on new_argv.
628
629 This function may change environ for the superior process.
630 Therefore, the superior process must save and restore the value
631 of environ around the vfork and the call to this function.
632
633 ENV is the environment for the subprocess.
634
635 XEmacs: We've removed the SET_PGRP argument because it's already
636 done by the callers of child_setup.
637
638 CURRENT_DIR is an elisp string giving the path of the current
639 directory the subprocess should have. Since we can't really signal
640 a decent error from within the child, this should be verified as an
641 executable directory by the parent. */
642
643 static int relocate_fd (int fd, int min);
644
645 void
646 child_setup (int in, int out, int err, char **new_argv,
647 CONST char *current_dir)
648 {
649 #ifdef MSDOS
650 /* The MSDOS port of gcc cannot fork, vfork, ... so we must call system
651 instead. */
652 #else /* not MSDOS */
653 char **env;
654 char *pwd;
655 #ifdef WINDOWSNT
656 int cpid;
657 HANDLE handles[4];
658 #endif /* WINDOWSNT */
659
660 #ifdef SET_EMACS_PRIORITY
661 if (emacs_priority != 0)
662 nice (- emacs_priority);
663 #endif
664
665 #if !defined (NO_SUBPROCESSES)
666 /* Close Emacs's descriptors that this process should not have. */
667 close_process_descs ();
668 #endif
669 close_load_descs ();
670
671 /* Note that use of alloca is always safe here. It's obvious for systems
672 that do not have true vfork or that have true (stack) alloca.
673 If using vfork and C_ALLOCA it is safe because that changes
674 the superior's static variables as if the superior had done alloca
675 and will be cleaned up in the usual way. */
676 {
677 REGISTER int i;
678
679 i = strlen (current_dir);
680 pwd = (char *) alloca (i + 6);
681 memcpy (pwd, "PWD=", 4);
682 memcpy (pwd + 4, current_dir, i);
683 i += 4;
684 if (!IS_DIRECTORY_SEP (pwd[i - 1]))
685 pwd[i++] = DIRECTORY_SEP;
686 pwd[i] = 0;
687
688 /* We can't signal an Elisp error here; we're in a vfork. Since
689 the callers check the current directory before forking, this
690 should only return an error if the directory's permissions
691 are changed between the check and this chdir, but we should
692 at least check. */
693 if (chdir (pwd + 4) < 0)
694 {
695 /* Don't report the chdir error, or ange-ftp.el doesn't work. */
696 /* (FSFmacs does _exit (errno) here.) */
697 pwd = 0;
698 }
699 else
700 {
701 /* Strip trailing "/". Cretinous *[]&@$#^%@#$% Un*x */
702 /* leave "//" (from FSF) */
703 while (i > 6 && IS_DIRECTORY_SEP (pwd[i - 1]))
704 pwd[--i] = 0;
705 }
706 }
707
708 /* Set `env' to a vector of the strings in Vprocess_environment. */
709 {
710 REGISTER Lisp_Object tem;
711 REGISTER char **new_env;
712 REGISTER int new_length;
713
714 new_length = 0;
715 for (tem = Vprocess_environment;
716 (CONSP (tem)
717 && STRINGP (XCAR (tem)));
718 tem = XCDR (tem))
719 new_length++;
720
721 /* new_length + 2 to include PWD and terminating 0. */
722 env = new_env = (char **) alloca ((new_length + 2) * sizeof (char *));
723
724 /* If we have a PWD envvar and we know the real current directory,
725 pass one down, but with corrected value. */
726 if (pwd && getenv ("PWD"))
727 *new_env++ = pwd;
728
729 /* Copy the Vprocess_environment strings into new_env. */
730 for (tem = Vprocess_environment;
731 (CONSP (tem)
732 && STRINGP (XCAR (tem)));
733 tem = XCDR (tem))
734 {
735 char **ep = env;
736 char *string = (char *) string_data (XSTRING (XCAR (tem)));
737 /* See if this string duplicates any string already in the env.
738 If so, don't put it in.
739 When an env var has multiple definitions,
740 we keep the definition that comes first in process-environment. */
741 for (; ep != new_env; ep++)
742 {
743 char *p = *ep, *q = string;
744 while (1)
745 {
746 if (*q == 0)
747 /* The string is malformed; might as well drop it. */
748 goto duplicate;
749 if (*q != *p)
750 break;
751 if (*q == '=')
752 goto duplicate;
753 p++, q++;
754 }
755 }
756 if (pwd && !strncmp ("PWD=", string, 4))
757 {
758 *new_env++ = pwd;
759 pwd = 0;
760 }
761 else
762 *new_env++ = string;
763 duplicate: ;
764 }
765 *new_env = 0;
766 }
767 #ifdef WINDOWSNT
768 prepare_standard_handles (in, out, err, handles);
769 #else /* not WINDOWSNT */
770 /* Make sure that in, out, and err are not actually already in
771 descriptors zero, one, or two; this could happen if Emacs is
772 started with its standard in, out, or error closed, as might
773 happen under X. */
774 {
775 int oin = in, oout = out;
776
777 /* We have to avoid relocating the same descriptor twice! */
778
779 in = relocate_fd (in, 3);
780
781 if (out == oin) out = in;
782 else out = relocate_fd (out, 3);
783
784 if (err == oin) err = in;
785 else if (err == oout) err = out;
786 else err = relocate_fd (err, 3);
787 }
788
789 close (0);
790 close (1);
791 close (2);
792
793 dup2 (in, 0);
794 dup2 (out, 1);
795 dup2 (err, 2);
796
797 close (in);
798 close (out);
799 close (err);
800
801 /* I can't think of any reason why child processes need any more
802 than the standard 3 file descriptors. It would be cleaner to
803 close just the ones that need to be, but the following brute
804 force approach is certainly effective, and not too slow. */
805 {
806 int fd;
807 for (fd=3; fd<=64; fd++)
808 {
809 close(fd);
810 }
811 }
812 #endif /* not WINDOWSNT */
813
814 #ifdef vipc
815 something missing here;
816 #endif /* vipc */
817
818 #ifdef WINDOWSNT
819 /* Spawn the child. (See ntproc.c:Spawnve). */
820 cpid = spawnve (_P_NOWAIT, new_argv[0], new_argv, env);
821 if (cpid == -1)
822 /* An error occurred while trying to spawn the process. */
823 report_file_error ("Spawning child process", Qnil);
824 reset_standard_handles (in, out, err, handles);
825 return cpid;
826 #else /* not WINDOWSNT */
827 /* execvp does not accept an environment arg so the only way
828 to pass this environment is to set environ. Our caller
829 is responsible for restoring the ambient value of environ. */
830 environ = env;
831 execvp (new_argv[0], new_argv);
832
833 stdout_out ("Cant't exec program %s\n", new_argv[0]);
834 _exit (1);
835 #endif /* not WINDOWSNT */
836 #endif /* not MSDOS */
837 }
838
839 /* Move the file descriptor FD so that its number is not less than MIN.
840 If the file descriptor is moved at all, the original is freed. */
841 static int
842 relocate_fd (int fd, int min)
843 {
844 if (fd >= min)
845 return fd;
846 else
847 {
848 int new = dup (fd);
849 if (new == -1)
850 {
851 stderr_out ("Error while setting up child: %s\n",
852 strerror (errno));
853 _exit (1);
854 }
855 /* Note that we hold the original FD open while we recurse,
856 to guarantee we'll get a new FD if we need it. */
857 new = relocate_fd (new, min);
858 close (fd);
859 return new;
860 }
861 }
862
863 static int
864 getenv_internal (CONST Bufbyte *var,
865 Bytecount varlen,
866 Bufbyte **value,
867 Bytecount *valuelen)
868 {
869 Lisp_Object scan;
870
871 for (scan = Vprocess_environment; CONSP (scan); scan = XCDR (scan))
872 {
873 Lisp_Object entry = XCAR (scan);
874
875 if (STRINGP (entry)
876 && string_length (XSTRING (entry)) > varlen
877 && string_byte (XSTRING (entry), varlen) == '='
878 #ifdef WINDOWSNT
879 /* NT environment variables are case insensitive. */
880 && ! memicmp (string_data (XSTRING (entry)), var, varlen)
881 #else /* not WINDOWSNT */
882 && ! memcmp (string_data (XSTRING (entry)), var, varlen)
883 #endif /* not WINDOWSNT */
884 )
885 {
886 *value = string_data (XSTRING (entry)) + (varlen + 1);
887 *valuelen = string_length (XSTRING (entry)) - (varlen + 1);
888 return 1;
889 }
890 }
891
892 return 0;
893 }
894
895 DEFUN ("getenv", Fgetenv, Sgetenv, 1, 2, "sEnvironment variable: \np" /*
896 Return the value of environment variable VAR, as a string.
897 VAR is a string, the name of the variable.
898 When invoked interactively, prints the value in the echo area.
899 */ )
900 (var, interactivep)
901 Lisp_Object var, interactivep;
902 {
903 Bufbyte *value;
904 Bytecount valuelen;
905 Lisp_Object v = Qnil;
906 struct gcpro gcpro1;
907
908 CHECK_STRING (var);
909 GCPRO1 (v);
910 if (getenv_internal (string_data (XSTRING (var)),
911 string_length (XSTRING (var)),
912 &value, &valuelen))
913 v = make_string (value, valuelen);
914 if (!NILP (interactivep))
915 {
916 if (NILP (v))
917 message ("%s not defined in environment",
918 string_data (XSTRING (var)));
919 else
920 message ("\"%s\"", value);
921 }
922 RETURN_UNGCPRO (v);
923 }
924
925 /* A version of getenv that consults process_environment, easily
926 callable from C. */
927 char *
928 egetenv (CONST char *var)
929 {
930 Bufbyte *value;
931 Bytecount valuelen;
932
933 if (getenv_internal ((CONST Bufbyte *) var, strlen (var), &value, &valuelen))
934 return (char *) value;
935 else
936 return 0;
937 }
938 #endif /* not VMS */
939
940
941 void
942 init_callproc (void)
943 {
944 /* This function can GC */
945 REGISTER char *sh;
946 Lisp_Object tempdir;
947
948 Vprocess_environment = Qnil;
949 /* jwz: always initialize Vprocess_environment, so that egetenv() works
950 in temacs. */
951 {
952 char **envp;
953 for (envp = environ; envp && *envp; envp++)
954 Vprocess_environment = Fcons (build_ext_string (*envp, FORMAT_OS),
955 Vprocess_environment);
956 }
957
958 /* jwz: don't do these things when in temacs (this used to be the case by
959 virtue of egetenv() always returning 0, but that has been changed).
960 */
961 #ifndef CANNOT_DUMP
962 if (!initialized)
963 {
964 Vdata_directory = Qnil;
965 Vdoc_directory = Qnil;
966 Vexec_path = Qnil;
967 }
968 else
969 #endif
970 {
971 char *data_dir = egetenv ("EMACSDATA");
972 char *doc_dir = egetenv ("EMACSDOC");
973
974 #ifdef PATH_DATA
975 if (!data_dir)
976 data_dir = (char *) PATH_DATA;
977 #endif
978 #ifdef PATH_DOC
979 if (!doc_dir)
980 doc_dir = (char *) PATH_DOC;
981 #endif
982
983 if (data_dir)
984 Vdata_directory = Ffile_name_as_directory
985 (build_string (data_dir));
986 else
987 Vdata_directory = Qnil;
988 if (doc_dir)
989 Vdoc_directory = Ffile_name_as_directory
990 (build_string (doc_dir));
991 else
992 Vdoc_directory = Qnil;
993
994 /* Check the EMACSPATH environment variable, defaulting to the
995 PATH_EXEC path from paths.h. */
996 Vexec_path = decode_env_path ("EMACSPATH",
997 #ifdef PATH_EXEC
998 PATH_EXEC
999 #else
1000 0
1001 #endif
1002 );
1003 }
1004
1005 if (NILP (Vexec_path))
1006 Vexec_directory = Qnil;
1007 else
1008 Vexec_directory = Ffile_name_as_directory
1009 (Fcar (Vexec_path));
1010
1011 if (initialized)
1012 Vexec_path = nconc2 (decode_env_path ("PATH", 0),
1013 Vexec_path);
1014
1015 if (!NILP (Vexec_directory))
1016 {
1017 tempdir = Fdirectory_file_name (Vexec_directory);
1018 if (access ((char *) string_data (XSTRING (tempdir)), 0) < 0)
1019 {
1020 /* If the hard-coded path is bogus, fail silently.
1021 This will allow the normal heuristics to make an attempt. */
1022 #if 0
1023 warn_when_safe
1024 (Qpath, Qwarning,
1025 "Warning: machine-dependent data dir (%s) does not exist.\n",
1026 string_data (XSTRING (Vexec_directory)));
1027 #else
1028 Vexec_directory = Qnil;
1029 #endif
1030 }
1031 }
1032
1033 if (!NILP (Vdata_directory))
1034 {
1035 tempdir = Fdirectory_file_name (Vdata_directory);
1036 if (access ((char *) string_data (XSTRING (tempdir)), 0) < 0)
1037 {
1038 /* If the hard-coded path is bogus, fail silently.
1039 This will allow the normal heuristics to make an attempt. */
1040 #if 0
1041 warn_when_safe
1042 (Qpath, Qwarning,
1043 "Warning: machine-independent data dir (%s) does not exist.\n",
1044 string_data (XSTRING (Vdata_directory)));
1045 #else
1046 Vdata_directory = Qnil;
1047 #endif
1048 }
1049 }
1050
1051 #ifdef PATH_PREFIX
1052 Vprefix_directory = build_string ((char *) PATH_PREFIX);
1053 #else
1054 Vprefix_directory = Qnil;
1055 #endif
1056
1057 #ifdef VMS
1058 Vshell_file_name = build_string ("*dcl*");
1059 #else /* not VMS */
1060 sh = (char *) egetenv ("SHELL");
1061 #ifdef DOS_NT
1062 if (!sh) sh = egetenv ("COMSPEC");
1063 {
1064 char *tem;
1065 if (sh)
1066 {
1067 tem = (char *) alloca (strlen (sh) + 1);
1068 sh = dostounix_filename (strcpy (tem, sh));
1069 }
1070 }
1071 Vshell_file_name = build_string (sh ? sh : "/command.com");
1072 #else /* not DOS_NT */
1073 Vshell_file_name = build_string (sh ? sh : "/bin/sh");
1074 #endif /* not DOS_NT */
1075 #endif /* not VMS */
1076 }
1077
1078 #if 0
1079 void
1080 set_process_environment (void)
1081 {
1082 REGISTER char **envp;
1083
1084 Vprocess_environment = Qnil;
1085 #ifndef CANNOT_DUMP
1086 if (initialized)
1087 #endif
1088 for (envp = environ; *envp; envp++)
1089 Vprocess_environment = Fcons (build_string (*envp),
1090 Vprocess_environment);
1091 }
1092 #endif /* unused */
1093
1094 void
1095 syms_of_callproc (void)
1096 {
1097 #ifndef VMS
1098 defsubr (&Scall_process_internal);
1099 defsubr (&Sgetenv);
1100 #endif
1101 }
1102
1103 void
1104 vars_of_callproc (void)
1105 {
1106 /* This function can GC */
1107 #ifdef DOS_NT
1108 DEFVAR_LISP ("binary-process-input", &Vbinary_process_input /*
1109 *If non-nil then new subprocesses are assumed to take binary input.
1110 */ );
1111 Vbinary_process_input = Qnil;
1112
1113 DEFVAR_LISP ("binary-process-output", &Vbinary_process_output /*
1114 *If non-nil then new subprocesses are assumed to produce binary output.
1115 */ );
1116 Vbinary_process_output = Qnil;
1117 #endif /* DOS_NT */
1118
1119 DEFVAR_LISP ("shell-file-name", &Vshell_file_name /*
1120 *File name to load inferior shells from.
1121 Initialized from the SHELL environment variable.
1122 */ );
1123
1124 DEFVAR_LISP ("exec-path", &Vexec_path /*
1125 *List of directories to search programs to run in subprocesses.
1126 Each element is a string (directory name) or nil (try default directory).
1127 */ );
1128
1129 DEFVAR_LISP ("exec-directory", &Vexec_directory /*
1130 Directory of architecture-dependent files that come with XEmacs,
1131 especially executable programs intended for Emacs to invoke.
1132 */ );
1133
1134 DEFVAR_LISP ("data-directory", &Vdata_directory /*
1135 Directory of architecture-independent files that come with XEmacs,
1136 intended for Emacs to use.
1137 */ );
1138
1139 /* FSF puts the DOC file into data-directory. They do a bunch of
1140 contortions to attempt to put everything into the DOC file
1141 whether the support is there or not. */
1142 DEFVAR_LISP ("doc-directory", &Vdoc_directory /*
1143 Directory containing the DOC file that comes with XEmacs.
1144 This is usually the same as exec-directory.
1145 */ );
1146
1147 DEFVAR_LISP ("prefix-directory", &Vprefix_directory /*
1148 The default directory under which XEmacs is installed.
1149 */ );
1150
1151 DEFVAR_LISP ("process-environment", &Vprocess_environment /*
1152 List of environment variables for subprocesses to inherit.
1153 Each element should be a string of the form ENVVARNAME=VALUE.
1154 The environment which Emacs inherits is placed in this variable
1155 when Emacs starts.
1156 */ );
1157 }
1158
1159 void
1160 complex_vars_of_callproc (void)
1161 {
1162 DEFVAR_LISP ("configure-info-directory", &Vconfigure_info_directory /*
1163 For internal use by the build procedure only.
1164 This is the name of the directory in which the build procedure installed
1165 Emacs's info files; the default value for Info-default-directory-list
1166 includes this.
1167 */ );
1168 #ifdef PATH_INFO
1169 Vconfigure_info_directory =
1170 Ffile_name_as_directory (build_string (PATH_INFO));
1171 #else
1172 Vconfigure_info_directory = Qnil;
1173 #endif
1174 }