[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug with ${1+"$@"} in /bin/sh of Solaris 11 Express

From: Bruno Haible
Subject: bug with ${1+"$@"} in /bin/sh of Solaris 11 Express
Date: Mon, 29 Nov 2010 04:29:14 +0100
User-agent: KMail/1.9.9


The Autoconf manual suggests to use ${1+"$@"} as a way to capture all
arguments of the currently running shell script.

Libtool uses this in its wrapper scripts.

But /bin/sh of Solaris 11 Express 2010-11 has a bug here: When the last
argument to be passed is an empty string, it is omitted.

The immediate effect is that unit tests of some programs may fail when
the package is configured with --enable-shared but succeed when it is
configured with --disable-shared.

Possible workarounds are:
  - Use /bin/bash instead of /bin/sh.
  - Test the number of arguments explicitly against 0, like this:
      case $# in
        0) exec prog;;
        *) exec prog "$@";;

I've reported this as a bug in Solaris 11 Express. Since that release
is declared as not to be used for production or business use, I think
there's no need to modify the Autoconf manual or Libtool at this point;
just wait for the next Solaris 11 release, next year.


========== Contents that I posted in the Oracle bug tracker ============
/bin/sh: expansion of ${1+"$@"} is incorrect

In /bin/sh shell scripts, the expansion of ${1+"$@"} is missing the last 
if that argument is an empty string.

According to POSIX:2008
"$@" and ${1+"$@"} should expand to the list of arguments, one by one, not
combined together, and not subject to word splitting. The second form is
commonly used as a workaround for platforms where the first form does not work,

How to reproduce:
1) Save this as args.c
========================== args.c ==============================
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char* argv[])
  int i;
  printf("argc = %d\n",argc);
  for (i = 0; i < argc; i++) printf("argv[%d] = %s\n",i,argv[i]);
2) Compile it: gcc -o $HOME/bin/args args.c
3) Save this as args-caller.sh
======================== args-caller.sh =========================
#! /bin/sh
exec $HOME/bin/args ${1+"$@"} end
Make it executable: chmod a+x args-caller.sh
4) Run it with various arguments:

$ ./args-caller.sh ''
Actual output:
argc = 2
argv[0] = /home/bruno/bin/args
argv[1] = end
Expected output:
argc = 3
argv[0] = /home/bruno/bin/args
argv[1] = 
argv[2] = end

$ ./args-caller.sh foo '' ''
Actual output:
argc = 4
argv[0] = /home/bruno/bin/args
argv[1] = foo
argv[2] = 
argv[3] = end
Expected output:
argc = 5
argv[0] = /home/bruno/bin/args
argv[1] = foo
argv[2] = 
argv[3] = 
argv[4] = end

reply via email to

[Prev in Thread] Current Thread [Next in Thread]