summaryrefslogtreecommitdiff
path: root/src/cli_new.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cli_new.c')
-rw-r--r--src/cli_new.c85
1 files changed, 60 insertions, 25 deletions
diff --git a/src/cli_new.c b/src/cli_new.c
index 716c06f..a7cd122 100644
--- a/src/cli_new.c
+++ b/src/cli_new.c
@@ -5,9 +5,19 @@
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <unistd.h>
#include <fcntl.h>
+
+/* Workaround for features present in current kernel but
+ missing from old includes (glibc) in Debian Squeeze */
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 02000000
+#endif
+#ifndef F_DUPFD_CLOEXEC
+#define F_DUPFD_CLOEXEC 0x406
+#endif
+
#include <sys/wait.h>
-#include <unistd.h>
#include <dirent.h>
#include <limits.h>
#include <stdarg.h>
@@ -2043,9 +2053,9 @@ static int set_reference_environment(const char* var_reference,
/*** output ***/
+#define OUT_FD_MIN 16
int out_fd = -1;
FILE *out_stream = NULL;
-
int err_fd = -1;
FILE *err_stream = NULL;
int new_out_fd = -1;
@@ -2054,35 +2064,55 @@ int new_err_fd = -1;
int
initialize_output(const char *op)
{
- if ((out_fd = dup(STDOUT_FILENO)) == -1) {
- return -1;
- }
- if ((out_stream = fdopen(out_fd, "a")) == NULL) {
- return -1;
- }
- if ((err_fd = dup(STDOUT_FILENO)) == -1) {
- return -1;
- }
- if ((err_stream = fdopen(err_fd, "a")) == NULL) {
- return -1;
+ out_fd = fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, OUT_FD_MIN);
+ if (out_fd < 0)
+ goto err1;
+
+ out_stream = fdopen(out_fd, "w");
+ if (out_stream == NULL) {
+ close(out_fd);
+ goto err1;
}
- new_out_fd = open(LOGFILE_STDOUT, O_WRONLY | O_CREAT, 0660);
- new_err_fd = open(LOGFILE_STDERR, O_WRONLY | O_CREAT, 0660);
- if (new_out_fd == -1 || new_err_fd == -1) {
- return -1;
- }
- if ((lseek(new_out_fd, 0, SEEK_END) == ((off_t) -1))
- || (lseek(new_err_fd, 0, SEEK_END) == ((off_t) -1))) {
- return -1;
+ err_fd = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, OUT_FD_MIN);
+ if (err_fd < 0)
+ goto err2;
+
+ err_stream = fdopen(err_fd, "w");
+ if (err_stream == NULL) {
+ close(err_fd);
+ goto err2;
}
+
+ new_out_fd = open(LOGFILE_STDOUT,
+ O_WRONLY | O_CREAT | O_APPEND | O_CLOEXEC, 0660);
+ if (new_out_fd < 0)
+ goto err3;
+
+ new_err_fd = open(LOGFILE_STDERR,
+ O_WRONLY | O_CREAT | O_APPEND | O_CLOEXEC, 0660);
+ if (new_err_fd < 0)
+ goto err4;
+
if ((dup2(new_out_fd, STDOUT_FILENO) == -1)
- || (dup2(new_err_fd, STDERR_FILENO) == -1)) {
- return -1;
- }
+ || (dup2(new_err_fd, STDERR_FILENO) == -1))
+ goto err5;
cli_operation_name = op;
return 0;
+
+err5:
+ close(new_err_fd); new_err_fd = -1;
+err4:
+ close(new_out_fd); new_out_fd = -1;
+err3:
+ fclose(err_stream);
+ err_stream = NULL; err_fd = -1;
+err2:
+ fclose(out_stream);
+ out_stream = NULL; out_fd = -1;
+err1:
+ return -1;
}
int
@@ -2139,11 +2169,14 @@ system_out(char *cmd, const char *prepend_msg, boolean eloc)
int waited = 0;
int prepend = 1;
+ close(pfd[1]);
+
if (cpid == -1) {
+ close(pfd[0]);
+ fprintf(stderr, "fork failed\n");
return -1;
}
- close(pfd[1]);
while (1) {
int sret;
fd_set readfds;
@@ -2278,6 +2311,7 @@ system_out(char *cmd, const char *prepend_msg, boolean eloc)
/* XXX XXX XXX END emulating original "error" location handling */
if (out_stream != NULL) {
if (fwrite(out, count, 1, out_stream) != 1) {
+ close(pfd[0]);
return -1;
}
fflush(out_stream);
@@ -2311,6 +2345,7 @@ system_out(char *cmd, const char *prepend_msg, boolean eloc)
|| (ret = dup2(pfd[1], STDERR_FILENO)) < 0) {
exit(1);
}
+ close(pfd[1]);
char *eargs[] = { "sh", "-c", cmd, NULL };
execv("/bin/sh", eargs);
return -1; /* should not get here */