Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 11 Mar 1997 12:53:06 +0000
From:      Gareth McCaughan <gjm11@dpmms.cam.ac.uk>
To:        freebsd-bugs@freebsd.org
Subject:   Re: bin/2934: sh(1) has problems with $ENV 
Message-ID:  <E0w4R3C-0001Np-00@g.pet.cam.ac.uk>
In-Reply-To: Your message of "Tue, 11 Mar 1997 00:55:56 %2B0100." <199703102355.AAA10899@uriah.heep.sax.de> 

next in thread | previous in thread | raw e-mail | index | archive | help
> >Description:
> 
> /bin/sh processes $ENV fine if it has been set inside ~/.profile like:
> 
> 	ENV=${HOME}/.env; export ENV
> 
> However, it fails to source $ENV in this case:
> 
> 	export ENV=${HOME}/.env

This is not quite correct. If you use this idiom, sh behaves
correctly. If, however, you use ~ instead of $HOME, then the
tilde doesn't get expanded when you do "export ENV=~/foo",
but it does when you do "ENV=~/foo".

Then, when your new sh starts up and reads ENV, it finds the
variable correctly in both cases; however, its ENV-processing
code doesn't interpret the ~ and so it fails to find the file.

My reading of the sh(1) manpage is that tilde expansion *should*
happen, and that the ENV-processing code *should not* try to
do tilde expansion, but I am no sh(1) guru so I speak subject
to correction.

If my reading is correct, then (1) the same problem also affects
the "readonly" command, and (2) I believe that the following patch
fixes both problems. (It's relative to the version of sh in 2.2-GAMMA.)

I repeat that I am not a sh(1) guru, so this ought to be checked
by someone who knows more than I do about this stuff. I've moved
the "locate command" code so that it happens as soon as it's known
what the command is; then, if the command is "export" or "readonly",
the args are expanded like initial var=val pairs are.

---------- patch begins ----------
*** eval.c.orig	Tue Nov 12 19:23:44 1996
--- eval.c	Tue Mar 11 12:47:04 1997
***************
*** 594,600 ****
  	char **argv;
  	int argc;
  	char **envp;
! 	int varflag;
  	struct strlist *sp;
  	int mode;
  	int pip[2];
--- 594,600 ----
  	char **argv;
  	int argc;
  	char **envp;
! 	int doing_cmd, setting_cmd;
  	struct strlist *sp;
  	int mode;
  	int pip[2];
***************
*** 607,612 ****
--- 607,613 ----
  	struct localvar *volatile savelocalvars;
  	volatile int e;
  	char *lastarg;
+ 	char *path=pathval();
  #if __GNUC__
  	/* Avoid longjmp clobbering */
  	(void) &argv;
***************
*** 620,641 ****
  	setstackmark(&smark);
  	arglist.lastp = &arglist.list;
  	varlist.lastp = &varlist.list;
! 	varflag = 1;
  	oexitstatus = exitstatus;
  	exitstatus = 0;
  	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
  		char *p = argp->narg.text;
! 		if (varflag && is_name(*p)) {
  			do {
  				p++;
  			} while (is_in_name(*p));
! 			if (*p == '=') {
! 				expandarg(argp, &varlist, EXP_VARTILDE);
  				continue;
  			}
  		}
! 		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
! 		varflag = 0;
  	}
  	*arglist.lastp = NULL;
  	*varlist.lastp = NULL;
--- 621,660 ----
  	setstackmark(&smark);
  	arglist.lastp = &arglist.list;
  	varlist.lastp = &varlist.list;
! 	doing_cmd = 1; setting_cmd = 0;
  	oexitstatus = exitstatus;
  	exitstatus = 0;
  	for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
  		char *p = argp->narg.text;
! 		if ((doing_cmd || setting_cmd) && is_name(*p)) {
  			do {
  				p++;
  			} while (is_in_name(*p));
! 			if (*p == '=') {	
! 				expandarg(argp,
! 				          setting_cmd ? &arglist : &varlist,
! 				          EXP_VARTILDE);
! 				if (doing_cmd) {
! 					static const char PATH[] = "PATH=";
! 					char *s = ((struct strlist *)varlist.lastp)->text;
! 					if (!strncmp(s, PATH, sizeof(PATH)-1))
! 						path = s + sizeof(PATH) - 1;
! 				}
  				continue;
  			}
  		}
! 		{
! 	                expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
! 	                if (doing_cmd) {
! 		                char *s = ((struct strlist *)arglist.lastp)->text;
! 	                        /* Now locate the command. */
! 	                        find_command(s, &cmdentry, 1, path);
! 	                        /* Does it require us to grok future var=val pairs? */
! 	                        if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == EXPORTCMD)
! 	                                setting_cmd=1;
! 	                }
! 	                doing_cmd = 0;
! 		}
  	}
  	*arglist.lastp = NULL;
  	*varlist.lastp = NULL;
***************
*** 675,692 ****
  		cmdentry.cmdtype = CMDBUILTIN;
  		cmdentry.u.index = BLTINCMD;
  	} else {
- 		static const char PATH[] = "PATH=";
- 		char *path = pathval();
- 
- 		/*
- 		 * Modify the command lookup path, if a PATH= assignment
- 		 * is present
- 		 */
- 		for (sp = varlist.list ; sp ; sp = sp->next)
- 			if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0)
- 				path = sp->text + sizeof(PATH) - 1;
- 
- 		find_command(argv[0], &cmdentry, 1, path);
  		if (cmdentry.cmdtype == CMDUNKNOWN) {	/* command not found */
  			exitstatus = 1;
  			flushout(&errout);
--- 694,699 ----
----------- patch ends -----------

-- 
Gareth McCaughan       Dept. of Pure Mathematics & Mathematical Statistics,
gjm11@dpmms.cam.ac.uk  Cambridge University, England.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?E0w4R3C-0001Np-00>