On Mon, Oct 17, 2016 at 08:38:29PM +0200, Martijn Dekker wrote:
[...]
The BASHPID variable is initialized with null_assign as its "assign_func". The
default value for this attribute in newly created variables is NULL.
The problem here is caused by the following code from variables.c (function is
bind_variable_internal):
2753 else if (entry->assign_func) /* array vars have assign functions
now */
2754 {
2755 INVALIDATE_EXPORTSTR (entry);
2756 newval = (aflags & ASS_APPEND) ? make_variable_value (entry,
value, aflags) : value;
2757 if (assoc_p (entry))
2758 entry = (*(entry->assign_func)) (entry, newval, -1, savestring
("0"));
2759 else if (array_p (entry))
2760 entry = (*(entry->assign_func)) (entry, newval, 0, 0);
2761 else
2762 entry = (*(entry->assign_func)) (entry, newval, -1, 0);
2763 if (newval != value)
2764 free (newval);
2765 return (entry);
2766 }
2767 else
2768 {
2769 assign_value:
2770 if ((readonly_p (entry) && (aflags & ASS_FORCE) == 0) ||
noassign_p (entry))
2771 {
2772 if (readonly_p (entry))
2773 err_readonly (name_cell (entry));
2774 return (entry);
2775 }
2776
2777 /* Variables which are bound are visible. */
2778 VUNSETATTR (entry, att_invisible);
If a variable has a non-NULL assign_func, it will not run the readonly_p
(entry) check, and therefore, no error message is printed. I'm not sure why the
code exits, but it seems clear to me that the assign_func should be NULL in
this case.
I attach a patch with the "fix" (disclaimer, I'm not sure this is the proper
fix, that's for Chet to decide).
Patched bash:
dualbus@yaqui:~/local/src/gnu/bash$ ./bash -c 'BASHPID=1; echo $?'
./bash: BASHPID: readonly variable
--
Eduardo Bustamante
https://dualbus.me/
diff --git a/variables.c b/variables.c
index 2e8b38c..8cd5f58 100644
--- a/variables.c
+++ b/variables.c
@@ -1766,7 +1766,7 @@ initialize_dynamic_variables ()
INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno);
VSETATTR (v, att_integer);
- INIT_DYNAMIC_VAR ("BASHPID", (char *)NULL, get_bashpid, null_assign);
+ INIT_DYNAMIC_VAR ("BASHPID", (char *)NULL, get_bashpid,
(sh_var_assign_func_t *)NULL);
VSETATTR (v, att_integer|att_readonly);
#if defined (HISTORY)