|
|
1.1 root 1: /* Synchronous subprocess invocation for GNU Emacs.
2: Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
3:
4: This file is part of GNU Emacs.
5:
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)
9: any later version.
10:
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.
15:
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. */
19:
20:
21: /* This must precede sys/signal.h on certain machines. */
22: #include <sys/types.h>
23: #include <signal.h>
24:
25: #include "config.h"
26:
27: #define PRIO_PROCESS 0
28: #include <sys/file.h>
29: #ifdef USG5
30: #include <fcntl.h>
31: #endif
32:
33: #ifndef O_RDONLY
34: #define O_RDONLY 0
35: #endif
36:
37: #ifndef O_WRONLY
38: #define O_WRONLY 1
39: #endif
40:
41: #include "lisp.h"
42: #include "commands.h"
43: #include "buffer.h"
44: #include "paths.h"
45:
46: #define max(a, b) ((a) > (b) ? (a) : (b))
47:
48: Lisp_Object Vexec_path, Vexec_directory;
49:
50: Lisp_Object Vshell_file_name;
51:
52: #ifndef MAINTAIN_ENVIRONMENT
53: /* List of strings to append to front of environment of
54: all subprocesses when they are started. */
55:
56: Lisp_Object Vprocess_environment;
57: #endif
58:
59: #ifdef BSD4_1
60: /* Set nonzero when a synchronous subprocess is made,
61: and set to zero again when it is observed to die.
62: We wait for this to be zero in order to wait for termination. */
63: int synch_process_pid;
64: #endif /* BSD4_1 */
65:
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;
69:
70: /* Nonzero => this is a string explaining death of synchronous subprocess. */
71: char *synch_process_death;
72:
73: /* Exit code of synchronous subprocess if positive,
74: minus the signal number if negative. */
75: int synch_process_retcode;
76:
77: Lisp_Object
78: call_process_cleanup (fdpid)
79: Lisp_Object fdpid;
80: {
81: register Lisp_Object fd, pid;
82: fd = Fcar (fdpid);
83: pid = Fcdr (fdpid);
84: close (XFASTINT (fd));
85: kill (XFASTINT (pid), SIGKILL);
86: return Qnil;
87: }
88:
89: #ifdef VMS
90: #ifdef __GNUC__
91: #define environ $$PsectAttributes_NOSHR$$environ
92: extern char **environ;
93: #else
94: extern noshare char **environ;
95: #endif
96: #else
97: extern char **environ;
98: #endif
99:
100: DEFUN ("call-process", Fcall_process, Scall_process, 1, MANY, 0,
101: "Call PROGRAM in separate process.\n\
102: Program's input comes from file INFILE (nil means /dev/null).\n\
103: Insert output in BUFFER before point; t means current buffer;\n\
104: nil for BUFFER means discard it; 0 means discard and don't wait.\n\
105: Fourth arg DISPLAY non-nil means redisplay buffer as output is inserted.\n\
106: Remaining arguments are strings passed as command arguments to PROGRAM.\n\
107: Returns nil if BUFFER is 0; otherwise waits for PROGRAM to terminate\n\
108: and returns a numeric exit status or a signal description string.\n\
109: If you quit, the process is killed with SIGKILL.")
110: (nargs, args)
111: int nargs;
112: register Lisp_Object *args;
113: {
114: Lisp_Object display, buffer, path;
115: int fd[2];
116: int filefd;
117: register int pid;
118: char buf[1024];
119: int count = specpdl_ptr - specpdl;
120: register unsigned char **new_argv
121: = (unsigned char **) alloca ((max (2, nargs - 2)) * sizeof (char *));
122: struct buffer *old = current_buffer;
123:
124: CHECK_STRING (args[0], 0);
125:
126: if (nargs <= 1 || NULL (args[1]))
127: #ifdef VMS
128: args[1] = build_string ("NLA0:");
129: #else
130: args[1] = build_string ("/dev/null");
131: #endif /* not VMS */
132: else
133: args[1] = Fexpand_file_name (args[1], current_buffer->directory);
134:
135: CHECK_STRING (args[1], 1);
136:
137: {
138: register Lisp_Object tem;
139: buffer = tem = args[2];
140: if (nargs <= 2)
141: buffer = Qnil;
142: else if (!(EQ (tem, Qnil) || EQ (tem, Qt)
143: || XFASTINT (tem) == 0))
144: {
145: buffer = Fget_buffer (tem);
146: CHECK_BUFFER (buffer, 2);
147: }
148: }
149:
150: display = nargs > 3 ? args[3] : Qnil;
151:
152: {
153: register int i;
154: for (i = 4; i < nargs; i++)
155: {
156: CHECK_STRING (args[i], i);
157: new_argv[i - 3] = XSTRING (args[i])->data;
158: }
159: /* Program name is first command arg */
160: new_argv[0] = XSTRING (args[0])->data;
161: new_argv[i - 3] = 0;
162: }
163:
164: filefd = open (XSTRING (args[1])->data, O_RDONLY, 0);
165: if (filefd < 0)
166: {
167: report_file_error ("Opening process input file", Fcons (args[1], Qnil));
168: }
169: /* Search for program; barf if not found. */
170: openp (Vexec_path, args[0], "", &path, 1);
171: if (NULL (path))
172: {
173: close (filefd);
174: report_file_error ("Searching for program", Fcons (args[0], Qnil));
175: }
176: new_argv[0] = XSTRING (path)->data;
177:
178: if (XTYPE (buffer) == Lisp_Int)
179: #ifdef VMS
180: fd[1] = open ("NLA0:", 0), fd[0] = -1;
181: #else
182: fd[1] = open ("/dev/null", O_WRONLY), fd[0] = -1;
183: #endif /* not VMS */
184: else
185: {
186: pipe (fd);
187: #if 0
188: /* Replaced by close_process_descs */
189: set_exclusive_use (fd[0]);
190: #endif
191: }
192:
193: synch_process_death = 0;
194: synch_process_retcode = 0;
195:
196: {
197: /* child_setup must clobber environ in systems with true vfork.
198: Protect it from permanent change. */
199: register char **save_environ = environ;
200: register int fd1 = fd[1];
201: char **env;
202:
203: #ifdef MAINTAIN_ENVIRONMENT
204: env = (char **) alloca (size_of_current_environ ());
205: get_current_environ (env);
206: #else
207: env = environ;
208: #endif /* MAINTAIN_ENVIRONMENT */
209:
210: pid = vfork ();
211: #ifdef BSD4_1
212: /* cause SIGCHLD interrupts to look for this pid. */
213: synch_process_pid = pid;
214: #endif /* BSD4_1 */
215:
216: if (pid == 0)
217: {
218: if (fd[0] >= 0)
219: close (fd[0]);
220: #ifdef USG
221: #ifdef HAVE_PTYS
222: setpgrp ();
223: #endif
224: #endif
225: child_setup (filefd, fd1, fd1, new_argv, env);
226: }
227:
228: environ = save_environ;
229:
230: close (filefd);
231: close (fd1);
232: }
233:
234: if (pid < 0)
235: {
236: close (fd[0]);
237: report_file_error ("Doing vfork", Qnil);
238: }
239:
240: if (XTYPE (buffer) == Lisp_Int)
241: {
242: #ifndef subprocesses
243: wait_without_blocking ();
244: #endif subprocesses
245: return Qnil;
246: }
247:
248: record_unwind_protect (call_process_cleanup,
249: Fcons (make_number (fd[0]), make_number (pid)));
250:
251:
252: if (XTYPE (buffer) == Lisp_Buffer)
253: Fset_buffer (buffer);
254:
255: immediate_quit = 1;
256: QUIT;
257:
258: {
259: register int nread;
260:
261: while ((nread = read (fd[0], buf, sizeof buf)) > 0)
262: {
263: immediate_quit = 0;
264: if (!NULL (buffer))
265: insert (buf, nread);
266: if (!NULL (display) && FROM_KBD)
267: redisplay_preserve_echo_area ();
268: immediate_quit = 1;
269: QUIT;
270: }
271: }
272:
273: /* Wait for it to terminate, unless it already has. */
274: wait_for_termination (pid);
275:
276: immediate_quit = 0;
277:
278: set_buffer_internal (old);
279:
280: unbind_to (count);
281:
282: if (synch_process_death)
283: return build_string (synch_process_death);
284: return make_number (synch_process_retcode);
285: }
286:
287: DEFUN ("call-process-region", Fcall_process_region, Scall_process_region,
288: 3, MANY, 0,
289: "Send text from START to END to a process running PROGRAM.\n\
290: Delete the text if DELETE is non-nil.\n\
291: Insert output in BUFFER before point; t means current buffer;\n\
292: nil for BUFFER means discard it; 0 means discard and don't wait.\n\
293: Sixth arg DISPLAY non-nil means redisplay buffer as output is inserted.\n\
294: Remaining arguments are strings passed as command arguments to PROGRAM.\n\
295: Returns nil if BUFFER is 0; otherwise waits for PROGRAM to terminate\n\
296: and returns a numeric exit status or a signal description string.\n\
297: If you quit, the process is killed with SIGKILL.")
298: (nargs, args)
299: int nargs;
300: register Lisp_Object *args;
301: {
302: register Lisp_Object filename_string, start, end, status;
303: char tempfile[20];
304:
305: strcpy (tempfile, "/tmp/emacsXXXXXX");
306: mktemp (tempfile);
307:
308: filename_string = build_string (tempfile);
309: start = args[0];
310: end = args[1];
311: Fwrite_region (start, end, filename_string, Qnil, Qlambda);
312:
313: if (!NULL (args[3]))
314: Fdelete_region (start, end);
315:
316: args[3] = filename_string;
317: status = Fcall_process (nargs - 2, args + 2);
318: unlink (tempfile);
319: return status;
320: }
321:
322: /* This is the last thing run in a newly forked inferior
323: either synchronous or asynchronous.
324: Copy descriptors IN, OUT and ERR as descriptors 0, 1 and 2.
325: Initialize inferior's priority, pgrp, connected dir and environment.
326: then exec another program based on new_argv.
327:
328: This function may change environ for the superior process.
329: Therefore, the superior process must save and restore the value
330: of environ around the vfork and the call to this function.
331:
332: ENV is the environment */
333:
334: child_setup (in, out, err, new_argv, env)
335: int in, out, err;
336: register char **new_argv;
337: char **env;
338: {
339: register int pid = getpid();
340:
341: setpriority (PRIO_PROCESS, pid, 0);
342:
343: #ifdef subprocesses
344: /* Close Emacs's descriptors that this process should not have. */
345: close_process_descs ();
346: #endif
347:
348: /* Note that use of alloca is always safe here. It's obvious for systems
349: that do not have true vfork or that have true (stack) alloca.
350: If using vfork and C_ALLOCA it is safe because that changes
351: the superior's static variables as if the superior had done alloca
352: and will be cleaned up in the usual way. */
353:
354: if (XTYPE (current_buffer->directory) == Lisp_String)
355: {
356: register unsigned char *temp;
357: register int i;
358:
359: i = XSTRING (current_buffer->directory)->size;
360: temp = (unsigned char *) alloca (i + 2);
361: bcopy (XSTRING (current_buffer->directory)->data, temp, i);
362: if (temp[i - 1] != '/') temp[i++] = '/';
363: temp[i] = 0;
364: chdir (temp);
365: }
366:
367: #ifndef MAINTAIN_ENVIRONMENT
368: /* Set `env' to a vector of the strings in Vprocess_environment. */
369: {
370: register Lisp_Object tem;
371: register char **new_env;
372: register int new_length;
373:
374: new_length = 0;
375: for (tem = Vprocess_environment;
376: (XTYPE (tem) == Lisp_Cons
377: && XTYPE (XCONS (tem)->car) == Lisp_String);
378: tem = XCONS (tem)->cdr)
379: new_length++;
380:
381: /* new_length + 1 to include terminating 0 */
382: env = new_env = (char **) alloca ((new_length + 1) * sizeof (char *));
383:
384: /* Copy the env strings into new_env. */
385: for (tem = Vprocess_environment;
386: (XTYPE (tem) == Lisp_Cons
387: && XTYPE (XCONS (tem)->car) == Lisp_String);
388: tem = XCONS (tem)->cdr)
389: *new_env++ = (char *) XSTRING (XCONS (tem)->car)->data;
390: *new_env = 0;
391: }
392: #endif /* Not MAINTAIN_ENVIRONMENT */
393:
394: close (0);
395: close (1);
396: close (2);
397:
398: dup2 (in, 0);
399: dup2 (out, 1);
400: dup2 (err, 2);
401: close (in);
402: close (out);
403: close (err);
404:
405: #ifdef USG
406: #ifndef HAVE_PTYS
407: setpgrp (); /* No arguments but equivalent in this case */
408: #endif
409: #else
410: setpgrp (pid, pid);
411: #endif /* USG */
412: setpgrp_of_tty (pid);
413:
414: #ifdef vipc
415: something missing here;
416: #endif vipc
417:
418: /* execvp does not accept an environment arg so the only way
419: to pass this environment is to set environ. Our caller
420: is responsible for restoring the ambient value of environ. */
421: environ = env;
422: execvp (new_argv[0], new_argv);
423:
424: write (1, "Couldn't exec the program ", 26);
425: write (1, new_argv[0], strlen (new_argv[0]));
426: _exit (1);
427: }
428:
429: init_callproc ()
430: {
431: register char * sh;
432: extern char **environ;
433: register char **envp;
434: Lisp_Object execdir;
435:
436: /* Turn PATH_EXEC into a path. Don't look at environment. */
437: Vexec_path = decode_env_path (0, PATH_EXEC);
438: Vexec_directory = Ffile_name_as_directory (Fcar (Vexec_path));
439: Vexec_path = nconc2 (decode_env_path ("PATH", ""), Vexec_path);
440:
441: execdir = Fdirectory_file_name (Vexec_directory);
442: if (access (XSTRING (execdir)->data, 0) < 0)
443: {
444: printf ("Warning: executable/documentation dir (%s) does not exist.\n",
445: XSTRING (Vexec_directory)->data);
446: sleep (2);
447: }
448:
449: sh = (char *) egetenv ("SHELL");
450: Vshell_file_name = build_string (sh ? sh : "/bin/sh");
451:
452: #ifndef MAINTAIN_ENVIRONMENT
453: /* The equivalent of this operation was done
454: in init_environ in environ.c if MAINTAIN_ENVIRONMENT */
455: Vprocess_environment = Qnil;
456: #ifndef CANNOT_DUMP
457: if (initialized)
458: #endif
459: for (envp = environ; *envp; envp++)
460: Vprocess_environment = Fcons (build_string (*envp),
461: Vprocess_environment);
462: #endif /* MAINTAIN_ENVIRONMENT */
463: }
464:
465: syms_of_callproc ()
466: {
467: DEFVAR_LISP ("shell-file-name", &Vshell_file_name,
468: "*File name to load inferior shells from.\n\
469: Initialized from the SHELL environment variable.");
470:
471: DEFVAR_LISP ("exec-path", &Vexec_path,
472: "*List of directories to search programs to run in subprocesses.\n\
473: Each element is a string (directory name) or nil (try default directory).");
474:
475: DEFVAR_LISP ("exec-directory", &Vexec_directory,
476: "Directory that holds programs that come with GNU Emacs,\n\
477: intended for Emacs to invoke.");
478:
479: #ifndef MAINTAIN_ENVIRONMENT
480: DEFVAR_LISP ("process-environment", &Vprocess_environment,
481: "List of strings to append to environment of subprocesses that are started.\n\
482: Each string should have the format ENVVARNAME=VALUE.");
483: #endif
484:
485: defsubr (&Scall_process);
486: defsubr (&Scall_process_region);
487: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.