fix for %P in TIMEFORMAT; make updating variables that aren't subject to allexport smoother; fix spurious compiler warning about realloc; efficiency improvement for command timing; fix issue with read builtin and failure to set terminal attributes

This commit is contained in:
Chet Ramey
2025-10-06 15:29:41 -04:00
parent 4f536430e4
commit f2f545ad7b
11 changed files with 118 additions and 80 deletions
+49
View File
@@ -11862,3 +11862,52 @@ parse.y
- 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>
+2 -4
View File
@@ -622,8 +622,7 @@ read_builtin (WORD_LIST *list)
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);
@@ -639,8 +638,7 @@ read_builtin (WORD_LIST *list)
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;
+5 -14
View File
@@ -532,7 +532,7 @@ set_shellopts (void)
{
char *value;
char tflag[N_O_OPTIONS];
int i, *ip, exported;
int i, *ip;
size_t vsize, vptr;
SHELL_VAR *v;
@@ -571,21 +571,12 @@ set_shellopts (void)
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);
}
+4 -11
View File
@@ -823,7 +823,7 @@ set_bashopts (void)
{
char *value;
char tflag[N_SHOPT_OPTIONS];
int i, exported;
int i;
size_t vsize, vptr;
SHELL_VAR *v;
@@ -853,21 +853,14 @@ set_bashopts (void)
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);
}
+4
View File
@@ -2513,6 +2513,10 @@ A filename whose suffix matches one of the entries in
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
+7 -2
View File
@@ -7174,8 +7174,13 @@ A colon-separated list of suffixes to ignore when performing
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
+31 -38
View File
@@ -1408,7 +1408,7 @@ print_formatted_time (FILE *fp, char *format,
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);
@@ -1468,9 +1468,6 @@ time_command (COMMAND *command, int asynchronous, int pipe_in, int pipe_out, str
#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)
@@ -1479,24 +1476,28 @@ time_command (COMMAND *command, int asynchronous, int pipe_in, int pipe_out, str
# 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)
@@ -1508,35 +1509,27 @@ time_command (COMMAND *command, int asynchronous, int pipe_in, int pipe_out, str
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);
+4
View File
@@ -119,6 +119,10 @@ static const unsigned long long int maxquad = ULLONG_MAX;
# 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
+7 -7
View File
@@ -47,7 +47,7 @@
#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"
@@ -2579,21 +2579,21 @@ shell_getc (int remove_quoted_newline)
/* 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);
}
}
@@ -2735,7 +2735,7 @@ shell_getc (int remove_quoted_newline)
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));
+2 -1
View File
@@ -45,7 +45,7 @@
/* 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 */
@@ -59,6 +59,7 @@
#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 */
+3 -3
View File
@@ -3166,7 +3166,7 @@ assign_value:
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))
@@ -3208,7 +3208,7 @@ assign_value:
}
}
if (mark_modified_vars)
if (mark_modified_vars && (aflags & ASS_NOEXPORT) == 0)
VSETATTR (entry, att_exported);
if (exported_p (entry))
@@ -3363,7 +3363,7 @@ bind_variable_value (SHELL_VAR *var, char *value, int aflags)
INVALIDATE_EXPORTSTR (var);
if (mark_modified_vars)
if (mark_modified_vars && (aflags & ASS_NOEXPORT) == 0)
VSETATTR (var, att_exported);
if (exported_p (var))