1 /* Synchronous subprocess invocation for GNU Emacs.
2 Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
25 /* Define SIGCHLD as an alias for SIGCLD. */
27 #if !defined (SIGCHLD) && defined (SIGCLD)
28 #define SIGCHLD SIGCLD
31 #include <sys/types.h>
32 #define PRIO_PROCESS 0
53 extern noshare
char **environ
;
55 extern char **environ
;
58 #define max(a, b) ((a) > (b) ? (a) : (b))
60 Lisp_Object Vexec_path
, Vexec_directory
, Vdata_directory
;
62 Lisp_Object Vshell_file_name
;
64 Lisp_Object Vprocess_environment
;
66 /* True iff we are about to fork off a synchronous process or if we
67 are waiting for it. */
68 int synch_process_alive
;
70 /* Nonzero => this is a string explaining death of synchronous subprocess. */
71 char *synch_process_death
;
73 /* If synch_process_death is zero,
74 this is exit code of synchronous subprocess. */
75 int synch_process_retcode
;
77 #ifndef VMS /* VMS version is in vmsproc.c. */
80 call_process_cleanup (fdpid
)
83 register Lisp_Object fd
, pid
;
86 close (XFASTINT (fd
));
87 kill (XFASTINT (pid
), SIGKILL
);
88 synch_process_alive
= 0;
92 DEFUN ("call-process", Fcall_process
, Scall_process
, 1, MANY
, 0,
93 "Call PROGRAM synchronously in separate process.\n\
94 The program's input comes from file INFILE (nil means `/dev/null').\n\
95 Insert output in BUFFER before point; t means current buffer;\n\
96 nil for BUFFER means discard it; 0 means discard and don't wait.\n\
97 Fourth arg DISPLAY non-nil means redisplay buffer as output is inserted.\n\
98 Remaining arguments are strings passed as command arguments to PROGRAM.\n\
99 If BUFFER is nil or 0, returns immediately with value nil.\n\
100 Otherwise waits for PROGRAM to terminate\n\
101 and returns a numeric exit status or a signal name as a string.\n\
102 If you quit, the process is killed with SIGKILL.")
105 register Lisp_Object
*args
;
107 Lisp_Object display
, buffer
, path
;
112 int count
= specpdl_ptr
- specpdl
;
113 register unsigned char **new_argv
114 = (unsigned char **) alloca ((max (2, nargs
- 2)) * sizeof (char *));
115 struct buffer
*old
= current_buffer
;
119 CHECK_STRING (args
[0], 0);
121 if (nargs
<= 1 || NILP (args
[1]))
122 args
[1] = build_string ("/dev/null");
124 args
[1] = Fexpand_file_name (args
[1], current_buffer
->directory
);
126 CHECK_STRING (args
[1], 1);
129 register Lisp_Object tem
;
130 buffer
= tem
= args
[2];
133 else if (!(EQ (tem
, Qnil
) || EQ (tem
, Qt
)
134 || XFASTINT (tem
) == 0))
136 buffer
= Fget_buffer (tem
);
137 CHECK_BUFFER (buffer
, 2);
141 display
= nargs
>= 3 ? args
[3] : Qnil
;
145 for (i
= 4; i
< nargs
; i
++)
147 CHECK_STRING (args
[i
], i
);
148 new_argv
[i
- 3] = XSTRING (args
[i
])->data
;
150 /* Program name is first command arg */
151 new_argv
[0] = XSTRING (args
[0])->data
;
155 filefd
= open (XSTRING (args
[1])->data
, O_RDONLY
, 0);
158 report_file_error ("Opening process input file", Fcons (args
[1], Qnil
));
160 /* Search for program; barf if not found. */
161 openp (Vexec_path
, args
[0], "", &path
, 1);
165 report_file_error ("Searching for program", Fcons (args
[0], Qnil
));
167 new_argv
[0] = XSTRING (path
)->data
;
169 if (XTYPE (buffer
) == Lisp_Int
)
170 fd
[1] = open ("/dev/null", O_WRONLY
), fd
[0] = -1;
175 /* Replaced by close_process_descs */
176 set_exclusive_use (fd
[0]);
181 /* child_setup must clobber environ in systems with true vfork.
182 Protect it from permanent change. */
183 register char **save_environ
= environ
;
184 register int fd1
= fd
[1];
189 #if 0 /* Some systems don't have sigblock. */
190 mask
= sigblock (sigmask (SIGCHLD
));
193 /* Record that we're about to create a synchronous process. */
194 synch_process_alive
= 1;
207 child_setup (filefd
, fd1
, fd1
, new_argv
, env
, 0);
211 /* Tell SIGCHLD handler to look for this pid. */
212 synch_process_pid
= pid
;
213 /* Now let SIGCHLD come through. */
217 environ
= save_environ
;
226 report_file_error ("Doing vfork", Qnil
);
229 if (XTYPE (buffer
) == Lisp_Int
)
232 wait_without_blocking ();
233 #endif /* subprocesses */
237 record_unwind_protect (call_process_cleanup
,
238 Fcons (make_number (fd
[0]), make_number (pid
)));
241 if (XTYPE (buffer
) == Lisp_Buffer
)
242 Fset_buffer (buffer
);
250 while ((nread
= read (fd
[0], buf
, sizeof buf
)) > 0)
255 if (!NILP (display
) && INTERACTIVE
)
256 redisplay_preserve_echo_area ();
262 /* Wait for it to terminate, unless it already has. */
263 wait_for_termination (pid
);
267 set_buffer_internal (old
);
269 unbind_to (count
, Qnil
);
271 if (synch_process_death
)
272 return build_string (synch_process_death
);
273 return make_number (synch_process_retcode
);
278 delete_temp_file (name
)
281 unlink (XSTRING (name
)->data
);
284 DEFUN ("call-process-region", Fcall_process_region
, Scall_process_region
,
286 "Send text from START to END to a synchronous process running PROGRAM.\n\
287 Delete the text if fourth arg DELETE is non-nil.\n\
288 Insert output in BUFFER before point; t means current buffer;\n\
289 nil for BUFFER means discard it; 0 means discard and don't wait.\n\
290 Sixth arg DISPLAY non-nil means redisplay buffer as output is inserted.\n\
291 Remaining args are passed to PROGRAM at startup as command args.\n\
292 If BUFFER is nil, returns immediately with value nil.\n\
293 Otherwise waits for PROGRAM to terminate\n\
294 and returns a numeric exit status or a signal name as a string.\n\
295 If you quit, the process is killed with SIGKILL.")
298 register Lisp_Object
*args
;
300 register Lisp_Object filename_string
, start
, end
;
302 int count
= specpdl_ptr
- specpdl
;
305 strcpy (tempfile
, "tmp:emacsXXXXXX.");
307 strcpy (tempfile
, "/tmp/emacsXXXXXX");
311 filename_string
= build_string (tempfile
);
314 Fwrite_region (start
, end
, filename_string
, Qnil
, Qlambda
);
315 record_unwind_protect (delete_temp_file
, filename_string
);
318 Fdelete_region (start
, end
);
320 args
[3] = filename_string
;
321 Fcall_process (nargs
- 2, args
+ 2);
323 return unbind_to (count
, Qnil
);
326 #ifndef VMS /* VMS version is in vmsproc.c. */
328 /* This is the last thing run in a newly forked inferior
329 either synchronous or asynchronous.
330 Copy descriptors IN, OUT and ERR as descriptors 0, 1 and 2.
331 Initialize inferior's priority, pgrp, connected dir and environment.
332 then exec another program based on new_argv.
334 This function may change environ for the superior process.
335 Therefore, the superior process must save and restore the value
336 of environ around the vfork and the call to this function.
338 ENV is the environment for the subprocess.
340 SET_PGRP is nonzero if we should put the subprocess into a separate
343 child_setup (in
, out
, err
, new_argv
, env
, set_pgrp
)
345 register char **new_argv
;
349 register int pid
= getpid();
351 setpriority (PRIO_PROCESS
, pid
, 0);
354 /* Close Emacs's descriptors that this process should not have. */
355 close_process_descs ();
358 /* Note that use of alloca is always safe here. It's obvious for systems
359 that do not have true vfork or that have true (stack) alloca.
360 If using vfork and C_ALLOCA it is safe because that changes
361 the superior's static variables as if the superior had done alloca
362 and will be cleaned up in the usual way. */
364 if (XTYPE (current_buffer
->directory
) == Lisp_String
)
366 register unsigned char *temp
;
369 i
= XSTRING (current_buffer
->directory
)->size
;
370 temp
= (unsigned char *) alloca (i
+ 2);
371 bcopy (XSTRING (current_buffer
->directory
)->data
, temp
, i
);
372 if (temp
[i
- 1] != '/') temp
[i
++] = '/';
374 /* Switch to that directory, and report any error. */
375 if (chdir (temp
) < 0)
376 report_file_error ("In chdir",
377 Fcons (current_buffer
->directory
, Qnil
));
380 /* Set `env' to a vector of the strings in Vprocess_environment. */
382 register Lisp_Object tem
;
383 register char **new_env
;
384 register int new_length
;
387 for (tem
= Vprocess_environment
;
388 (XTYPE (tem
) == Lisp_Cons
389 && XTYPE (XCONS (tem
)->car
) == Lisp_String
);
390 tem
= XCONS (tem
)->cdr
)
393 /* new_length + 1 to include terminating 0 */
394 env
= new_env
= (char **) alloca ((new_length
+ 1) * sizeof (char *));
396 /* Copy the env strings into new_env. */
397 for (tem
= Vprocess_environment
;
398 (XTYPE (tem
) == Lisp_Cons
399 && XTYPE (XCONS (tem
)->car
) == Lisp_String
);
400 tem
= XCONS (tem
)->cdr
)
401 *new_env
++ = (char *) XSTRING (XCONS (tem
)->car
)->data
;
416 setpgrp_of_tty (pid
);
419 something missing here
;
422 /* execvp does not accept an environment arg so the only way
423 to pass this environment is to set environ. Our caller
424 is responsible for restoring the ambient value of environ. */
426 execvp (new_argv
[0], new_argv
);
428 write (1, "Couldn't exec the program ", 26);
429 write (1, new_argv
[0], strlen (new_argv
[0]));
434 getenv_internal (var
, varlen
, value
, valuelen
)
442 for (scan
= Vprocess_environment
; CONSP (scan
); scan
= XCONS (scan
)->cdr
)
444 Lisp_Object entry
= XCONS (scan
)->car
;
446 if (XTYPE (entry
) == Lisp_String
447 && XSTRING (entry
)->size
> varlen
448 && XSTRING (entry
)->data
[varlen
] == '='
449 && ! bcmp (XSTRING (entry
)->data
, var
, varlen
))
451 *value
= XSTRING (entry
)->data
+ (varlen
+ 1);
452 *valuelen
= XSTRING (entry
)->size
- (varlen
+ 1);
460 DEFUN ("getenv", Fgetenv
, Sgetenv
, 1, 2, 0,
461 "Return the value of environment variable VAR, as a string.\n\
462 VAR should be a string. Value is nil if VAR is undefined in the environment.\n\
463 This function consults the variable ``process-environment'' for its value.")
470 CHECK_STRING (var
, 0);
471 if (getenv_internal (XSTRING (var
)->data
, XSTRING (var
)->size
,
473 return make_string (value
, valuelen
);
478 /* A version of getenv that consults process_environment, easily
486 if (getenv_internal (var
, strlen (var
), &value
, &valuelen
))
497 register char **envp
;
500 Vdata_directory
= Ffile_name_as_directory (build_string (PATH_DATA
));
502 /* Turn PATH_EXEC into a path. `==' is just a string which we know
503 will not be the name of an environment variable. */
504 Vexec_path
= decode_env_path ("==", PATH_EXEC
);
505 Vexec_directory
= Ffile_name_as_directory (Fcar (Vexec_path
));
506 Vexec_path
= nconc2 (decode_env_path ("PATH", ""), Vexec_path
);
508 tempdir
= Fdirectory_file_name (Vexec_directory
);
509 if (access (XSTRING (tempdir
)->data
, 0) < 0)
511 printf ("Warning: arch-dependent data dir (%s) does not exist.\n",
512 XSTRING (Vexec_directory
)->data
);
516 tempdir
= Fdirectory_file_name (Vdata_directory
);
517 if (access (XSTRING (tempdir
)->data
, 0) < 0)
519 printf ("Warning: arch-independent data dir (%s) does not exist.\n",
520 XSTRING (Vdata_directory
)->data
);
525 Vshell_file_name
= build_string ("*dcl*");
527 sh
= (char *) getenv ("SHELL");
528 Vshell_file_name
= build_string (sh
? sh
: "/bin/sh");
531 Vprocess_environment
= Qnil
;
535 for (envp
= environ
; *envp
; envp
++)
536 Vprocess_environment
= Fcons (build_string (*envp
),
537 Vprocess_environment
);
542 DEFVAR_LISP ("shell-file-name", &Vshell_file_name
,
543 "*File name to load inferior shells from.\n\
544 Initialized from the SHELL environment variable.");
546 DEFVAR_LISP ("exec-path", &Vexec_path
,
547 "*List of directories to search programs to run in subprocesses.\n\
548 Each element is a string (directory name) or nil (try default directory).");
550 DEFVAR_LISP ("exec-directory", &Vexec_directory
,
551 "Directory of architecture-dependent files that come with GNU Emacs,\n\
552 especially executable programs intended for Emacs to invoke.");
554 DEFVAR_LISP ("data-directory", &Vdata_directory
,
555 "Directory of architecture-independent files that come with GNU Emacs,\n\
556 intended for Emacs to use.");
558 DEFVAR_LISP ("process-environment", &Vprocess_environment
,
559 "List of environment variables for subprocesses to inherit.\n\
560 Each element should be a string of the form ENVVARNAME=VALUE.\n\
561 The environment which Emacs inherits is placed in this variable\n\
562 when Emacs starts.");
565 defsubr (&Scall_process
);
568 defsubr (&Scall_process_region
);