Date: Wed, 29 Jan 2020 09:23:05 -0500 From: Greg Wooledge <wool...@eeg.ccf.org> Message-ID: <20200129142305.gx1...@eeg.ccf.org>
| As far as functions go, bash allows you to define local variables within | a function. This avoids namespace collisions as long as you're within | that function. It actually doesn't, or not generally - it allows the function to avoid namespace collisions with random globals (or other locals) that might exist up the call stack, but doesn't prevent functions that are called from trampling all over this function's local vars. Some variants of ksh apparently make local vars work more like local vars in C (or other similar languages) and inaccessible outside the function, but that doesn't really work well for shell, it is useful to be able to make things like PATH, IFS, ... local in a function, change their values, and then call other functions which then use (and can alter) the modified values. | Obviously, sh doesn't have this feature, The POSIX spec doesn't have local vars, but all the shells that are used very much do, though the details of exactly how they work differ. If we could get everyone to agree on how they should work, they'd be in POSIX by now as well. | Since the Subject: of this thread includes the word "Bash", it seems | likely that the OP is not concerned with portable-sh issues at the | moment. Of course, which is why I suggested using local vars. One must however remain aware of the limitations. Of course if the function in question calls no other functions, then there is no problem, but knowing that is true for any function that does any more than variable manipulations (X=${Y%...} type things, including arithmetic, and which doesn't do everything in a subshell) is very difficult, and then unless the function writes "command" (or in bash, perhaps "builtin") before everything that is a command, then it remains vulnerable. Consider the proposed trap handling function, copied from another message sigint_handler() { trap - INT kill -INT $$ } (which has no vars, and manipulates none, so looks dafe enough) but then consider trap() { My_Var=123 command trap "$@" } kill() { PATH=/bin:/usr/bin command kill "$@" } and to make this a little more illustrative, consider that instead of the above, we have: sigint_handler() { local My_Var=$$ trap - INT kill -s INT "${My_Var}" } None of this is very likely in practice, but things like it do occasionally happen. It could be fixed by sigint_handler() { command local My_Var=$$ command trap - INT command kill -s INT "${My_Var}" } but when you find someone who actually writes their code like that, please let me know. kre