diff options
Diffstat (limited to 'builtins')
-rw-r--r-- | builtins/Makefile.in | 17 | ||||
-rw-r--r-- | builtins/cd.def | 24 | ||||
-rw-r--r-- | builtins/enable.def | 39 | ||||
-rw-r--r-- | builtins/evalstring.c | 21 | ||||
-rw-r--r-- | builtins/fc.def | 59 | ||||
-rw-r--r-- | builtins/getopt.c | 13 | ||||
-rw-r--r-- | builtins/getopts.def | 3 | ||||
-rw-r--r-- | builtins/mkbuiltins.c | 24 | ||||
-rw-r--r-- | builtins/printf.def | 20 | ||||
-rw-r--r-- | builtins/pushd.def | 98 | ||||
-rw-r--r-- | builtins/read.def | 5 | ||||
-rw-r--r-- | builtins/reserved.def | 2 | ||||
-rw-r--r-- | builtins/set.def | 2 | ||||
-rw-r--r-- | builtins/shopt.def | 31 | ||||
-rw-r--r-- | builtins/test.def | 5 | ||||
-rw-r--r-- | builtins/type.def | 85 | ||||
-rw-r--r-- | builtins/ulimit.def | 115 | ||||
-rw-r--r-- | builtins/umask.def | 149 |
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); } |