[net.bugs.4bsd] bug in CSH

lantz (04/05/83)

There was a report in unix-wizards of a "bug in vi" which caused it to
give a "Too many file names" error, if a file name was given in a :e
command which contained an asterisk, even if only one file name matched.
The same error occurs if the filename starts with a tilde.

This was correctly found by Scott Bradner at Harvard University to be
caused by the fact that csh, which is used by vi to expand the filename,
was printing its prompt in addition to the filename.  I had also found
this prompt annoying when other programs, such as Franz Lisp, invoke the
shell to execute one command.

Bradner's correction was not exactly what was called for, however.  The csh
has a flag 'prompt' which is true if the shell is supposed to prompt for
input.  This flag is set by default, and is reset by certain flags, including
the -c flag, which is the one used by vi and Franz Lisp.  The problem is
that THIS FLAG IS NOT CHECKED by the shell before it prints a prompt!  The
check goes in the routine process, in sh.c.  Diffs follow.

						Philip Lantz
						duke!ucf-cs!lantz

*** sh.c.old	Mon Apr  4 22:33:47 1983
--- sh.c	Mon Apr  4 22:33:31 1983
***************
*** 669,673
  		if (neednote)
  			pnote();

! 		if (intty && evalvec == 0) {
  			mailchk();

--- 669,674 -----
  		if (neednote)
  			pnote();

! 	/* Check of prompt added by PRL, UCF, April 1983. */
! 		if (intty && prompt && evalvec == 0) {
  			mailchk();

smb (04/06/83)

My experience is that the alleged bug in csh (that it prints the prompt
when it shouldn't, thereby affecting file-name expansion from 'vi' and
'ucbmail') isn't a bug; rather, many people unconditionally set 'prompt'
in their .cshrc files.  It should only be set if it's already set to
something:

	if ($?prompt) set prompt='MyPrompt '

rascal (04/06/83)

I agree with the line:
	if($?prompt) set prompt='my prompt'
You should now all change your .cshrc files.  Also, change all your friends.
Send a note to msgs.  If you are in charge of setting up accounts, remember
to put this line in everyone's .cshrc file.  Whoever is in charge of a manual,
(including vi and lisp), you might want to include a little note.

I don't ever want to hear about this problem again.  I also don't ever want
to hear about shell files that don't work when people have shell variables
set (like $D and spell).

	Thank you all.

chris@pixutl.UUCP (chris) (10/05/84)

There are a couple of bugs in the 'history' command of /bin/csh (and
offspring, such as newcsh):

1) The maximum number of arguments to the history command is set to 2.

2) The validity of the flags is not checked and since the argument pointer
is only incremented when a valid flag is found, using a wrong flag throws
the Cshell in a loop.

				-------------

To duplicate, type:
	csh
	set history = 100
	history -h -r 5
	history -x

				-------------

To fix:

1) In sh.init.c, change the following line:
	"history",	dohist,		0,	2,
to:
	"history",	dohist,		0,	4,

2) in sh.hist.c, change the following lines in dohist():
	vp++;
	while (*vp && *vp[0] == '-') {
		if (*vp && eq(*vp, "-h")) {
			hflg++;
			vp++;
		}
		if (*vp && eq(*vp, "-r")) {
			rflg++;
			vp++;
		}
	}
to:
	while (*++vp && **vp == '-') {
		while(*++*vp)
			switch(**vp) {
			case 'h':
				hflg++; break;
			case 'r':
				rflg++; break;
			case '-': /* ignore multiple '-'s */
				break;
			default:
				printf("Unknown flag: -%c\n", **vp);
				error("Usage: history [-rh] [# of events]");
			}
	}
		-----------------------------------------
-- 

 Chris Bertin            :         (617) 657-8720 x2318
 Pixel Computer Inc.     :
 260 Fordham Rd.         :  {allegra|ihnp4|cbosgd|ima|genrad|amd|harvard}\
 Wilmington, Ma 01887    :     !wjh12!pixel!pixutl!chris

glenn@wacsvax.OZ (Glenn Huxtable) (10/25/84)

A fix was reported for a bug in scanning 'history' command arguments
of CSH. I installed this fix, to find another bug. The fix was given as ...

	>2) The validity of the flags is not checked and since the argument 
	>   pointer is only incremented when a valid flag is found, using a
	>    wrong flag throws the Cshell in a loop.
	>2) in sh.hist.c, change the following lines in dohist():
	>	vp++;
	>	while (*vp && *vp[0] == '-') {
	>		if (*vp && eq(*vp, "-h")) {
	>			hflg++;
	>			vp++;
	>		}
	>		if (*vp && eq(*vp, "-r")) {
	>			rflg++;
	>			vp++;
	>		}
	>	}
	>to:
	>	while (*++vp && **vp == '-') {
	>		while(*++*vp)
	>			switch(**vp) {
	>			case 'h':
	>				hflg++; break;
	>			case 'r':
	>				rflg++; break;
	>			case '-': /* ignore multiple '-'s */
	>				break;
	>			default:
	>				printf("Unknown flag: -%c\n", **vp);
	>				error("Usage: history [-rh] [# of events]");
	>			}
	>	}

The fix introduced another bug, as the line 'while(*++*vp)' modifies the
argument pointer in scanning through the argument. Later CSH tries to use this
pointer (which now points to the end of the argument) to free the memory
used to store the command. Free (malloc) gets an mfree botch and CSH dies.
The solution is to use a local pointer 'vp2' say the fix becomes ...

=>	char *vp2;
	...
	while (*++vp && **vp == '-') {
=>		vp2 = *vp;
=>		while(*++vp2)
=>			switch(*vp2) {
			case 'h':
				hflg++; break;
			case 'r':
				rflg++; break;
			case '-': /* ignore multiple '-'s */
				break;
			default:
=>				printf("Unknown flag: -%c\n", *vp2);
				error("Usage: history [-rh] [# of events]");
			}
	}
-----------------------------------------------------
Glenn Huxtable					Department of Computer Science
						University of Western Australia
USENET:		...decvax!mulga!wacsvax!glenn
OZNET:		glenn:wacsvax