aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Blandy1992-08-07 12:28:53 +0000
committerJim Blandy1992-08-07 12:28:53 +0000
commite576cab4e28a61d225d5b93af33eb4c1b7068c76 (patch)
treee67e5f3b202c33b4a4931ccc93398145d80aa8a7
parent7e9b0c9610dfefa0e9294ca3703fe3a236f38e03 (diff)
downloademacs-e576cab4e28a61d225d5b93af33eb4c1b7068c76.tar.gz
emacs-e576cab4e28a61d225d5b93af33eb4c1b7068c76.zip
Restored up-to-date version of this file from pogo. What is going on
here?
-rw-r--r--src/callproc.c216
1 files changed, 120 insertions, 96 deletions
diff --git a/src/callproc.c b/src/callproc.c
index 85e86c50da9..d3fc963313d 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -1,5 +1,5 @@
1/* Synchronous subprocess invocation for GNU Emacs. 1/* Synchronous subprocess invocation for GNU Emacs.
2 Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc. 2 Copyright (C) 1985, 1986, 1987, 1988, 1992 Free Software Foundation, Inc.
3 3
4This file is part of GNU Emacs. 4This file is part of GNU Emacs.
5 5
@@ -19,6 +19,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19 19
20 20
21#include <signal.h> 21#include <signal.h>
22#include <errno.h>
22 23
23#include "config.h" 24#include "config.h"
24 25
@@ -57,16 +58,11 @@ extern char **environ;
57 58
58#define max(a, b) ((a) > (b) ? (a) : (b)) 59#define max(a, b) ((a) > (b) ? (a) : (b))
59 60
60Lisp_Object Vexec_path, Vexec_directory; 61Lisp_Object Vexec_path, Vexec_directory, Vdata_directory;
61 62
62Lisp_Object Vshell_file_name; 63Lisp_Object Vshell_file_name;
63 64
64#ifndef MAINTAIN_ENVIRONMENT
65/* List of strings to append to front of environment of
66 all subprocesses when they are started. */
67
68Lisp_Object Vprocess_environment; 65Lisp_Object Vprocess_environment;
69#endif
70 66
71/* True iff we are about to fork off a synchronous process or if we 67/* True iff we are about to fork off a synchronous process or if we
72 are waiting for it. */ 68 are waiting for it. */
@@ -101,15 +97,15 @@ Insert output in BUFFER before point; t means current buffer;\n\
101 nil for BUFFER means discard it; 0 means discard and don't wait.\n\ 97 nil for BUFFER means discard it; 0 means discard and don't wait.\n\
102Fourth arg DISPLAY non-nil means redisplay buffer as output is inserted.\n\ 98Fourth arg DISPLAY non-nil means redisplay buffer as output is inserted.\n\
103Remaining arguments are strings passed as command arguments to PROGRAM.\n\ 99Remaining arguments are strings passed as command arguments to PROGRAM.\n\
104If BUFFER is nil or 0, returns immediately with value nil.\n\ 100If BUFFER is 0, returns immediately with value nil.\n\
105Otherwise waits for PROGRAM to terminate\n\ 101Otherwise waits for PROGRAM to terminate\n\
106and returns a numeric exit status or a signal name as a string.\n\ 102and returns a numeric exit status or a signal description string.\n\
107If you quit, the process is killed with SIGKILL.") 103If you quit, the process is killed with SIGKILL.")
108 (nargs, args) 104 (nargs, args)
109 int nargs; 105 int nargs;
110 register Lisp_Object *args; 106 register Lisp_Object *args;
111{ 107{
112 Lisp_Object display, buffer, path; 108 Lisp_Object display, infile, buffer, path, current_dir;
113 int fd[2]; 109 int fd[2];
114 int filefd; 110 int filefd;
115 register int pid; 111 register int pid;
@@ -121,34 +117,37 @@ If you quit, the process is killed with SIGKILL.")
121#if 0 117#if 0
122 int mask; 118 int mask;
123#endif 119#endif
124 struct gcpro gcpro1;
125
126 GCPRO1 (*args);
127 gcpro1.nvars = nargs;
128
129 CHECK_STRING (args[0], 0); 120 CHECK_STRING (args[0], 0);
130 121
131 if (nargs <= 1 || NILP (args[1])) 122 if (nargs >= 2 && ! NILP (args[1]))
132 args[1] = build_string ("/dev/null"); 123 {
124 infile = Fexpand_file_name (args[1], current_buffer->directory);
125 CHECK_STRING (infile, 1);
126 }
133 else 127 else
134 args[1] = Fexpand_file_name (args[1], current_buffer->directory); 128#ifdef VMS
129 infile = build_string ("NLA0:");
130#else
131 infile = build_string ("/dev/null");
132#endif /* not VMS */
135 133
136 CHECK_STRING (args[1], 1); 134 if (nargs >= 3)
135 {
136 register Lisp_Object tem;
137 137
138 { 138 buffer = tem = args[2];
139 register Lisp_Object tem; 139 if (!(EQ (tem, Qnil)
140 buffer = tem = args[2]; 140 || EQ (tem, Qt)
141 if (nargs <= 2) 141 || XFASTINT (tem) == 0))
142 buffer = Qnil; 142 {
143 else if (!(EQ (tem, Qnil) || EQ (tem, Qt) 143 buffer = Fget_buffer (tem);
144 || XFASTINT (tem) == 0)) 144 CHECK_BUFFER (buffer, 2);
145 { 145 }
146 buffer = Fget_buffer (tem); 146 }
147 CHECK_BUFFER (buffer, 2); 147 else
148 } 148 buffer = Qnil;
149 }
150 149
151 display = nargs >= 3 ? args[3] : Qnil; 150 display = nargs >= 4 ? args[3] : Qnil;
152 151
153 { 152 {
154 register int i; 153 register int i;
@@ -162,10 +161,10 @@ If you quit, the process is killed with SIGKILL.")
162 new_argv[i - 3] = 0; 161 new_argv[i - 3] = 0;
163 } 162 }
164 163
165 filefd = open (XSTRING (args[1])->data, O_RDONLY, 0); 164 filefd = open (XSTRING (infile)->data, O_RDONLY, 0);
166 if (filefd < 0) 165 if (filefd < 0)
167 { 166 {
168 report_file_error ("Opening process input file", Fcons (args[1], Qnil)); 167 report_file_error ("Opening process input file", Fcons (infile, Qnil));
169 } 168 }
170 /* Search for program; barf if not found. */ 169 /* Search for program; barf if not found. */
171 openp (Vexec_path, args[0], "", &path, 1); 170 openp (Vexec_path, args[0], "", &path, 1);
@@ -187,19 +186,19 @@ If you quit, the process is killed with SIGKILL.")
187#endif 186#endif
188 } 187 }
189 188
189 /* Make sure that the child will be able to chdir to the current
190 buffer's current directory. We can't just have the child check
191 for an error when it does the chdir, since it's in a vfork. */
192 current_dir = expand_and_dir_to_file (current_buffer->directory, Qnil);
193 if (NILP (Ffile_accessible_directory_p (current_dir)))
194 report_file_error ("Setting current directory",
195 Fcons (current_buffer->directory, Qnil));
196
190 { 197 {
191 /* child_setup must clobber environ in systems with true vfork. 198 /* child_setup must clobber environ in systems with true vfork.
192 Protect it from permanent change. */ 199 Protect it from permanent change. */
193 register char **save_environ = environ; 200 register char **save_environ = environ;
194 register int fd1 = fd[1]; 201 register int fd1 = fd[1];
195 char **env;
196
197#ifdef MAINTAIN_ENVIRONMENT
198 env = (char **) alloca (size_of_current_environ ());
199 get_current_environ (env);
200#else
201 env = environ;
202#endif /* MAINTAIN_ENVIRONMENT */
203 202
204#if 0 /* Some systems don't have sigblock. */ 203#if 0 /* Some systems don't have sigblock. */
205 mask = sigblock (sigmask (SIGCHLD)); 204 mask = sigblock (sigmask (SIGCHLD));
@@ -219,7 +218,7 @@ If you quit, the process is killed with SIGKILL.")
219#else 218#else
220 setpgrp (pid, pid); 219 setpgrp (pid, pid);
221#endif /* USG */ 220#endif /* USG */
222 child_setup (filefd, fd1, fd1, new_argv, env, 0); 221 child_setup (filefd, fd1, fd1, new_argv, 0, current_dir);
223 } 222 }
224 223
225#if 0 224#if 0
@@ -244,13 +243,17 @@ If you quit, the process is killed with SIGKILL.")
244 if (XTYPE (buffer) == Lisp_Int) 243 if (XTYPE (buffer) == Lisp_Int)
245 { 244 {
246#ifndef subprocesses 245#ifndef subprocesses
246 /* If Emacs has been built with asynchronous subprocess support,
247 we don't need to do this, I think because it will then have
248 the facilities for handling SIGCHLD. */
247 wait_without_blocking (); 249 wait_without_blocking ();
248#endif /* subprocesses */ 250#endif /* subprocesses */
249
250 UNGCPRO;
251 return Qnil; 251 return Qnil;
252 } 252 }
253 253
254 synch_process_death = 0;
255 synch_process_retcode = 0;
256
254 record_unwind_protect (call_process_cleanup, 257 record_unwind_protect (call_process_cleanup,
255 Fcons (make_number (fd[0]), make_number (pid))); 258 Fcons (make_number (fd[0]), make_number (pid)));
256 259
@@ -285,8 +288,6 @@ If you quit, the process is killed with SIGKILL.")
285 288
286 unbind_to (count, Qnil); 289 unbind_to (count, Qnil);
287 290
288 UNGCPRO;
289
290 if (synch_process_death) 291 if (synch_process_death)
291 return build_string (synch_process_death); 292 return build_string (synch_process_death);
292 return make_number (synch_process_retcode); 293 return make_number (synch_process_retcode);
@@ -310,7 +311,7 @@ Sixth arg DISPLAY non-nil means redisplay buffer as output is inserted.\n\
310Remaining args are passed to PROGRAM at startup as command args.\n\ 311Remaining args are passed to PROGRAM at startup as command args.\n\
311If BUFFER is nil, returns immediately with value nil.\n\ 312If BUFFER is nil, returns immediately with value nil.\n\
312Otherwise waits for PROGRAM to terminate\n\ 313Otherwise waits for PROGRAM to terminate\n\
313and returns a numeric exit status or a signal name as a string.\n\ 314and returns a numeric exit status or a signal description string.\n\
314If you quit, the process is killed with SIGKILL.") 315If you quit, the process is killed with SIGKILL.")
315 (nargs, args) 316 (nargs, args)
316 int nargs; 317 int nargs;
@@ -319,10 +320,6 @@ If you quit, the process is killed with SIGKILL.")
319 register Lisp_Object filename_string, start, end; 320 register Lisp_Object filename_string, start, end;
320 char tempfile[20]; 321 char tempfile[20];
321 int count = specpdl_ptr - specpdl; 322 int count = specpdl_ptr - specpdl;
322 struct gcpro gcpro1;
323
324 GCPRO1 (*args);
325 gcpro1.nvars = 2;
326 323
327#ifdef VMS 324#ifdef VMS
328 strcpy (tempfile, "tmp:emacsXXXXXX."); 325 strcpy (tempfile, "tmp:emacsXXXXXX.");
@@ -343,7 +340,6 @@ If you quit, the process is killed with SIGKILL.")
343 args[3] = filename_string; 340 args[3] = filename_string;
344 Fcall_process (nargs - 2, args + 2); 341 Fcall_process (nargs - 2, args + 2);
345 342
346 UNGCPRO;
347 return unbind_to (count, Qnil); 343 return unbind_to (count, Qnil);
348} 344}
349 345
@@ -362,14 +358,21 @@ If you quit, the process is killed with SIGKILL.")
362 ENV is the environment for the subprocess. 358 ENV is the environment for the subprocess.
363 359
364 SET_PGRP is nonzero if we should put the subprocess into a separate 360 SET_PGRP is nonzero if we should put the subprocess into a separate
365 process group. */ 361 process group.
362
363 CURRENT_DIR is an elisp string giving the path of the current
364 directory the subprocess should have. Since we can't really signal
365 a decent error from within the child, this should be verified as an
366 executable directory by the parent. */
366 367
367child_setup (in, out, err, new_argv, env, set_pgrp) 368child_setup (in, out, err, new_argv, set_pgrp, current_dir)
368 int in, out, err; 369 int in, out, err;
369 register char **new_argv; 370 register char **new_argv;
370 char **env;
371 int set_pgrp; 371 int set_pgrp;
372 Lisp_Object current_dir;
372{ 373{
374 char **env;
375
373 register int pid = getpid(); 376 register int pid = getpid();
374 377
375 setpriority (PRIO_PROCESS, pid, 0); 378 setpriority (PRIO_PROCESS, pid, 0);
@@ -384,24 +387,25 @@ child_setup (in, out, err, new_argv, env, set_pgrp)
384 If using vfork and C_ALLOCA it is safe because that changes 387 If using vfork and C_ALLOCA it is safe because that changes
385 the superior's static variables as if the superior had done alloca 388 the superior's static variables as if the superior had done alloca
386 and will be cleaned up in the usual way. */ 389 and will be cleaned up in the usual way. */
390 {
391 register unsigned char *temp;
392 register int i;
387 393
388 if (XTYPE (current_buffer->directory) == Lisp_String) 394 i = XSTRING (current_dir)->size;
389 { 395 temp = (unsigned char *) alloca (i + 2);
390 register unsigned char *temp; 396 bcopy (XSTRING (current_dir)->data, temp, i);
391 register int i; 397 if (temp[i - 1] != '/') temp[i++] = '/';
392 398 temp[i] = 0;
393 i = XSTRING (current_buffer->directory)->size; 399
394 temp = (unsigned char *) alloca (i + 2); 400 /* We can't signal an Elisp error here; we're in a vfork. Since
395 bcopy (XSTRING (current_buffer->directory)->data, temp, i); 401 the callers check the current directory before forking, this
396 if (temp[i - 1] != '/') temp[i++] = '/'; 402 should only return an error if the directory's permissions
397 temp[i] = 0; 403 are changed between the check and this chdir, but we should
398 /* Switch to that directory, and report any error. */ 404 at least check. */
399 if (chdir (temp) < 0) 405 if (chdir (temp) < 0)
400 report_file_error ("In chdir", 406 exit (errno);
401 Fcons (current_buffer->directory, Qnil)); 407 }
402 }
403 408
404#ifndef MAINTAIN_ENVIRONMENT
405 /* Set `env' to a vector of the strings in Vprocess_environment. */ 409 /* Set `env' to a vector of the strings in Vprocess_environment. */
406 { 410 {
407 register Lisp_Object tem; 411 register Lisp_Object tem;
@@ -418,7 +422,7 @@ child_setup (in, out, err, new_argv, env, set_pgrp)
418 /* new_length + 1 to include terminating 0 */ 422 /* new_length + 1 to include terminating 0 */
419 env = new_env = (char **) alloca ((new_length + 1) * sizeof (char *)); 423 env = new_env = (char **) alloca ((new_length + 1) * sizeof (char *));
420 424
421 /* Copy the env strings into new_env. */ 425 /* Copy the Vprocess_alist strings into new_env. */
422 for (tem = Vprocess_environment; 426 for (tem = Vprocess_environment;
423 (XTYPE (tem) == Lisp_Cons 427 (XTYPE (tem) == Lisp_Cons
424 && XTYPE (XCONS (tem)->car) == Lisp_String); 428 && XTYPE (XCONS (tem)->car) == Lisp_String);
@@ -426,7 +430,6 @@ child_setup (in, out, err, new_argv, env, set_pgrp)
426 *new_env++ = (char *) XSTRING (XCONS (tem)->car)->data; 430 *new_env++ = (char *) XSTRING (XCONS (tem)->car)->data;
427 *new_env = 0; 431 *new_env = 0;
428 } 432 }
429#endif /* Not MAINTAIN_ENVIRONMENT */
430 433
431 close (0); 434 close (0);
432 close (1); 435 close (1);
@@ -439,6 +442,11 @@ child_setup (in, out, err, new_argv, env, set_pgrp)
439 close (out); 442 close (out);
440 close (err); 443 close (err);
441 444
445#ifdef USG
446 setpgrp (); /* No arguments but equivalent in this case */
447#else
448 setpgrp (pid, pid);
449#endif /* USG */
442 setpgrp_of_tty (pid); 450 setpgrp_of_tty (pid);
443 451
444#ifdef vipc 452#ifdef vipc
@@ -468,7 +476,7 @@ getenv_internal (var, varlen, value, valuelen)
468 for (scan = Vprocess_environment; CONSP (scan); scan = XCONS (scan)->cdr) 476 for (scan = Vprocess_environment; CONSP (scan); scan = XCONS (scan)->cdr)
469 { 477 {
470 Lisp_Object entry = XCONS (scan)->car; 478 Lisp_Object entry = XCONS (scan)->car;
471 479
472 if (XTYPE (entry) == Lisp_String 480 if (XTYPE (entry) == Lisp_String
473 && XSTRING (entry)->size > varlen 481 && XSTRING (entry)->size > varlen
474 && XSTRING (entry)->data[varlen] == '=' 482 && XSTRING (entry)->data[varlen] == '='
@@ -502,10 +510,10 @@ This function consults the variable ``process-environment'' for its value.")
502} 510}
503 511
504/* A version of getenv that consults process_environment, easily 512/* A version of getenv that consults process_environment, easily
505 callable from C. */ 513 callable from C. */
506char * 514char *
507egetenv (var) 515egetenv (var)
508 char *var; 516 char *var;
509{ 517{
510 char *value; 518 char *value;
511 int valuelen; 519 int valuelen;
@@ -522,32 +530,45 @@ init_callproc ()
522{ 530{
523 register char * sh; 531 register char * sh;
524 register char **envp; 532 register char **envp;
525 Lisp_Object execdir; 533 Lisp_Object tempdir;
534
535 {
536 char *data_dir = egetenv ("EMACSDATA");
537
538 Vdata_directory =
539 Ffile_name_as_directory
540 (build_string (data_dir ? data_dir : PATH_DATA));
541 }
526 542
527 /* Turn PATH_EXEC into a path. `==' is just a string which we know 543 /* Check the EMACSPATH environment variable, defaulting to the
528 will not be the name of an environment variable. */ 544 PATH_EXEC path from paths.h. */
529 Vexec_path = decode_env_path ("==", PATH_EXEC); 545 Vexec_path = decode_env_path ("EMACSPATH", PATH_EXEC);
530 Vexec_directory = Ffile_name_as_directory (Fcar (Vexec_path)); 546 Vexec_directory = Ffile_name_as_directory (Fcar (Vexec_path));
531 Vexec_path = nconc2 (decode_env_path ("PATH", ""), Vexec_path); 547 Vexec_path = nconc2 (decode_env_path ("PATH", ""), Vexec_path);
532 548
533 execdir = Fdirectory_file_name (Vexec_directory); 549 tempdir = Fdirectory_file_name (Vexec_directory);
534 if (access (XSTRING (execdir)->data, 0) < 0) 550 if (access (XSTRING (tempdir)->data, 0) < 0)
535 { 551 {
536 printf ("Warning: executable/documentation dir (%s) does not exist.\n", 552 printf ("Warning: arch-dependent data dir (%s) does not exist.\n",
537 XSTRING (Vexec_directory)->data); 553 XSTRING (Vexec_directory)->data);
538 sleep (2); 554 sleep (2);
539 } 555 }
540 556
557 tempdir = Fdirectory_file_name (Vdata_directory);
558 if (access (XSTRING (tempdir)->data, 0) < 0)
559 {
560 printf ("Warning: arch-independent data dir (%s) does not exist.\n",
561 XSTRING (Vdata_directory)->data);
562 sleep (2);
563 }
564
541#ifdef VMS 565#ifdef VMS
542 Vshell_file_name = build_string ("*dcl*"); 566 Vshell_file_name = build_string ("*dcl*");
543#else 567#else
544 sh = (char *) egetenv ("SHELL"); 568 sh = (char *) getenv ("SHELL");
545 Vshell_file_name = build_string (sh ? sh : "/bin/sh"); 569 Vshell_file_name = build_string (sh ? sh : "/bin/sh");
546#endif 570#endif
547 571
548#ifndef MAINTAIN_ENVIRONMENT
549 /* The equivalent of this operation was done
550 in init_environ in environ.c if MAINTAIN_ENVIRONMENT */
551 Vprocess_environment = Qnil; 572 Vprocess_environment = Qnil;
552#ifndef CANNOT_DUMP 573#ifndef CANNOT_DUMP
553 if (initialized) 574 if (initialized)
@@ -555,7 +576,6 @@ init_callproc ()
555 for (envp = environ; *envp; envp++) 576 for (envp = environ; *envp; envp++)
556 Vprocess_environment = Fcons (build_string (*envp), 577 Vprocess_environment = Fcons (build_string (*envp),
557 Vprocess_environment); 578 Vprocess_environment);
558#endif /* MAINTAIN_ENVIRONMENT */
559} 579}
560 580
561syms_of_callproc () 581syms_of_callproc ()
@@ -569,18 +589,22 @@ Initialized from the SHELL environment variable.");
569Each element is a string (directory name) or nil (try default directory)."); 589Each element is a string (directory name) or nil (try default directory).");
570 590
571 DEFVAR_LISP ("exec-directory", &Vexec_directory, 591 DEFVAR_LISP ("exec-directory", &Vexec_directory,
572 "Directory that holds programs that come with GNU Emacs,\n\ 592 "Directory of architecture-dependent files that come with GNU Emacs,\n\
573intended for Emacs to invoke."); 593especially executable programs intended for Emacs to invoke.");
594
595 DEFVAR_LISP ("data-directory", &Vdata_directory,
596 "Directory of architecture-independent files that come with GNU Emacs,\n\
597intended for Emacs to use.");
574 598
575#ifndef MAINTAIN_ENVIRONMENT
576 DEFVAR_LISP ("process-environment", &Vprocess_environment, 599 DEFVAR_LISP ("process-environment", &Vprocess_environment,
577 "List of strings to append to environment of subprocesses that are started.\n\ 600 "List of environment variables for subprocesses to inherit.\n\
578Each string should have the format ENVVARNAME=VALUE."); 601Each element should be a string of the form ENVVARNAME=VALUE.\n\
579#endif 602The environment which Emacs inherits is placed in this variable\n\
603when Emacs starts.");
580 604
581#ifndef VMS 605#ifndef VMS
582 defsubr (&Scall_process); 606 defsubr (&Scall_process);
583#endif 607#endif
584 defsubr (&Scall_process_region);
585 defsubr (&Sgetenv); 608 defsubr (&Sgetenv);
609 defsubr (&Scall_process_region);
586} 610}