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