mu_spawnvp(): new function - like system, but doesn't use /bin/sh, just
forks and calls execvp(), with system-like signal handling.
Showing
1 changed file
with
94 additions
and
8 deletions
... | @@ -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 | ... | ... |
-
Please register or sign in to post a comment