From owner-freebsd-bugs Tue Mar 11 04:53:08 1997 Return-Path: Received: (from root@localhost) by freefall.freebsd.org (8.8.5/8.8.5) id EAA28121 for bugs-outgoing; Tue, 11 Mar 1997 04:53:08 -0800 (PST) Received: from mauve.csi.cam.ac.uk (exim@mauve.csi.cam.ac.uk [131.111.8.38]) by freefall.freebsd.org (8.8.5/8.8.5) with SMTP id EAA28106 for ; Tue, 11 Mar 1997 04:53:03 -0800 (PST) Received: from g.pet.cam.ac.uk [131.111.209.233] by mauve.csi.cam.ac.uk with smtp (Exim 1.58 #1) id 0w4R2u-0003DO-00; Tue, 11 Mar 1997 12:52:48 +0000 Received: from g.pet.cam.ac.uk [127.0.0.1] by g.pet.cam.ac.uk with esmtp (Exim 1.59 #1) id 0w4R3C-0001Np-00; Tue, 11 Mar 1997 12:53:06 +0000 To: freebsd-bugs@freebsd.org Subject: Re: bin/2934: sh(1) has problems with $ENV In-reply-to: Your message of "Tue, 11 Mar 1997 00:55:56 +0100." <199703102355.AAA10899@uriah.heep.sax.de> Date: Tue, 11 Mar 1997 12:53:06 +0000 From: Gareth McCaughan Message-Id: Sender: owner-bugs@freebsd.org X-Loop: FreeBSD.org Precedence: bulk > >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.