Tuesday, September 27, 2011

Bash Function Return Values and Exit

For those lucky souls out there programming in bash, you may be making use of the bash subshell trick that allows you to "return" a value from a function.

function echoTwice() {
  echo "$1"
  echo "$1"
}

declare twice=$(echoTwice "woot")
echo "Twice is: $twice"

Will produce the output,

Twice is: woot woot

The tricky gotcha in this situation involves exiting on error conditions. For example, consider the following enhancement to echoTwice,

function echoTwice() {
  if [ -z "$1" ]; then
    echo "Must provide an argument" >&2
    exit 1
  fi

  echo "$1"
  echo "$1"
}

declare twice=$(echoTwice)
echo "Twice is: $twice"

You would expect to see the error message and nothing else.  However, instead you see

Must provide an argument
Twice is:

Why does this happen? It happens because the assignment to $twice happens via a subshell. A subshell is spawned to evaluate the result of echoTwice. When that subshell exits early, bash treats it no differently than had the whole function proceded. Subsequently, rather than quitting your code, processing continues when the subshell completes. So, how do you accomodate this in your code without resorting to ugly globals?

The solution that I have found is to test if $twice was assigned.

if [ -z "$twice" ]; then
  # Error message emitted by echoTwice prints to STD_ERR and
  # ...will not be consumed by the sub-shell
  exit 1
fi

The reason I can't just check the exit status is because declare twice= is an actual execution and will typically have a valid exit status.

EDIT (Nov 2nd, 11): It turns out that you can check the return status! The issue is accurately described that declare twice= has its own exit status, but the exit status arises from the use of the bash built-in "declare" and NOT from the assignment to the variable (See the "declare" section of http://www.gnu.org/software/bash/manual/bashref.html#Bash-Builtins).  So, the solution becomes:

declare twice=
twice=$(echoTwice)
if [ $? -ne 0 ]; then
  # Error message emitted by echoTwice prints to STD_ERR and
  # ...will not be consumed by the sub-shell
  exit 1
fi
echo "Twice is: $twice"

Friday, September 16, 2011

Don't Lose Your Phone

I get lots of credit card offers in the mail and in my email. In my life, I'm probably indirectly responsible for the life of an entire tree just to print all the offers I've received (not to account for the energy expended delivering them, ink for printing, etc.).  Today I finally resolved to bring the offers to an end. There is a phone number listed at the bottom of most offers, 1-888-5OPTOUT, which you can call to remove yourself from the list of people agencies will contact with the great deals. According to the FTC, this number is provided by the National Credit Bureau (http://www.ftc.gov/privacy/protect.shtm).

I called the number and was very shocked at the information it exposed about me via the simple fact of the phone number from which I was calling. Essentially, by identifying my phone number the automated service provided me, with no security challenge at all, my home address and full name. Transcript below:

  • NCB: Are you calling from your home phone?
  • Me: Yes
  • NCB: Please verify your address. Is it 123 Street Name, Town, State?
  • Me: Yes
  • NCM: Is your last name "Plumber"?
  • Me: Yes
  • NCM: Is your first name "Joe"?
  • Me: Yes
  • NCM: Please enter your SSN
After this point, I actually had to provide the information to verify it was me. 

So, I suppose that knowing someone's phone number may be enough to find their information online already anyway (white pages?), but I was utterly shocked that a service sponsored by the federal government would so easily give your private information away. My conclusion, be extra careful not to lose your phone and don't give your phone number out too willingly.