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. | +------------------------------------------------------------------------------+