[comp.unix.wizards] still another two fixes for csh

greim@sbsvax.UUCP (Michael Greim) (01/29/88)

Here come two more fixes for csh.

The first one is connected with my earlier fixes (373@sbsvax.UUCP  12.jan.88,
374@sbsvax.UUCP 18.jan.88, 375@sbsvax.UUCP 25.jan.88)
The second one is for another bug.

The examples below only work, if my prior fixes have been applied.
My version of the csh is the BSD4.2 csh, but the bugs are in the BSD4.3
csh, the SUN csh and ULTRIX 2.0 csh too.

BTW, how about some responses ? We are new to the net, so I don't know, if
my news are heard, or whether the fixes are totally outdated and superfluous ?

Some time ago I made some other fixes in csh, interested ? Try the following :
	alias a '\!#'
	b; a
But be sure you can kill this csh from another terminal :-,

BTW, if my texts seem to be unaligned, try 'set tabstop=4' in vi.

1.) Symptoms

		Try the following :

		set a23456789012345678901234=(a b c)
		echo $a23456789012345678901234
		shift a23456789012345678901234
	--> won't work
		echo $a23456789012345678901234

	Diagnosis

		in the routine dealing with 'shift' the name is not truncated
		to 20 characters

	Therapy

		apply the following context diff to sh.set.c

*** sh.set.c.old	Fri Jan 29 11:52:55 1988
--- sh.set.c	Fri Jan 29 12:26:58 1988
***************
*** 536,551 ****
  
  shift(v)
  	register char **v;
  {
  	register struct varent *argv;
! 	register char *name;
  
  	v++;
! 	name = *v;
! 	if (name == 0)
! 		name = "argv";
! 	else
  		strip(name);
  	argv = adrof(name);
  	if (argv == 0)
  		udvar(name);
--- 536,567 ----
  
  shift(v)
  	register char **v;
+ /*
+  * 28.jan.88 mg
+  * changed routine to take var names up to 20 chars long
+  */
  {
  	register struct varent *argv;
! 	char name [MAX_NAME_LENGTH+1];
! 	register int i;
! 	char * s;
  
  	v++;
! 	if (*v == 0)
! 		strcpy (name, "argv");
! 	else {
! 		s = *v;
! 		if (! letter (*s))
! 			bferr ("Name must start with letter");
! 		for (i = 0; *s != '\0'; s++) {
! 			if (! alnum (*s))
! 				bferr ("Name must consist of letter,number,underline");
! 			if (i < MAX_NAME_LENGTH)
! 				name [i++] = *s;
! 		}
! 		name[i] = '\0';
  		strip(name);
+ 	}
  	argv = adrof(name);
  	if (argv == 0)
  		udvar(name);

2.) Symptoms

		The manual says the syntax of unsetenv is 'unsetenv pattern',
		but you cannot 'unsetenv' variables via patterns.
		Try the following :

			setenv a1 gurrugurru
			setenv a2 rhubarb
			setenv a1help -soup
			setenv a2help -pie
			setenv a3help -plant
		either
			unsetenv a*
		or
			unsetenv a?
		or
			unsetenv a2*
		or
			unsetenv a[2-3]h*
	
		Nothing works.

	Diagnosis

		Somebody forgot to put in the code to compare names to patterns,
		so unsetenv only matches char by char correctness.

	Therapy

		Apply the following context diff to sh.func.c

*** sh.func.c.old	Fri Jan 29 11:52:54 1988
--- sh.func.c	Fri Jan 29 11:52:53 1988
***************
*** 837,862 ****
  	setenv(name, value);
  }
  
! unsetenv(name)
! 	char *name;
  {
! 	register char **ep = environ;
! 	register char *cp, *dp;
! 	char **oep = ep;
  
! 	for (; *ep; ep++) {
! 		for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++)
! 			continue;
! 		if (*cp != 0 || *dp != '=')
! 			continue;
! 		cp = *ep;
! 		*ep = 0;
! 		environ = blkspl(environ, ep+1);
! 		*ep = cp;
! 		xfree(cp);
! 		xfree((char *)oep);
! 		return;
  	}
  }
  
  doumask(v)
--- 837,910 ----
  	setenv(name, value);
  }
  
! /*
!  * 28.jan.88 mg
!  * The manual says : 'unsetenv pattern', but the routine only removes
!  * variables whose whole name matches.
!  * Changed this.
!  */
! unsetenv(pat)
! 	char *pat;
  {
! 	register char **ep;
! 	register char *p;
! 	char **oep;
! 	int i, j;
! 	static char * name = NULL;
! 	extern char * malloc ();
  
! 	if (name != NULL) {						/* maybe we were interupted ? */
! 		free (name);
! 		name = NULL;
  	}
+ 	/*
+ 	 * to optimize the storage, we count length of environment variables,
+ 	 * the longest wins.
+ 	 */
+ 	ep = environ;
+ 	for (i = 0; *ep; ep++) {
+ 		for (j = 0, p = *ep; *p && *p != '='; p++, j++);
+ 		if (j > i)
+ 			i = j;
+ 	}
+ 	/*
+ 	 * now allocate space for name
+ 	 */
+ 	name = (char *) malloc (i + 1);
+ 
+ 	/*
+ 	 * j indicates whether we had a match (1) or not (0)
+ 	 *
+ 	 * as long as we had a match, we restart from environ (is changed
+ 	 * when a variable is deleted), and search again
+ 	 */
+ 	for (j = 1; j == 1;) {
+ 		j = 0;
+ 		for (ep = environ; *ep; ep++) {		/* for each environment var ... */
+ 			p = *ep;						/* isolate the name */
+ 			for (i = 0; p[i] && p[i] != '='; i++);
+ 			name[i] = '\0';
+ 			for (i--; i >= 0; i--)
+ 				name[i] = p[i];
+ 			if ( ! Gmatch (name, pat))
+ 				continue;
+ 			j = 1;
+ 			/*
+ 			 * it matches -->  delete it
+ 			 * and rewind to outer loop
+ 			 */
+ 			oep = environ;
+ 			p = *ep;
+ 			*ep = 0;
+ 			environ = blkspl(environ, ep+1);
+ 			*ep = p;
+ 			xfree(p);
+ 			xfree((char *)oep);
+ 			break;
+ 		}
+ 	}
+ 	free (name);
+ 	name = NULL;
  }
  
  doumask(v)


	NOTE : it is not an error for the pattern to contain non alphanumeric
	characters as it is no error for names of environment variables
	to contain non alphanumeric characters.

	-- Michael

+------------------------------------------------------------------------------+
| UUCP:  ...!uunet!unido!sbsvax!greim   | Michael T. Greim                     |
|        or greim@sbsvax.UUCP           | Universitaet des Saarlandes          |
| CSNET: greim%sbsvax.uucp@Germany.CSnet| FB 10 - Informatik (Dept. of CS)     |
| ARPA:  greim%sbsvax.uucp@uunet.UU.NET | Bau 36, Im Stadtwald 15              |
| Phone: +49 681 302 2434               | D-6600 Saarbruecken 11, West Germany |
+------------------------------------------------------------------------------+
| "And when the nukes come raining down it's great to be alive, well, world    |
| war III can be such fun if you protect and survive." The Dubliners.          |
+------------------------------------------------------------------------------+