aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2005-09-21 18:25:05 +0000
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2005-09-21 18:25:05 +0000
commit9d7010ca86feff8fffdfecadf6554ca9aac268c1 (patch)
tree2132c3f716ef7eba3fea0d157fd8886fb3a0bc76
parentd4cffd1cc3437910393c319215d14bd2dcaa4df6 (diff)
downloadbusybox-w32-9d7010ca86feff8fffdfecadf6554ca9aac268c1.tar.gz
busybox-w32-9d7010ca86feff8fffdfecadf6554ca9aac268c1.tar.bz2
busybox-w32-9d7010ca86feff8fffdfecadf6554ca9aac268c1.zip
- add applet nohup(1)
-rw-r--r--coreutils/Config.in6
-rw-r--r--coreutils/Makefile.in1
-rw-r--r--coreutils/nohup.c188
-rw-r--r--include/applets.h3
-rw-r--r--include/usage.h7
5 files changed, 205 insertions, 0 deletions
diff --git a/coreutils/Config.in b/coreutils/Config.in
index 9e06c0d80..f92cd0d31 100644
--- a/coreutils/Config.in
+++ b/coreutils/Config.in
@@ -361,6 +361,12 @@ config CONFIG_NICE
361 help 361 help
362 nice runs a program with modified scheduling priority. 362 nice runs a program with modified scheduling priority.
363 363
364config CONFIG_NOHUP
365 bool "nohup"
366 default n
367 help
368 run a command immune to hangups, with output to a non-tty.
369
364config CONFIG_OD 370config CONFIG_OD
365 bool "od" 371 bool "od"
366 default n 372 default n
diff --git a/coreutils/Makefile.in b/coreutils/Makefile.in
index c46dcbacb..2dc9ebabc 100644
--- a/coreutils/Makefile.in
+++ b/coreutils/Makefile.in
@@ -60,6 +60,7 @@ COREUTILS-$(CONFIG_MKFIFO) += mkfifo.o
60COREUTILS-$(CONFIG_MKNOD) += mknod.o 60COREUTILS-$(CONFIG_MKNOD) += mknod.o
61COREUTILS-$(CONFIG_MV) += mv.o 61COREUTILS-$(CONFIG_MV) += mv.o
62COREUTILS-$(CONFIG_NICE) += nice.o 62COREUTILS-$(CONFIG_NICE) += nice.o
63COREUTILS-$(CONFIG_NOHUP) += nohup.o
63COREUTILS-$(CONFIG_OD) += od.o 64COREUTILS-$(CONFIG_OD) += od.o
64COREUTILS-$(CONFIG_PRINTENV) += printenv.o 65COREUTILS-$(CONFIG_PRINTENV) += printenv.o
65COREUTILS-$(CONFIG_PRINTF) += printf.o 66COREUTILS-$(CONFIG_PRINTF) += printf.o
diff --git a/coreutils/nohup.c b/coreutils/nohup.c
new file mode 100644
index 000000000..407cf00ea
--- /dev/null
+++ b/coreutils/nohup.c
@@ -0,0 +1,188 @@
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.
4
5 Licensed under the GPL v2, see the file LICENSE in this tarball.
6
7 */
8
9/* Written by Jim Meyering */
10/* initial busybox port by Bernhard Fischer */
11
12#include <stdio_ext.h> /* __fpending */
13#include <stdio.h>
14#include <unistd.h>
15#include <fcntl.h>
16#include <sys/types.h>
17#include <signal.h>
18#include <errno.h>
19
20#include "busybox.h"
21#define EXIT_CANNOT_INVOKE (126)
22#define NOHUP_FAILURE (127)
23#define EXIT_ENOENT NOHUP_FAILURE
24
25
26
27#if defined F_GETFD && defined F_SETFD
28static inline int set_cloexec_flag (int desc)
29{
30 int flags = fcntl (desc, F_GETFD, 0);
31 if (0 <= flags) {
32 if (flags == (flags |= FD_CLOEXEC) ||
33 fcntl (desc, F_SETFD, flags) != -1) {
34 return 0;
35 }
36 }
37 return -1;
38}
39#else
40#define set_cloexec_flag(desc) (0)
41#endif
42
43static int fd_reopen (int desired_fd, char const *file, int flags, mode_t mode)
44{
45 int fd;
46
47 close (desired_fd);
48 fd = open (file, flags, mode);
49 if (fd == desired_fd || fd < 0)
50 return fd;
51 else {
52 int fd2 = fcntl (fd, F_DUPFD, desired_fd);
53 int saved_errno = errno;
54 close (fd);
55 errno = saved_errno;
56 return fd2;
57 }
58}
59
60
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.
73
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.
77
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. */
81
82static void close_stdout (void)
83{
84 int prev_fail = ferror (stdout);
85 int none_pending = (0 == __fpending (stdout));
86 int fclose_fail = fclose (stdout);
87
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)
96 return;
97
98 bb_perror_msg_and_die(bb_msg_write_error);
99 }
100}
101
102
103int nohup_main (int argc, char **argv)
104{
105 int saved_stderr_fd;
106
107 if (argc < 2)
108 bb_show_usage();
109
110 bb_default_error_retval = NOHUP_FAILURE;
111
112 atexit (close_stdout);
113
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, "/dev/null", O_WRONLY, 0);
119
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,
126 O_CREAT | O_WRONLY | O_APPEND, S_IRUSR | S_IWUSR);
127
128 if (fd < 0) {
129 if ((in_home = getenv ("HOME")) != NULL) {
130 in_home = concat_path_file(in_home, file);
131 fd = fd_reopen (STDOUT_FILENO, in_home,
132 O_CREAT | O_WRONLY | O_APPEND, S_IRUSR | S_IWUSR);
133 }
134 if (fd < 0) {
135 bb_perror_msg("failed to open '%s'", file);
136 if (in_home)
137 bb_perror_msg("failed to open '%s'",in_home);
138 exit (NOHUP_FAILURE);
139 }
140 file = in_home;
141 }
142
143 umask (~(S_IRUSR | S_IWUSR));
144 bb_error_msg("appending output to '%s'", file);
145 if (ENABLE_FEATURE_CLEAN_UP)
146 free (in_home);
147 }
148
149 /* If standard error is a tty, redirect it to stdout. */
150 if (isatty (STDERR_FILENO)) {
151 /* Save a copy of stderr before redirecting, so we can use the original
152 if execve fails. It's no big deal if this dup fails. It might
153 not change anything, and at worst, it'll lead to suppression of
154 the post-failed-execve diagnostic. */
155 saved_stderr_fd = dup (STDERR_FILENO);
156
157 if (0 <= saved_stderr_fd && set_cloexec_flag (saved_stderr_fd) == -1)
158 bb_perror_msg_and_die("failed to set the copy"
159 "of stderr to close on exec");
160
161 if (dup2 (STDOUT_FILENO, STDERR_FILENO) < 0) {
162 if (errno != EBADF)
163 bb_perror_msg_and_die("failed to redirect standard error");
164 close (STDERR_FILENO);
165 }
166 } else
167 saved_stderr_fd = STDERR_FILENO;
168
169 signal (SIGHUP, SIG_IGN);
170
171 {
172 char **cmd = argv + 1;
173
174 execvp (*cmd, cmd);
175
176 /* The execve failed. Output a diagnostic to stderr only if:
177 - stderr was initially redirected to a non-tty, or
178 - stderr was initially directed to a tty, and we
179 can dup2 it to point back to that same tty.
180 In other words, output the diagnostic if possible, but only if
181 it will go to the original stderr. */
182 if (dup2 (saved_stderr_fd, STDERR_FILENO) == STDERR_FILENO)
183 bb_perror_msg("cannot run command '%s'",*cmd);
184
185 return (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
186 }
187}
188
diff --git a/include/applets.h b/include/applets.h
index 916597078..56ec0a6de 100644
--- a/include/applets.h
+++ b/include/applets.h
@@ -462,6 +462,9 @@
462#ifdef CONFIG_NICE 462#ifdef CONFIG_NICE
463 APPLET(nice, nice_main, _BB_DIR_BIN, _BB_SUID_NEVER) 463 APPLET(nice, nice_main, _BB_DIR_BIN, _BB_SUID_NEVER)
464#endif 464#endif
465#ifdef CONFIG_NOHUP
466 APPLET(nohup, nohup_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER)
467#endif
465#ifdef CONFIG_NSLOOKUP 468#ifdef CONFIG_NSLOOKUP
466 APPLET(nslookup, nslookup_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) 469 APPLET(nslookup, nslookup_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER)
467#endif 470#endif
diff --git a/include/usage.h b/include/usage.h
index 43b6f7048..f702729e5 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -2035,6 +2035,13 @@
2035 "Options:\n" \ 2035 "Options:\n" \
2036 "\t-n ADJUST\tAdjust the scheduling priority by ADJUST" 2036 "\t-n ADJUST\tAdjust the scheduling priority by ADJUST"
2037 2037
2038#define nohup_trivial_usage \
2039 "COMMAND [ARGS]"
2040#define nohup_full_usage \
2041 "run a command immune to hangups, with output to a non-tty"
2042#define nohup_example_usage \
2043 "$ nohup make &"
2044
2038#define nslookup_trivial_usage \ 2045#define nslookup_trivial_usage \
2039 "[HOST] [SERVER]" 2046 "[HOST] [SERVER]"
2040#define nslookup_full_usage \ 2047#define nslookup_full_usage \