[comp.bugs.sys5] bug in /bin/sh

chris@cetia4.UUCP (Christian Bertin) (05/24/89)

First, I apologized if this is an ancient bug. There is a problem in the
argument passing when shell functions are used: The expansion of $* turns
quoted strings into multiple arguments. The expansion of $1, for example,
works fine:

If I type:

			$ print() echo $1
			$ print a b

I get

			a

Which is OK. If I type:

			$ print "a b" c

I get

			a b

Which is also OK.

But, if I type:

			$ mail() /usr/bin/mailx $*
			$ mail -s "a b c d e f" chris

the quoted string has become multiple arguments to 'mailx', so if I type

			~h

I get

			To: b c d e f chris
			Subject: a
			Cc:
			Bcc:

When I should have

			To: chris
			Subject: a b c d e f
			Cc:
			Bcc:

If 'mailx' is used directly, everything is OK. Single quotes don't work any
better, in case you were tempted to try. If there is a fix for this, I would
appreciate if someone could mail it to me.

Thanks in advance.


Chris

-- 
Chris Bertin	| -- CETIA -- 150, Av Marcelin Berthelot, Z.I. Toulon-Est
+33(94)212005	| 83088 Toulon Cedex, France
		| inria!cetia!chris

maart@cs.vu.nl (Maarten Litmaath) (05/26/89)

chris@cetia4.UUCP (Christian Bertin) writes:
\...			$ mail() /usr/bin/mailx $*
\			$ mail -s "a b c d e f" chris
\...
\I get
\			To: b c d e f chris
\			Subject: a

$ RTFM() /usr/bin/mailx "$@"
-- 
 "`Goto considered harmful' considered |Maarten Litmaath @ VU Amsterdam:
      harmful" considered harmful!     |maart@cs.vu.nl, mcvax!botter!maart

ccea3@rivm.UUCP (Adri Verhoef) (05/26/89)

>			$ print() echo $1
>			$ print a b
>			a

>			$ print "a b" c
>			a b

>			$ mail() /usr/bin/mailx $*
>			$ mail -s "a b c d e f" chris
>			~h
>			To: b c d e f chris
>			Subject: a

No, it's not a bug.  Now let's try this again.
			$ mail() /usr/bin/mailx "$@"
Now look:
			$ mail -s "a b c d e f" chris
			~h
			To: chris
			Subject: a b c d e f
			Cc:
			Bcc:

chip@ateng.ateng.com (Chip Salzenberg) (05/26/89)

According to chris@cetia4.UUCP (Christian Bertin):
>First, I apologized if this is an ancient bug. There is a problem in the
>argument passing when shell functions are used: The expansion of $* turns
>quoted strings into multiple arguments.

>       $ mail() /usr/bin/mailx $*

Feature alert!  That's the way $* is supposed to work.
What you probably want is:

	$ mail() /usr/bin/mailx ${1+"$@"}

-- 
Chip Salzenberg             <chip@ateng.com> or <uunet!ateng!chip>
A T Engineering             Me?  Speak for my company?  Surely you jest!
	  "It's no good.  They're tapping the lines."

danl@cbnewsc.ATT.COM (daniel.r.levy) (05/26/89)

< 			$ mail() /usr/bin/mailx $*
< 			$ mail -s "a b c d e f" chris
< 
< the quoted string has become multiple arguments to 'mailx', so ...
< I get
< 
< 			To: b c d e f chris
< 			Subject: a
< 
< When I [wanted]
< 
< 			To: chris
< 			Subject: a b c d e f

Use "$@" [sic, including the double quotes] instead of $*.  $* re-formats the
arguments into individual tokens.
-- 
Dan'l Levy                 UNIX(R) mail:  att!ttbcad!levy, att!cbnewsc!danl
AT&T Bell Laboratories
5555 West Touhy Avenue     Any opinions expressed in the message above are
Skokie, Illinois  60077    mine, and not necessarily AT&T's.

danl@cbnewsc.ATT.COM (daniel.r.levy) (05/26/89)

In article <1011@cbnewsc.ATT.COM> I wrote:
< < 			$ mail() /usr/bin/mailx $*

< Use "$@" [sic, including the double quotes] instead of $*.  $* re-formats the
< arguments into individual tokens.

Since you might want to invoke this without arguments at all, use ${1+"$@"}
which will expand to nothing if there are no arguments.  Otherwise,
/usr/bin/mailx will see one null argument if there are no arguments
passed to the function, and won't do what you want it to.
-- 
Dan'l Levy                 UNIX(R) mail:  att!ttbcad!levy, att!cbnewsc!danl
AT&T Bell Laboratories
5555 West Touhy Avenue     Any opinions expressed in the message above are
Skokie, Illinois  60077    mine, and not necessarily AT&T's.

worley@ardent.UUCP (John Worley) (05/26/89)

> There is a problem in the
> argument passing when shell functions are used: The expansion of $* turns
> quoted strings into multiple arguments. The expansion of $1, for example,
> works fine:
> 

    Not really.  Parameters are substituted before the command is parsed, so
any white space in the parameter will be seen as separating the arguments,
unless the parameter is enclosed in "".  The example

		print() {
			echo $1
		}

    when invoked with, is executed as follows:

                print "a b" c   ->      echo $1
                                ->      echo a b        # Note - 2 params!
                                ->      a b

    visually indistinguishable from

		print() {
			echo "$1"
		}

    which is what you though was happening.

> But, if I type:
> 
> 			$ mail() /usr/bin/mailx $*
> 			$ mail -s "a b c d e f" chris

    This is defintely NOT a bug.  From the manual page for the Bourne shell:

*       If $* is within a pair of double quotes, the positional
*       parameters are substituted and quoted, separated by quoted
*       spaces ("$1 $2 ..."); however, if $@ is within a pair of
*       double quotes, the positional parameters are substituted and
*       quoted, separated by unquoted spaces ("$1" "$2" ... ).

    So, /bin/sh is behaving as documented; what you wanted was:

        mail() {
		/usr/bin/mailx "$@"
        }

					Regards,
					John Worley
					uunet!ardent!worley

bga@bgalli.eds.com (Billy G. Allie) (05/26/89)

In article <883@cetia4.UUCP>, chris@cetia4.UUCP (Christian Bertin) writes:
> First, I apologized if this is an ancient bug. There is a problem in the
> argument passing when shell functions are used: The expansion of $* turns
> quoted strings into multiple arguments.
>
> But, if I type:
> 
> 			$ mail() /usr/bin/mailx $*
> 			$ mail -s "a b c d e f" chris
> 
> the quoted string has become multiple arguments to 'mailx'

The shell expand the parameters $* and $@ into a list of all positional 
parameters seperated by spaces so that the following command is executed:

	/usr/bin/mailx -s a b c d e f chris

To get the effect you desire, you must use the $@ parameter within quotes.
For example, your mail function should be written as follows:

	mail() /usr/bin/mailx "$@"

Note that both the $* and the $@ parameters receive special treatment by
the shell when they are quoted.  "$*" is equivalent to "$1 $2 $3 ..." and
"$@" is equivalent to "$1" "$2" "$3" ....
-- 
____	   | Billy G. Allie	| Internet..: bga@bgalli.eds.com
|  /|	   | 7436 Hartwell	| UUCP......: uunet!{mcf|edsews}!bgalli!bga
|-/-|----- | Dearborn, MI 48126	| Compuserve: 76337,2061
|/  |LLIE  | (313) 582-1540	| Genie.....: BGALLIE

emike@richsun.UUCP (E. Mike Durbin) (05/26/89)

In article <883@cetia4.UUCP> chris@cetia4.UUCP (Christian Bertin) writes:
>But, if I type:
>
>			$ mail() /usr/bin/mailx $*
>			$ mail -s "a b c d e f" chris
>

The problem is the arguments are reevaluated after they are assembled
by the function (or shell script).  $* dosn't group them.  That is why
you have all seperate arguments (the "'s are gone when they are
reevaluated).  "$*" will expand as "$1 $2 $3".  This also is not what
you want.  "$@" will expand as "$1" "$2" "$3".  This *IS* what you want:

	tst()
	{
		echo '"$@"'
		for i in "$@"
		do
			echo "-> $i"
		done

		echo '"$*"'
		for i in "$*"
		do
			echo "-> $i"
		done

		echo '$*'
		for i in "$*"
		do
			echo "-> $i"
		done
	}

	$ tst "a b c" d
	"$@"
	-> a b c
	-> d
	"$*"
	-> a b c d
	$*
	-> a
	-> b
	-> c
	-> d


						E. Mike Durbin
						Rich Inc.
						uunet!richsun!emike

chris@cetia4.UUCP (Christian Bertin) (05/29/89)

Thanks to all the people who sent me mail about this feature. Rob Gordon,
from Instruction Set, gave me another solution to handle the 'no-argument'
case:

	${@+"$@"}

That works fine too.

Chris
-- 
Chris Bertin	| -- CETIA -- 150, Av Marcelin Berthelot, Z.I. Toulon-Est
+33(94)212005	| 83088 Toulon Cedex, France
		| inria!cetia!chris