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