NeoMutt
2025-12-11-1039-g550ac6
Teaching an old dog new tricks
DOXYGEN
Toggle main menu visibility
Loading...
Searching...
No Matches
filter.c
Go to the documentation of this file.
1
23
29
30
#include "config.h"
31
#include <stdbool.h>
32
#include <stdlib.h>
33
#include <sys/wait.h>
34
#include <unistd.h>
35
#include "
filter.h
"
36
#include "
signal2.h
"
37
62
pid_t
filter_create_fd
(
const
char
*cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err,
63
int
fdin,
int
fdout,
int
fderr,
char
**envlist)
64
{
65
int
pin[2] = { 0 };
66
int
pout[2] = { 0 };
67
int
perr[2] = { 0 };
68
int
pid;
69
70
/* Create pipes for each requested I/O stream (stdin, stdout, stderr).
71
* On failure, clean up any already-created pipes before returning. */
72
if
(fp_in)
73
{
74
*fp_in = NULL;
75
if
(pipe(pin) == -1)
76
return
-1;
77
}
78
79
if
(fp_out)
80
{
81
*fp_out = NULL;
82
if
(pipe(pout) == -1)
83
{
84
if
(fp_in)
85
{
86
close(pin[0]);
87
close(pin[1]);
88
}
89
return
-1;
90
}
91
}
92
93
if
(fp_err)
94
{
95
*fp_err = NULL;
96
if
(pipe(perr) == -1)
97
{
98
if
(fp_in)
99
{
100
close(pin[0]);
101
close(pin[1]);
102
}
103
if
(fp_out)
104
{
105
close(pout[0]);
106
close(pout[1]);
107
}
108
return
-1;
109
}
110
}
111
112
/* Block signals around fork to prevent child from inheriting pending signals */
113
mutt_sig_block_system
();
114
115
pid = fork();
116
if
(pid == 0)
117
{
118
/* Child process: redirect pipe ends to stdin/stdout/stderr via dup2(),
119
* or use the caller-supplied file descriptors as fallback */
120
mutt_sig_unblock_system
(
false
);
121
mutt_sig_reset_child_signals
();
122
123
if
(fp_in)
124
{
125
close(pin[1]);
126
dup2(pin[0], 0);
127
close(pin[0]);
128
}
129
else
if
(fdin != -1)
130
{
131
dup2(fdin, 0);
132
close(fdin);
133
}
134
135
if
(fp_out)
136
{
137
close(pout[0]);
138
dup2(pout[1], 1);
139
close(pout[1]);
140
}
141
else
if
(fdout != -1)
142
{
143
dup2(fdout, 1);
144
close(fdout);
145
}
146
147
if
(fp_err)
148
{
149
close(perr[0]);
150
dup2(perr[1], 2);
151
close(perr[1]);
152
}
153
else
if
(fderr != -1)
154
{
155
dup2(fderr, 2);
156
close(fderr);
157
}
158
159
execle(
EXEC_SHELL
,
"sh"
,
"-c"
, cmd, NULL, envlist);
160
_exit(127);
161
}
162
else
if
(pid == -1)
163
{
164
/* Fork failed: clean up all pipe file descriptors */
165
mutt_sig_unblock_system
(
true
);
166
167
if
(fp_in)
168
{
169
close(pin[0]);
170
close(pin[1]);
171
}
172
173
if
(fp_out)
174
{
175
close(pout[0]);
176
close(pout[1]);
177
}
178
179
if
(fp_err)
180
{
181
close(perr[0]);
182
close(perr[1]);
183
}
184
185
return
-1;
186
}
187
188
/* Parent process: close the child's end of each pipe and wrap
189
* the parent's end in a FILE stream for the caller */
190
if
(fp_out)
191
{
192
close(pout[1]);
193
*fp_out = fdopen(pout[0],
"r"
);
194
}
195
196
if
(fp_in)
197
{
198
close(pin[0]);
199
*fp_in = fdopen(pin[1],
"w"
);
200
}
201
202
if
(fp_err)
203
{
204
close(perr[1]);
205
*fp_err = fdopen(perr[0],
"r"
);
206
}
207
208
return
pid;
209
}
210
220
pid_t
filter_create
(
const
char
*cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err,
char
**envlist)
221
{
222
return
filter_create_fd
(cmd, fp_in, fp_out, fp_err, -1, -1, -1, envlist);
223
}
224
231
int
filter_wait
(pid_t pid)
232
{
233
int
rc = 0;
234
235
waitpid(pid, &rc, 0);
236
mutt_sig_unblock_system
(
true
);
237
rc = WIFEXITED(rc) ? WEXITSTATUS(rc) : -1;
238
239
return
rc;
240
}
filter_wait
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition
filter.c:231
filter_create_fd
pid_t filter_create_fd(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, int fdin, int fdout, int fderr, char **envlist)
Run a command on a pipe (optionally connect stdin/stdout).
Definition
filter.c:62
filter_create
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, char **envlist)
Set up filter program.
Definition
filter.c:220
filter.h
Pass files through external commands (filters).
EXEC_SHELL
#define EXEC_SHELL
Default shell to use for executing commands.
Definition
filter.h:30
signal2.h
Signal handling.
mutt_sig_reset_child_signals
void mutt_sig_reset_child_signals(void)
Reset ignored signals back to the default.
Definition
signal.c:336
mutt_sig_block_system
void mutt_sig_block_system(void)
Block signals before calling exec().
Definition
signal.c:260
mutt_sig_unblock_system
void mutt_sig_unblock_system(bool restore)
Restore previously blocked signals.
Definition
signal.c:284