X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=lib-sys%2Funix.c;fp=lib-sys%2Funix.c;h=f2141c0c18849a0655a459ac80afdee7ec986d20;hp=372ff0631890a88640bcb76ed6a3345603373881;hb=97677c08933e16e25ecb3c12473ef1efdab7962b;hpb=dbacadf0ce81052365d7a43373ac7d4ac67ff91e diff --git a/lib-sys/unix.c b/lib-sys/unix.c index 372ff06..f2141c0 100644 --- a/lib-sys/unix.c +++ b/lib-sys/unix.c @@ -8,13 +8,20 @@ * please see the file GPL in the top level source directory. */ +#include #include +#include +#include #include #include #include #include "unix.h" +#include "mutt_signal.h" + +#include /* for imap_wait_keepalive EEEEK */ + /* Extract the real name from /etc/passwd's GECOS field. * When set, honor the regular expression in rx, @@ -61,3 +68,91 @@ ssize_t mutt_gecos_name(char *dst, ssize_t n, struct passwd *pw, rx_t *rx) return len; } + +int _mutt_system(const char *cmd, int flags) +{ + int rc = -1; + struct sigaction act; + struct sigaction oldtstp; + struct sigaction oldcont; + sigset_t set; + pid_t pid; + + if (m_strisempty(cmd)) + return 0; + + /* must ignore SIGINT and SIGQUIT */ + mutt_block_signals_system(); + + /* also don't want to be stopped right now */ + if (flags & M_DETACH_PROCESS) { + sigemptyset(&set); + sigaddset(&set, SIGTSTP); + sigprocmask(SIG_BLOCK, &set, NULL); + } else { + act.sa_handler = SIG_DFL; + /* we want to restart the waitpid() below */ +#ifdef SA_RESTART + act.sa_flags = SA_RESTART; +#endif + sigemptyset(&act.sa_mask); + sigaction(SIGTSTP, &act, &oldtstp); + sigaction(SIGCONT, &act, &oldcont); + } + + pid = fork (); + if (pid == 0) { + act.sa_flags = 0; + + if (flags & M_DETACH_PROCESS) { + /* give up controlling terminal */ + setsid(); + + switch (fork()) { + int fd, nb_fds; + + case 0: + nb_fds = getdtablesize(); + for (fd = 0; fd < nb_fds; fd++) { + close(fd); + } + chdir ("/"); + act.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &act, NULL); + break; + + case -1: + _exit(127); + + default: + _exit(0); + } + } + + /* reset signals for the child; not really needed, but... */ + mutt_unblock_signals_system(0); + act.sa_handler = SIG_DFL; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + sigaction(SIGTERM, &act, NULL); + sigaction(SIGTSTP, &act, NULL); + sigaction(SIGCONT, &act, NULL); + + execl("/bin/sh", "sh", "-c", cmd, NULL); + _exit(127); /* execl error */ + } else + if (pid != -1) { + rc = imap_wait_keepalive(pid); + } + + sigaction(SIGCONT, &oldcont, NULL); + sigaction(SIGTSTP, &oldtstp, NULL); + + /* reset SIGINT, SIGQUIT and SIGCHLD */ + mutt_unblock_signals_system(1); + if (flags & M_DETACH_PROCESS) { + sigprocmask (SIG_UNBLOCK, &set, NULL); + } + + return (pid > 0 && WIFEXITED(rc)) ? WEXITSTATUS(rc) : -1; +}