64407cc9a22e92c97cc4b739cd6f70259b514347
[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 } 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   { "POSIX2_BC_BASE_MAX",       CONSTANT,       _POSIX2_BC_BASE_MAX     },
109   { "POSIX2_BC_DIM_MAX",        CONSTANT,       _POSIX2_BC_DIM_MAX      },
110   { "POSIX2_BC_SCALE_MAX",      CONSTANT,       _POSIX2_BC_SCALE_MAX    },
111   { "POSIX2_BC_STRING_MAX",     CONSTANT,       _POSIX2_BC_STRING_MAX   },
112   { "POSIX2_COLL_WEIGHTS_MAX",  CONSTANT,       _POSIX2_COLL_WEIGHTS_MAX },
113 #if defined (_POSIX2_EQUIV_CLASS_MAX)
114   { "POSIX2_EQUIV_CLASS_MAX",   CONSTANT,       _POSIX2_EQUIV_CLASS_MAX },
115 #endif
116   { "POSIX2_EXPR_NEST_MAX",     CONSTANT,       _POSIX2_EXPR_NEST_MAX   },
117   { "POSIX2_LINE_MAX",          CONSTANT,       _POSIX2_LINE_MAX        },
118   { "POSIX2_RE_DUP_MAX",        CONSTANT,       _POSIX2_RE_DUP_MAX      },
119 #if defined (_POSIX2_VERSION)
120   { "POSIX2_VERSION",           CONSTANT,       _POSIX2_VERSION         },
121 #endif
122
123   /* POSIX.1 Minimum Values */
124   { "_POSIX_ARG_MAX",           CONSTANT,       _POSIX_ARG_MAX          },
125   { "_POSIX_CHILD_MAX",         CONSTANT,       _POSIX_CHILD_MAX        },
126   { "_POSIX_LINK_MAX",          CONSTANT,       _POSIX_LINK_MAX         },
127   { "_POSIX_MAX_CANON",         CONSTANT,       _POSIX_MAX_CANON        },
128   { "_POSIX_MAX_INPUT",         CONSTANT,       _POSIX_MAX_INPUT        },
129   { "_POSIX_NAME_MAX",          CONSTANT,       _POSIX_NAME_MAX         },
130   { "_POSIX_NGROUPS_MAX",       CONSTANT,       _POSIX_NGROUPS_MAX      },
131   { "_POSIX_OPEN_MAX",          CONSTANT,       _POSIX_OPEN_MAX         },
132   { "_POSIX_PATH_MAX",          CONSTANT,       _POSIX_PIPE_BUF         },
133   { "_POSIX_PIPE_BUF",          CONSTANT,       _POSIX_PIPE_BUF         },
134   { "_POSIX_SSIZE_MAX",         CONSTANT,       _POSIX_SSIZE_MAX        },
135   { "_POSIX_STREAM_MAX",        CONSTANT,       _POSIX_STREAM_MAX       },
136   { "_POSIX_TZNAME_MAX",        CONSTANT,       _POSIX_TZNAME_MAX       },
137
138   /* POSIX.2 Symbolic Utility Limits */
139   { "BC_BASE_MAX",              SYSCONF,        _SC_BC_BASE_MAX         },
140   { "BC_DIM_MAX",               SYSCONF,        _SC_BC_DIM_MAX          },
141   { "BC_SCALE_MAX",             SYSCONF,        _SC_BC_SCALE_MAX        },
142   { "BC_STRING_MAX",            SYSCONF,        _SC_BC_STRING_MAX       },
143   { "COLL_WEIGHTS_MAX",         SYSCONF,        _SC_COLL_WEIGHTS_MAX    },
144   { "EXPR_NEST_MAX",            SYSCONF,        _SC_EXPR_NEST_MAX       },
145   { "LINE_MAX",                 SYSCONF,        _SC_LINE_MAX            },
146   { "RE_DUP_MAX",               SYSCONF,        _SC_RE_DUP_MAX          },
147
148   /* POSIX.2 Optional Facility Configuration Values */
149   { "POSIX2_C_BIND",            SYSCONF,        _SC_2_C_BIND            },
150   { "POSIX2_C_DEV",             SYSCONF,        _SC_2_C_DEV             },
151 #if defined (_SC_2_C_VERSION)
152   { "POSIX2_C_VERSION",         SYSCONF,        _SC_2_C_VERSION         },
153 #endif
154 #if defined (_SC_2_CHAR_TERM)
155   { "POSIX2_CHAR_TERM",         SYSCONF,        _SC_2_CHAR_TERM         },
156 #endif
157   { "POSIX2_FORT_DEV",          SYSCONF,        _SC_2_FORT_DEV          },
158   { "POSIX2_FORT_RUN",          SYSCONF,        _SC_2_FORT_RUN          },
159   { "POSIX2_LOCALEDEF",         SYSCONF,        _SC_2_LOCALEDEF         },
160   { "POSIX2_SW_DEV",            SYSCONF,        _SC_2_SW_DEV            },
161 #if defined (_SC2_UPE)
162   { "POSIX2_UPE",               SYSCONF,        _SC_2_UPE               },
163 #endif
164 #if !defined (_POSIX2_VERSION) && defined (_SC_2_VERSION)
165   { "POSIX2_VERSION"            SYSCONF,        _SC_2_VERSION           },
166 #endif
167
168   /* POSIX.1 Configurable System Variables */
169   { "ARG_MAX",                  SYSCONF,        _SC_ARG_MAX             },
170   { "CHILD_MAX",                SYSCONF,        _SC_CHILD_MAX           },
171   { "CLK_TCK",                  SYSCONF,        _SC_CLK_TCK             },
172   { "NGROUPS_MAX",              SYSCONF,        _SC_NGROUPS_MAX         },
173   { "OPEN_MAX",                 SYSCONF,        _SC_OPEN_MAX            },
174   { "STREAM_MAX",               SYSCONF,        _SC_STREAM_MAX          },
175   { "TZNAME_MAX",               SYSCONF,        _SC_TZNAME_MAX          },
176   { "_POSIX_JOB_CONTROL",       SYSCONF,        _SC_JOB_CONTROL         },
177   { "_POSIX_SAVED_IDS",         SYSCONF,        _SC_SAVED_IDS           },
178   { "_POSIX_VERSION",           SYSCONF,        _SC_VERSION             },
179
180   /* POSIX.1 Optional Facility Configuration Values */
181 #if defined (_SC_ASYNCHRONOUS_IO)
182   { "_POSIX_ASYNCHRONOUS_IO",   SYSCONF,        _SC_ASYNCHRONOUS_IO     },
183 #endif
184 #if defined (_SC_FSYNC)
185   { "_POSIX_FSYNC",             SYSCONF,        _SC_FSYNC               },
186 #endif
187 #if defined (_SC_MAPPED_FILES)
188   { "_POSIX_MAPPED_FILES",      SYSCONF,        _SC_MAPPED_FILES        },
189 #endif
190 #if defined (_SC_MEMLOCK)
191   { "_POSIX_MEMLOCK",           SYSCONF,        _SC_MEMLOCK             },
192 #endif
193 #if defined (_SC_MEMLOCK_RANGE)
194   { "_POSIX_MEMLOCK_RANGE",     SYSCONF,        _SC_MEMLOCK_RANGE       },
195 #endif
196 #if defined (_SC_MEMORY_PROTECTION)
197   { "_POSIX_MEMORY_PROTECTION", SYSCONF,        _SC_MEMORY_PROTECTION   },
198 #endif
199 #if defined (_SC_MESSAGE_PASSING)
200   { "_POSIX_MESSAGE_PASSING",   SYSCONF,        _SC_MESSAGE_PASSING     },
201 #endif
202 #if defined (SC_PRIORITIZED_IO)
203   { "_POSIX_PRIORITIZED_IO",    SYSCONF,        _SC_PRIORITIZED_IO      },
204 #endif
205 #if defined (_SC_PRIORITY_SCHEDULING)
206   { "_POSIX_PRIORITY_SCHEDULING", SYSCONF,      _SC_PRIORITY_SCHEDULING },
207 #endif
208 #if defined (_SC_REALTIME_SIGNALS)
209   { "_POSIX_REALTIME_SIGNALS",  SYSCONF,        _SC_REALTIME_SIGNALS    },
210 #endif
211 #if defined (_SC_SEMAPHORES)
212   { "_POSIX_SEMAPHORES",        SYSCONF,        _SC_SEMAPHORES          },
213 #endif
214 #if defined (_SC_SHARED_MEMORY_OBJECTS)
215   { "_POSIX_SHARED_MEMORY_OBJECTS", SYSCONF,    _SC_SHARED_MEMORY_OBJECTS },
216 #endif
217 #if defined (_SC_SYNCHRONIZED_IO)
218   { "_POSIX_SYNCHRONIZED_IO",   SYSCONF,        _SC_SYNCHRONIZED_IO     },
219 #endif
220 #if defined (_SC_TIMERS)
221   { "_POSIX_TIMERS",            SYSCONF,        _SC_TIMERS              },
222 #endif
223 #if defined (_SC_THREADS)
224   { "_POSIX_THREADS",           SYSCONF,        _SC_THREADS             },
225 #endif
226 #if defined (_SC_THREADS)
227   { "_POSIX_THREAD_ATTR_STACKADDR", SYSCONF,    _SC_THREAD_ATTR_STACKADDR },
228 #endif
229 #if defined (_SC_THREAD_ATTR_STACKSIZE)
230   { "_POSIX_THREAD_ATTR_STACKSIZE", SYSCONF,    _SC_THREAD_ATTR_STACKSIZE },
231 #endif
232 #if defined (_SC_THREAD_PRIORITY_SCHEDULING)
233   { "_POSIX_THREAD_PRIORITY_SCHEDULING", SYSCONF, _SC_THREAD_PRIORITY_SCHEDULING },
234 #endif
235 #if defined (_SC_THREAD_PRIO_INHERIT)
236   { "_POSIX_THREAD_PRIO_INHERIT", SYSCONF,      _SC_THREAD_PRIO_INHERIT },
237 #endif
238 #if defined (_SC_THREAD_PRIO_PROTECT)
239   { "_POSIX_THREAD_PRIO_PROTECT", SYSCONF,      _SC_THREAD_PRIO_PROTECT },
240 #endif
241 #if defined (_SC_THREAD_PROCESS_SHARED)
242   { "_POSIX_THREAD_PROCESS_SHARED", SYSCONF,    _SC_THREAD_PROCESS_SHARED },
243 #endif
244 #if defined (_SC_THREAD_SAFE_FUNCTIONS)
245   { "_POSIX_THREAD_SAFE_FUNCTIONS", SYSCONF,    _SC_THREAD_SAFE_FUNCTIONS },
246 #endif
247
248   /* XPG 4.2 Configurable System Variables. */
249 #if defined (_SC_ATEXIT_MAX)
250   { "ATEXIT_MAX",               SYSCONF,        _SC_ATEXIT_MAX          },
251 #endif
252 #if defined (_SC_IOV_MAX)
253   { "IOV_MAX",                  SYSCONF,        _SC_IOV_MAX             },
254 #endif
255 #if defined (_SC_PAGESIZE)
256   { "PAGESIZE",                 SYSCONF,        _SC_PAGESIZE            },
257 #endif
258 #if defined (_SC_PAGE_SIZE)
259   { "PAGE_SIZE",                SYSCONF,        _SC_PAGE_SIZE           },
260 #endif
261
262 #if defined (_SC_AIO_LISTIO_MAX)
263   { "AIO_LISTIO_MAX",           SYSCONF,        _SC_AIO_LISTIO_MAX      },
264 #endif
265 #if defined (_SC_AIO_MAX)
266   { "AIO_MAX",                  SYSCONF,        _SC_AIO_MAX             },
267 #endif
268 #if defined (_SC_AIO_PRIO_DELTA_MAX)
269   { "AIO_PRIO_DELTA_MAX",       SYSCONF,        _SC_AIO_PRIO_DELTA_MAX  },
270 #endif
271 #if defined (_SC_DELAYTIMER_MAX)
272   { "DELAYTIMER_MAX",           SYSCONF,        _SC_DELAYTIMER_MAX      },
273 #endif
274 #if defined (_SC_GETGR_R_SIZE_MAX)
275   { "GETGR_R_SIZE_MAX",         SYSCONF,        _SC_GETGR_R_SIZE_MAX    },
276 #endif
277 #if defined (_SC_GETPW_R_SIZE_MAX)
278   { "GETPW_R_SIZE_MAX",         SYSCONF,        _SC_GETPW_R_SIZE_MAX    },
279 #endif
280 #if defined (_SC_MQ_OPEN_MAX)
281   { "MQ_OPEN_MAX",              SYSCONF,        _SC_MQ_OPEN_MAX         },
282 #endif
283 #if defined (_SC_MQ_PRIO_MAX)
284   { "MQ_PRIO_MAX",              SYSCONF,        _SC_MQ_PRIO_MAX         },
285 #endif
286 #if defined (_SC_RTSIG_MAX)
287   { "RTSIG_MAX",                SYSCONF,        _SC_RTSIG_MAX           },
288 #endif
289 #if defined (_SC_SEM_NSEMS_MAX)
290   { "SEM_NSEMS_MAX",            SYSCONF,        _SC_SEM_NSEMS_MAX       },
291 #endif
292 #if defined (_SC_SEM_VALUE_MAX)
293   { "SEM_VALUE_MAX",            SYSCONF,        _SC_SEM_VALUE_MAX       },
294 #endif
295 #if defined (_SC_SIGQUEUE_MAX)
296   { "SIGQUEUE_MAX",             SYSCONF,        _SC_SIGQUEUE_MAX        },
297 #endif
298 #if defined (_SC_TIMER_MAX)
299   { "TIMER_MAX",                SYSCONF,        _SC_TIMER_MAX           },
300 #endif
301
302 #if defined (_SC_LOGIN_NAME_MAX)
303   { "LOGIN_NAME_MAX",           SYSCONF,        _SC_LOGIN_NAME_MAX      },
304 #endif
305 #if defined (_SC_LOGNAME_MAX)
306   { "LOGNAME_MAX",              SYSCONF,        _SC_LOGNAME_MAX         },
307 #endif
308 #if defined (_SC_TTY_NAME_MAX)
309   { "TTY_NAME_MAX",             SYSCONF,        _SC_TTY_NAME_MAX        },
310 #endif
311
312 #if defined (_SC_THREAD_DESTRUCTOR_ITERATIONS)
313   { "PTHREAD_DESTRUCTOR_ITERATIONS", SYSCONF,   _SC_THREAD_DESTRUCTOR_ITERATIONS },
314 #endif
315 #if defined (_SC_THREAD_KEYS_MAX)
316   { "PTHREAD_KEYS_MAX",         SYSCONF,        _SC_THREAD_KEYS_MAX },
317 #endif
318 #if defined (_SC_THREAD_STACK_MIN)
319   { "PTHREAD_STACK_MIN",        SYSCONF,        _SC_THREAD_STACK_MIN },
320 #endif
321 #if defined (_SC_THREAD_THREADS_MAX)
322   { "PTHREAD_THREADS_MAX",      SYSCONF,        _SC_THREAD_THREADS_MAX },
323 #endif
324
325   /* XPG 4.2 Optional Facility Configuration Values */
326 #if defined (_SC_XOPEN_UNIX)
327   { "_XOPEN_UNIX",              SYSCONF,        _SC_XOPEN_UNIX          },
328   { "_XOPEN_CRYPT",             SYSCONF,        _SC_XOPEN_CRYPT         },
329   { "_XOPEN_ENH_I18N",          SYSCONF,        _SC_XOPEN_ENH_I18N      },
330   { "_XOPEN_SHM",               SYSCONF,        _SC_XOPEN_SHM           },
331   { "_XOPEN_VERSION",           SYSCONF,        _SC_XOPEN_VERSION       },
332 #  if defined (_SC_XOPEN_XCU_VERSION)
333   { "_XOPEN_XCU_VERSION",       SYSCONF,        _SC_XOPEN_XCU_VERSION   },
334 #  endif
335 #endif
336 #if defined (_SC_XOPEN_REALTIME)
337   { "_XOPEN_REALTIME",          SYSCONF,        _SC_XOPEN_REALTIME      },
338   { "_XOPEN_REALTIME_THREADS",  SYSCONF,        _SC_XOPEN_REALTIME_THREADS },
339 #endif
340 #if defined (_SC_XOPEN_LEGACY)
341   { "_XOPEN_LEGACY",            SYSCONF,        _SC_XOPEN_LEGACY        },
342 #endif /* _SC_XOPEN_LEGACY */
343
344   /* Single UNIX Specification version 2 Optional Facility Configuration Values */
345 #if defined (_SC_XBS5_ILP32_OFF32)
346   { "_XBS5_ILP32_OFF32",        SYSCONF,        _SC_XBS5_ILP32_OFF32    },
347   { "_XBS5_ILP32_OFFBIG",       SYSCONF,        _SC_XBS5_ILP32_OFFBIG   },
348   { "_XBS5_LP64_OFF64",         SYSCONF,        _SC_XBS5_LP64_OFF64     },
349   { "_XBS5_LPBIG_OFFBIG",       SYSCONF,        _SC_XBS5_LPBIG_OFFBIG   },
350 #endif /* _SC_XBS5_ILP32_OFF32 */
351
352   /* POSIX.1 Configurable Pathname Values */
353   { "LINK_MAX",                 PATHCONF,       _PC_LINK_MAX            },
354   { "MAX_CANON",                PATHCONF,       _PC_MAX_CANON           },
355   { "MAX_INPUT",                PATHCONF,       _PC_MAX_INPUT           },
356   { "NAME_MAX",                 PATHCONF,       _PC_NAME_MAX            },
357   { "PATH_MAX",                 PATHCONF,       _PC_PATH_MAX            },
358   { "PIPE_BUF",                 PATHCONF,       _PC_PIPE_BUF            },
359   { "_POSIX_CHOWN_RESTRICTED",  PATHCONF,       _PC_CHOWN_RESTRICTED    },
360   { "_POSIX_NO_TRUNC",          PATHCONF,       _PC_NO_TRUNC            },
361   { "_POSIX_VDISABLE",          PATHCONF,       _PC_VDISABLE            },
362
363   /* XPG 4.2 Configurable Pathname Values */
364 #if defined (_PC_FILESIZEBITS)
365   { "FILESIZEBITS",             PATHCONF,       _PC_FILESIZEBITS },
366 #endif
367 #if defined (_PC_ASYNC_IO)
368   { "_POSIX_ASYNC_IO",          PATHCONF,       _PC_ASYNC_IO },
369 #endif
370 #if defined (_PC_PRIO_IO)
371   { "_POSIX_PRIO_IO",           PATHCONF,       _PC_PRIO_IO },
372 #endif
373 #if defined (_PC_SYNC_IO)
374   { "_POSIX_SYNC_IO",           PATHCONF,       _PC_SYNC_IO },
375 #endif
376
377   { NULL }
378 };
379
380 static int num_getconf_variables = sizeof(conf_table) / sizeof(struct conf_variable) - 1;
381
382 extern char *this_command_name;
383 extern char *xmalloc ();
384 extern char **make_builtin_argv ();
385
386 static void getconf_help ();
387 static int getconf_print ();
388 static int getconf_one ();
389 static int getconf_all ();
390
391 int
392 getconf_builtin (list)
393      WORD_LIST *list;
394 {
395   int c, r, opt, aflag;
396   char **v;
397
398   aflag = 0;
399   reset_internal_getopt();
400   while ((opt = internal_getopt (list, "ah")) != -1) {
401         switch (opt) {
402         case 'a':
403                 aflag = 1;
404                 break;
405         case 'h':
406                 getconf_help();
407                 return(EXECUTION_SUCCESS);
408         default:
409                 builtin_usage();
410                 return(EX_USAGE);
411         }
412   }
413  
414   list = loptend;
415   if ((aflag == 0 && list == 0) || (aflag && list) || list_length(list) > 2) {
416         builtin_usage();
417         return(EX_USAGE);
418   }
419
420   r = aflag ? getconf_all() : getconf_one(list);
421
422   return r;
423 }
424
425 static void
426 getconf_help()
427 {
428         const struct conf_variable *cp;
429         register int i, column;
430
431         builtin_usage();
432         printf("Acceptable variable names are:\n");
433         for (cp = conf_table; cp->name != NULL; cp++) {
434                 if (cp->type == PATHCONF)
435                         printf("%s pathname\n", cp->name);
436                 else
437                         printf("%s\n", cp->name);
438         }
439 }
440
441 static int
442 getconf_print(cp, vpath, all)
443 struct conf_variable *cp;
444 char *vpath;
445 int all;
446 {
447         long val;
448         char *sval;
449         size_t slen;
450
451         switch (cp->type) {
452         case CONSTANT:
453                 printf("%ld\n", cp->value);
454                 break;
455
456         case CONFSTR:
457                 errno = 0;
458                 slen = confstr (cp->value, (char *) 0, (size_t) 0);
459                 if (slen == 0) {
460                         if (errno != 0) {
461                                 if (all)
462                                         printf ("getconf: %s\n", strerror(errno));
463                                 else
464                                         builtin_error ("%s", strerror(errno));
465                         } else
466                                 printf ("undefined\n");
467                         return (EXECUTION_FAILURE);
468                 }
469                 sval = xmalloc(slen);
470
471                 confstr(cp->value, sval, slen);
472                 printf("%s\n", sval);
473                 free(sval);
474                 break;
475
476         case SYSCONF:
477                 errno = 0;
478                 if ((val = sysconf(cp->value)) == -1) {
479                         if (errno != 0) {
480                                 if (all)
481                                         printf("getconf: %s\n", strerror (errno));
482                                 else
483                                         builtin_error ("%s", strerror (errno));
484                                 return (EXECUTION_FAILURE);
485                         }
486
487                         printf ("undefined\n");
488                 } else {
489                         printf("%ld\n", val);
490                 }
491                 break;
492
493         case PATHCONF:
494                 errno = 0;
495                 if ((val = pathconf(vpath, cp->value)) == -1) {
496                         if (errno != 0) {
497                                 if (all)
498                                         printf("getconf: %s: %s\n", vpath, strerror (errno));
499                                 else
500                                         builtin_error ("%s: %s", vpath, strerror (errno));
501                                 return (EXECUTION_FAILURE);
502                         }
503
504                         printf ("undefined\n");
505                 } else {
506                         printf ("%ld\n", val);
507                 }
508                 break;
509         }
510
511         return (ferror(stdout) ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
512 }
513
514 static int
515 getconf_all()
516 {
517         const struct conf_variable *cp;
518         int ret;
519
520         ret = EXECUTION_SUCCESS;
521         for (cp = conf_table; cp->name != NULL; cp++) {
522                 printf("%-35s", cp->name);
523                 if (getconf_print(cp, ".", 1) == EXECUTION_FAILURE)
524                         ret = EXECUTION_FAILURE;
525         }
526         return ret;
527 }
528
529 static int
530 getconf_one(list)
531         WORD_LIST *list;
532 {
533         const struct conf_variable *cp;
534         char *vname, *vpath;
535
536         vname = list->word->word;
537         vpath = (list->next && list->next->word) ? list->next->word->word
538                                                  : (char *)NULL;
539
540         for (cp = conf_table; cp->name != NULL; cp++) {
541                 if (strcmp(vname, cp->name) == 0)
542                         break;
543         }
544         if (cp->name == NULL) {
545                 builtin_error ("%s: unknown variable", vname);
546                 return (EXECUTION_FAILURE);
547         }
548
549         if (cp->type == PATHCONF) {
550                 if (list->next == 0) {
551                         builtin_usage();
552                         return(EX_USAGE);
553                 }
554         } else {
555                 if (list->next) {
556                         builtin_usage();
557                         return(EX_USAGE);
558                 }
559         }
560
561         return (getconf_print(cp, vpath, 0));
562 }
563
564 static char *getconf_doc[] = {
565         "getconf writes the current value of a configurable system limit or",
566         "option variable to the standard output.",
567         (char *)NULL
568 };
569
570 struct builtin getconf_struct = {
571         "getconf",
572         getconf_builtin,
573         BUILTIN_ENABLED,
574         getconf_doc,
575         "getconf -a or getconf -h or getconf sysvar or getconf pathvar pathname",
576         0
577 };