aboutsummaryrefslogtreecommitdiffstats
path: root/src/callproc.c
diff options
context:
space:
mode:
authorPaul Eggert2012-11-28 14:33:35 -0800
committerPaul Eggert2012-11-28 14:33:35 -0800
commit60aeceb8c41fffee197d43e7eae2b46d9e3fcc74 (patch)
treee29f8adf206ac107b41ea6769d17589381da78fe /src/callproc.c
parente7c8fcc44eff6dbc6ccb6ebc7f6389233ee516ab (diff)
downloademacs-60aeceb8c41fffee197d43e7eae2b46d9e3fcc74.tar.gz
emacs-60aeceb8c41fffee197d43e7eae2b46d9e3fcc74.zip
* callproc.c (Fcall_process): Fix vfork portability problems.
Do not assume that fd[0], count, filefd, and save_environ survive vfork. Fix bug whereby wrong errno value could be reported for pipe failure. Some minor cleanups, too, as follows. Move buf and bufsize to the context where they're needed. Change new_argv to be of type char **, as this is more convenient and avoids casts. (CALLPROC_BUFFER_SIZE_MIN, CALLPROC_BUFFER_SIZE_MAX): Now local constants, not macros.
Diffstat (limited to 'src/callproc.c')
-rw-r--r--src/callproc.c86
1 files changed, 48 insertions, 38 deletions
diff --git a/src/callproc.c b/src/callproc.c
index c9a504746b3..bba1c043b4c 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -183,16 +183,11 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
183{ 183{
184 Lisp_Object infile, buffer, current_dir, path, cleanup_info_tail; 184 Lisp_Object infile, buffer, current_dir, path, cleanup_info_tail;
185 bool display_p; 185 bool display_p;
186 int fd[2]; 186 int fd0, fd1, filefd;
187 int filefd;
188#define CALLPROC_BUFFER_SIZE_MIN (16 * 1024)
189#define CALLPROC_BUFFER_SIZE_MAX (4 * CALLPROC_BUFFER_SIZE_MIN)
190 char buf[CALLPROC_BUFFER_SIZE_MAX];
191 int bufsize = CALLPROC_BUFFER_SIZE_MIN;
192 ptrdiff_t count = SPECPDL_INDEX (); 187 ptrdiff_t count = SPECPDL_INDEX ();
193 USE_SAFE_ALLOCA; 188 USE_SAFE_ALLOCA;
194 189
195 register const unsigned char **new_argv; 190 char **new_argv;
196 /* File to use for stderr in the child. 191 /* File to use for stderr in the child.
197 t means use same as standard output. */ 192 t means use same as standard output. */
198 Lisp_Object error_file; 193 Lisp_Object error_file;
@@ -432,12 +427,12 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
432 } 427 }
433 UNGCPRO; 428 UNGCPRO;
434 for (i = 4; i < nargs; i++) 429 for (i = 4; i < nargs; i++)
435 new_argv[i - 3] = SDATA (args[i]); 430 new_argv[i - 3] = SSDATA (args[i]);
436 new_argv[i - 3] = 0; 431 new_argv[i - 3] = 0;
437 } 432 }
438 else 433 else
439 new_argv[1] = 0; 434 new_argv[1] = 0;
440 new_argv[0] = SDATA (path); 435 new_argv[0] = SSDATA (path);
441 436
442#ifdef MSDOS /* MW, July 1993 */ 437#ifdef MSDOS /* MW, July 1993 */
443 438
@@ -466,29 +461,35 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
466 } 461 }
467 else 462 else
468 outfilefd = fd_output; 463 outfilefd = fd_output;
469 fd[0] = filefd; 464 fd0 = filefd;
470 fd[1] = outfilefd; 465 fd1 = outfilefd;
471#endif /* MSDOS */ 466#endif /* MSDOS */
472 467
473 if (INTEGERP (buffer)) 468 if (INTEGERP (buffer))
474 fd[1] = emacs_open (NULL_DEVICE, O_WRONLY, 0), fd[0] = -1; 469 {
470 fd0 = -1;
471 fd1 = emacs_open (NULL_DEVICE, O_WRONLY, 0);
472 }
475 else 473 else
476 { 474 {
477#ifndef MSDOS 475#ifndef MSDOS
478 errno = 0; 476 int fd[2];
479 if (pipe (fd) == -1) 477 if (pipe (fd) == -1)
480 { 478 {
479 int pipe_errno = errno;
481 emacs_close (filefd); 480 emacs_close (filefd);
481 errno = pipe_errno;
482 report_file_error ("Creating process pipe", Qnil); 482 report_file_error ("Creating process pipe", Qnil);
483 } 483 }
484 fd0 = fd[0];
485 fd1 = fd[1];
484#endif 486#endif
485 } 487 }
486 488
487 { 489 {
488 /* child_setup must clobber environ in systems with true vfork. 490 /* child_setup must clobber environ in systems with true vfork.
489 Protect it from permanent change. */ 491 Protect it from permanent change. */
490 register char **save_environ = environ; 492 char **save_environ = environ;
491 register int fd1 = fd[1];
492 int fd_error = fd1; 493 int fd_error = fd1;
493 494
494 if (fd_output >= 0) 495 if (fd_output >= 0)
@@ -520,8 +521,8 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
520 if (fd_error < 0) 521 if (fd_error < 0)
521 { 522 {
522 emacs_close (filefd); 523 emacs_close (filefd);
523 if (fd[0] != filefd) 524 if (fd0 != filefd)
524 emacs_close (fd[0]); 525 emacs_close (fd0);
525 if (fd1 >= 0) 526 if (fd1 >= 0)
526 emacs_close (fd1); 527 emacs_close (fd1);
527#ifdef MSDOS 528#ifdef MSDOS
@@ -538,8 +539,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
538 /* Note that on MSDOS `child_setup' actually returns the child process 539 /* Note that on MSDOS `child_setup' actually returns the child process
539 exit status, not its PID, so we assign it to `synch_process_retcode' 540 exit status, not its PID, so we assign it to `synch_process_retcode'
540 below. */ 541 below. */
541 pid = child_setup (filefd, outfilefd, fd_error, (char **) new_argv, 542 pid = child_setup (filefd, outfilefd, fd_error, new_argv, 0, current_dir);
542 0, current_dir);
543 543
544 /* Record that the synchronous process exited and note its 544 /* Record that the synchronous process exited and note its
545 termination status. */ 545 termination status. */
@@ -559,8 +559,8 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
559 { 559 {
560 /* Since CRLF is converted to LF within `decode_coding', we 560 /* Since CRLF is converted to LF within `decode_coding', we
561 can always open a file with binary mode. */ 561 can always open a file with binary mode. */
562 fd[0] = emacs_open (tempfile, O_RDONLY | O_BINARY, 0); 562 fd0 = emacs_open (tempfile, O_RDONLY | O_BINARY, 0);
563 if (fd[0] < 0) 563 if (fd0 < 0)
564 { 564 {
565 unlink (tempfile); 565 unlink (tempfile);
566 emacs_close (filefd); 566 emacs_close (filefd);
@@ -569,11 +569,10 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
569 } 569 }
570 } 570 }
571 else 571 else
572 fd[0] = -1; /* We are not going to read from tempfile. */ 572 fd0 = -1; /* We are not going to read from tempfile. */
573#else /* not MSDOS */ 573#else /* not MSDOS */
574#ifdef WINDOWSNT 574#ifdef WINDOWSNT
575 pid = child_setup (filefd, fd1, fd_error, (char **) new_argv, 575 pid = child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir);
576 0, current_dir);
577#else /* not WINDOWSNT */ 576#else /* not WINDOWSNT */
578 577
579 block_input (); 578 block_input ();
@@ -586,11 +585,15 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
586 bool volatile display_p_volatile = display_p; 585 bool volatile display_p_volatile = display_p;
587 bool volatile output_to_buffer_volatile = output_to_buffer; 586 bool volatile output_to_buffer_volatile = output_to_buffer;
588 bool volatile sa_must_free_volatile = sa_must_free; 587 bool volatile sa_must_free_volatile = sa_must_free;
588 int volatile fd0_volatile = fd0;
589 int volatile fd1_volatile = fd1; 589 int volatile fd1_volatile = fd1;
590 int volatile fd_error_volatile = fd_error; 590 int volatile fd_error_volatile = fd_error;
591 int volatile fd_output_volatile = fd_output; 591 int volatile fd_output_volatile = fd_output;
592 int volatile filefd_volatile = filefd;
593 ptrdiff_t volatile count_volatile = count;
592 ptrdiff_t volatile sa_count_volatile = sa_count; 594 ptrdiff_t volatile sa_count_volatile = sa_count;
593 unsigned char const **volatile new_argv_volatile = new_argv; 595 char **volatile new_argv_volatile = new_argv;
596 char **volatile new_save_environ = save_environ;
594 597
595 pid = vfork (); 598 pid = vfork ();
596 599
@@ -598,27 +601,30 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
598 coding_systems = coding_systems_volatile; 601 coding_systems = coding_systems_volatile;
599 current_dir = current_dir_volatile; 602 current_dir = current_dir_volatile;
600 display_p = display_p_volatile; 603 display_p = display_p_volatile;
604 output_to_buffer = output_to_buffer_volatile;
605 sa_must_free = sa_must_free_volatile;
606 fd0 = fd0_volatile;
601 fd1 = fd1_volatile; 607 fd1 = fd1_volatile;
602 fd_error = fd_error_volatile; 608 fd_error = fd_error_volatile;
603 fd_output = fd_output_volatile; 609 fd_output = fd_output_volatile;
604 output_to_buffer = output_to_buffer_volatile; 610 filefd = filefd_volatile;
605 sa_must_free = sa_must_free_volatile; 611 count = count_volatile;
606 sa_count = sa_count_volatile; 612 sa_count = sa_count_volatile;
607 new_argv = new_argv_volatile; 613 new_argv = new_argv_volatile;
614 save_environ = new_save_environ;
608 } 615 }
609 616
610 if (pid == 0) 617 if (pid == 0)
611 { 618 {
612 if (fd[0] >= 0) 619 if (fd0 >= 0)
613 emacs_close (fd[0]); 620 emacs_close (fd0);
614 621
615 setsid (); 622 setsid ();
616 623
617 /* Emacs ignores SIGPIPE, but the child should not. */ 624 /* Emacs ignores SIGPIPE, but the child should not. */
618 signal (SIGPIPE, SIG_DFL); 625 signal (SIGPIPE, SIG_DFL);
619 626
620 child_setup (filefd, fd1, fd_error, (char **) new_argv, 627 child_setup (filefd, fd1, fd_error, new_argv, 0, current_dir);
621 0, current_dir);
622 } 628 }
623 629
624 unblock_input (); 630 unblock_input ();
@@ -632,7 +638,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
632 638
633 environ = save_environ; 639 environ = save_environ;
634 640
635 /* Close most of our fd's, but not fd[0] 641 /* Close most of our file descriptors, but not fd0
636 since we will use that to read input from. */ 642 since we will use that to read input from. */
637 emacs_close (filefd); 643 emacs_close (filefd);
638 if (fd_output >= 0) 644 if (fd_output >= 0)
@@ -643,15 +649,15 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
643 649
644 if (pid < 0) 650 if (pid < 0)
645 { 651 {
646 if (fd[0] >= 0) 652 if (fd0 >= 0)
647 emacs_close (fd[0]); 653 emacs_close (fd0);
648 report_file_error ("Doing vfork", Qnil); 654 report_file_error ("Doing vfork", Qnil);
649 } 655 }
650 656
651 if (INTEGERP (buffer)) 657 if (INTEGERP (buffer))
652 { 658 {
653 if (fd[0] >= 0) 659 if (fd0 >= 0)
654 emacs_close (fd[0]); 660 emacs_close (fd0);
655 return Qnil; 661 return Qnil;
656 } 662 }
657 663
@@ -666,7 +672,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
666#endif /* not MSDOS */ 672#endif /* not MSDOS */
667 record_unwind_protect (call_process_cleanup, 673 record_unwind_protect (call_process_cleanup,
668 Fcons (Fcurrent_buffer (), 674 Fcons (Fcurrent_buffer (),
669 Fcons (INTEGER_TO_CONS (fd[0]), 675 Fcons (INTEGER_TO_CONS (fd0),
670 cleanup_info_tail))); 676 cleanup_info_tail)));
671 677
672 if (BUFFERP (buffer)) 678 if (BUFFERP (buffer))
@@ -723,6 +729,10 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
723 729
724 if (output_to_buffer) 730 if (output_to_buffer)
725 { 731 {
732 enum { CALLPROC_BUFFER_SIZE_MIN = 16 * 1024 };
733 enum { CALLPROC_BUFFER_SIZE_MAX = 4 * CALLPROC_BUFFER_SIZE_MIN };
734 char buf[CALLPROC_BUFFER_SIZE_MAX];
735 int bufsize = CALLPROC_BUFFER_SIZE_MIN;
726 int nread; 736 int nread;
727 bool first = 1; 737 bool first = 1;
728 EMACS_INT total_read = 0; 738 EMACS_INT total_read = 0;
@@ -739,7 +749,7 @@ usage: (call-process PROGRAM &optional INFILE BUFFER DISPLAY &rest ARGS) */)
739 nread = carryover; 749 nread = carryover;
740 while (nread < bufsize - 1024) 750 while (nread < bufsize - 1024)
741 { 751 {
742 int this_read = emacs_read (fd[0], buf + nread, 752 int this_read = emacs_read (fd0, buf + nread,
743 bufsize - nread); 753 bufsize - nread);
744 754
745 if (this_read < 0) 755 if (this_read < 0)