Rocco Rutte:
[apps/madmutt.git] / filter.c
1 /*
2  * Copyright (C) 1996-2000 Michael R. Elkins.
3  * 
4  *     This program is free software; you can redistribute it and/or modify
5  *     it under the terms of the GNU General Public License as published by
6  *     the Free Software Foundation; either version 2 of the License, or
7  *     (at your option) any later version.
8  * 
9  *     This program is distributed in the hope that it will be useful,
10  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *     GNU General Public License for more details.
13  * 
14  *     You should have received a copy of the GNU General Public License
15  *     along with this program; if not, write to the Free Software
16  *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
17  */ 
18
19 #if HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 #include "mutt.h"
24
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <sys/wait.h>
28
29 /* Invokes a commmand on a pipe and optionally connects its stdin and stdout
30  * to the specified handles.
31  */
32 pid_t
33 mutt_create_filter_fd (const char *cmd, FILE **in, FILE **out, FILE **err,
34                        int fdin, int fdout, int fderr)
35 {
36   int pin[2], pout[2], perr[2], thepid;
37
38   if (in)
39   {
40     *in = 0;
41     if (pipe (pin) == -1)
42       return (-1);
43   }
44
45   if (out)
46   {
47     *out = 0;
48     if (pipe (pout) == -1)
49     {
50       if (in)
51       {
52         close (pin[0]);
53         close (pin[1]);
54       }
55       return (-1);
56     }
57   }
58
59   if (err)
60   {
61     *err = 0;
62     if (pipe (perr) == -1)
63     {
64       if (in)
65       {
66         close (pin[0]);
67         close (pin[1]);
68       }
69       if (out)
70       {
71         close (pout[0]);
72         close (pout[1]);
73       }
74       return (-1);
75     }
76   }
77
78   mutt_block_signals_system ();
79
80   if ((thepid = fork ()) == 0)
81   {
82     mutt_unblock_signals_system (0);
83
84     if (in)
85     {
86       close (pin[1]);
87       dup2 (pin[0], 0);
88       close (pin[0]);
89     }
90     else if (fdin != -1)
91     {
92       dup2 (fdin, 0);
93       close (fdin);
94     }
95
96     if (out)
97     {
98       close (pout[0]);
99       dup2 (pout[1], 1);
100       close (pout[1]);
101     }
102     else if (fdout != -1)
103     {
104       dup2 (fdout, 1);
105       close (fdout);
106     }
107
108     if (err)
109     {
110       close (perr[0]);
111       dup2 (perr[1], 2);
112       close (perr[1]);
113     }
114     else if (fderr != -1)
115     {
116       dup2 (fderr, 2);
117       close (fderr);
118     }
119
120     execl (EXECSHELL, "sh", "-c", cmd, NULL);
121     _exit (127);
122   }
123   else if (thepid == -1)
124   {
125     mutt_unblock_signals_system (1);
126
127     if (in)
128     {
129       close (pin[0]);
130       close (pin[1]);
131     }
132     
133     if (out)
134     {
135       close (pout[0]);
136       close (pout[1]);
137     }
138
139     if (err)
140     {
141       close (perr[0]);
142       close (perr[1]);
143     }
144
145     return (-1);
146   }
147
148   if (out)
149   {
150     close (pout[1]);
151     *out = fdopen (pout[0], "r");
152   }
153
154   if (in)
155   {
156     close (pin[0]);
157     *in = fdopen (pin[1], "w");
158   }
159
160   if (err)
161   {
162     close (perr[1]);
163     *err = fdopen (perr[0], "r");
164   }
165
166   return (thepid);
167 }
168
169 pid_t mutt_create_filter (const char *s, FILE **in, FILE **out, FILE **err)
170 {
171   return (mutt_create_filter_fd (s, in, out, err, -1, -1, -1));
172 }
173
174 int mutt_wait_filter (pid_t pid)
175 {
176   int rc;
177   
178   waitpid (pid, &rc, 0);
179   mutt_unblock_signals_system (1);
180   rc = WIFEXITED (rc) ? WEXITSTATUS (rc) : -1;
181   
182   return rc;
183 }