Eu tenho o script para fazer o que eu queria, não é a solução mais elegante, mas faz o trabalho.
O shell principal cria um arquivo temporário, exporta seu nome para subshells subseqüentes, que podem gravar nele. O shell principal, em seguida, no final lê o código de retorno, exclui o arquivo temporário e retorna o valor do código de erro.
#!/bin/bash
export tmpf='mktemp'
rcode=0
echo $rcode > $tmpf
...
check_file() {
...
echo 1 > $tmpf
...
}
...
rcode='cat $tmpf'
rm -f $tmpf
echo "done."
exit $rcode