[comp.bugs.4bsd] nohup

karl@haddock.UUCP (Karl Heuer) (12/03/86)

The shell script /usr/bin/nohup uses `$*' where it should use `$@';
this breaks things like `nohup sh -c "echo foo"' because the quotes
get lost.

Moreover, it insists on sending stdout and stderr to the same place,
even if they were both redirected; and the destination is either
nohup.out or the existing stdout, but the decision is based on the
status of *stderr*.  (So that, e.g., `nohup cmd 2>/dev/null' will 
actually leave its output at the terminal.)

It might also be mentioned that `test -t >&2' is a bit obscure; the
notation `test -t 2' or `[ -t 2 ]' is more transparent, if indeed
this is the desired effect.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

jeb@lambda.UUCP (John Berry) (12/05/86)

We here have a sys5 version of nohup which works real fine on our
bsd systems.

dce@quacky.UUCP (David Elliott) (12/06/86)

In article <181@haddock.UUCP> karl@haddock.isc.com.UUCP (Karl Heuer) writes:
>The shell script /usr/bin/nohup uses `$*' where it should use `$@';
>this breaks things like `nohup sh -c "echo foo"' because the quotes
>get lost.
>

Yes and no. Nohup should say

	exec nice -5 "$@"

instead of

	exec nice -5 $*

to avoid the problems mentioned.

There is one slight problem with "$@", which can be shown by the following

	#!/bin/sh
	echo "Number of arguments - $#"
	for i in "$@"
	{
		echo "Argument - $i"
	}

Execute this with 1 argument, and it behaves as expected. Execute it with
no arguments, and it says that there are 0 arguments, but the loop is
executed once.

With 'for' loops, this can be easily fixed by saying 'for i' instead of
'for i in "$@"', but this still breaks things like the old /usr/ucb/print
command, and a ton of other shell scripts written by people not as
paranoid as Karl, Jerry Peek, and I. I've discussed this bug with
Steve Bourne, and he agrees that it is incorrect behavior.

Anyway, the following statement can be used to fix this bug in most
versions of sh.

	if (strcmp (as, "\"$@\"") == 0 && dolc == 0) {
		return(fixstak());
	}

Add these to the beginning of the subroutine macro() in macro.c, and the
bug goes away. It is somewhat kludgy, but it works.

Also, while I'm here, I'll show a way to properly build a list into a single
variable. Typically, this is done as

	for i
	{
		List="$List $i"
	}
	command $List

This is incorrect, since it breaks if an argument contains spaces or tabs
or newlines or what have you. The following works much better:


	Arg_list=""
	for arg
	{

		Arg_list="$Arg_list '$arg'"
	}
	eval command "$Arg_list"


			David "The Walking Something-or-other" Elliott
			decwrl!mips!dce