bash using unknown tmp - library based? static link on linux? (was Re: bash not using pipes or /tmp @ boot?)

2014-10-07 Thread Linda Walsh



Chet Ramey wrote:

On 10/6/14, 6:03 PM, Linda Walsh wrote:

Not sure how but this went off into space, sorta...

Greg Wooledge wrote:

On Mon, Oct 06, 2014 at 12:14:57PM -0700, Linda Walsh wrote:

   done <<<"$(get_net_IFnames_hwaddrs)"
Where am I using a HERE doc?

<<< and << both create temporary files.



Yeah... where?


Wherever $TMPDIR says to.  If $TMPDIR doesn't name a writable directory,
bash looks for various system definitions (P_tmpdir), finally defaulting
to /tmp or /var/tmp.


P_tmpdir?  in ENV?

I don't have TMP or TMPDIR in my env during normal runtime
and tmp's were put in /tmp... I don't know where they were going
@ boot time, as /tmp and /var/tmp were writeable, but still
TMP/TMPDIR were unset.  (anyway -- went back to the process substitution)
since that actually worked -- when trying to debug it earlier, it was
thought that might be the problem... but it *seemed* to be a local
redefinition of a global -- which actually doesn't make complete sense, as
the script worked interactively.

Hmmm...oh well... even if /var/tmp and /tmp were not mounted,
bash running as root could still create files in it so not
sure what the problem was.






Maybe if bash didn't create tmp files in non-standard locations,
this never would have been an issue (or just use pipes)..


Please.  Your assumptions about what is going on make your conclusions
shaky at best.


Um...assumptions were that tmp files weren't getting created
in standard locations of /tmp or /var/tmp for unknown reasons.  Interactively
and @ run time, it works fine... it's probably some library bash is linking
with...

speaking of which ... does anyone have static link working on linux these days,
or is the static link break a suse-special?  I wanted  a safe shell to put
on root, since the way things are going, I'm expecting bash to be the next
piece of software that has to be merged with systemd...






Re: "export -p" output not suitable for input when env vars contain non-identifiers

2014-10-07 Thread Chet Ramey
On 10/7/14, 12:28 PM, Stephane Chazelas wrote:

> Since those environment variables cannot be mapped to shell
> variables, they should not be included in the output of "export
> -p".

Thanks.  This will be fixed in the next release of bash.

> I can see there are a number of bugs at savannah
> (https://savannah.gnu.org/support/?group=bash), but not much
> activity on those bugs. Is that in use? Is it worth me adding an
> entry there?

I don't look there very often.  This mailing list is the best way
to report bugs.

Chet
-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: Bash-4.3 Official Patch 30

2014-10-07 Thread Chet Ramey
On 10/7/14, 6:31 PM, Ángel González wrote:

>>> Changing it to return 0 instead of '\0' would probably be more clear.
>>> No need to return a pointer to a static empty string.
>>
>> It depends on how you want the function to work.  It is nice to
>> differentiate between the cases where there is no shell input line
>> at all, where the index is just wrong, and the actual current input
>> pointer.  A "" indicates the second case better than a 0, though it's
>> not perfect.
>>
>> Chet
> 
> 
> Note it **is** returning NULL, not "" as it seemed implied by earlier
> messages. Only verified gcc (4.9.1) behavior, but that's also what I
> expected from the C code:  '\0' (char) promoted to 0 (int), then to 
> NULL (char*)

Yes, that's right.  The question is whether that case of the index out
of bounds should continue to return NULL, but in a clearer way, or
return "" to differentiate it from the case where shell_input_line is
NULL.


-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: bash uses tmp files for inter-process communication instead of pipes?

2014-10-07 Thread Chet Ramey
On 10/7/14, 5:35 PM, Linda Walsh wrote:
> 
> 
> Chet Ramey wrote:
>> On 10/7/14, 1:45 PM, Linda Walsh wrote:
>>
>>> There is no fundamental reason why, say, process substitution needs to
>>> use /dev/fd or /proc/anything -- and couldn't operate exactly like piped
>>> processes do now.  On my first implementation of multiple IPC programs,
>>> I've used semaphores, message queues, named pipes, and shared memory.
>>> With the exception of using shared memory for mutiple megabytes of
>>> memory for each of several children, pipes provided equal or better
>>> performance.
>>
>> I think you have a fundamental misunderstanding of the purpose of
>> process substitution.  It is a way to turn a pipe to another process
>> into a file name, so that you can open what looks like a file,
> 
> You mean "< <(process)" is the part you are saying looks like a file?
> 
> If it wasn't for the shell mangling eoln's why wouldn't <$(process) be the
> same?

OK.  Let's take a step back.  <(process) expands to a file name like
/dev/fd/26.  When you open that file for reading, you can read the output
of the process.  If you open it for writing, using the >(process) syntax,
you can write to the process's stdin.  This can be asynchronous, not
synchronous like pipes, and, since it can be combined with `exec' and a
redirection, you can save the file descriptor for later use.  In other
words, you can treat dynamically-generated data like a file.  That
filename isn't private to the shell; it can be used as an argument to
another program.

$(process) expands directly to the output of `process'.  Instead of
being able to read and process that data, it appears on the command line
as an expanded word.  You could make `process' output a filename that
the redirection opens, but that's not the same thing as dynamically
generating the data.

> Or are you saying that the shell not mangling eoln's is a way of making it
> look like a filei that you can use the normal set of !!!WRITE!!!...
> calls I can write to such a process?

This doesn't make any sense.

> 
> But I never got that < <(process) was anything more than a one way read
> from the
> right-hand process into the left -- and was not any different than
> (process)|  where left hand process feeds into the right hand process.
> 
> I.e. both looked like unidirectional communication over a pipe.

They are superficially simimlar.  The < redirection is what makes it a
`one-way read'.  That's not the only thing you can do with a process
substitution.

> Both being cases where you can write to a process through a pipe.  I've
> used FIFO's but other than making it a bit easier to parse lines, they
> weren't much different than pipes -- which get parsed into lines all the time
> over the net et al.

Pipes are synchronous and anonymous.  Process substitution creates a
usable filename that you can use to communicate asynchronously with a
process.  They can be made to do the same thing, but are different.

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: Bash-4.3 Official Patch 30

2014-10-07 Thread Ángel González
Chet Ramey wrote:
> On 10/6/14, 6:16 PM, John E. Malmberg wrote:
> 
> >>> Do you mean return ""; ?
> >>
> >> Yes, good catch.  It doesn't make a difference: clang and gcc both accept
> >> it as written and it behaves as desired.  However, I'll change it for the
> >> next version.
> > 
> > Changing it to return 0 instead of '\0' would probably be more clear.
> > No need to return a pointer to a static empty string.
> 
> It depends on how you want the function to work.  It is nice to
> differentiate between the cases where there is no shell input line
> at all, where the index is just wrong, and the actual current input
> pointer.  A "" indicates the second case better than a 0, though it's
> not perfect.
> 
> Chet


Note it **is** returning NULL, not "" as it seemed implied by earlier
messages. Only verified gcc (4.9.1) behavior, but that's also what I
expected from the C code:  '\0' (char) promoted to 0 (int), then to 
NULL (char*)


Regards


> #include 
> 
> char *
> foo()
> {
>   return '\0';
> }
> 
> int main()
> {
>   printf("The value is: %p\n", foo());
>   return 0;
> }

Output:
> (nil)




Re: bash uses tmp files for inter-process communication instead of pipes?

2014-10-07 Thread Linda Walsh

Pierre Gaston wrote:

That's where you are wrong, there is no reason for *your* use case, but the
basic idea behind process substitution is to be able to use a pipe in a
place where you normally need a file name.
  
Well, that's not what I needed it for.  I needed to read from a child 
process that
changed directories. 


How can you say there is no reason for my use case...

It's not thoroughly  polished yet, but it does work.  It can rename and 
reorder your

network interfaces on boot so you can keep them with consistent names and
ordering -- something systemd doesn't seem to support.  Furthermore, it
doesn't depend on any suse library code -- which they've been putting in
hooks and traps for those not using systemd.  Supposedly people not using
systemd won't be able to boot their systems. 

This is one of my side projects to keep my system booting and to make 
available

to anyone who might want to use it.  But you call that no reason?

Sigh.

IF you want to see what I was doing in context, its attached.
It's a stand alone script to tell you if your interfaces are in your
desired order, reorder them if you wish, and act as a startup/shutdown 
script
to fix things each boot.  I haven't spent any time in cleanup, but it's 
still

not bad code.  See if the code is not readable -- even for shell!




#!/bin/bash 
#boot.assign_network_names
### BEGIN INIT INFO
# Provides:   net-devices
# Required-Start: boot.udev boot.device-mapper boot.localfs
# Required-Stop:  $null   
# Default-Start:   B
# Default-Stop:
# Short-Description:   reorder and rename net devices
# Description: reorder and rename net devs if needed
### END INIT INFO
#
# assign network names as rc-script
#   L A Walsh, (free to use/modify/distribute to nice people) (c) 2013-2014
#  
#include standard template:
_prgpth=${0:?}; _prgpth=${_prgpth#-} _prg=${_prgpth##*/}; 
_prgdr=${_prgpth%/$_prg}
[[ -z $_prgdr || $_prg == $_prgdr ]] && _prgdr="$PWD"
#if ! typeset -f include >&/dev/null ;then 
#   source ${_LOCAL_DIR:=/etc/local}/bash_env.sh;
#fi
export PATH="/etc/local/bin:/etc/local/lib:$PATH"
export 
PS4='>>${BASH_SOURCE:+${BASH_SOURCE[0]}}#${LINENO}${FUNCNAME:+(${FUNCNAME[0]})}>
 '


#include stdalias (needed entries included "inline", below)
shopt -s extglob expand_aliases

alias dcl=declare   sub=function 
alias int=dcl\ -i   map=dcl\ -A 
hash=dcl\ -Aarray=dcl\ -a
alias lower=dcl\ -l upper=dcl\ -u   
string=dcl  my=dcl
alias map2int=dcl\ -Ai  intArray=dcl\ -ia

cfg_fn="/etc/sysconfig/assign_netif_names"

[[ -f $cfg_fn ]] || {
echo "Cannot find required config file: $cfg_fn"; exit 1; }

# expected variables to be read in
array needed_drivers
array Linknames
array Default
map if2hw

. $cfg_fn || { echo "Error in reading config file $cfg_fn"; exit 2; }

DfltRE="^+(${Default_good[@]})$"
DfltRE=${DfltRE// /|}

declare -a down_ln=()
for ln in "${Linknames[@]}"; do
[[ $DfltRE =~ $ln ]] && continue;
down_ln+=($ln)
done

map hw2if

for intf in "${!if2hw[@]}" ; do
addr=${if2hw[$intf]}
hw2if[$addr]="$intf"
done


# end read config ##

#include rc.status  -- essential funcs included below:
int rc_status=0
sub rc_reset { rc_status=0; }

sub rc_status { 
rc_status=$?;
if ((rc_status))  && { (($#)) && [[ $1 = -v ]] ; }; then
echo "Abnormal rc_status was $rc_status." 
elif (($#)) && [[ $1 = -v ]] ; then
echo "rc_status: ok"
fi
}

sub rc_exit {
rc_status=$?;
rc_status
exit $rc_status
}

sub warn () { local msg="Warning: ${1:-"general"}"
printf "%s" >&2 "$msg"
}

sub die () { int stat=$?; local msg="Error. ${1:-"unknown"}"
echo "$msg (errno=$stat)" >&2
(exit $stat);   
#sets $? (doesn't exit inside ()
rc_status -v 
rc_exit
exit $stat  
# exit unless die called in 
subshell
}

sysfs=/sys
sysnet=$sysfs/class/net

[[ -d $sysfs && -d $sysnet ]] ||
sysnet=$sysfs/class/net
sys_modules=$sysfs/module

if [[ -z $(type -P modprobe) ]]; then   # verify find of modprobe
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:$PATH
fi

if [[ -n $(type -P modprobe) ]]; then   # if found, alias it
alias modprobe="$(type -P modprobe)"
else
# only throw 
error if needed
alias modprobe="die 'cannot load required modules'"
fi

if [[ -z $(type -P ip ) ]]; then# ip is ne

Re: bash uses tmp files for inter-process communication instead of pipes?

2014-10-07 Thread Linda Walsh



Chet Ramey wrote:

On 10/7/14, 1:45 PM, Linda Walsh wrote:


There is no fundamental reason why, say, process substitution needs to
use /dev/fd or /proc/anything -- and couldn't operate exactly like piped
processes do now.  On my first implementation of multiple IPC programs,
I've used semaphores, message queues, named pipes, and shared memory.
With the exception of using shared memory for mutiple megabytes of
memory for each of several children, pipes provided equal or better
performance.


I think you have a fundamental misunderstanding of the purpose of
process substitution.  It is a way to turn a pipe to another process
into a file name, so that you can open what looks like a file,


You mean "< <(process)" is the part you are saying looks like a file?

If it wasn't for the shell mangling eoln's why wouldn't <$(process) be the same?

Or are you saying that the shell not mangling eoln's is a way of making it
look like a filei that you can use the normal set of !!!WRITE!!!...

calls I can write to such a process?  I've never seen this documented
where did I miss this... if that's the case, then I'll rethink my position.

But I never got that < <(process) was anything more than a one way read from the
right-hand process into the left -- and was not any different than

(process)|  where left hand process feeds into the right hand process.

I.e. both looked like unidirectional communication over a pipe.

But if < <(process) has bidirectional communication, do you have an example
of this? Ahhh... you are referring to > >(process) which is like |(process)

Both being cases where you can write to a process through a pipe.  I've
used FIFO's but other than making it a bit easier to parse lines, they
weren't much different than pipes -- which get parsed into lines all the time
over the net et al.

What read/write calls can you do with < <() > >() that you cannot with "|"'
that don't involve a "which process is on top" paradigm (which, as you mention,
is switchable with "lastpipe" anyway)?



Gosh, you mean I could write a stdio library that would have to be portable
over the whole set of systems on which bash currently runs and support it
forever, abandoning all the work vendors have done?  It sounds too good to
be true!


I can let you use mine but it's specific to my use case and partly
in c++ which I'm learning as I work on something.  But the specific to use
case is also the point.  You don't need the whole set to buffer IPC in memory.

I generally prefer my own code and utils because their interfaces are
relatively stable compared to my needs -- BUT MOST of all -- because if 
something
is broken, since I know the code, I have a reasonable chance of fixing it.  
That's
harder to say picking up other people's stuff -- IF that is even an option.

FWIW -- I went back to using process substitution because I don't
know where the tmpfiles are opening (TMP and TMPFILE are not set, and /tmp
and /var/tmp are/were both writeable).  Now it is working.

None of the problems had to do with any of the IPC methods but with
what appeared to be a secondary declaration of the global variables in
a sub... hiding the globals.

I couldn't see what I was doing that would have caused problems since 
both
dev and proc were mounted and tmp is writeable but that's what tmp error 
message
seemed to think.

Even though it's a startup script, it's not starting up the kernel --
its renaming and reordering network interfaces to suit the user's choice.

Responses on other stuff  later...





Re: bash uses tmp files for inter-process communication instead of pipes?

2014-10-07 Thread Chet Ramey
On 10/7/14, 1:45 PM, Linda Walsh wrote:

> There is no fundamental reason why, say, process substitution needs to
> use /dev/fd or /proc/anything -- and couldn't operate exactly like piped
> processes do now.  On my first implementation of multiple IPC programs,
> I've used semaphores, message queues, named pipes, and shared memory.
> With the exception of using shared memory for mutiple megabytes of
> memory for each of several children, pipes provided equal or better
> performance.

I think you have a fundamental misunderstanding of the purpose of
process substitution.  It is a way to turn a pipe to another process
into a file name, so that you can open what looks like a file, get a
file descriptor, use the normal set of read and write calls on it, and
all the while talk to another process.  There are only a few ways to
do that, and /dev/fd and named pipes are really the only viable ones.

> It was certainly fun to try the various methods and compare them, but
> having an implementation that only depends on the LCD (pipes in this
> case), would make the code more portable and faster.  For HEREDOC's
> there is no reason why chet couldn't use his own STDIO lib for the needs
> of bash that keep everything in memory or spill on extra large sizes.

Gosh, you mean I could write a stdio library that would have to be portable
over the whole set of systems on which bash currently runs and support it
forever, abandoning all the work vendors have done?  It sounds too good to
be true!

> Design choice doesn't have to become feature constraint -- or if it
> does, then it's time to think about a different design choice.  Then all
> of those features that currently use linux-only or linux-like extensions
> like proc and /dev/fd can be ported to platforms that don't support such
> a wide feature set.

/dev/fd (which I prefer to /proc) is not Linux specific.  Named pipes are
standard.

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: bash uses tmp files for inter-process communication instead of pipes?

2014-10-07 Thread Pierre Gaston
On Tue, Oct 7, 2014 at 8:45 PM, Linda Walsh  wrote:

>
>
> Greg Wooledge wrote:
>
>> OK, then use a function to give you an escapable block:
>>
>> declare -A ...
>> create_maps() {
>> cd "$sysnet" || return
>> for ifname in ...; do
>> hwaddr=$(<"$ifname"/address)
>> act_hw2if[$hwaddr]="$ifname"
>> act_hw2if[$ifname]="$hwaddr"
>> done
>> }
>> create_maps
>>
>>  Either way, they code as you have suggested won't work
>>> without overcoming another set of side effects.
>>>
>>
>> There are ways to NOT use subshells.  I have given you two of those
>> ways now.
>>
> 
>
> I appreciate the options, but the option I want is the parent
> staying
> "put", and only sending children out to change dir's.  Say some new
> version of init wants to isolate init processes by putting them in their
> own dir and then deleting the dir.  As long as they don't cd out of the
> dir, they are fine, but if they do, they can't get back to it.
>
> Why can't I spawn a child that cd's into a dir and reports back
> what
> it finds in the dir?  I do this in perl or C w/no problem.
>
> I have an iomonitor program, that monitors multiple data inputs.  For
> each, I spawn a child that sits in that directory, holding the FD open
> and rewinding it for updated status.  There's no constant
> opening/reopening of files -- no walking paths.  Each time you open
> a path, the kernel has to walk the path -- if cached, happens very
> quickly -- but still work as it also has to check access on each
> traversal (it can change).  If your data-gathering routines sit where
> the data is and don't move, there is no waisted I/O or CPU accessing the
> data and the parent gets updates via pipes.
>
> There is no fundamental reason why, say, process substitution needs to
> use /dev/fd or /proc/anything -- and couldn't operate exactly like piped
> processes do now.  On my first implementation of multiple IPC programs,
> I've used semaphores, message queues, named pipes, and shared memory.
>

That's where you are wrong, there is no reason for *your* use case, but the
basic idea behind process substitution is to be able to use a pipe in a
place where you normally need a file name.


Re: bash uses tmp files for inter-process communication instead of pipes?

2014-10-07 Thread Greg Wooledge
On Tue, Oct 07, 2014 at 10:45:53AM -0700, Linda Walsh wrote:
>   I appreciate the options, but the option I want is the parent staying
> "put", and only sending children out to change dir's.  Say some new
> version of init wants to isolate init processes by putting them in their
> own dir and then deleting the dir.  As long as they don't cd out of the
> dir, they are fine, but if they do, they can't get back to it.
> 
>   Why can't I spawn a child that cd's into a dir and reports back what
> it finds in the dir?  I do this in perl or C w/no problem.

You are adding layers of non-negligible complexity to work around an
imaginary problem.



Re: bash uses tmp files for inter-process communication instead of pipes?

2014-10-07 Thread Linda Walsh



Greg Wooledge wrote:

OK, then use a function to give you an escapable block:

declare -A ...
create_maps() {
cd "$sysnet" || return
for ifname in ...; do
hwaddr=$(<"$ifname"/address)
act_hw2if[$hwaddr]="$ifname"
act_hw2if[$ifname]="$hwaddr"
done
}
create_maps


Either way, they code as you have suggested won't work
without overcoming another set of side effects.


There are ways to NOT use subshells.  I have given you two of those
ways now.



I appreciate the options, but the option I want is the parent staying
"put", and only sending children out to change dir's.  Say some new
version of init wants to isolate init processes by putting them in their
own dir and then deleting the dir.  As long as they don't cd out of the
dir, they are fine, but if they do, they can't get back to it.

Why can't I spawn a child that cd's into a dir and reports back what
it finds in the dir?  I do this in perl or C w/no problem.

I have an iomonitor program, that monitors multiple data inputs.  For
each, I spawn a child that sits in that directory, holding the FD open
and rewinding it for updated status.  There's no constant
opening/reopening of files -- no walking paths.  Each time you open
a path, the kernel has to walk the path -- if cached, happens very
quickly -- but still work as it also has to check access on each
traversal (it can change).  If your data-gathering routines sit where
the data is and don't move, there is no waisted I/O or CPU accessing the
data and the parent gets updates via pipes.

There is no fundamental reason why, say, process substitution needs to
use /dev/fd or /proc/anything -- and couldn't operate exactly like piped
processes do now.  On my first implementation of multiple IPC programs,
I've used semaphores, message queues, named pipes, and shared memory.
With the exception of using shared memory for mutiple megabytes of
memory for each of several children, pipes provided equal or better
performance.

It was certainly fun to try the various methods and compare them, but
having an implementation that only depends on the LCD (pipes in this
case), would make the code more portable and faster.  For HEREDOC's
there is no reason why chet couldn't use his own STDIO lib for the needs
of bash that keep everything in memory or spill on extra large sizes.

Design choice doesn't have to become feature constraint -- or if it
does, then it's time to think about a different design choice.  Then all
of those features that currently use linux-only or linux-like extensions
like proc and /dev/fd can be ported to platforms that don't support such
a wide feature set.






Re: bash uses tmp files for inter-process communication instead of pipes?

2014-10-07 Thread Greg Wooledge
On Tue, Oct 07, 2014 at 09:54:21AM -0700, Linda Walsh wrote:
> Chet Ramey wrote:
> >It's syslog.  Some vendors integrated patches that log all shell commands
> >to syslog.
> >
> No... that wasn't syslog, it was strace in another terminal where I attached
> the bacsh that was doing the various types of data transfer (pipes, process 
> subst)
> assignment... etc)

Chet is saying that your vendor's version of Bash may have been patched
to make client-side calls to syslog(2), and this might be what you are
seeing in your strace.

If it turns out this is what's causing your problem, then you'll have
some tough choices to make.

> Um... it used a socket.. to transfer *i^Ht^H*SOMETHING,
> then it uses a tmp file on top of that:
> 
> rt_sigaction(SIGINT, {0x4320b1, [], SA_RESTORER|SA_RESTART, 0x30020358d0}, 
> {0x4320b1, [], SA_RESTORER|SA_RESTART, 0x30020358d0}, 8) = 0
> open("/tmp/sh-thd-110678907923", O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600) = 3
> write(3, "one two three four", 18)  = 18
> write(3, "\n", 1)   = 1
> open("/tmp/sh-thd-110678907923", O_RDONLY) = 4
> close(3)= 0
> unlink("/tmp/sh-thd-110678907923")  = 0

The opens & writes & close & unlink are straight out of redir.c function
here_document_to_fd.  So that's bash opening the temp file for the
here document.  Any socket stuff before that could be from a vendor
patch, or a child process, or something else other than vanilla bash.

> I have neither TMP nor TMPDIR set at this point.  I don't
> think TMP or TMPDIR is set in the runscript at boot, but the script could 
> be inheriting
> a value from the bootup-infrastructure environment.

You could always add some debugging lines to the script to find out.

> the script in question is "assign_netif_names" run fairly late.
> But if I Break in on 'B', I get control before S01boot.  If I run the 
> command
> manually at that point, **it works**.   Only when I'm letting it boot 
> normally, does
> it hit this problem.

Ouch.

> >>>/etc/init.d/boot.assign_netif_names#193(get_net_IFnames_hwaddrs)> echo 
> >>>eth5 a0:36:9f:15:c9:c2
> /etc/init.d/boot.assign_netif_names: line 204: cannot create temp file for 
> here-document: No such file or directory

This error message definitely indicates the failure of bash internal
function here_document_to_fd (in redir.c).  The question is exactly
what failed, and why.

I've given you a workaround for the immediate problem you're seeing,
so you could use that until you are able to diagnose the underlying
problem and find out why this particular feature is failing.

To reiterate (and expanding a bit, because I omitted a few details
in the previous message):

declare -A map1 map2 # etc.
here=$PWD
create_maps() {
cd /some/place || return
for ifname in ...; do
hwaddr=$(

Re: bash uses tmp files for inter-process communication instead of pipes?

2014-10-07 Thread Linda Walsh



Chet Ramey wrote:

On 10/7/14, 8:55 AM, Dan Douglas wrote:


Um... it used a socket.. to transfer it, then it uses a tmp file on top
of that?!  :
That's the wrong process. AF_NETLINK is the interface used by iproute2 for IPC 
with the kernel. Bash doesn't use netlink sockets.


It's syslog.  Some vendors integrated patches that log all shell commands
to syslog.

Chet


No... that wasn't syslog, it was strace in another terminal where I attached
the bacsh that was doing the various types of data transfer (pipes, process 
subst)
assignment... etc)


strace -p 48785 -ff

Process 48785 attached
read(0, "\r", 1)= 1
write(2, "\n", 1)   = 1
socket(PF_NETLINK, SOCK_RAW, 9) = 3
sendmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=}, 
msg_iov(2)=[{"*\0\0\0d\4\1\0\0\0\0\0\0\0\0\0", 16}, {"read a b c d 
<<<${arr[@]}\0", 26}], msg_controllen=0, msg_flags=0}, 0) = 42

close(3)= 0
-
Um... it used a socket.. to transfer *i^Ht^H*SOMETHING,
then it uses a tmp file on top of that:

rt_sigaction(SIGINT, {0x4320b1, [], SA_RESTORER|SA_RESTART, 0x30020358d0}, 
{0x4320b1, [], SA_RESTORER|SA_RESTART, 0x30020358d0}, 8) = 0

open("/tmp/sh-thd-110678907923", O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600) = 3
write(3, "one two three four", 18)  = 18
write(3, "\n", 1)   = 1
open("/tmp/sh-thd-110678907923", O_RDONLY) = 4
close(3)= 0
unlink("/tmp/sh-thd-110678907923")  = 0
fcntl(0, F_GETFD)   = 0
fcntl(0, F_DUPFD, 10)   = 10
fcntl(0, F_GETFD)   = 0
fcntl(10, F_SETFD, FD_CLOEXEC)  = 0
dup2(4, 0)  = 0
close(4)= 0



Bash may not use netlink sockets directly, but perhaps that was a weird looking 
call
to 'nss' to do some name or group lookup... but the presence of the read text as
part of one of the messages seems a bit peculiar.


Of NOTE:
straces I ran with the system up in normal RL3 -- that is where I see it writing
to tmp.  I have neither TMP nor TMPDIR set at this point.  I don't
think TMP or TMPDIR is set in the runscript at boot, but the script could be 
inheriting

a value from the bootup-infrastructure environment.  I would have expected them
to write into /tmp -- which was why in one of the listings I did the "du" on 
both
/tmp and /var/tmp to show they were mounted and did a test "write" (touch) on
a file in /tmp and verified I was able to do so and see it with "ls".

If TMP{DIR} are set to a value, it isn't "/tmp or /var/tmp" since both are up 
and
available at that point.

The problem is that if I manually break into the boot process (this system goes
through a 'B' state to do these things:

/etc/rc.d/boot.d/S01boot.sysctl@
/etc/rc.d/boot.d/S01boot.usr-mount@
/etc/rc.d/boot.d/S02boot.udev@
/etc/rc.d/boot.d/S04boot.lvm@
/etc/rc.d/boot.d/S05boot.clock@
/etc/rc.d/boot.d/S06boot.localnet@
/etc/rc.d/boot.d/S07boot.cgroup@
/etc/rc.d/boot.d/S11boot.localfs@
/etc/rc.d/boot.d/S13boot.klog@
/etc/rc.d/boot.d/S13boot.lvm_monitor@
/etc/rc.d/boot.d/S13boot.swap@
/etc/rc.d/boot.d/S13setserial@
/etc/rc.d/boot.d/S14boot.isapnp@
/etc/rc.d/boot.d/S14boot.ldconfig@
/etc/rc.d/boot.d/S50boot.assign_netif_names@
/etc/rc.d/boot.d/S50boot.sys_settings@
/etc/rc.d/boot.d/S50boot.sysstat@

the script in question is "assign_netif_names" run fairly late.
But if I Break in on 'B', I get control before S01boot.  If I run the command
manually at that point, **it works**.   Only when I'm letting it boot normally, 
does
it hit this problem.

During a normal boot some of these are happening in parallel, however, that was
why I tested the writability of /tmp (verified it to be so).  I'll print out
TMP and TMPDIR -- and see if they contain unexpected values, but my assumption 
has
been they are empty then as they are after boot, with /tmp taking the tmp file 
(as
was the case in the strace I ran w/system up).

The messages I see, record and transmit are the boot logs -- not trace logs, and
show the kernel boot followed by a switchover (when klog is called) from the
kernel format to a more user-ish format i.e:
[4.058222] rtc_cmos 00:01: RTC can wake from S4
[4.058567] rtc_cmos 00:01: rtc core: registered rtc_cmos as rtc0
[4.058607] rtc_cmos 00:01: alarms up to one day, y3k, 242 bytes nvram, hpet 
irqs
[4.058772] device-mapper: uevent: version 1.0.3
[4.059034] device-mapper: ioctl: 4.27.0-ioctl (2013-10-30) initialised...

.root fs is next:
(> mount |grep sdc1
/dev/sdc1 on / type xfs (rw,nodiratime,relatime,attr2,inode64,noquota))

[4.356688] XFS (sdc1): Mounting V4 Filesystem
[4.423530] usb 1-3.1: new low-speed USB device number 3 using ehci-pci
[4.447749] XFS (sdc1): Ending clean mount
[4.451993] VFS: Mounted root (xfs filesystem) on device 8:33.
[4.461451] devtmpfs: mounted

... last kernel USB probe.. then a 15-second ga

"export -p" output not suitable for input when env vars contain non-identifiers

2014-10-07 Thread Stephane Chazelas
2014-09-30 17:06:22 +0100, Stephane Chazelas:
[...]
> $ env -i $'a\necho test\na=b' bash -c 'export -p'
> declare -x OLDPWD
> declare -x PWD="/home/stephane"
> declare -x SHLVL="1"
> declare -x a
> echo test
> a
[...]

Just reiterating in case that had gone unnoticed earlier:

$ env 'a;echo OOPS;: =' bash -c 'export -p' | bash
OOPS

That's because bash outputs:

declare -x a;echo OOPS;:

Since those environment variables cannot be mapped to shell
variables, they should not be included in the output of "export
-p".

Same applies for env variables called "1" or "#" or "*" for
instance.

I had already reported that 5 years ago actually:
http://thread.gmane.org/gmane.comp.shells.bash.bugs/11306
and it doesn't look like it was addressed at the time.

I can see there are a number of bugs at savannah
(https://savannah.gnu.org/support/?group=bash), but not much
activity on those bugs. Is that in use? Is it worth me adding an
entry there?

-- 
Stephane




Re: bash uses tmp files for inter-process communication instead of pipes?

2014-10-07 Thread Chet Ramey
On 10/7/14, 8:55 AM, Dan Douglas wrote:

>> Um... it used a socket.. to transfer it, then it uses a tmp file on top
>> of that?!  :
> 
> That's the wrong process. AF_NETLINK is the interface used by iproute2 for 
> IPC 
> with the kernel. Bash doesn't use netlink sockets.

It's syslog.  Some vendors integrated patches that log all shell commands
to syslog.

Chet
-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: Bash-4.3 Official Patch 30

2014-10-07 Thread Chet Ramey
On 10/6/14, 6:16 PM, John E. Malmberg wrote:

>>> Do you mean return ""; ?
>>
>> Yes, good catch.  It doesn't make a difference: clang and gcc both accept
>> it as written and it behaves as desired.  However, I'll change it for the
>> next version.
> 
> Changing it to return 0 instead of '\0' would probably be more clear.
> No need to return a pointer to a static empty string.

It depends on how you want the function to work.  It is nice to
differentiate between the cases where there is no shell input line
at all, where the index is just wrong, and the actual current input
pointer.  A "" indicates the second case better than a 0, though it's
not perfect.

Chet


-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: bash uses tmp files for inter-process communication instead of pipes?

2014-10-07 Thread Chet Ramey
On 10/7/14, 2:07 AM, Linda Walsh wrote:

> I thought I was getting rid of this bogus problem (which shouldn't
> be a problem anyway -- since it's just another pipe but with parent receiving
> the data instead of child receiving it) by storing it in a variable
> transfer form
> <<<($VAR)... cuz was told that didn't involve a voodoo process-substitution.

I suppose it's voodoo because you didn't understand the underlying OS
resource process substitution uses and therefore didn't realize when that
resource is and is not available.  People using process substitution using
/dev/fd on a system like FreeBSD also encounter similar issues, since
/dev/fd is a separate file system that must be mounted.

> 
> But it involves a heredoc that even though /tmp and /tmp/var are writeable,
> BASH can't use.  Either it's writing to //network or trying to open a
> tmp file in the current (/sys) directory... eitherway is buggy.

You misunderstand what is going on, but now that you know here documents
and here strings use temporary files, and that, as documented, bash uses
$TMPDIR as the directory where it creates these temporary files, you can
modify your script to set TMPDIR appropriately.

> 
> But a heredoc is just reading from an in-memory buffer.  That bash is
> going the inefficient route and putting the buffer in "tmp", first, is
> the 2nd problem you are pointing out -- why do people who want a heredoc
> need a fork OR a tmpfile?   The output I generated is < 512 bytes.  Would it
> be too silly to simply put any heredoc output  write it to any file?  shopt heredocsize=XXX[KMG]... and overflow to tmp
> if needed.

Maybe.  At some point, however, you have to turn it into a file descriptor,
because that is what the redirections produce.  That constrains your set of
choices.  You could invent new syntax, but it would not be a here-document
or here-string any more.

> Having several that would work woudl be nice.  Um... having 1 that would
> work even... how do you turn around parent/child I/O and get the vars on the
> other side without heredoc or procsub?  Why no pipes?

There are several mechanisms.  You simply have to use them correctly.
Since you're running a non-interactive shell without job control enabled,
you could even use pipes and the `lastpipe' shell option, but that only
first appeared in bash-4.2.

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: Fwd: bash not using pipes or /tmp @ boot?

2014-10-07 Thread Chet Ramey
On 10/6/14, 6:03 PM, Linda Walsh wrote:
> Not sure how but this went off into space, sorta...
> 
> Greg Wooledge wrote:
>> On Mon, Oct 06, 2014 at 12:14:57PM -0700, Linda Walsh wrote:
>>>done <<<"$(get_net_IFnames_hwaddrs)"
>>
>>> Where am I using a HERE doc?
>>
>> <<< and << both create temporary files.
> 
> 
> Yeah... where?

Wherever $TMPDIR says to.  If $TMPDIR doesn't name a writable directory,
bash looks for various system definitions (P_tmpdir), finally defaulting
to /tmp or /var/tmp.


> Maybe if bash didn't create tmp files in non-standard locations,
> this never would have been an issue (or just use pipes)..

Please.  Your assumptions about what is going on make your conclusions
shaky at best.

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: bash uses tmp files for inter-process communication instead of pipes?

2014-10-07 Thread Chet Ramey
On 10/6/14, 5:00 PM, Linda Walsh wrote:

>> You are working in a severely constrained environment. 
> That isn't the problem:  the assignment using a tmp file is:
>> strace -p 48785 -ff
> Process 48785 attached
> read(0, "\r", 1)= 1
> write(2, "\n", 1)   = 1
> socket(PF_NETLINK, SOCK_RAW, 9) = 3
> sendmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=},
> msg_iov(2)=[{"*\0\0\0d\4\1\0\0\0\0\0\0\0\0\0", 16}, {"read a b c d
> <<<${arr[@]}\0", 26}], msg_controllen=0, msg_flags=0}, 0) = 42
> close(3)= 0
> -
> Um... it used a socket.. to transfer it, then it uses a tmp file on top
> of that?!  :

Slow down and read the trace, espcially the data being transferred.  This
is syslog saving the command.

> rt_sigaction(SIGINT, {0x4320b1, [], SA_RESTORER|SA_RESTART, 0x30020358d0},
> {0x4320b1, [], SA_RESTORER|SA_RESTART, 0x30020358d0}, 8) = 0
> open("/tmp/sh-thd-110678907923", O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600) = 3
> write(3, "one two three four", 18)  = 18
> write(3, "\n", 1)   = 1
> open("/tmp/sh-thd-110678907923", O_RDONLY) = 4
> close(3)= 0
> unlink("/tmp/sh-thd-110678907923")  = 0
> fcntl(0, F_GETFD)   = 0
> fcntl(0, F_DUPFD, 10)   = 10
> fcntl(0, F_GETFD)   = 0
> fcntl(10, F_SETFD, FD_CLOEXEC)  = 0
> dup2(4, 0)  = 0
> close(4)= 0
> ioctl(0, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS,
> 0x7fff85627820) = -1 ENOTTY (Inappropriate ioctl for device)
> lseek(0, 0, SEEK_CUR)   = 0
> read(0, "one two three four\n", 128)= 19
> dup2(10, 0) = 0
> fcntl(10, F_GETFD)  = 0x1 (flags FD_CLOEXEC)
> close(10)   = 0
> -
> 
> Why in gods name would it use a socket (still of arguable overhead, when
> it could be done in a local lib), but THEN it duplicates the i/o in a file?

Read the trace.  There's no duplication going on.  The shell uses temp
files to implement here documents -- an implementation choice you may
disagree with under your peculiar circumstances but one that is simple
and general.


>> Maybe the best solution here is to move your script to a different part
>> of the boot sequence.  If you run it after all the local file systems
>> have been mounted, then you should be able to create temporary files,
>> which in turns means << and <<< become available, should you need them.
> 
> Theoretically, they ARE mounted What I think may be happening
> is that $TMP is not set so it is trying to open the tmp dir in:
> 
> "//sh-thd-183928392381" -- a network address.

This is not a network address.  The pathname you've shown is consistent
with TMPDIR being set to a single slash (TMPDIR=/), which is a directory
writable by the current user.

You might try setting TMPDIR=/tmp in your startup script.


> ---
> Correctness before elegance.  1), use memory before OS services.
> 2) use in-memory services before file services, 3) Don't use uninitialized
> variables (TMP) -- verify that they are sane values before usage.
> 4) don't use network for tmp when /tmp or /var/tmp would have worked just
> fine.

This is basically word salad.


>  This type of redirection instructs the shell to  read  input  from  the
>current source until a line containing only delimiter (with no trailing
>blanks) is seen.  All of the lines read up to that point are then  used
>as the standard input for a command.
> 
> "The current source" -- can be anything that input can be
> redirected from -- including memory.

In your case, the current source is the script, where the data appears.

> How could you use a seek in the middle of a HERE doc
> read?

Think about your use cases.  Many programs check whether or not their
input is a seekable device so they can read more than one character at
a time.

> Not only that, it's just wrong./dev/stdin most often comes from
> a tty which is not random access.

Again, it depends on your use cases.  There are a number of programs
whose primary use is in a filter environment rather than directly by
a user at a terminal.

>>> Creating a tmp file to do an assignment, I assert is a bug.

You're still mixing a general capability with your use of that capability.

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: bash uses tmp files for inter-process communication instead of pipes?

2014-10-07 Thread Chet Ramey
On 10/6/14, 3:38 PM, Linda Walsh wrote:
> Greg Wooledge wrote:
>> On Mon, Oct 06, 2014 at 12:14:57PM -0700, Linda Walsh wrote:
>>>done <<<"$(get_net_IFnames_hwaddrs)"
>>
>>> Where am I using a HERE doc?
>>
>> <<< and << both create temporary files.
> 
> 
> According to Chet , only way to do a multi-var assignment in bash is
> 
> read a b c d  <<<$(echo ${array[@]})
> 
> Forcing a simple assignment into using a tmp file seems Machiavellian --
> as it does exactly the thing the user is trying to avoid through
> unexpected means.

Don't mix a capability -- shorthand to provide arbitrary data on stdin
to the shell or a different process -- with your use of it.  You've
chosen to use this mechanism for assignment rather than something less
baroque, but that doesn't mean the capability is any less general.

Chet

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: bash uses tmp files for inter-process communication instead of pipes?

2014-10-07 Thread Chet Ramey
On 10/6/14, 3:14 PM, Linda Walsh wrote:
> In running a startup script, I am endeavoring not to use tmp files
> where possible, As part of this, I sent the output of a command
> to stdout where I read it using the "variable read" syntax:
> 
>while read ifname hwaddr; do
>printf "ifname=%s, hwaddr=%s\n" "$ifname" "$hwaddr"
>act_hw2if[$hwaddr]="$ifname"
>act_if2hw[$ifname]="$hwaddr"
>printf "act_hw2if[%s]=%s, act_if2hw[%s]=%s\n"
> "${act_hw2if[$hwaddr]}" "${act_if2hw[$ifname]}"
>done <<<"$(get_net_IFnames_hwaddrs)"
> 
> Note, I used the <<<"$()" form to avoid process substitution -- as I was told
> on this list that the <<< form didn't use process substitution.

Correct, it does not.

> 
> So I now get:
>> >>/etc/init.d/boot.assign_netif_names#192(get_net_IFnames_hwaddrs)> 
> echo eth5 a0:36:9f:15:c9:c2
> /etc/init.d/boot.assign_netif_names: line 203: cannot create temp file for
> here-document: No such file or directory
> 
> Where am I using a HERE doc?

You're using a here-string, which is a variant of a here-document.  They
differ very little, mostly in syntax.  The internal implementation is
identical.

> More importantly, at this point, where is it trying to write?/(Read).
> 
> Simple Q.  Why isn't it using some small fraction of the 90+G of memory
> that is free for use at this point?

Because the shell uses temp files for this.  It's a simple, general
solution to the problem of providing arbitrary data on stdin.

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: bash uses tmp files for inter-process communication instead of pipes?

2014-10-07 Thread Dan Douglas
On Monday, October 06, 2014 02:00:47 PM Linda Walsh wrote:
> 
> Greg Wooledge wrote:
> > On Mon, Oct 06, 2014 at 12:38:21PM -0700, Linda Walsh wrote:
> >> According to Chet , only way to do a multi-var assignment in bash is
> >>
> >> read a b c d  <<<$(echo ${array[@]})

It's best to avoid turning your nice data structure into a stream only to read 
(and mangle) it back again.

If you must, create a function.

function unpack {
${1+:} return 1
typeset -n _arrRef=$1 _ref
typeset -a _keys=("${!_arrRef[@]}")
typeset -i n=0
shift

for _ref; do
${_keys[n]+:} return
_ref=${_arrRef[${_keys[n++]}]}
done
}

#  $ a=(1 2 3) e=hi; unpack a b c d e; typeset -p {a..e}
# declare -a a='([0]="1" [1]="2" [2]="3")'
# declare -- b="1"
# declare -- c="2"
# declare -- d="3"  

  
# declare -- e="hi"

> Um... it used a socket.. to transfer it, then it uses a tmp file on top
> of that?!  :

That's the wrong process. AF_NETLINK is the interface used by iproute2 for IPC 
with the kernel. Bash doesn't use netlink sockets.

> >> So why would someone use a tmp file to do an assignment.
> > 
> > It has nothing to do with assignments.  Temp files are how here documents
> > (and their cousin here strings) are implemented.  A here document is a
> > redirection of standard input.  A redirection *from a file*
> 
>   Nope:
>   This type of redirection instructs the shell to  read  input  from  the
> current source until a line containing only delimiter (with no 
trailing
> blanks) is seen.  All of the lines read up to that point are then  
used
> as the standard input for a command.
> 
> "The current source" -- can be anything that input can be
> redirected from -- including memory.
> 
> 
> > in fact,
> > albeit a file that is created on the fly for you by the shell.
> 
> Gratuitous expectation of slow resources...  Non-conservation
> of resources, not for the user, but for itself.
> 
> Note:
> > a=$( > echo "$a"
> one
> two
> three
> ---
> no tmp files used, but it does a file read on foo.
> 
> b=$a
> -- the above uses no tmp files.
> 
> b=$(echo "$a")
> ---
> THAT uses no tmp files.
> 
> But
> b=<<<$a
> 
> uses a tmp file.
> 
> That's ridiculously lame.

That isn't working code the way you think (except in mksh). In most shells its 
just a null command that sets b to empty.

Just perform the assignment directly. There's no need for any special 
expansion or redirect.

> >> So why would a temp file be used?
> > 
> > Historical reasons, and because many processes will expect standard input
> > to have random access capabilities (at least the ability to rewind via
> > lseek).  Since bash has no idea what program is going to be reading the
> > here document, why take chances?
> 
>   How could you use a seek in the middle of a HERE doc
> read?
> 
> Not only that, it's just wrong./dev/stdin most often comes from
> a tty which is not random access.

There is no requirement for how heredocs are implemented. Temp files are 
perfectly reasonable and most shells use them. The shell reads the heredoc, 
but it is the command that would be doing any seeking, or possibly the shell 
itself via nonstandard features like the <#(()) redirect.

This can be an optimization. Consider:

for file in file1 ... filen; do
ed -s "$file" 

Re: bash uses tmp files for inter-process communication instead of pipes?

2014-10-07 Thread Greg Wooledge
On Mon, Oct 06, 2014 at 04:04:25PM -0700, Linda Walsh wrote:
> Greg Wooledge wrote:
> >netdev_pat=... # (and other variable assignments)
> >(cd "$sysnet" &&
> >for ifname in ...; do
> >hwaddr=$(<"$ifname"/address)
> >act_hw2if[$hwaddr]="$ifname"
> >act_if2hw[$ifname]="$hwaddr"
> >done)
> 
> Except that either act_hw2if + pair were just assigned to
> in the sub process that was meant to isolate the change
> of directory from the rest of the program,
> OR
> we aren't in the right directory when we do the reads.

OK, then use a function to give you an escapable block:

declare -A ...
create_maps() {
cd "$sysnet" || return
for ifname in ...; do
hwaddr=$(<"$ifname"/address)
act_hw2if[$hwaddr]="$ifname"
act_hw2if[$ifname]="$hwaddr"
done
}
create_maps

> Either way, they code as you have suggested won't work
> without overcoming another set of side effects.

There are ways to NOT use subshells.  I have given you two of those
ways now.