File: fdflags.c

package info (click to toggle)
inn2 2.4.5-5
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 8,912 kB
  • ctags: 7,860
  • sloc: ansic: 85,104; perl: 11,427; sh: 9,863; makefile: 2,498; yacc: 1,563; python: 298; lex: 252; tcl: 7
file content (103 lines) | stat: -rw-r--r-- 3,159 bytes parent folder | download
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 4740 2001-05-14 03:52:34Z rra $
**
**  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 "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 */