rob@pbhyf.PacBell.COM (Rob Bernardo) (08/18/88)
In one of the earlier guides to ksh, I found any interesting way to set the ENV variable so that your ENV file gets read only by *interactive* invocations of ksh (which reduces a lot of overhead when doing shell escapes and whatnot). The solution was the following: export START ENV START=$HOME/.kshrc # Name of file with aliases, functions # for interactive ksh invocations only ENV='${START[(_$-=1)+(_=0)-(_$-!=_${-%%*i*})]}' What I'd like to do is something similar, have ENV set to one file for interactive ksh invocations and to another file for non-interactive invocations. But since I can't figure out all that's going on here, I'm having difficulty. Even if no one can come up to the solution for having two ENV files, maybe at least someone can help explain the above way of conditionally using a single ENV file. What I understand so far is this. ENV (and also PS1) is unusual in that it gets evaluated upon *use*. Hence, upon use, that which is inside the single quotes gets evaluated. This is how I figure it gets evaluated: 1. (_$-=1) $- contains the flags with which the ksh was invoked, typically "ism" for interactive shells and "shc" for non-interactive shell. So this expression sets the variable, either _ism or _shc to a value of 1 and the value of this whole expression is 1. 2. (_=0) This expression sets the variable _ to the value of 0, and the expression has a value of 0. 3. (_$-!=_${-%%*i*}) This expression checks for the inequality of two variables. The left hand side is the variable set in the first of the three expressions in ()'s, _blah (where blah stands for whatever were the invocations flags, typically "ism" or "shc"). The right hand side first examines $- and strips it of everything if it contains an 'i' (the flag that alone really denotes an interactive ksh), which means that if the ksh is interactive, the right hand side evalutes to _, whose value was set to 0 in the second () expression, otherwise to _blah, whose value was set to 1 in the first () expressions. So this inequality test is true (returns 1) if this is an interactive ksh, otherwise false (returns 0). 4. Therefore, if the ksh is interactive the subscript for START is 0 (1+0-1) otherwise 1 (1+0-0). Since START[0] is defined but START[1] is not defined, our ENV variable is set to a bona fide file name only if the ksh is interactive. Voila`! That much works. One thing I can't figure out is that the third () expression seems to get evaluated twice, and I must be wrong about this. The first time I'm supposing the ${-%%*ism} evaluates the invocation flags and takes them away if they contain 'i'. The second time the variable whose name is _ suffixed with the result of that pattern substitution undergoes inequality testing. Okay, so the above works in setting ENV only if the ksh is interactive. So in order to have different ENV files for interactive and non-interactive ksh invocations, I figured what I could do this this: export START ENV START[0]=$HOME/.kshirc # Name of file with aliases, functions # for interactive ksh invocations only START[1]=$HOME/.kshnirc # Name of file with aliases, functions # for non-interactive ksh invocations only ENV='${START[(_$-=1)+(_=0)-(_$-!=_${-%%*i*})]}' Looks like it should work, but it doesn't! What I find is this: 1. My initial interactive ksh, namely my login shell, works okay, and ENV has been set to the value of START[0]. 2. Any other interactive ksh's, do not work okay. ENV is set to the value of START[0], ****but**** the value of START[0] and START[1] have been altered!!!! START[0] now has the former value of START[1] and START[1] isn't set! 3. And non-interactive ksh's do not have an ENV value, presumably because, like above, START[1] has been unset. I fiddled with this more and found that whatever is the highest subscripted START, it's the one whose value gets copied to START[0] in all non-login ksh's! This is absolutely bizarre. So I have two questions: 1. Why are the values of START[x] being altered for subsequent ksh invocations? 2. How do I solve what I originally set out to do - namely, have ENV set to one file for all interactive ksh invocations and set to a different file for all non-interactive ksh invocations? -- Rob Bernardo, Pacific Bell UNIX Small Bus. Systems Development & Maintenance Email: ...![backbone]!pacbell!rob OR rob@PacBell.COM Office: (415) 823-2417 Room 4E750A, San Ramon Valley Administrative Center Residence: (415) 827-4301 R Bar JB, Concord, California
merlyn@intelob.intel.com (Randal L. Schwartz @ Stonehenge) (08/19/88)
In article <3790@pbhyf.PacBell.COM>, rob@pbhyf (Rob Bernardo) writes: | | In one of the earlier guides to ksh, I found any interesting way | to set the ENV variable so that your ENV file gets read | only by *interactive* invocations of ksh (which reduces a lot of | overhead when doing shell escapes and whatnot). The solution | was the following: [ long details omitted ... ] | 2. How do I solve what I originally set out to do - namely, have ENV | set to one file for all interactive ksh invocations and set to a | different file for all non-interactive ksh invocations? Here's what I do: .profile contains: ENV=$HOME/.kshrc; export ENV $HOME/.kshrc contains: . $ENV.host case X$- in *i* ) . ${ENV}i ;; *) ## NON INTERACTIVE SHELL ONLY ## ;; esac and $HOME/.kshrci contains my interactive shell stuff. If you added ". ${ENV}u" where it says "NON INTERACTIVE SHELL" above, you could source your other file instead, calling it "$HOME/.kshrcu". (I don't have a need for that, but the hooks are there.) This stuff is all pretty fast, because the "case" doesn't fork a shell. The reason I don't just put the .kshrc stuff in .profile is that I don't want a /bin/sh to interpret it, just a /bin/ksh. Hope this helps... -- Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 on contract to BiiN Technical Publications (for now :-), Hillsboro, Oregon <merlyn@intelob.intel.com> or ...!tektronix!inteloa[!intelob]!merlyn Standard disclaimer: I *am* my employer!
ekrell@hector.UUCP (Eduardo Krell) (08/19/88)
In article <3790@pbhyf.PacBell.COM> rob@pbhyf.UUCP writes: >export START ENV >START=$HOME/.kshrc # Name of file with aliases, functions > # for interactive ksh invocations only >ENV='${START[(_$-=1)+(_=0)-(_$-!=_${-%%*i*})]}' I do it in a more readable way. In my ENV file I have: case $- in *i*) ... ... esac Where "..." represents whatever you want your interactive shell to execute. This way, you'll execute "..." only when $- (ksh's invocation flags) contains an "i" (for interactive shell). Eduardo Krell AT&T Bell Laboratories, Murray Hill, NJ UUCP: {att,decvax,ucbvax}!ulysses!ekrell Internet: ekrell@ulysses.att.com
rob@pbhyf.PacBell.COM (Rob Bernardo) (08/19/88)
In article <10519@ulysses.homer.nj.att.com> ekrell@hector.UUCP (Eduardo Krell) writes:
+I do it in a more readable way. In my ENV file I have:
+
+case $- in
+ *i*) ...
+ ...
+esac
+
+Where "..." represents whatever you want your interactive shell
+to execute.
+This way, you'll execute "..." only when $- (ksh's invocation flags)
+contains an "i" (for interactive shell).
This is one solution, but like anything, it has its minuses. In this
case the newly spawned ksh has to read the entire file, even the
parts it will never wind up executing. This can slow things down
quite a bit when doing a simply shell escape, e.g. from vi.
Someone wrote me (Thanks, Doug!) that the reason why the KSHRC array
(see the orginal posting - too long to repeat it here) gets mangled
is that ksh cannot correctly pass arrays to its environment.
In any case, I came up with a decent solution to the problem. What
I have in my .profile is the following:
ENV='$HOME/.kshrc${-%%[a-hj-z]*}' # Where to find ksh stuff.
# ENV file is .kshrc for non-interactive ksh invocations.
# ENV file is .kshrci for interactive ksh invocations.
# Presumes i flag is first if it occurs.
(Btw, my .kshrci file has as its first line:
. .kshrc
so that all the aliases and fuctions in the latter don't need to be
repeated in the former.)
--
Rob Bernardo, Pacific Bell UNIX Small Bus. Systems Development & Maintenance
Email: ...![backbone]!pacbell!rob OR rob@PacBell.COM
Office: (415) 823-2417 Room 4E750A, San Ramon Valley Administrative Center
Residence: (415) 827-4301 R Bar JB, Concord, California
ditto@cbmvax.UUCP (Michael "Ford" Ditto) (08/19/88)
In article <3790@pbhyf.PacBell.COM> rob@pbhyf.PacBell.COM (Rob Bernardo) writes: > >In one of the earlier guides to ksh, I found any interesting way >to set the ENV variable so that your ENV file gets read >only by *interactive* invocations of ksh (which reduces a lot of >overhead when doing shell escapes and whatnot). The solution >was the following: > >export START ENV >START=$HOME/.kshrc # Name of file with aliases, functions > # for interactive ksh invocations only >ENV='${START[(_$-=1)+(_=0)-(_$-!=_${-%%*i*})]}' >Okay, so the above works in setting ENV only if the ksh is interactive. >So in order to have different ENV files for interactive and non-interactive >ksh invocations, I figured what I could do this this: > >export START ENV >START[0]=$HOME/.kshirc # Name of file with aliases, functions > # for interactive ksh invocations only >START[1]=$HOME/.kshnirc # Name of file with aliases, functions > # for non-interactive ksh invocations only >ENV='${START[(_$-=1)+(_=0)-(_$-!=_${-%%*i*})]}' >Looks like it should work, but it doesn't! What I find is this: > >2. Any other interactive ksh's, do not work okay. ENV is set to the >value of START[0], ****but**** the value of START[0] and START[1] have >been altered!!!! START[0] now has the former value of START[1] and >START[1] isn't set! This is because you did not give START[] any values in those shells. Since START was exported by the login shell, it will be inherited by children as $START, which can also be accessed as $START[0]. $START[1] will not be set. >I fiddled with this more and found that whatever is the highest subscripted >START, it's the one whose value gets copied to START[0] in all non-login >ksh's! This is absolutely bizarre. It's actually the LAST value that was given to any element of START, not the highest numbered one. >2. How do I solve what I originally set out to do - namely, have ENV >set to one file for all interactive ksh invocations and set to a >different file for all non-interactive ksh invocations? Why not just set your ENV to $HOME/.kshrc or whatever, and in that file do the checking... like: case "$-" in *i*) echo "Interactive code goes here" ;; *) echo "Noninteractive code goes here" ;; esac To make it go faster, have the $ENV file just source one or the other of two sub-kshrc's. -- -=] Ford [=- . . (In Real Life: Mike Ditto) . : , ford@kenobi.cts.com This space under construction, ...!ucsd!elgar!ford pardon our dust. ditto@cbmvax.commodore.com