]> granicus.if.org Git - mutt/blob - filter.c
Convert smime_invoke_import() and helpers to use buffer pool.
[mutt] / 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18
19 #if HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 #include "mutt.h"
24 #include "mutt_curses.h"
25 #ifdef USE_IMAP
26 # include "imap.h"
27 #endif
28
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <sys/wait.h>
32
33 /* Invokes a command on a pipe and optionally connects its stdin and stdout
34  * to the specified handles.
35  */
36 pid_t
37 mutt_create_filter_fd (const char *cmd, FILE **in, FILE **out, FILE **err,
38                        int fdin, int fdout, int fderr)
39 {
40   int pin[2], pout[2], perr[2], thepid;
41   char columns[11];
42
43   if (in)
44   {
45     *in = 0;
46     if (pipe (pin) == -1)
47       return (-1);
48   }
49
50   if (out)
51   {
52     *out = 0;
53     if (pipe (pout) == -1)
54     {
55       if (in)
56       {
57         close (pin[0]);
58         close (pin[1]);
59       }
60       return (-1);
61     }
62   }
63
64   if (err)
65   {
66     *err = 0;
67     if (pipe (perr) == -1)
68     {
69       if (in)
70       {
71         close (pin[0]);
72         close (pin[1]);
73       }
74       if (out)
75       {
76         close (pout[0]);
77         close (pout[1]);
78       }
79       return (-1);
80     }
81   }
82
83   mutt_block_signals_system ();
84
85   if ((thepid = fork ()) == 0)
86   {
87     mutt_unblock_signals_system (0);
88
89     if (in)
90     {
91       close (pin[1]);
92       dup2 (pin[0], 0);
93       close (pin[0]);
94     }
95     else if (fdin != -1)
96     {
97       dup2 (fdin, 0);
98       close (fdin);
99     }
100
101     if (out)
102     {
103       close (pout[0]);
104       dup2 (pout[1], 1);
105       close (pout[1]);
106     }
107     else if (fdout != -1)
108     {
109       dup2 (fdout, 1);
110       close (fdout);
111     }
112
113     if (err)
114     {
115       close (perr[0]);
116       dup2 (perr[1], 2);
117       close (perr[1]);
118     }
119     else if (fderr != -1)
120     {
121       dup2 (fderr, 2);
122       close (fderr);
123     }
124
125     if (MuttIndexWindow && (MuttIndexWindow->cols > 0))
126     {
127       snprintf (columns, sizeof (columns), "%d", MuttIndexWindow->cols);
128       mutt_envlist_set ("COLUMNS", columns, 1);
129     }
130
131     execle (EXECSHELL, "sh", "-c", cmd, NULL, mutt_envlist ());
132     _exit (127);
133   }
134   else if (thepid == -1)
135   {
136     mutt_unblock_signals_system (1);
137
138     if (in)
139     {
140       close (pin[0]);
141       close (pin[1]);
142     }
143
144     if (out)
145     {
146       close (pout[0]);
147       close (pout[1]);
148     }
149
150     if (err)
151     {
152       close (perr[0]);
153       close (perr[1]);
154     }
155
156     return (-1);
157   }
158
159   if (out)
160   {
161     close (pout[1]);
162     *out = fdopen (pout[0], "r");
163   }
164
165   if (in)
166   {
167     close (pin[0]);
168     *in = fdopen (pin[1], "w");
169   }
170
171   if (err)
172   {
173     close (perr[1]);
174     *err = fdopen (perr[0], "r");
175   }
176
177   return (thepid);
178 }
179
180 pid_t mutt_create_filter (const char *s, FILE **in, FILE **out, FILE **err)
181 {
182   return (mutt_create_filter_fd (s, in, out, err, -1, -1, -1));
183 }
184
185 int mutt_wait_filter (pid_t pid)
186 {
187   int rc;
188
189   waitpid (pid, &rc, 0);
190   mutt_unblock_signals_system (1);
191   rc = WIFEXITED (rc) ? WEXITSTATUS (rc) : -1;
192
193   return rc;
194 }
195
196 /*
197  * This is used for filters that are actually interactive commands
198  * with input piped in: e.g. in mutt_view_attachment(), a mailcap
199  * entry without copiousoutput _and_ without a %s.
200  *
201  * For those cases, we treat it like a blocking system command, and
202  * poll IMAP to keep connections open.
203  */
204 int mutt_wait_interactive_filter (pid_t pid)
205 {
206   int rc;
207
208 #ifndef USE_IMAP
209   waitpid (pid, &rc, 0);
210 #else
211   rc = imap_wait_keepalive (pid);
212 #endif
213   mutt_unblock_signals_system (1);
214   rc = WIFEXITED (rc) ? WEXITSTATUS (rc) : -1;
215
216   return rc;
217 }