Subject: Problem with csh

From: [email-masked] (Steven Beard)

The version of csh used in netbsd has an obscure problem when executing an
"eval set" command. For example:

	set b = xxxx
	set a = b
	eval set temp = \$$a

This should set "temp" to "xxxx". Instead it is set to "$b". The command

	eval echo \$$a

produces "xxxx" as expected.

>From function doeval() in csh/func.c:

    gflag = 0, tglob(v);
    if (gflag) {
	gv = v = globall(v);		<==== "eval set" executes here
	gargv = 0;
	if (v == 0)
	    stderror(ERR_NOMATCH);
	v = copyblk(v);
    }
    else {
	gv = NULL;			<=== "eval echo" executes here
	v = copyblk(v);
	trim(v);
    }

The problem occurs because the tglob() function sets the value of gflag
differently for the "set" and "echo" commands. "gflag" is non-zero for the
"set" command and the all important trim() function is not called. trim()
is used to remove the quote flag from characters which in this case allows
variable expansion when the evaluation is done.

>From csh/glob.c:

void
tglob(t)
    register Char **t;
{
    register Char *p, c;

    while (p = *t++) {
	if (*p == '~' || *p == '=')	<===============================
	    gflag |= G_CSH;
	else if (*p == '{' &&
		 (p[1] == '\0' || p[1] == '}' && p[2] == '\0'))
	    continue;
	while (c = *p++)
	    if (isglob(c))
		gflag |= (c == '{' || c == '`') ? G_CSH : G_GLOB;
    }
}

The problem in tglob() is the addition of the test for '=' indicated above.
This test just happens to catch the "set" command since it contains an "=".
When this line is changed to

	if (*p == '~')

everything works correctly. Previous versions of csh used this form of the
test and also worked correctly.

As far as I can tell this change was introduced sometime between the BSD 4.3
and Net 2 releases. The problem does not occur on SunOS 4.1.3, SunOS 5.3,
HP-UX or Ultrix. The change seems to have been made along with the changes
which allow 8 bit characters.

I have fixed the version I am using as indicated above and have detected no
problems. I believe that the netbsd version of csh should be changed to behave
like other common versions so that scripts will be portable. However, I am
worried that the fix I made may have undesired side effects. Does anyone
know why the "=" test was added?

Steven Beard ([email-masked])