diff --git a/NEWS b/NEWS index 043ffc834..18134d46e 100644 --- a/NEWS +++ b/NEWS @@ -27,6 +27,8 @@ Any uppercase BUG_* names are modernish shell bug IDs. (this keeps the 2020-05-13 BUG_REDIRIO fix for the POSIX mode while restoring traditional ksh93 behaviour for backwards compatibility) * disables a noncompliant 'test -t' == 'test -t 1' compatibility hack + * disables passing an exported variable's attributes (such as integer or + readonly) to a new ksh process through the environment 2020-08-19: diff --git a/src/cmd/ksh93/sh.1 b/src/cmd/ksh93/sh.1 index 30993cb24..e77a4df14 100644 --- a/src/cmd/ksh93/sh.1 +++ b/src/cmd/ksh93/sh.1 @@ -980,8 +980,9 @@ The attributes supported by the shell are described later with the .B typeset\^ special built-in command. -Exported variables pass values and attributes to -the environment. +Exported variables pass their attributes to the environment so that a newly +invoked ksh that is a child or exec'ed process of the current shell will +automatically import them, unless the \fBposix\fR shell option is on. .PP The shell supports both indexed and associative arrays. An element of an array variable is referenced by a @@ -7040,6 +7041,7 @@ to fail or zero if no command has failed. .B posix Enable full POSIX standard compliance mode. This option is on by default if ksh is invoked as \fBsh\fR. It +disables passing exported variables' attributes (such as integer or readonly) to a new ksh process through the environment, causes file descriptors > 2 to be left open when invoking another program, makes the \fB<>\fR redirection operator default to standard input, disables a hack that makes \fBtest -t\fR (\fB[ -t ]\fR) equivalent to \fBtest -t 1\fR (\fB[ -t 1 ]\fR), diff --git a/src/cmd/ksh93/sh/init.c b/src/cmd/ksh93/sh/init.c index 50af01d3d..ac35b42cc 100644 --- a/src/cmd/ksh93/sh/init.c +++ b/src/cmd/ksh93/sh/init.c @@ -199,7 +199,7 @@ typedef struct _init_ static Init_t *ip; static int lctype; static int nbltins; -static void env_init(Shell_t*); +static void env_init(Shell_t*,int); static Init_t *nv_init(Shell_t*); static Dt_t *inittree(Shell_t*,const struct shtable2*); static int shlvl; @@ -1285,7 +1285,7 @@ Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit) stakinstall(NIL(Stak_t*),nospace); /* set up memory for name-value pairs */ shp->init_context = nv_init(shp); - /* read the environment */ + /* initialize shell type */ if(argc>0) { type = sh_type(*argv); @@ -1294,7 +1294,8 @@ Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit) if(type&SH_TYPE_POSIX) sh_onoption(SH_POSIX); } - env_init(shp); + /* read the environment; don't import attributes yet */ + env_init(shp,0); if(!ENVNOD->nvalue.cp) { sfprintf(shp->strbuf,"%s/.kshrc",nv_getval(HOME)); @@ -1395,6 +1396,9 @@ Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit) beenhere = 2; } } + /* import variable attributes from environment */ + if(!sh_isoption(SH_POSIX)) + env_init(shp,1); #if SHOPT_PFSH if (sh_isoption(SH_PFSH)) { @@ -1876,16 +1880,24 @@ static Dt_t *inittree(Shell_t *shp,const struct shtable2 *name_vals) /* * read in the process environment and set up name-value pairs * skip over items that are not name-value pairs + * + * Must be called with import_attributes == 0 first, then again with + * import_attributes == 1 if variable attributes are to be imported + * from the environment. */ -static void env_init(Shell_t *shp) +static void env_init(Shell_t *shp, int import_attributes) { register char *cp; register Namval_t *np,*mp; register char **ep=environ; - char *dp,*next=0; + char *dp; int nenv=0,k=0,size=0; Namval_t *np0; + static char *next=0; /* next variable whose attributes to import */ + + if(import_attributes) + goto import_attributes; if(!ep) goto skip; while(*ep++) @@ -1902,10 +1914,10 @@ static void env_init(Shell_t *shp) mp->nvenv = (char*)cp; dp[-1] = '='; } - else if(*cp=='A' && cp[1]=='_' && cp[2]=='_' && cp[3]=='z' && cp[4]==0) + else if(strcmp(cp,e_envmarker)==0) { dp[-1] = '='; - next = cp+4; + next = cp + strlen(e_envmarker); continue; } else @@ -1915,7 +1927,7 @@ static void env_init(Shell_t *shp) mp->nvname = cp; size += strlen(cp); } - nv_onattr(mp,NV_IMPORT); + nv_onattr(mp,NV_IMPORT); if(mp->nvfun || nv_isattr(mp,NV_INTEGER)) nv_putval(mp,dp,0); else @@ -1937,6 +1949,18 @@ static void env_init(Shell_t *shp) dp += size+1; dtinsert(shp->var_base,np++); } +skip: + if(nv_isnull(PWDNOD) || nv_isattr(PWDNOD,NV_TAGGED)) + { + nv_offattr(PWDNOD,NV_TAGGED); + path_pwd(shp,0); + } + if((cp = nv_getval(SHELLNOD)) && (sh_type(cp)&SH_TYPE_RESTRICTED)) + sh_onoption(SH_RESTRICTED); /* restricted shell */ + return; + + /* Import variable attributes from environment (from variable named by e_envmarker) */ +import_attributes: while(cp=next) { if(next = strchr(++cp,'=')) @@ -1978,14 +2002,6 @@ static void env_init(Shell_t *shp) else cp += 2; } -skip: - if(nv_isnull(PWDNOD) || nv_isattr(PWDNOD,NV_TAGGED)) - { - nv_offattr(PWDNOD,NV_TAGGED); - path_pwd(shp,0); - } - if((cp = nv_getval(SHELLNOD)) && (sh_type(cp)&SH_TYPE_RESTRICTED)) - sh_onoption(SH_RESTRICTED); /* restricted shell */ return; } diff --git a/src/cmd/ksh93/sh/name.c b/src/cmd/ksh93/sh/name.c index a2db5cd91..604b2cc4d 100644 --- a/src/cmd/ksh93/sh/name.c +++ b/src/cmd/ksh93/sh/name.c @@ -2179,8 +2179,10 @@ char **sh_envgen(void) memcpy((void*)er,environ,shp->nenv*sizeof(char*)); nv_scan(shp->var_tree, pushnam,&data,NV_EXPORT, NV_EXPORT); *data.argnam = (char*)stakalloc(data.attsize); + /* Export variable attributes into env var named by e_envmarker, unless POSIX mode is on */ cp = data.attval = strcopy(*data.argnam,e_envmarker); - nv_scan(shp->var_tree, attstore,&data,0,(NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER)); + if(!sh_isoption(SH_POSIX)) + nv_scan(shp->var_tree, attstore,&data,0,(NV_RDONLY|NV_UTOL|NV_LTOU|NV_RJUST|NV_LJUST|NV_ZFILL|NV_INTEGER)); *data.attval = 0; if(cp!=data.attval) data.argnam++; diff --git a/src/cmd/ksh93/tests/attributes.sh b/src/cmd/ksh93/tests/attributes.sh index b97acd456..beaa2eebe 100755 --- a/src/cmd/ksh93/tests/attributes.sh +++ b/src/cmd/ksh93/tests/attributes.sh @@ -86,6 +86,16 @@ fi if [[ $($SHELL -c 'xi=xi+4;echo $xi') != 24 ]] then err_exit export attributes fails fi +if [[ -o ?posix && $(set -o posix; "$SHELL" -c 'xi=xi+4;echo $xi') != "xi+4" ]] +then err_exit "attributes exported despite posix mode (-o posix)" +fi +if [[ -o ?posix && $("$SHELL" -o posix -c 'xi=xi+4;echo $xi') != "xi+4" ]] +then err_exit "attributes imported despite posix mode (-o posix)" +fi +ln -s "$SHELL" "$tmp/sh" +if [[ $("$tmp/sh" -c 'xi=xi+4;echo $xi') != "xi+4" ]] +then err_exit "attributes imported despite posix mode (invoked as sh)" +fi x=$(foo=abc $SHELL <