cloexec.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /* cloexec.c - set or clear the close-on-exec descriptor flag
  2. Copyright (C) 1991, 2004-2006, 2009-2023 Free Software Foundation, Inc.
  3. This file is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as
  5. published by the Free Software Foundation; either version 2.1 of the
  6. License, or (at your option) any later version.
  7. This file is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  13. /* The code is taken from glibc/manual/llio.texi */
  14. #include <config.h>
  15. #include "cloexec.h"
  16. #include <errno.h>
  17. #include <fcntl.h>
  18. #include <unistd.h>
  19. /* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true,
  20. or clear the flag if VALUE is false.
  21. Return 0 on success, or -1 on error with 'errno' set.
  22. Note that on MingW, this function does NOT protect DESC from being
  23. inherited into spawned children. Instead, either use dup_cloexec
  24. followed by closing the original DESC, or use interfaces such as
  25. open or pipe2 that accept flags like O_CLOEXEC to create DESC
  26. non-inheritable in the first place. */
  27. int
  28. set_cloexec_flag (int desc, bool value)
  29. {
  30. #ifdef F_SETFD
  31. int flags = fcntl (desc, F_GETFD, 0);
  32. if (0 <= flags)
  33. {
  34. int newflags = (value ? flags | FD_CLOEXEC : flags & ~FD_CLOEXEC);
  35. if (flags == newflags
  36. || fcntl (desc, F_SETFD, newflags) != -1)
  37. return 0;
  38. }
  39. return -1;
  40. #else /* !F_SETFD */
  41. /* Use dup2 to reject invalid file descriptors; the cloexec flag
  42. will be unaffected. */
  43. if (desc < 0)
  44. {
  45. errno = EBADF;
  46. return -1;
  47. }
  48. if (dup2 (desc, desc) < 0)
  49. /* errno is EBADF here. */
  50. return -1;
  51. /* There is nothing we can do on this kind of platform. Punt. */
  52. return 0;
  53. #endif /* !F_SETFD */
  54. }
  55. /* Duplicates a file handle FD, while marking the copy to be closed
  56. prior to exec or spawn. Returns -1 and sets errno if FD could not
  57. be duplicated. */
  58. int
  59. dup_cloexec (int fd)
  60. {
  61. return fcntl (fd, F_DUPFD_CLOEXEC, 0);
  62. }