Andreas Krennmair:
[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 #include "mutt.h"
20
21 #include <unistd.h>
22 #include <stdlib.h>
23 #include <sys/wait.h>
24
25 /* Invokes a commmand on a pipe and optionally connects its stdin and stdout
26  * to the specified handles.
27  */
28 pid_t
29 mutt_create_filter_fd (const char *cmd, FILE **in, FILE **out, FILE **err,
30                        int fdin, int fdout, int fderr)
31 {
32   int pin[2], pout[2], perr[2], thepid;
33
34   if (in)
35   {
36     *in = 0;
37     if (pipe (pin) == -1)
38       return (-1);
39   }
40
41   if (out)
42   {
43     *out = 0;
44     if (pipe (pout) == -1)
45     {
46       if (in)
47       {
48         close (pin[0]);
49         close (pin[1]);
50       }
51       return (-1);
52     }
53   }
54
55   if (err)
56   {
57     *err = 0;
58     if (pipe (perr) == -1)
59     {
60       if (in)
61       {
62         close (pin[0]);
63         close (pin[1]);
64       }
65       if (out)
66       {
67         close (pout[0]);
68         close (pout[1]);
69       }
70       return (-1);
71     }
72   }
73
74   mutt_block_signals_system ();
75
76   if ((thepid = fork ()) == 0)
77   {
78     mutt_unblock_signals_system (0);
79
80     if (in)
81     {
82       close (pin[1]);
83       dup2 (pin[0], 0);
84       close (pin[0]);
85     }
86     else if (fdin != -1)
87     {
88       dup2 (fdin, 0);
89       close (fdin);
90     }
91
92     if (out)
93     {
94       close (pout[0]);
95       dup2 (pout[1], 1);
96       close (pout[1]);
97     }
98     else if (fdout != -1)
99     {
100       dup2 (fdout, 1);
101       close (fdout);
102     }
103
104     if (err)
105     {
106       close (perr[0]);
107       dup2 (perr[1], 2);
108       close (perr[1]);
109     }
110     else if (fderr != -1)
111     {
112       dup2 (fderr, 2);
113       close (fderr);
114     }
115
116     execl (EXECSHELL, "sh", "-c", cmd, NULL);
117     _exit (127);
118   }
119   else if (thepid == -1)
120   {
121     mutt_unblock_signals_system (1);
122
123     if (in)
124     {
125       close (pin[0]);
126       close (pin[1]);
127     }
128     
129     if (out)
130     {
131       close (pout[0]);
132       close (pout[1]);
133     }
134
135     if (err)
136     {
137       close (perr[0]);
138       close (perr[1]);
139     }
140
141     return (-1);
142   }
143
144   if (out)
145   {
146     close (pout[1]);
147     *out = fdopen (pout[0], "r");
148   }
149
150   if (in)
151   {
152     close (pin[0]);
153     *in = fdopen (pin[1], "w");
154   }
155
156   if (err)
157   {
158     close (perr[1]);
159     *err = fdopen (perr[0], "r");
160   }
161
162   return (thepid);
163 }
164
165 pid_t mutt_create_filter (const char *s, FILE **in, FILE **out, FILE **err)
166 {
167   return (mutt_create_filter_fd (s, in, out, err, -1, -1, -1));
168 }
169
170 int mutt_wait_filter (pid_t pid)
171 {
172   int rc;
173   
174   waitpid (pid, &rc, 0);
175   mutt_unblock_signals_system (1);
176   rc = WIFEXITED (rc) ? WEXITSTATUS (rc) : -1;
177   
178   return rc;
179 }