logo

utils-std

Collection of commonly available Unix tools
commit: 00f9110aaef088dfb282d0775449f273000c189c
parent 1523b277a5e4a7fc9fa8e10dbce03f6275de141f
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Mon, 15 Apr 2024 06:11:14 +0200

cmd/nohup: new

Diffstat:

Mcmd/env.14+++-
Acmd/nohup.156++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acmd/nohup.c114+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcoreutils.txt2+-
Mlsb_commands.txt2+-
Mposix_utilities.txt2+-
6 files changed, 176 insertions(+), 4 deletions(-)

diff --git a/cmd/env.1 b/cmd/env.1 @@ -43,7 +43,9 @@ is invoked, the exit status of .Nm shall be the exit status of .Ar command ; -Otherwise, the env utility shall exit with one of the following values: +Otherwise, the +.Nm +utility shall exit with one of the following values: .Bl -tag -width Ds .It 0 .Nm diff --git a/cmd/nohup.1 b/cmd/nohup.1 @@ -0,0 +1,56 @@ +.\" utils-std: Collection of commonly available Unix tools +.\" Copyright 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +.\" SPDX-License-Identifier: MPL-2.0 +.Dd 2024-04-15 +.Dt NOHUP 1 +.Os +.Sh NAME +.Nm nohup +.Nd run command with hangups ignored +.Sh SYNOPSIS +.Nm +.Ar command +.Op Ar arguments ... +.Sh DESCRIPTION +.Nm +runs +.Ar command +with SIGHUP ignored, allowing to keep +.Ar command +running even after the terminal hanged up. +.Pp +If stdout is TTY, it's output is saved to +.Pa ./nohup.out +or if it fails to open it for writing, to +.Pa ~/nohup.out . +If stderr is also a TTY, it's output is also saved to +.Pa nohup.out . +.Sh EXIT STATUS +If +.Ar command +is invoked, the exit status of +.Nm +shall be the exit status of +.Ar command ; +Otherwise, the +.Nm +utility shall exit with one of the following values: +.Bl -tag -width Ds +.It 126 +.Ar command +was found but couldn't be invoked. +.It 127 +.Ar command +wasn't found or an error occured within the +.Nm +utility. +.El +.Sh SEE ALSO +.Xr tmux 1 +.Sh STANDARDS +.Nm +should be compliant with the +.St -p1003.1-2008 +specification. +.Sh AUTHORS +.An Haelwenn (lanodan) Monnier Aq Mt contact+utils@hacktivis.me diff --git a/cmd/nohup.c b/cmd/nohup.c @@ -0,0 +1,114 @@ +// utils-std: Collection of commonly available Unix tools +// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +// SPDX-License-Identifier: MPL-2.0 + +#define _POSIX_C_SOURCE 200809L + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> // open +#include <limits.h> // PATH_MAX +#include <signal.h> +#include <stdbool.h> +#include <stdio.h> // fprintf +#include <stdlib.h> // getenv +#include <string.h> // strerror +#include <sys/stat.h> // S_IRUSR, S_IWUSR +#include <unistd.h> // isatty + +static void +usage() +{ + fprintf(stderr, "Usage: nohup command [args ...]\n"); +} + +int +main(int argc, char *argv[]) +{ + int nohup_fd = -1; + + if(argc <= 1) + { + usage(); + return 127; + } + + if(signal(SIGHUP, SIG_IGN) == SIG_ERR) + { + fprintf(stderr, "nohup: Failed to set SIGHUP as ignored: %s\n", strerror(errno)); + return 127; + } + + assert(errno == 0); + if(isatty(1)) + { + assert(errno == 0); + nohup_fd = open("nohup.out", O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR); + if(nohup_fd < 0) + { + fprintf(stderr, + "nohup: Warning: Failed opening ./nohup.out (%s), fallbacking to ~/nohup.out\n", + strerror(errno)); + + char *home = getenv("HOME"); + if(!home) + { + fprintf( + stderr, + "nohup: $HOME is undefined, can't fallback writing from ./nohup.out to ~/nohup.out\n"); + return 127; + } + + char home_nohup[PATH_MAX]; + if(snprintf(home_nohup, sizeof(home_nohup), "%s/nohup.out", home) < 0) + { + fprintf( + stderr, "nohup: Failed concatenating $HOME and '/nohup.out': %s\n", strerror(errno)); + return 127; + } + + nohup_fd = open(home_nohup, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR); + if(nohup_fd < 0) + { + fprintf(stderr, "nohup: Error: Failed opening ~/nohup.out: %s\n", strerror(errno)); + return 127; + } + } + + if(dup2(nohup_fd, 1) < 0) + { + fprintf( + stderr, "nohup: Error: Failed assigning 'nohup.out' to stdout: %s\n", strerror(errno)); + return 127; + } + + if(isatty(2)) + { + assert(errno == 0); + if(dup2(1, 2)) + { + fprintf(stderr, "nohup: Error: Failed assigning stdout to stderr: %s\n", strerror(errno)); + return 127; + } + } + else + errno = 0; // isatty sets errno on returning false + } + else + errno = 0; // isatty sets errno on returning false + + argc -= 1; + argv += 1; + + assert(argv[0]); + assert(errno == 0); + /* flawfinder: ignore. No restrictions on commands is intended */ + if(execvp(argv[0], argv) < 0) + { + fprintf(stderr, "nohup: execvp(\"%s\", ...): %s\n", argv[0], strerror(errno)); + + return (errno == ENOENT) ? 127 : 126; + } + + assert(false); +} diff --git a/coreutils.txt b/coreutils.txt @@ -50,7 +50,7 @@ mktemp: Todo mv: Todo nice: Maybe nl: No, use sed -nohup: Maybe +nohup: Done nproc: ? numfmt: Maybe, consider humanize(1) od: Todo diff --git a/lsb_commands.txt b/lsb_commands.txt @@ -88,7 +88,7 @@ mv: Todo newgrp: out of scope nice: Maybe nl: No, use sed -nohup: Maybe +nohup: Done od: Todo passwd: out of scope paste: Todo diff --git a/posix_utilities.txt b/posix_utilities.txt @@ -88,7 +88,7 @@ newgrp nice nl nm: no, toolchain -nohup +nohup: done od paste patch: no