[comp.bugs.sys5] even more bugs in make

fritz@polecat.caltech.edu (Fritz Nordby) (06/01/87)

I don't know if this has been noticed before, but there is a severe problem
with make and Bourne shell scripts.  If the IFS environment variable is set
when make is invoked, then make resets IFS to an empty string.  This almost
guarantees that Bourne shell scripts will die horribly.

To repeat, create an empty directory, cd there, and do:
% /bin/sh
$ cat >foo <<FOO
echo \$#
set "\$@"
echo \$#
FOO
$ chmod +x foo
$ cat >makefile <<FOO
x:	y
	foo 1 2 3
FOO
$ >y
$ foo 1 2 3
3
3
$ IFS=' 	
'
$ # that's IFS='<space><tab><newline>'
$ export IFS
$ foo 1 2 3
3
3
$ make
	foo 1 2 3
3
1
$ ^D
% 

The final "1" output by foo is the error.  The problem is that the
	set "$@"
in foo is being expanded into
	set "1" "2" "3"
which, since IFS is empty (and therefore there are no field seperators),
is interpreted as
	set "1 2 3"
-- i.e., there is just one argument to set.  Needless to say, this causes
some problems.  For example, suppose /bin/cc is a shell script which invokes
the compiler after adding some flags to the comand line:
	#!/bin/sh
	exec /lib/cc -foo -bar "$@"
If IFS is set when make is invoked, and if make invokes cc, then /lib/cc will
be invoked with argc==2, as if it had been invoked by
	exec /lib/cc "-foo -bar $*"

		Fritz Nordby.	fritz@vlsi.caltech.edu	cit-vax!fritz

xsimon@its63b.UUCP (06/03/87)

In article <2888@cit-vax.Caltech.Edu> fritz@polecat.Caltech.EDU (Fritz Nordby) writes:
>I don't know if this has been noticed before, but there is a severe problem
>with make and Bourne shell scripts.  If the IFS environment variable is set
>when make is invoked, then make resets IFS to an empty string.  This almost
>guarantees that Bourne shell scripts will die horribly.

It's not that it resets it to an empty string explicitly - it's a side-effect
of the way that Make sets up make-variables from the environment list. What
it does is it parses each environ entry for <name>=<value>, and then just
simulates an assignment (such as <name> = <value> inside a Makefile). Of
course, it strips out any "whitespace" between the <name> and the <value> -
which is very embarassing for variables such as IFS in which the whitespace
is an important part of the <value>.
The same problem occurs for ANY variable which has an initial whitespace 
component - the whitespace will get stripped off by Make.


-- 
----------------------------------
| Simon Brown 		         | UUCP:  seismo!mcvax!ukc!{its63b,cstvax}!simon
| Department of Computer Science | JANET: simon@uk.ac.ed.{its63b,cstvax}
| University of Edinburgh,       | ARPA:  simon%{its63b,cstvax}.ed.ac.uk ...
| Scotland, UK.			 |				@cs.ucl.ac.uk
----------------------------------	 "Life's like that, you know"

gwyn@brl-smoke.UUCP (06/04/87)

In article <2888@cit-vax.Caltech.Edu>, fritz@polecat.caltech.edu (Fritz Nordby) writes:
> ...  If the IFS environment variable is set
> when make is invoked, then make resets IFS to an empty string.

That isn't quite what's happening.  Environment strings are handed to
the YACC-based parser inside "make", with the idea that they'll be treated
just like a "NAME=value" definition within a makefile.  Eventually it
is the parsed-and-assigned-to-"make"-variables values that get put back in
the environment when augmented "make" forks a shell.  What is happening here
is that the parser cannot handle environment variables containing funny stuff
like newlines.

I don't know how to fix this other than to rip all the environment fooey
out of "make".  Better to not screw around with IFS.  I think every shell
should set IFS to defaults when it starts up rather than trusting the IFS
that may be in the environment.  That would also avoid your problem.