summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Roessler <roessler@does-not-exist.org>1999-02-10 21:19:34 +0000
committerThomas Roessler <roessler@does-not-exist.org>1999-02-10 21:19:34 +0000
commit15739ddd2345d227a16d18a3abfb740ae7c2ec0f (patch)
treebd608a8b9771d60c785a9cc84e297748960fe33d
parent25a768b966efe0f5570d6b6356b9752add6efb49 (diff)
patch.mutt-0.95.1i.ld.signals.1: A major redesign of how child
processes are invoked. From Liviu.
-rw-r--r--TODO4
-rw-r--r--attach.c11
-rw-r--r--commands.c10
-rw-r--r--compose.c6
-rw-r--r--curs_lib.c12
-rw-r--r--globals.h3
-rw-r--r--mutt.h12
-rw-r--r--protos.h1
-rw-r--r--send.c9
-rw-r--r--sendlib.c270
-rw-r--r--signal.c147
-rw-r--r--system.c86
12 files changed, 302 insertions, 269 deletions
diff --git a/TODO b/TODO
index 3f93e3a4..72f428fc 100644
--- a/TODO
+++ b/TODO
@@ -1,5 +1,9 @@
Problems are listed in approximate order of priority.
+- Fix postponing: Headers should be RFC2047 en- and de-coded.
+- character set support: We should have a global cache of
+ character to file name mappings.
+
- Help formatting could be revamped a bit.
- re-add support for .mh_sequences files
diff --git a/attach.c b/attach.c
index da283f24..41311b8e 100644
--- a/attach.c
+++ b/attach.c
@@ -124,9 +124,13 @@ int mutt_compose_attachment (BODY *a)
}
else
{
+ int r;
+
endwin ();
- mutt_system (command);
- if (entry->composetypecommand)
+ if ((r = mutt_system (command)) == -1)
+ mutt_error (_("Error running \"%s\"!"), command);
+
+ if (r != -1 && entry->composetypecommand)
{
BODY *b;
FILE *fp, *tfp;
@@ -248,7 +252,8 @@ int mutt_edit_attachment (BODY *a)
else
{
endwin ();
- mutt_system (command);
+ if (mutt_system (command) == -1)
+ mutt_error (_("Error running \"%s\"!"), command);
}
}
}
diff --git a/commands.c b/commands.c
index 64dd3f43..9929fee3 100644
--- a/commands.c
+++ b/commands.c
@@ -147,13 +147,17 @@ int mutt_display_message (HEADER *cur)
}
else
{
+ int r;
+
endwin ();
snprintf (buf, sizeof (buf), "%s %s", NONULL(Pager), tempfile);
- mutt_system (buf);
+ if ((r = mutt_system (buf)) == -1)
+ mutt_error (_("Error running \"%s\"!"), buf);
unlink (tempfile);
keypad (stdscr, TRUE);
- mutt_set_flag (Context, cur, M_READ, 1);
- if (option (OPTPROMPTAFTER))
+ if (r != -1)
+ mutt_set_flag (Context, cur, M_READ, 1);
+ if (r != -1 && option (OPTPROMPTAFTER))
{
mutt_ungetch (mutt_any_key_to_continue _("Command: "), 0);
rc = km_dokey (MENU_PAGER);
diff --git a/compose.c b/compose.c
index ccf2849a..7d6b045f 100644
--- a/compose.c
+++ b/compose.c
@@ -1166,8 +1166,10 @@ int mutt_compose_menu (HEADER *msg, /* structure for new message */
case OP_COMPOSE_ISPELL:
endwin ();
snprintf (buf, sizeof (buf), "%s -x %s", NONULL(Ispell), msg->content->filename);
- mutt_system (buf);
- mutt_update_encoding(msg->content);
+ if (mutt_system (buf) == -1)
+ mutt_error (_("Error running \"%s\"!"), buf);
+ else
+ mutt_update_encoding (msg->content);
break;
case OP_COMPOSE_WRITE_MESSAGE:
diff --git a/curs_lib.c b/curs_lib.c
index 0d47e4c8..a35d4a55 100644
--- a/curs_lib.c
+++ b/curs_lib.c
@@ -124,7 +124,8 @@ void mutt_edit_file (const char *editor, const char *data)
endwin ();
mutt_expand_file_fmt (cmd, sizeof (cmd), editor, data);
- mutt_system (cmd);
+ if (mutt_system (cmd) == -1)
+ mutt_error (_("Error running \"%s\"!"), cmd);
keypad (stdscr, TRUE);
clearok (stdscr, TRUE);
}
@@ -317,9 +318,14 @@ int mutt_do_pager (const char *banner,
endwin ();
mutt_expand_file_fmt (cmd, sizeof(cmd), Pager, tempfile);
- mutt_system (cmd);
+ if (mutt_system (cmd) == -1)
+ {
+ mutt_error (_("Error running \"%s\"!"), cmd);
+ rc = -1;
+ }
+ else
+ rc = 0;
mutt_unlink (tempfile);
- rc = 0;
}
return rc;
diff --git a/globals.h b/globals.h
index 6ccbb354..836768db 100644
--- a/globals.h
+++ b/globals.h
@@ -118,7 +118,8 @@ WHERE short Timeout;
WHERE short WriteInc;
/* vector to store received signals */
-WHERE short Signals INITVAL (0);
+/* hopefully it's an integer type... */
+WHERE volatile sig_atomic_t Signals INITVAL (0);
WHERE int CurrentMenu;
diff --git a/mutt.h b/mutt.h
index 44c61e51..190375b5 100644
--- a/mutt.h
+++ b/mutt.h
@@ -27,6 +27,7 @@
#include <time.h>
#include <limits.h>
#include <stdarg.h>
+#include <signal.h>
#ifndef _POSIX_PATH_MAX
#include <posix1_lim.h>
@@ -371,6 +372,7 @@ enum
OPTMSGERR, /* (pseudo) used by mutt_error/mutt_message */
OPTSEARCHINVALID, /* (pseudo) used to invalidate the search pat */
OPTSIGNALSBLOCKED, /* (pseudo) using by mutt_block_signals () */
+ OPTSYSSIGNALSBLOCKED, /* (pseudo) using by mutt_block_signals_system () */
OPTNEEDRESORT, /* (pseudo) used to force a re-sort */
OPTVIEWATTACH, /* (pseudo) signals that we are viewing attachments */
OPTFORCEREDRAWINDEX, /* (pseudo) used to force a redraw in the main index */
@@ -403,9 +405,13 @@ enum
#define option(x) mutt_bit_isset(Options,x)
/* Bit fields for ``Signals'' */
-#define S_INTERRUPT (1<<1)
-#define S_SIGWINCH (1<<2)
-#define S_ALARM (1<<3)
+#define S_INTERRUPT (1<<0)
+#define S_SIGWINCH (1<<1)
+#define S_ALARM (1<<2)
+
+/* Exit values used in send_msg() */
+#define S_ERR 127
+#define S_BKG 126
typedef struct list_t
{
diff --git a/protos.h b/protos.h
index a86fc865..25672655 100644
--- a/protos.h
+++ b/protos.h
@@ -130,7 +130,6 @@ char *mutt_substrdup (const char *, const char *);
const char *mutt_fqdn(short);
-void mutt_add_child_pid (pid_t);
void mutt_alias_menu (char *, size_t, ALIAS *);
void mutt_block_signals (void);
void mutt_block_signals_system (void);
diff --git a/send.c b/send.c
index 743ad15f..9f0e301d 100644
--- a/send.c
+++ b/send.c
@@ -832,7 +832,7 @@ static int send_message (HEADER *msg)
i = mutt_invoke_sendmail (msg->env->to, msg->env->cc, msg->env->bcc,
tempfile, (msg->content->encoding == ENC8BIT));
- return (i ? -1 : 0);
+ return (i);
}
/* rfc2047 encode the content-descriptions */
@@ -1327,7 +1327,7 @@ full_fcc:
}
#endif /* _PGPPATH */
- if (send_message (msg) == -1)
+ if ((i = send_message (msg)) == -1)
{
if (!(flags & SENDBATCH))
{
@@ -1340,9 +1340,8 @@ full_fcc:
goto cleanup;
}
}
-
- if (!option (OPTNOCURSES) && ! (flags & SENDMAILX))
- mutt_message _("Mail sent.");
+ else if (!option (OPTNOCURSES) && ! (flags & SENDMAILX))
+ mutt_message (i == 0 ? _("Mail sent.") : _("Sending in background."));
if (flags & SENDREPLY)
{
diff --git a/sendlib.c b/sendlib.c
index 05d1d3b2..533cf0eb 100644
--- a/sendlib.c
+++ b/sendlib.c
@@ -23,6 +23,7 @@
#include "mime.h"
#include "mailbox.h"
#include "copy.h"
+#include "pager.h"
#include "charset.h"
#include <string.h>
@@ -49,47 +50,48 @@ static struct sysexits
sysexits_h[] =
{
#ifdef EX_USAGE
- { EX_USAGE, "The command was used incorrectly." },
+ { 0xff & EX_USAGE, "The command was used incorrectly." },
#endif
#ifdef EX_DATAERR
- { EX_DATAERR, "The input data was incorrect." },
+ { 0xff & EX_DATAERR, "The input data was incorrect." },
#endif
#ifdef EX_NOINPUT
- { EX_NOINPUT, "No input." },
+ { 0xff & EX_NOINPUT, "No input." },
#endif
#ifdef EX_NOUSER
- { EX_NOUSER, "No such user." },
+ { 0xff & EX_NOUSER, "No such user." },
#endif
#ifdef EX_NOHOST
- { EX_NOHOST, "Host not found." },
+ { 0xff & EX_NOHOST, "Host not found." },
#endif
#ifdef EX_UNAVAILABLE
- { EX_UNAVAILABLE, "Service unavailable." },
+ { 0xff & EX_UNAVAILABLE, "Service unavailable." },
#endif
#ifdef EX_SOFTWARE
- { EX_SOFTWARE, "Software error." },
+ { 0xff & EX_SOFTWARE, "Software error." },
#endif
#ifdef EX_OSERR
- { EX_OSERR, "Operating system error." },
+ { 0xff & EX_OSERR, "Operating system error." },
#endif
#ifdef EX_OSFILE
- { EX_OSFILE, "System file is missing." },
+ { 0xff & EX_OSFILE, "System file is missing." },
#endif
#ifdef EX_CANTCREAT
- { EX_CANTCREAT, "Can't create output." },
+ { 0xff & EX_CANTCREAT, "Can't create output." },
#endif
#ifdef EX_IOERR
- { EX_IOERR, "I/O error." },
+ { 0xff & EX_IOERR, "I/O error." },
#endif
#ifdef EX_TEMPFAIL
- { EX_TEMPFAIL, "Temporary failure." },
+ { 0xff & EX_TEMPFAIL, "Temporary failure." },
#endif
#ifdef EX_PROTOCOL
- { EX_PROTOCOL, "Protocol error." },
+ { 0xff & EX_PROTOCOL, "Protocol error." },
#endif
#ifdef EX_NOPERM
- { EX_NOPERM, "Permission denied." },
+ { 0xff & EX_NOPERM, "Permission denied." },
#endif
+ { S_ERR, "Exec error." },
{ -1, NULL}
};
@@ -1429,17 +1431,18 @@ static RETSIGTYPE alarm_handler (int sig)
static int
send_msg (const char *path, char **args, const char *msg, char **tempfile)
{
- int fd, st, w = 0, err = 0;
+ sigset_t set;
+ int fd, st;
pid_t pid;
- struct sigaction act, oldint, oldquit, oldalrm;
- memset (&act, 0, sizeof (struct sigaction));
- sigemptyset (&(act.sa_mask));
- act.sa_handler = SIG_IGN;
- sigaction (SIGINT, &act, &oldint);
- sigaction (SIGQUIT, &act, &oldquit);
+ mutt_block_signals_system ();
- if (SendmailWait)
+ sigemptyset (&set);
+ /* we also don't want to be stopped right now */
+ sigaddset (&set, SIGTSTP);
+ sigprocmask (SIG_BLOCK, &set, NULL);
+
+ if (SendmailWait >= 0)
{
char tmp[_POSIX_PATH_MAX];
@@ -1449,135 +1452,119 @@ send_msg (const char *path, char **args, const char *msg, char **tempfile)
if ((pid = fork ()) == 0)
{
- /* reset signals for the child */
- act.sa_handler = SIG_DFL;
- /* we need SA_RESTART for the open() below */
-#ifdef SA_RESTART
- act.sa_flags = SA_NOCLDSTOP | SA_RESTART;
+ struct sigaction act, oldalrm;
+
+ /* we want the delivery to continue even after the main process dies,
+ * so we put ourselves into another session right away
+ */
+ setsid ();
+
+ /* next we close all open files */
+#if defined(OPEN_MAX)
+ for (fd = 0; fd < OPEN_MAX; fd++)
+ close (fd);
+#elif defined(_POSIX_OPEN_MAX)
+ for (fd = 0; fd < _POSIX_OPEN_MAX; fd++)
+ close (fd);
#else
- act.sa_flags = SA_NOCLDSTOP;
+ close (0);
+ close (1);
+ close (2);
#endif
- sigaction (SIGCHLD, &act, NULL);
- act.sa_flags = 0;
- sigaction (SIGINT, &act, NULL);
- sigaction (SIGQUIT, &act, NULL);
-
- /* if it is possible that we will deliver in the background, then we have
- to detach the child from this process group or it will die when the
- parent process exists, causing the mail to not get delivered. The
- problem here is that any error messages will get lost... */
- if (SendmailWait)
- setsid ();
+
+ /* now the second fork() */
if ((pid = fork ()) == 0)
{
- fd = open (msg, O_RDONLY, 0);
- if (fd < 0)
- _exit (127);
- dup2 (fd, 0);
- close (fd);
- if (SendmailWait)
+ /* "msg" will be opened as stdin */
+ if (open (msg, O_RDONLY, 0) < 0)
{
- /* write stdout to a tempfile */
- w = open (*tempfile, O_WRONLY | O_CREAT | O_EXCL, 0600);
- if (w < 0)
+ unlink (msg);
+ _exit (S_ERR);
+ }
+ unlink (msg);
+
+ if (SendmailWait >= 0)
+ {
+ /* *tempfile will be opened as stdout */
+ if (open (*tempfile, O_WRONLY | O_APPEND | O_CREAT | O_EXCL, 0600) < 0)
+ _exit (errno);
+ /* redirect stderr to *tempfile too */
+ if (dup (1) < 0)
_exit (errno);
- dup2 (w, 1);
- close (w);
}
- sigaction (SIGCHLD, &act, NULL);
+
execv (path, args);
- unlink (msg);
- _exit (127);
+ _exit (S_ERR);
}
else if (pid == -1)
{
unlink (msg);
- _exit (errno);
+ safe_free ((void **) tempfile);
+ _exit (S_ERR);
}
+ /* SendmailWait > 0: interrupt waitpid() after SendmailWait seconds
+ * SendmailWait = 0: wait forever
+ * SendmailWait < 0: don't wait
+ */
+ if (SendmailWait > 0)
+ {
+ Signals &= ~S_ALARM;
+ act.sa_handler = alarm_handler;
+#ifdef SA_INTERRUPT
+ /* need to make sure waitpid() is interrupted on SIGALRM */
+ act.sa_flags = SA_INTERRUPT;
+#else
+ act.sa_flags = 0;
+#endif
+ sigemptyset (&act.sa_mask);
+ sigaddset (&act.sa_mask, SIGTSTP);
+ sigaddset (&act.sa_mask, SIGINT);
+#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
+ sigaddset (&act.sa_mask, SIGWINCH);
+#endif
+ sigaction (SIGALRM, &act, &oldalrm);
+ alarm (SendmailWait);
+ }
+ else if (SendmailWait < 0)
+ _exit (0xff & EX_OK);
+
if (waitpid (pid, &st, 0) > 0)
{
- st = WIFEXITED (st) ? WEXITSTATUS (st) : 127;
- if (st == (EX_OK & 0xff) && SendmailWait)
+ st = WIFEXITED (st) ? WEXITSTATUS (st) : S_ERR;
+ if (SendmailWait && st == (0xff & EX_OK))
+ {
unlink (*tempfile); /* no longer needed */
+ safe_free ((void **) tempfile);
+ }
}
else
{
- st = 127;
- if (SendmailWait)
+ st = (SendmailWait > 0 && errno == EINTR && (Signals & S_ALARM)) ?
+ S_BKG : S_ERR;
+ if (SendmailWait > 0)
+ {
unlink (*tempfile);
+ safe_free ((void **) tempfile);
+ }
}
- unlink (msg);
- _exit (st);
- }
- /* SendmailWait > 0: SIGALRM will interrupt wait() after alrm seconds
- SendmailWait = 0: wait forever
- SendmailWait < 0: don't wait */
- if (SendmailWait > 0)
- {
- Signals &= ~S_ALARM;
- act.sa_handler = alarm_handler;
-#ifdef SA_INTERRUPT
- /* need to make sure the waitpid() is interrupted on SIGALRM */
- act.sa_flags = SA_INTERRUPT;
-#else
- act.sa_flags = 0;
-#endif
- sigaction (SIGALRM, &act, &oldalrm);
- alarm (SendmailWait);
- }
- if (SendmailWait >= 0)
- {
- w = waitpid (pid, &st, 0);
- err = errno; /* save error since it might be clobbered by another
- system call before we check the value */
- dprint (1, (debugfile, "send_msg(): waitpid returned %d (%s)\n", w,
- (w < 0 ? strerror (errno) : "OK")));
- }
- if (SendmailWait > 0)
- {
+
+ /* reset alarm; not really needed, but... */
alarm (0);
sigaction (SIGALRM, &oldalrm, NULL);
+
+ _exit (st);
}
- if (SendmailWait < 0 || ((Signals & S_ALARM) && w < 0 && err == EINTR))
- {
- /* add to list of children pids to reap */
- mutt_add_child_pid (pid);
- /* since there is no way for the user to be notified of error in this case,
- remove the temp file now */
- unlink (*tempfile);
- FREE (tempfile);
-#ifdef DEBUG
- if (Signals & S_ALARM)
- dprint (1, (debugfile, "send_msg(): received SIGALRM\n"));
- dprint (1, (debugfile, "send_msg(): putting sendmail in the background\n"));
-#endif
- st = EX_OK & 0xff;
- }
- else if (w < 0)
- {
- /* if err==EINTR, alarm interrupt, child status unknown,
- otherwise, there was an error invoking the child */
- st = (err == EINTR) ? (EX_OK & 0xff) : 127;
- }
+
+ sigprocmask (SIG_UNBLOCK, &set, NULL);
+
+ if (pid != -1 && waitpid (pid, &st, 0) > 0)
+ st = WIFEXITED (st) ? WEXITSTATUS (st) : S_ERR; /* return child status */
else
- {
-#ifdef DEBUG
- if (WIFEXITED (st))
- {
- dprint (1, (debugfile, "send_msg(): child exited %d\n", WEXITSTATUS (st)));
- }
- else
- {
- dprint (1, (debugfile, "send_msg(): child did not exit\n"));
- }
-#endif /* DEBUG */
- st = WIFEXITED (st) ? WEXITSTATUS (st) : -1; /* return child status */
- }
- sigaction (SIGINT, &oldint, NULL);
- sigaction (SIGQUIT, &oldquit, NULL);
- /* restore errno so that the caller can build an error message */
- errno = err;
+ st = S_ERR; /* error */
+
+ mutt_unblock_signals_system (1);
+
return (st);
}
@@ -1675,26 +1662,39 @@ mutt_invoke_sendmail (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc, /* recips */
args[argslen++] = NULL;
- if (!option (OPTNOCURSES))
- endwin ();
if ((i = send_msg (path, args, msg, &childout)) != (EX_OK & 0xff))
{
- const char *e = strsysexit(i);
-
- fprintf (stderr, _("Error sending message, child exited %d (%s).\n"), i, NONULL (e));
- if (childout)
- fprintf (stderr, _("Saved output of child process to %s.\n"), childout);
- if (!option (OPTNOCURSES))
+ if (i == S_BKG)
+ mutt_message (_("Delivery continued in background."));
+ else
{
- mutt_any_key_to_continue (NULL);
- mutt_error _("Error sending message.");
+ const char *e = strsysexit (i);
+
+ e = strsysexit (i);
+ mutt_error (_("Error sending message, child exited %d (%s)."), i, NONULL (e));
+ if (childout)
+ {
+ struct stat st;
+
+ if (stat (childout, &st) == 0 && st.st_size > 0)
+ mutt_do_pager (_("Output of the delivery process"), childout, 0, NULL);
+ }
}
}
+ else
+ unlink (childout);
+
FREE (&childout);
FREE (&path);
FREE (&s);
FREE (&args);
+ if (i == (EX_OK & 0xff))
+ i = 0;
+ else if (i == S_BKG)
+ i = 1;
+ else
+ i = -1;
return (i);
}
diff --git a/signal.c b/signal.c
index dba16da3..73996313 100644
--- a/signal.c
+++ b/signal.c
@@ -22,20 +22,19 @@
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
+#include <errno.h>
static sigset_t Sigset;
+static sigset_t SigsetSys;
static int IsEndwin = 0;
-static pid_t *PidList = NULL;
-static int PidListLen = 0;
-
/* Attempt to catch "ordinary" signals and shut down gracefully. */
-RETSIGTYPE mutt_exit_handler (int sig)
+RETSIGTYPE exit_handler (int sig)
{
curs_set (1);
endwin (); /* just to be safe */
#if SYS_SIGLIST_DECLARED
- printf(_("Caught %s... Exiting.\n"), sys_siglist[sig]);
+ printf(_("%s... Exiting.\n"), sys_siglist[sig]);
#else
#if (__sun__ && __svr4__)
printf(_("Caught %s... Exiting.\n"), _sys_siglist[sig]);
@@ -46,55 +45,19 @@ RETSIGTYPE mutt_exit_handler (int sig)
exit (0);
}
-static void reap_children (void)
+RETSIGTYPE chld_handler (int sig)
{
- int i, flag;
-
- /* at this point we don't know which child died */
- for (i = 0; i < PidListLen; i++)
- {
- if (PidList[i])
- {
- /* try to reap child "i" */
- flag = 0;
- while (waitpid (PidList[i], NULL, WNOHANG) > 0)
- flag = 1;
- /* remove child from list if reaped */
- if (flag)
- PidList[i] = 0;
- /* don't break here */
- }
- }
-}
-
-void mutt_add_child_pid (pid_t pid)
-{
- int i;
-
- for (i = 0; i < PidListLen; i++)
- {
- if (PidList[i] == 0)
- {
- PidList[i] = pid;
- break;
- }
- }
- if (i >= PidListLen)
- {
- /* quite a few children around... */
- safe_realloc ((void **) &PidList, (PidListLen += 2) * sizeof (pid_t));
- PidList[i++] = pid;
- for (; i < PidListLen; i++)
- PidList[i] = 0;
- }
+ /* empty */
}
RETSIGTYPE sighandler (int sig)
{
+ int save_errno = errno;
+
switch (sig)
{
case SIGTSTP: /* user requested a suspend */
- if(!option(OPTSUSPEND))
+ if (!option (OPTSUSPEND))
break;
IsEndwin = isendwin ();
curs_set (1);
@@ -113,14 +76,13 @@ RETSIGTYPE sighandler (int sig)
Signals |= S_SIGWINCH;
break;
#endif
+
case SIGINT:
Signals |= S_INTERRUPT;
break;
- case SIGCHLD:
- reap_children ();
- break;
}
+ errno = save_errno;
}
#ifdef USE_SLANG_CURSES
@@ -134,40 +96,42 @@ void mutt_signal_init (void)
{
struct sigaction act;
- memset (&act, 0, sizeof (struct sigaction));
-
+ sigemptyset (&act.sa_mask);
+ act.sa_flags = 0;
act.sa_handler = SIG_IGN;
sigaction (SIGPIPE, &act, NULL);
- act.sa_handler = mutt_exit_handler;
+ act.sa_handler = exit_handler;
sigaction (SIGTERM, &act, NULL);
sigaction (SIGHUP, &act, NULL);
+ sigaction (SIGQUIT, &act, NULL);
- act.sa_handler = sighandler;
-#ifdef SA_INTERRUPT
- /* POSIX.1 uses SA_RESTART, but SunOS 4.x uses this instead */
- act.sa_flags = SA_INTERRUPT;
+ /* we want to avoid race conditions */
+ sigaddset (&act.sa_mask, SIGTSTP);
+ sigaddset (&act.sa_mask, SIGINT);
+#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
+ sigaddset (&act.sa_mask, SIGWINCH);
#endif
- sigaction (SIGCONT, &act, NULL);
- sigaction (SIGINT, &act, NULL);
- /* SIGTSTP is the one signal in which we want to restart a system call if it
- * was interrupted in progress. This is especially important if we are in
- * the middle of a system() call, like if the user is editing a message.
- * Otherwise, the system() will exit when SIGCONT is received and Mutt will
- * resume even though the subprocess may not be finished.
- */
+ /* we also don't want to mess with interrupted system calls */
#ifdef SA_RESTART
act.sa_flags = SA_RESTART;
-#else
- act.sa_flags = 0;
#endif
- sigaction (SIGTSTP, &act, NULL);
+ act.sa_handler = sighandler;
+ sigaction (SIGCONT, &act, NULL);
+ sigaction (SIGTSTP, &act, NULL);
+ sigaction (SIGINT, &act, NULL);
#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
sigaction (SIGWINCH, &act, NULL);
#endif
+ /* POSIX doesn't allow us to ignore SIGCHLD,
+ * so we just install a dummy handler for it
+ */
+ act.sa_handler = chld_handler;
+ /* don't need to block any other signals here */
+ sigemptyset (&act.sa_mask);
/* we don't want to mess with stopped children */
act.sa_flags |= SA_NOCLDSTOP;
sigaction (SIGCHLD, &act, NULL);
@@ -190,11 +154,13 @@ void mutt_block_signals (void)
if (!option (OPTSIGNALSBLOCKED))
{
sigemptyset (&Sigset);
- sigaddset (&Sigset, SIGINT);
- sigaddset (&Sigset, SIGWINCH);
- sigaddset (&Sigset, SIGHUP);
sigaddset (&Sigset, SIGTERM);
+ sigaddset (&Sigset, SIGHUP);
sigaddset (&Sigset, SIGTSTP);
+ sigaddset (&Sigset, SIGINT);
+#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
+ sigaddset (&Sigset, SIGWINCH);
+#endif
sigprocmask (SIG_BLOCK, &Sigset, 0);
set_option (OPTSIGNALSBLOCKED);
}
@@ -214,15 +180,17 @@ void mutt_block_signals_system (void)
{
struct sigaction sa;
- if (! option (OPTSIGNALSBLOCKED))
+ if (! option (OPTSYSSIGNALSBLOCKED))
{
+ /* POSIX: ignore SIGINT and SIGQUIT & block SIGCHLD before exec */
sa.sa_handler = SIG_IGN;
sa.sa_flags = 0;
sigaction (SIGINT, &sa, NULL);
sigaction (SIGQUIT, &sa, NULL);
- sigemptyset (&Sigset);
- sigaddset (&Sigset, SIGCHLD);
- sigprocmask (SIG_BLOCK, &Sigset, 0);
+
+ sigemptyset (&SigsetSys);
+ sigaddset (&SigsetSys, SIGCHLD);
+ sigprocmask (SIG_BLOCK, &SigsetSys, 0);
set_option (OPTSIGNALSBLOCKED);
}
}
@@ -231,15 +199,36 @@ void mutt_unblock_signals_system (int catch)
{
struct sigaction sa;
- if (option (OPTSIGNALSBLOCKED))
+ if (option (OPTSYSSIGNALSBLOCKED))
{
+ sigprocmask (SIG_UNBLOCK, &SigsetSys, NULL);
+ sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
- sa.sa_handler = mutt_exit_handler;
- sigaction (SIGQUIT, &sa, NULL);
if (catch)
+ {
+ sa.sa_handler = exit_handler;
+ sigaction (SIGQUIT, &sa, NULL);
+
+ /* we want to avoid race conditions */
+ sigaddset (&sa.sa_mask, SIGTSTP);
+ sigaddset (&sa.sa_mask, SIGINT);
+#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
+ sigaddset (&sa.sa_mask, SIGWINCH);
+#endif
+ /* we also don't want to mess with interrupted system calls */
+#ifdef SA_RESTART
+ sa.sa_flags = SA_RESTART;
+#endif
sa.sa_handler = sighandler;
- sigaction (SIGINT, &sa, NULL);
- sigprocmask (SIG_UNBLOCK, &Sigset, NULL);
+ sigaction (SIGINT, &sa, NULL);
+ }
+ else
+ {
+ sa.sa_handler = SIG_DFL;
+ sigaction (SIGQUIT, &sa, NULL);
+ sigaction (SIGINT, &sa, NULL);
+ }
+
unset_option (OPTSIGNALSBLOCKED);
}
}
diff --git a/system.c b/system.c
index eb9a2aad..7bd1de29 100644
--- a/system.c
+++ b/system.c
@@ -28,50 +28,64 @@ int _mutt_system (const char *cmd, int flags)
{
int rc = -1;
struct sigaction act;
- struct sigaction oldcont;
struct sigaction oldtstp;
- struct sigaction oldint;
- struct sigaction oldquit;
- struct sigaction oldchld;
+ struct sigaction oldcont;
sigset_t set;
pid_t thepid;
- /* must block SIGCHLD and ignore SIGINT and SIGQUIT */
+ if (!cmd || !*cmd)
+ return (0);
+
+ /* must ignore SIGINT and SIGQUIT */
- act.sa_handler = SIG_IGN;
- act.sa_flags = 0;
- sigemptyset (&(act.sa_mask));
- sigaction (SIGINT, &act, &oldint);
- sigaction (SIGQUIT, &act, &oldquit);
+ mutt_block_signals_system ();
+
+ /* also don't want to be stopped right now */
if (flags & M_DETACH_PROCESS)
{
- act.sa_flags = SA_NOCLDSTOP;
- sigaction (SIGCHLD, &act, &oldchld);
- act.sa_flags = 0;
+ sigemptyset (&set);
+ sigaddset (&set, SIGTSTP);
+ sigprocmask (SIG_BLOCK, &set, NULL);
}
else
{
- sigemptyset (&set);
- sigaddset (&set, SIGCHLD);
- sigprocmask (SIG_BLOCK, &set, NULL);
+ 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);
}
- act.sa_handler = SIG_DFL;
- sigaction (SIGTSTP, &act, &oldtstp);
- sigaction (SIGCONT, &act, &oldcont);
-
if ((thepid = fork ()) == 0)
{
- /* reset signals for the child */
- sigaction (SIGINT, &act, NULL);
- sigaction (SIGQUIT, &act, NULL);
+ act.sa_flags = 0;
if (flags & M_DETACH_PROCESS)
{
+ int fd;
+
+ /* give up controlling terminal */
setsid ();
+
switch (fork ())
{
case 0:
+#if defined(OPEN_MAX)
+ for (fd = 0; fd < OPEN_MAX; fd++)
+ close (fd);
+#elif defined(_POSIX_OPEN_MAX)
+ for (fd = 0; fd < _POSIX_OPEN_MAX; fd++)
+ close (fd);
+#else
+ close (0);
+ close (1);
+ close (2);
+#endif
+ chdir ("/");
+ act.sa_handler = SIG_DFL;
sigaction (SIGCHLD, &act, NULL);
break;
@@ -82,30 +96,34 @@ int _mutt_system (const char *cmd, int flags)
_exit (0);
}
}
- else
- sigprocmask (SIG_UNBLOCK, &set, NULL);
+
+ /* 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 (EXECSHELL, "sh", "-c", cmd, NULL);
_exit (127); /* execl error */
}
else if (thepid != -1)
{
- /* wait for the child process to finish */
+ /* wait for the (first) child process to finish */
waitpid (thepid, &rc, 0);
}
+ sigaction (SIGCONT, &oldcont, NULL);
+ sigaction (SIGTSTP, &oldtstp, NULL);
+
/* reset SIGINT, SIGQUIT and SIGCHLD */
- sigaction (SIGINT, &oldint, NULL);
- sigaction (SIGQUIT, &oldquit, NULL);
+ mutt_unblock_signals_system (1);
if (flags & M_DETACH_PROCESS)
- sigaction (SIGCHLD, &oldchld, NULL);
- else
sigprocmask (SIG_UNBLOCK, &set, NULL);
- sigaction (SIGCONT, &oldcont, NULL);
- sigaction (SIGTSTP, &oldtstp, NULL);
-
- rc = WIFEXITED (rc) ? WEXITSTATUS (rc) : -1;
+ rc = (thepid != -1) ? (WIFEXITED (rc) ? WEXITSTATUS (rc) : -1) : -1;
return (rc);
}