aboutsummaryrefslogtreecommitdiffstats
path: root/builtins
diff options
context:
space:
mode:
Diffstat (limited to 'builtins')
-rw-r--r--builtins/Makefile.in17
-rw-r--r--builtins/cd.def24
-rw-r--r--builtins/enable.def39
-rw-r--r--builtins/evalstring.c21
-rw-r--r--builtins/fc.def59
-rw-r--r--builtins/getopt.c13
-rw-r--r--builtins/getopts.def3
-rw-r--r--builtins/mkbuiltins.c24
-rw-r--r--builtins/printf.def20
-rw-r--r--builtins/pushd.def98
-rw-r--r--builtins/read.def5
-rw-r--r--builtins/reserved.def2
-rw-r--r--builtins/set.def2
-rw-r--r--builtins/shopt.def31
-rw-r--r--builtins/test.def5
-rw-r--r--builtins/type.def85
-rw-r--r--builtins/ulimit.def115
-rw-r--r--builtins/umask.def149
18 files changed, 461 insertions, 251 deletions
diff --git a/builtins/Makefile.in b/builtins/Makefile.in
index 2cf5d68..1c546c9 100644
--- a/builtins/Makefile.in
+++ b/builtins/Makefile.in
@@ -1,10 +1,11 @@
# This Makefile for building libbuiltins.a is in -*- text -*- for Emacs.
#
-SHELL = /bin/sh
+SHELL = @MAKE_SHELL@
RANLIB = @RANLIB@
CC = @CC@
CC_FOR_BUILD = @CC_FOR_BUILD@
AR = @AR@
+ARFLAGS = @ARFLAGS@
RM = rm -f
CP = cp
@@ -24,7 +25,7 @@ LDFLAGS = @LDFLAGS@ $(LOCAL_LDFLAGS) $(CFLAGS)
LOCAL_LDFLAGS = @LOCAL_LDFLAGS@
LIBS = @LIBS@
-INCLUDES = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(srcdir)
+INCLUDES = -I. -I.. @RL_INCLUDE@ -I$(topdir) -I$(topdir)/lib -I$(srcdir)
CCFLAGS = ${PROFILE_FLAGS} $(DEFS) $(LOCAL_DEFS) $(SYSTEM_FLAGS) $(CPPFLAGS) \
${INCLUDES} $(LOCAL_CFLAGS) $(CFLAGS)
@@ -87,7 +88,7 @@ all: $(MKBUILTINS) libbuiltins.a
libbuiltins.a: $(MKBUILTINS) $(OFILES) builtins.o
$(RM) $@
- $(AR) cr $@ $(OFILES)
+ $(AR) $(ARFLAGS) $@ $(OFILES)
-$(RANLIB) $@
builtext.h builtins.c: $(MKBUILTINS) $(DEFSRC)
@@ -95,12 +96,12 @@ builtext.h builtins.c: $(MKBUILTINS) $(DEFSRC)
@-if test -f builtext.h; then mv -f builtext.h old-builtext.h; fi
./$(MKBUILTINS) -externfile builtext.h -structfile builtins.c \
-noproduction $(DIRECTDEFINE) $(DEFSRC)
- @-if cmp -s old-builtext.h builtext.h; then \
+ @-if cmp -s old-builtext.h builtext.h 2>/dev/null; then \
mv old-builtext.h builtext.h; \
else \
$(RM) old-builtext.h; \
fi
- @-if cmp -s old-builtins.c builtins.c; then \
+ @-if cmp -s old-builtins.c builtins.c 2>/dev/null; then \
mv old-builtins.c builtins.c; \
else \
$(RM) old-builtins.c; \
@@ -112,7 +113,7 @@ mkbuiltins.o: mkbuiltins.c
$(CC_FOR_BUILD) -c $(CCFLAGS) $<
mkbuiltins: mkbuiltins.o
- $(CC_FOR_BUILD) $(LDFLAGS) -o $(MKBUILTINS) mkbuiltins.o $(LIBS)
+ $(CC_FOR_BUILD) $(PROFILE_FLAGS) $(LDFLAGS) -o $(MKBUILTINS) mkbuiltins.o $(LIBS)
# rules for deficient makes, like SunOS
mkbuiltins.o: mkbuiltins.c
@@ -126,7 +127,7 @@ evalfile.o: evalfile.c
ulimit.o: pipesize.h
pipesize.h: psize.aux
- $(SHELL) $(srcdir)/psize.sh > pipesize.h
+ $(SHELL) $(srcdir)/psize.sh > $@
psize.aux: psize.c
$(CC_FOR_BUILD) $(CCFLAGS) -o $@ $(srcdir)/psize.c
@@ -139,7 +140,7 @@ builtins.texi: $(MKBUILTINS)
./$(MKBUILTINS) -documentonly $(DEFSRC)
clean:
- $(RM) $(OFILES) $(CREATED_FILES) $(MKBUILTINS) libbuiltins.a
+ $(RM) $(OFILES) $(CREATED_FILES) $(MKBUILTINS) mkbuiltins.o libbuiltins.a
mostlyclean:
$(RM) $(OFILES) libbuiltins.a
diff --git a/builtins/cd.def b/builtins/cd.def
index 76ef14b..b6bf692 100644
--- a/builtins/cd.def
+++ b/builtins/cd.def
@@ -140,22 +140,20 @@ bindpwd (no_symlinks)
else
dirname = get_working_directory ("cd");
- bind_variable ("OLDPWD", get_string_value ("PWD"));
-
old_anm = array_needs_making;
+ pwdvar = get_string_value ("PWD");
+
+ tvar = bind_variable ("OLDPWD", pwdvar);
+ if (old_anm == 0 && array_needs_making && exported_p (tvar))
+ {
+ update_export_env_inplace ("OLDPWD=", 7, pwdvar);
+ array_needs_making = 0;
+ }
+
tvar = bind_variable ("PWD", dirname);
- /* This is an efficiency hack. If PWD is exported, we will need to
- remake the exported environment every time we change directories.
- If there is no other reason to make the exported environment, just
- update PWD in place and mark the exported environment as no longer
- needing a remake. */
if (old_anm == 0 && array_needs_making && exported_p (tvar))
{
- pwdvar = xmalloc (STRLEN (dirname) + 5); /* 5 = "PWD" + '=' + '\0' */
- strcpy (pwdvar, "PWD=");
- if (dirname)
- strcpy (pwdvar + 4, dirname);
- add_or_supercede_exported_var (pwdvar, 0);
+ update_export_env_inplace ("PWD=", 4, dirname);
array_needs_making = 0;
}
@@ -243,7 +241,7 @@ cd_builtin (list)
{
/* Find directory in $CDPATH. */
path_index = 0;
- while ((path = extract_colon_unit (cdpath, &path_index)))
+ while (path = extract_colon_unit (cdpath, &path_index))
{
/* OPT is 1 if the path element is non-empty */
opt = path[0] != '\0';
diff --git a/builtins/enable.def b/builtins/enable.def
index 61ea109..20842d5 100644
--- a/builtins/enable.def
+++ b/builtins/enable.def
@@ -26,17 +26,17 @@ $FUNCTION enable_builtin
$SHORT_DOC enable [-pnds] [-a] [-f filename] [name ...]
Enable and disable builtin shell commands. This allows
you to use a disk command which has the same name as a shell
-builtin. If -n is used, the NAMEs become disabled; otherwise
-NAMEs are enabled. For example, to use the `test' found on your
-path instead of the shell builtin version, type `enable -n test'.
-On systems supporting dynamic loading, the -f option may be used
-to load new builtins from the shared object FILENAME. The -d
-option will delete a builtin previously loaded with -f. If no
-non-option names are given, or the -p option is supplied, a list
-of builtins is printed. The -a option means to print every builtin
-with an indication of whether or not it is enabled. The -s option
-restricts the output to the Posix.2 `special' builtins. The -n
-option displays a list of all disabled builtins.
+builtin without specifying a full pathname. If -n is used, the
+NAMEs become disabled; otherwise NAMEs are enabled. For example,
+to use the `test' found in $PATH instead of the shell builtin
+version, type `enable -n test'. On systems supporting dynamic
+loading, the -f option may be used to load new builtins from the
+shared object FILENAME. The -d option will delete a builtin
+previously loaded with -f. If no non-option names are given, or
+the -p option is supplied, a list of builtins is printed. The
+-a option means to print every builtin with an indication of whether
+or not it is enabled. The -s option restricts the output to the POSIX.2
+`special' builtins. The -n option displays a list of all disabled builtins.
$END
#include <config.h>
@@ -391,6 +391,20 @@ delete_builtin (b)
shell_builtins = new_shell_builtins;
}
+/* Tenon's MachTen has a dlclose that doesn't return a value, so we
+ finesse it with a local wrapper. */
+static int
+local_dlclose (handle)
+ void *handle;
+{
+#if !defined (__MACHTEN__)
+ return (dlclose (handle));
+#else /* __MACHTEN__ */
+ dlclose (handle);
+ return ((dlerror () != NULL) ? -1 : 0);
+#endif /* __MACHTEN__ */
+}
+
static int
dyn_unload_builtin (name)
char *name;
@@ -398,6 +412,7 @@ dyn_unload_builtin (name)
struct builtin *b;
void *handle;
int ref, i;
+ char *uerror;
b = builtin_address_internal (name, 1);
if (b == 0)
@@ -420,7 +435,7 @@ dyn_unload_builtin (name)
/* Don't remove the shared object unless the reference count of builtins
using it drops to zero. */
- if (ref == 1 && dlclose (handle) != 0)
+ if (ref == 1 && local_dlclose (handle) != 0)
{
builtin_error ("cannot delete %s: %s", name, dlerror ());
return (EXECUTION_FAILURE);
diff --git a/builtins/evalstring.c b/builtins/evalstring.c
index 0063b71..56d2e1b 100644
--- a/builtins/evalstring.c
+++ b/builtins/evalstring.c
@@ -51,6 +51,8 @@
extern int errno;
#endif
+#define IS_BUILTIN(s) (builtin_address_internal(s, 0) != (struct builtin *)NULL)
+
extern void run_trap_cleanup ();
extern int interactive, interactive_shell;
@@ -181,7 +183,7 @@ parse_and_execute (string, from_file, flags)
}
default:
- programming_error ("parse_and_execute: bad jump: code %d", code);
+ command_error ("parse_and_execute", CMDERR_BADJUMP, code, 0);
break;
}
}
@@ -206,9 +208,20 @@ parse_and_execute (string, from_file, flags)
global_command = (COMMAND *)NULL;
#if defined (ONESHOT)
- if (startup_state == 2 && *bash_input.location.string == '\0' &&
- command->type == cm_simple && !command->redirects &&
- !command->value.Simple->redirects &&
+ /*
+ * IF
+ * we were invoked as `bash -c' (startup_state == 2) AND
+ * parse_and_execute has not been called recursively AND
+ * we have parsed the full command (string == '\0') AND
+ * we have a simple command without redirections AND
+ * the command is not being timed
+ * THEN
+ * tell the execution code that we don't need to fork
+ */
+ if (startup_state == 2 && parse_and_execute_level == 1 &&
+ *bash_input.location.string == '\0' &&
+ command->type == cm_simple &&
+ !command->redirects && !command->value.Simple->redirects &&
((command->flags & CMD_TIME_PIPELINE) == 0))
{
command->flags |= CMD_NO_FORK;
diff --git a/builtins/fc.def b/builtins/fc.def
index 587d7ed..064420b 100644
--- a/builtins/fc.def
+++ b/builtins/fc.def
@@ -26,13 +26,13 @@ $FUNCTION fc_builtin
$DEPENDS_ON HISTORY
$SHORT_DOC fc [-e ename] [-nlr] [first] [last] or fc -s [pat=rep] [cmd]
+fc is used to list or edit and re-execute commands from the history list.
FIRST and LAST can be numbers specifying the range, or FIRST can be a
string, which means the most recent command beginning with that
string.
-e ENAME selects which editor to use. Default is FCEDIT, then EDITOR,
- then the editor which corresponds to the current readline editing
- mode, then vi.
+ then vi.
-l means list lines instead of editing.
-n means no line numbers listed.
@@ -156,7 +156,7 @@ fc_builtin (list)
register int i;
register char *sep;
int numbering, reverse, listing, execute;
- int histbeg, histend, last_hist, retval, first, opt;
+ int histbeg, histend, last_hist, retval, opt;
FILE *stream;
REPL *rlist, *rl;
char *ename, *command, *newcom, *line;
@@ -372,64 +372,11 @@ fc_builtin (list)
return (EXECUTION_FAILURE);
}
- /* Now reopen the file and execute the edited commands. */
-
- stream = fopen (fn, "r");
-
- if (stream == NULL)
- {
- builtin_error ("cannot reopen temp file %s", fn);
- unlink (fn);
- return (EXECUTION_FAILURE);
- }
-
- retval = EXECUTION_SUCCESS;
- first = 1;
-
-#if 1
/* Make sure parse_and_execute doesn't turn this off, even though a
call to parse_and_execute farther up the function call stack (e.g.,
if this is called by vi_edit_and_execute_command) may have already
called bash_history_disable. */
remember_on_history = 1;
-#else
- /* First, write the commands to the history file. This will not happen
- when we call parse_and_execute, since parse_and_execute disables
- the command line history while it executes. */
-
- opt = current_command_line_count;
- while ((line = fc_readline (stream)) != NULL)
- {
- if (line[0] == '\n')
- {
- free (line);
- continue; /* Skip blank lines. */
- }
-
- if (first)
- {
- first = 0;
- /* If we retrieved only one command from the history file, but we
- read multiple lines from the edited file, and literal_history
- has been set by `shopt', we assume that it was a compound
- command stored with embedded newlines. In this case, we want
- the history code to store it as one command again. */
- if (literal_history && histbeg == histend)
- current_command_line_count = 1;
- fc_replhist (line);
- }
- else
- {
- if (literal_history && histbeg == histend)
- current_command_line_count++;
- fc_addhist (line);
- }
-
- free (line);
- }
- fclose (stream);
- current_command_line_count = opt;
-#endif
/* Turn on the `v' flag while fc_execute_file runs so the commands
will be echoed as they are read by the parser. */
diff --git a/builtins/getopt.c b/builtins/getopt.c
index 2fbcac7..ff44340 100644
--- a/builtins/getopt.c
+++ b/builtins/getopt.c
@@ -232,6 +232,19 @@ sh_getopt_restore_state (argv)
nextchar = argv[sh_curopt] + sh_charindex;
}
+#if 0
+void
+sh_getopt_debug_restore_state (argv)
+ char **argv;
+{
+ if (nextchar && nextchar != argv[sh_curopt] + sh_charindex)
+ {
+ itrace("sh_getopt_debug_restore_state: resetting nextchar");
+ nextchar = argv[sh_curopt] + sh_charindex;
+ }
+}
+#endif
+
#ifdef TEST
/* Compile with -DTEST to make an executable for use in testing
diff --git a/builtins/getopts.def b/builtins/getopts.def
index 533775a..941b666 100644
--- a/builtins/getopts.def
+++ b/builtins/getopts.def
@@ -181,6 +181,8 @@ dogetopts (argc, argv)
{
for (i = 0; i < 10 && dollar_vars[i]; i++)
;
+
+ sh_getopt_restore_state (dollar_vars);
ret = sh_getopt (i, dollar_vars, optstr);
}
else
@@ -198,6 +200,7 @@ dogetopts (argc, argv)
for (words = rest_of_args; words; words = words->next, i++)
v[i] = words->word->word;
v[i] = (char *)NULL;
+ sh_getopt_restore_state (v);
ret = sh_getopt (i, v, optstr);
free (v);
}
diff --git a/builtins/mkbuiltins.c b/builtins/mkbuiltins.c
index 8cd2703..2151eb4 100644
--- a/builtins/mkbuiltins.c
+++ b/builtins/mkbuiltins.c
@@ -130,6 +130,10 @@ char *assignment_builtins[] =
static int is_special_builtin ();
static int is_assignment_builtin ();
+#if !defined (HAVE_RENAME)
+static int rename ();
+#endif
+
void extract_info ();
void file_error ();
@@ -265,8 +269,7 @@ main (argc, argv)
{
write_longdocs (structfile, saved_builtins);
fclose (structfile);
- link (temp_struct_filename, struct_filename);
- unlink (temp_struct_filename);
+ rename (temp_struct_filename, struct_filename);
}
if (externfile)
@@ -457,6 +460,10 @@ extract_info (filename, structfile, externfile)
if ((nr = read (fd, buffer, file_size)) < 0)
file_error (filename);
+ /* This is needed on WIN32, and does not hurt on Unix. */
+ if (nr < file_size)
+ file_size = nr;
+
close (fd);
if (nr == 0)
@@ -1395,3 +1402,16 @@ is_assignment_builtin (name)
{
return (_find_in_table (name, assignment_builtins));
}
+
+#if !defined (HAVE_RENAME)
+static int
+rename (from, to)
+ char *from, *to;
+{
+ unlink (to);
+ if (link (from, to) < 0)
+ return (-1);
+ unlink (from);
+ return (0);
+}
+#endif /* !HAVE_RENAME */
diff --git a/builtins/printf.def b/builtins/printf.def
index 9d1493b..b573ece 100644
--- a/builtins/printf.def
+++ b/builtins/printf.def
@@ -99,7 +99,7 @@ int
printf_builtin (list)
WORD_LIST *list;
{
- int ch, end, fieldwidth, precision, foundmod;
+ int ch, end, fieldwidth, precision, foundmod, fmtlen;
char convch, nextch, *format, *fmt, *start;
retval = EXECUTION_SUCCESS;
@@ -125,12 +125,12 @@ printf_builtin (list)
if (list->word->word == 0 || list->word->word[0] == '\0')
return (EXECUTION_SUCCESS);
- format = ansicstr (list->word->word, strlen (list->word->word), (int *)NULL, (int *)NULL);
+ format = ansicstr (list->word->word, strlen (list->word->word), (int *)NULL, &fmtlen);
garglist = list->next;
/* If the format string is empty after preprocessing, return immediately. */
- if (format == 0 || *format == 0)
+ if ((format == 0 || *format == 0) && fmtlen == 0)
return (EXECUTION_SUCCESS);
/* Basic algorithm is to scan the format string for conversion
@@ -139,11 +139,12 @@ printf_builtin (list)
format strings are reused as necessary to use up the provided
arguments, arguments of zero/null string are provided to use
up the format string. */
+#define FMTIND (fmt - format)
do
{
/* find next format specification */
- for (fmt = format; *fmt; fmt++)
+ for (fmt = format; FMTIND < fmtlen; fmt++)
{
precision = fieldwidth = foundmod = 0;
@@ -179,11 +180,6 @@ printf_builtin (list)
/* skip to conversion char */
for (; *fmt && strchr(SKIP2, *fmt); ++fmt)
;
- if (*fmt == 0)
- {
- builtin_error ("`%s': missing format character", start);
- PRETURN (EXECUTION_FAILURE);
- }
/* skip possible format modifiers */
if (*fmt == 'l' || *fmt == 'L' || *fmt == 'h')
@@ -192,6 +188,12 @@ printf_builtin (list)
foundmod = 1;
}
+ if (*fmt == 0)
+ {
+ builtin_error ("`%s': missing format character", start);
+ PRETURN (EXECUTION_FAILURE);
+ }
+
convch = *fmt;
nextch = fmt[1];
fmt[1] = '\0';
diff --git a/builtins/pushd.def b/builtins/pushd.def
index 7226ab2..c80271f 100644
--- a/builtins/pushd.def
+++ b/builtins/pushd.def
@@ -117,6 +117,10 @@ $END
#include "common.h"
#include "builtext.h"
+#ifdef LOADABLE_BUILTIN
+# include "builtins.h"
+#endif
+
#if !defined (errno)
extern int errno;
#endif /* !errno */
@@ -642,4 +646,98 @@ get_directory_stack ()
free (d);
return ret; /* was (REVERSE_LIST (ret, (WORD_LIST *)); */
}
+
+#ifdef LOADABLE_BUILTIN
+static char *dirs_doc[] = {
+ "Display the list of currently remembered directories. Directories",
+ "find their way onto the list with the `pushd' command; you can get",
+ "back up through the list with the `popd' command.",
+ "",
+ "The -l flag specifies that `dirs' should not print shorthand versions",
+ "of directories which are relative to your home directory. This means",
+ "that `~/bin' might be displayed as `/homes/bfox/bin'. The -v flag",
+ "causes `dirs' to print the directory stack with one entry per line,",
+ "prepending the directory name with its position in the stack. The -p",
+ "flag does the same thing, but the stack position is not prepended.",
+ "The -c flag clears the directory stack by deleting all of the elements.",
+ "",
+ "+N displays the Nth entry counting from the left of the list shown by",
+ " dirs when invoked without options, starting with zero.",
+ "",
+ "-N displays the Nth entry counting from the right of the list shown by",
+ " dirs when invoked without options, starting with zero.",
+ (char *)NULL
+};
+
+static char *pushd_doc[] = {
+ "Adds a directory to the top of the directory stack, or rotates",
+ "the stack, making the new top of the stack the current working",
+ "directory. With no arguments, exchanges the top two directories.",
+ "",
+ "+N Rotates the stack so that the Nth directory (counting",
+ " from the left of the list shown by `dirs', starting with",
+ " zero) is at the top.",
+ "",
+ "-N Rotates the stack so that the Nth directory (counting",
+ " from the right of the list shown by `dirs', starting with",
+ " zero) is at the top.",
+ "",
+ "-n suppress the normal change of directory when adding directories",
+ " to the stack, so only the stack is manipulated.",
+ "",
+ "dir adds DIR to the directory stack at the top, making it the",
+ " new current working directory.",
+ "",
+ "You can see the directory stack with the `dirs' command.",
+ (char *)NULL
+};
+
+static char *popd_doc[] = {
+ "Removes entries from the directory stack. With no arguments,",
+ "removes the top directory from the stack, and cd's to the new",
+ "top directory.",
+ "",
+ "+N removes the Nth entry counting from the left of the list",
+ " shown by `dirs', starting with zero. For example: `popd +0'",
+ " removes the first directory, `popd +1' the second.",
+ "",
+ "-N removes the Nth entry counting from the right of the list",
+ " shown by `dirs', starting with zero. For example: `popd -0'",
+ " removes the last directory, `popd -1' the next to last.",
+ "",
+ "-n suppress the normal change of directory when removing directories",
+ " from the stack, so only the stack is manipulated.",
+ "",
+ "You can see the directory stack with the `dirs' command.",
+ (char *)NULL
+};
+
+struct builtin pushd_struct = {
+ "pushd",
+ pushd_builtin,
+ BUILTIN_ENABLED,
+ pushd_doc,
+ "pushd [+N | -N] [-n] [dir]",
+ 0
+};
+
+struct builtin popd_struct = {
+ "popd",
+ popd_builtin,
+ BUILTIN_ENABLED,
+ popd_doc,
+ "popd [+N | -N] [-n]",
+ 0
+};
+
+struct builtin dirs_struct = {
+ "dirs",
+ dirs_builtin,
+ BUILTIN_ENABLED,
+ dirs_doc,
+ "dirs [-clpv] [+N] [-N]",
+ 0
+};
+#endif /* LOADABLE_BUILTIN */
+
#endif /* PUSHD_AND_POPD */
diff --git a/builtins/read.def b/builtins/read.def
index 6d161f6..61288af 100644
--- a/builtins/read.def
+++ b/builtins/read.def
@@ -189,6 +189,7 @@ read_builtin (list)
c = rlbuf[rlind++];
}
else
+ {
#endif
while (((retval = read (0, &c, 1)) < 0) && errno == EINTR)
@@ -199,6 +200,10 @@ read_builtin (list)
break;
}
+#if defined (READLINE)
+ }
+#endif
+
if (i + 2 >= size)
input_string = xrealloc (input_string, size += 128);
diff --git a/builtins/reserved.def b/builtins/reserved.def
index da59050..527fc15 100644
--- a/builtins/reserved.def
+++ b/builtins/reserved.def
@@ -89,7 +89,7 @@ $END
$BUILTIN { ... }
$DOCNAME grouping_braces
-$SHORT_DOC { COMMANDS }
+$SHORT_DOC { COMMANDS ; }
Run a set of commands in a group. This is one way to redirect an
entire set of commands.
$END
diff --git a/builtins/set.def b/builtins/set.def
index b5ac83b..423a067 100644
--- a/builtins/set.def
+++ b/builtins/set.def
@@ -92,7 +92,7 @@ $SHORT_DOC set [--abefhkmnptuvxBCHP] [-o option] [arg ...]
noclobber same as -C
noexec same as -n
noglob same as -f
- notify save as -b
+ notify same as -b
nounset same as -u
onecmd same as -t
physical same as -P
diff --git a/builtins/shopt.def b/builtins/shopt.def
index 762bb42..1ee5b54 100644
--- a/builtins/shopt.def
+++ b/builtins/shopt.def
@@ -79,10 +79,19 @@ extern int hist_verify, history_reediting, perform_hostname_completion;
extern void enable_hostname_completion ();
#endif
+#if defined (RESTRICTED_SHELL)
+extern int restricted_shell;
+extern char *shell_name;
+#endif
+
extern void set_shellopts ();
static int set_interactive_comments ();
+#if defined (RESTRICTED_SHELL)
+static int set_restricted_shell ();
+#endif
+
static struct {
char *name;
int *value;
@@ -120,6 +129,9 @@ static struct {
{ "nocaseglob", &glob_ignore_case, (Function *)NULL },
{ "nullglob", &allow_null_glob_expansion, (Function *)NULL },
{ "promptvars", &promptvars, (Function *)NULL },
+#if defined (RESTRICTED_SHELL)
+ { "restricted_shell", &restricted_shell, set_restricted_shell },
+#endif
{ "shift_verbose", &print_shift_error, (Function *)NULL },
{ "sourcepath", &source_uses_path, (Function *)NULL },
{ (char *)0, (int *)0, (Function *)NULL }
@@ -262,7 +274,7 @@ toggle_shopts (mode, list, quiet)
return (rval);
}
-static int
+static void
print_shopt (name, val, flags)
char *name;
int val, flags;
@@ -400,3 +412,20 @@ set_interactive_comments (mode)
set_shellopts ();
return (0);
}
+
+#if defined (RESTRICTED_SHELL)
+/* Don't allow the value of restricted_shell to be modified. */
+
+static int
+set_restricted_shell (mode)
+ int mode;
+{
+ static int save_restricted = -1;
+
+ if (save_restricted == -1)
+ save_restricted = shell_is_restricted (shell_name);
+
+ restricted_shell = save_restricted;
+ return (0);
+}
+#endif /* RESTRICTED_SHELL */
diff --git a/builtins/test.def b/builtins/test.def
index eded0fa..abae8b4 100644
--- a/builtins/test.def
+++ b/builtins/test.def
@@ -129,7 +129,10 @@ test_builtin (list)
if (list == 0)
{
if (this_command_name[0] == '[' && !this_command_name[1])
- builtin_error ("missing `]'");
+ {
+ builtin_error ("missing `]'");
+ return (EX_BADUSAGE);
+ }
return (EXECUTION_FAILURE);
}
diff --git a/builtins/type.def b/builtins/type.def
index 93c8ff8..c9338ba 100644
--- a/builtins/type.def
+++ b/builtins/type.def
@@ -62,6 +62,7 @@ $END
#endif /* ALIAS */
#include "common.h"
+#include "bashgetopt.h"
extern int find_reserved_word ();
@@ -69,14 +70,14 @@ extern int find_reserved_word ();
it as a simple command. i.e., which file would this shell use to
execve, or if it is a builtin command, or an alias. Possible flag
arguments:
- -type Returns the "type" of the object, one of
+ -t Returns the "type" of the object, one of
`alias', `keyword', `function', `builtin',
or `file'.
- -path Returns the pathname of the file if -type is
+ -p Returns the pathname of the file if -type is
a file.
- -all Returns all occurrences of words, whether they
+ -a Returns all occurrences of words, whether they
be a filename in the path, alias, function,
or builtin.
Order of evaluation:
@@ -86,12 +87,14 @@ extern int find_reserved_word ();
builtin
file
*/
+
int
type_builtin (list)
WORD_LIST *list;
{
int path_only, type_only, all, verbose;
- int successful_finds;
+ int successful_finds, opt;
+ WORD_LIST *prev, *this;
if (list == 0)
return (EXECUTION_SUCCESS);
@@ -99,32 +102,69 @@ type_builtin (list)
path_only = type_only = all = 0;
successful_finds = 0;
- while (list && *(list->word->word) == '-')
+ /* Handle the obsolescent `-type', `-path', and `-all' by prescanning
+ the arguments and removing those options from the list before calling
+ internal_getopt. Recognize `--type', `--path', and `--all' also.
+ THIS SHOULD REALLY GO AWAY. */
+ for (this = list; this && this->word->word[0] == '-'; )
{
- char *flag = &(list->word->word[1]);
+ char *flag = &(this->word->word[1]);
- if (flag[0] == 't' && (!flag[1] || strcmp (flag + 1, "ype") == 0))
+ if (STREQ (flag, "type") || STREQ (flag, "-type"))
{
type_only = 1;
path_only = 0;
}
- else if (flag[0] == 'p' && (!flag[1] || strcmp (flag + 1, "ath") == 0))
+ else if (STREQ (flag, "path") || STREQ (flag, "-path"))
{
path_only = 1;
type_only = 0;
}
- else if (flag[0] == 'a' && (!flag[1] || strcmp (flag + 1, "ll") == 0))
+ else if (STREQ (flag, "all") || STREQ (flag, "-all"))
+ all = 1;
+ else
{
- all = 1;
+ prev = this;
+ this = this->next;
+ continue;
}
+
+ /* We found a long option; remove it from the argument list. Don't
+ free it if it's the head of the argument list, though -- the
+ argument list will be freed by the caller. */
+ if (this == list)
+ this = list = list->next;
else
{
- bad_option (flag);
+ prev->next = this->next;
+ this->next = (WORD_LIST *)NULL;
+ dispose_words (this);
+ this = prev->next;
+ }
+ }
+
+ reset_internal_getopt ();
+ while ((opt = internal_getopt (list, "apt")) != -1)
+ {
+ switch (opt)
+ {
+ case 't':
+ type_only = 1;
+ path_only = 0;
+ break;
+ case 'p':
+ path_only = 1;
+ type_only = 0;
+ break;
+ case 'a':
+ all = 1;
+ break;
+ default:
builtin_usage ();
return (EX_USAGE);
}
- list = list->next;
}
+ list = loptend;
if (type_only)
verbose = 1;
@@ -150,10 +190,7 @@ type_builtin (list)
fflush (stdout);
- if (successful_finds != 0)
- return (EXECUTION_SUCCESS);
- else
- return (EXECUTION_FAILURE);
+ return ((successful_finds != 0) ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
}
/*
@@ -202,7 +239,7 @@ describe_command (command, verbose, all)
found = 1;
- if (!all)
+ if (all == 0)
return (1);
}
#endif /* ALIAS */
@@ -220,7 +257,7 @@ describe_command (command, verbose, all)
found = 1;
- if (!all)
+ if (all == 0)
return (1);
}
@@ -251,7 +288,7 @@ describe_command (command, verbose, all)
found = 1;
- if (!all)
+ if (all == 0)
return (1);
}
@@ -267,7 +304,7 @@ describe_command (command, verbose, all)
found = 1;
- if (!all)
+ if (all == 0)
return (1);
}
@@ -293,9 +330,9 @@ describe_command (command, verbose, all)
}
}
- /* If the user isn't doing "-all", then we might care about
+ /* If the user isn't doing "-a", then we might care about
whether the file is present in our hash table. */
- if (!all)
+ if (all == 0)
{
if ((full_path = find_hashed_filename (command)) != (char *)NULL)
{
@@ -314,7 +351,7 @@ describe_command (command, verbose, all)
/* Now search through $PATH. */
while (1)
{
- if (!all)
+ if (all == 0)
full_path = find_user_command (command);
else
full_path =
@@ -337,7 +374,7 @@ describe_command (command, verbose, all)
free (full_path);
full_path = (char *)NULL;
- if (!all)
+ if (all == 0)
break;
}
diff --git a/builtins/ulimit.def b/builtins/ulimit.def
index bbeb7c9..f3d0c8e 100644
--- a/builtins/ulimit.def
+++ b/builtins/ulimit.def
@@ -154,24 +154,20 @@ extern int errno;
# define RLIM_INFINITY 0x7fffffff
#endif
-#if !defined (RLIM_INVALID)
-# define RLIM_INVALID (RLIMTYPE)-1
-#endif
-
#define LIMIT_HARD 0x01
#define LIMIT_SOFT 0x02
-static int ulimit_internal ();
-static void printone ();
-static void print_all_limits ();
+static int ulimit_internal __P((int, char *, int, int));
+static void printone __P((int, RLIMTYPE, int));
+static void print_all_limits __P((int));
-static int get_limit ();
-static int set_limit ();
+static int get_limit __P((int, int, RLIMTYPE *));
+static int set_limit __P((int, RLIMTYPE, int));
-static RLIMTYPE filesize ();
-static RLIMTYPE pipesize ();
-static RLIMTYPE getmaxuprc ();
-static RLIMTYPE getmaxvm ();
+static int filesize __P((RLIMTYPE *));
+static int pipesize __P((RLIMTYPE *));
+static int getmaxuprc __P((int, RLIMTYPE *));
+static int getmaxvm __P((int, RLIMTYPE *));
typedef struct {
int option; /* The ulimit option for this limit. */
@@ -351,7 +347,6 @@ ulimit_internal (cmd, cmdarg, mode, multiple)
long block_factor;
RLIMTYPE current_limit, real_limit, limit;
- limit = RLIM_INVALID;
setting = cmdarg != 0;
limind = _findlim (cmd);
if (mode == 0)
@@ -412,26 +407,30 @@ get_limit (ind, mode, limptr)
switch (limits[ind].parameter)
{
case RLIMIT_FILESIZE:
- value = filesize ();
+ if (filesize (&value) < 0)
+ return -1;
break;
case RLIMIT_PIPESIZE:
- value = pipesize ();
+ if (pipesize (&value) < 0)
+ return -1;
break;
case RLIMIT_OPENFILES:
value = (RLIMTYPE)getdtablesize ();
break;
case RLIMIT_VIRTMEM:
- value = getmaxvm (mode);
+ if (getmaxvm (mode, &value) < 0)
+ return -1;
break;
case RLIMIT_MAXUPROC:
- value = getmaxuprc (mode);
+ if (getmaxuprc (mode, &value) < 0)
+ return -1;
break;
default:
errno = EINVAL;
return -1;
}
*limptr = value;
- return ((value == RLIM_INVALID) ? -1 : 0);
+ return (0);
}
else
{
@@ -439,6 +438,11 @@ get_limit (ind, mode, limptr)
if (getrlimit (limits[ind].parameter, &limit) < 0)
return -1;
value = (mode & LIMIT_SOFT) ? limit.rlim_cur : limit.rlim_max;
+# if defined (HPUX9)
+ if (limits[ind].parameter == RLIMIT_FILESIZE)
+ *limptr = value * 512; /* Ugh. */
+ else
+# endif /* HPUX9 */
*limptr = value;
return 0;
#else
@@ -486,6 +490,10 @@ set_limit (ind, newlim, mode)
#if defined (HAVE_RESOURCE)
if (getrlimit (limits[ind].parameter, &limit) < 0)
return -1;
+# if defined (HPUX9)
+ if (limits[ind].parameter == RLIMIT_FILESIZE)
+ newlim /= 512; /* Ugh. */
+# endif /* HPUX9 */
val = (current_user.euid != 0 && newlim == RLIM_INFINITY &&
(limit.rlim_cur <= limit.rlim_max))
? limit.rlim_max : newlim;
@@ -502,72 +510,91 @@ set_limit (ind, newlim, mode)
}
}
-static RLIMTYPE
-getmaxvm (mode)
+static int
+getmaxvm (mode, valuep)
int mode;
+ RLIMTYPE *valuep;
{
#if defined (HAVE_RESOURCE)
struct rlimit rl;
RLIMTYPE maxdata, maxstack;
if (getrlimit (RLIMIT_DATA, &rl) < 0)
- return (RLIM_INVALID);
+ return -1;
else
maxdata = (mode & LIMIT_SOFT) ? rl.rlim_cur : rl.rlim_max;
if (getrlimit (RLIMIT_STACK, &rl) < 0)
- return (RLIM_INVALID);
+ return -1;
else
maxstack = (mode & LIMIT_SOFT) ? rl.rlim_cur : rl.rlim_max;
/* Protect against overflow. */
- return ((maxdata / 1024L) + (maxstack / 1024L));
+ *valuep = (maxdata / 1024L) + (maxstack / 1024L);
+ return 0;
#else
errno = EINVAL;
- return RLIM_INVALID;
+ return -1;
#endif /* HAVE_RESOURCE */
}
-static RLIMTYPE
-filesize()
+static int
+filesize(valuep)
+ RLIMTYPE *valuep;
{
#if !defined (HAVE_RESOURCE)
- return ((RLIMTYPE)ulimit (1, 0L));
+ long result;
+ if ((result = ulimit (1, 0L)) < 0)
+ return -1;
+ else
+ *valuep = (RLIMTYPE) result;
+ return 0;
#else
errno = EINVAL;
- return RLIM_INVALID;
+ return -1;
#endif
}
-static RLIMTYPE
-pipesize ()
+static int
+pipesize (valuep)
+ RLIMTYPE *valuep;
{
#if defined (PIPE_BUF)
/* This is defined on Posix systems. */
- return ((RLIMTYPE) PIPE_BUF);
+ *valuep = (RLIMTYPE) PIPE_BUF;
+ return 0;
#else
# if defined (PIPESIZE)
/* This is defined by running a program from the Makefile. */
- return ((RLIMTYPE) PIPESIZE);
+ *valuep = (RLIMTYPE) PIPESIZE;
+ return 0;
# else
errno = EINVAL;
- return RLIM_INVALID;
+ return -1;
# endif /* PIPESIZE */
#endif /* PIPE_BUF */
}
-static RLIMTYPE
-getmaxuprc (mode)
+static int
+getmaxuprc (mode, valuep)
int mode;
+ RLIMTYPE *valuep;
{
# if defined (HAVE_SYSCONF) && defined (_SC_CHILD_MAX)
- return ((RLIMTYPE)sysconf (_SC_CHILD_MAX));
+ long maxchild;
+ maxchild = sysconf (_SC_CHILD_MAX);
+ if (maxchild < 0)
+ return -1;
+ else
+ *valuep = (RLIMTYPE) maxchild;
+ return 0;
# else /* !HAVE_SYSCONF || !_SC_CHILD_MAX */
# if defined (MAXUPRC)
- return ((RLIMTYPE)MAXUPRC);
+ *valuep = (RLIMTYPE) MAXUPRC;
+ return 0;
# else /* MAXUPRC */
errno = EINVAL;
- return RLIM_INVALID;
+ return -1;
# endif /* !MAXUPRC */
# endif /* !HAVE_SYSCONF || !_SC_CHILD_MAX */
}
@@ -585,8 +612,12 @@ print_all_limits (mode)
for (i = 0; limits[i].option > 0; i++)
{
if (get_limit (i, mode, &value) < 0)
- value = RLIM_INVALID;
- printone (i, value, 1);
+ {
+ fprintf (stderr, DESCFMT, limits[i].description);
+ builtin_error ("cannot get limit: %s", strerror (errno));
+ }
+ else
+ printone (i, value, 1);
}
}
@@ -600,8 +631,6 @@ printone (limind, curlim, pdesc)
printf (DESCFMT, limits[limind].description);
if (curlim == RLIM_INFINITY)
puts ("unlimited");
- else if (curlim == RLIM_INVALID)
- builtin_error ("cannot get limit: %s\n", strerror (errno));
else
print_rlimtype ((curlim / limits[limind].block_factor), 1);
}
diff --git a/builtins/umask.def b/builtins/umask.def
index f734113..5b98c0c 100644
--- a/builtins/umask.def
+++ b/builtins/umask.def
@@ -174,29 +174,15 @@ print_symbolic_umask (um)
printf ("u=%s,g=%s,o=%s\n", ubits, gbits, obits);
}
-/* Set the umask from a symbolic mode string similar to that accepted
- by chmod. If the -S argument is given, then print the umask in a
- symbolic form. */
-static int
-symbolic_umask (list)
- WORD_LIST *list;
+int
+parse_symbolic_mode (mode, initial_bits)
+ char *mode;
+ int initial_bits;
{
- int um, umc, c;
- int who, op, perm, mask;
+ int who, op, perm, mask, bits, c;
char *s;
- /* Get the initial umask. Don't change it yet. */
- um = umask (022);
- umask (um);
-
- /* All work below is done with the complement of the umask -- it's
- more intuitive and easier to deal with. It is complemented
- again before being returned. */
- umc = ~um;
-
- s = list->word->word;
-
- for (;;)
+ for (s = mode, bits = initial_bits;;)
{
who = op = perm = mask = 0;
@@ -205,20 +191,20 @@ symbolic_umask (list)
{
switch (c = *s++)
{
- case 'u':
- who |= S_IRWXU;
- continue;
- case 'g':
- who |= S_IRWXG;
- continue;
- case 'o':
- who |= S_IRWXO;
- continue;
- case 'a':
- who |= S_IRWXU | S_IRWXG | S_IRWXO;
- continue;
- default:
- break;
+ case 'u':
+ who |= S_IRWXU;
+ continue;
+ case 'g':
+ who |= S_IRWXG;
+ continue;
+ case 'o':
+ who |= S_IRWXO;
+ continue;
+ case 'a':
+ who |= S_IRWXU | S_IRWXG | S_IRWXO;
+ continue;
+ default:
+ break;
}
}
@@ -226,13 +212,13 @@ symbolic_umask (list)
op = *s++;
switch (op)
{
- case '+':
- case '-':
- case '=':
- break;
- default:
- builtin_error ("bad symbolic mode operator: %c", op);
- return (-1);
+ case '+':
+ case '-':
+ case '=':
+ break;
+ default:
+ builtin_error ("bad symbolic mode operator: %c", op);
+ return (-1);
}
/* Parse out the `perm' section of the symbolic mode clause. */
@@ -242,17 +228,15 @@ symbolic_umask (list)
switch (c)
{
- case 'r':
- perm |= S_IRUGO;
- break;
-
- case 'w':
- perm |= S_IWUGO;
- break;
-
- case 'x':
- perm |= S_IXUGO;
- break;
+ case 'r':
+ perm |= S_IRUGO;
+ break;
+ case 'w':
+ perm |= S_IWUGO;
+ break;
+ case 'x':
+ perm |= S_IXUGO;
+ break;
}
}
@@ -265,32 +249,22 @@ symbolic_umask (list)
switch (op)
{
- case '+':
- umc |= perm;
- break;
-
- case '-':
- umc &= ~perm;
- break;
-
- case '=':
- umc &= ~who;
- umc |= perm;
- break;
-
-#if 0
- /* No other values are possible. */
- default:
- builtin_error ("bad symbolic mode operator: %c", op);
- return (-1);
-#endif
- }
-
- if (!*s)
- {
- um = ~umc & 0777;
+ case '+':
+ bits |= perm;
+ break;
+ case '-':
+ bits &= ~perm;
break;
+ case '=':
+ bits &= ~who;
+ bits |= perm;
+ break;
+
+ /* No other values are possible. */
}
+
+ if (*s == '\0')
+ break;
else
s++; /* skip past ',' */
}
@@ -300,5 +274,28 @@ symbolic_umask (list)
return (-1);
}
}
+
+ return (bits);
+}
+
+/* Set the umask from a symbolic mode string similar to that accepted
+ by chmod. If the -S argument is given, then print the umask in a
+ symbolic form. */
+static int
+symbolic_umask (list)
+ WORD_LIST *list;
+{
+ int um, bits;
+
+ /* Get the initial umask. Don't change it yet. */
+ um = umask (022);
+ umask (um);
+
+ /* All work is done with the complement of the umask -- it's
+ more intuitive and easier to deal with. It is complemented
+ again before being returned. */
+ bits = parse_symbolic_mode (list->word->word, ~um);
+
+ um = ~bits & 0777;
return (um);
}