logo

utils-std

Collection of commonly available Unix tools git clone https://anongit.hacktivis.me/git/utils-std.git/

nohup.c (2648B)


  1. // utils-std: Collection of commonly available Unix tools
  2. // SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
  3. // SPDX-License-Identifier: MPL-2.0
  4. #define _POSIX_C_SOURCE 200809L
  5. #include <assert.h>
  6. #include <errno.h>
  7. #include <fcntl.h> // open
  8. #include <limits.h> // PATH_MAX
  9. #include <signal.h>
  10. #include <stdbool.h>
  11. #include <stdio.h> // fprintf
  12. #include <stdlib.h> // getenv
  13. #include <string.h> // strerror
  14. #include <sys/stat.h> // S_IRUSR, S_IWUSR
  15. #include <unistd.h> // isatty
  16. const char *argv0 = "nohup";
  17. static void
  18. usage(void)
  19. {
  20. fprintf(stderr, "Usage: nohup command [args ...]\n");
  21. }
  22. int
  23. main(int argc, char *argv[])
  24. {
  25. int nohup_fd = -1;
  26. if(argc <= 1)
  27. {
  28. usage();
  29. return 127;
  30. }
  31. if(signal(SIGHUP, SIG_IGN) == SIG_ERR)
  32. {
  33. fprintf(stderr, "%s: error: Failed to set SIGHUP as ignored: %s\n", argv0, strerror(errno));
  34. return 127;
  35. }
  36. if(isatty(1))
  37. {
  38. nohup_fd = open("nohup.out", O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
  39. if(nohup_fd < 0)
  40. {
  41. fprintf(stderr,
  42. "%s: warning: Failed opening ./nohup.out (%s), fallbacking to ~/nohup.out\n",
  43. argv0,
  44. strerror(errno));
  45. char *home = getenv("HOME");
  46. if(!home)
  47. {
  48. fprintf(stderr,
  49. "%s: error: $HOME is undefined, can't fallback writing from ./nohup.out to "
  50. "~/nohup.out\n",
  51. argv0);
  52. return 127;
  53. }
  54. char home_nohup[PATH_MAX];
  55. if(snprintf(home_nohup, sizeof(home_nohup), "%s/nohup.out", home) < 0)
  56. {
  57. fprintf(stderr,
  58. "%s: error: Failed concatenating $HOME and '/nohup.out': %s\n",
  59. argv0,
  60. strerror(errno));
  61. return 127;
  62. }
  63. nohup_fd = open(home_nohup, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
  64. if(nohup_fd < 0)
  65. {
  66. fprintf(stderr, "%s: error: Failed opening ~/nohup.out: %s\n", argv0, strerror(errno));
  67. return 127;
  68. }
  69. }
  70. if(dup2(nohup_fd, 1) < 0)
  71. {
  72. fprintf(stderr,
  73. "%s: error: Failed assigning 'nohup.out' to stdout: %s\n",
  74. argv0,
  75. strerror(errno));
  76. return 127;
  77. }
  78. if(isatty(2))
  79. {
  80. if(dup2(1, 2))
  81. {
  82. fprintf(
  83. stderr, "%s: error: Failed assigning stdout to stderr: %s\n", argv0, strerror(errno));
  84. return 127;
  85. }
  86. }
  87. else
  88. errno = 0; // isatty sets errno on returning false
  89. }
  90. else
  91. errno = 0; // isatty sets errno on returning false
  92. argc -= 1;
  93. argv += 1;
  94. (void)argc;
  95. assert(argv[0]);
  96. if(execvp(argv[0], argv) < 0)
  97. {
  98. fprintf(stderr, "%s: error: Failed executing '%s': %s\n", argv0, argv[0], strerror(errno));
  99. return (errno == ENOENT) ? 127 : 126;
  100. }
  101. assert(false);
  102. }