File: fdflags.c

package info (click to toggle)
inn2 2.5.2-2~squeeze1
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 11,072 kB
  • ctags: 8,521
  • sloc: ansic: 91,418; sh: 13,249; perl: 12,311; makefile: 2,928; yacc: 868; python: 342; lex: 266
file content (103 lines) | stat: -rw-r--r-- 3,165 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*  $Id: fdflags.c 7585 2006-11-21 09:37:51Z eagle $
**
**  Set or clear file descriptor flags.
**
**  Simple functions (wrappers around fcntl) to set or clear file descriptor
**  flags like close on exec or nonblocking I/O.
*/

#include "config.h"
#include "clibrary.h"
#include "inn/libinn.h"
#include <errno.h>
#include <fcntl.h>

/*
**  Set a file to close on exec.
**
**  One is supposed to retrieve the flags, add FD_CLOEXEC, and then set
**  them, although I've never seen a system with any flags other than
**  close-on-exec.  Do it right anyway; it's not that expensive.  Avoid
**  changing errno.  Errors are ignored, since it generally doesn't cause
**  significant harm to fail.
*/
void
close_on_exec(int fd, bool flag)
{
    int oerrno;
    int oflag;

    oerrno = errno;
    oflag = fcntl(fd, F_GETFD, 0);
    if (oflag < 0) {
        errno = oerrno;
        return;
    }
    fcntl(fd, F_SETFD, flag ? (oflag | FD_CLOEXEC) : (oflag & ~FD_CLOEXEC));
    errno = oerrno;
}


/*
**  Set a file descriptor to nonblocking (or clear the nonblocking flag if
**  flag is false).
**
**  Always use O_NONBLOCK; O_NDELAY is *not* the same thing historically.
**  The semantics of O_NDELAY are that if the read would block, it returns 0
**  instead.  This is indistinguishable from an end of file condition.
**  POSIX added O_NONBLOCK, which requires read to return -1 and set errno
**  to EAGAIN, which is what we want.
**
**  FNDELAY (4.3BSD) originally did the correct thing, although it has a
**  different incompatibility (affecting all users of a socket rather than
**  just a file descriptor and returning EWOULDBLOCK instead of EAGAIN) that
**  we don't care about in INN.  Using it is *probably* safe, but BSD should
**  also have the ioctl, and at least on Solaris FNDELAY does the same thing
**  as O_NDELAY, not O_NONBLOCK.  So if we don't have O_NONBLOCK, fall back
**  to the ioctl instead.
**
**  Reference:  Stevens, Advanced Unix Programming, pg. 364.
**
**  Note that O_NONBLOCK is known not to work on earlier versions of ULTRIX,
**  SunOS, and AIX, possibly not setting the socket nonblocking at all,
**  despite the fact that they do define it.  It works in later SunOS and,
**  current AIX, however, and a 1999-10-25 survey of current operating
**  systems failed to turn up any that didn't handle it correctly (as
**  required by POSIX), while HP-UX 11.00 did use the broken return-zero
**  semantics of O_NDELAY (most other operating systems surveyed treated
**  O_NDELAY as synonymous with O_NONBLOCK).  Accordingly, we currently
**  unconditionally use O_NONBLOCK.  If this causes too many problems, an
**  autoconf test may be required.
*/

#ifdef O_NONBLOCK

int
nonblocking(int fd, bool flag)
{
    int mode;

    mode = fcntl(fd, F_GETFL, 0);
    if (mode < 0)
        return -1;
    mode = (flag ? (mode | O_NONBLOCK) : (mode & ~O_NONBLOCK));
    return fcntl(fd, F_SETFL, mode);
}

#else /* !O_NONBLOCK */

#include <sys/ioctl.h>
#if HAVE_SYS_FILIO_H
# include <sys/filio.h>
#endif

int
nonblocking(int fd, bool flag)
{
    int state;

    state = flag ? 1 : 0;
    return ioctl(fd, FIONBIO, &state);
}

#endif /* !O_NONBLOCK */