1 | /* Copyright (C) 1991-2023 Free Software Foundation, Inc. |
2 | This file is part of the GNU C Library. |
3 | |
4 | The GNU C Library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2.1 of the License, or (at your option) any later version. |
8 | |
9 | The GNU C Library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Lesser General Public |
15 | License along with the GNU C Library; if not, see |
16 | <https://www.gnu.org/licenses/>. */ |
17 | |
18 | #include <stddef.h> |
19 | #include <errno.h> |
20 | #include <unistd.h> |
21 | #include <string.h> |
22 | #include <confstr.h> |
23 | #include "../version.h" |
24 | |
25 | #define NEED_SPEC_ARRAY 0 |
26 | #include <posix-conf-vars.h> |
27 | |
28 | /* If BUF is not NULL and LEN > 0, fill in at most LEN - 1 bytes |
29 | of BUF with the value corresponding to NAME and zero-terminate BUF. |
30 | Return the number of bytes required to hold NAME's entire value. */ |
31 | size_t |
32 | __confstr (int name, char *buf, size_t len) |
33 | { |
34 | const char *string = "" ; |
35 | size_t string_len = 1; |
36 | |
37 | /* Note that this buffer must be large enough for the longest strings |
38 | used below. */ |
39 | char restenvs[4 * sizeof "POSIX_V7_LPBIG_OFFBIG" ]; |
40 | |
41 | switch (name) |
42 | { |
43 | case _CS_PATH: |
44 | { |
45 | static const char cs_path[] = CS_PATH; |
46 | string = cs_path; |
47 | string_len = sizeof (cs_path); |
48 | } |
49 | break; |
50 | |
51 | /* For _CS_V7_WIDTH_RESTRICTED_ENVS, _CS_V6_WIDTH_RESTRICTED_ENVS |
52 | and _CS_V5_WIDTH_RESTRICTED_ENVS: |
53 | |
54 | We have to return a newline-separated list of names of |
55 | programming environments in which the widths of blksize_t, |
56 | cc_t, mode_t, nfds_t, pid_t, ptrdiff_t, size_t, speed_t, |
57 | ssize_t, suseconds_t, tcflag_t, useconds_t, wchar_t, and |
58 | wint_t types are no greater than the width of type long. |
59 | |
60 | Currently this means all environments that the system allows. */ |
61 | |
62 | #define START_ENV_GROUP(VERSION) \ |
63 | case _CS_##VERSION##_WIDTH_RESTRICTED_ENVS: \ |
64 | string_len = 0; |
65 | |
66 | #define END_ENV_GROUP(VERSION) \ |
67 | restenvs[string_len++] = '\0'; \ |
68 | string = restenvs; \ |
69 | break; |
70 | |
71 | #define KNOWN_ABSENT_ENVIRONMENT(SC_PREFIX, ENV_PREFIX, SUFFIX) \ |
72 | /* Empty. */ |
73 | |
74 | #define KNOWN_PRESENT_ENV_STRING(STR) \ |
75 | if (string_len > 0) \ |
76 | restenvs[string_len++] = '\n'; \ |
77 | memcpy (restenvs + string_len, STR, \ |
78 | sizeof STR - 1); \ |
79 | string_len += sizeof STR - 1; |
80 | |
81 | #define KNOWN_PRESENT_ENVIRONMENT(SC_PREFIX, ENV_PREFIX, SUFFIX) \ |
82 | KNOWN_PRESENT_ENV_STRING (#ENV_PREFIX "_" #SUFFIX) |
83 | |
84 | #define UNKNOWN_ENVIRONMENT(SC_PREFIX, ENV_PREFIX, SUFFIX) \ |
85 | if (__sysconf (_SC_##SC_PREFIX##_##SUFFIX) > 0) \ |
86 | { \ |
87 | KNOWN_PRESENT_ENVIRONMENT (SC_PREFIX, ENV_PREFIX, SUFFIX) \ |
88 | } |
89 | |
90 | #include "posix-envs.def" |
91 | |
92 | #undef START_ENV_GROUP |
93 | #undef END_ENV_GROUP |
94 | #undef KNOWN_ABSENT_ENVIRONMENT |
95 | #undef KNOWN_PRESENT_ENV_STRING |
96 | #undef KNOWN_PRESENT_ENVIRONMENT |
97 | #undef UNKNOWN_ENVIRONMENT |
98 | |
99 | case _CS_XBS5_ILP32_OFF32_CFLAGS: |
100 | case _CS_POSIX_V6_ILP32_OFF32_CFLAGS: |
101 | case _CS_POSIX_V7_ILP32_OFF32_CFLAGS: |
102 | #ifdef __ILP32_OFF32_CFLAGS |
103 | # if CONF_IS_DEFINED_UNSET (_POSIX_V7_ILP32_OFF32) |
104 | # error "__ILP32_OFF32_CFLAGS should not be defined" |
105 | # elif CONF_IS_UNDEFINED (_POSIX_V7_ILP32_OFF32) |
106 | if (__sysconf (_SC_V7_ILP32_OFF32) < 0) |
107 | break; |
108 | # endif |
109 | string = __ILP32_OFF32_CFLAGS; |
110 | string_len = sizeof (__ILP32_OFF32_CFLAGS); |
111 | #endif |
112 | break; |
113 | |
114 | case _CS_XBS5_ILP32_OFFBIG_CFLAGS: |
115 | case _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS: |
116 | case _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS: |
117 | #ifdef __ILP32_OFFBIG_CFLAGS |
118 | # if CONF_IS_DEFINED_UNSET (_POSIX_V7_ILP32_OFFBIG) |
119 | # error "__ILP32_OFFBIG_CFLAGS should not be defined" |
120 | # elif CONF_IS_UNDEFINED (_POSIX_V7_ILP32_OFFBIG) |
121 | if (__sysconf (_SC_V7_ILP32_OFFBIG) < 0) |
122 | break; |
123 | # endif |
124 | string = __ILP32_OFFBIG_CFLAGS; |
125 | string_len = sizeof (__ILP32_OFFBIG_CFLAGS); |
126 | #endif |
127 | break; |
128 | |
129 | case _CS_XBS5_LP64_OFF64_CFLAGS: |
130 | case _CS_POSIX_V6_LP64_OFF64_CFLAGS: |
131 | case _CS_POSIX_V7_LP64_OFF64_CFLAGS: |
132 | #ifdef __LP64_OFF64_CFLAGS |
133 | # if CONF_IS_DEFINED_UNSET (_POSIX_V7_LP64_OFF64) |
134 | # error "__LP64_OFF64_CFLAGS should not be defined" |
135 | # elif CONF_IS_UNDEFINED (_POSIX_V7_LP64_OFF64) |
136 | if (__sysconf (_SC_V7_LP64_OFF64) < 0) |
137 | break; |
138 | # endif |
139 | string = __LP64_OFF64_CFLAGS; |
140 | string_len = sizeof (__LP64_OFF64_CFLAGS); |
141 | #endif |
142 | break; |
143 | |
144 | case _CS_XBS5_ILP32_OFF32_LDFLAGS: |
145 | case _CS_POSIX_V6_ILP32_OFF32_LDFLAGS: |
146 | case _CS_POSIX_V7_ILP32_OFF32_LDFLAGS: |
147 | #ifdef __ILP32_OFF32_LDFLAGS |
148 | # if CONF_IS_DEFINED_UNSET (_POSIX_V7_ILP32_OFF32 ) |
149 | # error "__ILP32_OFF32_LDFLAGS should not be defined" |
150 | # elif CONF_IS_UNDEFINED (_POSIX_V7_ILP32_OFF32) |
151 | if (__sysconf (_SC_V7_ILP32_OFF32) < 0) |
152 | break; |
153 | # endif |
154 | string = __ILP32_OFF32_LDFLAGS; |
155 | string_len = sizeof (__ILP32_OFF32_LDFLAGS); |
156 | #endif |
157 | break; |
158 | |
159 | case _CS_XBS5_ILP32_OFFBIG_LDFLAGS: |
160 | case _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS: |
161 | case _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS: |
162 | #ifdef __ILP32_OFFBIG_LDFLAGS |
163 | # if CONF_IS_DEFINED_UNSET (_POSIX_V7_ILP32_OFFBIG) |
164 | # error "__ILP32_OFFBIG_LDFLAGS should not be defined" |
165 | # elif CONF_IS_UNDEFINED (_POSIX_V7_ILP32_OFFBIG) |
166 | if (__sysconf (_SC_V7_ILP32_OFFBIG) < 0) |
167 | break; |
168 | # endif |
169 | string = __ILP32_OFFBIG_LDFLAGS; |
170 | string_len = sizeof (__ILP32_OFFBIG_LDFLAGS); |
171 | #endif |
172 | break; |
173 | |
174 | case _CS_XBS5_LP64_OFF64_LDFLAGS: |
175 | case _CS_POSIX_V6_LP64_OFF64_LDFLAGS: |
176 | case _CS_POSIX_V7_LP64_OFF64_LDFLAGS: |
177 | #ifdef __LP64_OFF64_LDFLAGS |
178 | # if CONF_IS_DEFINED_UNSET (_POSIX_V7_LP64_OFF64) |
179 | # error "__LP64_OFF64_LDFLAGS should not be defined" |
180 | # elif CONF_IS_UNDEFINED (_POSIX_V7_LP64_OFF64) |
181 | if (__sysconf (_SC_V7_LP64_OFF64) < 0) |
182 | break; |
183 | # endif |
184 | string = __LP64_OFF64_LDFLAGS; |
185 | string_len = sizeof (__LP64_OFF64_LDFLAGS); |
186 | #endif |
187 | break; |
188 | |
189 | case _CS_LFS_CFLAGS: |
190 | case _CS_LFS_LINTFLAGS: |
191 | #if (CONF_IS_DEFINED_SET (_POSIX_V6_ILP32_OFF32) \ |
192 | && CONF_IS_DEFINED_SET (_POSIX_V6_ILP32_OFFBIG)) |
193 | # define __LFS_CFLAGS "-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" |
194 | /* Signal that we want the new ABI. */ |
195 | string = __LFS_CFLAGS; |
196 | string_len = sizeof (__LFS_CFLAGS); |
197 | #endif |
198 | break; |
199 | |
200 | case _CS_LFS_LDFLAGS: |
201 | case _CS_LFS_LIBS: |
202 | /* No special libraries or linker flags needed. */ |
203 | break; |
204 | |
205 | case _CS_LFS64_CFLAGS: |
206 | case _CS_LFS64_LINTFLAGS: |
207 | #define __LFS64_CFLAGS "-D_LARGEFILE64_SOURCE" |
208 | string = __LFS64_CFLAGS; |
209 | string_len = sizeof (__LFS64_CFLAGS); |
210 | break; |
211 | |
212 | case _CS_LFS64_LDFLAGS: |
213 | case _CS_LFS64_LIBS: |
214 | /* No special libraries or linker flags needed. */ |
215 | break; |
216 | |
217 | case _CS_XBS5_ILP32_OFF32_LIBS: |
218 | case _CS_XBS5_ILP32_OFF32_LINTFLAGS: |
219 | case _CS_XBS5_ILP32_OFFBIG_LIBS: |
220 | case _CS_XBS5_ILP32_OFFBIG_LINTFLAGS: |
221 | case _CS_XBS5_LP64_OFF64_LIBS: |
222 | case _CS_XBS5_LP64_OFF64_LINTFLAGS: |
223 | case _CS_XBS5_LPBIG_OFFBIG_CFLAGS: |
224 | case _CS_XBS5_LPBIG_OFFBIG_LDFLAGS: |
225 | case _CS_XBS5_LPBIG_OFFBIG_LIBS: |
226 | case _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS: |
227 | |
228 | case _CS_POSIX_V6_ILP32_OFF32_LIBS: |
229 | case _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS: |
230 | case _CS_POSIX_V6_ILP32_OFFBIG_LIBS: |
231 | case _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS: |
232 | case _CS_POSIX_V6_LP64_OFF64_LIBS: |
233 | case _CS_POSIX_V6_LP64_OFF64_LINTFLAGS: |
234 | case _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS: |
235 | case _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS: |
236 | case _CS_POSIX_V6_LPBIG_OFFBIG_LIBS: |
237 | case _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS: |
238 | |
239 | case _CS_POSIX_V7_ILP32_OFF32_LIBS: |
240 | case _CS_POSIX_V7_ILP32_OFF32_LINTFLAGS: |
241 | case _CS_POSIX_V7_ILP32_OFFBIG_LIBS: |
242 | case _CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS: |
243 | case _CS_POSIX_V7_LP64_OFF64_LIBS: |
244 | case _CS_POSIX_V7_LP64_OFF64_LINTFLAGS: |
245 | case _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS: |
246 | case _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS: |
247 | case _CS_POSIX_V7_LPBIG_OFFBIG_LIBS: |
248 | case _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS: |
249 | /* GNU libc does not require special actions to use LFS functions. */ |
250 | break; |
251 | |
252 | case _CS_GNU_LIBC_VERSION: |
253 | string = "glibc " VERSION; |
254 | string_len = sizeof ("glibc " VERSION); |
255 | break; |
256 | |
257 | case _CS_GNU_LIBPTHREAD_VERSION: |
258 | #ifdef LIBPTHREAD_VERSION |
259 | string = LIBPTHREAD_VERSION; |
260 | string_len = sizeof LIBPTHREAD_VERSION; |
261 | break; |
262 | #else |
263 | /* No thread library. */ |
264 | __set_errno (EINVAL); |
265 | return 0; |
266 | #endif |
267 | |
268 | case _CS_V6_ENV: |
269 | case _CS_V7_ENV: |
270 | /* Maybe something else is needed in future. */ |
271 | string = "POSIXLY_CORRECT=1" ; |
272 | string_len = sizeof ("POSIXLY_CORRECT=1" ); |
273 | break; |
274 | |
275 | default: |
276 | __set_errno (EINVAL); |
277 | return 0; |
278 | } |
279 | |
280 | if (len > 0 && buf != NULL) |
281 | { |
282 | if (string_len <= len) |
283 | memcpy (buf, string, string_len); |
284 | else |
285 | { |
286 | memcpy (buf, string, len - 1); |
287 | buf[len - 1] = '\0'; |
288 | } |
289 | } |
290 | return string_len; |
291 | } |
292 | libc_hidden_def (__confstr) |
293 | libc_hidden_def (confstr) |
294 | weak_alias (__confstr, confstr) |
295 | |