From cce855bc5b117cb7ae70064131120687bc69fac0 Mon Sep 17 00:00:00 2001 From: Jari Aalto Date: Fri, 17 Apr 1998 19:52:44 +0000 Subject: Imported from ../bash-2.02.tar.gz. --- builtins/Makefile.in | 62 +++-- builtins/alias.def | 14 +- builtins/bashgetopt.c | 2 + builtins/bind.def | 62 +++-- builtins/break.def | 5 +- builtins/builtin.def | 3 + builtins/cd.def | 37 ++- builtins/command.def | 18 +- builtins/common.c | 28 +- builtins/common.h | 98 +++---- builtins/declare.def | 15 ++ builtins/enable.def | 3 + builtins/eval.def | 5 +- builtins/evalfile.c | 20 +- builtins/evalstring.c | 123 ++++++++- builtins/exec.def | 1 + builtins/exit.def | 2 +- builtins/fc.def | 8 +- builtins/getopt.c | 3 + builtins/getopts.def | 3 + builtins/hash.def | 26 +- builtins/help.def | 6 +- builtins/history.def | 4 +- builtins/jobs.def | 31 ++- builtins/kill.def | 22 +- builtins/let.def | 3 + builtins/mkbuiltins.c | 38 ++- builtins/printf.def | 693 ++++++++++++++++++++++++++++++++++++++++++++++++++ builtins/psize.c | 5 + builtins/psize.sh | 22 +- builtins/pushd.def | 36 ++- builtins/read.def | 5 + builtins/return.def | 3 + builtins/set.def | 96 +++---- builtins/setattr.def | 6 + builtins/shift.def | 3 + builtins/shopt.def | 82 ++++-- builtins/source.def | 6 +- builtins/suspend.def | 3 + builtins/test.def | 14 +- builtins/times.def | 5 +- builtins/trap.def | 3 + builtins/type.def | 18 +- builtins/ulimit.def | 13 +- builtins/umask.def | 23 +- builtins/wait.def | 6 + 46 files changed, 1431 insertions(+), 253 deletions(-) create mode 100644 builtins/printf.def (limited to 'builtins') diff --git a/builtins/Makefile.in b/builtins/Makefile.in index 73e719d..2cf5d68 100644 --- a/builtins/Makefile.in +++ b/builtins/Makefile.in @@ -3,6 +3,7 @@ SHELL = /bin/sh RANLIB = @RANLIB@ CC = @CC@ +CC_FOR_BUILD = @CC_FOR_BUILD@ AR = @AR@ RM = rm -f CP = cp @@ -11,13 +12,16 @@ srcdir = @srcdir@ VPATH = .:@srcdir@ topdir = @top_srcdir@ includedir = @includedir@ +BUILD_DIR = @BUILD_DIR@ -PROFILE_FLAGS = +PROFILE_FLAGS = @PROFILE_FLAGS@ CFLAGS = @CFLAGS@ LOCAL_CFLAGS = @LOCAL_CFLAGS@ CPPFLAGS = @CPPFLAGS@ DEFS = @DEFS@ LOCAL_DEFS = @LOCAL_DEFS@ +LDFLAGS = @LDFLAGS@ $(LOCAL_LDFLAGS) $(CFLAGS) +LOCAL_LDFLAGS = @LOCAL_LDFLAGS@ LIBS = @LIBS@ INCLUDES = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(srcdir) @@ -62,7 +66,8 @@ DEFSRC = $(srcdir)/alias.def $(srcdir)/bind.def $(srcdir)/break.def \ $(srcdir)/source.def $(srcdir)/suspend.def $(srcdir)/test.def \ $(srcdir)/times.def $(srcdir)/trap.def $(srcdir)/type.def \ $(srcdir)/ulimit.def $(srcdir)/umask.def $(srcdir)/wait.def \ - $(srcdir)/reserved.def $(srcdir)/pushd.def $(srcdir)/shopt.def + $(srcdir)/reserved.def $(srcdir)/pushd.def $(srcdir)/shopt.def \ + $(srcdir)/printf.def STATIC_SOURCE = common.c evalstring.c evalfile.c getopt.c bashgetopt.c \ getopt.h @@ -74,40 +79,57 @@ OFILES = builtins.o \ exit.o fc.o fg_bg.o hash.o help.o history.o jobs.o kill.o let.o \ pushd.o read.o return.o set.o setattr.o shift.o source.o \ suspend.o test.o times.o trap.o type.o ulimit.o umask.o \ - wait.o getopts.o shopt.o getopt.o bashgetopt.o + wait.o getopts.o shopt.o printf.o getopt.o bashgetopt.o CREATED_FILES = builtext.h builtins.c psize.aux pipesize.h all: $(MKBUILTINS) libbuiltins.a -libbuiltins.a: $(MKBUILTINS) $(OFILES) +libbuiltins.a: $(MKBUILTINS) $(OFILES) builtins.o $(RM) $@ $(AR) cr $@ $(OFILES) -$(RANLIB) $@ builtext.h builtins.c: $(MKBUILTINS) $(DEFSRC) - $(RM) builtext.h builtins.c + @-if test -f builtins.c; then mv -f builtins.c old-builtins.c; fi + @-if test -f builtext.h; then mv -f builtext.h old-builtext.h; fi ./$(MKBUILTINS) -externfile builtext.h -structfile builtins.c \ - -noproduction $(DIRECTDEFINE) $(DEFSRC) + -noproduction $(DIRECTDEFINE) $(DEFSRC) + @-if cmp -s old-builtext.h builtext.h; then \ + mv old-builtext.h builtext.h; \ + else \ + $(RM) old-builtext.h; \ + fi + @-if cmp -s old-builtins.c builtins.c; then \ + mv old-builtins.c builtins.c; \ + else \ + $(RM) old-builtins.c; \ + fi -mkbuiltins: $(srcdir)/mkbuiltins.c ../config.h - $(CC) $(CCFLAGS) -o $(MKBUILTINS) $(srcdir)/mkbuiltins.c $(LIBS) +mkbuiltins.o: ../config.h +mkbuiltins.o: mkbuiltins.c + $(RM) $@ + $(CC_FOR_BUILD) -c $(CCFLAGS) $< + +mkbuiltins: mkbuiltins.o + $(CC_FOR_BUILD) $(LDFLAGS) -o $(MKBUILTINS) mkbuiltins.o $(LIBS) # rules for deficient makes, like SunOS +mkbuiltins.o: mkbuiltins.c +builtins.o: builtins.c common.o: common.c bashgetopt.o: bashgetopt.c getopt.o: getopt.c -evalstring.o: evalstring.c -evalfile.o: evalfile.c +evalstring.o: evalstring.c +evalfile.o: evalfile.c -ulimit.o: ulimit.def ulimit.o: pipesize.h pipesize.h: psize.aux $(SHELL) $(srcdir)/psize.sh > pipesize.h psize.aux: psize.c - $(CC) $(CCFLAGS) -o $@ $(srcdir)/psize.c + $(CC_FOR_BUILD) $(CCFLAGS) -o $@ $(srcdir)/psize.c documentation: builtins.texi @@ -146,6 +168,7 @@ history.o: history.def jobs.o: jobs.def kill.o: kill.def let.o: let.def +printf.o: printf.def pushd.o: pushd.def read.o: read.def return.o: return.def @@ -159,6 +182,7 @@ test.o: test.def times.o: times.def trap.o: trap.def type.o: type.def +ulimit.o: ulimit.def umask.o: umask.def wait.o: wait.def getopts.o: getopts.def @@ -274,6 +298,7 @@ exec.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h exec.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/flags.h exec.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h exec.o: $(srcdir)/common.h $(topdir)/execute_cmd.h $(topdir)/maxpath.h +exec.o: $(topdir)/findcmd.h exit.o: $(topdir)/bashtypes.h exit.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h exit.o: $(topdir)/error.h $(topdir)/general.h @@ -302,7 +327,7 @@ getopts.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h getopts.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h getopts.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h hash.o: $(topdir)/builtins.h $(topdir)/command.h $(topdir)/quit.h -hash.o: $(topdir)/execute_cmd.h $(topdir)/hashlib.h +hash.o: $(topdir)/findcmd.h $(topdir)/hashlib.h hash.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h hash.o: $(topdir)/error.h $(topdir)/general.h hash.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h @@ -339,6 +364,12 @@ let.o: $(topdir)/error.h $(topdir)/general.h let.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h let.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h let.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h +printf.o: ../config.h $(topdir)/memalloc.h $(topdir)/bashjmp.h +printf.o: $(topdir)/command.h $(topdir)/error.h $(topdir)/general.h +printf.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h +printf.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/sig.h +printf.o: $(topdir)/pathnames.h $(topdir)/shell.h $(topdir)/unwind_prot.h +printf.o: $(topdir)/variables.h $(topdir)/stdc.h $(srcdir)/bashgetopt.h pushd.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h pushd.o: $(topdir)/error.h $(topdir)/general.h pushd.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h @@ -372,7 +403,7 @@ shift.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h shift.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h shift.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h source.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h -source.o: $(topdir)/error.h $(topdir)/general.h +source.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/findcmd.h source.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h source.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h source.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h @@ -386,6 +417,7 @@ test.o: $(topdir)/error.h $(topdir)/general.h test.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h test.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/maxpath.h test.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h +test.o: $(topdir)/test.h times.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h times.o: $(topdir)/error.h $(topdir)/general.h times.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h @@ -396,7 +428,7 @@ trap.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/externs.h trap.o: $(topdir)/quit.h $(srcdir)/common.h $(topdir)/maxpath.h trap.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h trap.o: $(topdir)/shell.h $(topdir)/unwind_prot.h $(topdir)/variables.h -trap.o: $(topdir)/execute_cmd.h +trap.o: $(topdir)/findcmd.h type.o: $(topdir)/command.h ../config.h $(topdir)/memalloc.h type.o: $(topdir)/error.h $(topdir)/general.h type.o: $(topdir)/quit.h $(srcdir)/common.h $(topdir)/maxpath.h diff --git a/builtins/alias.def b/builtins/alias.def index 044b44d..dec72f6 100644 --- a/builtins/alias.def +++ b/builtins/alias.def @@ -37,6 +37,9 @@ $END #if defined (ALIAS) #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif @@ -80,12 +83,12 @@ alias_builtin (list) if (list == 0 || pflag) { if (aliases == 0) - return (EXECUTION_FAILURE); + return (EXECUTION_SUCCESS); alias_list = all_aliases (); if (alias_list == 0) - return (EXECUTION_FAILURE); + return (EXECUTION_SUCCESS); for (offset = 0; alias_list[offset]; offset++) print_alias (alias_list[offset]); @@ -118,8 +121,7 @@ alias_builtin (list) print_alias (t); else { - if (interactive) - builtin_error ("`%s' not found", name); + builtin_error ("`%s' not found", name); any_failed++; } } @@ -179,9 +181,7 @@ unalias_builtin (list) remove_alias (alias->name); else { - if (interactive) - builtin_error ("`%s': not an alias", list->word->word); - + builtin_error ("`%s': not an alias", list->word->word); aflag++; } diff --git a/builtins/bashgetopt.c b/builtins/bashgetopt.c index 72ac900..65b8d08 100644 --- a/builtins/bashgetopt.c +++ b/builtins/bashgetopt.c @@ -161,6 +161,7 @@ reset_internal_getopt () sp = 1; } +#ifdef INCLUDE_UNUSED void report_bad_option () { @@ -171,3 +172,4 @@ report_bad_option () s[2] = '\0'; bad_option (s); } +#endif diff --git a/builtins/bind.def b/builtins/bind.def index 908803a..6b8ac56 100644 --- a/builtins/bind.def +++ b/builtins/bind.def @@ -26,7 +26,7 @@ $PRODUCES bind.c $BUILTIN bind $DEPENDS_ON READLINE $FUNCTION bind_builtin -$SHORT_DOC bind [-lpvsPVS] [-m keymap] [-f filename] [-q name] [-r keyseq] [keyseq:readline-function] +$SHORT_DOC bind [-lpvsPVS] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [keyseq:readline-function] Bind a key sequence to a Readline function, or to a macro. The syntax is equivalent to that found in ~/.inputrc, but must be passed as a single argument: bind '"\C-x\C-r": re-read-init-file'. @@ -42,6 +42,7 @@ Arguments we accept: -r keyseq Remove the binding for KEYSEQ. -f filename Read key bindings from FILENAME. -q function-name Query about which keys invoke the named function. + -u function-name Unbind all keys which are bound to the named function. -V List variable names and values -v List variable names and values in a form that can be reused as input. @@ -53,6 +54,9 @@ $END #if defined (READLINE) #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif @@ -71,22 +75,24 @@ extern int errno; #include "common.h" static int query_bindings (); +static int unbind_command (); extern int no_line_editing; #define BIND_RETURN(x) do { return_code = x; goto bind_exit; } while (0) -#define LFLAG 0x01 -#define PFLAG 0x02 -#define FFLAG 0x04 -#define VFLAG 0x08 -#define QFLAG 0x10 -#define MFLAG 0x20 -#define RFLAG 0x40 -#define PPFLAG 0x80 -#define VVFLAG 0x100 -#define SFLAG 0x200 -#define SSFLAG 0x400 +#define LFLAG 0x0001 +#define PFLAG 0x0002 +#define FFLAG 0x0004 +#define VFLAG 0x0008 +#define QFLAG 0x0010 +#define MFLAG 0x0020 +#define RFLAG 0x0040 +#define PPFLAG 0x0080 +#define VVFLAG 0x0100 +#define SFLAG 0x0200 +#define SSFLAG 0x0400 +#define UFLAG 0x0800 int bind_builtin (list) @@ -96,14 +102,14 @@ bind_builtin (list) FILE *old_rl_outstream; Keymap kmap, saved_keymap; int flags, opt; - char *initfile, *map_name, *fun_name, *remove_seq; + char *initfile, *map_name, *fun_name, *unbind_name, *remove_seq; if (no_line_editing) return (EXECUTION_FAILURE); kmap = saved_keymap = (Keymap) NULL; flags = 0; - initfile = map_name = fun_name = remove_seq = (char *)NULL; + initfile = map_name = fun_name = unbind_name = remove_seq = (char *)NULL; return_code = EXECUTION_SUCCESS; if (!bash_readline_initialized) @@ -116,7 +122,7 @@ bind_builtin (list) rl_outstream = stdout; reset_internal_getopt (); - while ((opt = internal_getopt (list, "lvpVPsSf:q:m:r:")) != EOF) + while ((opt = internal_getopt (list, "lvpVPsSf:q:u:m:r:")) != EOF) { switch (opt) { @@ -141,6 +147,10 @@ bind_builtin (list) flags |= QFLAG; fun_name = list_optarg; break; + case 'u': + flags |= UFLAG; + unbind_name = list_optarg; + break; case 'r': flags |= RFLAG; remove_seq = list_optarg; @@ -220,6 +230,9 @@ bind_builtin (list) if ((flags & QFLAG) && fun_name) return_code = query_bindings (fun_name); + if ((flags & UFLAG) && unbind_name) + return_code = unbind_command (unbind_name); + if ((flags & RFLAG) && remove_seq) { if (rl_set_key (remove_seq, (Function *)NULL, rl_get_keymap ()) != 0) @@ -253,7 +266,7 @@ query_bindings (name) int j; function = rl_named_function (name); - if (!function) + if (function == 0) { builtin_error ("unknown function name `%s'", name); return EXECUTION_FAILURE; @@ -275,4 +288,21 @@ query_bindings (name) free_array (keyseqs); return EXECUTION_SUCCESS; } + +static int +unbind_command (name) + char *name; +{ + Function *function; + + function = rl_named_function (name); + if (function == 0) + { + builtin_error ("unknown function name `%s'", name); + return EXECUTION_FAILURE; + } + + rl_unbind_function_in_map (function, rl_get_keymap ()); + return EXECUTION_SUCCESS; +} #endif /* READLINE */ diff --git a/builtins/break.def b/builtins/break.def index 5354ef6..e99d136 100644 --- a/builtins/break.def +++ b/builtins/break.def @@ -30,7 +30,10 @@ $END #include #if defined (HAVE_UNISTD_H) -#include +# ifdef _MINIX +# include +# endif +# include #endif #include "../shell.h" diff --git a/builtins/builtin.def b/builtins/builtin.def index 75d25a0..b18960c 100644 --- a/builtins/builtin.def +++ b/builtins/builtin.def @@ -31,6 +31,9 @@ $END #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif diff --git a/builtins/cd.def b/builtins/cd.def index 4bbad7e..ef8d805 100644 --- a/builtins/cd.def +++ b/builtins/cd.def @@ -23,13 +23,18 @@ $PRODUCES cd.c #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif #include "../bashtypes.h" #include "../posixdir.h" #include "../posixstat.h" +#ifndef _MINIX #include +#endif #include @@ -66,11 +71,11 @@ $BUILTIN cd $FUNCTION cd_builtin $SHORT_DOC cd [-PL] [dir] Change the current directory to DIR. The variable $HOME is the -default DIR. The variable $CDPATH defines the search path for +default DIR. The variable CDPATH defines the search path for the directory containing DIR. Alternative directory names in CDPATH are separated by a colon (:). A null directory name is the same as the current directory, i.e. `.'. If DIR begins with a slash (/), -then $CDPATH is not used. If the directory is not found, and the +then CDPATH is not used. If the directory is not found, and the shell option `cdable_vars' is set, then try the word as a variable name. If that variable has a value, then cd to the value of that variable. The -P option says to use the physical directory structure @@ -146,9 +151,10 @@ bindpwd (no_symlinks) needing a remake. */ if (old_anm == 0 && array_needs_making && exported_p (tvar)) { - pwdvar = xmalloc (strlen (dirname) + 5); /* 5 = "PWD" + '=' + '\0' */ + pwdvar = xmalloc (STRLEN (dirname) + 5); /* 5 = "PWD" + '=' + '\0' */ strcpy (pwdvar, "PWD="); - strcpy (pwdvar + 4, dirname); + if (dirname) + strcpy (pwdvar + 4, dirname); add_or_supercede_exported_var (pwdvar, 0); array_needs_making = 0; } @@ -226,6 +232,8 @@ cd_builtin (list) builtin_error ("%s: %s", dirname, strerror (errno)); return (EXECUTION_FAILURE); } + if (interactive) + printf ("%s\n", dirname); } else { @@ -237,6 +245,8 @@ cd_builtin (list) path_index = 0; while ((path = extract_colon_unit (cdpath, &path_index))) { + /* OPT is 1 if the path element is non-empty */ + opt = path[0] != '\0'; temp = mkpath (path, dirname, 1); free (path); @@ -248,17 +258,30 @@ cd_builtin (list) if (change_to_directory (temp, no_symlinks)) { - if (temp[0] != '.' || temp[1] != '/') - printf ("%s\n", temp); + /* POSIX.2 says that if a nonempty directory from CDPATH + is used to find the directory to change to, the new + directory name is echoed to stdout, whether or not + the shell is interactive. */ + if (opt) + printf ("%s\n", the_current_working_directory); free (temp); /* Posix.2 says that after using CDPATH, the resultant value of $PWD will not contain symlinks. */ - return (bindpwd (posixly_correct)); + return (bindpwd (posixly_correct || no_symlinks)); } else free (temp); } + + /* POSIX.2 says that if `.' does not appear in $CDPATH, we don't + try the current directory, so we just punt now with an error + message if POSIXLY_CORRECT is non-zero. */ + if (posixly_correct) + { + builtin_error ("%s: %s", dirname, strerror (ENOENT)); + return (EXECUTION_FAILURE); + } } if (change_to_directory (dirname, no_symlinks)) diff --git a/builtins/command.def b/builtins/command.def index 6e6e5f6..415b6d1 100644 --- a/builtins/command.def +++ b/builtins/command.def @@ -35,6 +35,9 @@ $END #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif @@ -179,11 +182,16 @@ get_standard_path () size_t len; len = (size_t)confstr (_CS_PATH, (char *)NULL, (size_t)0); - p = xmalloc ((int)len + 2); - *p = '\0'; - confstr (_CS_PATH, p, len); - return (p); -#else /* !_CSPATH || !HAVE_CONFSTR */ + if (len > 0) + { + p = xmalloc ((int)len + 2); + *p = '\0'; + confstr (_CS_PATH, p, len); + return (p); + } + else + return (savestring (STANDARD_UTILS_PATH)); +#else /* !_CS_PATH || !HAVE_CONFSTR */ # if defined (CS_PATH) return (savestring (CS_PATH)); # else diff --git a/builtins/common.c b/builtins/common.c index 1b82032..696901e 100644 --- a/builtins/common.c +++ b/builtins/common.c @@ -19,6 +19,9 @@ #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif @@ -27,6 +30,8 @@ #include "../posixstat.h" #include +#include + #if defined (PREFER_STDARG) # include #else @@ -54,6 +59,10 @@ # include "../bashhist.h" #endif +#if !defined (errno) +extern int errno; +#endif /* !errno */ + extern int no_symbolic_links, interactive, interactive_shell; extern int indirection_level, startup_state, subshell_environment; extern int line_number; @@ -399,11 +408,12 @@ get_working_directory (for_whom) directory = getcwd (the_current_working_directory, PATH_MAX); if (directory == 0) { - fprintf (stderr, "%s: could not get current directory: %s\n", + fprintf (stderr, "%s: could not get current directory: %s: %s\n", (for_whom && *for_whom) ? for_whom : get_name_for_error (), the_current_working_directory[0] ? the_current_working_directory - : bash_getcwd_errstr); + : bash_getcwd_errstr, + strerror (errno)); free (the_current_working_directory); the_current_working_directory = (char *)NULL; @@ -691,8 +701,13 @@ shell_builtin_compare (sbp1, sbp2) void initialize_shell_builtins () { +#ifdef _MINIX + qsort (shell_builtins, num_shell_builtins, sizeof (struct builtin), + (int (*)(const void *, const void *))shell_builtin_compare); +#else qsort (shell_builtins, num_shell_builtins, sizeof (struct builtin), shell_builtin_compare); +#endif } /* **************************************************************** */ @@ -791,10 +806,14 @@ backslash_quote (string) *r++ = '\\'; *r++ = c; break; - case '#': /* comment char */ #if 0 case '~': /* tilde expansion */ + if (s == string || s[-1] == '=' || s[-1] == ':') + *r++ = '\\'; + *r++ = c; + break; #endif + case '#': /* comment char */ if (s == string) *r++ = '\\'; /* FALLTHROUGH */ @@ -827,6 +846,9 @@ contains_shell_metas (string) case '^': case '$': case '`': /* expansion chars */ return (1); + case '~': /* tilde expansion */ + if (s == string || s[-1] == '=' || s[-1] == ':') + return (1); case '#': if (s == string) /* comment char */ return (1); diff --git a/builtins/common.h b/builtins/common.h index eec5444..f6fa101 100644 --- a/builtins/common.h +++ b/builtins/common.h @@ -30,77 +30,79 @@ #define SEVAL_INTERACT 0x02 #define SEVAL_NOHIST 0x04 +/* Functions from common.c */ extern void builtin_error __P((const char *, ...)); -extern void builtin_usage (); -extern void bad_option (); - -extern char **make_builtin_argv (); - -extern int get_numeric_arg (); -extern void remember_args (); -extern void no_args (); -extern int no_options (); - -extern int read_octal (); - -extern void push_context (), pop_context (); -extern void push_dollar_vars (), pop_dollar_vars (); -extern void dispose_saved_dollar_vars (); -extern int dollar_vars_changed (); -extern void set_dollar_vars_unchanged (), set_dollar_vars_changed (); +extern void builtin_usage __P((void)); +extern void no_args __P((WORD_LIST *)); +extern void bad_option __P((char *)); +extern int no_options __P((WORD_LIST *)); + +extern char **make_builtin_argv __P((WORD_LIST *, int *)); +extern void remember_args __P((WORD_LIST *, int)); + +extern void push_context __P((void)); +extern void pop_context __P((void)); +extern void push_dollar_vars __P((void)); +extern void pop_dollar_vars __P((void)); +extern void dispose_saved_dollar_vars __P((void)); +extern int dollar_vars_changed __P((void)); +extern void set_dollar_vars_unchanged __P((void)); +extern void set_dollar_vars_changed __P((void)); + +extern int get_numeric_arg __P((WORD_LIST *, int)); +extern int read_octal __P((char *)); /* Keeps track of the current working directory. */ extern char *the_current_working_directory; -extern char *get_working_directory (); -extern void set_working_directory (); +extern char *get_working_directory __P((char *)); +extern void set_working_directory __P((char *)); #if defined (JOB_CONTROL) -extern int get_job_spec (); +extern int get_job_spec __P((WORD_LIST *)); #endif - -extern int display_signal_list (); +extern int display_signal_list __P((WORD_LIST *, int)); /* It's OK to declare a function as returning a Function * without providing a definition of what a `Function' is. */ -extern struct builtin *builtin_address_internal (); -extern Function *find_shell_builtin (); -extern Function *builtin_address (); -extern Function *find_special_builtin (); - -extern void initialize_shell_builtins (); +extern struct builtin *builtin_address_internal __P((char *, int)); +extern Function *find_shell_builtin __P((char *)); +extern Function *builtin_address __P((char *)); +extern Function *find_special_builtin __P((char *)); +extern void initialize_shell_builtins __P((void)); -extern char *single_quote (); -extern char *double_quote (); -extern char *backslash_quote (); -extern int contains_shell_metas (); +extern char *single_quote __P((char *)); +extern char *double_quote __P((char *)); +extern char *backslash_quote __P((char *)); +extern int contains_shell_metas __P((char *)); /* Functions from set.def */ -extern void initialize_shell_options (); -extern void list_minus_o_opts (); -extern int set_minus_o_option (); -extern int minus_o_option_value (); -extern void reset_shell_options (); +extern void initialize_shell_options __P((int)); +extern void list_minus_o_opts __P((int, int)); +extern int set_minus_o_option __P((int, char *)); +extern int minus_o_option_value __P((char *)); +extern void reset_shell_options __P((void)); /* Functions from shopt.def */ -extern void reset_shopt_options (); +extern void reset_shopt_options __P((void)); /* Functions from type.def */ -extern int describe_command (); +extern int describe_command __P((char *, int, int)); /* Functions from setattr.def */ -extern int set_or_show_attributes (); -extern int show_var_attributes (); -extern int show_name_attributes (); -extern void set_var_attribute (); +extern int set_or_show_attributes __P((WORD_LIST *, int, int)); +extern int show_var_attributes __P((SHELL_VAR *, int, int)); +extern int show_name_attributes __P((char *, int)); +extern void set_var_attribute __P((char *, int, int)); /* Functions from pushd.def */ -extern char *get_dirstack_element (); -extern void set_dirstack_element (); -extern WORD_LIST *get_directory_stack (); +extern char *get_dirstack_from_string __P((char *)); +extern char *get_dirstack_element __P((int, int)); +extern void set_dirstack_element __P((int, int, char *)); +extern WORD_LIST *get_directory_stack __P((void)); /* Functions from evalstring.c */ -extern int parse_and_execute (); -extern void parse_and_execute_cleanup (); +extern int parse_and_execute __P((char *, char *, int)); +extern void parse_and_execute_cleanup __P((void)); /* Functions from evalfile.c */ extern int maybe_execute_file __P((char *, int)); diff --git a/builtins/declare.def b/builtins/declare.def index ae49b66..3bdca64 100644 --- a/builtins/declare.def +++ b/builtins/declare.def @@ -57,6 +57,9 @@ $END #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif @@ -377,6 +380,18 @@ declare_internal (list, local_var) FREE (var->value); var->value = t; } + + /* If we found this variable in the temporary environment, as with + `var=value declare -x var', make sure it is treated identically + to `var=value export var'. Do the same for `declare -r' and + `readonly'. Preserve the attributes, except for att_tempvar. */ + if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var)) + { + SHELL_VAR *tv; + tv = bind_variable (var->name, var->value ? var->value : ""); + tv->attributes = var->attributes & ~att_tempvar; + dispose_variable (var); + } } stupidly_hack_special_variables (name); diff --git a/builtins/enable.def b/builtins/enable.def index 049a7f0..61ea109 100644 --- a/builtins/enable.def +++ b/builtins/enable.def @@ -42,6 +42,9 @@ $END #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif diff --git a/builtins/eval.def b/builtins/eval.def index 62db712..c37b99a 100644 --- a/builtins/eval.def +++ b/builtins/eval.def @@ -29,7 +29,10 @@ $END #include #if defined (HAVE_UNISTD_H) -#include +# ifdef _MINIX +# include +# endif +# include #endif #include "../shell.h" diff --git a/builtins/evalfile.c b/builtins/evalfile.c index 3ffccbe..bb3217d 100644 --- a/builtins/evalfile.c +++ b/builtins/evalfile.c @@ -75,6 +75,7 @@ _evalfile (filename, flags) int return_val, fd, result, pflags; char *string; struct stat finfo; + size_t file_size; VFunction *errfunc; fd = open (filename, O_RDONLY); @@ -108,20 +109,33 @@ file_error_and_exit: return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1); } - string = xmalloc (1 + (int)finfo.st_size); - result = read (fd, string, finfo.st_size); + file_size = (size_t)finfo.st_size; + /* Check for overflow with large files. */ + if (file_size != finfo.st_size || file_size + 1 < file_size) + { + (*errfunc) ("%s: file is too large", filename); + return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1); + } + string = xmalloc (1 + file_size); + result = read (fd, string, file_size); string[result] = '\0'; return_val = errno; close (fd); errno = return_val; - if (result != (int)finfo.st_size) + if (result < 0) /* XXX was != file_size, not < 0 */ { free (string); goto file_error_and_exit; } + if (result == 0) + { + free (string); + return ((flags & FEVAL_BUILTIN) ? EXECUTION_SUCCESS : 1); + } + if (check_binary_file ((unsigned char *)string, (result > 80) ? 80 : result)) { free (string); diff --git a/builtins/evalstring.c b/builtins/evalstring.c index 1a22887..0063b71 100644 --- a/builtins/evalstring.c +++ b/builtins/evalstring.c @@ -19,12 +19,18 @@ #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif #include #include +#include + +#include "../filecntl.h" #include "../bashansi.h" #include "../shell.h" @@ -33,6 +39,7 @@ #include "../flags.h" #include "../input.h" #include "../execute_cmd.h" +#include "../redir.h" #if defined (HISTORY) # include "../bashhist.h" @@ -40,6 +47,10 @@ #include "common.h" +#if !defined (errno) +extern int errno; +#endif + extern void run_trap_cleanup (); extern int interactive, interactive_shell; @@ -47,10 +58,13 @@ extern int indirection_level, startup_state, subshell_environment; extern int line_number; extern int last_command_exit_value; extern int running_trap; +extern int posixly_correct; extern COMMAND *global_command; int parse_and_execute_level = 0; +static int cat_file (); + /* How to force parse_and_execute () to clean up after itself. */ void parse_and_execute_cleanup () @@ -202,7 +216,23 @@ parse_and_execute (string, from_file, flags) } #endif /* ONESHOT */ - last_result = execute_command_internal + /* See if this is a candidate for $( type == cm_simple && !command->redirects && + (command->flags & CMD_TIME_PIPELINE) == 0 && + command->value.Simple->words == 0 && + command->value.Simple->redirects && + command->value.Simple->redirects->next == 0 && + command->value.Simple->redirects->instruction == r_input_direction) + { + int r; + r = cat_file (command->value.Simple->redirects); + last_result = (r < 0) ? EXECUTION_FAILURE : EXECUTION_SUCCESS; + } + else + last_result = execute_command_internal (command, 0, NO_PIPE, NO_PIPE, bitmap); dispose_command (command); @@ -238,3 +268,94 @@ parse_and_execute (string, from_file, flags) return (last_result); } + +/* Write NB bytes from BUF to file descriptor FD, retrying the write if + it is interrupted. We retry three times if we get a zero-length + write. Any other signal causes this function to return prematurely. */ +static int +zwrite (fd, buf, nb) + int fd; + unsigned char *buf; + int nb; +{ + int n, i, nt; + + for (n = nb, nt = 0;;) + { + i = write (fd, buf, n); + if (i > 0) + { + n -= i; + if (n <= 0) + return nb; + } + else if (i == 0) + { + if (++nt > 3) + return (nb - n); + } + else if (errno != EINTR) + return -1; + } +} + +/* Handle a $( < file ) command substitution. This expands the filename, + returning errors as appropriate, then just cats the file to the standard + output. */ +static int +cat_file (r) + REDIRECT *r; +{ + char lbuf[128], *fn; + int nr, fd, rval; + + if (r->instruction != r_input_direction) + return -1; + + /* Get the filename. */ + if (posixly_correct && !interactive_shell) + disallow_filename_globbing++; + fn = redirection_expand (r->redirectee.filename); + if (posixly_correct && !interactive_shell) + disallow_filename_globbing--; + + if (fn == 0) + { + redirection_error (r, AMBIGUOUS_REDIRECT); + return -1; + } + + fd = open(fn, O_RDONLY); + if (fd < 0) + { + file_error (fn); + free (fn); + return -1; + } + + rval = 0; + while (1) + { + /* Retry the reads on EINTR. Any other error causes a break from the + loop. */ + while ((nr = read (fd, lbuf, sizeof(lbuf))) < 0 && errno == EINTR) + ; + if (nr == 0) + break; + else if (nr < 0) + { + rval = -1; + break; + } + if (zwrite (1, lbuf, nr) < 0) + { + rval = -1; + break; + } + } + + free (fn); + close (fd); + + return (0); +} diff --git a/builtins/exec.def b/builtins/exec.def index cc7f5a9..4e1394d 100644 --- a/builtins/exec.def +++ b/builtins/exec.def @@ -49,6 +49,7 @@ $END #include "../shell.h" #include "../execute_cmd.h" +#include "../findcmd.h" #if defined (JOB_CONTROL) # include "../jobs.h" #endif diff --git a/builtins/exit.def b/builtins/exit.def index ee02b38..37f1d7b 100644 --- a/builtins/exit.def +++ b/builtins/exit.def @@ -75,7 +75,7 @@ int logout_builtin (list) WORD_LIST *list; { - if (login_shell == 0 && interactive) + if (login_shell == 0 /* && interactive */) { builtin_error ("not login shell: use `exit'"); return (EXECUTION_FAILURE); diff --git a/builtins/fc.def b/builtins/fc.def index e88ba12..587d7ed 100644 --- a/builtins/fc.def +++ b/builtins/fc.def @@ -49,10 +49,14 @@ $END #include #if defined (HISTORY) -#include +#ifndef _MINIX +# include +#endif #include "../bashtypes.h" #include "../posixstat.h" -#include +#ifndef _MINIX +# include +#endif #if defined (HAVE_UNISTD_H) # include diff --git a/builtins/getopt.c b/builtins/getopt.c index b5f8bc4..2fbcac7 100644 --- a/builtins/getopt.c +++ b/builtins/getopt.c @@ -20,6 +20,9 @@ #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif diff --git a/builtins/getopts.def b/builtins/getopts.def index a9c5116..533775a 100644 --- a/builtins/getopts.def +++ b/builtins/getopts.def @@ -61,6 +61,9 @@ $END #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif diff --git a/builtins/hash.def b/builtins/hash.def index 813cb03..f601c10 100644 --- a/builtins/hash.def +++ b/builtins/hash.def @@ -35,6 +35,8 @@ $END #include +#include "../bashtypes.h" + #if defined (HAVE_UNISTD_H) # include #endif @@ -43,8 +45,8 @@ $END #include "../shell.h" #include "../builtins.h" -#include "../execute_cmd.h" #include "../flags.h" +#include "../findcmd.h" #include "../hashcmd.h" #include "common.h" #include "bashgetopt.h" @@ -63,7 +65,7 @@ hash_builtin (list) WORD_LIST *list; { int expunge_hash_table, opt; - char *word, *pathname; + char *w, *pathname; if (hashing_enabled == 0) { @@ -107,12 +109,12 @@ hash_builtin (list) for (opt = EXECUTION_SUCCESS; list; list = list->next) { /* Add or rehash the specified commands. */ - word = list->word->word; + w = list->word->word; if (pathname) - remember_filename (word, pathname, 0, 0); - else if (absolute_program (word)) + remember_filename (w, pathname, 0, 0); + else if (absolute_program (w)) continue; - else if (add_hashed_command (word, 0)) + else if (add_hashed_command (w, 0)) opt = EXECUTION_FAILURE; } @@ -121,23 +123,23 @@ hash_builtin (list) } static int -add_hashed_command (word, quiet) - char *word; +add_hashed_command (w, quiet) + char *w; int quiet; { int rv; char *full_path; rv = 0; - if (find_function (word) == 0 && find_shell_builtin (word) == 0) + if (find_function (w) == 0 && find_shell_builtin (w) == 0) { - full_path = find_user_command (word); + full_path = find_user_command (w); if (full_path && executable_file (full_path)) - remember_filename (word, full_path, dot_found_in_search, 0); + remember_filename (w, full_path, dot_found_in_search, 0); else { if (quiet == 0) - builtin_error ("%s: not found", word); + builtin_error ("%s: not found", w); rv++; } if (full_path) diff --git a/builtins/help.def b/builtins/help.def index 9c47910..cd59d3c 100644 --- a/builtins/help.def +++ b/builtins/help.def @@ -36,11 +36,15 @@ $END #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif #include "../shell.h" #include "../builtins.h" +#include "../pathexp.h" #include "bashgetopt.h" #include @@ -100,7 +104,7 @@ help_builtin (list) { QUIT; if ((strncmp (pattern, name, plen) == 0) || - (fnmatch (pattern, name, 0) != FNM_NOMATCH)) + (fnmatch (pattern, name, FNMATCH_EXTFLAG) != FNM_NOMATCH)) { printf ("%s: %s\n", name, shell_builtins[i].short_doc); diff --git a/builtins/history.def b/builtins/history.def index b1e3ab3..92094d6 100644 --- a/builtins/history.def +++ b/builtins/history.def @@ -46,7 +46,9 @@ $END #if defined (HISTORY) #include "../bashtypes.h" -#include +#ifndef _MINIX +# include +#endif #include "../posixstat.h" #include "../filecntl.h" #include diff --git a/builtins/jobs.def b/builtins/jobs.def index 2c818af..4cc9b77 100644 --- a/builtins/jobs.def +++ b/builtins/jobs.def @@ -205,11 +205,12 @@ execute_list_with_replacements (list) $BUILTIN disown $FUNCTION disown_builtin $DEPENDS_ON JOB_CONTROL -$SHORT_DOC disown [-h] [jobspec ...] +$SHORT_DOC disown [-h] [-ar] [jobspec ...] By default, removes each JOBSPEC argument from the table of active jobs. If the -h option is given, the job is not removed from the table, but is marked so that SIGHUP is not sent to the job if the shell receives a -SIGHUP. +SIGHUP. The -a option, when JOBSPEC is not supplied, means to remove all +jobs from the job table; the -r option means to remove only running jobs. $END #if defined (JOB_CONTROL) @@ -217,18 +218,24 @@ int disown_builtin (list) WORD_LIST *list; { - int opt, job, retval, nohup_only; + int opt, job, retval, nohup_only, running_jobs, all_jobs; sigset_t set, oset; - nohup_only = 0; + nohup_only = running_jobs = all_jobs = 0; reset_internal_getopt (); - while ((opt = internal_getopt (list, "h")) != -1) + while ((opt = internal_getopt (list, "ahr")) != -1) { switch (opt) { + case 'a': + all_jobs = 1; + break; case 'h': nohup_only = 1; break; + case 'r': + running_jobs = 1; + break; default: builtin_usage (); return (EX_USAGE); @@ -237,17 +244,15 @@ disown_builtin (list) list = loptend; retval = EXECUTION_SUCCESS; -#if 0 - /* For the future `disown -a' */ - if (list == 0) + /* `disown -a' or `disown -r' */ + if (list == 0 && (all_jobs || running_jobs)) { if (nohup_only) - nohup_all_jobs (); + nohup_all_jobs (running_jobs); else - delete_all_jobs (); + delete_all_jobs (running_jobs); return (EXECUTION_SUCCESS); } -#endif do { @@ -256,7 +261,7 @@ disown_builtin (list) ? get_job_by_pid (atoi(list->word->word), 0) : get_job_spec (list); - if (job == NO_JOB || jobs == 0 || jobs[job] == 0) + if (job == NO_JOB || jobs == 0 || job < 0 || job >= job_slots || jobs[job] == 0) { builtin_error ("%s: no such job", list ? list->word->word : "current"); retval = EXECUTION_FAILURE; @@ -264,7 +269,7 @@ disown_builtin (list) else if (nohup_only) nohup_job (job); else - delete_job (job); + delete_job (job, 1); UNBLOCK_CHILD (oset); if (list) diff --git a/builtins/kill.def b/builtins/kill.def index ea78bd5..6efb37b 100644 --- a/builtins/kill.def +++ b/builtins/kill.def @@ -39,6 +39,9 @@ $END #include #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif @@ -77,7 +80,10 @@ kill_builtin (list) pid_t pid; if (list == 0) - return (EXECUTION_SUCCESS); + { + builtin_usage (); + return (EXECUTION_FAILURE); + } any_succeeded = listing = saw_signal = 0; signal = SIGTERM; @@ -145,6 +151,12 @@ kill_builtin (list) return (EXECUTION_FAILURE); } + if (list == 0) + { + builtin_usage (); + return (EXECUTION_FAILURE); + } + while (list) { word = list->word->word; @@ -152,7 +164,7 @@ kill_builtin (list) if (*word == '-') word++; - if (all_digits (word)) + if (*word && all_digits (word)) { /* Use the entire argument in case of minus sign presence. */ pid = (pid_t) atoi (list->word->word); @@ -162,12 +174,12 @@ kill_builtin (list) else any_succeeded++; } - else if (*list->word->word != '%') + else if (*list->word->word && *list->word->word != '%') { builtin_error ("%s: no such pid", list->word->word); CONTINUE_OR_FAIL; } - else if (interactive || job_control) + else if (*word && (interactive || job_control)) /* Posix.2 says you can kill without job control active (4.32.4) */ { /* Must be a job spec. Check it out. */ int job; @@ -208,7 +220,7 @@ kill_builtin (list) } else { - builtin_error ("`%s' is not a pid or valid job spec", list->word->word); + builtin_error ("`%s': not a pid or valid job spec", list->word->word); CONTINUE_OR_FAIL; } continue_killing: diff --git a/builtins/let.def b/builtins/let.def index b747962..fd037cd 100644 --- a/builtins/let.def +++ b/builtins/let.def @@ -63,6 +63,9 @@ $END #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif diff --git a/builtins/mkbuiltins.c b/builtins/mkbuiltins.c index 983bada..8cd2703 100644 --- a/builtins/mkbuiltins.c +++ b/builtins/mkbuiltins.c @@ -22,18 +22,20 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif +#ifndef _MINIX #include "../bashtypes.h" #include +#endif + #include "../posixstat.h" #include "../filecntl.h" -#if defined (HAVE_UNISTD_H) -# include -#endif /* HAVE_UNISTD_H */ - #include "../bashansi.h" #include @@ -437,8 +439,9 @@ extract_info (filename, structfile, externfile) register int i; DEF_FILE *defs; struct stat finfo; + size_t file_size; char *buffer, *line; - int fd; + int fd, nr; if (stat (filename, &finfo) == -1) file_error (filename); @@ -448,13 +451,20 @@ extract_info (filename, structfile, externfile) if (fd == -1) file_error (filename); - buffer = xmalloc (1 + (int)finfo.st_size); + file_size = (size_t)finfo.st_size; + buffer = xmalloc (1 + file_size); - if (read (fd, buffer, finfo.st_size) != finfo.st_size) + if ((nr = read (fd, buffer, file_size)) < 0) file_error (filename); close (fd); + if (nr == 0) + { + fprintf (stderr, "mkbuiltins: %s: skipping zero-length file\n", filename); + return; + } + /* Create and fill in the initial structure describing this file. */ defs = (DEF_FILE *)xmalloc (sizeof (DEF_FILE)); defs->filename = filename; @@ -466,11 +476,11 @@ extract_info (filename, structfile, externfile) /* Build the array of lines. */ i = 0; - while (i < finfo.st_size) + while (i < file_size) { array_add (&buffer[i], defs->lines); - while (buffer[i] != '\n' && i < finfo.st_size) + while (buffer[i] != '\n' && i < file_size) i++; buffer[i++] = '\0'; } @@ -676,7 +686,10 @@ current_builtin (directive, defs) DEF_FILE *defs; { must_be_building (directive, defs); - return ((BUILTIN_DESC *)defs->builtins->array[defs->builtins->sindex - 1]); + if (defs->builtins) + return ((BUILTIN_DESC *)defs->builtins->array[defs->builtins->sindex - 1]); + else + return ((BUILTIN_DESC *)NULL); } /* Add LINE to the long documentation for the current builtin. @@ -756,6 +769,11 @@ function_handler (self, defs, arg) builtin = current_builtin (self, defs); + if (builtin == 0) + { + line_error (defs, "syntax error: no current builtin for $FUNCTION directive"); + exit (1); + } if (builtin->function) line_error (defs, "%s already has a function (%s)", builtin->name, builtin->function); diff --git a/builtins/printf.def b/builtins/printf.def new file mode 100644 index 0000000..43ccb56 --- /dev/null +++ b/builtins/printf.def @@ -0,0 +1,693 @@ +This file is printf.def, from which is created printf.c. +It implements the builtin "printf" in Bash. + +Copyright (C) 1997 Free Software Foundation, Inc. + +This file is part of GNU Bash, the Bourne Again SHell. + +Bash 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 1, or (at your option) any later +version. + +Bash 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 Bash; see the file COPYING. If not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA + +$PRODUCES printf.c + +$BUILTIN printf +$FUNCTION printf_builtin +$SHORT_DOC printf format [arguments] +printf formats and prints ARGUMENTS under control of the FORMAT. FORMAT +is a character string which contains three types of objects: plain +characters, which are simply copied to standard output, character escape +sequences which are converted and copied to the standard output, and +format specifications, each of which causes printing of the next successive +argument. In addition to the standard printf(1) formats, %b means to +expand backslash escape sequences in the corresponding argument, and %q +means to quote the argument in a way that can be reused as shell input. +$END + +#include + +#include "../bashtypes.h" + +#include +#if defined (HAVE_LIMITS_H) +# include +#else + /* Assume 32-bit ints and longs. */ +# define LONG_MAX 2147483647L +# define LONG_MIN (-2147483647L-1) +# define INT_MAX 2147483647 +# define INT_MIN (-2147483647-1) +#endif + +#include +#include + +#include "../bashansi.h" +#include "../shell.h" +#include "../stdc.h" +#include "bashgetopt.h" + +#if !defined (errno) +extern int errno; +#endif + +#define PF(f, func) \ + do { \ + if (fieldwidth && precision) \ + (void)printf(f, fieldwidth, precision, func); \ + else if (fieldwidth && precision == 0) \ + (void)printf(f, fieldwidth, func); \ + else if (precision) \ + (void)printf(f, precision, func); \ + else \ + (void)printf(f, func); \ + } while (0) + +#define PRETURN(value) \ + do { free (format); fflush (stdout); return (value); } while (0) + +#define SKIP1 "#-+ 0" +#define SKIP2 "*0123456789" + +static void printstr __P((char *, char *, int, int, int)); +static char *bexpand __P((char *, int, int *, int *)); +static char *mklong __P((char *, int)); +static int getchr __P((void)); +static char *getstr __P((void)); +static int getint __P((void)); +static int getlong __P((long *)); +static int getulong __P((unsigned long *)); +static double getdouble __P((void)); +static int asciicode __P((void)); + +static WORD_LIST *garglist; +static int retval; + +extern char *backslash_quote (); + +int +printf_builtin (list) + WORD_LIST *list; +{ + int ch, end, fieldwidth, precision, foundmod; + char convch, nextch, *format, *fmt, *start; + + retval = EXECUTION_SUCCESS; + reset_internal_getopt (); + while ((ch = internal_getopt (list, "")) != -1) + { + switch (ch) + { + case '?': + default: + builtin_usage(); + return (EX_USAGE); + } + } + list = loptend; + + if (list == 0) + { + builtin_usage (); + return (EX_USAGE); + } + + 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); + + garglist = list->next; + + /* Basic algorithm is to scan the format string for conversion + specifications -- once one is found, find out if the field + width or precision is a '*'; if it is, gather up value. Note, + 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. */ + + do + { + /* find next format specification */ + for (fmt = format; *fmt; fmt++) + { + precision = fieldwidth = foundmod = 0; + + if (*fmt != '%') + { + putchar (*fmt); + continue; + } + + /* ASSERT(*fmt == '%') */ + start = fmt++; + + if (*fmt == '%') /* %% prints a % */ + { + putchar ('%'); + continue; + } + + /* found format specification, skip to field width */ + for (; *fmt && strchr(SKIP1, *fmt); ++fmt) + ; + fieldwidth = (*fmt == '*') ? getint () : 0; + + /* skip to possible '.', get following precision */ + for (; *fmt && strchr(SKIP2, *fmt); ++fmt) + ; + if (*fmt == '.') + { + ++fmt; + precision = (*fmt == '*') ? getint () : 0; + } + + /* 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') + { + fmt++; + foundmod = 1; + } + + convch = *fmt; + nextch = fmt[1]; + fmt[1] = '\0'; + switch(convch) + { + case 'c': + { + char p; + + p = getchr (); + PF(start, p); + break; + } + + case 's': + { + char *p; + + p = getstr (); + PF(start, p); + break; + } + + case 'b': /* expand escapes in argument */ + { + char *p, *xp; + int rlen; + + p = getstr (); + ch = rlen = 0; + xp = bexpand (p, strlen (p), &ch, &rlen); + + if (xp) + { + /* Have to use printstr because of possible NUL bytes + in XP -- printf does not handle that well. */ + printstr (start, xp, rlen, fieldwidth, precision); + free (xp); + } + + if (ch) + PRETURN (retval); + break; + } + + case 'q': /* print with shell quoting */ + { + char *p, *xp; + + p = getstr (); + xp = backslash_quote (p); + if (xp) + { + /* Use printstr to get fieldwidth and precision right. */ + printstr (start, xp, strlen (xp), fieldwidth, precision); + free (xp); + } + break; + } + + case 'd': + case 'i': + { + long p; + char *f; + + if (foundmod == 0 && ((f = mklong (start, convch)) == NULL)) + PRETURN (EXECUTION_FAILURE); + else + f = start; + if (getlong (&p)) + PRETURN (EXECUTION_FAILURE); + PF(f, p); + break; + } + + case 'o': + case 'u': + case 'x': + case 'X': + { + unsigned long p; + char *f; + + if (foundmod == 0 && ((f = mklong (start, convch)) == NULL)) + PRETURN (EXECUTION_FAILURE); + else + f = start; + if (getulong (&p)) + PRETURN (EXECUTION_FAILURE); + PF (f, p); + break; + } + + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + { + double p; + + p = getdouble (); + PF(start, p); + break; + } + + /* We output unrecognized format characters, but we print a + warning message and return a failure exit status. */ + default: + builtin_error ("`%c': illegal format character", convch); + PRETURN (EXECUTION_FAILURE); + } + + fmt[1] = nextch; + } + } + while (garglist); + + PRETURN (retval); +} + +/* We duplicate a lot of what printf(3) does here. */ +static void +printstr (fmt, string, len, fieldwidth, precision) + char *fmt; /* format */ + char *string; /* expanded string argument */ + int len; /* length of expanded string */ + int fieldwidth; /* argument for width of `*' */ + int precision; /* argument for precision of `*' */ +{ +#if 0 + char *s; +#endif + int padlen, nc, ljust, i; + int fw, pr; /* fieldwidth and precision */ + + if (string == 0 || *string == '\0') + return; + +#if 0 + s = fmt; +#endif + if (*fmt == '%') + fmt++; + + ljust = fw = pr = 0; + + /* skip flags */ + while (*fmt == '#' || *fmt == '-' || *fmt == '+' || *fmt == ' ' || *fmt == '0') + { + if (*fmt == '-') + ljust = 1; + fmt++; + } + + /* get fieldwidth, if present */ + if (*fmt == '*') + { + fmt++; + fw = fieldwidth; + } + else if (isdigit (*fmt)) + { + fw = *fmt++ - '0'; + while (isdigit (*fmt)) + fw = (fw * 10) + (*fmt++ - '0'); + } + + /* get precision, if present */ + if (*fmt == '.') + { + fmt++; + if (*fmt == '*') + { + fmt++; + pr = precision; + } + else if (isdigit (*fmt)) + { + pr = *fmt++ - '0'; + while (isdigit (*fmt)) + pr = (pr * 10) + (*fmt++ - '0'); + } + } + +#if 0 + /* If we remove this, get rid of `s'. */ + if (*fmt != 'b' && *fmt != 'q') + { + internal_error ("format parsing problem: %s", s); + fw = pr = 0; + } +#endif + + /* chars from string to print */ + nc = (pr > 0 && pr <= len) ? pr : len; + + padlen = fw - nc; + if (padlen < 0) + padlen = 0; + if (ljust) + padlen = -padlen; + + /* leading pad characters */ + for (; padlen > 0; padlen--) + putchar (' '); + + /* output NC characters from STRING */ + for (i = 0; i < nc; i++) + putchar (string[i]); + + /* output any necessary trailing padding */ + for (; padlen < 0; padlen++) + putchar (' '); +} + +/* Convert STRING by expanding the escape sequences specified by the + POSIX standard for printf's `%b' format string. If SAWC is non-null, + recognize `\c' and use that as a string terminator. If we see \c, set + *SAWC to 1 before returning. LEN is the length of STRING. */ + +#ifdef isoctal +#undef isoctal +#endif + +#define isoctal(c) ((c) >= '0' && (c) <= '7') + +#define OCTVALUE(c) ((c) - '0') + +#ifndef isxdigit +# define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) +#endif + +#define HEXVALUE(c) \ + ((c) >= 'a' && (c) <= 'f' ? (c)-'a'+10 : (c) >= 'A' && (c) <= 'F' ? (c)-'A'+10 : (c)-'0') + +static char * +bexpand (string, len, sawc, lenp) + char *string; + int len, *sawc, *lenp; +{ + int c, temp; + char *ret, *r, *s; + + if (string == 0 || *string == '\0') + { + if (sawc) + *sawc = 0; + if (lenp) + *lenp = 0; + return ((char *)NULL); + } + + ret = xmalloc (len + 1); + for (r = ret, s = string; s && *s; ) + { + c = *s++; + if (c != '\\' || *s == '\0') + { + *r++ = c; + continue; + } + + switch (c = *s++) + { +#if defined (__STDC__) + case 'a': c = '\a'; break; +#else + case 'a': c = '\007'; break; +#endif + + case 'b': c = '\b'; break; + + case 'e': c = '\033'; break; /* ESC -- non-ANSI */ + + case 'f': c = '\f'; break; + + case 'n': c = '\n'; break; + + case 'r': c = '\r'; break; + + case 't': c = '\t'; break; + + case 'v': c = '\v'; break; + + /* %b octal constants are `\0' followed by one, two, or three + octal digits... */ + case '0': + for (temp = 3, c = 0; isoctal (*s) && temp--; s++) + c = (c * 8) + OCTVALUE (*s); + break; + + /* but, as an extension, the other echo-like octal escape + sequences are supported as well. */ + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': + for (temp = 2, c -= '0'; isoctal (*s) && temp--; s++) + c = (c * 8) + OCTVALUE (*s); + break; + + /* And, as another extension, we allow \xNNN, where each N is a + hex digit. */ + case 'x': + for (temp = 3, c = 0; isxdigit (*s) && temp--; s++) + c = (c * 16) + HEXVALUE (*s); + if (temp == 3) + { + builtin_error ("missing hex digit for \\x"); + *r++ = '\\'; + c = 'x'; + } + break; + + case '\\': +#if 0 + case '\'': /* XXX */ + case '"': /* XXX */ +#endif + break; + + case 'c': + if (sawc) + *sawc = 1; + *r = '\0'; + if (lenp) + *lenp = r - ret; + return ret; + + /* other backslash escapes are passed through unaltered */ + default: *r++ = '\\'; break; + } + + *r++ = c; + } + + *r = '\0'; + if (lenp) + *lenp = r - ret; + return ret; +} + +static char * +mklong (str, ch) + char *str; + int ch; +{ + static char copy[64]; + int len; + + len = strlen (str) + 2; + FASTCOPY (str, copy, len - 3); + copy[len - 3] = 'l'; + copy[len - 2] = ch; + copy[len - 1] = '\0'; + return (copy); +} + +static int +getchr () +{ + int ret; + + if (garglist == 0) + return ('\0'); + + ret = (int)garglist->word->word[0]; + garglist = garglist->next; + return ret; +} + +static char * +getstr () +{ + char *ret; + + if (garglist == 0) + return (""); + + ret = garglist->word->word; + garglist = garglist->next; + return ret; +} + +static int +getint () +{ + long ret; + + if (getlong (&ret)) + return (0); + + if (ret > INT_MAX) + { + builtin_error ("%s: %s", garglist->word->word, strerror(ERANGE)); + return (0); + } + + return ((int)ret); +} + +static int +getlong (lp) + long *lp; +{ + long ret; + + if (garglist == 0) + { + *lp = 0L; + return (0); + } + + if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"') + { + *lp = (long)asciicode (); + return (0); + } + + errno = 0; + /* legal_number does not currently detect overflow, but it should. + Someday it will. */ + if (legal_number (garglist->word->word, &ret) == 0) + { + builtin_error ("%s: illegal number", garglist->word->word); + return (1); + } + else if (errno == ERANGE) + { + builtin_error ("%s: %s", garglist->word->word, strerror(ERANGE)); + return (1); + } + + *lp = ret; + garglist = garglist->next; + return (0); +} + +static int +getulong (ulp) + unsigned long *ulp; +{ + unsigned long ret; + char *ep; + + if (garglist == 0) + { + *ulp = (unsigned long)0; + return (0); + } + + if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"') + { + *ulp = (unsigned long)asciicode (); + return (0); + } + + errno = 0; + ret = strtoul (garglist->word->word, &ep, 0); + + if (*ep) + { + builtin_error ("%s: illegal number", garglist->word->word); + return (1); + } + else if (errno == ERANGE) + { + builtin_error ("%s: %s", garglist->word->word, strerror(ERANGE)); + return (1); + } + + *ulp = ret; + garglist = garglist->next; + return (0); +} + +static double +getdouble () +{ + double ret; + + if (garglist == 0) + return ((double)0); + + if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"') + return ((double)asciicode ()); + + /* This should use strtod if it is available. */ + ret = atof (garglist->word->word); + garglist = garglist->next; + return (ret); +} + +/* NO check is needed for garglist here. */ +static int +asciicode () +{ + register int ch; + + ch = garglist->word->word[1]; + garglist = garglist->next; + return (ch); +} diff --git a/builtins/psize.c b/builtins/psize.c index 6037d7a..596f97f 100644 --- a/builtins/psize.c +++ b/builtins/psize.c @@ -24,11 +24,16 @@ #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif #include +#ifndef _MINIX #include "../bashtypes.h" +#endif #include #include diff --git a/builtins/psize.sh b/builtins/psize.sh index 961becd..84f1f2a 100755 --- a/builtins/psize.sh +++ b/builtins/psize.sh @@ -3,6 +3,12 @@ # psize.sh -- determine this system's pipe size, and write a define to # pipesize.h so ulimit.c can use it. +TMPDIR=/tmp +TMPNAME=pipsize.$$ +TMPFILE=$TMPDIR/$TMPNAME + +trap 'rm -f $TMPFILE' 0 1 2 3 6 15 + echo "/*" echo " * pipesize.h" echo " *" @@ -11,14 +17,20 @@ echo " * Do not edit!" echo " */" echo "" -./psize.aux 2>/tmp/pipesize | sleep 3 +# +# Try to avoid tempfile races. We can't really check for the file's +# existance before we run psize.aux, because `test -e' is not portable, +# `test -h' (test for symlinks) is not portable, and `test -f' only +# checks for regular files +# +rm -f $TMPFILE + +./psize.aux 2>$TMPFILE | sleep 3 -if [ -s /tmp/pipesize ]; then - echo "#define PIPESIZE `cat /tmp/pipesize`" +if [ -s $TMPFILE ]; then + echo "#define PIPESIZE `cat $TMPFILE`" else echo "#define PIPESIZE 512" fi -rm -f /tmp/pipesize - exit 0 diff --git a/builtins/pushd.def b/builtins/pushd.def index 87300dc..7226ab2 100644 --- a/builtins/pushd.def +++ b/builtins/pushd.def @@ -95,9 +95,14 @@ $END #if defined (PUSHD_AND_POPD) #include -#include +#ifndef _MINIX +# include +#endif #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif @@ -547,6 +552,34 @@ get_dirstack_index (ind, sign, indexp) return (sign > 0 ? directory_list_offset - ind : ind); } +/* Used by the tilde expansion code. */ +char * +get_dirstack_from_string (string) + char *string; +{ + int ind, sign, index_flag; + long i; + + sign = 1; + if (*string == '-' || *string == '+') + { + sign = (*string == '-') ? -1 : 1; + string++; + } + if (legal_number (string, &i) == 0) + return ((char *)NULL); + + index_flag = 0; + ind = get_dirstack_index (i, sign, &index_flag); + if (index_flag && (ind < 0 || ind > directory_list_offset)) + return ((char *)NULL); + if (index_flag == 0 || (index_flag == 1 && ind == 0)) + return (get_string_value ("PWD")); + else + return (pushd_directory_list[ind]); +} + +#ifdef INCLUDE_UNUSED char * get_dirstack_element (ind, sign) int ind, sign; @@ -557,6 +590,7 @@ get_dirstack_element (ind, sign) return (i < 0 || i > directory_list_offset) ? (char *)NULL : pushd_directory_list[i]; } +#endif void set_dirstack_element (ind, sign, value) diff --git a/builtins/read.def b/builtins/read.def index e1e6354..6d161f6 100644 --- a/builtins/read.def +++ b/builtins/read.def @@ -43,6 +43,9 @@ $END #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif @@ -395,11 +398,13 @@ bind_read_variable (name, value) #if defined (ARRAY_VARS) if (valid_array_reference (name) == 0) { +#if 0 if (legal_identifier (name) == 0) { builtin_error ("`%s': not a valid identifier", name); return ((SHELL_VAR *)NULL); } +#endif return (bind_variable (name, value)); } else diff --git a/builtins/return.def b/builtins/return.def index da5b76b..e88808c 100644 --- a/builtins/return.def +++ b/builtins/return.def @@ -32,6 +32,9 @@ $END #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif diff --git a/builtins/set.def b/builtins/set.def index 74f2e5c..b5ac83b 100644 --- a/builtins/set.def +++ b/builtins/set.def @@ -24,6 +24,9 @@ $PRODUCES set.c #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif @@ -229,31 +232,20 @@ minus_o_option_value (name) #define MINUS_O_FORMAT "%-15s\t%s\n" -void -list_minus_o_opts (mode) - int mode; +static void +print_minus_o_option (name, value, pflag) + char *name; + int value, pflag; { - register int i; - int *on_or_off, value; - - for (value = i = 0; o_options[i].name; i++) - { - on_or_off = find_flag (o_options[i].letter); - if (on_or_off == FLAG_UNKNOWN) - on_or_off = &value; - if (mode == -1 || mode == *on_or_off) - printf (MINUS_O_FORMAT, o_options[i].name, *on_or_off ? on : off); - } - for (i = 0; binary_o_options[i].name; i++) - { - value = GET_BINARY_O_OPTION_VALUE (i, binary_o_options[i].name); - if (mode == -1 || mode == value) - printf (MINUS_O_FORMAT, binary_o_options[i].name, value ? on : off); - } + if (pflag == 0) + printf (MINUS_O_FORMAT, name, value ? on : off); + else + printf ("set %co %s\n", value ? '-' : '+', name); } -static void -minus_o_option_commands () +void +list_minus_o_opts (mode, reusable) + int mode, reusable; { register int i; int *on_or_off, value; @@ -263,12 +255,14 @@ minus_o_option_commands () on_or_off = find_flag (o_options[i].letter); if (on_or_off == FLAG_UNKNOWN) on_or_off = &value; - printf ("set %co %s\n", *on_or_off ? '-' : '+', o_options[i].name); + if (mode == -1 || mode == *on_or_off) + print_minus_o_option (o_options[i].name, *on_or_off, reusable); } for (i = 0; binary_o_options[i].name; i++) { value = GET_BINARY_O_OPTION_VALUE (i, binary_o_options[i].name); - printf ("set %co %s\n", value ? '-' : '+', binary_o_options[i].name); + if (mode == -1 || mode == value) + print_minus_o_option (binary_o_options[i].name, value, reusable); } } @@ -421,7 +415,7 @@ void set_shellopts () { char *value; - int vsize, i, vptr, *ip; + int vsize, i, vptr, *ip, exported; SHELL_VAR *v; for (vsize = i = 0; o_options[i].name; i++) @@ -458,10 +452,25 @@ set_shellopts () value[vptr] = '\0'; v = find_variable ("SHELLOPTS"); + + /* Turn off the read-only attribute so we can bind the new value, and + note whether or not the variable was exported. */ if (v) - v->attributes &= ~att_readonly; + { + v->attributes &= ~att_readonly; + exported = exported_p (v); + } + else + exported = 0; + v = bind_variable ("SHELLOPTS", value); + + /* Turn the read-only attribute back on, and turn off the export attribute + if it was set implicitly by mark_modified_vars and SHELLOPTS was not + exported before we bound the new value. */ v->attributes |= att_readonly; + if (mark_modified_vars && exported == 0 && exported_p (v)) + v->attributes &= ~att_exported; free (value); } @@ -482,20 +491,24 @@ parse_shellopts (value) } void -initialize_shell_options () +initialize_shell_options (no_shellopts) + int no_shellopts; { char *temp; SHELL_VAR *var; - var = find_variable ("SHELLOPTS"); - /* set up any shell options we may have inherited. */ - if (var && imported_p (var)) + if (no_shellopts == 0) { - temp = (array_p (var)) ? (char *)NULL : savestring (value_cell (var)); - if (temp) + var = find_variable ("SHELLOPTS"); + /* set up any shell options we may have inherited. */ + if (var && imported_p (var)) { - parse_shellopts (temp); - free (temp); + temp = (array_p (var)) ? (char *)NULL : savestring (value_cell (var)); + if (temp) + { + parse_shellopts (temp); + free (temp); + } } } @@ -607,10 +620,7 @@ set_builtin (list) if (opt == 0) { - if (on_or_off == '-') - list_minus_o_opts (-1); - else - minus_o_option_commands (); + list_minus_o_opts (-1, (on_or_off == '+')); continue; } @@ -619,10 +629,7 @@ set_builtin (list) if (option_name == 0 || *option_name == '\0' || *option_name == '-' || *option_name == '+') { - if (on_or_off == '-') - list_minus_o_opts (-1); - else - minus_o_option_commands (); + list_minus_o_opts (-1, (on_or_off == '+')); continue; } list = list->next; /* Skip over option name. */ @@ -730,7 +737,10 @@ unset_builtin (list) } #endif - if (legal_identifier (name) == 0) + /* Bash allows functions with names which are not valid identifiers + to be created when not in posix mode, so check only when in posix + mode when unsetting a function. */ + if (((unset_function && posixly_correct) || !unset_function) && legal_identifier (name) == 0) { builtin_error ("`%s': not a valid identifier", name); NEXT_VARIABLE (); diff --git a/builtins/setattr.def b/builtins/setattr.def index d4068a3..1fadee6 100644 --- a/builtins/setattr.def +++ b/builtins/setattr.def @@ -24,6 +24,9 @@ $PRODUCES setattr.c #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif @@ -339,6 +342,7 @@ show_name_attributes (name, nodefs) int nodefs; { SHELL_VAR *var; + int ret; var = find_tempenv_variable (name); if (var == 0) @@ -347,6 +351,8 @@ show_name_attributes (name, nodefs) if (var && invisible_p (var) == 0) { show_var_attributes (var, READONLY_OR_EXPORT, nodefs); + if (tempvar_p (var)) + dispose_variable (var); return (0); } else diff --git a/builtins/shift.def b/builtins/shift.def index 293c31b..cc2a4f2 100644 --- a/builtins/shift.def +++ b/builtins/shift.def @@ -24,6 +24,9 @@ $PRODUCES shift.c #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif diff --git a/builtins/shopt.def b/builtins/shopt.def index bc26a96..762bb42 100644 --- a/builtins/shopt.def +++ b/builtins/shopt.def @@ -38,6 +38,9 @@ $END #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif @@ -59,6 +62,12 @@ extern int no_exit_on_failed_exec, print_shift_error; extern int check_hashed_filenames, promptvars, interactive_comments; extern int cdspelling, expand_aliases; extern int check_window_size; +extern int glob_ignore_case; +extern int hup_on_exit; + +#if defined (EXTENDED_GLOB) +extern int extended_glob; +#endif #if defined (HISTORY) extern int literal_history, command_oriented_history; @@ -89,6 +98,9 @@ static struct { { "dotglob", &glob_dot_filenames, (Function *)NULL }, { "execfail", &no_exit_on_failed_exec, (Function *)NULL }, { "expand_aliases", &expand_aliases, (Function *)NULL }, +#if defined (EXTENDED_GLOB) + { "extglob", &extended_glob, (Function *)NULL }, +#endif #if defined (READLINE) { "histreedit", &history_reediting, (Function *)NULL }, #endif @@ -99,11 +111,13 @@ static struct { { "histverify", &hist_verify, (Function *)NULL }, { "hostcomplete", &perform_hostname_completion, (Function *)enable_hostname_completion }, #endif + { "huponexit", &hup_on_exit, (Function *)NULL }, { "interactive_comments", &interactive_comments, set_interactive_comments }, #if defined (HISTORY) { "lithist", &literal_history, (Function *)NULL }, #endif { "mailwarn", &mail_warning, (Function *)NULL }, + { "nocaseglob", &glob_ignore_case, (Function *)NULL }, { "nullglob", &allow_null_glob_expansion, (Function *)NULL }, { "promptvars", &promptvars, (Function *)NULL }, { "shift_verbose", &print_shift_error, (Function *)NULL }, @@ -166,17 +180,17 @@ shopt_builtin (list) rval = EXECUTION_SUCCESS; if ((flags & OFLAG) && ((flags & (SFLAG|UFLAG)) == 0)) /* shopt -o */ - rval = list_shopt_o_options (list, flags & QFLAG); + rval = list_shopt_o_options (list, flags); else if (list && (flags & OFLAG)) /* shopt -so args */ rval = set_shopt_o_options ((flags & SFLAG) ? FLAG_ON : FLAG_OFF, list, flags & QFLAG); else if (flags & OFLAG) /* shopt -so */ - rval = list_some_o_options ((flags & SFLAG) ? FLAG_ON : FLAG_OFF, flags & QFLAG); + rval = list_some_o_options ((flags & SFLAG) ? 1 : 0, flags); else if (list && (flags & (SFLAG|UFLAG))) /* shopt -su args */ rval = toggle_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, list, flags & QFLAG); else if ((flags & (SFLAG|UFLAG)) == 0) /* shopt [args] */ - rval = list_shopts (list, flags & QFLAG); + rval = list_shopts (list, flags); else /* shopt -su */ - rval = list_some_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, flags & QFLAG); + rval = list_some_shopts ((flags & SFLAG) ? SETOPT : UNSETOPT, flags); return (rval); } @@ -192,6 +206,10 @@ reset_shopt_options () source_uses_path = promptvars = 1; +#if defined (EXTENDED_GLOB) + extended_glob = 0; +#endif + #if defined (HISTORY) literal_history = force_append_history = 0; command_oriented_history = 1; @@ -244,12 +262,23 @@ toggle_shopts (mode, list, quiet) return (rval); } +static int +print_shopt (name, val, flags) + char *name; + int val, flags; +{ + if (flags & PFLAG) + printf ("shopt %s %s\n", val ? "-s" : "-u", name); + else + printf (OPTFMT, name, val ? on : off); +} + /* List the values of all or any of the `shopt' options. Returns 0 if all were listed or all variables queried were on; 1 otherwise. */ static int -list_shopts (list, quiet) +list_shopts (list, flags) WORD_LIST *list; - int quiet; + int flags; { WORD_LIST *l; int i, val, rval; @@ -259,8 +288,8 @@ list_shopts (list, quiet) for (i = 0; shopt_vars[i].name; i++) { val = *shopt_vars[i].value; - if (quiet == 0) - printf (OPTFMT, shopt_vars[i].name, val ? on : off); + if ((flags & QFLAG) == 0) + print_shopt (shopt_vars[i].name, val, flags); } return (EXECUTION_SUCCESS); } @@ -277,39 +306,39 @@ list_shopts (list, quiet) val = *shopt_vars[i].value; if (val == 0) rval = EXECUTION_FAILURE; - if (quiet == 0) - printf (OPTFMT, l->word->word, val ? on : off); + if ((flags & QFLAG) == 0) + print_shopt (l->word->word, val, flags); } return (rval); } static int -list_some_shopts (mode, quiet) - int mode, quiet; +list_some_shopts (mode, flags) + int mode, flags; { int val, i; for (i = 0; shopt_vars[i].name; i++) { val = *shopt_vars[i].value; - if (quiet == 0 && mode == val) - printf (OPTFMT, shopt_vars[i].name, val ? on : off); + if (((flags & QFLAG) == 0) && mode == val) + print_shopt (shopt_vars[i].name, val, flags); } return (EXECUTION_SUCCESS); } static int -list_shopt_o_options (list, quiet) +list_shopt_o_options (list, flags) WORD_LIST *list; - int quiet; + int flags; { WORD_LIST *l; int val, rval; if (list == 0) { - if (quiet == 0) - list_minus_o_opts (-1); + if ((flags & QFLAG) == 0) + list_minus_o_opts (-1, (flags & PFLAG)); return (EXECUTION_SUCCESS); } @@ -324,18 +353,23 @@ list_shopt_o_options (list, quiet) } if (val == 0) rval = EXECUTION_FAILURE; - if (quiet == 0) - printf (OPTFMT, l->word->word, val ? "on" : "off"); + if ((flags & QFLAG) == 0) + { + if (flags & PFLAG) + printf ("set %co %s\n", val ? '-' : '+', l->word->word); + else + printf (OPTFMT, l->word->word, val ? on : off); + } } return (rval); } static int -list_some_o_options (mode, quiet) - int mode, quiet; +list_some_o_options (mode, flags) + int mode, flags; { - if (quiet == 0) - list_minus_o_opts (mode); + if ((flags & QFLAG) == 0) + list_minus_o_opts (mode, (flags & PFLAG)); return (EXECUTION_SUCCESS); } diff --git a/builtins/source.def b/builtins/source.def index 1bb3e73..8979f0b 100644 --- a/builtins/source.def +++ b/builtins/source.def @@ -41,7 +41,9 @@ $END #include "../bashtypes.h" #include "../posixstat.h" #include "../filecntl.h" -#include +#ifndef _MINIX +# include +#endif #include #if defined (HAVE_UNISTD_H) @@ -51,7 +53,7 @@ $END #include "../bashansi.h" #include "../shell.h" -#include "../execute_cmd.h" +#include "../findcmd.h" #include "common.h" #if !defined (errno) diff --git a/builtins/suspend.def b/builtins/suspend.def index 82ec71b..3e949ba 100644 --- a/builtins/suspend.def +++ b/builtins/suspend.def @@ -34,6 +34,9 @@ $END #if defined (JOB_CONTROL) #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif diff --git a/builtins/test.def b/builtins/test.def index 03de47d..eded0fa 100644 --- a/builtins/test.def +++ b/builtins/test.def @@ -50,9 +50,10 @@ File operators: -x FILE True if the file is executable by you. -O FILE True if the file is effectively owned by you. -G FILE True if the file is effectively owned by your group. + -N FILE True if the file has been modified since it was last read. - FILE1 -nt FILE2 True if file1 is newer than (according to - modification date) file2. + FILE1 -nt FILE2 True if file1 is newer than file2 (according to + modification date). FILE1 -ot FILE2 True if file1 is older than file2. @@ -70,12 +71,13 @@ String operators: STRING1 != STRING2 True if the strings are not equal. STRING1 < STRING2 - True if STRING1 sorts before STRING2 lexicographically + True if STRING1 sorts before STRING2 lexicographically. STRING1 > STRING2 - True if STRING1 sorts after STRING2 lexicographically + True if STRING1 sorts after STRING2 lexicographically. Other operators: + -o OPTION True if the shell option OPTION is enabled. ! EXPR True if expr is false. EXPR1 -a EXPR2 True if both expr1 AND expr2 are true. EXPR1 -o EXPR2 True if either expr1 OR expr2 is true. @@ -99,12 +101,16 @@ $END #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif #include "../bashansi.h" #include "../shell.h" +#include "../test.h" #include "common.h" extern char *this_command_name; diff --git a/builtins/times.def b/builtins/times.def index 216abcb..630642c 100644 --- a/builtins/times.def +++ b/builtins/times.def @@ -31,6 +31,9 @@ $END #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif @@ -53,7 +56,7 @@ $END # include #endif /* HAVE_SYS_TIMES_H */ -#if defined (HAVE_SYS_RESOURCE_H) +#if defined (HAVE_SYS_RESOURCE_H) && !defined (RLIMTYPE) # include #endif diff --git a/builtins/trap.def b/builtins/trap.def index 252a1db..522e2a4 100644 --- a/builtins/trap.def +++ b/builtins/trap.def @@ -42,6 +42,9 @@ $END #include #if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif # include #endif diff --git a/builtins/type.def b/builtins/type.def index 3af018f..93c8ff8 100644 --- a/builtins/type.def +++ b/builtins/type.def @@ -27,20 +27,18 @@ $SHORT_DOC type [-apt] name [name ...] For each NAME, indicate how it would be interpreted if used as a command name. -If the -t option is used, returns a single word which is one of +If the -t option is used, `type' outputs a single word which is one of `alias', `keyword', `function', `builtin', `file' or `', if NAME is an alias, shell reserved word, shell function, shell builtin, disk file, or unfound, respectively. -If the -p flag is used, either returns the name of the disk file -that would be executed, or nothing if -t would not return `file'. +If the -p flag is used, `type' either returns the name of the disk +file that would be executed, or nothing if `type -t NAME' would not +return `file'. -If the -a flag is used, displays all of the places that contain an -executable named `file'. This includes aliases and functions, if and -only if the -p flag is not also used. - -Type accepts -all, -path, and -type in place of -a, -p, and -t, -respectively. +If the -a flag is used, `type' displays all of the places that contain +an executable named `file'. This includes aliases and functions, if +and only if the -p flag is not also used. $END #include @@ -56,7 +54,7 @@ $END #include "../bashansi.h" #include "../shell.h" -#include "../execute_cmd.h" +#include "../findcmd.h" #include "../hashcmd.h" #if defined (ALIAS) diff --git a/builtins/ulimit.def b/builtins/ulimit.def index 3cdf26a..bbeb7c9 100644 --- a/builtins/ulimit.def +++ b/builtins/ulimit.def @@ -23,7 +23,7 @@ $PRODUCES ulimit.c $BUILTIN ulimit $FUNCTION ulimit_builtin -$DEPENDS_ON !MINIX +$DEPENDS_ON !_MINIX $SHORT_DOC ulimit [-SHacdflmnpstuv] [limit] Ulimit provides control over the resources available to processes started by the shell, on systems that allow such control. If an @@ -52,10 +52,14 @@ increments of 512 bytes, and -u, which is an unscaled number of processes. $END +#if !defined (_MINIX) + #include #include "../bashtypes.h" -#include +#ifndef _MINIX +# include +#endif #if defined (HAVE_UNISTD_H) # include @@ -101,7 +105,7 @@ extern int errno; #if !defined (RLIMTYPE) # define RLIMTYPE long -# define string_to_rlimtype string_to_long +# define string_to_rlimtype(s) strtol(s, (char **)NULL, 10) # define print_rlimtype(num, nl) printf ("%ld%s", num, nl ? "\n" : "") #endif @@ -597,7 +601,8 @@ printone (limind, curlim, pdesc) if (curlim == RLIM_INFINITY) puts ("unlimited"); else if (curlim == RLIM_INVALID) - printf ("cannot get limit: %s\n", strerror (errno)); + builtin_error ("cannot get limit: %s\n", strerror (errno)); else print_rlimtype ((curlim / limits[limind].block_factor), 1); } +#endif /* !_MINIX */ diff --git a/builtins/umask.def b/builtins/umask.def index 85bf220..f734113 100644 --- a/builtins/umask.def +++ b/builtins/umask.def @@ -23,19 +23,23 @@ $PRODUCES umask.c $BUILTIN umask $FUNCTION umask_builtin -$SHORT_DOC umask [-S] [mode] +$SHORT_DOC umask [-p] [-S] [mode] The user file-creation mask is set to MODE. If MODE is omitted, or if `-S' is supplied, the current value of the mask is printed. The `-S' option makes the output symbolic; otherwise an octal number is output. -If MODE begins with a digit, it is interpreted as an octal number, -otherwise it is a symbolic mode string like that accepted by chmod(1). +If `-p' is supplied, and MODE is omitted, the output is in a form +that may be used as input. If MODE begins with a digit, it is +interpreted as an octal number, otherwise it is a symbolic mode string +like that accepted by chmod(1). $END #include #include "../bashtypes.h" #include "../filecntl.h" -#include +#ifndef _MINIX +# include +#endif #if defined (HAVE_UNISTD_H) #include @@ -63,18 +67,21 @@ int umask_builtin (list) WORD_LIST *list; { - int print_symbolically, opt, umask_value; + int print_symbolically, opt, umask_value, pflag; mode_t umask_arg; - print_symbolically = 0; + print_symbolically = pflag = 0; reset_internal_getopt (); - while ((opt = internal_getopt (list, "S")) != -1) + while ((opt = internal_getopt (list, "Sp")) != -1) { switch (opt) { case 'S': print_symbolically++; break; + case 'p': + pflag++; + break; default: builtin_usage (); return (EX_USAGE); @@ -116,6 +123,8 @@ umask_builtin (list) umask_arg = umask (022); umask (umask_arg); + if (pflag) + printf ("umask%s ", (print_symbolically ? " -S" : "")); if (print_symbolically) print_symbolic_umask (umask_arg); else diff --git a/builtins/wait.def b/builtins/wait.def index 741ff5c..11fe85a 100644 --- a/builtins/wait.def +++ b/builtins/wait.def @@ -136,6 +136,12 @@ wait_builtin (list) UNBLOCK_CHILD (oset); status = wait_for_job (job); } + else if (job_control == 0 && *w == '%') + { + /* can't use jobspecs as arguments if job control is not active. */ + builtin_error ("job control not enabled"); + status = EXECUTION_FAILURE; + } #endif /* JOB_CONTROL */ else { -- cgit v1.2.3