Fix compilation warnings in menu.c
[apps/madmutt.git] / system.c
1 /*
2  * Copyright notice from original mutt:
3  * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
4  *
5  * This file is part of mutt-ng, see http://www.muttng.org/.
6  * It's licensed under the GNU General Public License,
7  * please see the file GPL in the top level source directory.
8  */
9
10 #if HAVE_CONFIG_H
11 # include "config.h"
12 #endif
13
14 #include "mutt.h"
15 #include <imap/imap.h>
16
17 #include <errno.h>
18 #include <stdlib.h>
19 #include <signal.h>
20 #include <string.h>
21 #include <sys/wait.h>
22 #include <unistd.h>
23
24 int _mutt_system (const char *cmd, int flags)
25 {
26   int rc = -1;
27   struct sigaction act;
28   struct sigaction oldtstp;
29   struct sigaction oldcont;
30   sigset_t set;
31   pid_t thepid;
32
33   if (!cmd || !*cmd)
34     return (0);
35
36   /* must ignore SIGINT and SIGQUIT */
37
38   mutt_block_signals_system ();
39
40   /* also don't want to be stopped right now */
41   if (flags & M_DETACH_PROCESS) {
42     sigemptyset (&set);
43     sigaddset (&set, SIGTSTP);
44     sigprocmask (SIG_BLOCK, &set, NULL);
45   }
46   else {
47     act.sa_handler = SIG_DFL;
48     /* we want to restart the waitpid() below */
49 #ifdef SA_RESTART
50     act.sa_flags = SA_RESTART;
51 #endif
52     sigemptyset (&act.sa_mask);
53     sigaction (SIGTSTP, &act, &oldtstp);
54     sigaction (SIGCONT, &act, &oldcont);
55   }
56
57   if ((thepid = fork ()) == 0) {
58     act.sa_flags = 0;
59
60     if (flags & M_DETACH_PROCESS) {
61       int fd;
62
63       /* give up controlling terminal */
64       setsid ();
65
66       switch (fork ()) {
67       case 0:
68 #if defined(OPEN_MAX)
69         for (fd = 0; fd < OPEN_MAX; fd++)
70           close (fd);
71 #elif defined(_POSIX_OPEN_MAX)
72         for (fd = 0; fd < _POSIX_OPEN_MAX; fd++)
73           close (fd);
74 #else
75         close (0);
76         close (1);
77         close (2);
78 #endif
79         chdir ("/");
80         act.sa_handler = SIG_DFL;
81         sigaction (SIGCHLD, &act, NULL);
82         break;
83
84       case -1:
85         _exit (127);
86
87       default:
88         _exit (0);
89       }
90     }
91
92     /* reset signals for the child; not really needed, but... */
93     mutt_unblock_signals_system (0);
94     act.sa_handler = SIG_DFL;
95     act.sa_flags = 0;
96     sigemptyset (&act.sa_mask);
97     sigaction (SIGTERM, &act, NULL);
98     sigaction (SIGTSTP, &act, NULL);
99     sigaction (SIGCONT, &act, NULL);
100
101     execl ("/bin/sh", "sh", "-c", cmd, NULL);
102     _exit (127);                /* execl error */
103   }
104   else if (thepid != -1) {
105     rc = imap_wait_keepalive (thepid);
106   }
107
108   sigaction (SIGCONT, &oldcont, NULL);
109   sigaction (SIGTSTP, &oldtstp, NULL);
110
111   /* reset SIGINT, SIGQUIT and SIGCHLD */
112   mutt_unblock_signals_system (1);
113   if (flags & M_DETACH_PROCESS)
114     sigprocmask (SIG_UNBLOCK, &set, NULL);
115
116   rc = (thepid != -1) ? (WIFEXITED (rc) ? WEXITSTATUS (rc) : -1) : -1;
117
118   return (rc);
119 }