Commit 2de90f2c 2de90f2cd76a35205e9bb42e5845779a3a0c0bc2 by Sam Roberts

mu_spawnvp(): new function - like system, but doesn't use /bin/sh, just

forks and calls execvp(), with system-like signal handling.
1 parent d88120f6
...@@ -20,22 +20,28 @@ ...@@ -20,22 +20,28 @@
20 # include <config.h> 20 # include <config.h>
21 #endif 21 #endif
22 22
23 #include <errno.h>
24 #include <netdb.h>
25 #include <pwd.h>
26 #include <signal.h>
23 #include <stdio.h> 27 #include <stdio.h>
24 #include <stdlib.h> 28 #include <stdlib.h>
25 #ifdef HAVE_STRINGS_H 29 #include <string.h>
26 #include <strings.h>
27 #endif
28 #include <time.h> 30 #include <time.h>
29 #include <pwd.h>
30 #include <unistd.h> 31 #include <unistd.h>
31 #include <string.h> 32
32 #include <netdb.h>
33 #include <errno.h>
34 #include <sys/stat.h> 33 #include <sys/stat.h>
34 #include <sys/types.h>
35 #include <sys/wait.h>
36
37 #ifdef HAVE_STRINGS_H
38 #include <strings.h>
39 #endif
35 40
36 #include <mailutils/error.h> 41 #include <mailutils/error.h>
37 #include <mailutils/mutil.h>
38 #include <mailutils/iterator.h> 42 #include <mailutils/iterator.h>
43 #include <mailutils/list.h>
44 #include <mailutils/mutil.h>
39 45
40 /* convert a sequence of hex characters into an integer */ 46 /* convert a sequence of hex characters into an integer */
41 47
...@@ -687,3 +693,83 @@ mu_tempfile (const char *tmpdir, char **namep) ...@@ -687,3 +693,83 @@ mu_tempfile (const char *tmpdir, char **namep)
687 693
688 return fd; 694 return fd;
689 } 695 }
696
697 /* See Advanced Programming in the UNIX Environment, Stevens,
698 * program 10.20 for the rational for the signal handling. I
699 * had to look it up, so if somebody else is curious, thats where
700 * to find it.
701 */
702 int mu_spawnvp(const char* prog, const char* const av_[], int* stat)
703 {
704 pid_t pid;
705 int err = 0;
706 int progstat;
707 struct sigaction ignore;
708 struct sigaction saveintr;
709 struct sigaction savequit;
710 sigset_t chldmask;
711 sigset_t savemask;
712 char** av = (char**) av_;
713
714 if (!prog || !av)
715 return EINVAL;
716
717 ignore.sa_handler = SIG_IGN; /* ignore SIGINT and SIGQUIT */
718 ignore.sa_flags = 0;
719 sigemptyset (&ignore.sa_mask);
720
721 if (sigaction (SIGINT, &ignore, &saveintr) < 0)
722 return errno;
723 if (sigaction (SIGQUIT, &ignore, &savequit) < 0)
724 return errno;
725
726 sigemptyset (&chldmask); /* now block SIGCHLD */
727 sigaddset (&chldmask, SIGCHLD);
728
729 if (sigprocmask (SIG_BLOCK, &chldmask, &savemask) < 0)
730 return errno;
731
732 #ifdef HAVE_VFORK
733 pid = vfork ();
734 #else
735 pid = fork ();
736 #endif
737
738 if (pid < 0)
739 {
740 err = errno;
741 }
742 else if (pid == 0)
743 { /* child */
744 /* restore previous signal actions & reset signal mask */
745 sigaction (SIGINT, &saveintr, NULL);
746 sigaction (SIGQUIT, &savequit, NULL);
747 sigprocmask (SIG_SETMASK, &savemask, NULL);
748
749 execvp(av[0], av);
750 _exit (127); /* exec error */
751 }
752 else
753 { /* parent */
754 while (waitpid (pid, &progstat, 0) < 0)
755 if (errno != EINTR)
756 {
757 err = errno; /* error other than EINTR from waitpid() */
758 break;
759 }
760 if(err == 0 && stat)
761 *stat = progstat;
762 }
763
764 /* restore previous signal actions & reset signal mask */
765 /* preserve first error number, but still try and reset the signals */
766 if (sigaction (SIGINT, &saveintr, NULL) < 0)
767 err = err ? err : errno;
768 if (sigaction (SIGQUIT, &savequit, NULL) < 0)
769 err = err ? err : errno;
770 if (sigprocmask (SIG_SETMASK, &savemask, NULL) < 0)
771 err = err ? err : errno;
772
773 return err;
774 }
775
......