1 /* $NetBSD: mime_child.c,v 1.6 2007/10/29 23:20:38 christos Exp $ */
4 * Copyright (c) 2006 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/cdefs.h>
37 __RCSID("$NetBSD: mime_child.c,v 1.6 2007/10/29 23:20:38 christos Exp $");
38 #endif /* not __lint__ */
52 #include "mime_child.h"
56 * This module contains the core routines used by mime modules that
57 * need to fork children. Nothing else in the mime modules should be
58 * doing a pipe(), fork(), or a call to any popen functions that do.
59 * These routines are tied to the file registry in popen.c and hence
60 * share much of popen code.
67 get_cmd_flags(const char *cmd
, const char **cmd_start
)
73 for (cp
= cmd
; cp
&& *cp
; cp
++)
76 flags
|= CMD_FLAG_ALTERNATIVE
;
79 flags
|= CMD_FLAG_NO_DECODE
;
82 flags
|= CMD_FLAG_SHELLCMD
;
96 prepare_pipe(sigset_t
*nset
, int p
[2])
101 (void)fcntl(p
[READ
], F_SETFD
, FD_CLOEXEC
);
102 (void)fcntl(p
[WRITE
], F_SETFD
, FD_CLOEXEC
);
104 * We _must_ ignore SIGINT and SIGPIPE or the child
105 * will end up in our earlier handlers.
107 (void)sigemptyset(nset
);
108 (void)sigaddset(nset
, SIGINT
);
109 (void)sigaddset(nset
, SIGPIPE
);
110 (void)sigaddset(nset
, SIGHUP
);
111 (void)sigaddset(nset
, SIGTSTP
);
112 (void)sigaddset(nset
, SIGTTOU
);
113 (void)sigaddset(nset
, SIGTTIN
);
120 mime_run_command(const char *cmd
, FILE *fo
)
131 flags
= get_cmd_flags(cmd
, &cmd
);
132 if (fo
== NULL
) /* no output file, just return the flags! */
135 if ((flags
& CMD_FLAG_SHELLCMD
) != 0) { /* run command under the shell */
138 if ((shellcmd
= value(ENAME_SHELL
)) == NULL
)
139 shellcmd
= __UNCONST(_PATH_CSHELL
);
140 (void)sasprintf(&cp
, "%s -c '%s'", shellcmd
, cmd
);
143 if (prepare_pipe(&nset
, p
) != 0) {
144 warn("mime_run_command: prepare_pipe");
145 return flags
; /* XXX - this or -1? */
147 flush_files(fo
, 0); /* flush fo, all registered files, and stdout */
149 switch (pid
= start_command(cmd
, &nset
, p
[READ
], fileno(fo
), NULL
)) {
151 /* start_command already did a warn(). */
152 warnx("mime_run_command: %s", cmd
); /* tell a bit more */
153 (void)close(p
[READ
]);
154 (void)close(p
[WRITE
]);
155 return flags
; /* XXX - this or -1? */
158 assert(/*CONSTCOND*/ 0); /* a real coding error! */
161 default: /* parent */
162 (void)close(p
[READ
]);
164 nfo
= fdopen(p
[WRITE
], "w");
166 warn("mime_run_command: fdopen");
167 (void)close(p
[WRITE
]);
171 register_file(nfo
, 1, pid
);
178 mime_run_function(void (*fn
)(FILE *, FILE *, void *), FILE *fo
, void *cookie
)
185 if (prepare_pipe(&nset
, p
) != 0) {
186 warn("mime_run_function: pipe");
189 flush_files(fo
, 0); /* flush fo, all registered files, and stdout */
191 switch (pid
= fork()) {
193 warn("mime_run_function: fork");
194 (void)close(p
[READ
]);
195 (void)close(p
[WRITE
]);
199 (void)close(p
[WRITE
]);
200 prepare_child(&nset
, p
[READ
], fileno(fo
));
201 fn(stdin
, stdout
, cookie
);
202 (void)fflush(stdout
);
206 default: /* parent */
207 (void)close(p
[READ
]);
208 nfo
= fdopen(p
[WRITE
], "w");
210 warn("run_function: fdopen");
211 (void)close(p
[WRITE
]);
214 register_file(nfo
, 1, pid
);
219 #endif /* MIME_SUPPORT */