chiark / gitweb /
Commit 2.4.5-5 as unpacked
[inn-innduct.git] / lib / fdlimit.c
1 /*  $Id: fdlimit.c 4511 2001-02-07 23:41:08Z rra $
2 **
3 **  Portably determine or set the limit on open file descriptors.
4 **
5 **  Pretty much all platforms these days have getrlimit and setrlimit, so
6 **  prefer those, but for determining the current limit preserve the old
7 **  portability (if we don't have getrlimit, try sysconf, then
8 **  getdtablesize, then ulimit, and then try to find a hard-coded constant
9 **  in <sys/param.h> and failing that fall back to the POSIX-guaranteed
10 **  minimum of 20.
11 **
12 **  For setting the limit, only setrlimit is supported; if it isn't
13 **  available, return -1 always.  We also refuse to set the limit to
14 **  something higher than select can handle, checking against FD_SETSIZE.
15 **
16 **  Note that on some versions of Linux (2.2.x reported), sysconf may return
17 **  the wrong value for the maximum file descriptors.  getrlimit is correct,
18 **  so always prefer it.
19 */
20
21 #include "config.h"
22 #include "clibrary.h"
23 #include <errno.h>
24 #if HAVE_SYS_SELECT_H
25 # include <sys/select.h>
26 #endif
27
28 /* FreeBSD 3.4 RELEASE needs <sys/time.h> before <sys/resource.h>. */
29 #if HAVE_GETRLIMIT || HAVE_SETRLIMIT
30 # if HAVE_SYS_TIME_H
31 #  include <sys/time.h>
32 # endif
33 # include <sys/resource.h>
34 #endif
35
36 #include "libinn.h"
37
38 #if HAVE_SETRLIMIT && defined(RLIMIT_NOFILE)
39
40 int
41 setfdlimit(unsigned int limit)
42 {
43     struct rlimit rl;
44
45 #ifdef FD_SETSIZE
46     if (limit > FD_SETSIZE) {
47         errno = EINVAL;
48         return -1;
49     }
50 #endif
51
52     rl.rlim_cur = 0;
53     rl.rlim_max = 0;
54
55 #if HAVE_GETRLIMIT
56     if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
57         rl.rlim_cur = 0;
58         rl.rlim_max = 0;
59     }
60 #endif
61
62     rl.rlim_cur = limit;
63     if (limit > rl.rlim_max)
64         rl.rlim_max = limit;
65     return setrlimit(RLIMIT_NOFILE, &rl);
66 }
67
68 #else /* !(HAVE_SETRLIMIT && RLIMIT_NOFILE) */
69
70 int
71 setfdlimit(unsigned int limit UNUSED)
72 {
73     /* Unimplemented system call is close enough. */
74     errno = ENOSYS;
75     return -1;
76 }
77
78 #endif /* !(HAVE_SETRLIMIT && RLIMIT_NOFILE) */
79
80 #if HAVE_GETRLIMIT && defined(RLIMIT_NOFILE)
81
82 int
83 getfdlimit(void)
84 {
85     struct rlimit rl;
86
87     if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
88         return -1;
89     return rl.rlim_cur;
90 }
91
92 #elif HAVE_SYSCONF
93
94 int
95 getfdlimit(void)
96 {
97     return sysconf(_SC_OPEN_MAX);
98 }
99
100 #elif HAVE_GETDTABLESIZE
101
102 int
103 getfdlimit(void)
104 {
105     return getdtablesize();
106 }
107
108 #elif HAVE_ULIMIT
109
110 int
111 getfdlimit(void)
112 {
113 # ifdef UL_GDESLIM
114     return ulimit(UL_GDESLIM, 0);
115 # else
116     return ulimit(4, 0);
117 # endif
118 }
119
120 #else /* no function mechanism available */
121 # if HAVE_LIMITS_H
122 #  include <limits.h>
123 # endif
124 # include <sys/param.h>
125
126 int
127 getfdcount(void)
128 {
129 # ifdef NOFILE
130     return NOFILE;
131 # else
132     return 20;
133 # endif
134 }
135
136 #endif