1 /* vi: set sw=4 ts=4: */
2 /* nohup -- run a command immune to hangups, with output to a non-tty
3 Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
5 Licensed under the GPL v2, see the file LICENSE in this tarball.
9 /* Written by Jim Meyering */
10 /* initial busybox port by Bernhard Fischer */
12 #include <stdio_ext.h> /* __fpending */
16 #include <sys/types.h>
21 #define EXIT_CANNOT_INVOKE (126)
22 #define NOHUP_FAILURE (127)
23 #define EXIT_ENOENT NOHUP_FAILURE
27 #if defined F_GETFD && defined F_SETFD
28 static inline int set_cloexec_flag (int desc)
30 int flags = fcntl (desc, F_GETFD, 0);
32 if (flags == (flags |= FD_CLOEXEC) ||
33 fcntl (desc, F_SETFD, flags) != -1) {
40 #define set_cloexec_flag(desc) (0)
43 static int fd_reopen (int desired_fd, char const *file, int flags)
48 fd = open (file, flags | O_WRONLY, S_IRUSR | S_IWUSR);
49 if (fd == desired_fd || fd < 0)
52 int fd2 = fcntl (fd, F_DUPFD, desired_fd);
53 int saved_errno = errno;
61 /* Close standard output, exiting with status 'exit_failure' on failure.
62 If a program writes *anything* to stdout, that program should close
63 stdout and make sure that it succeeds before exiting. Otherwise,
64 suppose that you go to the extreme of checking the return status
65 of every function that does an explicit write to stdout. The last
66 printf can succeed in writing to the internal stream buffer, and yet
67 the fclose(stdout) could still fail (due e.g., to a disk full error)
68 when it tries to write out that buffered data. Thus, you would be
69 left with an incomplete output file and the offending program would
70 exit successfully. Even calling fflush is not always sufficient,
71 since some file systems (NFS and CODA) buffer written/flushed data
72 until an actual close call.
74 Besides, it's wasteful to check the return value from every call
75 that writes to stdout -- just let the internal stream state record
76 the failure. That's what the ferror test is checking below.
78 It's important to detect such failures and exit nonzero because many
79 tools (most notably `make' and other build-management systems) depend
80 on being able to detect failure in other tools via their exit status. */
82 static void close_stdout (void)
84 int prev_fail = ferror (stdout);
85 int none_pending = (0 == __fpending (stdout));
86 int fclose_fail = fclose (stdout);
88 if (prev_fail || fclose_fail) {
89 /* If ferror returned zero, no data remains to be flushed, and we'd
90 otherwise fail with EBADF due to a failed fclose, then assume that
91 it's ok to ignore the fclose failure. That can happen when a
92 program like cp is invoked like this `cp a b >&-' (i.e., with
93 stdout closed) and doesn't generate any output (hence no previous
94 error and nothing to be flushed). */
95 if ((fclose_fail ? errno : 0) == EBADF && !prev_fail && none_pending)
98 bb_perror_msg_and_die(bb_msg_write_error);
103 int nohup_main (int argc, char **argv)
110 bb_default_error_retval = NOHUP_FAILURE;
112 atexit (close_stdout);
114 /* If standard input is a tty, replace it with /dev/null.
115 Note that it is deliberately opened for *writing*,
116 to ensure any read evokes an error. */
117 if (isatty (STDIN_FILENO))
118 fd_reopen (STDIN_FILENO, bb_dev_null, 0);
120 /* If standard output is a tty, redirect it (appending) to a file.
121 First try nohup.out, then $HOME/nohup.out. */
122 if (isatty (STDOUT_FILENO)) {
123 char *in_home = NULL;
124 char const *file = "nohup.out";
125 int fd = fd_reopen (STDOUT_FILENO, file, O_CREAT | O_APPEND);
128 if ((in_home = getenv ("HOME")) != NULL) {
129 in_home = concat_path_file(in_home, file);
130 fd = fd_reopen (STDOUT_FILENO, in_home, O_CREAT | O_APPEND);
133 bb_perror_msg("failed to open '%s'", file);
135 bb_perror_msg("failed to open '%s'",in_home);
136 return (NOHUP_FAILURE);
141 umask (~(S_IRUSR | S_IWUSR));
142 bb_error_msg("appending output to '%s'", file);
143 if (ENABLE_FEATURE_CLEAN_UP)
147 /* If standard error is a tty, redirect it to stdout. */
148 if (isatty (STDERR_FILENO)) {
149 /* Save a copy of stderr before redirecting, so we can use the original
150 if execve fails. It's no big deal if this dup fails. It might
151 not change anything, and at worst, it'll lead to suppression of
152 the post-failed-execve diagnostic. */
153 saved_stderr_fd = dup (STDERR_FILENO);
155 if (0 <= saved_stderr_fd && set_cloexec_flag (saved_stderr_fd) == -1)
156 bb_perror_msg_and_die("failed to set the copy"
157 "of stderr to close on exec");
159 if (dup2 (STDOUT_FILENO, STDERR_FILENO) < 0) {
161 bb_perror_msg_and_die("failed to redirect standard error");
162 close (STDERR_FILENO);
165 saved_stderr_fd = STDERR_FILENO;
167 signal (SIGHUP, SIG_IGN);
170 char **cmd = argv + 1;
174 /* The execve failed. Output a diagnostic to stderr only if:
175 - stderr was initially redirected to a non-tty, or
176 - stderr was initially directed to a tty, and we
177 can dup2 it to point back to that same tty.
178 In other words, output the diagnostic if possible, but only if
179 it will go to the original stderr. */
180 if (dup2 (saved_stderr_fd, STDERR_FILENO) == STDERR_FILENO)
181 bb_perror_msg("cannot run command '%s'",*cmd);
183 return (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);