From e896ec1ef5ec6da70c49aeb9e0c7b0726fc73f35 Mon Sep 17 00:00:00 2001 From: Mike Barcroft Date: Thu, 19 Jul 2001 21:25:10 +0000 Subject: [PATCH] o Integrate security enhancements from OpenBSD. - Don't assume environment variable HOME is not NULL. o Integrate standards compliance from NetBSD. - Allow -- before the command. - Blocking SIGQUIT isn't standards compliant. - Proper exit(3) levels. - Actually append to nohup.out (as documented and required by standard) instead of clobbering it. o Remove some FreeBSD specific access(2) cruft (relating to incorrect appending). o Document the fact that two or more instances of nohup can append to the same file. o Constify; Staticize functions; Set WARNS?=2 Reviewed by: bde Approved by: des Obtained from: NetBSD, OpenBSD MFC after: 9 days --- usr.bin/nohup/nohup.1 | 36 +++++++++++++------ usr.bin/nohup/nohup.c | 80 ++++++++++++++++++++++++++----------------- 2 files changed, 74 insertions(+), 42 deletions(-) diff --git a/usr.bin/nohup/nohup.1 b/usr.bin/nohup/nohup.1 index d409c335c2af..ac3ba82ffb5e 100644 --- a/usr.bin/nohup/nohup.1 +++ b/usr.bin/nohup/nohup.1 @@ -43,6 +43,7 @@ .Nd invoke a command immune to hangups .Sh SYNOPSIS .Nm +.Op Ar -- .Ar command .Op Ar arguments .Sh DESCRIPTION @@ -50,16 +51,11 @@ The .Nm utility invokes .Ar command -with -its +with its .Ar arguments and at this time sets the signal .Dv SIGHUP to be ignored. -The signal -.Dv SIGQUIT -may also be set -to be ignored. If the standard output is a terminal, the standard output is appended to the file .Pa nohup.out @@ -67,10 +63,6 @@ in the current directory. If standard error is a terminal, it is directed to the same place as the standard output. .Pp -.Nm Nohup -exits 1 if an error occurs, otherwise the exit status is that of -.Ar command . -.Pp Some shells may provide a builtin .Nm command which is similar or identical to this utility. @@ -90,6 +82,26 @@ utility uses the directory named by .Ev HOME to create the file. .El +.Sh DIAGNOSTICS +The +.Nm +utility exits with one of the following values: +.Bl -tag -width Ds +.It 126 +The +.Ar command +was found, but could not be invoked. +.It 127 +The +.Ar command +could not be found or an error occurred in +.Nm . +.El +.Pp +Otherwise, the exit status of +.Nm +will be that of +.Ar command . .Sh SEE ALSO .Xr builtin 1 , .Xr csh 1 , @@ -100,3 +112,7 @@ The utility is expected to be .St -p1003.2 compatible. +.Sh BUGS +Two or more instances of +.Nm +can append to the same file, which makes for a confusing output. diff --git a/usr.bin/nohup/nohup.c b/usr.bin/nohup/nohup.c index 36f832e26a71..8d8df862d238 100644 --- a/usr.bin/nohup/nohup.c +++ b/usr.bin/nohup/nohup.c @@ -57,67 +57,83 @@ static const char rcsid[] = #include #include -void dofile __P((void)); +static void dofile __P((void)); static void usage __P((void)); +#define FILENAME "nohup.out" +/* + * POSIX mandates that we exit with: + * 126 - If the utility was found, but failed to execute. + * 127 - If any other error occurred. + */ +#define EXIT_NOEXEC 126 +#define EXIT_NOTFOUND 127 +#define EXIT_MISC 127 + int main(argc, argv) int argc; char *argv[]; { - if (argc < 2) + int exit_status; + + while (getopt(argc, argv, "") != -1) + usage(); + argc -= optind; + argv += optind; + if (argc < 1) usage(); if (isatty(STDOUT_FILENO)) dofile(); - if (isatty(STDERR_FILENO) && dup2(STDOUT_FILENO, STDERR_FILENO) == -1) { + if (isatty(STDERR_FILENO) && dup2(STDOUT_FILENO, STDERR_FILENO) == -1) /* may have just closed stderr */ - (void)fprintf(stdin, "nohup: %s\n", strerror(errno)); - exit(1); - } + err(EXIT_MISC, "%s", argv[0]); (void)signal(SIGHUP, SIG_IGN); - (void)signal(SIGQUIT, SIG_IGN); - execvp(argv[1], &argv[1]); - err(1, "%s", argv[1]); + execvp(*argv, argv); + exit_status = (errno == ENOENT) ? EXIT_NOTFOUND : EXIT_NOEXEC; + err(exit_status, "%s", argv[0]); } -void +static void dofile() { - int append; int fd; - char *p, path[MAXPATHLEN]; + char path[MAXPATHLEN]; + const char *p; -#define FILENAME "nohup.out" + /* + * POSIX mandates if the standard output is a terminal, the standard + * output is appended to nohup.out in the working directory. Failing + * that, it will be appended to nohup.out in the directory obtained + * from the HOME environment variable. If file creation is required, + * the mode_t is set to S_IRUSR | S_IWUSR. + */ p = FILENAME; - append = !access(p, F_OK); - if ((fd = open(p, O_RDWR|O_CREAT, S_IRUSR | S_IWUSR)) >= 0) + fd = open(p, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR); + if (fd != -1) goto dupit; - if ((p = getenv("HOME"))) { - (void)strcpy(path, p); - (void)strcat(path, "/"); - (void)strcat(path, FILENAME); - append = !access(path, F_OK); - if ((fd = open(p = path, - O_RDWR|O_CREAT, S_IRUSR | S_IWUSR)) >= 0) + if ((p = getenv("HOME")) != NULL && *p != '\0' && + (size_t)snprintf(path, sizeof(path), "%s/%s", p, FILENAME) < + sizeof(path)) { + fd = open(p = path, O_RDWR | O_CREAT | O_APPEND, + S_IRUSR | S_IWUSR); + if (fd != -1) goto dupit; } - errx(1, "can't open a nohup.out file"); + errx(EXIT_MISC, "can't open a nohup.out file"); -dupit: (void)lseek(fd, (off_t)0, SEEK_END); +dupit: if (dup2(fd, STDOUT_FILENO) == -1) - err(1, NULL); - if (append) - (void)fprintf(stderr, "appending output to existing %s\n", p); - else - (void)fprintf(stderr, "sending output to %s\n", p); + err(EXIT_MISC, NULL); + (void)fprintf(stderr, "appending output to %s\n", p); } -void +static void usage() { - (void)fprintf(stderr, "usage: nohup command [arguments]\n"); - exit(1); + (void)fprintf(stderr, "usage: nohup [--] command [arguments]\n"); + exit(EXIT_MISC); }