Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 533368 - sys-apps/gentoo-functions-0.8: "shift" and "type" bugs/bashisms
Summary: sys-apps/gentoo-functions-0.8: "shift" and "type" bugs/bashisms
Alias: None
Product: Gentoo Linux
Classification: Unclassified
Component: [OLD] Core system (show other bugs)
Hardware: All Linux
: Normal normal (vote)
Assignee: William Hubbs
Depends on:
Blocks: nonbash
  Show dependency tree
Reported: 2014-12-23 09:14 UTC by Martin Väth
Modified: 2021-01-07 17:47 UTC (History)
3 users (show)

See Also:
Package list:
Runtime testing required: ---


Note You need to log in before you can comment on or make changes to this bug.
Description Martin Väth 2014-12-23 09:14:58 UTC
When installing ccache-3.2.1-r1 with /bin/sh -> dash there is the error:

/usr/bin/ccache-config: 266: shift: can't shift that many

This is due to cache-config being a #/bin/sh script and using gentoo-functions.
gentoo-functions has 3 possible issues with non-bash:

1. In line 266 there is possibly a "shift" executed with an empty argument list.
Bash does not complain, but this is a bashism: most shells give some error.
Workaround: Instead of "shift" use one of
  [ -z "${1++}" ] || shift
  [ $# -eq 0 ] || shift

2. (several occurences): "type" is not POSIX (it works in dash but fails perhaps in other POSIX shells):
Workaround: Instead of all occurrences of "type" use the POSIX compatible variant
  command -v

3. "local" is not POSIX. However, for this I don't know a workaround, and it is usually not a problem unless you use a very ancient shell which also lacks other POSIX features needed by gentoo-functions.
Comment 1 William Hubbs gentoo-dev 2015-03-17 17:01:05 UTC
The first two issues listed are fixed in commit 6ad1c02.
This will be included in release 0.9.
I am not concerned at this time with the use of local. It is true that
this is not POSIX, but as stated above it should not be a problem. If I
find that it is a problem later, I will look into it.
Comment 2 Kerin Millar 2021-01-07 17:47:41 UTC
(In reply to Martin Väth from comment #0)
> 3. "local" is not POSIX. However, for this I don't know a workaround, and it
> is usually not a problem unless you use a very ancient shell which also
> lacks other POSIX features needed by gentoo-functions.

I realise that this is an old comment but it caught my interest. It can often be worked around by having the compound command that constitutes the function body be of the kind that creates a subshell, rather than the kind that does not. For example, this ...

f() {
    local a

... might be written as this ...

f() (

Of course, this method is only suitable where it is acceptable to dispense with any changes in state incurred by the subshell. In particular, don't proceed to alter variables that were defined on some other scope and expect the parent shell to be any the wiser. Still, it's surprising how much code there is out there where it is turns out not to be an issue. Indeed, losing state changes is often useful (think set -f, IFS changes and so forth). As such, I wish that the technique were more often employed. It seems that people have it hard-wired into their brains that function 'bodies' are defined by the curly braces but it's simply not true of the shell.

Furthermore, but there are two pitfalls with local that I see people walking into time and time again. The first is that it results in the exit status value of a command substitution being lost. One needs to declare the variable and perform the assignment separately to avoid that. The second is that, depending on the exact implementation, one may need to quote the right-hand-side, even in situations where it _wouldn't_ have been necessary without local. The netifrc project is an example of one that is peppered with potential bugs as a result of not taking into consideration these nuances. See bug 528314 as an example; now well over 6 years old.

What's the easiest solution? Not to use local and to be serious about POSIX conformance, as it happens. Either that, or to stop pretending and target a specific shell.