Imported from ../bash-2.05.tar.gz.
[platform/upstream/bash.git] / examples / loadables / getconf.c
1 /*
2  * ORIGINAL COPYRIGHT STATEMENT:
3  *
4  * Copyright (c) 1994 Winning Strategies, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by Winning Strategies, Inc.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 /*
34  * POSIX.2 getconf utility
35  *
36  * Originally Written by:
37  *      J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
38  *
39  * Heavily modified for inclusion in bash by
40  *      Chet Ramey <chet@po.cwru.edu>
41  */
42
43 #include <stdio.h>
44 #include <limits.h>
45 #include <locale.h>
46 #include <unistd.h>
47 #include <errno.h>
48 #include "bashansi.h"
49 #include "shell.h"
50 #include "builtins.h"
51 #include "stdc.h"
52 #include "common.h"
53 #include "bashgetopt.h"
54
55 struct conf_variable
56 {
57   const char *name;
58   enum { SYSCONF, CONFSTR, PATHCONF, CONSTANT, G_UNDEF } type;
59   long value;
60 };
61
62 /* Some systems do not define these; use POSIX.2 minimum recommended values. */
63 #ifndef _POSIX2_COLL_WEIGHTS_MAX
64 #  define _POSIX2_COLL_WEIGHTS_MAX 2
65 #endif
66
67 static const struct conf_variable conf_table[] =
68 {
69   /* POSIX.2 Configurable Variable Values */
70   { "PATH",                     CONFSTR,        _CS_PATH                },
71   { "CS_PATH",                  CONFSTR,        _CS_PATH                },
72
73   /* POSIX.1 Configurable Variable Values (only Solaris?) */
74 #if defined (_CS_LFS_CFLAGS)
75   { "LFS_CFLAGS",               CONFSTR,        _CS_LFS_CFLAGS          },
76   { "LFS_LDFLAGS",              CONFSTR,        _CS_LFS_LDFLAGS         },
77   { "LFS_LIBS",                 CONFSTR,        _CS_LFS_LIBS            },
78   { "LFS_LINTFLAGS",            CONFSTR,        _CS_LFS_LINTFLAGS       },
79 #endif
80 #if defined (_CS_LFS64_CFLAGS)
81   { "LFS64_CFLAGS",             CONFSTR,        _CS_LFS64_CFLAGS        },
82   { "LFS64_LDFLAGS",            CONFSTR,        _CS_LFS64_LDFLAGS       },
83   { "LFS64_LIBS",               CONFSTR,        _CS_LFS64_LIBS          },
84   { "LFS64_LINTFLAGS",          CONFSTR,        _CS_LFS64_LINTFLAGS     },
85 #endif
86
87   /* Single UNIX Specification version 2 Configurable Variable Values */
88 #if defined (_CS_XBS5_ILP32_OFF32_CFLAGS)
89   { "XBS5_ILP32_OFF32_CFLAGS",          CONFSTR,        _CS_XBS5_ILP32_OFF32_CFLAGS },
90   { "XBS5_ILP32_OFF32_LDFLAGS",         CONFSTR,        _CS_XBS5_ILP32_OFF32_LDFLAGS },
91   { "XBS5_ILP32_OFF32_LIBS",            CONFSTR,        _CS_XBS5_ILP32_OFF32_LIBS },
92   { "XBS5_ILP32_OFF32_LINTFLAGS",       CONFSTR,        _CS_XBS5_ILP32_OFF32_LINTFLAGS },
93   { "XBS5_ILP32_OFFBIG_CFLAGS",         CONFSTR,        _CS_XBS5_ILP32_OFFBIG_CFLAGS },
94   { "XBS5_ILP32_OFFBIG_LDFLAGS",        CONFSTR,        _CS_XBS5_ILP32_OFFBIG_LDFLAGS },
95   { "XBS5_ILP32_OFFBIG_LIBS",           CONFSTR,        _CS_XBS5_ILP32_OFFBIG_LIBS },
96   { "XBS5_ILP32_OFFBIG_LINTFLAGS",      CONFSTR,        _CS_XBS5_ILP32_OFFBIG_LINTFLAGS },
97   { "XBS5_LP64_OFF64_CFLAGS",           CONFSTR,        _CS_XBS5_LP64_OFF64_CFLAGS },
98   { "XBS5_LP64_OFF64_LDFLAGS",          CONFSTR,        _CS_XBS5_LP64_OFF64_LDFLAGS },
99   { "XBS5_LP64_OFF64_LIBS",             CONFSTR,        _CS_XBS5_LP64_OFF64_LIBS },
100   { "XBS5_LP64_OFF64_LINTFLAGS",        CONFSTR,        _CS_XBS5_LP64_OFF64_LINTFLAGS },
101   { "XBS5_LPBIG_OFFBIG_CFLAGS",         CONFSTR,        _CS_XBS5_LPBIG_OFFBIG_CFLAGS },
102   { "XBS5_LPBIG_OFFBIG_LDFLAGS",        CONFSTR,        _CS_XBS5_LPBIG_OFFBIG_LDFLAGS },
103   { "XBS5_LPBIG_OFFBIG_LIBS",           CONFSTR,        _CS_XBS5_LPBIG_OFFBIG_LIBS },
104   { "XBS5_LPBIG_OFFBIG_LINTFLAGS",      CONFSTR,        _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS },
105 #endif /* _CS_XBS5_ILP32_OFF32_CFLAGS */
106
107   /* POSIX.2 Utility Limit Minimum Values */
108 #ifdef _POSIX2_BC_BASE_MAX
109   { "POSIX2_BC_BASE_MAX",       CONSTANT,       _POSIX2_BC_BASE_MAX     },
110 #else
111   { "POSIX2_BC_BASE_MAX",       G_UNDEF,        -1                      },
112 #endif
113 #ifdef _POSIX2_BC_DIM_MAX
114   { "POSIX2_BC_DIM_MAX",        CONSTANT,       _POSIX2_BC_DIM_MAX      },
115 #else
116   { "POSIX2_BC_DIM_MAX",        G_UNDEF,        -1                      },
117 #endif
118 #ifdef _POSIX2_BC_SCALE_MAX
119   { "POSIX2_BC_SCALE_MAX",      CONSTANT,       _POSIX2_BC_SCALE_MAX    },
120 #else
121   { "POSIX2_BC_SCALE_MAX",      G_UNDEF,        -1                      },
122 #endif
123 #ifdef _POSIX2_BC_STRING_MAX
124   { "POSIX2_BC_STRING_MAX",     CONSTANT,       _POSIX2_BC_STRING_MAX   },
125 #else
126   { "POSIX2_BC_STRING_MAX",     G_UNDEF,        -1                      },
127 #endif
128 #ifdef _POSIX2_COLL_WEIGHTS_MAX
129   { "POSIX2_COLL_WEIGHTS_MAX",  CONSTANT,       _POSIX2_COLL_WEIGHTS_MAX },
130 #else
131   { "POSIX2_COLL_WEIGHTS_MAX",  G_UNDEF,        -1                       },
132 #endif
133 #if defined (_POSIX2_EQUIV_CLASS_MAX)
134   { "POSIX2_EQUIV_CLASS_MAX",   CONSTANT,       _POSIX2_EQUIV_CLASS_MAX },
135 #endif
136 #ifdef _POSIX2_EXPR_NEST_MAX
137   { "POSIX2_EXPR_NEST_MAX",     CONSTANT,       _POSIX2_EXPR_NEST_MAX   },
138 #else
139   { "POSIX2_EXPR_NEST_MAX",     G_UNDEF,        -1                      },
140 #endif
141 #ifdef _POSIX2_LINE_MAX
142   { "POSIX2_LINE_MAX",          CONSTANT,       _POSIX2_LINE_MAX        },
143 #else
144   { "POSIX2_LINE_MAX",          G_UNDEF,        -1                      },
145 #endif
146 #ifdef _POSIX2_RE_DUP_MAX
147   { "POSIX2_RE_DUP_MAX",        CONSTANT,       _POSIX2_RE_DUP_MAX      },
148 #else
149   { "POSIX2_RE_DUP_MAX",        G_UNDEF,        -1                      },
150 #endif
151 #if defined (_POSIX2_VERSION)
152   { "POSIX2_VERSION",           CONSTANT,       _POSIX2_VERSION         },
153 #else
154 #  if !defined (_SC_2_VERSION)
155   { "POSIX2_VERSION",           G_UNDEF,        -1                      },
156 #  endif
157 #endif
158
159   /* POSIX.1 Minimum Values */
160   { "_POSIX_ARG_MAX",           CONSTANT,       _POSIX_ARG_MAX          },
161   { "_POSIX_CHILD_MAX",         CONSTANT,       _POSIX_CHILD_MAX        },
162   { "_POSIX_LINK_MAX",          CONSTANT,       _POSIX_LINK_MAX         },
163   { "_POSIX_MAX_CANON",         CONSTANT,       _POSIX_MAX_CANON        },
164   { "_POSIX_MAX_INPUT",         CONSTANT,       _POSIX_MAX_INPUT        },
165   { "_POSIX_NAME_MAX",          CONSTANT,       _POSIX_NAME_MAX         },
166   { "_POSIX_NGROUPS_MAX",       CONSTANT,       _POSIX_NGROUPS_MAX      },
167   { "_POSIX_OPEN_MAX",          CONSTANT,       _POSIX_OPEN_MAX         },
168   { "_POSIX_PATH_MAX",          CONSTANT,       _POSIX_PIPE_BUF         },
169   { "_POSIX_PIPE_BUF",          CONSTANT,       _POSIX_PIPE_BUF         },
170   { "_POSIX_SSIZE_MAX",         CONSTANT,       _POSIX_SSIZE_MAX        },
171   { "_POSIX_STREAM_MAX",        CONSTANT,       _POSIX_STREAM_MAX       },
172   { "_POSIX_TZNAME_MAX",        CONSTANT,       _POSIX_TZNAME_MAX       },
173
174   /* POSIX.2 Symbolic Utility Limits */
175   { "BC_BASE_MAX",              SYSCONF,        _SC_BC_BASE_MAX         },
176   { "BC_DIM_MAX",               SYSCONF,        _SC_BC_DIM_MAX          },
177   { "BC_SCALE_MAX",             SYSCONF,        _SC_BC_SCALE_MAX        },
178   { "BC_STRING_MAX",            SYSCONF,        _SC_BC_STRING_MAX       },
179   { "COLL_WEIGHTS_MAX",         SYSCONF,        _SC_COLL_WEIGHTS_MAX    },
180   { "EXPR_NEST_MAX",            SYSCONF,        _SC_EXPR_NEST_MAX       },
181   { "LINE_MAX",                 SYSCONF,        _SC_LINE_MAX            },
182   { "RE_DUP_MAX",               SYSCONF,        _SC_RE_DUP_MAX          },
183
184   /* POSIX.2 Optional Facility Configuration Values */
185 #ifdef _SC_2_C_BIND
186   { "POSIX2_C_BIND",            SYSCONF,        _SC_2_C_BIND            },
187 #else
188   { "POSIX2_C_BIND",            G_UNDEF,        -1                      },
189 #endif
190 #ifdef _SC_2_C_DEV
191   { "POSIX2_C_DEV",             SYSCONF,        _SC_2_C_DEV             },
192 #else
193   { "POSIX2_C_DEV",             G_UNDEF,        -1                      },
194 #endif
195 #if defined (_SC_2_C_VERSION)
196   { "POSIX2_C_VERSION",         SYSCONF,        _SC_2_C_VERSION         },
197 #else
198   { "POSIX2_C_VERSION",         G_UNDEF,        -1                      },
199 #endif
200 #if defined (_SC_2_CHAR_TERM)
201   { "POSIX2_CHAR_TERM",         SYSCONF,        _SC_2_CHAR_TERM         },
202 #else
203   { "POSIX2_CHAR_TERM",         G_UNDEF,        -1                      },
204 #endif
205 #ifdef _SC_2_FORT_DEV
206   { "POSIX2_FORT_DEV",          SYSCONF,        _SC_2_FORT_DEV          },
207 #else
208   { "POSIX2_FORT_DEV",          G_UNDEF,        -1                      },
209 #endif
210 #ifdef _SC_2_FORT_RUN
211   { "POSIX2_FORT_RUN",          SYSCONF,        _SC_2_FORT_RUN          },
212 #else
213   { "POSIX2_FORT_RUN",          G_UNDEF,        -1                      },
214 #endif
215 #ifdef _SC_2_LOCALEDEF
216   { "POSIX2_LOCALEDEF",         SYSCONF,        _SC_2_LOCALEDEF         },
217 #else
218   { "POSIX2_LOCALEDEF",         G_UNDEF,        -1                      },
219 #endif
220 #ifdef _SC_2_SW_DEV
221   { "POSIX2_SW_DEV",            SYSCONF,        _SC_2_SW_DEV            },
222 #else
223   { "POSIX2_SW_DEV",            G_UNDEF,        -1                      },
224 #endif
225 #if defined (_SC2_UPE)
226   { "POSIX2_UPE",               SYSCONF,        _SC_2_UPE               },
227 #else
228   { "POSIX2_UPE",               G_UNDEF,        -1                      },
229 #endif
230 #if !defined (_POSIX2_VERSION) && defined (_SC_2_VERSION)
231   { "POSIX2_VERSION"            SYSCONF,        _SC_2_VERSION           },
232 #endif
233
234   /* POSIX.1 Configurable System Variables */
235   { "ARG_MAX",                  SYSCONF,        _SC_ARG_MAX             },
236   { "CHILD_MAX",                SYSCONF,        _SC_CHILD_MAX           },
237   { "CLK_TCK",                  SYSCONF,        _SC_CLK_TCK             },
238   { "NGROUPS_MAX",              SYSCONF,        _SC_NGROUPS_MAX         },
239   { "OPEN_MAX",                 SYSCONF,        _SC_OPEN_MAX            },
240   { "STREAM_MAX",               SYSCONF,        _SC_STREAM_MAX          },
241   { "TZNAME_MAX",               SYSCONF,        _SC_TZNAME_MAX          },
242   { "_POSIX_JOB_CONTROL",       SYSCONF,        _SC_JOB_CONTROL         },
243   { "_POSIX_SAVED_IDS",         SYSCONF,        _SC_SAVED_IDS           },
244   { "_POSIX_VERSION",           SYSCONF,        _SC_VERSION             },
245
246   /* POSIX.1 Optional Facility Configuration Values */
247 #if defined (_SC_ASYNCHRONOUS_IO)
248   { "_POSIX_ASYNCHRONOUS_IO",   SYSCONF,        _SC_ASYNCHRONOUS_IO     },
249 #endif
250 #if defined (_SC_FSYNC)
251   { "_POSIX_FSYNC",             SYSCONF,        _SC_FSYNC               },
252 #endif
253 #if defined (_SC_MAPPED_FILES)
254   { "_POSIX_MAPPED_FILES",      SYSCONF,        _SC_MAPPED_FILES        },
255 #endif
256 #if defined (_SC_MEMLOCK)
257   { "_POSIX_MEMLOCK",           SYSCONF,        _SC_MEMLOCK             },
258 #endif
259 #if defined (_SC_MEMLOCK_RANGE)
260   { "_POSIX_MEMLOCK_RANGE",     SYSCONF,        _SC_MEMLOCK_RANGE       },
261 #endif
262 #if defined (_SC_MEMORY_PROTECTION)
263   { "_POSIX_MEMORY_PROTECTION", SYSCONF,        _SC_MEMORY_PROTECTION   },
264 #endif
265 #if defined (_SC_MESSAGE_PASSING)
266   { "_POSIX_MESSAGE_PASSING",   SYSCONF,        _SC_MESSAGE_PASSING     },
267 #endif
268 #if defined (SC_PRIORITIZED_IO)
269   { "_POSIX_PRIORITIZED_IO",    SYSCONF,        _SC_PRIORITIZED_IO      },
270 #endif
271 #if defined (_SC_PRIORITY_SCHEDULING)
272   { "_POSIX_PRIORITY_SCHEDULING", SYSCONF,      _SC_PRIORITY_SCHEDULING },
273 #endif
274 #if defined (_SC_REALTIME_SIGNALS)
275   { "_POSIX_REALTIME_SIGNALS",  SYSCONF,        _SC_REALTIME_SIGNALS    },
276 #endif
277 #if defined (_SC_SEMAPHORES)
278   { "_POSIX_SEMAPHORES",        SYSCONF,        _SC_SEMAPHORES          },
279 #endif
280 #if defined (_SC_SHARED_MEMORY_OBJECTS)
281   { "_POSIX_SHARED_MEMORY_OBJECTS", SYSCONF,    _SC_SHARED_MEMORY_OBJECTS },
282 #endif
283 #if defined (_SC_SYNCHRONIZED_IO)
284   { "_POSIX_SYNCHRONIZED_IO",   SYSCONF,        _SC_SYNCHRONIZED_IO     },
285 #endif
286 #if defined (_SC_TIMERS)
287   { "_POSIX_TIMERS",            SYSCONF,        _SC_TIMERS              },
288 #endif
289 #if defined (_SC_THREADS)
290   { "_POSIX_THREADS",           SYSCONF,        _SC_THREADS             },
291 #endif
292 #if defined (_SC_THREADS)
293   { "_POSIX_THREAD_ATTR_STACKADDR", SYSCONF,    _SC_THREAD_ATTR_STACKADDR },
294 #endif
295 #if defined (_SC_THREAD_ATTR_STACKSIZE)
296   { "_POSIX_THREAD_ATTR_STACKSIZE", SYSCONF,    _SC_THREAD_ATTR_STACKSIZE },
297 #endif
298 #if defined (_SC_THREAD_PRIORITY_SCHEDULING)
299   { "_POSIX_THREAD_PRIORITY_SCHEDULING", SYSCONF, _SC_THREAD_PRIORITY_SCHEDULING },
300 #endif
301 #if defined (_SC_THREAD_PRIO_INHERIT)
302   { "_POSIX_THREAD_PRIO_INHERIT", SYSCONF,      _SC_THREAD_PRIO_INHERIT },
303 #endif
304 #if defined (_SC_THREAD_PRIO_PROTECT)
305   { "_POSIX_THREAD_PRIO_PROTECT", SYSCONF,      _SC_THREAD_PRIO_PROTECT },
306 #endif
307 #if defined (_SC_THREAD_PROCESS_SHARED)
308   { "_POSIX_THREAD_PROCESS_SHARED", SYSCONF,    _SC_THREAD_PROCESS_SHARED },
309 #endif
310 #if defined (_SC_THREAD_SAFE_FUNCTIONS)
311   { "_POSIX_THREAD_SAFE_FUNCTIONS", SYSCONF,    _SC_THREAD_SAFE_FUNCTIONS },
312 #endif
313
314   /* XPG 4.2 Configurable System Variables. */
315 #if defined (_SC_ATEXIT_MAX)
316   { "ATEXIT_MAX",               SYSCONF,        _SC_ATEXIT_MAX          },
317 #endif
318 #if defined (_SC_IOV_MAX)
319   { "IOV_MAX",                  SYSCONF,        _SC_IOV_MAX             },
320 #endif
321 #if defined (_SC_PAGESIZE)
322   { "PAGESIZE",                 SYSCONF,        _SC_PAGESIZE            },
323 #endif
324 #if defined (_SC_PAGE_SIZE)
325   { "PAGE_SIZE",                SYSCONF,        _SC_PAGE_SIZE           },
326 #endif
327
328 #if defined (_SC_AIO_LISTIO_MAX)
329   { "AIO_LISTIO_MAX",           SYSCONF,        _SC_AIO_LISTIO_MAX      },
330 #endif
331 #if defined (_SC_AIO_MAX)
332   { "AIO_MAX",                  SYSCONF,        _SC_AIO_MAX             },
333 #endif
334 #if defined (_SC_AIO_PRIO_DELTA_MAX)
335   { "AIO_PRIO_DELTA_MAX",       SYSCONF,        _SC_AIO_PRIO_DELTA_MAX  },
336 #endif
337 #if defined (_SC_DELAYTIMER_MAX)
338   { "DELAYTIMER_MAX",           SYSCONF,        _SC_DELAYTIMER_MAX      },
339 #endif
340 #if defined (_SC_GETGR_R_SIZE_MAX)
341   { "GETGR_R_SIZE_MAX",         SYSCONF,        _SC_GETGR_R_SIZE_MAX    },
342 #endif
343 #if defined (_SC_GETPW_R_SIZE_MAX)
344   { "GETPW_R_SIZE_MAX",         SYSCONF,        _SC_GETPW_R_SIZE_MAX    },
345 #endif
346 #if defined (_SC_MQ_OPEN_MAX)
347   { "MQ_OPEN_MAX",              SYSCONF,        _SC_MQ_OPEN_MAX         },
348 #endif
349 #if defined (_SC_MQ_PRIO_MAX)
350   { "MQ_PRIO_MAX",              SYSCONF,        _SC_MQ_PRIO_MAX         },
351 #endif
352 #if defined (_SC_RTSIG_MAX)
353   { "RTSIG_MAX",                SYSCONF,        _SC_RTSIG_MAX           },
354 #endif
355 #if defined (_SC_SEM_NSEMS_MAX)
356   { "SEM_NSEMS_MAX",            SYSCONF,        _SC_SEM_NSEMS_MAX       },
357 #endif
358 #if defined (_SC_SEM_VALUE_MAX)
359   { "SEM_VALUE_MAX",            SYSCONF,        _SC_SEM_VALUE_MAX       },
360 #endif
361 #if defined (_SC_SIGQUEUE_MAX)
362   { "SIGQUEUE_MAX",             SYSCONF,        _SC_SIGQUEUE_MAX        },
363 #endif
364 #if defined (_SC_TIMER_MAX)
365   { "TIMER_MAX",                SYSCONF,        _SC_TIMER_MAX           },
366 #endif
367
368 #if defined (_SC_LOGIN_NAME_MAX)
369   { "LOGIN_NAME_MAX",           SYSCONF,        _SC_LOGIN_NAME_MAX      },
370 #endif
371 #if defined (_SC_LOGNAME_MAX)
372   { "LOGNAME_MAX",              SYSCONF,        _SC_LOGNAME_MAX         },
373 #endif
374 #if defined (_SC_TTY_NAME_MAX)
375   { "TTY_NAME_MAX",             SYSCONF,        _SC_TTY_NAME_MAX        },
376 #endif
377
378 #if defined (_SC_THREAD_DESTRUCTOR_ITERATIONS)
379   { "PTHREAD_DESTRUCTOR_ITERATIONS", SYSCONF,   _SC_THREAD_DESTRUCTOR_ITERATIONS },
380 #endif
381 #if defined (_SC_THREAD_KEYS_MAX)
382   { "PTHREAD_KEYS_MAX",         SYSCONF,        _SC_THREAD_KEYS_MAX },
383 #endif
384 #if defined (_SC_THREAD_STACK_MIN)
385   { "PTHREAD_STACK_MIN",        SYSCONF,        _SC_THREAD_STACK_MIN },
386 #endif
387 #if defined (_SC_THREAD_THREADS_MAX)
388   { "PTHREAD_THREADS_MAX",      SYSCONF,        _SC_THREAD_THREADS_MAX },
389 #endif
390
391   /* XPG 4.2 Optional Facility Configuration Values */
392 #if defined (_SC_XOPEN_UNIX)
393   { "_XOPEN_UNIX",              SYSCONF,        _SC_XOPEN_UNIX          },
394   { "_XOPEN_CRYPT",             SYSCONF,        _SC_XOPEN_CRYPT         },
395   { "_XOPEN_ENH_I18N",          SYSCONF,        _SC_XOPEN_ENH_I18N      },
396   { "_XOPEN_SHM",               SYSCONF,        _SC_XOPEN_SHM           },
397   { "_XOPEN_VERSION",           SYSCONF,        _SC_XOPEN_VERSION       },
398 #  if defined (_SC_XOPEN_XCU_VERSION)
399   { "_XOPEN_XCU_VERSION",       SYSCONF,        _SC_XOPEN_XCU_VERSION   },
400 #  endif
401 #endif
402 #if defined (_SC_XOPEN_REALTIME)
403   { "_XOPEN_REALTIME",          SYSCONF,        _SC_XOPEN_REALTIME      },
404   { "_XOPEN_REALTIME_THREADS",  SYSCONF,        _SC_XOPEN_REALTIME_THREADS },
405 #endif
406 #if defined (_SC_XOPEN_LEGACY)
407   { "_XOPEN_LEGACY",            SYSCONF,        _SC_XOPEN_LEGACY        },
408 #endif /* _SC_XOPEN_LEGACY */
409
410   /* Single UNIX Specification version 2 Optional Facility Configuration Values */
411 #if defined (_SC_XBS5_ILP32_OFF32)
412   { "_XBS5_ILP32_OFF32",        SYSCONF,        _SC_XBS5_ILP32_OFF32    },
413   { "_XBS5_ILP32_OFFBIG",       SYSCONF,        _SC_XBS5_ILP32_OFFBIG   },
414   { "_XBS5_LP64_OFF64",         SYSCONF,        _SC_XBS5_LP64_OFF64     },
415   { "_XBS5_LPBIG_OFFBIG",       SYSCONF,        _SC_XBS5_LPBIG_OFFBIG   },
416 #endif /* _SC_XBS5_ILP32_OFF32 */
417
418   /* POSIX.1 Configurable Pathname Values */
419   { "LINK_MAX",                 PATHCONF,       _PC_LINK_MAX            },
420   { "MAX_CANON",                PATHCONF,       _PC_MAX_CANON           },
421   { "MAX_INPUT",                PATHCONF,       _PC_MAX_INPUT           },
422   { "NAME_MAX",                 PATHCONF,       _PC_NAME_MAX            },
423   { "PATH_MAX",                 PATHCONF,       _PC_PATH_MAX            },
424   { "PIPE_BUF",                 PATHCONF,       _PC_PIPE_BUF            },
425   { "_POSIX_CHOWN_RESTRICTED",  PATHCONF,       _PC_CHOWN_RESTRICTED    },
426   { "_POSIX_NO_TRUNC",          PATHCONF,       _PC_NO_TRUNC            },
427   { "_POSIX_VDISABLE",          PATHCONF,       _PC_VDISABLE            },
428
429   /* XPG 4.2 Configurable Pathname Values */
430 #if defined (_PC_FILESIZEBITS)
431   { "FILESIZEBITS",             PATHCONF,       _PC_FILESIZEBITS },
432 #endif
433 #if defined (_PC_ASYNC_IO)
434   { "_POSIX_ASYNC_IO",          PATHCONF,       _PC_ASYNC_IO },
435 #endif
436 #if defined (_PC_PRIO_IO)
437   { "_POSIX_PRIO_IO",           PATHCONF,       _PC_PRIO_IO },
438 #endif
439 #if defined (_PC_SYNC_IO)
440   { "_POSIX_SYNC_IO",           PATHCONF,       _PC_SYNC_IO },
441 #endif
442
443   { NULL }
444 };
445
446 static int num_getconf_variables = sizeof(conf_table) / sizeof(struct conf_variable) - 1;
447
448 extern char *this_command_name;
449 extern char *xmalloc ();
450 extern char **make_builtin_argv ();
451
452 static void getconf_help ();
453 static int getconf_print ();
454 static int getconf_one ();
455 static int getconf_all ();
456
457 int
458 getconf_builtin (list)
459      WORD_LIST *list;
460 {
461   int c, r, opt, aflag;
462   char **v;
463
464   aflag = 0;
465   reset_internal_getopt();
466   while ((opt = internal_getopt (list, "ah")) != -1) {
467         switch (opt) {
468         case 'a':
469                 aflag = 1;
470                 break;
471         case 'h':
472                 getconf_help();
473                 return(EXECUTION_SUCCESS);
474         default:
475                 builtin_usage();
476                 return(EX_USAGE);
477         }
478   }
479  
480   list = loptend;
481   if ((aflag == 0 && list == 0) || (aflag && list) || list_length(list) > 2) {
482         builtin_usage();
483         return(EX_USAGE);
484   }
485
486   r = aflag ? getconf_all() : getconf_one(list);
487
488   return r;
489 }
490
491 static void
492 getconf_help()
493 {
494         const struct conf_variable *cp;
495         register int i, column;
496
497         builtin_usage();
498         printf("Acceptable variable names are:\n");
499         for (cp = conf_table; cp->name != NULL; cp++) {
500                 if (cp->type == PATHCONF)
501                         printf("%s pathname\n", cp->name);
502                 else
503                         printf("%s\n", cp->name);
504         }
505 }
506
507 static int
508 getconf_print(cp, vpath, all)
509 struct conf_variable *cp;
510 char *vpath;
511 int all;
512 {
513         long val;
514         char *sval;
515         size_t slen;
516
517         switch (cp->type) {
518         case G_UNDEF:
519                 printf("undefined\n");
520                 break;
521
522         case CONSTANT:
523                 printf("%ld\n", cp->value);
524                 break;
525
526         case CONFSTR:
527                 errno = 0;
528                 slen = confstr (cp->value, (char *) 0, (size_t) 0);
529                 if (slen == 0) {
530                         if (errno != 0) {
531                                 if (all)
532                                         printf ("getconf: %s\n", strerror(errno));
533                                 else
534                                         builtin_error ("%s", strerror(errno));
535                         } else
536                                 printf ("undefined\n");
537                         return (EXECUTION_FAILURE);
538                 }
539                 sval = xmalloc(slen);
540
541                 confstr(cp->value, sval, slen);
542                 printf("%s\n", sval);
543                 free(sval);
544                 break;
545
546         case SYSCONF:
547                 errno = 0;
548                 if ((val = sysconf(cp->value)) == -1) {
549                         if (errno != 0) {
550                                 if (all)
551                                         printf("getconf: %s\n", strerror (errno));
552                                 else
553                                         builtin_error ("%s", strerror (errno));
554                                 return (EXECUTION_FAILURE);
555                         }
556
557                         printf ("undefined\n");
558                 } else {
559                         printf("%ld\n", val);
560                 }
561                 break;
562
563         case PATHCONF:
564                 errno = 0;
565                 if ((val = pathconf(vpath, cp->value)) == -1) {
566                         if (errno != 0) {
567                                 if (all)
568                                         printf("getconf: %s: %s\n", vpath, strerror (errno));
569                                 else
570                                         builtin_error ("%s: %s", vpath, strerror (errno));
571                                 return (EXECUTION_FAILURE);
572                         }
573
574                         printf ("undefined\n");
575                 } else {
576                         printf ("%ld\n", val);
577                 }
578                 break;
579         }
580
581         return ((ferror(stdout) || cp->type == G_UNDEF) ? EXECUTION_FAILURE
582                                                         : EXECUTION_SUCCESS);
583 }
584
585 static int
586 getconf_all()
587 {
588         const struct conf_variable *cp;
589         int ret;
590
591         ret = EXECUTION_SUCCESS;
592         for (cp = conf_table; cp->name != NULL; cp++) {
593                 printf("%-35s", cp->name);
594                 if (getconf_print(cp, ".", 1) == EXECUTION_FAILURE)
595                         ret = EXECUTION_FAILURE;
596         }
597         return ret;
598 }
599
600 static int
601 getconf_one(list)
602         WORD_LIST *list;
603 {
604         const struct conf_variable *cp;
605         char *vname, *vpath;
606
607         vname = list->word->word;
608         vpath = (list->next && list->next->word) ? list->next->word->word
609                                                  : (char *)NULL;
610
611         for (cp = conf_table; cp->name != NULL; cp++) {
612                 if (strcmp(vname, cp->name) == 0)
613                         break;
614         }
615         if (cp->name == NULL) {
616                 builtin_error ("%s: unknown variable", vname);
617                 return (EXECUTION_FAILURE);
618         }
619
620         if (cp->type == PATHCONF) {
621                 if (list->next == 0) {
622                         builtin_usage();
623                         return(EX_USAGE);
624                 }
625         } else {
626                 if (list->next) {
627                         builtin_usage();
628                         return(EX_USAGE);
629                 }
630         }
631
632         return (getconf_print(cp, vpath, 0));
633 }
634
635 static char *getconf_doc[] = {
636         "getconf writes the current value of a configurable system limit or",
637         "option variable to the standard output.",
638         (char *)NULL
639 };
640
641 struct builtin getconf_struct = {
642         "getconf",
643         getconf_builtin,
644         BUILTIN_ENABLED,
645         getconf_doc,
646         "getconf -a or getconf -h or getconf sysvar or getconf pathvar pathname",
647         0
648 };