diff options
author | Jilles Tjoelker <jilles@FreeBSD.org> | 2013-10-27 21:49:52 +0000 |
---|---|---|
committer | Jilles Tjoelker <jilles@FreeBSD.org> | 2013-10-27 21:49:52 +0000 |
commit | f7ac7dae04495f9c8eda7ef223f4c3aa4adea3a3 (patch) | |
tree | bce615ddb3d482a6ded8d654cc0812526438c177 /lib/libc | |
parent | aa5e088c696fb748d9d20371efc367bce09a67cc (diff) | |
download | src-test2-f7ac7dae04495f9c8eda7ef223f4c3aa4adea3a3.tar.gz src-test2-f7ac7dae04495f9c8eda7ef223f4c3aa4adea3a3.zip |
Notes
Diffstat (limited to 'lib/libc')
-rw-r--r-- | lib/libc/stdio/fdopen.c | 6 | ||||
-rw-r--r-- | lib/libc/stdio/flags.c | 50 | ||||
-rw-r--r-- | lib/libc/stdio/fopen.3 | 17 | ||||
-rw-r--r-- | lib/libc/stdio/freopen.c | 5 |
4 files changed, 55 insertions, 23 deletions
diff --git a/lib/libc/stdio/fdopen.c b/lib/libc/stdio/fdopen.c index 26e2cd70bc1e..8fc90a438b99 100644 --- a/lib/libc/stdio/fdopen.c +++ b/lib/libc/stdio/fdopen.c @@ -80,6 +80,12 @@ fdopen(fd, mode) if ((fp = __sfp()) == NULL) return (NULL); + + if ((oflags & O_CLOEXEC) && _fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { + fp->_flags = 0; + return (NULL); + } + fp->_flags = flags; /* * If opened for appending, but underlying descriptor does not have diff --git a/lib/libc/stdio/flags.c b/lib/libc/stdio/flags.c index 0b6b0755bd3b..d08071dd71b6 100644 --- a/lib/libc/stdio/flags.c +++ b/lib/libc/stdio/flags.c @@ -53,7 +53,7 @@ __sflags(mode, optr) const char *mode; int *optr; { - int ret, m, o; + int ret, m, o, known; switch (*mode++) { @@ -80,28 +80,34 @@ __sflags(mode, optr) return (0); } - /* 'b' (binary) is ignored */ - if (*mode == 'b') - mode++; - - /* [rwa][b]\+ means read and write */ - if (*mode == '+') { - mode++; - ret = __SRW; - m = O_RDWR; - } - - /* 'b' (binary) can appear here, too -- and is ignored again */ - if (*mode == 'b') - mode++; - - /* 'x' means exclusive (fail if the file exists) */ - if (*mode == 'x') { - if (m == O_RDONLY) { - errno = EINVAL; - return (0); + do { + known = 1; + switch (*mode++) { + case 'b': + /* 'b' (binary) is ignored */ + break; + case '+': + /* [rwa][b]\+ means read and write */ + ret = __SRW; + m = O_RDWR; + break; + case 'x': + /* 'x' means exclusive (fail if the file exists) */ + o |= O_EXCL; + break; + case 'e': + /* set close-on-exec */ + o |= O_CLOEXEC; + break; + default: + known = 0; + break; } - o |= O_EXCL; + } while (known); + + if ((o & O_EXCL) != 0 && m == O_RDONLY) { + errno = EINVAL; + return (0); } *optr = m | o; diff --git a/lib/libc/stdio/fopen.3 b/lib/libc/stdio/fopen.3 index 57f5a3dbf88b..f11f4e07e3de 100644 --- a/lib/libc/stdio/fopen.3 +++ b/lib/libc/stdio/fopen.3 @@ -100,6 +100,14 @@ or causes the .Fn fopen call to fail if the file already exists. +An optional +.Dq Li e +following the above +causes the +.Fn fopen +call to set the +.Dv FD_CLOEXEC +flag on the underlying file descriptor. .Pp The .Fa mode @@ -149,6 +157,11 @@ of the stream must be compatible with the mode of the file descriptor. The .Dq Li x mode option is ignored. +If the +.Dq Li e +mode option is present, the +.Dv FD_CLOEXEC +flag is set, otherwise it remains unchanged. When the stream is closed via .Xr fclose 3 , .Fa fildes @@ -313,6 +326,10 @@ function conforms to .St -p1003.1-88 . The +.Dq Li e +mode option does not conform to any standard +but is also supported by glibc. +The .Fn fmemopen function conforms to diff --git a/lib/libc/stdio/freopen.c b/lib/libc/stdio/freopen.c index be7bc8a2f8d0..8d1ec917086a 100644 --- a/lib/libc/stdio/freopen.c +++ b/lib/libc/stdio/freopen.c @@ -118,6 +118,8 @@ freopen(file, mode, fp) (void) ftruncate(fp->_file, (off_t)0); if (!(oflags & O_APPEND)) (void) _sseek(fp, (fpos_t)0, SEEK_SET); + if (oflags & O_CLOEXEC) + (void) _fcntl(fp->_file, F_SETFD, FD_CLOEXEC); f = fp->_file; isopen = 0; wantfd = -1; @@ -194,7 +196,8 @@ finish: * assume stderr is always fd STDERR_FILENO, even if being freopen'd. */ if (wantfd >= 0) { - if (_dup2(f, wantfd) >= 0) { + if ((oflags & O_CLOEXEC ? _fcntl(f, F_DUP2FD_CLOEXEC, wantfd) : + _dup2(f, wantfd)) >= 0) { (void)_close(f); f = wantfd; } else |