chiark / gitweb /
use libinn logging where applicable
[inn-innduct.git] / lib / fdflags.c
1 /*  $Id: fdflags.c 4740 2001-05-14 03:52:34Z rra $
2 **
3 **  Set or clear file descriptor flags.
4 **
5 **  Simple functions (wrappers around fcntl) to set or clear file descriptor
6 **  flags like close on exec or nonblocking I/O.
7 */
8
9 #include "config.h"
10 #include "clibrary.h"
11 #include "libinn.h"
12 #include <errno.h>
13 #include <fcntl.h>
14
15 /*
16 **  Set a file to close on exec.
17 **
18 **  One is supposed to retrieve the flags, add FD_CLOEXEC, and then set
19 **  them, although I've never seen a system with any flags other than
20 **  close-on-exec.  Do it right anyway; it's not that expensive.  Avoid
21 **  changing errno.  Errors are ignored, since it generally doesn't cause
22 **  significant harm to fail.
23 */
24 void
25 close_on_exec(int fd, bool flag)
26 {
27     int oerrno;
28     int oflag;
29
30     oerrno = errno;
31     oflag = fcntl(fd, F_GETFD, 0);
32     if (oflag < 0) {
33         errno = oerrno;
34         return;
35     }
36     fcntl(fd, F_SETFD, flag ? (oflag | FD_CLOEXEC) : (oflag & ~FD_CLOEXEC));
37     errno = oerrno;
38 }
39
40
41 /*
42 **  Set a file descriptor to nonblocking (or clear the nonblocking flag if
43 **  flag is false).
44 **
45 **  Always use O_NONBLOCK; O_NDELAY is *not* the same thing historically.
46 **  The semantics of O_NDELAY are that if the read would block, it returns 0
47 **  instead.  This is indistinguishable from an end of file condition.
48 **  POSIX added O_NONBLOCK, which requires read to return -1 and set errno
49 **  to EAGAIN, which is what we want.
50 **
51 **  FNDELAY (4.3BSD) originally did the correct thing, although it has a
52 **  different incompatibility (affecting all users of a socket rather than
53 **  just a file descriptor and returning EWOULDBLOCK instead of EAGAIN) that
54 **  we don't care about in INN.  Using it is *probably* safe, but BSD should
55 **  also have the ioctl, and at least on Solaris FNDELAY does the same thing
56 **  as O_NDELAY, not O_NONBLOCK.  So if we don't have O_NONBLOCK, fall back
57 **  to the ioctl instead.
58 **
59 **  Reference:  Stevens, Advanced Unix Programming, pg. 364.
60 **
61 **  Note that O_NONBLOCK is known not to work on earlier versions of ULTRIX,
62 **  SunOS, and AIX, possibly not setting the socket nonblocking at all,
63 **  despite the fact that they do define it.  It works in later SunOS and,
64 **  current AIX, however, and a 1999-10-25 survey of current operating
65 **  systems failed to turn up any that didn't handle it correctly (as
66 **  required by POSIX), while HP-UX 11.00 did use the broken return-zero
67 **  semantics of O_NDELAY (most other operating systems surveyed treated
68 **  O_NDELAY as synonymous with O_NONBLOCK).  Accordingly, we currently
69 **  unconditionally use O_NONBLOCK.  If this causes too many problems, an
70 **  autoconf test may be required.
71 */
72
73 #ifdef O_NONBLOCK
74
75 int
76 nonblocking(int fd, bool flag)
77 {
78     int mode;
79
80     mode = fcntl(fd, F_GETFL, 0);
81     if (mode < 0)
82         return -1;
83     mode = (flag ? (mode | O_NONBLOCK) : (mode & ~O_NONBLOCK));
84     return fcntl(fd, F_SETFL, mode);
85 }
86
87 #else /* !O_NONBLOCK */
88
89 #include <sys/ioctl.h>
90 #if HAVE_SYS_FILIO_H
91 # include <sys/filio.h>
92 #endif
93
94 int
95 nonblocking(int fd, bool flag)
96 {
97     int state;
98
99     state = flag ? 1 : 0;
100     return ioctl(fd, FIONBIO, &state);
101 }
102
103 #endif /* !O_NONBLOCK */