nohup.c (2735B)
- // 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
- const char *argv0 = "nohup";
- static void
- usage(void)
- {
- 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, "%s: error: Failed to set SIGHUP as ignored: %s\n", argv0, 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,
- "%s: warning: Failed opening ./nohup.out (%s), fallbacking to ~/nohup.out\n",
- argv0,
- strerror(errno));
- char *home = getenv("HOME");
- if(!home)
- {
- fprintf(stderr,
- "%s: error: $HOME is undefined, can't fallback writing from ./nohup.out to "
- "~/nohup.out\n",
- argv0);
- return 127;
- }
- char home_nohup[PATH_MAX];
- if(snprintf(home_nohup, sizeof(home_nohup), "%s/nohup.out", home) < 0)
- {
- fprintf(stderr,
- "%s: error: Failed concatenating $HOME and '/nohup.out': %s\n",
- argv0,
- 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, "%s: error: Failed opening ~/nohup.out: %s\n", argv0, strerror(errno));
- return 127;
- }
- }
- if(dup2(nohup_fd, 1) < 0)
- {
- fprintf(stderr,
- "%s: error: Failed assigning 'nohup.out' to stdout: %s\n",
- argv0,
- strerror(errno));
- return 127;
- }
- if(isatty(2))
- {
- assert(errno == 0);
- if(dup2(1, 2))
- {
- fprintf(
- stderr, "%s: error: Failed assigning stdout to stderr: %s\n", argv0, 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;
- (void)argc;
- assert(argv[0]);
- assert(errno == 0);
- if(execvp(argv[0], argv) < 0)
- {
- fprintf(stderr, "%s: error: Failed executing '%s': %s\n", argv0, argv[0], strerror(errno));
- return (errno == ENOENT) ? 127 : 126;
- }
- assert(false);
- }