diff options
author | An-Cheng Huang <ancheng@vyatta.com> | 2007-11-12 13:06:02 -0800 |
---|---|---|
committer | An-Cheng Huang <ancheng@vyatta.com> | 2007-11-12 13:06:02 -0800 |
commit | b7fc9e0f6d6105ba2203f219743d4b269415e84b (patch) | |
tree | ef6586dfc62798c2b17487b443864699aca55f31 /examples/loadables | |
download | vyatta-bash-b7fc9e0f6d6105ba2203f219743d4b269415e84b.tar.gz vyatta-bash-b7fc9e0f6d6105ba2203f219743d4b269415e84b.zip |
initial import from bash_3.1dfsg.orig.tar.gz
Diffstat (limited to 'examples/loadables')
36 files changed, 6144 insertions, 0 deletions
diff --git a/examples/loadables/Makefile.in b/examples/loadables/Makefile.in new file mode 100644 index 0000000..f6208f5 --- /dev/null +++ b/examples/loadables/Makefile.in @@ -0,0 +1,238 @@ +# +# Simple makefile for the sample loadable builtins +# +# Copyright (C) 1996 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +# Include some boilerplate Gnu makefile definitions. +prefix = @prefix@ + +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +infodir = @infodir@ +includedir = @includedir@ + +topdir = @top_srcdir@ +BUILD_DIR = @BUILD_DIR@ +srcdir = @srcdir@ +VPATH = .:@srcdir@ + +@SET_MAKE@ +CC = @CC@ +RM = rm -f + +SHELL = @MAKE_SHELL@ + +host_os = @host_os@ +host_cpu = @host_cpu@ +host_vendor = @host_vendor@ + +CFLAGS = @CFLAGS@ +LOCAL_CFLAGS = @LOCAL_CFLAGS@ +DEFS = @DEFS@ +LOCAL_DEFS = @LOCAL_DEFS@ + +CPPFLAGS = @CPPFLAGS@ + +BASHINCDIR = ${topdir}/include + +LIBBUILD = ${BUILD_DIR}/lib + +INTL_LIBSRC = ${topdir}/lib/intl +INTL_BUILDDIR = ${LIBBUILD}/intl +INTL_INC = @INTL_INC@ +LIBINTL_H = @LIBINTL_H@ + +CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) $(CFLAGS) + +# +# These values are generated for configure by ${topdir}/support/shobj-conf. +# If your system is not supported by that script, but includes facilities for +# dynamic loading of shared objects, please update the script and send the +# changes to bash-maintainers@gnu.org. +# +SHOBJ_CC = @SHOBJ_CC@ +SHOBJ_CFLAGS = @SHOBJ_CFLAGS@ +SHOBJ_LD = @SHOBJ_LD@ +SHOBJ_LDFLAGS = @SHOBJ_LDFLAGS@ +SHOBJ_XLDFLAGS = @SHOBJ_XLDFLAGS@ +SHOBJ_LIBS = @SHOBJ_LIBS@ +SHOBJ_STATUS = @SHOBJ_STATUS@ + +INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins \ + -I$(BASHINCDIR) -I$(BUILD_DIR) -I$(LIBBUILD) \ + -I$(BUILD_DIR)/builtins $(INTL_INC) + +.c.o: + $(SHOBJ_CC) $(SHOBJ_CFLAGS) $(CCFLAGS) $(INC) -c -o $@ $< + + +ALLPROG = print truefalse sleep pushd finfo logname basename dirname \ + tty pathchk tee head mkdir rmdir printenv id whoami \ + uname sync push ln unlink cut realpath getconf strftime +OTHERPROG = necho hello cat + +all: $(SHOBJ_STATUS) + +supported: $(ALLPROG) +others: $(OTHERPROG) + +unsupported: + @echo "Your system (${host_os}) is not supported by the" + @echo "${topdir}/support/shobj-conf script." + @echo "If your operating system provides facilities for dynamic" + @echo "loading of shared objects using the dlopen(3) interface," + @echo "please update the script and re-run configure. + @echo "Please send the changes you made to bash-maintainers@gnu.org" + @echo "for inclusion in future bash releases." + +everything: supported others + +print: print.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ print.o $(SHOBJ_LIBS) + +necho: necho.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ necho.o $(SHOBJ_LIBS) + +getconf: getconf.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ getconf.o $(SHOBJ_LIBS) + +hello: hello.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ hello.o $(SHOBJ_LIBS) + +truefalse: truefalse.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ truefalse.o $(SHOBJ_LIBS) + +sleep: sleep.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ sleep.o $(SHOBJ_LIBS) + +finfo: finfo.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ finfo.o $(SHOBJ_LIBS) + +cat: cat.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cat.o $(SHOBJ_LIBS) + +logname: logname.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ logname.o $(SHOBJ_LIBS) + +basename: basename.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ basename.o $(SHOBJ_LIBS) + +dirname: dirname.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ dirname.o $(SHOBJ_LIBS) + +tty: tty.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ tty.o $(SHOBJ_LIBS) + +pathchk: pathchk.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pathchk.o $(SHOBJ_LIBS) + +tee: tee.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ tee.o $(SHOBJ_LIBS) + +mkdir: mkdir.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ mkdir.o $(SHOBJ_LIBS) + +rmdir: rmdir.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ rmdir.o $(SHOBJ_LIBS) + +head: head.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ head.o $(SHOBJ_LIBS) + +printenv: printenv.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ printenv.o $(SHOBJ_LIBS) + +id: id.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ id.o $(SHOBJ_LIBS) + +whoami: whoami.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ whoami.o $(SHOBJ_LIBS) + +uname: uname.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ uname.o $(SHOBJ_LIBS) + +sync: sync.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ sync.o $(SHOBJ_LIBS) + +push: push.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ push.o $(SHOBJ_LIBS) + +ln: ln.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ ln.o $(SHOBJ_LIBS) + +unlink: unlink.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ unlink.o $(SHOBJ_LIBS) + +cut: cut.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cut.o $(SHOBJ_LIBS) + +realpath: realpath.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ realpath.o $(SHOBJ_LIBS) + +strftime: strftime.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ strftime.o $(SHOBJ_LIBS) + +# pushd is a special case. We use the same source that the builtin version +# uses, with special compilation options. +# +pushd.c: ${topdir}/builtins/pushd.def + $(RM) $@ + ${BUILD_DIR}/builtins/mkbuiltins -D ${topdir}/builtins ${topdir}/builtins/pushd.def + +pushd.o: pushd.c + $(RM) $@ + $(SHOBJ_CC) -DHAVE_CONFIG_H -DPUSHD_AND_POPD -DLOADABLE_BUILTIN $(SHOBJ_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(INC) -c -o $@ $< + +pushd: pushd.o + $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pushd.o $(SHOBJ_LIBS) + +clean: + $(RM) $(ALLPROG) $(OTHERPROG) *.o + -( cd perl && ${MAKE} ${MFLAGS} $@ ) + +mostlyclean: clean + -( cd perl && ${MAKE} ${MFLAGS} $@ ) + +distclean maintainer-clean: clean + $(RM) Makefile pushd.c + -( cd perl && ${MAKE} ${MFLAGS} $@ ) + +print.o: print.c +truefalse.o: truefalse.c +sleep.o: sleep.c +finfo.o: finfo.c +logname.o: logname.c +basename.o: basename.c +dirname.o: dirname.c +tty.o: tty.c +pathchk.o: pathchk.c +tee.o: tee.c +head.o: head.c +rmdir.o: rmdir.c +necho.o: necho.c +getconf.o: getconf.c +hello.o: hello.c +cat.o: cat.c +printenv.o: printenv.c +id.o: id.c +whoami.o: whoami.c +uname.o: uname.c +sync.o: sync.c +push.o: push.c +mkdir.o: mkdir.c +realpath.o: realpath.c +strftime.o: strftime.c diff --git a/examples/loadables/README b/examples/loadables/README new file mode 100644 index 0000000..db67860 --- /dev/null +++ b/examples/loadables/README @@ -0,0 +1,33 @@ +Some examples of ready-to-dynamic-load builtins. Most of the +examples given are reimplementations of standard commands whose +execution time is dominated by process startup time. The +exceptions are sleep, which allows you to sleep for fractions +of a second, finfo, which provides access to the rest of the +elements of the `stat' structure that `test' doesn't let you +see, and pushd/popd/dirs, which allows you to compile them out +of the shell. + +All of the new builtins in ksh93 that bash didn't already have +are included here, as is the ksh `print' builtin. + +The configure script in the top-level source directory uses the +support/shobj-conf script to set the right values in the Makefile, +so you should not need to change the Makefile. If your system +is not supported by support/shobj-conf, and it has the necessary +facilities for building shared objects and support for the +dlopen/dlsyn/dlclose/dlerror family of functions, please make +the necessary changes to support/shobj-conf and send the changes +to bash-maintainers@gnu.org. + +Loadable builtins are loaded into a running shell with + + enable -f filename builtin-name + +enable uses a simple reference-counting scheme to avoid unloading a +shared object that implements more than one loadable builtin before +all loadable builtins implemented in the object are removed. + +Many of the details needed by builtin writers are found in hello.c, +the canonical example. There is no real `builtin writers' programming +guide'. The file template.c provides a template to use for creating +new loadable builtins. diff --git a/examples/loadables/basename.c b/examples/loadables/basename.c new file mode 100644 index 0000000..7f254c7 --- /dev/null +++ b/examples/loadables/basename.c @@ -0,0 +1,108 @@ +/* basename - return nondirectory portion of pathname */ + +/* See Makefile for compilation details. */ + +#include "config.h" + +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif + +#include <stdio.h> +#include "builtins.h" +#include "shell.h" + +basename_builtin (list) + WORD_LIST *list; +{ + int slen, sufflen, off; + char *string, *suffix, *fn; + + if (list == 0) + { + builtin_usage (); + return (EX_USAGE); + } + + if (no_options (list)) + return (EX_USAGE); + + string = list->word->word; + suffix = (char *)NULL; + if (list->next) + { + list = list->next; + suffix = list->word->word; + } + + if (list->next) + { + builtin_usage (); + return (EX_USAGE); + } + + slen = strlen (string); + + /* Strip trailing slashes */ + while (slen > 0 && string[slen - 1] == '/') + slen--; + + /* (2) If string consists entirely of slash characters, string shall be + set to a single slash character. In this case, skip steps (3) + through (5). */ + if (slen == 0) + { + fputs ("/\n", stdout); + return (EXECUTION_SUCCESS); + } + + /* (3) If there are any trailing slash characters in string, they + shall be removed. */ + string[slen] = '\0'; + + /* (4) If there are any slash characters remaining in string, the prefix + of string up to an including the last slash character in string + shall be removed. */ + while (--slen >= 0) + if (string[slen] == '/') + break; + + fn = string + slen + 1; + + /* (5) If the suffix operand is present, is not identical to the + characters remaining in string, and is identical to a suffix + of the characters remaining in string, the suffix suffix + shall be removed from string. Otherwise, string shall not be + modified by this step. */ + if (suffix) + { + sufflen = strlen (suffix); + slen = strlen (fn); + if (sufflen < slen) + { + off = slen - sufflen; + if (strcmp (fn + off, suffix) == 0) + fn[off] = '\0'; + } + } + printf ("%s\n", fn); + return (EXECUTION_SUCCESS); +} + +char *basename_doc[] = { + "The STRING is converted to a filename corresponding to the last", + "pathname component in STRING. If the suffix string SUFFIX is", + "supplied, it is removed.", + (char *)NULL +}; + +/* The standard structure describing a builtin command. bash keeps an array + of these structures. */ +struct builtin basename_struct = { + "basename", /* builtin name */ + basename_builtin, /* function implementing the builtin */ + BUILTIN_ENABLED, /* initial flags for builtin */ + basename_doc, /* array of long documentation strings. */ + "basename string [suffix]", /* usage synopsis */ + 0 /* reserved for internal use */ +}; diff --git a/examples/loadables/cat.c b/examples/loadables/cat.c new file mode 100644 index 0000000..9dd1d1a --- /dev/null +++ b/examples/loadables/cat.c @@ -0,0 +1,100 @@ +/* + * cat replacement + * + * no options - the way cat was intended + */ + +#include <fcntl.h> +#include <errno.h> + +#include "builtins.h" +#include "shell.h" + +#ifndef errno +extern int errno; +#endif + +extern char *strerror (); +extern char **make_builtin_argv (); + +static int +fcopy(fd) +int fd; +{ + char buf[1024], *s; + int n, w, e; + + while (n = read(fd, buf, sizeof (buf))) { + w = write(1, buf, n); + if (w != n) { + e = errno; + write(2, "cat: write error: ", 18); + s = strerror(e); + write(2, s, strlen(s)); + write(2, "\n", 1); + return 1; + } + } + return 0; +} + +cat_main (argc, argv) +int argc; +char **argv; +{ + int i, fd, r; + char *s; + + if (argc == 1) + return (fcopy(0)); + + for (i = r = 1; i < argc; i++) { + if (argv[i][0] == '-' && argv[i][1] == '\0') + fd = 0; + else { + fd = open(argv[i], O_RDONLY, 0666); + if (fd < 0) { + s = strerror(errno); + write(2, "cat: cannot open ", 17); + write(2, argv[i], strlen(argv[i])); + write(2, ": ", 2); + write(2, s, strlen(s)); + write(2, "\n", 1); + continue; + } + } + r = fcopy(fd); + if (fd != 0) + close(fd); + } + return (r); +} + +cat_builtin(list) +WORD_LIST *list; +{ + char **v; + int c, r; + + v = make_builtin_argv(list, &c); + r = cat_main(c, v); + free(v); + + return r; +} + +char *cat_doc[] = { + "Read each FILE and display it on the standard output. If any", + "FILE is `-' or if no FILE argument is given, the standard input", + "is read.", + (char *)0 +}; + +struct builtin cat_struct = { + "cat", + cat_builtin, + BUILTIN_ENABLED, + cat_doc, + "cat [-] [file ...]", + 0 +}; diff --git a/examples/loadables/cut.c b/examples/loadables/cut.c new file mode 100644 index 0000000..d874034 --- /dev/null +++ b/examples/loadables/cut.c @@ -0,0 +1,376 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Adam S. Moskowitz of Menlo Consulting and Marciano Pitargue. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1989, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static const char sccsid[] = "@(#)cut.c 8.3 (Berkeley) 5/4/95"; +#endif /* not lint */ + +#include <config.h> + +#include <ctype.h> +#include <stdio.h> +#include <errno.h> + +#include "bashansi.h" + +#ifdef HAVE_LIMITS_H +# include <limits.h> +#endif + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#include "builtins.h" +#include "shell.h" +#include "bashgetopt.h" + +#if !defined (errno) +extern int errno; +#endif + +#if !defined (_POSIX2_LINE_MAX) +# define _POSIX2_LINE_MAX 2048 +#endif + +static int cflag; +static char dchar; +static int dflag; +static int fflag; +static int sflag; + +static int autostart, autostop, maxval; +static char positions[_POSIX2_LINE_MAX + 1]; + +static int c_cut __P((FILE *, char *)); +static int f_cut __P((FILE *, char *)); +static int get_list __P((char *)); +static char *_cut_strsep __P((char **, const char *)); + +int +cut_builtin(list) + WORD_LIST *list; +{ + FILE *fp; + int (*fcn) __P((FILE *, char *)) = NULL; + int ch; + + fcn = NULL; + dchar = '\t'; /* default delimiter is \t */ + + /* Since we don't support multi-byte characters, the -c and -b + options are equivalent, and the -n option is meaningless. */ + reset_internal_getopt (); + while ((ch = internal_getopt (list, "b:c:d:f:sn")) != -1) + switch(ch) { + case 'b': + case 'c': + fcn = c_cut; + if (get_list(list_optarg) < 0) + return (EXECUTION_FAILURE); + cflag = 1; + break; + case 'd': + dchar = *list_optarg; + dflag = 1; + break; + case 'f': + fcn = f_cut; + if (get_list(list_optarg) < 0) + return (EXECUTION_FAILURE); + fflag = 1; + break; + case 's': + sflag = 1; + break; + case 'n': + break; + case '?': + default: + builtin_usage(); + return (EX_USAGE); + } + + list = loptend; + + if (fflag) { + if (cflag) { + builtin_usage(); + return (EX_USAGE); + } + } else if (!cflag || dflag || sflag) { + builtin_usage(); + return (EX_USAGE); + } + + if (list) { + while (list) { + fp = fopen(list->word->word, "r"); + if (fp == 0) { + builtin_error("%s", list->word->word); + return (EXECUTION_FAILURE); + } + ch = (*fcn)(fp, list->word->word); + (void)fclose(fp); + if (ch < 0) + return (EXECUTION_FAILURE); + list = list->next; + } + } else { + ch = (*fcn)(stdin, "stdin"); + if (ch < 0) + return (EXECUTION_FAILURE); + } + + return (EXECUTION_SUCCESS); +} + +static int +get_list(list) + char *list; +{ + int setautostart, start, stop; + char *pos; + char *p; + + /* + * set a byte in the positions array to indicate if a field or + * column is to be selected; use +1, it's 1-based, not 0-based. + * This parser is less restrictive than the Draft 9 POSIX spec. + * POSIX doesn't allow lists that aren't in increasing order or + * overlapping lists. We also handle "-3-5" although there's no + * real reason too. + */ + for (; (p = _cut_strsep(&list, ", \t")) != NULL;) { + setautostart = start = stop = 0; + if (*p == '-') { + ++p; + setautostart = 1; + } + if (isdigit((unsigned char)*p)) { + start = stop = strtol(p, &p, 10); + if (setautostart && start > autostart) + autostart = start; + } + if (*p == '-') { + if (isdigit((unsigned char)p[1])) + stop = strtol(p + 1, &p, 10); + if (*p == '-') { + ++p; + if (!autostop || autostop > stop) + autostop = stop; + } + } + if (*p) { + builtin_error("[-cf] list: illegal list value"); + return -1; + } + if (!stop || !start) { + builtin_error("[-cf] list: values may not include zero"); + return -1; + } + if (stop > _POSIX2_LINE_MAX) { + builtin_error("[-cf] list: %d too large (max %d)", + stop, _POSIX2_LINE_MAX); + return -1; + } + if (maxval < stop) + maxval = stop; + for (pos = positions + start; start++ <= stop; *pos++ = 1); + } + + /* overlapping ranges */ + if (autostop && maxval > autostop) + maxval = autostop; + + /* set autostart */ + if (autostart) + memset(positions + 1, '1', autostart); + + return 0; +} + +/* ARGSUSED */ +static int +c_cut(fp, fname) + FILE *fp; + char *fname; +{ + int ch, col; + char *pos; + + ch = 0; + for (;;) { + pos = positions + 1; + for (col = maxval; col; --col) { + if ((ch = getc(fp)) == EOF) + return; + if (ch == '\n') + break; + if (*pos++) + (void)putchar(ch); + } + if (ch != '\n') { + if (autostop) + while ((ch = getc(fp)) != EOF && ch != '\n') + (void)putchar(ch); + else + while ((ch = getc(fp)) != EOF && ch != '\n'); + } + (void)putchar('\n'); + } + return (0); +} + +static int +f_cut(fp, fname) + FILE *fp; + char *fname; +{ + int ch, field, isdelim; + char *pos, *p, sep; + int output; + char lbuf[_POSIX2_LINE_MAX + 1]; + + for (sep = dchar; fgets(lbuf, sizeof(lbuf), fp);) { + output = 0; + for (isdelim = 0, p = lbuf;; ++p) { + if (!(ch = *p)) { + builtin_error("%s: line too long.", fname); + return -1; + } + /* this should work if newline is delimiter */ + if (ch == sep) + isdelim = 1; + if (ch == '\n') { + if (!isdelim && !sflag) + (void)printf("%s", lbuf); + break; + } + } + if (!isdelim) + continue; + + pos = positions + 1; + for (field = maxval, p = lbuf; field; --field, ++pos) { + if (*pos) { + if (output++) + (void)putchar(sep); + while ((ch = *p++) != '\n' && ch != sep) + (void)putchar(ch); + } else { + while ((ch = *p++) != '\n' && ch != sep) + continue; + } + if (ch == '\n') + break; + } + if (ch != '\n') { + if (autostop) { + if (output) + (void)putchar(sep); + for (; (ch = *p) != '\n'; ++p) + (void)putchar(ch); + } else + for (; (ch = *p) != '\n'; ++p); + } + (void)putchar('\n'); + } + return (0); +} + +/* + * Get next token from string *stringp, where tokens are possibly-empty + * strings separated by characters from delim. + * + * Writes NULs into the string at *stringp to end tokens. + * delim need not remain constant from call to call. + * On return, *stringp points past the last NUL written (if there might + * be further tokens), or is NULL (if there are definitely no more tokens). + * + * If *stringp is NULL, strsep returns NULL. + */ +static char * +_cut_strsep(stringp, delim) + register char **stringp; + register const char *delim; +{ + register char *s; + register const char *spanp; + register int c, sc; + char *tok; + + if ((s = *stringp) == NULL) + return (NULL); + for (tok = s;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *stringp = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} + +static char *cut_doc[] = { + "Select portions of each line (as specified by LIST) from each FILE", + "(by default, the standard input), and write them to the standard output.", + "Items specified by LIST are either column positions or fields delimited", + "by a special character. Column numbering starts at 1.", + (char *)0 +}; + +struct builtin cut_struct = { + "cut", + cut_builtin, + BUILTIN_ENABLED, + cut_doc, + "cut -b list [-n] [file ...] OR cut -c list [file ...] OR cut -f list [-s] [-d delim] [file ...]", + 0 +}; diff --git a/examples/loadables/dirname.c b/examples/loadables/dirname.c new file mode 100644 index 0000000..6159560 --- /dev/null +++ b/examples/loadables/dirname.c @@ -0,0 +1,95 @@ +/* dirname - return directory portion of pathname */ + +/* See Makefile for compilation details. */ + +#include "config.h" + +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif + +#include <stdio.h> +#include "builtins.h" +#include "shell.h" + +dirname_builtin (list) + WORD_LIST *list; +{ + int slen; + char *string; + + if (list == 0 || list->next) + { + builtin_usage (); + return (EX_USAGE); + } + + if (no_options (list)) + return (EX_USAGE); + + string = list->word->word; + slen = strlen (string); + + /* Strip trailing slashes */ + while (slen > 0 && string[slen - 1] == '/') + slen--; + + /* (2) If string consists entirely of slash characters, string shall be + set to a single slash character. In this case, skip steps (3) + through (8). */ + if (slen == 0) + { + fputs ("/\n", stdout); + return (EXECUTION_SUCCESS); + } + + /* (3) If there are any trailing slash characters in string, they + shall be removed. */ + string[slen] = '\0'; + + /* (4) If there are no slash characters remaining in string, string + shall be set to a single period character. In this case, skip + steps (5) through (8). + + (5) If there are any trailing nonslash characters in string, + they shall be removed. */ + + while (--slen >= 0) + if (string[slen] == '/') + break; + + if (slen < 0) + { + fputs (".\n", stdout); + return (EXECUTION_SUCCESS); + } + + /* (7) If there are any trailing slash characters in string, they + shall be removed. */ + while (--slen >= 0) + if (string[slen] != '/') + break; + string[++slen] = '\0'; + + /* (8) If the remaining string is empty, string shall be set to a single + slash character. */ + printf ("%s\n", (slen == 0) ? "/" : string); + return (EXECUTION_SUCCESS); +} + +char *dirname_doc[] = { + "The STRING is converted to the name of the directory containing", + "the filename corresponding to the last pathname component in STRING.", + (char *)NULL +}; + +/* The standard structure describing a builtin command. bash keeps an array + of these structures. */ +struct builtin dirname_struct = { + "dirname", /* builtin name */ + dirname_builtin, /* function implementing the builtin */ + BUILTIN_ENABLED, /* initial flags for builtin */ + dirname_doc, /* array of long documentation strings. */ + "dirname string", /* usage synopsis */ + 0 /* reserved for internal use */ +}; diff --git a/examples/loadables/finfo.c b/examples/loadables/finfo.c new file mode 100644 index 0000000..c1682ed --- /dev/null +++ b/examples/loadables/finfo.c @@ -0,0 +1,596 @@ +/* + * finfo - print file info + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <sys/types.h> +#include "posixstat.h" +#include <stdio.h> +#include <pwd.h> +#include <grp.h> +#include <errno.h> + +#include "bashansi.h" +#include "shell.h" +#include "builtins.h" +#include "common.h" + +#ifndef errno +extern int errno; +#endif + +extern char **make_builtin_argv (); + +static int printst(); +static int printsome(); +static int printfinfo(); +static int finfo_main(); + +extern int sh_optind; +extern char *sh_optarg; +extern char *this_command_name; + +static char *prog; +static int pmask; + +#define OPT_UID 0x00001 +#define OPT_GID 0x00002 +#define OPT_DEV 0x00004 +#define OPT_INO 0x00008 +#define OPT_PERM 0x00010 +#define OPT_LNKNAM 0x00020 +#define OPT_FID 0x00040 +#define OPT_NLINK 0x00080 +#define OPT_RDEV 0x00100 +#define OPT_SIZE 0x00200 +#define OPT_ATIME 0x00400 +#define OPT_MTIME 0x00800 +#define OPT_CTIME 0x01000 +#define OPT_BLKSIZE 0x02000 +#define OPT_BLKS 0x04000 +#define OPT_FTYPE 0x08000 +#define OPT_PMASK 0x10000 +#define OPT_OPERM 0x20000 + +#define OPT_ASCII 0x1000000 + +#define OPTIONS "acdgiflmnopsuACGMP:U" + +static int +octal(s) +char *s; +{ + int r; + + r = *s - '0'; + while (*++s >= '0' && *s <= '7') + r = (r * 8) + (*s - '0'); + return r; +} + +static int +finfo_main(argc, argv) +int argc; +char **argv; +{ + register int i; + int mode, flags, opt; + + sh_optind = 0; /* XXX */ + prog = base_pathname(argv[0]); + if (argc == 1) { + builtin_usage(); + return(1); + } + flags = 0; + while ((opt = sh_getopt(argc, argv, OPTIONS)) != EOF) { + switch(opt) { + case 'a': flags |= OPT_ATIME; break; + case 'A': flags |= OPT_ATIME|OPT_ASCII; break; + case 'c': flags |= OPT_CTIME; break; + case 'C': flags |= OPT_CTIME|OPT_ASCII; break; + case 'd': flags |= OPT_DEV; break; + case 'i': flags |= OPT_INO; break; + case 'f': flags |= OPT_FID; break; + case 'g': flags |= OPT_GID; break; + case 'G': flags |= OPT_GID|OPT_ASCII; break; + case 'l': flags |= OPT_LNKNAM; break; + case 'm': flags |= OPT_MTIME; break; + case 'M': flags |= OPT_MTIME|OPT_ASCII; break; + case 'n': flags |= OPT_NLINK; break; + case 'o': flags |= OPT_OPERM; break; + case 'p': flags |= OPT_PERM; break; + case 'P': flags |= OPT_PMASK; pmask = octal(sh_optarg); break; + case 's': flags |= OPT_SIZE; break; + case 'u': flags |= OPT_UID; break; + case 'U': flags |= OPT_UID|OPT_ASCII; break; + default: builtin_usage (); return(1); + } + } + + argc -= sh_optind; + argv += sh_optind; + + if (argc == 0) { + builtin_usage(); + return(1); + } + + for (i = 0; i < argc; i++) + opt = flags ? printsome (argv[i], flags) : printfinfo(argv[i]); + + return(opt); +} + +static struct stat * +getstat(f) +char *f; +{ + static struct stat st; + int fd, r; + intmax_t lfd; + + if (strncmp(f, "/dev/fd/", 8) == 0) { + if ((legal_number(f + 8, &lfd) == 0) || (int)lfd != lfd) { + builtin_error("%s: invalid fd", f + 8); + return ((struct stat *)0); + } + fd = lfd; + r = fstat(fd, &st); + } else +#ifdef HAVE_LSTAT + r = lstat(f, &st); +#else + r = stat(f, &st); +#endif + if (r < 0) { + builtin_error("%s: cannot stat: %s", f, strerror(errno)); + return ((struct stat *)0); + } + return (&st); +} + +static int +printfinfo(f) +char *f; +{ + struct stat *st; + + st = getstat(f); + return (st ? printst(st) : 1); +} + +static int +getperm(m) +int m; +{ + return (m & (S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID)); +} + +static int +perms(m) +int m; +{ + char ubits[4], gbits[4], obits[4]; /* u=rwx,g=rwx,o=rwx */ + int i; + + i = 0; + if (m & S_IRUSR) + ubits[i++] = 'r'; + if (m & S_IWUSR) + ubits[i++] = 'w'; + if (m & S_IXUSR) + ubits[i++] = 'x'; + ubits[i] = '\0'; + + i = 0; + if (m & S_IRGRP) + gbits[i++] = 'r'; + if (m & S_IWGRP) + gbits[i++] = 'w'; + if (m & S_IXGRP) + gbits[i++] = 'x'; + gbits[i] = '\0'; + + i = 0; + if (m & S_IROTH) + obits[i++] = 'r'; + if (m & S_IWOTH) + obits[i++] = 'w'; + if (m & S_IXOTH) + obits[i++] = 'x'; + obits[i] = '\0'; + + if (m & S_ISUID) + ubits[2] = (m & S_IXUSR) ? 's' : 'S'; + if (m & S_ISGID) + gbits[2] = (m & S_IXGRP) ? 's' : 'S'; + if (m & S_ISVTX) + obits[2] = (m & S_IXOTH) ? 't' : 'T'; + + printf ("u=%s,g=%s,o=%s", ubits, gbits, obits); +} + +static int +printmode(mode) +int mode; +{ + if (S_ISBLK(mode)) + printf("S_IFBLK "); + if (S_ISCHR(mode)) + printf("S_IFCHR "); + if (S_ISDIR(mode)) + printf("S_IFDIR "); + if (S_ISREG(mode)) + printf("S_IFREG "); + if (S_ISFIFO(mode)) + printf("S_IFIFO "); + if (S_ISLNK(mode)) + printf("S_IFLNK "); + if (S_ISSOCK(mode)) + printf("S_IFSOCK "); +#ifdef S_ISWHT + if (S_ISWHT(mode)) + printf("S_ISWHT "); +#endif + perms(getperm(mode)); + printf("\n"); +} + +static int +printst(st) +struct stat *st; +{ + struct passwd *pw; + struct group *gr; + char *owner; + int ma, mi, d; + + ma = major (st->st_rdev); + mi = minor (st->st_rdev); +#if defined (makedev) + d = makedev (ma, mi); +#else + d = st->st_rdev & 0xFF; +#endif + printf("Device (major/minor): %d (%d/%d)\n", d, ma, mi); + + printf("Inode: %d\n", (int) st->st_ino); + printf("Mode: (%o) ", (int) st->st_mode); + printmode((int) st->st_mode); + printf("Link count: %d\n", (int) st->st_nlink); + pw = getpwuid(st->st_uid); + owner = pw ? pw->pw_name : "unknown"; + printf("Uid of owner: %d (%s)\n", (int) st->st_uid, owner); + gr = getgrgid(st->st_gid); + owner = gr ? gr->gr_name : "unknown"; + printf("Gid of owner: %d (%s)\n", (int) st->st_gid, owner); + printf("Device type: %d\n", (int) st->st_rdev); + printf("File size: %ld\n", (long) st->st_size); + printf("File last access time: %s", ctime (&st->st_atime)); + printf("File last modify time: %s", ctime (&st->st_mtime)); + printf("File last status change time: %s", ctime (&st->st_ctime)); + fflush(stdout); + return(0); +} + +static int +printsome(f, flags) +char *f; +int flags; +{ + struct stat *st; + struct passwd *pw; + struct group *gr; + int p; + char *b; + + st = getstat(f); + if (st == NULL) + return (1); + + /* Print requested info */ + if (flags & OPT_ATIME) { + if (flags & OPT_ASCII) + printf("%s", ctime(&st->st_atime)); + else + printf("%ld\n", st->st_atime); + } else if (flags & OPT_MTIME) { + if (flags & OPT_ASCII) + printf("%s", ctime(&st->st_mtime)); + else + printf("%ld\n", st->st_mtime); + } else if (flags & OPT_CTIME) { + if (flags & OPT_ASCII) + printf("%s", ctime(&st->st_ctime)); + else + printf("%ld\n", st->st_ctime); + } else if (flags & OPT_DEV) + printf("%d\n", st->st_dev); + else if (flags & OPT_INO) + printf("%d\n", st->st_ino); + else if (flags & OPT_FID) + printf("%d:%ld\n", st->st_dev, st->st_ino); + else if (flags & OPT_NLINK) + printf("%d\n", st->st_nlink); + else if (flags & OPT_LNKNAM) { +#ifdef S_ISLNK + b = xmalloc(4096); + p = readlink(f, b, 4096); + if (p >= 0 && p < 4096) + b[p] = '\0'; + else { + p = errno; + strcpy(b, prog); + strcat(b, ": "); + strcat(b, strerror(p)); + } + printf("%s\n", b); + free(b); +#else + printf("%s\n", f); +#endif + } else if (flags & OPT_PERM) { + perms(st->st_mode); + printf("\n"); + } else if (flags & OPT_OPERM) + printf("%o\n", getperm(st->st_mode)); + else if (flags & OPT_PMASK) + printf("%o\n", getperm(st->st_mode) & pmask); + else if (flags & OPT_UID) { + pw = getpwuid(st->st_uid); + if (flags & OPT_ASCII) + printf("%s\n", pw ? pw->pw_name : "unknown"); + else + printf("%d\n", st->st_uid); + } else if (flags & OPT_GID) { + gr = getgrgid(st->st_gid); + if (flags & OPT_ASCII) + printf("%s\n", gr ? gr->gr_name : "unknown"); + else + printf("%d\n", st->st_gid); + } else if (flags & OPT_SIZE) + printf("%ld\n", st->st_size); + + return (0); +} + +#ifndef NOBUILTIN +int +finfo_builtin(list) + WORD_LIST *list; +{ + int c, r; + char **v; + WORD_LIST *l; + + v = make_builtin_argv (list, &c); + r = finfo_main (c, v); + free (v); + + return r; +} + +static char *finfo_doc[] = { + "Display information about each FILE. Only single operators should", + "be supplied. If no options are supplied, a summary of the info", + "available about each FILE is printed. If FILE is of the form", + "/dev/fd/XX, file descriptor XX is described. Operators, if supplied,", + "have the following meanings:", + "", + " -a last file access time", + " -A last file access time in ctime format", + " -c last file status change time", + " -C last file status change time in ctime format", + " -m last file modification time", + " -M last file modification time in ctime format", + " -d device", + " -i inode", + " -f composite file identifier (device:inode)", + " -g gid of owner", + " -G group name of owner", + " -l name of file pointed to by symlink", + " -n link count", + " -o permissions in octal", + " -p permissions in ascii", + " -P mask permissions ANDed with MASK (like with umask)", + " -s file size in bytes", + " -u uid of owner", + " -U user name of owner", + (char *)0 +}; + +struct builtin finfo_struct = { + "finfo", + finfo_builtin, + BUILTIN_ENABLED, + finfo_doc, + "finfo [-acdgiflmnopsuACGMPU] file [file...]", + 0 +}; +#endif + +#ifdef NOBUILTIN +#if defined (PREFER_STDARG) +# include <stdarg.h> +#else +# if defined (PREFER_VARARGS) +# include <varargs.h> +# endif +#endif + +char *this_command_name; + +main(argc, argv) +int argc; +char **argv; +{ + this_command_name = argv[0]; + exit(finfo_main(argc, argv)); +} + +void +builtin_usage() +{ + fprintf(stderr, "%s: usage: %s [-%s] [file ...]\n", prog, OPTIONS); +} + +#ifndef HAVE_STRERROR +char * +strerror(e) +int e; +{ + static char ebuf[40]; + extern int sys_nerr; + extern char *sys_errlist[]; + + if (e < 0 || e > sys_nerr) { + sprintf(ebuf,"Unknown error code %d", e); + return (&ebuf[0]); + } + return (sys_errlist[e]); +} +#endif + +char * +xmalloc(s) +size_t s; +{ + char *ret; + extern char *malloc(); + + ret = malloc(s); + if (ret) + return (ret); + fprintf(stderr, "%s: cannot malloc %d bytes\n", prog, s); + exit(1); +} + +char * +base_pathname(p) +char *p; +{ + char *t; + + if (t = strrchr(p, '/')) + return(++t); + return(p); +} + +int +legal_number (string, result) + char *string; + long *result; +{ + int sign; + long value; + + sign = 1; + value = 0; + + if (result) + *result = 0; + + /* Skip leading whitespace characters. */ + while (whitespace (*string)) + string++; + + if (!*string) + return (0); + + /* We allow leading `-' or `+'. */ + if (*string == '-' || *string == '+') + { + if (!digit (string[1])) + return (0); + + if (*string == '-') + sign = -1; + + string++; + } + + while (digit (*string)) + { + if (result) + value = (value * 10) + digit_value (*string); + string++; + } + + /* Skip trailing whitespace, if any. */ + while (whitespace (*string)) + string++; + + /* Error if not at end of string. */ + if (*string) + return (0); + + if (result) + *result = value * sign; + + return (1); +} + +int sh_optind; +char *sh_optarg; +int sh_opterr; + +extern int optind; +extern char *optarg; + +int +sh_getopt(c, v, o) +int c; +char **v, *o; +{ + int r; + + r = getopt(c, v, o); + sh_optind = optind; + sh_optarg = optarg; + return r; +} + +#if defined (USE_VARARGS) +void +#if defined (PREFER_STDARG) +builtin_error (const char *format, ...) +#else +builtin_error (format, va_alist) + const char *format; + va_dcl +#endif +{ + va_list args; + + if (this_command_name && *this_command_name) + fprintf (stderr, "%s: ", this_command_name); + +#if defined (PREFER_STDARG) + va_start (args, format); +#else + va_start (args); +#endif + + vfprintf (stderr, format, args); + va_end (args); + fprintf (stderr, "\n"); +} +#else +void +builtin_error (format, arg1, arg2, arg3, arg4, arg5) + char *format, *arg1, *arg2, *arg3, *arg4, *arg5; +{ + if (this_command_name && *this_command_name) + fprintf (stderr, "%s: ", this_command_name); + + fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5); + fprintf (stderr, "\n"); + fflush (stderr); +} +#endif /* !USE_VARARGS */ + +#endif diff --git a/examples/loadables/getconf.c b/examples/loadables/getconf.c new file mode 100644 index 0000000..0bf2079 --- /dev/null +++ b/examples/loadables/getconf.c @@ -0,0 +1,1488 @@ +/* + * ORIGINAL COPYRIGHT STATEMENT: + * + * Copyright (c) 1994 Winning Strategies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Winning Strategies, Inc. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * POSIX.2 getconf utility + * + * Originally Written by: + * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc. + * + * Heavily modified for inclusion in bash by + * Chet Ramey <chet@po.cwru.edu> + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef HAVE_SYS_PARAM_H +# include <sys/param.h> +#endif + +#include <stdio.h> +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <errno.h> + +#include "typemax.h" + +#include "bashansi.h" +#include "shell.h" +#include "builtins.h" +#include "stdc.h" +#include "common.h" +#include "bashgetopt.h" + +#include "getconf.h" + +#ifndef errno +extern int errno; +#endif + +struct conf_variable +{ + const char *name; + enum { SYSCONF, CONFSTR, PATHCONF, CONSTANT, LLCONST, G_UNDEF } type; + long value; +}; + +#ifndef HAVE_CONFSTR +static size_t confstr __P((int, char *, size_t)); +#endif + +#ifndef HAVE_SYSCONF +static long sysconf __P((int)); +#endif + +#ifndef HAVE_PATHCONF +static long pathconf __P((const char *, int)); +#endif + +/* Hack to `encode' values wider than long into a conf_variable */ +#define VAL_LLONG_MIN -1000 +#define VAL_LLONG_MAX -1001 +#define VAL_ULLONG_MAX -1002 + +static const struct conf_variable conf_table[] = +{ + /* POSIX.2 Configurable Variable Values */ + { "PATH", CONFSTR, _CS_PATH }, + { "CS_PATH", CONFSTR, _CS_PATH }, + + /* POSIX.1 Configurable Variable Values (only Solaris?) */ +#if defined (_CS_LFS_CFLAGS) + { "LFS_CFLAGS", CONFSTR, _CS_LFS_CFLAGS }, + { "LFS_LDFLAGS", CONFSTR, _CS_LFS_LDFLAGS }, + { "LFS_LIBS", CONFSTR, _CS_LFS_LIBS }, + { "LFS_LINTFLAGS", CONFSTR, _CS_LFS_LINTFLAGS }, +#endif +#if defined (_CS_LFS64_CFLAGS) + { "LFS64_CFLAGS", CONFSTR, _CS_LFS64_CFLAGS }, + { "LFS64_LDFLAGS", CONFSTR, _CS_LFS64_LDFLAGS }, + { "LFS64_LIBS", CONFSTR, _CS_LFS64_LIBS }, + { "LFS64_LINTFLAGS", CONFSTR, _CS_LFS64_LINTFLAGS }, +#endif + + /* Single UNIX Specification version 2 Configurable Variable Values. The + SYSCONF variables say whether or not the appropriate CONFSTR variables + are available. */ +#if defined (_SC_XBS5_ILP32_OFF32) + { "XBS5_ILP32_OFF32", SYSCONF, _SC_XBS5_ILP32_OFF32 }, + { "_XBS5_ILP32_OFF32", SYSCONF, _SC_XBS5_ILP32_OFF32 }, +#endif +#if defined (_CS_XBS5_ILP32_OFF32_CFLAGS) + { "XBS5_ILP32_OFF32_CFLAGS", CONFSTR, _CS_XBS5_ILP32_OFF32_CFLAGS }, + { "XBS5_ILP32_OFF32_LDFLAGS", CONFSTR, _CS_XBS5_ILP32_OFF32_LDFLAGS }, + { "XBS5_ILP32_OFF32_LIBS", CONFSTR, _CS_XBS5_ILP32_OFF32_LIBS }, + { "XBS5_ILP32_OFF32_LINTFLAGS", CONFSTR, _CS_XBS5_ILP32_OFF32_LINTFLAGS }, +#endif +#if defined (_SC_XBS5_ILP32_OFFBIG) + { "XBS5_ILP32_OFFBIG", SYSCONF, _SC_XBS5_ILP32_OFFBIG }, + { "_XBS5_ILP32_OFFBIG", SYSCONF, _SC_XBS5_ILP32_OFFBIG }, +#endif +#if defined (_CS_XBS5_ILP32_OFFBIG_CFLAGS) + { "XBS5_ILP32_OFFBIG_CFLAGS", CONFSTR, _CS_XBS5_ILP32_OFFBIG_CFLAGS }, + { "XBS5_ILP32_OFFBIG_LDFLAGS", CONFSTR, _CS_XBS5_ILP32_OFFBIG_LDFLAGS }, + { "XBS5_ILP32_OFFBIG_LIBS", CONFSTR, _CS_XBS5_ILP32_OFFBIG_LIBS }, + { "XBS5_ILP32_OFFBIG_LINTFLAGS", CONFSTR, _CS_XBS5_ILP32_OFFBIG_LINTFLAGS }, +#endif +#if defined (_SC_XBS5_LP64_OFF64) + { "XBS5_LP64_OFF64", SYSCONF, _SC_XBS5_LP64_OFF64 }, + { "_XBS5_LP64_OFF64", SYSCONF, _SC_XBS5_LP64_OFF64 }, +#endif +#if defined (_CS_XBS5_LP64_OFF64_CFLAGS) + { "XBS5_LP64_OFF64_CFLAGS", CONFSTR, _CS_XBS5_LP64_OFF64_CFLAGS }, + { "XBS5_LP64_OFF64_LDFLAGS", CONFSTR, _CS_XBS5_LP64_OFF64_LDFLAGS }, + { "XBS5_LP64_OFF64_LIBS", CONFSTR, _CS_XBS5_LP64_OFF64_LIBS }, + { "XBS5_LP64_OFF64_LINTFLAGS", CONFSTR, _CS_XBS5_LP64_OFF64_LINTFLAGS }, +#endif +#if defined (_SC_XBS5_LPBIG_OFFBIG) + { "XBS5_LPBIG_OFFBIG", SYSCONF, _SC_XBS5_LPBIG_OFFBIG }, + { "_XBS5_LPBIG_OFFBIG", SYSCONF, _SC_XBS5_LPBIG_OFFBIG }, +#endif +#if defined (_CS_XBS5_LPBIG_OFFBIG_CFLAGS) + { "XBS5_LPBIG_OFFBIG_CFLAGS", CONFSTR, _CS_XBS5_LPBIG_OFFBIG_CFLAGS }, + { "XBS5_LPBIG_OFFBIG_LDFLAGS", CONFSTR, _CS_XBS5_LPBIG_OFFBIG_LDFLAGS }, + { "XBS5_LPBIG_OFFBIG_LIBS", CONFSTR, _CS_XBS5_LPBIG_OFFBIG_LIBS }, + { "XBS5_LPBIG_OFFBIG_LINTFLAGS", CONFSTR, _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS }, +#endif + + /* Single UNIX Specification version 3 (POSIX.1-200x) Configurable Variable + Values. The SYSCONF variables say whether or not the appropriate CONFSTR + variables are available. */ + +#if defined (_SC_POSIX_V6_ILP32_OFF32) + { "_POSIX_V6_ILP32_OFF32", SYSCONF, _SC_POSIX_V6_ILP32_OFF32 }, +#endif +#if defined (_CS_POSIX_V6_ILP32_OFF32_CFLAGS) + { "POSIX_V6_ILP32_OFF32_CFLAGS", CONFSTR, _CS_POSIX_V6_ILP32_OFF32_CFLAGS }, + { "POSIX_V6_ILP32_OFF32_LDFLAGS", CONFSTR, _CS_POSIX_V6_ILP32_OFF32_LDFLAGS }, + { "POSIX_V6_ILP32_OFF32_LIBS", CONFSTR, _CS_POSIX_V6_ILP32_OFF32_LIBS }, +#endif +#if defined (_CS_POSIX_V6_ILP32_OFF32_LINTFLAGS) + { "POSIX_V6_ILP32_OFF32_LINTFLAGS", CONFSTR, _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS }, +#endif +#if defined (_SC_POSIX_V6_ILP32_OFFBIG) + { "_POSIX_V6_ILP32_OFFBIG", SYSCONF, _SC_POSIX_V6_ILP32_OFFBIG }, +#endif +#if defined (_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS) + { "POSIX_V6_ILP32_OFFBIG_CFLAGS", CONFSTR, _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS }, + { "POSIX_V6_ILP32_OFFBIG_LDFLAGS", CONFSTR, _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS }, + { "POSIX_V6_ILP32_OFFBIG_LIBS", CONFSTR, _CS_POSIX_V6_ILP32_OFFBIG_LIBS }, +#endif +#if defined (_CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS) + { "POSIX_V6_ILP32_OFFBIG_LINTFLAGS", CONFSTR, _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS }, +#endif +#if defined (_SC_POSIX_V6_LP64_OFF64) + { "_POSIX_V6_LP64_OFF64", SYSCONF, _SC_POSIX_V6_LP64_OFF64 }, +#endif +#if defined (_CS_POSIX_V6_LP64_OFF64_CFLAGS) + { "POSIX_V6_LP64_OFF64_CFLAGS", CONFSTR, _CS_POSIX_V6_LP64_OFF64_CFLAGS }, + { "POSIX_V6_LP64_OFF64_LDFLAGS", CONFSTR, _CS_POSIX_V6_LP64_OFF64_LDFLAGS }, + { "POSIX_V6_LP64_OFF64_LIBS", CONFSTR, _CS_POSIX_V6_LP64_OFF64_LIBS }, +#endif +#if defined (CS_POSIX_V6_LP64_OFF64_LINTFLAGS) + { "POSIX_V6_LP64_OFF64_LINTFLAGS", CONFSTR, _CS_POSIX_V6_LP64_OFF64_LINTFLAGS }, +#endif +#if defined (_SC_POSIX_V6_LPBIG_OFFBIG) + { "_POSIX_V6_LPBIG_OFFBIG", SYSCONF, _SC_POSIX_V6_LPBIG_OFFBIG }, +#endif +#if defined (_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS) + { "POSIX_V6_LPBIG_OFFBIG_CFLAGS", CONFSTR, _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS }, + { "POSIX_V6_LPBIG_OFFBIG_LDFLAGS", CONFSTR, _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS }, + { "POSIX_V6_LPBIG_OFFBIG_LIBS", CONFSTR, _CS_POSIX_V6_LPBIG_OFFBIG_LIBS }, +#endif +#if defined (_CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS) + { "POSIX_V6_LPBIG_OFFBIG_LINTFLAGS", CONFSTR, _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS }, +#endif + +#if defined (_CS_POSIX_V6_WIDTH_RESTRICTED_ENVS) + { "POSIX_6_WIDTH_RESTRICTED_ENVS", CONFSTR, _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS }, +#endif + + /* POSIX.2 Utility Limit Minimum Values */ +#ifdef _POSIX2_BC_BASE_MAX + { "POSIX2_BC_BASE_MAX", CONSTANT, _POSIX2_BC_BASE_MAX }, +#else + { "POSIX2_BC_BASE_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX2_BC_DIM_MAX + { "POSIX2_BC_DIM_MAX", CONSTANT, _POSIX2_BC_DIM_MAX }, +#else + { "POSIX2_BC_DIM_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX2_BC_SCALE_MAX + { "POSIX2_BC_SCALE_MAX", CONSTANT, _POSIX2_BC_SCALE_MAX }, +#else + { "POSIX2_BC_SCALE_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX2_BC_STRING_MAX + { "POSIX2_BC_STRING_MAX", CONSTANT, _POSIX2_BC_STRING_MAX }, +#else + { "POSIX2_BC_STRING_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX2_CHARCLASS_NAME_MAX + { "POSIX2_CHARCLASS_NAME_MAX", CONSTANT, _POSIX2_CHARCLASS_NAME_MAX }, +#else + { "POSIX2_CHARCLASS_NAME_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX2_COLL_WEIGHTS_MAX + { "POSIX2_COLL_WEIGHTS_MAX", CONSTANT, _POSIX2_COLL_WEIGHTS_MAX }, +#else + { "POSIX2_COLL_WEIGHTS_MAX", G_UNDEF, -1 }, +#endif +#if defined (_POSIX2_EQUIV_CLASS_MAX) + { "POSIX2_EQUIV_CLASS_MAX", CONSTANT, _POSIX2_EQUIV_CLASS_MAX }, +#endif +#ifdef _POSIX2_EXPR_NEST_MAX + { "POSIX2_EXPR_NEST_MAX", CONSTANT, _POSIX2_EXPR_NEST_MAX }, +#else + { "POSIX2_EXPR_NEST_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX2_LINE_MAX + { "POSIX2_LINE_MAX", CONSTANT, _POSIX2_LINE_MAX }, +#else + { "POSIX2_LINE_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX2_RE_DUP_MAX + { "POSIX2_RE_DUP_MAX", CONSTANT, _POSIX2_RE_DUP_MAX }, +#else + { "POSIX2_RE_DUP_MAX", G_UNDEF, -1 }, +#endif +#if defined (_POSIX2_VERSION) + { "POSIX2_VERSION", CONSTANT, _POSIX2_VERSION }, +#else +# if !defined (_SC_2_VERSION) + { "POSIX2_VERSION", G_UNDEF, -1 }, +# endif +#endif + +#ifdef _POSIX2_BC_BASE_MAX + { "_POSIX2_BC_BASE_MAX", CONSTANT, _POSIX2_BC_BASE_MAX }, +#else + { "_POSIX2_BC_BASE_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX2_BC_DIM_MAX + { "_POSIX2_BC_DIM_MAX", CONSTANT, _POSIX2_BC_DIM_MAX }, +#else + { "_POSIX2_BC_DIM_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX2_BC_SCALE_MAX + { "_POSIX2_BC_SCALE_MAX", CONSTANT, _POSIX2_BC_SCALE_MAX }, +#else + { "_POSIX2_BC_SCALE_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX2_BC_STRING_MAX + { "_POSIX2_BC_STRING_MAX", CONSTANT, _POSIX2_BC_STRING_MAX }, +#else + { "_POSIX2_BC_STRING_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX2_CHARCLASS_NAME_MAX + { "_POSIX2_CHARCLASS_NAME_MAX", CONSTANT, _POSIX2_CHARCLASS_NAME_MAX }, +#else + { "_POSIX2_CHARCLASS_NAME_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX2_COLL_WEIGHTS_MAX + { "_POSIX2_COLL_WEIGHTS_MAX", CONSTANT, _POSIX2_COLL_WEIGHTS_MAX }, +#else + { "_POSIX2_COLL_WEIGHTS_MAX", G_UNDEF, -1 }, +#endif +#if defined (_POSIX2_EQUIV_CLASS_MAX) + { "POSIX2_EQUIV_CLASS_MAX", CONSTANT, _POSIX2_EQUIV_CLASS_MAX }, +#endif +#ifdef _POSIX2_EXPR_NEST_MAX + { "_POSIX2_EXPR_NEST_MAX", CONSTANT, _POSIX2_EXPR_NEST_MAX }, +#else + { "_POSIX2_EXPR_NEST_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX2_LINE_MAX + { "_POSIX2_LINE_MAX", CONSTANT, _POSIX2_LINE_MAX }, +#else + { "_POSIX2_LINE_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX2_RE_DUP_MAX + { "_POSIX2_RE_DUP_MAX", CONSTANT, _POSIX2_RE_DUP_MAX }, +#else + { "_POSIX2_RE_DUP_MAX", G_UNDEF, -1 }, +#endif + + /* X/OPEN Maxmimum Values */ +#ifdef _XOPEN_IOV_MAX + { "_XOPEN_IOV_MAX", CONSTANT, _XOPEN_IOV_MAX }, +#else + { "_XOPEN_IOV_MAX", G_UNDEF, -1 }, +#endif +#ifdef _XOPEN_NAME_MAX + { "_XOPEN_NAME_MAX", CONSTANT, _XOPEN_NAME_MAX }, +#else + { "_XOPEN_NAME_MAX", G_UNDEF, -1 }, +#endif +#ifdef _XOPEN_PATH_MAX + { "_XOPEN_PATH_MAX", CONSTANT, _XOPEN_PATH_MAX }, +#else + { "_XOPEN_PATH_MAX", G_UNDEF, -1 }, +#endif + + /* POSIX.1 Minimum Values */ +#ifdef _POSIX_AIO_LISTIO_MAX + { "_POSIX_AIO_LISTIO_MAX", CONSTANT, _POSIX_AIO_LISTIO_MAX }, +#else + { "_POSIX_AIO_LISTIO_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_AIO_MAX + { "_POSIX_AIO_MAX", CONSTANT, _POSIX_AIO_MAX }, +#else + { "_POSIX_AIO_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_ARG_MAX + { "_POSIX_ARG_MAX", CONSTANT, _POSIX_ARG_MAX }, +#else + { "_POSIX_ARG_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_CHILD_MAX + { "_POSIX_CHILD_MAX", CONSTANT, _POSIX_CHILD_MAX }, +#else + { "_POSIX_CHILD_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_DELAYTIMER_MAX + { "_POSIX_DELAYTIMER_MAX", CONSTANT, _POSIX_DELAYTIMER_MAX }, +#else + { "_POSIX_DELAYTIMER_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_HOST_NAME_MAX + { "_POSIX_HOST_NAME_MAX", CONSTANT, _POSIX_HOST_NAME_MAX }, +#else + { "_POSIX_HOST_NAME_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_LINK_MAX + { "_POSIX_LINK_MAX", CONSTANT, _POSIX_LINK_MAX }, +#else + { "_POSIX_LINK_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_LOGIN_NAME_MAX + { "_POSIX_LOGIN_NAME_MAX", CONSTANT, _POSIX_LOGIN_NAME_MAX }, +#else + { "_POSIX_LOGIN_NAME_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_MAX_CANON + { "_POSIX_MAX_CANON", CONSTANT, _POSIX_MAX_CANON }, +#else + { "_POSIX_MAX_CANON", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_MAX_INPUT + { "_POSIX_MAX_INPUT", CONSTANT, _POSIX_MAX_INPUT }, +#else + { "_POSIX_MAX_INPUT", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_MQ_OPEN_MAX + { "_POSIX_MQ_OPEN_MAX", CONSTANT, _POSIX_MQ_OPEN_MAX }, +#else + { "_POSIX_MQ_OPEN_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_MQ_PRIO_MAX + { "_POSIX_MQ_PRIO_MAX", CONSTANT, _POSIX_MQ_PRIO_MAX }, +#else + { "_POSIX_MQ_PRIO_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_NAME_MAX + { "_POSIX_NAME_MAX", CONSTANT, _POSIX_NAME_MAX }, +#else + { "_POSIX_NAME_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_NGROUPS_MAX + { "_POSIX_NGROUPS_MAX", CONSTANT, _POSIX_NGROUPS_MAX }, +#else + { "_POSIX_NGROUPS_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_OPEN_MAX + { "_POSIX_OPEN_MAX", CONSTANT, _POSIX_OPEN_MAX }, +#else + { "_POSIX_OPEN_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_PATH_MAX + { "_POSIX_PATH_MAX", CONSTANT, _POSIX_PATH_MAX }, +#else + { "_POSIX_PATH_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_PIPE_BUF + { "_POSIX_PIPE_BUF", CONSTANT, _POSIX_PIPE_BUF }, +#else + { "_POSIX_PIPE_BUF", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_RE_DUP_MAX + { "_POSIX_RE_DUP_MAX", CONSTANT, _POSIX_RE_DUP_MAX }, +#else + { "_POSIX_RE_DUP_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_RTSIG_MAX + { "_POSIX_RTSIG_MAX", CONSTANT, _POSIX_RTSIG_MAX }, +#else + { "_POSIX_RTSIG_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_SEM_NSEMS_MAX + { "_POSIX_SEM_NSEMS_MAX", CONSTANT, _POSIX_SEM_NSEMS_MAX }, +#else + { "_POSIX_SEM_NSEMS_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_SEM_VALUE_MAX + { "_POSIX_SEM_VALUE_MAX", CONSTANT, _POSIX_SEM_VALUE_MAX }, +#else + { "_POSIX_SEM_VALUE_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_SIGQUEUE_MAX + { "_POSIX_SIGQUEUE_MAX", CONSTANT, _POSIX_SIGQUEUE_MAX }, +#else + { "_POSIX_SIGQUEUE_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_SSIZE_MAX + { "_POSIX_SSIZE_MAX", CONSTANT, _POSIX_SSIZE_MAX }, +#else + { "_POSIX_SSIZE_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_SS_REPL_MAX + { "_POSIX_SS_REPL_MAX", CONSTANT, _POSIX_SS_REPL_MAX }, +#else + { "_POSIX_SS_REPL_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_STREAM_MAX + { "_POSIX_STREAM_MAX", CONSTANT, _POSIX_STREAM_MAX }, +#else + { "_POSIX_STREAM_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_SYMLINK_MAX + { "_POSIX_SYMLINK_MAX", CONSTANT, _POSIX_SYMLINK_MAX }, +#else + { "_POSIX_SYMLINK_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_SYMLOOP_MAX + { "_POSIX_SYMLOOP_MAX", CONSTANT, _POSIX_SYMLOOP_MAX }, +#else + { "_POSIX_SYMLOOP_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_THREAD_DESTRUCTOR_ITERATIONS + { "_POSIX_THREAD_DESTRUCTOR_ITERATIONS", CONSTANT, _POSIX_THREAD_DESTRUCTOR_ITERATIONS }, +#else + { "_POSIX_THREAD_DESTRUCTOR_ITERATIONS", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_THREAD_KEYS_MAX + { "_POSIX_THREAD_KEYS_MAX", CONSTANT, _POSIX_THREAD_KEYS_MAX }, +#else + { "_POSIX_THREAD_KEYS_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_THREAD_THREADS_MAX + { "_POSIX_THREAD_THREADS_MAX",CONSTANT, _POSIX_THREAD_THREADS_MAX }, +#else + { "_POSIX_THREAD_THREADS_MAX",G_UNDEF, -1 }, +#endif +#ifdef _POSIX_TIMER_MAX + { "_POSIX_TIMER_MAX", CONSTANT, _POSIX_TIMER_MAX }, +#else + { "_POSIX_TIMER_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_TRACE_EVENT_NAME_MAX + { "_POSIX_TRACE_EVENT_NAME_MAX", CONSTANT, _POSIX_TRACE_EVENT_NAME_MAX }, +#else + { "_POSIX_TRACE_EVENT_NAME_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_TRACE_NAME_MAX + { "_POSIX_TRACE_NAME_MAX", CONSTANT, _POSIX_TRACE_NAME_MAX }, +#else + { "_POSIX_TRACE_NAME_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_TRACE_SYS_MAX + { "_POSIX_TRACE_SYS_MAX", CONSTANT, _POSIX_TRACE_SYS_MAX }, +#else + { "_POSIX_TRACE_SYS_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_TRACE_USER_EVENT_MAX + { "_POSIX_TRACE_USER_EVENT_MAX", CONSTANT, _POSIX_TRACE_USER_EVENT_MAX }, +#else + { "_POSIX_TRACE_USER_EVENT_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_TTY_NAME_MAX + { "_POSIX_TTY_NAME_MAX", CONSTANT, _POSIX_TTY_NAME_MAX }, +#else + { "_POSIX_TTY_NAME_MAX", G_UNDEF, -1 }, +#endif +#ifdef _POSIX_TZNAME_MAX + { "_POSIX_TZNAME_MAX", CONSTANT, _POSIX_TZNAME_MAX }, +#else + { "_POSIX_TZNAME_MAX", G_UNDEF, -1 }, +#endif + + /* POSIX.1 Maximum Values */ +#ifdef _POSIX_CLOCKRES_MIN + { "_POSIX_CLOCKRES_MIN", CONSTANT, _POSIX_CLOCKRES_MIN }, +#else + { "_POSIX_CLOCKRES_MIN", G_UNDEF, -1 }, +#endif + + /* POSIX.1-2001/XPG6 (and later) Runtime Invariants from <limits.h> */ +#ifdef _SC_SS_REPL_MAX + { "SS_REPL_MAX", SYSCONF, _SC_SS_REPL_MAX }, +#endif +#ifdef _SC_TRACE_EVENT_NAME_MAX + { "TRACE_EVENT_NAME_MAX", SYSCONF, _SC_TRACE_EVENT_NAME_MAX }, +#endif +#ifdef _SC_TRACE_NAME_MAX + { "TRACE_NAME_MAX", SYSCONF, _SC_TRACE_NAME_MAX }, +#endif +#ifdef _SC_TRACE_SYS_MAX + { "TRACE_SYS_MAX", SYSCONF, _SC_TRACE_SYS_MAX }, +#endif +#ifdef _SC_TRACE_USER_EVENT_MAX + { "TRACE_USER_EVENT_MAX", SYSCONF, _SC_TRACE_USER_EVENT_MAX }, +#endif + + /* POSIX.2/XPG 4.2 (and later) Symbolic Utility Limits */ +#ifdef _SC_BC_BASE_MAX + { "BC_BASE_MAX", SYSCONF, _SC_BC_BASE_MAX }, +#endif +#ifdef _SC_BC_DIM_MAX + { "BC_DIM_MAX", SYSCONF, _SC_BC_DIM_MAX }, +#endif +#ifdef _SC_BC_SCALE_MAX + { "BC_SCALE_MAX", SYSCONF, _SC_BC_SCALE_MAX }, +#endif +#ifdef _SC_BC_STRING_MAX + { "BC_STRING_MAX", SYSCONF, _SC_BC_STRING_MAX }, +#endif +#ifdef CHARCLASS_NAME_MAX + { "CHARCLASS_NAME_MAX", CONSTANT, CHARCLASS_NAME_MAX }, +#endif +#ifdef _SC_COLL_WEIGHTS_MAX + { "COLL_WEIGHTS_MAX", SYSCONF, _SC_COLL_WEIGHTS_MAX }, +#endif +#ifdef _SC_EXPR_NEST_MAX + { "EXPR_NEST_MAX", SYSCONF, _SC_EXPR_NEST_MAX }, +#endif +#ifdef _SC_LINE_MAX + { "LINE_MAX", SYSCONF, _SC_LINE_MAX }, +#endif +# ifdef NL_ARGMAX + { "NL_ARGMAX", CONSTANT, NL_ARGMAX }, +#endif +#ifdef NL_LANGMAX + { "NL_LANGMAX", CONSTANT, NL_LANGMAX }, +#endif +#ifdef NL_MSGMAX + { "NL_MSGMAX", CONSTANT, NL_MSGMAX }, +#endif +#ifdef NL_NMAX + { "NL_NMAX", CONSTANT, NL_NMAX }, +#endif +#ifdef NL_SETMAX + { "NL_SETMAX", CONSTANT, NL_SETMAX }, +#endif +#ifdef NL_TEXTMAX + { "NL_TEXTMAX", CONSTANT, NL_TEXTMAX }, +#endif +#ifdef _SC_RAW_SOCKET + { "RAW_SOCKET", SYSCONF, _SC_RAW_SOCKET }, +#endif +#ifdef _SC_RE_DUP_MAX + { "RE_DUP_MAX", SYSCONF, _SC_RE_DUP_MAX }, +#endif + + /* POSIX.2 Optional Facility Configuration Values */ +#ifdef _SC_2_C_BIND + { "POSIX2_C_BIND", SYSCONF, _SC_2_C_BIND }, +#else + { "POSIX2_C_BIND", G_UNDEF, -1 }, +#endif +#ifdef _SC_2_C_DEV + { "POSIX2_C_DEV", SYSCONF, _SC_2_C_DEV }, +#else + { "POSIX2_C_DEV", G_UNDEF, -1 }, +#endif +#if defined (_SC_2_C_VERSION) + { "POSIX2_C_VERSION", SYSCONF, _SC_2_C_VERSION }, +#else + { "POSIX2_C_VERSION", G_UNDEF, -1 }, +#endif +#if defined (_SC_2_CHAR_TERM) + { "POSIX2_CHAR_TERM", SYSCONF, _SC_2_CHAR_TERM }, +#else + { "POSIX2_CHAR_TERM", G_UNDEF, -1 }, +#endif +#ifdef _SC_2_FORT_DEV + { "POSIX2_FORT_DEV", SYSCONF, _SC_2_FORT_DEV }, +#else + { "POSIX2_FORT_DEV", G_UNDEF, -1 }, +#endif +#ifdef _SC_2_FORT_RUN + { "POSIX2_FORT_RUN", SYSCONF, _SC_2_FORT_RUN }, +#else + { "POSIX2_FORT_RUN", G_UNDEF, -1 }, +#endif +#ifdef _SC_2_LOCALEDEF + { "POSIX2_LOCALEDEF", SYSCONF, _SC_2_LOCALEDEF }, +#else + { "POSIX2_LOCALEDEF", G_UNDEF, -1 }, +#endif +#ifdef _SC_2_SW_DEV + { "POSIX2_SW_DEV", SYSCONF, _SC_2_SW_DEV }, +#else + { "POSIX2_SW_DEV", G_UNDEF, -1 }, +#endif +#if defined (_SC2_UPE) + { "POSIX2_UPE", SYSCONF, _SC_2_UPE }, +#else + { "POSIX2_UPE", G_UNDEF, -1 }, +#endif +#if !defined (_POSIX2_VERSION) && defined (_SC_2_VERSION) + { "_POSIX2_VERSION", SYSCONF, _SC_2_VERSION }, +#else + { "_POSIX2_VERSION", G_UNDEF, -1 }, +#endif +#if defined (_SC_REGEX_VERSION) + { "REGEX_VERSION", SYSCONF, _SC_REGEX_VERSION }, + { "_REGEX_VERSION", SYSCONF, _SC_REGEX_VERSION }, +#else + { "REGEX_VERSION", G_UNDEF, -1 }, + { "_REGEX_VERSION", G_UNDEF, -1 }, +#endif + +#if defined (_SC_2_PBS) + { "_POSIX2_PBS", SYSCONF, _SC_2_PBS }, + { "_POSIX2_PBS_ACCOUNTING", SYSCONF, _SC_2_PBS_ACCOUNTING }, +# if defined (_SC_2_PBS_CHECKPOINT) + { "_POSIX2_PBS_CHECKPOINT", SYSCONF, _SC_2_PBS_CHECKPOINT }, +# endif + { "_POSIX2_PBS_LOCATE", SYSCONF, _SC_2_PBS_LOCATE }, + { "_POSIX2_PBS_MESSAGE", SYSCONF, _SC_2_PBS_MESSAGE }, + { "_POSIX2_PBS_TRACK", SYSCONF, _SC_2_PBS_TRACK }, +#endif + + /* POSIX.1 Configurable System Variables */ +#ifdef _SC_ARG_MAX + { "ARG_MAX", SYSCONF, _SC_ARG_MAX }, +#endif +#ifdef _SC_CHILD_MAX + { "CHILD_MAX", SYSCONF, _SC_CHILD_MAX }, +#endif +#ifdef _SC_CLK_TCK + { "CLK_TCK", SYSCONF, _SC_CLK_TCK }, +#endif +#ifdef _SC_DELAYTIMER_MAX + { "DELAYTIMER_MAX", SYSCONF, _SC_DELAYTIMER_MAX }, +#endif +#ifdef _SC_NGROUPS_MAX + { "NGROUPS_MAX", SYSCONF, _SC_NGROUPS_MAX }, +#endif +#ifdef NZERO + { "NZERO", CONSTANT, NZERO }, +#endif +#ifdef _SC_OPEN_MAX + { "OPEN_MAX", SYSCONF, _SC_OPEN_MAX }, +#endif +#ifdef PASS_MAX + { "PASS_MAX", CONSTANT, PASS_MAX }, +#endif +#ifdef _SC_STREAM_MAX + { "STREAM_MAX", SYSCONF, _SC_STREAM_MAX }, +#endif +#ifdef TMP_MAX + { "TMP_MAX", CONSTANT, TMP_MAX }, +#endif +#ifdef _SC_TZNAME_MAX + { "TZNAME_MAX", SYSCONF, _SC_TZNAME_MAX }, +#endif + + /* POSIX.1 Optional Facility Configuration Values */ +#if defined (_SC_ADVISORY_INFO) + { "_POSIX_ADVISORY_INFO", SYSCONF, _SC_ADVISORY_INFO }, +#endif +#if defined (_SC_ASYNCHRONOUS_IO) + { "_POSIX_ASYNCHRONOUS_IO", SYSCONF, _SC_ASYNCHRONOUS_IO }, +#endif +#if defined (_SC_BARRIERS) + { "_POSIX_BARRIERS", SYSCONF, _SC_BARRIERS }, +#endif +#if defined (_SC_BASE) + { "_POSIX_BASE", SYSCONF, _SC_BASE }, +#endif +#if defined (_SC_C_LANG_SUPPORT) + { "_POSIX_C_LANG_SUPPORT", SYSCONF, _SC_C_LANG_SUPPORT }, +#endif +#if defined (_SC_C_LANG_SUPPORT_R) + { "_POSIX_C_LANG_SUPPORT_R", SYSCONF, _SC_C_LANG_SUPPORT_R }, +#endif +#if defined (_SC_CLOCK_SELECTION) + { "_POSIX_CLOCK_SELECTION", SYSCONF, _SC_CLOCK_SELECTION }, +#endif +#if defined (_SC_CPUTIME) + { "_POSIX_CPUTIME", SYSCONF, _SC_CPUTIME }, +#endif +#if defined (_SC_DEVICE_IO) + { "_POSIX_DEVICE_IO", SYSCONF, _SC_DEVICE_IO }, +#endif +#if defined (_SC_DEVICE_SPECIFIC) + { "_POSIX_DEVICE_SPECIFIC", SYSCONF, _SC_DEVICE_SPECIFIC }, +#endif +#if defined (_SC_DEVICE_SPECIFIC_R) + { "_POSIX_DEVICE_SPECIFIC_R", SYSCONF, _SC_DEVICE_SPECIFIC_R }, +#endif +#if defined (_SC_FD_MGMT) + { "_POSIX_FD_MGMT", SYSCONF, _SC_FD_MGMT }, +#endif +#if defined (_SC_FIFO) + { "_POSIX_FIFO", SYSCONF, _SC_FIFO }, +#endif +#if defined (_SC_FILE_ATTRIBUTES) + { "_POSIX_FILE_ATTRIBUTES", SYSCONF, _SC_FILE_ATTRIBUTES }, +#endif +#if defined (_SC_FILE_LOCKING) + { "_POSIX_FILE_LOCKING", SYSCONF, _SC_FILE_LOCKING }, +#endif +#if defined (_SC_FILE_SYSTEM) + { "_POSIX_FILE_SYSTEM", SYSCONF, _SC_FILE_SYSTEM }, +#endif +#if defined (_SC_FSYNC) + { "_POSIX_FSYNC", SYSCONF, _SC_FSYNC }, +#endif +#if defined (_SC_IPV6) + { "_POSIX_IPV6", SYSCONF, _SC_IPV6 }, +#endif +#if defined (_SC_JOB_CONTROL) + { "_POSIX_JOB_CONTROL", SYSCONF, _SC_JOB_CONTROL }, +#endif +#if defined (_SC_MAPPED_FILES) + { "_POSIX_MAPPED_FILES", SYSCONF, _SC_MAPPED_FILES }, +#endif +#if defined (_SC_MEMLOCK) + { "_POSIX_MEMLOCK", SYSCONF, _SC_MEMLOCK }, +#endif +#if defined (_SC_MEMLOCK_RANGE) + { "_POSIX_MEMLOCK_RANGE", SYSCONF, _SC_MEMLOCK_RANGE }, +#endif +#if defined (_SC_MEMORY_PROTECTION) + { "_POSIX_MEMORY_PROTECTION", SYSCONF, _SC_MEMORY_PROTECTION }, +#endif +#if defined (_SC_MESSAGE_PASSING) + { "_POSIX_MESSAGE_PASSING", SYSCONF, _SC_MESSAGE_PASSING }, +#endif +#if defined (_SC_MONOTONIC_CLOCK) + { "_POSIX_MONOTONIC_CLOCK", SYSCONF, _SC_MONOTONIC_CLOCK }, +#endif +#if defined (_SC_MULTI_PROCESS) + { "_POSIX_MULTI_PROCESS", SYSCONF, _SC_MULTI_PROCESS }, +#endif +#if defined (_SC_NETWORKING) + { "_POSIX_NETWORKING", SYSCONF, _SC_NETWORKING }, +#endif +#if defined (_SC_PIPE) + { "_POSIX_PIPE", SYSCONF, _SC_PIPE }, +#endif +#if defined (SC_PRIORITIZED_IO) + { "_POSIX_PRIORITIZED_IO", SYSCONF, _SC_PRIORITIZED_IO }, +#endif +#if defined (_SC_PRIORITY_SCHEDULING) + { "_POSIX_PRIORITY_SCHEDULING", SYSCONF, _SC_PRIORITY_SCHEDULING }, +#endif +#if defined (_SC_READER_WRITER_LOCKS) + { "_POSIX_READER_WRITER_LOCKS", SYSCONF, _SC_READER_WRITER_LOCKS }, +#endif +#if defined (_SC_RAW_SOCKETS) + { "_POSIX_RAW_SOCKETS", SYSCONF, _SC_RAW_SOCKETS }, +#endif +#if defined (_SC_REALTIME_SIGNALS) + { "_POSIX_REALTIME_SIGNALS", SYSCONF, _SC_REALTIME_SIGNALS }, +#endif +#if defined (_SC_REGEXP) + { "_POSIX_REGEXP", SYSCONF, _SC_REGEXP }, +#endif +#if defined (_SC_SAVED_IDS) + { "_POSIX_SAVED_IDS", SYSCONF, _SC_SAVED_IDS }, +#endif +#if defined (_SC_SEMAPHORES) + { "_POSIX_SEMAPHORES", SYSCONF, _SC_SEMAPHORES }, +#endif +#if defined (_SC_SHARED_MEMORY_OBJECTS) + { "_POSIX_SHARED_MEMORY_OBJECTS", SYSCONF, _SC_SHARED_MEMORY_OBJECTS }, +#endif + { "_POSIX_SHELL", CONSTANT, 1 }, +#if defined (_SC_SIGNALS) + { "_POSIX_SIGNALS", SYSCONF, _SC_SIGNALS }, +#endif +#if defined (_SC_SINGLE_PROCESS) + { "_POSIX_SINGLE_PROCESS", SYSCONF, _SC_SINGLE_PROCESS }, +#endif +#if defined (_SC_SPAWN) + { "_POSIX_SPAWN", SYSCONF, _SC_SPAWN }, +#endif +#if defined (_SC_SPIN_LOCKS) + { "_POSIX_SPIN_LOCKS", SYSCONF, _SC_SPIN_LOCKS }, +#endif +#if defined (_SC_SPORADIC_SERVER) + { "_POSIX_SPORADIC_SERVER", SYSCONF, _SC_SPORADIC_SERVER }, +#endif +#if defined (_SC_SYMLOOP_MAX) + { "_POSIX_SYMLOOP_MAX", SYSCONF, _SC_SYMLOOP_MAX }, +#endif +#if defined (_SC_SYNCHRONIZED_IO) + { "_POSIX_SYNCHRONIZED_IO", SYSCONF, _SC_SYNCHRONIZED_IO }, +#endif +#if defined (_SC_SYSTEM_DATABASE) + { "_POSIX_SYSTEM_DATABASE", SYSCONF, _SC_SYSTEM_DATABASE }, +#endif +#if defined (_SC_SYSTEM_DATABASE_R) + { "_POSIX_SYSTEM_DATABASE_R", SYSCONF, _SC_SYSTEM_DATABASE_R }, +#endif +#if defined (_SC_THREAD_ATTR_STACKADDR) + { "_POSIX_THREAD_ATTR_STACKADDR", SYSCONF, _SC_THREAD_ATTR_STACKADDR }, +#endif +#if defined (_SC_THREAD_ATTR_STACKSIZE) + { "_POSIX_THREAD_ATTR_STACKSIZE", SYSCONF, _SC_THREAD_ATTR_STACKSIZE }, +#endif +#if defined (_SC_THREAD_CPUTIME) + { "_POSIX_THREAD_CPUTIME", SYSCONF, _SC_THREAD_CPUTIME }, +#endif +#if defined (_SC_THREAD_PRIO_INHERIT) + { "_POSIX_THREAD_PRIO_INHERIT", SYSCONF, _SC_THREAD_PRIO_INHERIT }, +#endif +#if defined (_SC_THREAD_PRIO_PROTECT) + { "_POSIX_THREAD_PRIO_PROTECT", SYSCONF, _SC_THREAD_PRIO_PROTECT }, +#endif +#if defined (_SC_THREAD_PRIORITY_SCHEDULING) + { "_POSIX_THREAD_PRIORITY_SCHEDULING", SYSCONF, _SC_THREAD_PRIORITY_SCHEDULING }, +#endif +#if defined (_SC_THREAD_PROCESS_SHARED) + { "_POSIX_THREAD_PROCESS_SHARED", SYSCONF, _SC_THREAD_PROCESS_SHARED }, +#endif +#if defined (_SC_THREAD_SAFE_FUNCTIONS) + { "_POSIX_THREAD_SAFE_FUNCTIONS", SYSCONF, _SC_THREAD_SAFE_FUNCTIONS }, +#endif +#if defined (_SC_THREAD_SPORADIC_SERVER) + { "_POSIX_THREAD_SPORADIC_SERVER", SYSCONF, _SC_THREAD_SPORADIC_SERVER }, +#endif +#if defined (_SC_THREADS) + { "_POSIX_THREADS", SYSCONF, _SC_THREADS }, +#endif +#if defined (_SC_TIMEOUTS) + { "_POSIX_TIMEOUTS", SYSCONF, _SC_TIMEOUTS }, +#endif +#if defined (_SC_TIMERS) + { "_POSIX_TIMERS", SYSCONF, _SC_TIMERS }, +#endif +#if defined (_SC_TRACE) + { "_POSIX_TRACE", SYSCONF, _SC_TRACE }, +#endif +#if defined (_SC_TRACE) + { "_POSIX_TRACE_EVENT_FILTER",SYSCONF, _SC_TRACE_EVENT_FILTER }, +#endif +#if defined (_SC_TRACE) + { "_POSIX_TRACE_INHERIT", SYSCONF, _SC_TRACE_INHERIT }, +#endif +#if defined (_SC_TRACE) + { "_POSIX_TRACE_LOG", SYSCONF, _SC_TRACE_LOG }, +#endif +#if defined (_SC_TYPED_MEMORY_OBJECTS) + { "_POSIX_TYPED_MEMORY_OBJECTS", SYSCONF, _SC_TYPED_MEMORY_OBJECTS }, +#endif +#if defined (_SC_VERSION) + { "_POSIX_VERSION", SYSCONF, _SC_VERSION }, +#endif + + /* XPG 4.2 Configurable System Variables. */ +#if defined (_SC_ATEXIT_MAX) + { "ATEXIT_MAX", SYSCONF, _SC_ATEXIT_MAX }, +#endif +#if defined (_SC_GETGR_R_SIZE_MAX) + { "GETGR_R_SIZE_MAX", SYSCONF, _SC_GETGR_R_SIZE_MAX }, +#endif +#if defined (_SC_GETPW_R_SIZE_MAX) + { "GETPW_R_SIZE_MAX", SYSCONF, _SC_GETPW_R_SIZE_MAX }, +#endif +#if defined (_SC_HOST_NAME_MAX) + { "HOST_NAME_MAX", SYSCONF, _SC_HOST_NAME_MAX }, +#endif +#if defined (_SC_IOV_MAX) + { "IOV_MAX", SYSCONF, _SC_IOV_MAX }, +#endif +#if defined (_SC_LOGIN_NAME_MAX) + { "LOGIN_NAME_MAX", SYSCONF, _SC_LOGIN_NAME_MAX }, +#endif +#if defined (_SC_LOGNAME_MAX) + { "LOGNAME_MAX", SYSCONF, _SC_LOGNAME_MAX }, +#endif +#if defined (_SC_PAGESIZE) + { "PAGESIZE", SYSCONF, _SC_PAGESIZE }, +#endif +#if defined (_SC_PAGE_SIZE) + { "PAGE_SIZE", SYSCONF, _SC_PAGE_SIZE }, +#endif +#if defined (_SC_SYMLOOP_MAX) + { "SYMLOOP_MAX", SYSCONF, _SC_SYMLOOP_MAX }, +#endif +#if defined (_SC_TTY_NAME_MAX) + { "TTY_NAME_MAX", SYSCONF, _SC_TTY_NAME_MAX }, +#endif +#if defined (_SC_USER_GROUPS) + { "_POSIX_USER_GROUPS", SYSCONF, _SC_USER_GROUPS }, +#endif +#if defined (_SC_USER_GROUPS_R) + { "_POSIX_USER_GROUPS_R", SYSCONF, _SC_USER_GROUPS_R }, +#endif + +#if defined (_SC_AIO_LISTIO_MAX) + { "AIO_LISTIO_MAX", SYSCONF, _SC_AIO_LISTIO_MAX }, +#endif +#if defined (_SC_AIO_MAX) + { "AIO_MAX", SYSCONF, _SC_AIO_MAX }, +#endif +#if defined (_SC_AIO_PRIO_DELTA_MAX) + { "AIO_PRIO_DELTA_MAX", SYSCONF, _SC_AIO_PRIO_DELTA_MAX }, +#endif +#if defined (_SC_MQ_OPEN_MAX) + { "MQ_OPEN_MAX", SYSCONF, _SC_MQ_OPEN_MAX }, +#endif +#if defined (_SC_MQ_PRIO_MAX) + { "MQ_PRIO_MAX", SYSCONF, _SC_MQ_PRIO_MAX }, +#endif +#if defined (_SC_RTSIG_MAX) + { "RTSIG_MAX", SYSCONF, _SC_RTSIG_MAX }, +#endif +#if defined (_SC_SEM_NSEMS_MAX) + { "SEM_NSEMS_MAX", SYSCONF, _SC_SEM_NSEMS_MAX }, +#endif +#if defined (_SC_SEM_VALUE_MAX) + { "SEM_VALUE_MAX", SYSCONF, _SC_SEM_VALUE_MAX }, +#endif +#if defined (_SC_SIGQUEUE_MAX) + { "SIGQUEUE_MAX", SYSCONF, _SC_SIGQUEUE_MAX }, +#endif +#if defined (_SC_TIMER_MAX) + { "TIMER_MAX", SYSCONF, _SC_TIMER_MAX }, +#endif + +#if defined (_SC_THREAD_DESTRUCTOR_ITERATIONS) + { "PTHREAD_DESTRUCTOR_ITERATIONS", SYSCONF, _SC_THREAD_DESTRUCTOR_ITERATIONS }, +#endif +#if defined (_SC_THREAD_KEYS_MAX) + { "PTHREAD_KEYS_MAX", SYSCONF, _SC_THREAD_KEYS_MAX }, +#endif +#if defined (_SC_THREAD_STACK_MIN) + { "PTHREAD_STACK_MIN", SYSCONF, _SC_THREAD_STACK_MIN }, +#endif +#if defined (_SC_THREAD_THREADS_MAX) + { "PTHREAD_THREADS_MAX", SYSCONF, _SC_THREAD_THREADS_MAX }, +#endif + + /* XPG 4.2 (and later) Optional Facility Configuration Values */ +#if defined (_SC_XOPEN_CRYPT) + { "_XOPEN_CRYPT", SYSCONF, _SC_XOPEN_CRYPT }, +#endif +#if defined (_SC_XOPEN_ENH_I18N) + { "_XOPEN_ENH_I18N", SYSCONF, _SC_XOPEN_ENH_I18N }, +#endif +#if defined (_SC_XOPEN_LEGACY) + { "_XOPEN_LEGACY", SYSCONF, _SC_XOPEN_LEGACY }, +#endif /* _SC_XOPEN_LEGACY */ +#if defined (_SC_XOPEN_REALTIME) + { "_XOPEN_REALTIME", SYSCONF, _SC_XOPEN_REALTIME }, +#endif +#if defined (_SC_XOPEN_REALTIME_THREADS) + { "_XOPEN_REALTIME_THREADS", SYSCONF, _SC_XOPEN_REALTIME_THREADS }, +#endif +#if defined (_SC_XOPEN_SHM) + { "_XOPEN_SHM", SYSCONF, _SC_XOPEN_SHM }, +#endif +#if defined (_SC_XOPEN_STREAMS) + { "_XOPEN_STREAMS", SYSCONF, _SC_XOPEN_STREAMS }, +#endif +#if defined (_SC_XOPEN_UNIX) + { "_XOPEN_UNIX", SYSCONF, _SC_XOPEN_UNIX }, +#endif +#if defined (_SC_XOPEN_VERSION) + { "_XOPEN_VERSION", SYSCONF, _SC_XOPEN_VERSION }, +#endif +#if defined (_SC_XOPEN_XCU_VERSION) + { "_XOPEN_XCU_VERSION", SYSCONF, _SC_XOPEN_XCU_VERSION }, +#endif +#if defined (_SC_XOPEN_XPG2) + { "_XOPEN_XPG2", SYSCONF, _SC_XOPEN_XPG2 }, +#endif +#if defined (_SC_XOPEN_XPG3) + { "_XOPEN_XPG3", SYSCONF, _SC_XOPEN_XPG3 }, +#endif +#if defined (_SC_XOPEN_XPG4) + { "_XOPEN_XPG4", SYSCONF, _SC_XOPEN_XPG4 }, +#endif +#if defined (_SC_XOPEN_XPG5) + { "_XOPEN_XPG5", SYSCONF, _SC_XOPEN_XPG5 }, +#endif + + /* POSIX.1 Configurable Pathname Values */ +#ifdef _PC_LINK_MAX + { "LINK_MAX", PATHCONF, _PC_LINK_MAX }, +#endif +#ifdef _PC_MAX_CANON + { "MAX_CANON", PATHCONF, _PC_MAX_CANON }, +#endif +#ifdef _PC_MAX_INPUT + { "MAX_INPUT", PATHCONF, _PC_MAX_INPUT }, +#endif +#ifdef _PC_NAME_MAX + { "NAME_MAX", PATHCONF, _PC_NAME_MAX }, +#endif +#ifdef _PC_PATH_MAX + { "PATH_MAX", PATHCONF, _PC_PATH_MAX }, +#endif +#ifdef _PC_PIPE_BUF + { "PIPE_BUF", PATHCONF, _PC_PIPE_BUF }, +#endif +#ifdef _PC_SYMLINK_MAX + { "SYMLINK_MAX", PATHCONF, _PC_SYMLINK_MAX }, +#endif +#ifdef _PC_CHOWN_RESTRICTED + { "_POSIX_CHOWN_RESTRICTED", PATHCONF, _PC_CHOWN_RESTRICTED }, +#endif +#ifdef _PC_NO_TRUNC + { "_POSIX_NO_TRUNC", PATHCONF, _PC_NO_TRUNC }, +#endif +#ifdef _PC_VDISABLE + { "_POSIX_VDISABLE", PATHCONF, _PC_VDISABLE }, +#endif + + /* XPG 4.2 Configurable Pathname Values */ +#if defined (_PC_FILESIZEBITS) + { "FILESIZEBITS", PATHCONF, _PC_FILESIZEBITS }, +#endif +#if defined (_PC_ASYNC_IO) + { "_POSIX_ASYNC_IO", PATHCONF, _PC_ASYNC_IO }, +#endif +#if defined (_PC_PRIO_IO) + { "_POSIX_PRIO_IO", PATHCONF, _PC_PRIO_IO }, +#endif +#if defined (_PC_SYNC_IO) + { "_POSIX_SYNC_IO", PATHCONF, _PC_SYNC_IO }, +#endif + + /* POSIX.1-200x configurable pathname values */ +#if defined (_PC_ALLOC_SIZE_MIN) + { "POSIX_ALLOC_SIZE_MIN", PATHCONF, _PC_ALLOC_SIZE_MIN }, + { "POSIX_REC_INCR_XFER_SIZE", PATHCONF, _PC_REC_INCR_XFER_SIZE }, + { "POSIX_REC_MAX_XFER_SIZE", PATHCONF, _PC_REC_MAX_XFER_SIZE }, + { "POSIX_REC_MIN_XFER_SIZE", PATHCONF, _PC_REC_MIN_XFER_SIZE }, + { "POSIX_REC_XFER_ALIGN", PATHCONF, _PC_REC_XFER_ALIGN }, +#endif + + /* ANSI/ISO C, POSIX.1-200x, XPG 4.2 (and later) C language type limits. */ + { "CHAR_BIT", CONSTANT, CHAR_BIT }, + { "CHAR_MAX", CONSTANT, CHAR_MAX }, + { "CHAR_MIN", CONSTANT, CHAR_MIN }, + { "INT_BIT", CONSTANT, INT_BIT }, + { "INT_MAX", CONSTANT, INT_MAX }, + { "INT_MIN", CONSTANT, INT_MIN }, +#ifdef LLONG_MAX + { "LLONG_MAX", LLCONST, VAL_LLONG_MAX }, + { "LLONG_MIN", LLCONST, VAL_LLONG_MIN }, +#endif + { "LONG_BIT", CONSTANT, LONG_BIT }, + { "LONG_MAX", CONSTANT, LONG_MAX }, + { "LONG_MIN", CONSTANT, LONG_MIN }, +#ifdef MB_LEN_MAX + { "MB_LEN_MAX", CONSTANT, MB_LEN_MAX }, +#endif + { "SCHAR_MAX", CONSTANT, SCHAR_MAX }, + { "SCHAR_MIN", CONSTANT, SCHAR_MIN }, + { "SHRT_MAX", CONSTANT, SHRT_MAX }, + { "SHRT_MIN", CONSTANT, SHRT_MIN }, + { "SIZE_MAX", CONSTANT, SIZE_MAX }, + { "SSIZE_MAX", CONSTANT, SSIZE_MAX }, + { "UCHAR_MAX", CONSTANT, UCHAR_MAX }, + { "UINT_MAX", CONSTANT, UINT_MAX }, +#ifdef ULLONG_MAX + { "ULLONG_MAX", LLCONST, VAL_ULLONG_MAX }, +#endif + { "ULONG_MAX", CONSTANT, ULONG_MAX }, + { "USHRT_MAX", CONSTANT, USHRT_MAX }, + { "WORD_BIT", CONSTANT, WORD_BIT }, + + { NULL } +}; + +static int num_getconf_variables = sizeof(conf_table) / sizeof(struct conf_variable) - 1; + +extern char *this_command_name; +extern char **make_builtin_argv (); + +static void getconf_help (); +static int getconf_print (); +static int getconf_one (); +static int getconf_all (); + +int +getconf_builtin (list) + WORD_LIST *list; +{ + int c, r, opt, aflag; + char **v; + + aflag = 0; + reset_internal_getopt(); + while ((opt = internal_getopt (list, "ahv:")) != -1) { + switch (opt) { + case 'a': + aflag = 1; + break; + case 'h': + getconf_help(); + return(EXECUTION_SUCCESS); + case 'v': + break; /* ignored */ + default: + builtin_usage(); + return(EX_USAGE); + } + } + + list = loptend; + if ((aflag == 0 && list == 0) || (aflag && list) || list_length(list) > 2) { + builtin_usage(); + return(EX_USAGE); + } + + r = aflag ? getconf_all() : getconf_one(list); + + return r; +} + +static void +getconf_help() +{ + const struct conf_variable *cp; + register int i, column; + + builtin_usage(); + printf("Acceptable variable names are:\n"); + for (cp = conf_table; cp->name != NULL; cp++) { + if (cp->type == PATHCONF) + printf("%s pathname\n", cp->name); + else + printf("%s\n", cp->name); + } +} + +static int +getconf_print(cp, vpath, all) +struct conf_variable *cp; +char *vpath; +int all; +{ + long val; + char *sval; + size_t slen; + + switch (cp->type) { + case G_UNDEF: + printf("undefined\n"); + break; + +#ifdef LLONG_MAX + case LLCONST: + switch (cp->value) { + default: + case VAL_LLONG_MIN: + printf ("%lld\n", LLONG_MIN); + break; + case VAL_LLONG_MAX: + printf ("%lld\n", LLONG_MAX); + break; +# if (ULLONG_MAX != LLONG_MAX) + case VAL_ULLONG_MAX: + printf ("%llu\n", ULLONG_MAX); + break; +# endif + } + break; +#endif + case CONSTANT: + switch (cp->value) { + case UCHAR_MAX: + case USHRT_MAX: + case UINT_MAX: +#if (ULONG_MAX != UINT_MAX) + case ULONG_MAX: +#endif +#if (SIZE_MAX != UINT_MAX) && (SIZE_MAX != ULONG_MAX) + case SIZE_MAX: +#endif + + printf("%lu\n", cp->value); + break; + default: + printf("%ld\n", cp->value); + break; + } + break; + + case CONFSTR: + errno = 0; + slen = confstr (cp->value, (char *) 0, (size_t) 0); + if (slen == 0) { + if (errno != 0) { + if (all) + printf ("getconf: %s\n", strerror(errno)); + else + builtin_error ("%s", strerror(errno)); + } else + printf ("undefined\n"); + return (EXECUTION_FAILURE); + } + sval = xmalloc(slen); + + confstr(cp->value, sval, slen); + printf("%s\n", sval); + free(sval); + break; + + case SYSCONF: + errno = 0; + if ((val = sysconf(cp->value)) == -1) { + if (errno != 0) { + if (all) + printf("getconf: %s\n", strerror (errno)); + else + builtin_error ("%s", strerror (errno)); + return (EXECUTION_FAILURE); + } + + printf ("undefined\n"); + } else { + printf("%ld\n", val); + } + break; + + case PATHCONF: + errno = 0; + if ((val = pathconf(vpath, cp->value)) == -1) { + if (errno != 0) { + if (all) + printf("getconf: %s: %s\n", vpath, strerror (errno)); + else + builtin_error ("%s: %s", vpath, strerror (errno)); + return (EXECUTION_FAILURE); + } + + printf ("undefined\n"); + } else { + printf ("%ld\n", val); + } + break; + } + + return (ferror(stdout) ? EXECUTION_FAILURE : EXECUTION_SUCCESS); +} + +static int +getconf_all() +{ + const struct conf_variable *cp; + int ret; + + ret = EXECUTION_SUCCESS; + for (cp = conf_table; cp->name != NULL; cp++) { + printf("%-35s", cp->name); + if (getconf_print(cp, "/", 1) == EXECUTION_FAILURE) + ret = EXECUTION_FAILURE; + } + return ret; +} + +static int +getconf_one(list) + WORD_LIST *list; +{ + const struct conf_variable *cp; + char *vname, *vpath; + + vname = list->word->word; + vpath = (list->next && list->next->word) ? list->next->word->word + : (char *)NULL; + + for (cp = conf_table; cp->name != NULL; cp++) { + if (strcmp(vname, cp->name) == 0) + break; + } + if (cp->name == NULL) { + builtin_error ("%s: unknown variable", vname); + return (EXECUTION_FAILURE); + } + + if (cp->type == PATHCONF) { + if (list->next == 0) { + builtin_usage(); + return(EX_USAGE); + } + } else { + if (list->next) { + builtin_usage(); + return(EX_USAGE); + } + } + + return (getconf_print(cp, vpath, 0)); +} + +static char *getconf_doc[] = { + "getconf writes the current value of a configurable system limit or", + "option variable to the standard output.", + (char *)NULL +}; + +struct builtin getconf_struct = { + "getconf", + getconf_builtin, + BUILTIN_ENABLED, + getconf_doc, + "getconf -[ah] or getconf [-v spec] sysvar or getconf [-v spec] pathvar pathname", + 0 +}; + +#ifndef HAVE_CONFSTR +static size_t +confstr (name, buf, len) + int name; + char *buf; + size_t len; +{ + switch (name) + { + case _CS_PATH: + if (len > 0 && buf) + { + strncpy (buf, STANDARD_UTILS_PATH, len - 1); + buf[len - 1] = '\0'; + } + return (sizeof (STANDARD_UTILS_PATH) + 1); + default: + errno = EINVAL; + return 0; + } +} +#endif + +#ifndef HAVE_SYSCONF +extern long get_clk_tck __P((void)); + +static long +sysconf (name) + int name; +{ +# if defined (_POSIX_VERSION) + switch (name) + { + case _SC_ARG_MAX: + return _POSIX_ARG_MAX; + case _SC_CHILD_MAX: + return _POSIX_CHILD_MAX; + case _SC_CLK_TCK: + return get_clk_tck(); + case _SC_NGROUPS_MAX: + return _POSIX_NGROUPS_MAX; + case _SC_OPEN_MAX: + return _POSIX_OPEN_MAX; + case _SC_JOB_CONTROL: + return _POSIX_JOB_CONTROL; + case _SC_SAVED_IDS: + return _POSIX_SAVED_IDS; + case _SC_VERSION: + return _POSIX_VERSION; + case _SC_BC_BASE_MAX: + return _POSIX2_BC_BASE_MAX; + case _SC_BC_DIM_MAX: + return _POSIX2_BC_DIM_MAX; + case _SC_BC_SCALE_MAX: + return _POSIX2_BC_SCALE_MAX; + case _SC_BC_STRING_MAX: + return _POSIX2_BC_STRING_MAX; + case _SC_COLL_WEIGHTS_MAX: + return -1; + case _SC_EXPR_NEST_MAX: + return _POSIX2_EXPR_NEST_MAX; + case _SC_LINE_MAX: + return _POSIX2_LINE_MAX; + case _SC_RE_DUP_MAX: + return _POSIX2_RE_DUP_MAX; + case _SC_STREAM_MAX: + return _POSIX_STREAM_MAX; + case _SC_TZNAME_MAX: + return _POSIX_TZNAME_MAX; + default: + errno = EINVAL; + return -1; + } +#else + errno = EINVAL; + return -1; +#endif +} +#endif + +#ifndef HAVE_PATHCONF +static long +pathconf (path, name) + const char *path; + int name; +{ +#if defined (_POSIX_VERSION) + switch (name) + { + case _PC_LINK_MAX: + return _POSIX_LINK_MAX; + case _PC_MAX_CANON: + return _POSIX_MAX_CANON; + case _PC_MAX_INPUT: + return _POSIX_MAX_INPUT; + case _PC_NAME_MAX: + return _POSIX_NAME_MAX; + case _PC_PATH_MAX: + return _POSIX_PATH_MAX; + case _PC_PIPE_BUF: + return _POSIX_PIPE_BUF; + case _PC_CHOWN_RESTRICTED: +#ifdef _POSIX_CHOWN_RESTRICTED + return _POSIX_CHOWN_RESTRICTED; +#else + return -1; +#endif + case _PC_NO_TRUNC: +#ifdef _POSIX_NO_TRUNC + return _POSIX_NO_TRUNC; +#else + return -1; +#endif + case _PC_VDISABLE: +#ifdef _POSIX_VDISABLE + return _POSIX_VDISABLE; +#else + return -1; +#endif + default: + errno = EINVAL; + return -1; + } +#else + errno = EINVAL; + return -1; +#endif +} +#endif diff --git a/examples/loadables/getconf.h b/examples/loadables/getconf.h new file mode 100644 index 0000000..c84062d --- /dev/null +++ b/examples/loadables/getconf.h @@ -0,0 +1,214 @@ +/* getconf.h -- replacement definitions for ones the system doesn't provide. */ + +#ifndef _GETCONF_H +#define _GETCONF_H + +/* Some systems do not define these; use POSIX.2 minimum recommended values. */ +#ifndef _POSIX2_COLL_WEIGHTS_MAX +# define _POSIX2_COLL_WEIGHTS_MAX 2 +#endif + +/* If we're on a posix system, but the system doesn't define the necessary + constants, use posix.1 minimum values. */ +#if defined (_POSIX_VERSION) + +#ifndef _POSIX_ARG_MAX +# define _POSIX_ARG_MAX 4096 +#endif +#ifndef _POSIX_CHILD_MAX +# define _POSIX_CHILD_MAX 6 +#endif +#ifndef _POSIX_LINK_MAX +# define _POSIX_LINK_MAX 8 +#endif +#ifndef _POSIX_MAX_CANON +# define _POSIX_MAX_CANON 255 +#endif +#ifndef _POSIX_MAX_INPUT +# define _POSIX_MAX_INPUT 255 +#endif +#ifndef _POSIX_NAME_MAX +# define _POSIX_NAME_MAX 14 +#endif +#ifndef _POSIX_NGROUPS_MAX +# define _POSIX_NGROUPS_MAX 0 +#endif +#ifndef _POSIX_OPEN_MAX +# define _POSIX_OPEN_MAX 16 +#endif +#ifndef _POSIX_PATH_MAX +# define _POSIX_PATH_MAX 255 +#endif +#ifndef _POSIX_PIPE_BUF +# define _POSIX_PIPE_BUF 512 +#endif +#ifndef _POSIX_SSIZE_MAX +# define _POSIX_SSIZE_MAX 32767 +#endif +#ifndef _POSIX_STREAM_MAX +# define _POSIX_STREAM_MAX 8 +#endif +#ifndef _POSIX_TZNAME_MAX +# define _POSIX_TZNAME_MAX 3 +#endif + +#ifndef _POSIX2_BC_BASE_MAX +# define _POSIX2_BC_BASE_MAX 99 +#endif +#ifndef _POSIX2_BC_DIM_MAX +# define _POSIX2_BC_DIM_MAX 2048 +#endif +#ifndef _POSIX2_BC_SCALE_MAX +# define _POSIX2_BC_SCALE_MAX 99 +#endif +#ifndef _POSIX2_BC_STRING_MAX +# define _POSIX2_BC_STRING_MAX 1000 +#endif +#ifndef _POSIX2_EQUIV_CLASS_MAX +# define _POSIX2_EQUIV_CLASS_MAX 2 +#endif +#ifndef _POSIX2_EXPR_NEST_MAX +# define _POSIX2_EXPR_NEST_MAX 32 +#endif +#ifndef _POSIX2_LINE_MAX +# define _POSIX2_LINE_MAX 2048 +#endif +#ifndef _POSIX2_RE_DUP_MAX +# define _POSIX2_RE_DUP_MAX 255 +#endif + +/* configurable system variables */ +#if !defined (HAVE_SYSCONF) + +#ifndef _SC_ARG_MAX +# define _SC_ARG_MAX 1 +# define _SC_CHILD_MAX 2 +# define _SC_CLK_TCK 3 +# define _SC_NGROUPS_MAX 4 +# define _SC_OPEN_MAX 5 +# define _SC_JOB_CONTROL 6 +# define _SC_SAVED_IDS 7 +# define _SC_VERSION 8 +# define _SC_BC_BASE_MAX 9 +# define _SC_BC_DIM_MAX 10 +# define _SC_BC_SCALE_MAX 11 +# define _SC_BC_STRING_MAX 12 +# define _SC_COLL_WEIGHTS_MAX 13 +# define _SC_EXPR_NEST_MAX 14 +# define _SC_LINE_MAX 15 +# define _SC_RE_DUP_MAX 16 +#if 0 +# define _SC_2_VERSION 17 +# define _SC_2_C_BIND 18 +# define _SC_2_C_DEV 19 +# define _SC_2_CHAR_TERM 20 +# define _SC_2_FORT_DEV 21 +# define _SC_2_FORT_RUN 22 +# define _SC_2_LOCALEDEF 23 +# define _SC_2_SW_DEV 24 +# define _SC_2_UPE 25 +#endif /* 0 */ + +# define _SC_STREAM_MAX 26 +# define _SC_TZNAME_MAX 27 +#endif /* !_SC_ARG_MAX */ + +#endif /* !HAVE_SYSCONF */ + +/* configurable pathname variables */ +#if !defined (HAVE_PATHCONF) + +#ifndef _PC_LINK_MAX +#define _PC_LINK_MAX 1 +#define _PC_MAX_CANON 2 +#define _PC_MAX_INPUT 3 +#define _PC_NAME_MAX 4 +#define _PC_PATH_MAX 5 +#define _PC_PIPE_BUF 6 +#define _PC_CHOWN_RESTRICTED 7 +#define _PC_NO_TRUNC 8 +#define _PC_VDISABLE 9 +#endif /* !_PC_LINK_MAX */ + +#endif /* !HAVE_PATHCONF */ + +#endif /* _POSIX_VERSION */ + +#ifndef _CS_PATH +# define _CS_PATH 1 +#endif + +/* ANSI/ISO C, POSIX.1-200x, XPG 4.2 (and later) C language type limits. + Defined only if the system include files don't. Assume a 32-bit + environment with signed 8-bit characters. */ + +#ifndef CHAR_BIT +# define CHAR_BIT 8 +#endif +#ifndef CHAR_MAX +# define CHAR_MAX 127 +#endif +#ifndef CHAR_MIN +# define CHAR_MIN -128 +#endif + +#ifndef INT_BIT +# define INT_BIT (sizeof (int) * CHAR_BIT) +#endif +#ifndef INT_MAX +# define INT_MAX 2147483647 +#endif +#ifndef INT_MIN +# define INT_MIN (-2147483647-1) +#endif + +#ifndef LONG_BIT +# define LONG_BIT (sizeof (long int) * CHAR_BIT) +#endif +#ifndef LONG_MAX +# define LONG_MAX 2147483647L +#endif +#ifndef LONG_MIN +# define LONG_MIN (-2147483647L-1L) +#endif + +#ifndef SCHAR_MAX +# define SCHAR_MAX CHAR_MAX +#endif +#ifndef SCHAR_MIN +# define SCHAR_MIN CHAR_MIN +#endif + +#ifndef SHRT_MAX +# define SHRT_MAX 32767 +#endif +#ifndef SHRT_MIN +# define SHRT_MIN (-32768) +#endif + +#ifndef UCHAR_MAX +# define UCHAR_MAX 255 +#endif +#ifndef UINT_MAX +# define UINT_MAX 4294967295U +#endif +#ifndef ULONG_MAX +# define ULONG_MAX 4294967295UL +#endif +#ifndef USHRT_MAX +# define UCHAR_MAX 65535 +#endif + +/* assume size_t is `unsigned int'; ssize_t is `int' */ +#ifndef SIZE_MAX +# define SIZE_MAX UINT_MAX +#endif +#ifndef SSIZE_MAX +# define SSIZE_MAX INT_MAX +#endif + +#ifndef WORD_BIT +# define WORD_BIT (sizeof (int) * CHAR_BIT) +#endif + +#endif /* _GETCONF_H */ diff --git a/examples/loadables/head.c b/examples/loadables/head.c new file mode 100644 index 0000000..9052689 --- /dev/null +++ b/examples/loadables/head.c @@ -0,0 +1,143 @@ +/* head - copy first part of files. */ + +/* See Makefile for compilation details. */ + +#include "config.h" + +#include "bashtypes.h" +#include "posixstat.h" +#include "filecntl.h" + +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif + +#include "bashansi.h" + +#include <stdio.h> +#include <errno.h> +#include "chartypes.h" + +#include "builtins.h" +#include "shell.h" +#include "bashgetopt.h" + +#if !defined (errno) +extern int errno; +#endif + +static void +munge_list (list) + WORD_LIST *list; +{ + WORD_LIST *l, *nl; + WORD_DESC *wd; + char *arg; + + for (l = list; l; l = l->next) + { + arg = l->word->word; + if (arg[0] != '-' || arg[1] == '-' || (DIGIT(arg[1]) == 0)) + return; + /* We have -[0-9]* */ + wd = make_bare_word (arg+1); + nl = make_word_list (wd, l->next); + l->word->word[1] = 'n'; + l->word->word[2] = '\0'; + l->next = nl; + l = nl; /* skip over new argument */ + } +} + +static int +file_head (fp, cnt) + FILE *fp; + int cnt; +{ + int ch; + + while (cnt--) + { + while ((ch = getc (fp)) != EOF) + { + if (putchar (ch) == EOF) + { + builtin_error ("write error: %s", strerror (errno)); + return EXECUTION_FAILURE; + } + if (ch == '\n') + break; + } + } +} + +head_builtin (list) + WORD_LIST *list; +{ + int nline, opt, rval; + WORD_LIST *l; + FILE *fp; + + char *t; + + munge_list (list); /* change -num into -n num */ + + reset_internal_getopt (); + nline = 10; + while ((opt = internal_getopt (list, "n:")) != -1) + { + switch (opt) + { + case 'n': + nline = atoi (list_optarg); + if (nline <= 0) + { + builtin_error ("bad line count: %s", list_optarg); + return (EX_USAGE); + } + break; + default: + builtin_usage (); + return (EX_USAGE); + } + } + list = loptend; + + if (list == 0) + return (file_head (stdin, nline)); + + for (rval = EXECUTION_SUCCESS, opt = 1, l = list; l; l = l->next) + { + fp = fopen (l->word->word, "r"); + if (fp == NULL) + { + builtin_error ("%s: %s", l->word->word, strerror (errno)); + continue; + } + if (list->next) /* more than one file */ + { + printf ("%s==> %s <==\n", opt ? "" : "\n", l->word->word); + opt = 0; + } + rval = file_head (fp, nline); + fclose (fp); + } + + return (rval); +} + +char *head_doc[] = { + "Copy the first N lines from the input files to the standard output.", + "N is supplied as an argument to the `-n' option. If N is not given,", + "the first ten lines are copied.", + (char *)NULL +}; + +struct builtin head_struct = { + "head", /* builtin name */ + head_builtin, /* function implementing the builtin */ + BUILTIN_ENABLED, /* initial flags for builtin */ + head_doc, /* array of long documentation strings. */ + "head [-n num] [file ...]", /* usage synopsis; becomes short_doc */ + 0 /* reserved for internal use */ +}; diff --git a/examples/loadables/hello.c b/examples/loadables/hello.c new file mode 100644 index 0000000..1d68c6f --- /dev/null +++ b/examples/loadables/hello.c @@ -0,0 +1,61 @@ +/* Sample builtin to be dynamically loaded with enable -f and create a new + builtin. */ + +/* See Makefile for compilation details. */ + +#include <config.h> + +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif + +#include <stdio.h> + +#include "builtins.h" +#include "shell.h" +#include "bashgetopt.h" + +/* A builtin `xxx' is normally implemented with an `xxx_builtin' function. + If you're converting a command that uses the normal Unix argc/argv + calling convention, use argv = make_builtin_argv (list, &argc) and call + the original `main' something like `xxx_main'. Look at cat.c for an + example. + + Builtins should use internal_getopt to parse options. It is the same as + getopt(3), but it takes a WORD_LIST *. Look at print.c for an example + of its use. + + If the builtin takes no options, call no_options(list) before doing + anything else. If it returns a non-zero value, your builtin should + immediately return EX_USAGE. Look at logname.c for an example. + + A builtin command returns EXECUTION_SUCCESS for success and + EXECUTION_FAILURE to indicate failure. */ +int +hello_builtin (list) + WORD_LIST *list; +{ + printf("hello world\n"); + fflush (stdout); + return (EXECUTION_SUCCESS); +} + +/* An array of strings forming the `long' documentation for a builtin xxx, + which is printed by `help xxx'. It must end with a NULL. */ +char *hello_doc[] = { + "this is the long doc for the sample hello builtin", + (char *)NULL +}; + +/* The standard structure describing a builtin command. bash keeps an array + of these structures. The flags must include BUILTIN_ENABLED so the + builtin can be used. */ +struct builtin hello_struct = { + "hello", /* builtin name */ + hello_builtin, /* function implementing the builtin */ + BUILTIN_ENABLED, /* initial flags for builtin */ + hello_doc, /* array of long documentation strings. */ + "hello", /* usage synopsis; becomes short_doc */ + 0 /* reserved for internal use */ +}; + diff --git a/examples/loadables/id.c b/examples/loadables/id.c new file mode 100644 index 0000000..945190d --- /dev/null +++ b/examples/loadables/id.c @@ -0,0 +1,308 @@ +/* + * id - POSIX.2 user identity + * + * (INCOMPLETE -- supplementary groups for other users not yet done) + * + * usage: id [-Ggu] [-nr] [user] + * + * The default output format looks something like: + * uid=xxx(chet) gid=xx groups=aa(aname), bb(bname), cc(cname) + */ + +#include <config.h> +#include <stdio.h> +#include "bashtypes.h" +#include <pwd.h> +#include <grp.h> +#include "bashansi.h" + +#ifdef HAVE_LIMITS_H +# include <limits.h> +#else +# include <sys/param.h> +#endif + +#if !defined (HAVE_GETPW_DECLS) +extern struct passwd *getpwuid (); +#endif +extern struct group *getgrgid (); + +#include "shell.h" +#include "builtins.h" +#include "stdc.h" +#include "common.h" +#include "bashgetopt.h" + +#define ID_ALLGROUPS 0x001 /* -G */ +#define ID_GIDONLY 0x002 /* -g */ +#define ID_USENAME 0x004 /* -n */ +#define ID_USEREAL 0x008 /* -r */ +#define ID_USERONLY 0x010 /* -u */ + +#define ID_FLAGSET(s) ((id_flags & (s)) != 0) + +static int id_flags; + +static uid_t ruid, euid; +static gid_t rgid, egid; + +static char *id_user; + +static int inituser (); + +static int id_pruser (); +static int id_prgrp (); +static int id_prgroups (); +static int id_prall (); + +int +id_builtin (list) + WORD_LIST *list; +{ + int opt; + char *user; + + id_flags = 0; + reset_internal_getopt (); + while ((opt = internal_getopt (list, "Ggnru")) != -1) + { + switch (opt) + { + case 'G': id_flags |= ID_ALLGROUPS; break; + case 'g': id_flags |= ID_GIDONLY; break; + case 'n': id_flags |= ID_USENAME; break; + case 'r': id_flags |= ID_USEREAL; break; + case 'u': id_flags |= ID_USERONLY; break; + default: + builtin_usage (); + return (EX_USAGE); + } + } + list = loptend; + + user = list ? list->word->word : (char *)NULL; + + /* Check for some invalid option combinations */ + opt = ID_FLAGSET (ID_ALLGROUPS) + ID_FLAGSET (ID_GIDONLY) + ID_FLAGSET (ID_USERONLY); + if (opt > 1 || (opt == 0 && ((id_flags & (ID_USEREAL|ID_USENAME)) != 0))) + { + builtin_usage (); + return (EX_USAGE); + } + + if (list && list->next) + { + builtin_usage (); + return (EX_USAGE); + } + + if (inituser (user) < 0) + return (EXECUTION_FAILURE); + + opt = 0; + if (id_flags & ID_USERONLY) + opt += id_pruser ((id_flags & ID_USEREAL) ? ruid : euid); + else if (id_flags & ID_GIDONLY) + opt += id_prgrp ((id_flags & ID_USEREAL) ? rgid : egid); + else if (id_flags & ID_ALLGROUPS) + opt += id_prgroups (user); + else + opt += id_prall (user); + putchar ('\n'); + fflush (stdout); + + return (opt == 0 ? EXECUTION_SUCCESS : EXECUTION_FAILURE); +} + +static int +inituser (uname) + char *uname; +{ + struct passwd *pwd; + + if (uname) + { + pwd = getpwnam (uname); + if (pwd == 0) + { + builtin_error ("%s: no such user", uname); + return -1; + } + ruid = euid = pwd->pw_uid; + rgid = egid = pwd->pw_gid; + } + else + { + ruid = current_user.uid; + euid = current_user.euid; + rgid = current_user.gid; + egid = current_user.egid; + } + return 0; +} + +/* Print the name or value of user ID UID. */ +static int +id_pruser (uid) + int uid; +{ + struct passwd *pwd = NULL; + int r; + + r = 0; + if (id_flags & ID_USENAME) + { + pwd = getpwuid (uid); + if (pwd == NULL) + r = 1; + } + if (pwd) + printf ("%s", pwd->pw_name); + else + printf ("%u", (unsigned) uid); + + return r; +} + +/* Print the name or value of group ID GID. */ + +static int +id_prgrp (gid) + int gid; +{ + struct group *grp = NULL; + int r; + + r = 0; + if (id_flags & ID_USENAME) + { + grp = getgrgid (gid); + if (grp == NULL) + r = 1; + } + + if (grp) + printf ("%s", grp->gr_name); + else + printf ("%u", (unsigned) gid); + + return r; +} + +static int +id_prgroups (uname) + char *uname; +{ + int *glist, ng, i, r; + + r = 0; + id_prgrp (rgid); + if (egid != rgid) + { + putchar (' '); + id_prgrp (egid); + } + + if (uname) + { + builtin_error ("supplementary groups for other users not yet implemented"); + glist = (int *)NULL; + ng = 0; + r = 1; + } + else + glist = get_group_array (&ng); + + for (i = 0; i < ng; i++) + if (glist[i] != rgid && glist[i] != egid) + { + putchar (' '); + id_prgrp (glist[i]); + } + + return r; +} + +static int +id_prall (uname) + char *uname; +{ + int r, i, ng, *glist; + struct passwd *pwd; + struct group *grp; + + r = 0; + printf ("uid=%u", (unsigned) ruid); + pwd = getpwuid (ruid); + if (pwd == NULL) + r = 1; + else + printf ("(%s)", pwd->pw_name); + + printf (" gid=%u", (unsigned) rgid); + grp = getgrgid (rgid); + if (grp == NULL) + r = 1; + else + printf ("(%s)", grp->gr_name); + + if (euid != ruid) + { + printf (" euid=%u", (unsigned) euid); + pwd = getpwuid (euid); + if (pwd == NULL) + r = 1; + else + printf ("(%s)", pwd->pw_name); + } + + if (egid != rgid) + { + printf (" egid=%u", (unsigned) egid); + grp = getgrgid (egid); + if (grp == NULL) + r = 1; + else + printf ("(%s)", grp->gr_name); + } + + if (uname) + { + builtin_error ("supplementary groups for other users not yet implemented"); + glist = (int *)NULL; + ng = 0; + r = 1; + } + else + glist = get_group_array (&ng); + + if (ng > 0) + printf (" groups="); + for (i = 0; i < ng; i++) + { + if (i > 0) + printf (", "); + printf ("%u", (unsigned) glist[i]); + grp = getgrgid (glist[i]); + if (grp == NULL) + r = 1; + else + printf ("(%s)", grp->gr_name); + } + + return r; +} + +char *id_doc[] = { + "return information about user identity", + (char *)NULL +}; + +struct builtin id_struct = { + "id", + id_builtin, + BUILTIN_ENABLED, + id_doc, + "id [user]\n\tid -G [-n] [user]\n\tid -g [-nr] [user]\n\tid -u [-nr] [user]", + 0 +}; diff --git a/examples/loadables/ln.c b/examples/loadables/ln.c new file mode 100644 index 0000000..e3234e3 --- /dev/null +++ b/examples/loadables/ln.c @@ -0,0 +1,205 @@ +/* ln - make links */ + +/* See Makefile for compilation details. */ + +#include "config.h" + +#include "bashtypes.h" + +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif + +#include "posixstat.h" + +#include <stdio.h> +#include <errno.h> + +#include "builtins.h" +#include "shell.h" +#include "bashgetopt.h" + +#if !defined (errno) +extern int errno; +#endif + +typedef int unix_link_syscall_t __P((const char *, const char *)); + +#define LN_SYMLINK 0x01 +#define LN_UNLINK 0x02 + +static unix_link_syscall_t *linkfn; +static int dolink (); + +ln_builtin (list) + WORD_LIST *list; +{ + int rval, opt, flags; + WORD_LIST *l; + char *sdir; + struct stat sb; + + flags = 0; + reset_internal_getopt (); + while ((opt = internal_getopt (list, "fs")) != -1) + { + switch (opt) + { + case 'f': + flags |= LN_UNLINK; + break; + case 's': + flags |= LN_SYMLINK; + break; + default: + builtin_usage (); + return (EX_USAGE); + } + } + list = loptend; + + if (list == 0) + { + builtin_usage (); + return (EX_USAGE); + } + + linkfn = (flags & LN_SYMLINK) ? symlink : link; + + if (list->next == 0) /* ln target, equivalent to ln target . */ + return (dolink (list->word->word, ".", flags)); + + if (list->next->next == 0) /* ln target source */ + return (dolink (list->word->word, list->next->word->word, flags)); + + /* ln target1 target2 ... directory */ + + /* find last argument: target directory, and make sure it's an existing + directory. */ + for (l = list; l->next; l = l->next) + ; + sdir = l->word->word; + + if (stat(sdir, &sb) < 0) + { + builtin_error ("%s", sdir); + return (EXECUTION_FAILURE); + } + + if (S_ISDIR (sb.st_mode) == 0) + { + builtin_usage (); + return (EX_USAGE); + } + + for (rval = EXECUTION_SUCCESS; list != l; list = list->next) + rval += dolink (list->word->word, sdir, flags); + + return rval; +} + +static char * +mkdirpath (dir, file) + char *dir, *file; +{ + int dlen, flen; + char *ret; + + dlen = strlen (dir); + flen = strlen (file); + + ret = xmalloc (2 + dlen + flen); + + strcpy (ret, dir); + if (ret[dlen - 1] != '/') + ret[dlen++] = '/'; + strcpy (ret + dlen, file); + return ret; +} + +#if defined (HAVE_LSTAT) +# define LSTAT lstat +#else +# define LSTAT stat +#endif + +static int +dolink (src, dst, flags) + char *src, *dst; + int flags; +{ + struct stat ssb, dsb; + int exists; + char *dst_path, *p; + + /* If we're not doing symlinks, the source must exist and not be a + directory. */ + if ((flags & LN_SYMLINK) == 0) + { + if (stat (src, &ssb) != 0) + { + builtin_error ("%s: %s", src, strerror (errno)); + return (EXECUTION_FAILURE); + } + if (S_ISDIR (ssb.st_mode)) + { + errno = EISDIR; + builtin_error ("%s: %s", src, strerror (errno)); + return (EXECUTION_FAILURE); + } + } + + /* If the destination is a directory, create the final filename by appending + the basename of the source to the destination. */ + dst_path = 0; + if ((stat (dst, &dsb) == 0) && S_ISDIR (dsb.st_mode)) + { + if ((p = strrchr (src, '/')) == 0) + p = src; + else + p++; + + dst_path = mkdirpath (dst, p); + dst = dst_path; + } + + exists = LSTAT (dst, &dsb) == 0; + + /* If -f was specified, and the destination exists, unlink it. */ + if ((flags & LN_UNLINK) && exists && unlink (dst) != 0) + { + builtin_error ("%s: cannot unlink: %s", dst, strerror (errno)); + FREE (dst_path); + return (EXECUTION_FAILURE); + } + + /* Perform the link. */ + if ((*linkfn) (src, dst) != 0) + { + builtin_error ("cannot link %s to %s: %s", dst, src, strerror (errno)); + FREE (dst_path); + return (EXECUTION_FAILURE); + } + + FREE (dst_path); + return (EXECUTION_SUCCESS); +} + +char *ln_doc[] = { + "Create a new directory entry with the same modes as the original", + "file. The -f option means to unlink any existing file, permitting", + "the link to occur. The -s option means to create a symbolic link.", + "By default, ln makes hard links.", + (char *)NULL +}; + +/* The standard structure describing a builtin command. bash keeps an array + of these structures. */ +struct builtin ln_struct = { + "ln", /* builtin name */ + ln_builtin, /* function implementing the builtin */ + BUILTIN_ENABLED, /* initial flags for builtin */ + ln_doc, /* array of long documentation strings. */ + "ln [-fs] file1 [file2] OR ln [-fs] file ... directory", /* usage synopsis; becomes short_doc */ + 0 /* reserved for internal use */ +}; diff --git a/examples/loadables/logname.c b/examples/loadables/logname.c new file mode 100644 index 0000000..00cfd19 --- /dev/null +++ b/examples/loadables/logname.c @@ -0,0 +1,52 @@ +/* logname - print login name of current user */ + +#include <config.h> + +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif + +#include <stdio.h> +#include <errno.h> + +#include "builtins.h" +#include "shell.h" + +#if !defined (errno) +extern int errno; +#endif + +logname_builtin (list) + WORD_LIST *list; +{ + char *np; + + if (no_options (list)) + return (EX_USAGE); + + np = getlogin (); + if (np == 0) + { + builtin_error ("cannot find username: %s", strerror (errno)); + return (EXECUTION_FAILURE); + } + printf ("%s\n", np); + return (EXECUTION_SUCCESS); +} + +char *logname_doc[] = { + "write the current user's login name to the standard output", + "and exit. logname ignores the LOGNAME and USER variables.", + "logname ignores any non-option arguments.", + (char *)NULL +}; + +struct builtin logname_struct = { + "logname", + logname_builtin, + BUILTIN_ENABLED, + logname_doc, + "logname", + 0 +}; + diff --git a/examples/loadables/mkdir.c b/examples/loadables/mkdir.c new file mode 100644 index 0000000..cd6e5f9 --- /dev/null +++ b/examples/loadables/mkdir.c @@ -0,0 +1,216 @@ +/* mkdir - make directories */ + +/* See Makefile for compilation details. */ + +#include <config.h> + +#include "bashtypes.h" +#include "posixstat.h" +#include <errno.h> +#include <stdio.h> +#include "bashansi.h" +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif + +#include "builtins.h" +#include "shell.h" +#include "bashgetopt.h" + +#if !defined (errno) +extern int errno; +#endif + +#define ISOCTAL(c) ((c) >= '0' && (c) <= '7') + +extern int parse_symbolic_mode (); + +static int make_path (); + +static int original_umask; + +int +mkdir_builtin (list) + WORD_LIST *list; +{ + int opt, pflag, omode, rval, octal, nmode, parent_mode, um; + char *mode; + WORD_LIST *l; + + reset_internal_getopt (); + pflag = 0; + mode = (char *)NULL; + while ((opt = internal_getopt(list, "m:p")) != -1) + switch (opt) + { + case 'p': + pflag = 1; + break; + case 'm': + mode = list_optarg; + break; + default: + builtin_usage(); + return (EX_USAGE); + } + list = loptend; + + if (list == 0) + { + builtin_usage (); + return (EX_USAGE); + } + + if (mode == NULL) + omode = S_IRWXU | S_IRWXG | S_IRWXO; /* a=rwx */ + else if (ISOCTAL (*mode)) /* octal number */ + { + omode = read_octal (mode); + if (omode < 0) + { + builtin_error ("invalid file mode: %s", mode); + return (EXECUTION_FAILURE); + } + octal = 1; + } + else if (mode) + { + /* initial bits are a=rwx; the mode argument modifies them */ + omode = parse_symbolic_mode (mode, S_IRWXU | S_IRWXG | S_IRWXO); + if (omode < 0) + { + builtin_error ("invalid file mode: %s", mode); + return (EXECUTION_FAILURE); + } + octal = 0; + } + + /* Make the new mode */ + original_umask = umask (0); + umask (original_umask); + + nmode = (S_IRWXU | S_IRWXG | S_IRWXO) & ~original_umask; + parent_mode = nmode | (S_IWRITE|S_IEXEC); /* u+wx */ + + /* Adjust new mode based on mode argument */ + nmode &= omode; + + for (rval = EXECUTION_SUCCESS, l = list; l; l = l->next) + { + if (pflag && make_path (l->word->word, nmode, parent_mode)) + { + rval = EXECUTION_FAILURE; + continue; + } + else if (pflag == 0 && mkdir (l->word->word, nmode) < 0) + { + builtin_error ("cannot create directory `%s': %s", l->word->word, strerror (errno)); + rval = EXECUTION_FAILURE; + } + } + return rval; +} + +/* Make all the directories leading up to PATH, then create PATH. Note that + this changes the process's umask; make sure that all paths leading to a + return reset it to ORIGINAL_UMASK */ +static int +make_path (path, nmode, parent_mode) + char *path; + int nmode, parent_mode; +{ + int oumask; + struct stat sb; + char *p, *npath; + + if (stat (path, &sb) == 0) + { + if (S_ISDIR (sb.st_mode) == 0) + { + builtin_error ("`%s': file exists but is not a directory", path); + return 1; + } + + if (chmod (path, nmode)) + { + builtin_error ("%s: %s", path, strerror (errno)); + return 1; + } + + return 0; + } + + oumask = umask (0); + npath = savestring (path); /* So we can write to it. */ + + /* Check whether or not we need to do anything with intermediate dirs. */ + + /* Skip leading slashes. */ + p = npath; + while (*p == '/') + p++; + + while (p = strchr (p, '/')) + { + *p = '\0'; + if (stat (npath, &sb) != 0) + { + if (mkdir (npath, parent_mode)) + { + builtin_error ("cannot create directory `%s': %s", npath, strerror (errno)); + umask (original_umask); + free (npath); + return 1; + } + } + else if (S_ISDIR (sb.st_mode) == 0) + { + builtin_error ("`%s': file exists but is not a directory", npath); + umask (original_umask); + free (npath); + return 1; + } + + *p++ = '/'; /* restore slash */ + while (*p == '/') + p++; + } + + /* Create the final directory component. */ + if (stat (npath, &sb) && mkdir (npath, nmode)) + { + builtin_error ("cannot create directory `%s': %s", npath, strerror (errno)); + umask (original_umask); + free (npath); + return 1; + } + + umask (original_umask); + free (npath); + return 0; +} + +char *mkdir_doc[] = { + "Make directories. Create the directories named as arguments, in", + "the order specified, using mode rwxrwxrwx as modified by the current", + "umask (see `help umask'). The -m option causes the file permission", + "bits of the final directory to be MODE. The MODE argument may be", + "an octal number or a symbolic mode like that used by chmod(1). If", + "a symbolic mode is used, the operations are interpreted relative to", + "an initial mode of \"a=rwx\". The -p option causes any required", + "intermediate directories in PATH to be created. The directories", + "are created with permssion bits of rwxrwxrwx as modified by the current", + "umask, plus write and search permissions for the owner. mkdir", + "returns 0 if the directories are created successfully, and non-zero", + "if an error occurs.", + (char *)NULL +}; + +struct builtin mkdir_struct = { + "mkdir", + mkdir_builtin, + BUILTIN_ENABLED, + mkdir_doc, + "mkdir [-p] [-m mode] directory [directory ...]", + 0 +}; diff --git a/examples/loadables/necho.c b/examples/loadables/necho.c new file mode 100644 index 0000000..521ee2c --- /dev/null +++ b/examples/loadables/necho.c @@ -0,0 +1,33 @@ +/* necho - echo without options or argument interpretation */ + +/* Sample builtin to be dynamically loaded with enable -f and replace an + existing builtin. */ + +#include <stdio.h> +#include "builtins.h" +#include "shell.h" + +necho_builtin (list) +WORD_LIST *list; +{ + print_word_list (list, " "); + printf("\n"); + fflush (stdout); + return (EXECUTION_SUCCESS); +} + +char *necho_doc[] = { + "Print the arguments to the standard ouput separated", + "by space characters and terminated with a newline.", + (char *)NULL +}; + +struct builtin necho_struct = { + "echo", + necho_builtin, + BUILTIN_ENABLED, + necho_doc, + "echo [args]", + 0 +}; + diff --git a/examples/loadables/pathchk.c b/examples/loadables/pathchk.c new file mode 100644 index 0000000..2e36f8f --- /dev/null +++ b/examples/loadables/pathchk.c @@ -0,0 +1,358 @@ +/* pathchk - check pathnames for validity and portability */ + +/* Usage: pathchk [-p] path ... + + For each PATH, print a message if any of these conditions are false: + * all existing leading directories in PATH have search (execute) permission + * strlen (PATH) <= PATH_MAX + * strlen (each_directory_in_PATH) <= NAME_MAX + + Exit status: + 0 All PATH names passed all of the tests. + 1 An error occurred. + + Options: + -p Instead of performing length checks on the + underlying filesystem, test the length of the + pathname and its components against the POSIX.1 + minimum limits for portability, _POSIX_NAME_MAX + and _POSIX_PATH_MAX in 2.9.2. Also check that + the pathname contains no character not in the + portable filename character set. */ + +/* See Makefile for compilation details. */ + +#include <config.h> + +#include <sys/types.h> +#include "posixstat.h" + +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif + +#if defined (HAVE_LIMITS_H) +# include <limits.h> +#endif + +#include "bashansi.h" + +#include <stdio.h> +#include <errno.h> + +#include "builtins.h" +#include "shell.h" +#include "stdc.h" +#include "bashgetopt.h" +#include "maxpath.h" + +#if !defined (errno) +extern int errno; +#endif + +#if !defined (_POSIX_PATH_MAX) +# define _POSIX_PATH_MAX 255 +#endif +#if !defined (_POSIX_NAME_MAX) +# define _POSIX_NAME_MAX 14 +#endif + +/* How do we get PATH_MAX? */ +#if defined (_POSIX_VERSION) && !defined (PATH_MAX) +# define PATH_MAX_FOR(p) pathconf ((p), _PC_PATH_MAX) +#endif + +/* How do we get NAME_MAX? */ +#if defined (_POSIX_VERSION) && !defined (NAME_MAX) +# define NAME_MAX_FOR(p) pathconf ((p), _PC_NAME_MAX) +#endif + +#if !defined (PATH_MAX_FOR) +# define PATH_MAX_FOR(p) PATH_MAX +#endif + +#if !defined (NAME_MAX_FOR) +# define NAME_MAX_FOR(p) NAME_MAX +#endif + +extern char *strerror (); + +static int validate_path (); + +pathchk_builtin (list) + WORD_LIST *list; +{ + int retval, pflag, opt; + + reset_internal_getopt (); + while ((opt = internal_getopt (list, "p")) != -1) + { + switch (opt) + { + case 'p': + pflag = 1; + break; + default: + builtin_usage (); + return (EX_USAGE); + } + } + list = loptend; + + if (list == 0) + { + builtin_usage (); + return (EX_USAGE); + } + + for (retval = 0; list; list = list->next) + retval |= validate_path (list->word->word, pflag); + + return (retval ? EXECUTION_FAILURE : EXECUTION_SUCCESS); +} + +char *pathchk_doc[] = { + "Check each pathname argument for validity (i.e., it may be used to", + "create or access a file without casuing syntax errors) and portability", + "(i.e., no filename truncation will result). If the `-p' option is", + "supplied, more extensive portability checks are performed.", + (char *)NULL +}; + +/* The standard structure describing a builtin command. bash keeps an array + of these structures. */ +struct builtin pathchk_struct = { + "pathchk", /* builtin name */ + pathchk_builtin, /* function implementing the builtin */ + BUILTIN_ENABLED, /* initial flags for builtin */ + pathchk_doc, /* array of long documentation strings. */ + "pathchk [-p] pathname ...", /* usage synopsis */ + 0 /* reserved for internal use */ +}; + +/* The remainder of this file is stolen shamelessly from `pathchk.c' in + the sh-utils-1.12 distribution, by + + David MacKenzie <djm@gnu.ai.mit.edu> + and Jim Meyering <meyering@cs.utexas.edu> */ + +/* Each element is nonzero if the corresponding ASCII character is + in the POSIX portable character set, and zero if it is not. + In addition, the entry for `/' is nonzero to simplify checking. */ +static char const portable_chars[256] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0-15 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16-31 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, /* 32-47 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 48-63 */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 64-79 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 80-95 */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 96-111 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 112-127 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* If PATH contains only portable characters, return 1, else 0. */ + +static int +portable_chars_only (path) + const char *path; +{ + const char *p; + + for (p = path; *p; ++p) + if (portable_chars[(const unsigned char) *p] == 0) + { + builtin_error ("path `%s' contains nonportable character `%c'", path, *p); + return 0; + } + return 1; +} + +/* On some systems, stat can return EINTR. */ + +#ifndef EINTR +# define SAFE_STAT(name, buf) stat (name, buf) +#else +# define SAFE_STAT(name, buf) safe_stat (name, buf) +static inline int +safe_stat (name, buf) + const char *name; + struct stat *buf; +{ + int ret; + + do + ret = stat (name, buf); + while (ret < 0 && errno == EINTR); + + return ret; +} +#endif + +/* Return 1 if PATH is a usable leading directory, 0 if not, + 2 if it doesn't exist. */ + +static int +dir_ok (path) + const char *path; +{ + struct stat stats; + + if (SAFE_STAT (path, &stats)) + return 2; + + if (!S_ISDIR (stats.st_mode)) + { + builtin_error ("`%s' is not a directory", path); + return 0; + } + + /* Use access to test for search permission because + testing permission bits of st_mode can lose with new + access control mechanisms. Of course, access loses if you're + running setuid. */ + if (access (path, X_OK) != 0) + { + if (errno == EACCES) + builtin_error ("directory `%s' is not searchable", path); + else + builtin_error ("%s: %s", path, strerror (errno)); + return 0; + } + + return 1; +} + +static char * +xstrdup (s) + char *s; +{ + return (savestring (s)); +} + +/* Make sure that + strlen (PATH) <= PATH_MAX + && strlen (each-existing-directory-in-PATH) <= NAME_MAX + + If PORTABILITY is nonzero, compare against _POSIX_PATH_MAX and + _POSIX_NAME_MAX instead, and make sure that PATH contains no + characters not in the POSIX portable filename character set, which + consists of A-Z, a-z, 0-9, ., _, -. + + Make sure that all leading directories along PATH that exist have + `x' permission. + + Return 0 if all of these tests are successful, 1 if any fail. */ + +static int +validate_path (path, portability) + char *path; + int portability; +{ + int path_max; + int last_elem; /* Nonzero if checking last element of path. */ + int exists; /* 2 if the path element exists. */ + char *slash; + char *parent; /* Last existing leading directory so far. */ + + if (portability && !portable_chars_only (path)) + return 1; + + if (*path == '\0') + return 0; + +#ifdef lint + /* Suppress `used before initialized' warning. */ + exists = 0; +#endif + + /* Figure out the parent of the first element in PATH. */ + parent = xstrdup (*path == '/' ? "/" : "."); + + slash = path; + last_elem = 0; + while (1) + { + int name_max; + int length; /* Length of partial path being checked. */ + char *start; /* Start of path element being checked. */ + + /* Find the end of this element of the path. + Then chop off the rest of the path after this element. */ + while (*slash == '/') + slash++; + start = slash; + slash = strchr (slash, '/'); + if (slash != NULL) + *slash = '\0'; + else + { + last_elem = 1; + slash = strchr (start, '\0'); + } + + if (!last_elem) + { + exists = dir_ok (path); + if (dir_ok == 0) + { + free (parent); + return 1; + } + } + + length = slash - start; + /* Since we know that `parent' is a directory, it's ok to call + pathconf with it as the argument. (If `parent' isn't a directory + or doesn't exist, the behavior of pathconf is undefined.) + But if `parent' is a directory and is on a remote file system, + it's likely that pathconf can't give us a reasonable value + and will return -1. (NFS and tempfs are not POSIX . . .) + In that case, we have no choice but to assume the pessimal + POSIX minimums. */ + name_max = portability ? _POSIX_NAME_MAX : NAME_MAX_FOR (parent); + if (name_max < 0) + name_max = _POSIX_NAME_MAX; + if (length > name_max) + { + builtin_error ("name `%s' has length %d; exceeds limit of %d", + start, length, name_max); + free (parent); + return 1; + } + + if (last_elem) + break; + + if (exists == 1) + { + free (parent); + parent = xstrdup (path); + } + + *slash++ = '/'; + } + + /* `parent' is now the last existing leading directory in the whole path, + so it's ok to call pathconf with it as the argument. */ + path_max = portability ? _POSIX_PATH_MAX : PATH_MAX_FOR (parent); + if (path_max < 0) + path_max = _POSIX_PATH_MAX; + free (parent); + if (strlen (path) > path_max) + { + builtin_error ("path `%s' has length %d; exceeds limit of %d", + path, strlen (path), path_max); + return 1; + } + + return 0; +} diff --git a/examples/loadables/perl/Makefile.in b/examples/loadables/perl/Makefile.in new file mode 100644 index 0000000..3af9b85 --- /dev/null +++ b/examples/loadables/perl/Makefile.in @@ -0,0 +1,97 @@ +# +# Makefile for builtin perl interpreter +# +# +# Copyright (C) 1998 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +# Include some boilerplate Gnu makefile definitions. +prefix = @prefix@ + +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +infodir = @infodir@ +includedir = @includedir@ + +topdir = @top_srcdir@ +BUILD_DIR = @BUILD_DIR@ +srcdir = @srcdir@ +VPATH = .:@srcdir@ + +@SET_MAKE@ +CC = @CC@ +RM = rm -f + +SHELL = @MAKE_SHELL@ + +PERL5 = perl5 + +CFLAGS = @CFLAGS@ + +# +# These values are generated for configure by ${topdir}/support/shobj-conf. +# If your system is not supported by that script, but includes facilities for +# dynamic loading of shared objects, please update the script and send the +# changes to bash-maintainers@gnu.org. +# +SHOBJ_CC = @SHOBJ_CC@ +SHOBJ_CFLAGS = @SHOBJ_CFLAGS@ +SHOBJ_LD = @SHOBJ_LD@ +SHOBJ_LDFLAGS = @SHOBJ_LDFLAGS@ +SHOBJ_XLDFLAGS = @SHOBJ_XLDFLAGS@ +SHOBJ_LIBS = @SHOBJ_LIBS@ +SHOBJ_STATUS = @SHOBJ_STATUS@ + +# Values used for compiling the perl files +PERL_LDOPTS = `${PERL5} -MExtUtils::Embed -e ldopts` +PERL_CFLAGS = ${CCFLAGS} `${PERL5} -MExtUtils::Embed -e ccopts` + +SRC = bperl.c iperl.c perlxsi.c +OBJ = bperl.o iperl.o perlxsi.o + +BUILTIN = bperl5 + +INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins \ + -I$(topdir)/include -I$(BUILD_DIR) -I$(BUILD_DIR)/lib \ + -I$(BUILD_DIR)/builtins + + +${BUILTIN}: ${OBJ} + ${RM} $@ + ${SHOBJ_LD} ${SHOBJ_LDFLAGS} ${SHOBJ_XLDFLAGS} -o $@ ${OBJ} ${PERL_LDOPTS} ${SHOBJ_LIBS} + +bperl.o: bperl.c + ${RM} $@ + $(SHOBJ_CC) $(SHOBJ_CFLAGS) $(CFLAGS) $(INC) -c -o $@ ${srcdir}/bperl.c + +iperl.o: iperl.c + ${RM} $@ + $(SHOBJ_CC) ${SHOBJ_CFLAGS} $(PERL_CFLAGS) -c -o $@ ${srcdir}/iperl.c + +perlxsi.c: + ${PERL5} -MExtUtils::Embed -e xsinit -- -o $@ + +perlxsi.o: perlxsi.c + ${RM} $@ + ${SHOBJ_CC} ${SHOBJ_CFLAGS} $(PERL_CFLAGS) -c -o $@ perlxsi.c + +clean mostlyclean: + ${RM} ${OBJ} + ${RM} ${BUILTIN} + +distclean maintainer-clean: clean + ${RM} perlxsi.c diff --git a/examples/loadables/perl/README b/examples/loadables/perl/README new file mode 100644 index 0000000..a70a99b --- /dev/null +++ b/examples/loadables/perl/README @@ -0,0 +1,6 @@ +This illustrates how to build a perl interpreter into bash. It's not +especially useful; more a proof of concept (it provides none of the +bash internals to the perl interpreter, for example). + +This *may* require adding "-rpath /path/to/perl/CORE" and -lperl options +when compiling bash itself. diff --git a/examples/loadables/perl/bperl.c b/examples/loadables/perl/bperl.c new file mode 100644 index 0000000..77e3f7c --- /dev/null +++ b/examples/loadables/perl/bperl.c @@ -0,0 +1,46 @@ +/* + * perl builtin + */ +#include <config.h> + +#include <fcntl.h> +#include <errno.h> + +#include "builtins.h" +#include "shell.h" + +#ifndef errno +extern int errno; +#endif + +extern char **make_builtin_argv (); +extern char **export_env; + +extern int perl_main(); + +bperl_builtin(list) +WORD_LIST *list; +{ + char **v; + int c, r; + + v = make_builtin_argv(list, &c); + r = perl_main(c, v, export_env); + free(v); + + return r; +} + +char *bperl_doc[] = { + "An interface to a perl5 interpreter.", + (char *)0 +}; + +struct builtin bperl_struct = { + "bperl", + bperl_builtin, + BUILTIN_ENABLED, + bperl_doc, + "bperl [perl options] [file ...]", + 0 +}; diff --git a/examples/loadables/perl/iperl.c b/examples/loadables/perl/iperl.c new file mode 100644 index 0000000..92a6038 --- /dev/null +++ b/examples/loadables/perl/iperl.c @@ -0,0 +1,24 @@ +#include <EXTERN.h> /* from the Perl distribution */ +#include <perl.h> /* from the Perl distribution */ + +extern void xs_init _((void)); + +static PerlInterpreter *iperl; /*** The Perl interpreter ***/ + +int +perl_main(int argc, char **argv, char **env) +{ + int r; + + iperl = perl_alloc(); + perl_construct(iperl); + perl_parse(iperl, xs_init, argc, argv, (char **)NULL); + r = perl_run(iperl); + +PerlIO_flush(PerlIO_stdout()); +PerlIO_flush(PerlIO_stderr()); + + perl_destruct(iperl); + perl_free(iperl); + return (r); +} diff --git a/examples/loadables/print.c b/examples/loadables/print.c new file mode 100644 index 0000000..ad658a7 --- /dev/null +++ b/examples/loadables/print.c @@ -0,0 +1,169 @@ +/* + * print -- loadable ksh-93 style print builtin + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "bashtypes.h" + +#include <errno.h> +#include <limits.h> +#include <stdio.h> + +#include "bashansi.h" +#include "shell.h" +#include "builtins.h" +#include "stdc.h" +#include "bashgetopt.h" + +#if !defined (errno) +extern int errno; +#endif + +int print_builtin (); +static int printargs (); + +static FILE *ofp; + +extern char *this_command_name; + +static char *print_doc[] = { + "Output the arguments. The -f option means to use the argument as a", + "format string as would be supplied to printf(1). The rest of the", + "options are as in ksh.", + (char *)NULL +}; + +struct builtin print_struct = { + "print", + print_builtin, + BUILTIN_ENABLED, + print_doc, + "print [-Rnprs] [-u unit] [-f format] [arguments]", + (char *)0 +}; + +#ifndef ISOPTION +#define ISOPTION(s, c) (s[0] == '-' && s[2] == '\0' && s[1] == c) +#endif + +int +print_builtin (list) + WORD_LIST *list; +{ + int c, r, nflag, raw, ofd, sflag; + intmax_t lfd; + char **v, *pfmt, *arg; + WORD_LIST *l; + + nflag = raw = sflag = 0; + ofd = 1; + pfmt = 0; + + reset_internal_getopt (); + while ((c = internal_getopt (list, "Rnprsu:f:")) != -1) + { + switch (c) + { + case 'R': + raw = 2; + loptend = lcurrent; + if (loptend && ISOPTION (loptend->word->word, 'n')) + { + loptend = loptend->next; + nflag = 1; + } + goto opt_end; + case 'r': + raw = 1; + break; + case 'n': + nflag = 1; + break; + case 's': + sflag = 1; + break; + case 'p': + break; /* NOP */ + case 'u': + if (all_digits (list_optarg) && legal_number (list_optarg, &lfd) && lfd == (int)lfd) + ofd = lfd; + else + { + for (l = list; l->next && l->next != lcurrent; l = l->next); + lcurrent = loptend = l; + goto opt_end; + } + break; + case 'f': + pfmt = list_optarg; + break; + default: + builtin_usage (); + return (EX_USAGE); + } + } + +opt_end: + list = loptend; + + ofp = (ofd == 1) ? stdout : fdopen (dup (ofd), "w"); + + if (pfmt) + { + WORD_DESC *w; + WORD_LIST *nlist; + + w = make_word (pfmt); + nlist = make_word_list (w, list); + r = printf_builtin (nlist); + nlist->next = (WORD_LIST *)NULL; + dispose_words (nlist); + return (r); + } + + if (raw) + { + for (l = list; l; l = l->next) + { + fprintf (ofp, "%s", l->word->word); + if (l->next) + fprintf (ofp, " "); + } + if (nflag == 0) + fprintf (ofp, "\n"); + fflush (ofp); + return (0); + } + + r = printargs (list, ofp); + if (r && nflag == 0) + fprintf (ofp, "\n"); + if (ofd != 1) + fclose (ofp); + return 0; +} + +static int +printargs (list, ofp) + WORD_LIST *list; + FILE *ofp; +{ + WORD_LIST *l; + char *ostr; + int sawc; + + for (sawc = 0, l = list; l; l = l->next) + { + ostr = ansicstr (l->word->word, strlen (l->word->word), 0, &sawc, (int *)0); + fprintf (ofp, "%s", ostr); + free (ostr); + if (sawc) + return (0); + if (l->next) + fprintf (ofp, " "); + } + return (1); +} diff --git a/examples/loadables/printenv.c b/examples/loadables/printenv.c new file mode 100644 index 0000000..16f398f --- /dev/null +++ b/examples/loadables/printenv.c @@ -0,0 +1,71 @@ +/* + * printenv -- minimal builtin clone of BSD printenv(1). + * + * usage: printenv [varname] + * + */ + +#include <config.h> +#include <stdio.h> + +#include "builtins.h" +#include "shell.h" +#include "bashgetopt.h" + +extern char **export_env; + +int +printenv_builtin (list) + WORD_LIST *list; +{ + register char **envp; + int opt; + SHELL_VAR *var; + + reset_internal_getopt (); + while ((opt = internal_getopt (list, "")) != -1) + { + switch (opt) + { + default: + builtin_usage (); + return (EX_USAGE); + } + } + list = loptend; + + /* printenv */ + if (list == 0) + { + maybe_make_export_env (); /* this allows minimal code */ + for (envp = export_env; *envp; envp++) + printf ("%s\n", *envp); + return (EXECUTION_SUCCESS); + } + + /* printenv varname */ + var = find_variable (list->word->word); + if (var == 0 || (exported_p (var) == 0)) + return (EXECUTION_FAILURE); + + if (function_p (var)) + print_var_function (var); + else + print_var_value (var, 0); + + return (EXECUTION_SUCCESS); +} + +char *printenv_doc[] = { + "print values of environment variables", + (char *)NULL +}; + +struct builtin printenv_struct = { + "printenv", + printenv_builtin, + BUILTIN_ENABLED, + printenv_doc, + "printenv [varname]", + 0 +}; diff --git a/examples/loadables/push.c b/examples/loadables/push.c new file mode 100644 index 0000000..497ecd0 --- /dev/null +++ b/examples/loadables/push.c @@ -0,0 +1,95 @@ +/* + * push - anyone remember TOPS-20? + * + */ + +#include <config.h> +#include <stdio.h> +#include <errno.h> + +#include "builtins.h" +#include "shell.h" +#include "jobs.h" +#include "bashgetopt.h" + +#ifndef errno +extern int errno; +#endif + +extern int dollar_dollar_pid; +extern int last_command_exit_value; + +int +push_builtin (list) + WORD_LIST *list; +{ + pid_t pid; + int xstatus, opt; + + xstatus = EXECUTION_SUCCESS; + reset_internal_getopt (); + while ((opt = internal_getopt (list, "")) != -1) + { + switch (opt) + { + default: + builtin_usage (); + return (EX_USAGE); + } + } + list = loptend; + + pid = make_child (savestring ("push"), 0); + if (pid == -1) + { + builtin_error ("cannot fork: %s", strerror (errno)); + return (EXECUTION_FAILURE); + } + else if (pid == 0) + { + /* Shell variable adjustments: $SHLVL, $$, $PPID, $! */ + adjust_shell_level (1); + dollar_dollar_pid = getpid (); + set_ppid (); + + /* Clean up job control stuff. */ + stop_making_children (); + cleanup_the_pipeline (); + delete_all_jobs (0); + + last_asynchronous_pid = NO_PID; + + /* Make sure the job control code has the right values for + the shell's process group and tty process group, and that + the signals are set correctly for job control. */ + initialize_job_control (0); + initialize_job_signals (); + + /* And read commands until exit. */ + reader_loop (); + exit_shell (last_command_exit_value); + } + else + { + stop_pipeline (0, (COMMAND *)NULL); + xstatus = wait_for (pid); + return (xstatus); + } +} + +char *push_doc[] = { + "Create a child that is an exact duplicate of the running shell", + "and wait for it to exit. The $SHLVL, $!, $$, and $PPID variables", + "are adjusted in the child. The return value is the exit status", + "of the child.", + (char *)NULL +}; + +struct builtin push_struct = { + "push", + push_builtin, + BUILTIN_ENABLED, + push_doc, + "push", + 0 +}; diff --git a/examples/loadables/realpath.c b/examples/loadables/realpath.c new file mode 100644 index 0000000..16478b7 --- /dev/null +++ b/examples/loadables/realpath.c @@ -0,0 +1,119 @@ +/* + * realpath -- canonicalize pathnames, resolving symlinks + * + * usage: realpath [-csv] pathname [pathname...] + * + * options: -c check whether or not each resolved path exists + * -s no output, exit status determines whether path is valid + * -v produce verbose output + * + * + * exit status: 0 if all pathnames resolved + * 1 if any of the pathname arguments could not be resolved + * + * + * Bash loadable builtin version + * + * Chet Ramey + * chet@po.cwru.edu + */ + +#include "config.h" + +#include <sys/types.h> +#include <sys/stat.h> + +#include <stdio.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include "bashansi.h" +#include <maxpath.h> +#include <errno.h> + +#include "builtins.h" +#include "shell.h" +#include "bashgetopt.h" + +#ifndef errno +extern int errno; +#endif + +extern char *sh_realpath(); + +realpath_builtin(list) +WORD_LIST *list; +{ + int opt, cflag, vflag, sflag, es; + char *r, realbuf[PATH_MAX], *p; + struct stat sb; + + if (list == 0) { + builtin_usage(); + return (EX_USAGE); + } + + vflag = cflag = sflag = 0; + reset_internal_getopt(); + while ((opt = internal_getopt (list, "csv")) != -1) { + switch (opt) { + case 'c': + cflag = 1; + break; + case 's': + sflag = 1; + break; + case 'v': + vflag = 1; + break; + default: + usage(); + } + } + + list = loptend; + + if (list == 0) + usage(); + + for (es = EXECUTION_SUCCESS; list; list = list->next) { + p = list->word->word; + r = sh_realpath(p, realbuf); + if (r == 0) { + es = EXECUTION_FAILURE; + if (sflag == 0) + builtin_error("%s: cannot resolve: %s", p, strerror(errno)); + continue; + } + if (cflag && (stat(realbuf, &sb) < 0)) { + es = EXECUTION_FAILURE; + if (sflag == 0) + builtin_error("%s: %s", p, strerror(errno)); + continue; + } + if (sflag == 0) { + if (vflag) + printf ("%s -> ", p); + printf("%s\n", realbuf); + } + } + return es; +} + +char *realpath_doc[] = { + "Display the canonicalized version of each PATHNAME argument, resolving", + "symbolic links. The -c option checks whether or not each resolved name", + "exists. The -s option produces no output; the exit status determines the", + "valididty of each PATHNAME. The -v option produces verbose output. The", + "exit status is 0 if each PATHNAME was resolved; non-zero otherwise.", + (char *)NULL +}; + +struct builtin realpath_struct = { + "realpath", /* builtin name */ + realpath_builtin, /* function implementing the builtin */ + BUILTIN_ENABLED, /* initial flags for builtin */ + realpath_doc, /* array of long documentation strings */ + "realpath [-csv] pathname [pathname...]", /* usage synopsis */ + 0 /* reserved for internal use */ +}; diff --git a/examples/loadables/rmdir.c b/examples/loadables/rmdir.c new file mode 100644 index 0000000..8d0f06a --- /dev/null +++ b/examples/loadables/rmdir.c @@ -0,0 +1,50 @@ +/* rmdir - remove directory */ + +/* See Makefile for compilation details. */ + +#include "config.h" + +#include <stdio.h> +#include <errno.h> +#include "builtins.h" +#include "shell.h" + +#if !defined (errno) +extern int errno; +#endif + +rmdir_builtin (list) + WORD_LIST *list; +{ + int rval; + WORD_LIST *l; + + if (no_options (list)) + return (EX_USAGE); + + for (rval = EXECUTION_SUCCESS, l = list; l; l = l->next) + if (rmdir (l->word->word) < 0) + { + builtin_error ("%s: %s", l->word->word, strerror (errno)); + rval = EXECUTION_FAILURE; + } + + return rval; +} + +char *rmdir_doc[] = { + "rmdir removes the directory entry specified by each argument,", + "provided the directory is empty.", + (char *)NULL +}; + +/* The standard structure describing a builtin command. bash keeps an array + of these structures. */ +struct builtin rmdir_struct = { + "rmdir", /* builtin name */ + rmdir_builtin, /* function implementing the builtin */ + BUILTIN_ENABLED, /* initial flags for builtin */ + rmdir_doc, /* array of long documentation strings. */ + "rmdir directory ...", /* usage synopsis; becomes short_doc */ + 0 /* reserved for internal use */ +}; diff --git a/examples/loadables/sleep.c b/examples/loadables/sleep.c new file mode 100644 index 0000000..10a62cf --- /dev/null +++ b/examples/loadables/sleep.c @@ -0,0 +1,146 @@ +/* + * sleep -- sleep for fractions of a second + * + * usage: sleep seconds[.fraction] + */ +#include "config.h" + +#include "bashtypes.h" + +#if defined (TIME_WITH_SYS_TIME) +# include <sys/time.h> +# include <time.h> +#else +# if defined (HAVE_SYS_TIME_H) +# include <sys/time.h> +# else +# include <time.h> +# endif +#endif + +#if defined (HAVE_UNISTD_H) +#include <unistd.h> +#endif + +#include <stdio.h> +#include "chartypes.h" + +#include "shell.h" +#include "builtins.h" + +#define RETURN(x) \ + do { \ + if (sp) *sp = sec; \ + if (usp) *usp = usec; \ + return (x); \ + } while (0) + +#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) +static int +fsleep(sec, usec) +long sec, usec; +{ + struct timeval tv; + + tv.tv_sec = sec; + tv.tv_usec = usec; + + return select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv); +} +#else /* !HAVE_TIMEVAL || !HAVE_SELECT */ +static int +fsleep(sec, usec) +long sec, usec; +{ + if (usec >= 500000) /* round */ + sec++; + return (sleep(sec)); +} +#endif /* !HAVE_TIMEVAL || !HAVE_SELECT */ + +/* + * An incredibly simplistic floating point converter. + */ +static int multiplier[7] = { 1, 100000, 10000, 1000, 100, 10, 1 }; + +static int +convert(s, sp, usp) +char *s; +long *sp, *usp; +{ + int n; + long sec, usec; + char *p; + + sec = usec = 0; + +#define DECIMAL '.' + + for (p = s; p && *p; p++) { + if (*p == DECIMAL) /* decimal point */ + break; + if (DIGIT(*p) == 0) + RETURN(0); + sec = (sec * 10) + (*p - '0'); + } + + if (*p == 0) + RETURN(1); + + if (*p == DECIMAL) + p++; + + /* Look for up to six digits past a decimal point. */ + for (n = 0; n < 6 && p[n]; n++) { + if (DIGIT(p[n]) == 0) + RETURN(0); + usec = (usec * 10) + (p[n] - '0'); + } + + /* Now convert to millionths */ + usec *= multiplier[n]; + + if (n == 6 && p[6] >= '5' && p[6] <= '9') + usec++; /* round up 1 */ + + RETURN(1); +} + +int +sleep_builtin (list) +WORD_LIST *list; +{ + long sec, usec; + + if (list == 0) { + builtin_usage(); + return(EX_USAGE); + } + + if (*list->word->word == '-' || list->next) { + builtin_usage (); + return (EX_USAGE); + } + + if (convert(list->word->word, &sec, &usec)) { + fsleep(sec, usec); + return(EXECUTION_SUCCESS); + } + + builtin_error("%s: bad sleep interval", list->word->word); + return (EXECUTION_FAILURE); +} + +static char *sleep_doc[] = { + "sleep suspends execution for a minimum of SECONDS[.FRACTION] seconds.", + (char *)NULL +}; + +struct builtin sleep_struct = { + "sleep", + sleep_builtin, + BUILTIN_ENABLED, + sleep_doc, + "sleep seconds[.fraction]", + 0 +}; diff --git a/examples/loadables/strftime.c b/examples/loadables/strftime.c new file mode 100644 index 0000000..92f489e --- /dev/null +++ b/examples/loadables/strftime.c @@ -0,0 +1,105 @@ +/* strftime - loadable builtin interface to strftime(3) */ + +/* See Makefile for compilation details. */ + +#include <config.h> + +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif + +#include "bashtypes.h" +#include "posixtime.h" + +#include <stdio.h> + +#include "builtins.h" +#include "shell.h" +#include "common.h" + +int +strftime_builtin (list) + WORD_LIST *list; +{ + char *format, *tbuf; + size_t tbsize, tsize; + time_t secs; + struct tm *t; + int n; + intmax_t i; + + if (list == 0) + { + builtin_usage (); + return (EX_USAGE); + } + + if (no_options (list)) + return (EX_USAGE); + + format = list->word->word; + if (format == 0 || *format == 0) + { + printf ("\n"); + return (EXECUTION_SUCCESS); + } + + list = list->next; + + if (list && list->word->word) + { + n = legal_number (list->word->word, &i); + if (n == 0 || i < 0 || i != (time_t)i) + { + sh_invalidnum (list->word->word); + return (EXECUTION_FAILURE); + } + else + secs = i; + } + else + secs = NOW; + + t = localtime (&secs); + + tbsize = strlen (format) * 4; + tbuf = 0; + + /* Now try to figure out how big the buffer should really be. strftime(3) + will return the number of bytes placed in the buffer unless it's greater + than MAXSIZE, in which case it returns 0. */ + for (n = 1; n < 4; n++) + { + tbuf = xrealloc (tbuf, tbsize * n); + tsize = strftime (tbuf, tbsize * n, format, t); + if (tsize) + break; + } + + printf ("%s\n", tbuf); + free (tbuf); + + return (EXECUTION_SUCCESS); +} + +/* An array of strings forming the `long' documentation for a builtin xxx, + which is printed by `help xxx'. It must end with a NULL. */ +char *strftime_doc[] = { + "Converts date and time format to a string and displays it on the", + "standard output. If the optional second argument is supplied, it", + "is used as the number of seconds since the epoch to use in the", + "conversion, otherwise the current time is used.", + (char *)NULL +}; + +/* The standard structure describing a builtin command. bash keeps an array + of these structures. The flags must include BUILTIN_ENABLED so the + builtin can be used. */ +struct builtin strftime_struct = { + "strftime", /* builtin name */ + strftime_builtin, /* function implementing the builtin */ + BUILTIN_ENABLED, /* initial flags for builtin */ + strftime_doc, /* array of long documentation strings. */ + "strftime format [seconds]", /* usage synopsis; becomes short_doc */ + 0 /* reserved for internal use */ +}; diff --git a/examples/loadables/sync.c b/examples/loadables/sync.c new file mode 100644 index 0000000..44d4e09 --- /dev/null +++ b/examples/loadables/sync.c @@ -0,0 +1,32 @@ +/* sync - sync the disks by forcing pending filesystem writes to complete */ + +#include <config.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "builtins.h" +#include "shell.h" +#include "bashgetopt.h" + +sync_builtin (list) + WORD_LIST *list; +{ + sync(); + return (EXECUTION_SUCCESS); +} + +char *sync_doc[] = { + "force completion of pending disk writes", + (char *)NULL +}; + +struct builtin sync_struct = { + "sync", /* builtin name */ + sync_builtin, /* function implementing the builtin */ + BUILTIN_ENABLED, /* initial flags for builtin */ + sync_doc, /* array of long documentation strings. */ + "sync", /* usage synopsis; becomes short_doc */ + 0 /* reserved for internal use */ +}; diff --git a/examples/loadables/tee.c b/examples/loadables/tee.c new file mode 100644 index 0000000..934abda --- /dev/null +++ b/examples/loadables/tee.c @@ -0,0 +1,157 @@ +/* tee - duplicate standard input */ + +/* See Makefile for compilation details. */ + +#include "config.h" + +#include "bashtypes.h" +#include "posixstat.h" +#include "filecntl.h" + +#include <signal.h> + +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif + +#include "bashansi.h" + +#include <stdio.h> +#include <errno.h> + +#include "builtins.h" +#include "shell.h" +#include "bashgetopt.h" + +#if !defined (errno) +extern int errno; +#endif + +typedef struct flist { + struct flist *next; + int fd; + char *fname; +} FLIST; + +static FLIST *tee_flist; + +#define TEE_BUFSIZE 8192 + +extern int interrupt_immediately; + +extern char *strerror (); + +tee_builtin (list) + WORD_LIST *list; +{ + int opt, append, nointr, rval, fd, fflags; + int n, nr, nw; + FLIST *fl; + char *buf, *bp; + + char *t; + + reset_internal_getopt (); + append = nointr = 0; + tee_flist = (FLIST *)NULL; + while ((opt = internal_getopt (list, "ai")) != -1) + { + switch (opt) + { + case 'a': + append = 1; + break; + case 'i': + nointr = 1; + break; + default: + builtin_usage (); + return (EX_USAGE); + } + } + list = loptend; + + if (nointr == 0) + interrupt_immediately++; + + buf = xmalloc (TEE_BUFSIZE); + + /* Initialize output file list. */ + fl = tee_flist = (FLIST *)xmalloc (sizeof(FLIST)); + tee_flist->fd = 1; + tee_flist->fname = "stdout"; + tee_flist->next = (FLIST *)NULL; + + /* Add file arguments to list of output files. */ + fflags = append ? O_WRONLY|O_CREAT|O_APPEND : O_WRONLY|O_CREAT|O_TRUNC; + for (rval = EXECUTION_SUCCESS; list; list = list->next) + { + fd = open (list->word->word, fflags, 0666); + if (fd < 0) + { + builtin_error ("%s: cannot open: %s", list->word->word, strerror (errno)); + rval = EXECUTION_FAILURE; + } + else + { + fl->next = (FLIST *)xmalloc (sizeof(FLIST)); + fl->next->fd = fd; + fl->next->fname = list->word->word; + fl = fl->next; + fl->next = (FLIST *)NULL; + } + } + + while ((nr = read(0, buf, TEE_BUFSIZE)) > 0) + for (fl = tee_flist; fl; fl = fl->next) + { + n = nr; + bp = buf; + do + { + if ((nw = write (fl->fd, bp, n)) == -1) + { + builtin_error ("%s: write error: %s", fl->fname, strerror (errno)); + rval = EXECUTION_FAILURE; + break; + } + bp += nw; + } + while (n -= nw); + } + if (nr < 0) + builtin_error ("read error: %s", strerror (errno)); + + /* Deallocate resources -- this is a builtin command. */ + tee_flist = tee_flist->next; /* skip bogus close of stdout */ + while (tee_flist) + { + fl = tee_flist; + if (close (fl->fd) < 0) + { + builtin_error ("%s: close_error: %s", fl->fname, strerror (errno)); + rval = EXECUTION_FAILURE; + } + tee_flist = tee_flist->next; + free (fl); + } + + return (rval); +} + +char *tee_doc[] = { + "Copy standard input to standard output, making a copy in each", + "filename argument. If the `-a' option is gived, the specified", + "files are appended to, otherwise they are overwritten. If the", + "`-i' option is supplied, tee ignores interrupts.", + (char *)NULL +}; + +struct builtin tee_struct = { + "tee", /* builtin name */ + tee_builtin, /* function implementing the builtin */ + BUILTIN_ENABLED, /* initial flags for builtin */ + tee_doc, /* array of long documentation strings. */ + "tee [-ai] [file ...]", /* usage synopsis; becomes short_doc */ + 0 /* reserved for internal use */ +}; diff --git a/examples/loadables/template.c b/examples/loadables/template.c new file mode 100644 index 0000000..7bb3f9f --- /dev/null +++ b/examples/loadables/template.c @@ -0,0 +1,56 @@ +/* template - example template for loadable builtin */ + +/* See Makefile for compilation details. */ + +#include <config.h> + +#if defined (HAVE_UNISTD_H) +# include <unistd.h> +#endif +#include "bashansi.h" +#include <stdio.h> +#include <errno.h> + +#include "builtins.h" +#include "shell.h" +#include "bashgetopt.h" + +#if !defined (errno) +extern int errno; +#endif + +extern char *strerror (); + +template_builtin (list) + WORD_LIST *list; +{ + int opt, rval; + + rval = EXECUTION_SUCCESS; + reset_internal_getopt (); + while ((opt = internal_getopt (list, "")) != -1) + { + switch (opt) + { + default: + builtin_usage (); + return (EX_USAGE); + } + } + list = loptend; + + return (rval); +} + +char *template_doc[] = { + (char *)NULL +}; + +struct builtin template_struct = { + "template", /* builtin name */ + template_builtin, /* function implementing the builtin */ + BUILTIN_ENABLED, /* initial flags for builtin */ + template_doc, /* array of long documentation strings. */ + "template", /* usage synopsis; becomes short_doc */ + 0 /* reserved for internal use */ +}; diff --git a/examples/loadables/truefalse.c b/examples/loadables/truefalse.c new file mode 100644 index 0000000..e77c74c --- /dev/null +++ b/examples/loadables/truefalse.c @@ -0,0 +1,45 @@ +/* true and false builtins */ + +#include "bashtypes.h" +#include "shell.h" +#include "builtins.h" + +true_builtin (list) + WORD_LIST *list; +{ + return EXECUTION_SUCCESS; +} + +false_builtin (list) + WORD_LIST *list; +{ + return EXECUTION_FAILURE; +} + +static char *true_doc[] = { + "Return a successful result.", + (char *)NULL +}; + +static char *false_doc[] = { + "Return an unsuccessful result.", + (char *)NULL +}; + +struct builtin true_struct = { + "true", + true_builtin, + BUILTIN_ENABLED, + true_doc, + "true", + 0 +}; + +struct builtin false_struct = { + "false", + false_builtin, + BUILTIN_ENABLED, + false_doc, + "false", + 0 +}; diff --git a/examples/loadables/tty.c b/examples/loadables/tty.c new file mode 100644 index 0000000..2183123 --- /dev/null +++ b/examples/loadables/tty.c @@ -0,0 +1,59 @@ +/* tty - return terminal name */ + +/* See Makefile for compilation details. */ + +#include "config.h" + +#include <stdio.h> +#include "builtins.h" +#include "shell.h" +#include "bashgetopt.h" + +extern char *ttyname (); + +tty_builtin (list) + WORD_LIST *list; +{ + int opt, sflag; + char *t; + + reset_internal_getopt (); + sflag = 0; + while ((opt = internal_getopt (list, "s")) != -1) + { + switch (opt) + { + case 's': + sflag = 1; + break; + default: + builtin_usage (); + return (EX_USAGE); + } + } + list = loptend; + + t = ttyname (0); + if (sflag == 0) + puts (t ? t : "not a tty"); + return (t ? EXECUTION_SUCCESS : EXECUTION_FAILURE); +} + +char *tty_doc[] = { + "tty writes the name of the terminal that is opened for standard", + "input to standard output. If the `-s' option is supplied, nothing", + "is written; the exit status determines whether or not the standard", + "input is connected to a tty.", + (char *)NULL +}; + +/* The standard structure describing a builtin command. bash keeps an array + of these structures. */ +struct builtin tty_struct = { + "tty", /* builtin name */ + tty_builtin, /* function implementing the builtin */ + BUILTIN_ENABLED, /* initial flags for builtin */ + tty_doc, /* array of long documentation strings. */ + "tty [-s]", /* usage synopsis; becomes short_doc */ + 0 /* reserved for internal use */ +}; diff --git a/examples/loadables/uname.c b/examples/loadables/uname.c new file mode 100644 index 0000000..9f450cd --- /dev/null +++ b/examples/loadables/uname.c @@ -0,0 +1,139 @@ +/* + * uname - print system information + * + * usage: uname [-amnrsv] + * + */ + +#include <config.h> +#include <stdio.h> + +#include "bashtypes.h" + +#if defined (HAVE_UNAME) +# include <sys/utsname.h> +#else +struct utsname { + char sysname[32]; + char nodename[32]; + char release[32]; + char version[32]; + char machine[32]; +}; +#endif + +#include <errno.h> + +#include "builtins.h" +#include "shell.h" +#include "bashgetopt.h" + +#define FLAG_SYSNAME 0x01 /* -s */ +#define FLAG_NODENAME 0x02 /* -n */ +#define FLAG_RELEASE 0x04 /* -r */ +#define FLAG_VERSION 0x08 /* -v */ +#define FLAG_MACHINE 0x10 /* -m, -p */ + +#define FLAG_ALL 0x1f + +#ifndef errno +extern int errno; +#endif + +static void uprint(); + +static int uname_flags; + +uname_builtin (list) + WORD_LIST *list; +{ + int opt, r; + struct utsname uninfo; + + uname_flags = 0; + reset_internal_getopt (); + while ((opt = internal_getopt (list, "amnprsv")) != -1) + { + switch (opt) + { + case 'a': + uname_flags |= FLAG_ALL; + break; + case 'm': + case 'p': + uname_flags |= FLAG_MACHINE; + break; + case 'n': + uname_flags |= FLAG_NODENAME; + break; + case 'r': + uname_flags |= FLAG_RELEASE; + break; + case 's': + uname_flags |= FLAG_SYSNAME; + break; + case 'v': + uname_flags |= FLAG_VERSION; + break; + default: + builtin_usage (); + return (EX_USAGE); + } + } + list = loptend; + + if (list) + { + builtin_usage (); + return (EX_USAGE); + } + + if (uname_flags == 0) + uname_flags = FLAG_SYSNAME; + + /* Only ancient systems will not have uname(2). */ +#ifdef HAVE_UNAME + if (uname (&uninfo) < 0) + { + builtin_error ("cannot get system name: %s", strerror (errno)); + return (EXECUTION_FAILURE); + } +#else + builtin_error ("cannot get system information: uname(2) not available"); + return (EXECUTION_FAILURE); +#endif + + uprint (FLAG_SYSNAME, uninfo.sysname); + uprint (FLAG_NODENAME, uninfo.nodename); + uprint (FLAG_RELEASE, uninfo.release); + uprint (FLAG_VERSION, uninfo.version); + uprint (FLAG_MACHINE, uninfo.machine); + + return (EXECUTION_SUCCESS); +} + +static void +uprint (flag, info) + int flag; + char *info; +{ + if (uname_flags & flag) + { + uname_flags &= ~flag; + printf ("%s%c", info, uname_flags ? ' ' : '\n'); + } +} + +char *uname_doc[] = { + "display information about the system", + (char *)NULL +}; + +struct builtin uname_struct = { + "uname", + uname_builtin, + BUILTIN_ENABLED, + uname_doc, + "uname [-amnrsv]", + 0 +}; diff --git a/examples/loadables/unlink.c b/examples/loadables/unlink.c new file mode 100644 index 0000000..8c81ad0 --- /dev/null +++ b/examples/loadables/unlink.c @@ -0,0 +1,52 @@ +/* unlink - remove a directory entry */ + +/* Should only be used to remove directories by a superuser prepared to let + fsck clean up the file system. */ + +#include <config.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include <stdio.h> +#include <errno.h> + +#include "builtins.h" +#include "shell.h" + +#ifndef errno +extern int errno; +#endif + +unlink_builtin (list) + WORD_LIST *list; +{ + if (list == 0) + { + builtin_usage (); + return (EX_USAGE); + } + + if (unlink (list->word->word) != 0) + { + builtin_error ("%s: cannot unlink: %s", list->word->word, strerror (errno)); + return (EXECUTION_FAILURE); + } + + return (EXECUTION_SUCCESS); +} + +char *unlink_doc[] = { + "Remove a directory entry.", + (char *)NULL +}; + +struct builtin unlink_struct = { + "unlink", /* builtin name */ + unlink_builtin, /* function implementing the builtin */ + BUILTIN_ENABLED, /* initial flags for builtin */ + unlink_doc, /* array of long documentation strings. */ + "unlink name", /* usage synopsis; becomes short_doc */ + 0 /* reserved for internal use */ +}; diff --git a/examples/loadables/whoami.c b/examples/loadables/whoami.c new file mode 100644 index 0000000..41fd5c4 --- /dev/null +++ b/examples/loadables/whoami.c @@ -0,0 +1,52 @@ +/* + * whoami - print out username of current user + */ + +#include <config.h> +#include <stdio.h> + +#include "builtins.h" +#include "shell.h" +#include "bashgetopt.h" + +whoami_builtin (list) + WORD_LIST *list; +{ + int opt; + + reset_internal_getopt (); + while ((opt = internal_getopt (list, "")) != -1) + { + switch (opt) + { + default: + builtin_usage (); + return (EX_USAGE); + } + } + list = loptend; + if (list) + { + builtin_usage (); + return (EX_USAGE); + } + + if (current_user.user_name == 0) + get_current_user_info (); + printf ("%s\n", current_user.user_name); + return (EXECUTION_SUCCESS); +} + +char *whoami_doc[] = { + "display name of current user", + (char *)NULL +}; + +struct builtin whoami_struct = { + "whoami", + whoami_builtin, + BUILTIN_ENABLED, + whoami_doc, + "whoami", + 0 +}; |