--- bin/ln/symlink.7.orig Tue Aug 5 01:01:59 2003 +++ bin/ln/symlink.7 Wed Aug 6 12:24:53 2003 @@ -426,6 +426,9 @@ .It @domainname Expands to the machine's domain name, as set by .Xr setdomainname 3 . +.It @env_XXXXX +Expands to the current setting of the environment variable +.Li XXXXX .It @hostname Expands to the machine's host name, as set by .Xr sethostname 3 . --- lib/libc/stdlib/setenv.c.orig Wed Sep 20 19:46:03 2000 +++ lib/libc/stdlib/setenv.c Mon Aug 4 19:13:10 2003 @@ -38,6 +38,12 @@ static const char rcsid[] = "$FreeBSD: src/lib/libc/stdlib/setenv.c,v 1.5.2.1 2000/09/20 19:46:03 brian Exp $"; #endif /* LIBC_SCCS and not lint */ +#include +#include +#include +#include +#include + #include #include #include @@ -45,6 +51,27 @@ char *__findenv __P((const char *, int *)); /* + * update_ps_strings -- + * Update the ps_envstr and ps_nenvstr members of the ps_strings + * structure to keep them up-to-date with setenv/unsetenv changes + */ +void +update_ps_strings(void) +{ + extern char **environ; + struct ps_strings *ps = (struct ps_strings *)PS_STRINGS; + char **envstr = environ; + int envc = 0; + + for(;*envstr;envstr++) { + envc++; + } + ps->ps_envstr = environ; + ps->ps_nenvstr = envc; + return; +} + +/* * setenv -- * Set the value of the environmental variable "name" to be * "value". If rewrite is set, replace any current value. @@ -99,6 +126,7 @@ return (-1); for (c = environ[offset]; (*c = *name++) && *c != '='; ++c); for (*c++ = '='; (*c++ = *value++); ); + update_ps_strings(); return (0); } @@ -118,4 +146,5 @@ for (p = &environ[offset];; ++p) if (!(*p = *(p + 1))) break; + update_ps_strings(); } --- sys/kern/vfs_lookup.c.orig Wed Aug 6 11:58:24 2003 +++ sys/kern/vfs_lookup.c Wed Aug 6 12:47:41 2003 @@ -54,10 +54,16 @@ #include #endif +/* need these for env stuff */ +#include +#include +#include +#include +#include +#include + #include -extern char osrelease[]; -extern char ostype[]; extern char kernel_ident[]; int symlink_magic __P((char *cp, int *len, struct proc *p)); @@ -279,6 +285,7 @@ { char tmp[MAXPATHLEN]; int change, i, newlen; + struct ps_strings ps; for (change = i = newlen = 0; i < *len; ) { if (cp[i] != '@') @@ -289,7 +296,58 @@ * The following checks should be ordered * according to frequency of use. */ - if (MATCH("machine_arch", '/')) { + if (MATCH("env", '_')) { + char envbuf[512]; + int error, j=i+4, envlen, envnamel; + char *envname = &cp[j]; + char **envvecp; + char *envstrp; + + /* retrieve env var name from symlink + * i points to "env_...", so i+4 points to + * environment var name we just have to stop + * at the '/' or NULL + */ + for (envnamel=0; + j+envnamel < *len && + envname[envnamel] != '/' && + envname[envnamel] != 0; + envnamel++); + + /* + * find the env var that is in symlink and + * substitute it in path + */ + if ((error = copyin((void *)PS_STRINGS,&ps,sizeof(struct ps_strings)))) { + break; + } + envvecp = ps.ps_envstr; + if ((error = copyin(envvecp++,&envstrp,sizeof(envstrp)))) { + break; + } + while (envstrp) { + if (copyinstr(envstrp, envbuf, sizeof(envbuf), &envlen)) { + break; + } + envbuf[sizeof(envbuf)-1] = '\0'; + if (!strncmp(envbuf, envname, envnamel) && + envbuf[envnamel] == '=') { + char *envval = &envbuf[envnamel+1]; + int envvall = strlen(envval); + + if ((newlen + envvall) > MAXPATHLEN) + return (1); + i += 4 + envnamel; + bcopy(envval, &tmp[newlen], envvall); + newlen += envvall; + change = 1; + break; + } + if (copyin(envvecp++,&envstrp,sizeof(envstrp))) { + break; + } + } + } else if (MATCH("machine_arch", '/')) { SUBSTITUTE("machine_arch", MACHINE_ARCH, sizeof(MACHINE_ARCH) - 1); } else if (MATCH("machine", '/')) {