1210284Sjmallett/* cloexec.c - set or clear the close-on-exec descriptor flag 2232812Sjmallett 3215990Sjmallett Copyright (C) 1991, 2004-2006, 2009-2020 Free Software Foundation, Inc. 4210284Sjmallett 5210284Sjmallett This program is free software: you can redistribute it and/or modify 6215990Sjmallett it under the terms of the GNU General Public License as published by 7215990Sjmallett the Free Software Foundation; either version 3 of the License, or 8215990Sjmallett (at your option) any later version. 9210284Sjmallett 10215990Sjmallett This program is distributed in the hope that it will be useful, 11215990Sjmallett but WITHOUT ANY WARRANTY; without even the implied warranty of 12210284Sjmallett MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13215990Sjmallett GNU General Public License for more details. 14215990Sjmallett 15215990Sjmallett You should have received a copy of the GNU General Public License 16215990Sjmallett along with this program. If not, see <https://www.gnu.org/licenses/>. 17215990Sjmallett 18232812Sjmallett The code is taken from glibc/manual/llio.texi */ 19215990Sjmallett 20215990Sjmallett#include <config.h> 21215990Sjmallett 22215990Sjmallett#include "cloexec.h" 23215990Sjmallett 24215990Sjmallett#include <errno.h> 25215990Sjmallett#include <fcntl.h> 26215990Sjmallett#include <unistd.h> 27215990Sjmallett 28215990Sjmallett/* Set the 'FD_CLOEXEC' flag of DESC if VALUE is true, 29232812Sjmallett or clear the flag if VALUE is false. 30215990Sjmallett Return 0 on success, or -1 on error with 'errno' set. 31215990Sjmallett 32215990Sjmallett Note that on MingW, this function does NOT protect DESC from being 33215990Sjmallett inherited into spawned children. Instead, either use dup_cloexec 34215990Sjmallett followed by closing the original DESC, or use interfaces such as 35215990Sjmallett open or pipe2 that accept flags like O_CLOEXEC to create DESC 36215990Sjmallett non-inheritable in the first place. */ 37215990Sjmallett 38210284Sjmallettint 39210284Sjmallettset_cloexec_flag (int desc, bool value) 40210284Sjmallett{ 41210284Sjmallett#ifdef F_SETFD 42210284Sjmallett 43210284Sjmallett int flags = fcntl (desc, F_GETFD, 0); 44210284Sjmallett 45215990Sjmallett if (0 <= flags) 46210284Sjmallett { 47210284Sjmallett int newflags = (value ? flags | FD_CLOEXEC : flags & ~FD_CLOEXEC); 48210284Sjmallett 49210284Sjmallett if (flags == newflags 50210284Sjmallett || fcntl (desc, F_SETFD, newflags) != -1) 51210284Sjmallett return 0; 52232812Sjmallett } 53210284Sjmallett 54210284Sjmallett return -1; 55210284Sjmallett 56210284Sjmallett#else /* !F_SETFD */ 57210284Sjmallett 58210284Sjmallett /* Use dup2 to reject invalid file descriptors; the cloexec flag 59210284Sjmallett will be unaffected. */ 60210284Sjmallett if (desc < 0) 61210284Sjmallett { 62210284Sjmallett errno = EBADF; 63210284Sjmallett return -1; 64210284Sjmallett } 65210284Sjmallett if (dup2 (desc, desc) < 0) 66210284Sjmallett /* errno is EBADF here. */ 67210284Sjmallett return -1; 68210284Sjmallett 69210284Sjmallett /* There is nothing we can do on this kind of platform. Punt. */ 70232812Sjmallett return 0; 71232812Sjmallett#endif /* !F_SETFD */ 72232812Sjmallett} 73232812Sjmallett 74232812Sjmallett 75210284Sjmallett/* Duplicates a file handle FD, while marking the copy to be closed 76210284Sjmallett prior to exec or spawn. Returns -1 and sets errno if FD could not 77210284Sjmallett be duplicated. */ 78210284Sjmallett 79210284Sjmallettint 80210284Sjmallettdup_cloexec (int fd) 81210284Sjmallett{ 82210284Sjmallett return fcntl (fd, F_DUPFD_CLOEXEC, 0); 83215990Sjmallett} 84215990Sjmallett