- reset_parser: reset shell_eof_token to 0, rely on callers to restore
it if they need to
Report from Grisha Levit <grishalevit@gmail.com>
+
+execute_cmd.c
+ - print_formatted_time: when processing %P, sum_frac should be in
+ microseconds; missed when making max precision 6 back in 6/2023
+ Report from pourko2@tutamail.com
+
+ 9/30
+ ----
+subst.h
+ - ASS_NOEXPORT: don't export the variable being assigned even if
+ `allexport' is enabled
+
+builtins/set.def
+ - set_shellopts: pass ASS_NOEXPORT so we don't have to mess with
+ unsetting the export attribute
+
+builtins/shopt.def
+ - set_bashopts: pass ASS_NOEXPORT so we don't have to mess with
+ unsetting the export attribute
+
+variables.c
+ - bind_variable_internal,bind_variable_value: if ASS_NOEXPORT is set in
+ the flags argument, don't export the variable even if `allexport'
+ (mark_modified_vars) is set.
+ Patch from Martin D Kealey <martin@kurahaupo.gen.nz>
+
+ 10/1
+ ----
+include/typemax.h
+ - PTRDIFF_MAX: add default max value for ptrdiff_t if the system
+ doesn't provide one
+
+parse.y
+ - SIZE_MAX -> PTRDIFF_MAX to avoid spurious compiler warning
+ Patch from Martin D Kealey <martin@kurahaupo.gen.nz> and
+ Grisha Levit <grishalevit@gmail.com>
+
+execute_cmd.c
+ - time_command: don't bother with time zone info in gettimeofday()
+ - time_command: don't bother trying to execute a null command in
+ posix mode, since we just want timing information since the shell
+ started
+
+ 10/3
+ ----
+builtins/read.def
+ - read_builtin: don't use i as a return value for functions and then
+ as an index into input_string without resetting it
+ Report and patch from Grisha Levit <grishalevit@gmail.com>
termsave.attrs = ttattrs;
ttset = ttattrs;
- i = silent ? ttfd_cbreak (fd, &ttset) : ttfd_onechar (fd, &ttset);
- if (i < 0)
+ if ((silent ? ttfd_cbreak (fd, &ttset) : ttfd_onechar (fd, &ttset)) < 0)
sh_ttyerror (1);
tty_modified = 1;
add_unwind_protect (uw_ttyrestore, &termsave);
termsave.attrs = ttattrs;
ttset = ttattrs;
- i = ttfd_noecho (fd, &ttset); /* ttnoecho (); */
- if (i < 0)
+ if (ttfd_noecho (fd, &ttset) < 0)
sh_ttyerror (1);
tty_modified = 1;
{
char *value;
char tflag[N_O_OPTIONS];
- int i, *ip, exported;
+ int i, *ip;
size_t vsize, vptr;
SHELL_VAR *v;
vptr--; /* cut off trailing colon */
value[vptr] = '\0';
- v = find_variable ("SHELLOPTS");
+ /* ASS_FORCE so we don't have to temporarily turn off readonly; ASS_NOEXPORT
+ so we don't have to work around allexport. */
+ v = bind_variable ("SHELLOPTS", value, ASS_FORCE|ASS_NOEXPORT);
- /* Note whether or not the variable was exported so we can adjust after the
- assignment. */
- exported = v ? exported_p (v) : 0;
-
- /* ASS_FORCE so we don't have to temporarily turn off readonly */
- v = bind_variable ("SHELLOPTS", value, ASS_FORCE);
-
- /* 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. */
+ /* Turn the read-only attribute back on. */
VSETATTR (v, att_readonly);
- if (mark_modified_vars && exported == 0 && exported_p (v))
- VUNSETATTR (v, att_exported);
free (value);
}
{
char *value;
char tflag[N_SHOPT_OPTIONS];
- int i, exported;
+ int i;
size_t vsize, vptr;
SHELL_VAR *v;
vptr--; /* cut off trailing colon */
value[vptr] = '\0';
- v = find_variable ("BASHOPTS");
-
- /* Note whether or not the variable was exported so we can adjust after the
- assignment. */
- exported = v ? exported_p (v) : 0;
-
- /* ASS_FORCE so we don't have to temporarily turn off readonly */
- v = bind_variable ("BASHOPTS", value, ASS_FORCE);
+ /* ASS_FORCE so we don't have to temporarily turn off readonly; ASS_NOEXPORT
+ so we don't have to work around allexport. */
+ v = bind_variable ("BASHOPTS", value, ASS_FORCE|ASS_NOEXPORT);
/* 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. */
VSETATTR (v, att_readonly);
- if (mark_modified_vars && exported == 0 && exported_p (v))
- VUNSETATTR (v, att_exported);
free (value);
}
is excluded from the list of matched filenames.
A sample value is
.Q .o:\*~ .
+Since tilde expansion takes place after
+.Q :
+in assignment statements,
+make sure to quote assignments appropriately to avoid it as appropriate.
.TP
.B FUNCNEST
If set to a numeric value greater than 0, defines a maximum function
filename completion.
A filename whose suffix matches one of the entries in
@env{FIGNORE}
-is excluded from the list of matched filenames. A sample
-value is @samp{.o:~}
+is excluded from the list of matched filenames.
+A sample value is
+@samp{.o:~}.
+Since tilde expansion takes place after
+@samp{:}
+in assignment statements,
+make sure to quote assignments appropriately to avoid it as appropriate.
@item FUNCNAME
An array variable containing the names of all shell functions
cpu = 10000;
#endif
sum = cpu / 100;
- sum_frac = (cpu % 100) * 10;
+ sum_frac = (cpu % 100) * 10000; /* convert to microseconds */
len = mkfmt (ts, 2, 0, sum, sum_frac);
RESIZE_MALLOCED_BUFFER (str, sindex, len, ssize, 64);
strcpy (str + sindex, ts);
#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
struct timeval real, user, sys;
struct timeval before, after;
-# if defined (HAVE_STRUCT_TIMEZONE)
- struct timezone dtz; /* posix doesn't define this */
-# endif
struct rusage selfb, selfa, kidsb, kidsa; /* a = after, b = before */
#else
# if defined (HAVE_TIMES)
# endif
#endif
+ rv = EXECUTION_SUCCESS; /* suppress uninitialized use warnings */
+
+ rs = us = ss = 0;
+ rsf = usf = ssf = 0;
+ cpu = 0;
+
+ old_subshell = subshell_environment;
+ posix_time = command && (command->flags & CMD_TIME_POSIX);
+ nullcmd = (command == 0) || (command->type == cm_simple && command->value.Simple->words == 0 && command->value.Simple->redirects == 0);
+
#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
-# if defined (HAVE_STRUCT_TIMEZONE)
- gettimeofday (&before, &dtz);
-# else
- gettimeofday (&before, NULL);
-# endif /* !HAVE_STRUCT_TIMEZONE */
getrusage (RUSAGE_SELF, &selfb);
getrusage (RUSAGE_CHILDREN, &kidsb);
+ gettimeofday (&before, NULL);
#else
# if defined (HAVE_TIMES)
tbefore = times (&before);
# endif
#endif
- old_subshell = subshell_environment;
- posix_time = command && (command->flags & CMD_TIME_POSIX);
-
- nullcmd = (command == 0) || (command->type == cm_simple && command->value.Simple->words == 0 && command->value.Simple->redirects == 0);
+ /* In posix mode, `time' without argument is equivalent to `times', but
+ obeys TIMEFORMAT. This is from POSIX interp 267 */
if (posixly_correct && nullcmd)
{
#if defined (HAVE_GETRUSAGE)
tbefore = shell_start_time * get_clk_tck ();
#endif
}
+ else
+ {
+ old_flags = command->flags;
+ COPY_PROCENV (top_level, save_top_level);
+ command->flags &= ~(CMD_TIME_PIPELINE|CMD_TIME_POSIX);
+ code = setjmp_nosigs (top_level);
+ if (code == NOT_JUMPED)
+ rv = execute_command_internal (command, asynchronous, pipe_in, pipe_out, fds_to_close);
+ COPY_PROCENV (save_top_level, top_level);
+ if (code == NOT_JUMPED)
+ command->flags = old_flags;
- rv = EXECUTION_SUCCESS; /* suppress uninitialized use warnings */
- old_flags = command->flags;
- COPY_PROCENV (top_level, save_top_level);
- command->flags &= ~(CMD_TIME_PIPELINE|CMD_TIME_POSIX);
- code = setjmp_nosigs (top_level);
- if (code == NOT_JUMPED)
- rv = execute_command_internal (command, asynchronous, pipe_in, pipe_out, fds_to_close);
- COPY_PROCENV (save_top_level, top_level);
-
- if (code == NOT_JUMPED)
- command->flags = old_flags;
-
- /* If we're jumping in a different subshell environment than we started,
- don't bother printing timing stats, just keep longjmping back to the
- original top level. */
- if (code != NOT_JUMPED && subshell_environment && subshell_environment != old_subshell)
- sh_longjmp (top_level, code);
-
- rs = us = ss = 0;
- rsf = usf = ssf = 0;
- cpu = 0;
+ /* If we're jumping in a different subshell environment than we started,
+ don't bother printing timing stats, just keep longjmping back to the
+ original top level. */
+ if (code != NOT_JUMPED && subshell_environment && subshell_environment != old_subshell)
+ sh_longjmp (top_level, code);
+ }
#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
-# if defined (HAVE_STRUCT_TIMEZONE)
- gettimeofday (&after, &dtz);
-# else
gettimeofday (&after, NULL);
-# endif /* !HAVE_STRUCT_TIMEZONE */
getrusage (RUSAGE_SELF, &selfa);
getrusage (RUSAGE_CHILDREN, &kidsa);
# define SIZE_MAX ((size_t) ~(size_t)0)
#endif
+#ifndef PTRDIFF_MAX
+# define PTRDIFF_MAX TYPE_MAXIMUM(ptrdiff_t)
+#endif
+
#ifndef sh_imaxabs
# define sh_imaxabs(x) (((x) >= 0) ? (x) : -(x))
#endif
#include "shell.h"
#include "execute_cmd.h"
-#include "typemax.h" /* SIZE_MAX if needed */
+#include "typemax.h" /* PTRDIFF_MAX if needed */
#include "trap.h"
#include "flags.h"
#include "parser.h"
/* If we can't put 256 bytes more into the buffer, allocate
everything we can and fill it as full as we can. */
/* XXX - we ignore rest of line using `truncating' flag */
- if (shell_input_line_size > (SIZE_MAX - 256))
+ if (shell_input_line_size > (PTRDIFF_MAX - 256))
{
size_t n;
- n = SIZE_MAX - i; /* how much more can we put into the buffer? */
+ n = PTRDIFF_MAX - i; /* how much more can we put into the buffer? */
if (n <= 2) /* we have to save 1 for the newline added below */
{
if (truncating == 0)
- internal_warning(_("shell_getc: shell_input_line_size (%zu) exceeds SIZE_MAX (%lu): line truncated"), shell_input_line_size, (unsigned long)SIZE_MAX);
+ internal_warning(_("shell_getc: shell_input_line_size (%zu) exceeds PTRDIFF_MAX (%lu): line truncated"), shell_input_line_size, (unsigned long)PTRDIFF_MAX);
shell_input_line[i] = '\0';
truncating = 1;
}
- if (shell_input_line_size < SIZE_MAX)
+ if (shell_input_line_size < PTRDIFF_MAX)
{
- shell_input_line_size = SIZE_MAX;
+ shell_input_line_size = PTRDIFF_MAX;
shell_input_line = xrealloc (shell_input_line, shell_input_line_size);
}
}
not already end in an EOF character. */
if (shell_input_line_terminator != EOF && shell_input_line_terminator != READERR)
{
- if (shell_input_line_size + 3 < SIZE_MAX && (shell_input_line_len+3 > shell_input_line_size))
+ if (shell_input_line_size + 3 < PTRDIFF_MAX && (shell_input_line_len+3 > shell_input_line_size))
shell_input_line = (char *)xrealloc (shell_input_line,
1 + (shell_input_line_size += 2));
/* Flag values controlling how assignment statements are treated. */
#define ASS_APPEND 0x0001 /* a+=b */
-#define ASS_MKLOCAL 0x0002
+#define ASS_MKLOCAL 0x0002 /* make a local variable */
#define ASS_MKASSOC 0x0004
#define ASS_MKGLOBAL 0x0008 /* force global assignment */
#define ASS_NAMEREF 0x0010 /* assigning to nameref variable */
#define ASS_ONEWORD 0x1000 /* don't check array subscripts, assume higher level has done that */
#define ASS_NOTEMPENV 0x2000 /* don't assign into temporary environment */
#define ASS_XTRACE 0x4000 /* print trace after compound assignment expansion */
+#define ASS_NOEXPORT 0x8000 /* don't export even if allexport is set */
/* Flags for the string extraction functions. */
#define SX_NOALLOC 0x0001 /* just skip; don't return substring */
INVALIDATE_EXPORTSTR (entry);
optimized_assignment (entry, value, aflags);
- if (mark_modified_vars)
+ if (mark_modified_vars && (aflags & ASS_NOEXPORT) == 0)
VSETATTR (entry, att_exported);
if (exported_p (entry))
}
}
- if (mark_modified_vars)
+ if (mark_modified_vars && (aflags & ASS_NOEXPORT) == 0)
VSETATTR (entry, att_exported);
if (exported_p (entry))
INVALIDATE_EXPORTSTR (var);
- if (mark_modified_vars)
+ if (mark_modified_vars && (aflags & ASS_NOEXPORT) == 0)
VSETATTR (var, att_exported);
if (exported_p (var))