remove spurious SPACEs before TABs
[coreutils.git] / src / nohup.c
blob6d006f216e128973c3b290a84748254e84111bc2
1 /* nohup -- run a command immume to hangups, with output to a non-tty
2 Copyright (C) 2003 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Written by Jim Meyering */
20 #include <config.h>
21 #include <stdio.h>
22 #include <sys/types.h>
23 #include <signal.h>
25 #include "system.h"
27 #include "error.h"
28 #include "long-options.h"
29 #include "path-concat.h"
30 #include "quote.h"
32 #define PROGRAM_NAME "nohup"
34 #define AUTHORS "Jim Meyering"
36 /* Exit statuses. */
37 enum
39 /* `nohup' found the specified command but failed to invoke it. */
40 NOHUP_FOUND_BUT_CANNOT_INVOKE = 126,
42 /* `nohup' itself failed, or did not find the specified command. */
43 NOHUP_FAILURE = 127
46 char *program_name;
48 void
49 usage (int status)
51 if (status != 0)
52 fprintf (stderr, _("Try `%s --help' for more information.\n"),
53 program_name);
54 else
56 printf (_("\
57 Usage: %s COMMAND [ARG]...\n\
58 or: %s OPTION\n\
59 "),
60 program_name, program_name);
62 fputs (_("\
63 Run COMMAND, ignoring hangup signals.\n\
64 \n\
65 "), stdout);
66 fputs (HELP_OPTION_DESCRIPTION, stdout);
67 fputs (VERSION_OPTION_DESCRIPTION, stdout);
68 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
70 exit (status);
73 int
74 main (int argc, char **argv)
76 int fd;
77 int saved_stderr_fd = -1;
78 int stderr_isatty;
80 initialize_main (&argc, &argv);
81 program_name = argv[0];
82 setlocale (LC_ALL, "");
83 bindtextdomain (PACKAGE, LOCALEDIR);
84 textdomain (PACKAGE);
86 atexit (close_stdout);
88 parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
89 usage, AUTHORS, (char const *) NULL);
91 /* The above handles --help and --version.
92 Now, handle `--'. */
93 if (argc > 1 && STREQ (argv[1], "--"))
95 --argc;
96 ++argv;
99 if (argc <= 1)
101 error (0, 0, _("too few arguments"));
102 usage (NOHUP_FAILURE);
105 /* If standard output is a tty, redirect it (appending) to a file.
106 First try nohup.out, then $HOME/nohup.out. */
107 if (isatty (STDOUT_FILENO))
109 char *in_home = NULL;
110 char const *file = "nohup.out";
111 int flags = O_CREAT | O_WRONLY | O_APPEND;
112 mode_t mode = S_IRUSR | S_IWUSR;
113 int saved_errno;
115 fd = open (file, flags, mode);
116 if (fd == -1)
118 saved_errno = errno;
119 in_home = path_concat (getenv ("HOME"), file, NULL);
120 fd = open (in_home, flags, mode);
121 if (fd == -1)
123 int saved_errno2 = errno;
124 error (0, saved_errno, _("failed to open %s"), quote (file));
125 error (0, saved_errno2, _("failed to open %s"), quote (in_home));
126 exit (NOHUP_FAILURE);
128 file = in_home;
131 /* Redirect standard output to the file. */
132 if (dup2 (fd, STDOUT_FILENO) == -1)
133 error (NOHUP_FAILURE, errno, _("failed to redirect standard output"));
135 error (0, 0, _("appending output to %s"), quote (file));
136 if (in_home)
137 free (in_home);
139 else
141 fd = STDOUT_FILENO;
144 /* If stderr is on a tty, redirect it to stdout. */
145 if ((stderr_isatty = isatty (STDERR_FILENO)))
147 /* Save a copy of stderr before redirecting, so we can use the original
148 if execve fails. It's no big deal if this dup fails. It might
149 not change anything, and at worst, it'll lead to suppression of
150 the post-failed-execve diagnostic. */
151 saved_stderr_fd = dup (STDERR_FILENO);
153 if (dup2 (fd, STDERR_FILENO) == -1)
154 error (NOHUP_FAILURE, errno, _("failed to redirect standard error"));
157 /* Ignore hang-up signals. */
159 #ifdef _POSIX_SOURCE
160 struct sigaction sigact;
161 sigact.sa_handler = SIG_IGN;
162 sigemptyset (&sigact.sa_mask);
163 sigact.sa_flags = 0;
164 sigaction (SIGHUP, &sigact, NULL);
165 #else
166 signal (SIGHUP, SIG_IGN);
167 #endif
171 int exit_status;
172 int saved_errno;
173 char **cmd = argv + 1;
175 execvp (*cmd, cmd);
176 exit_status = (errno == ENOENT
177 ? NOHUP_FAILURE
178 : NOHUP_FOUND_BUT_CANNOT_INVOKE);
179 saved_errno = errno;
181 /* The execve failed. Output a diagnostic to stderr only if:
182 - stderr was initially redirected to a non-tty, or
183 - stderr was initially directed to a tty, and we've
184 just dup2'd it to point back to that same tty.
185 In other words, output the diagnostic if possible, but not if
186 it'd go to nohup.out. */
187 if ( ! stderr_isatty
188 || (saved_stderr_fd != -1
189 && dup2 (saved_stderr_fd, STDERR_FILENO) != -1))
190 error (0, saved_errno, _("cannot run command %s"), quote (*cmd));
192 exit (exit_status);