logo

utils-std

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

nohup.c (2735B)


  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. assert(errno == 0);
  37. if(isatty(1))
  38. {
  39. assert(errno == 0);
  40. nohup_fd = open("nohup.out", O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
  41. if(nohup_fd < 0)
  42. {
  43. fprintf(stderr,
  44. "%s: warning: Failed opening ./nohup.out (%s), fallbacking to ~/nohup.out\n",
  45. argv0,
  46. strerror(errno));
  47. char *home = getenv("HOME");
  48. if(!home)
  49. {
  50. fprintf(stderr,
  51. "%s: error: $HOME is undefined, can't fallback writing from ./nohup.out to "
  52. "~/nohup.out\n",
  53. argv0);
  54. return 127;
  55. }
  56. char home_nohup[PATH_MAX];
  57. if(snprintf(home_nohup, sizeof(home_nohup), "%s/nohup.out", home) < 0)
  58. {
  59. fprintf(stderr,
  60. "%s: error: Failed concatenating $HOME and '/nohup.out': %s\n",
  61. argv0,
  62. strerror(errno));
  63. return 127;
  64. }
  65. nohup_fd = open(home_nohup, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
  66. if(nohup_fd < 0)
  67. {
  68. fprintf(stderr, "%s: error: Failed opening ~/nohup.out: %s\n", argv0, strerror(errno));
  69. return 127;
  70. }
  71. }
  72. if(dup2(nohup_fd, 1) < 0)
  73. {
  74. fprintf(stderr,
  75. "%s: error: Failed assigning 'nohup.out' to stdout: %s\n",
  76. argv0,
  77. strerror(errno));
  78. return 127;
  79. }
  80. if(isatty(2))
  81. {
  82. assert(errno == 0);
  83. if(dup2(1, 2))
  84. {
  85. fprintf(
  86. stderr, "%s: error: Failed assigning stdout to stderr: %s\n", argv0, strerror(errno));
  87. return 127;
  88. }
  89. }
  90. else
  91. errno = 0; // isatty sets errno on returning false
  92. }
  93. else
  94. errno = 0; // isatty sets errno on returning false
  95. argc -= 1;
  96. argv += 1;
  97. (void)argc;
  98. assert(argv[0]);
  99. assert(errno == 0);
  100. if(execvp(argv[0], argv) < 0)
  101. {
  102. fprintf(stderr, "%s: error: Failed executing '%s': %s\n", argv0, argv[0], strerror(errno));
  103. return (errno == ENOENT) ? 127 : 126;
  104. }
  105. assert(false);
  106. }