[comp.unix.questions] How Does One Change Variables That Are Set From A Sub-Shell

flan@ai.wustl.edu (Ian "No Excuse" Flanigan) (11/21/89)

There has been lots of talk here about how to flop environment variables
back and forth between scripts and so forth.  I have a new question along
the same lines:

	How does one pass a csh variable back to the old csh -or- grab said
	variable from a currently running shell and then feed it back.

I want to do this because I have a program that notifies me when I get
mail.  (I turn biff n, since it tends to destory the screen while this
other program writes nicely in the corner, leaving everything in tact.)  I
wouls also like this program to change my prompt from "flan@ai>" to
"(Mail)flan@ai>".  (Shades of rn, I know.)  I have not been able to find
any help or hints in TFM, and environment variables won't solve the
problem.  Any help, tips, or pointers from netland?

Thanks in advance.


Ian Flanigan

flan@ai.wustl.edu              "You can never have too many napkins."
wucs1.wustl.edu!ai!flan@uucp

jik@athena.mit.edu (Jonathan I. Kamens) (11/21/89)

In article <1989Nov20.190903.27550@wucs1.wustl.edu> flan@ai.wustl.edu (Ian "No
Excuse" Flanigan) writes:
>	How does one pass a csh variable back to the old csh -or- grab said
>	variable from a currently running shell and then feed it back.

  Has this question made it into the Frequently Asked Questions
posting yet (Now that I've posted two messages tonight in which I've
wondered this, I realize it's about time I started archiving each
month's version of that posting when it comes out.  Oh, well, too late
for this month's. :-)?

  You cannot pass environment variables or shell variables from a
sub-shell back to its parent, and you cannot (without reading the
memory image of the running sub-process in order to find the value of
the variable) "grab" a variable from a sub-process in order to set its
value in another process' environment.

  The only way this would be possible is if the parent and child
defined some special protocol (using a pipe, socket, whatever) for
transferring variable names and values between themselves.  None of
the "standard" shells (sh, csh, tcsh, ksh, bash, whatever) have any
facility for doing this, at least not that I know of.

>I want to do this because I have a program that notifies me when I get
>mail.  (I turn biff n, since it tends to destory the screen while this
>other program writes nicely in the corner, leaving everything in tact.)  I
>wouls also like this program to change my prompt from "flan@ai>" to
>"(Mail)flan@ai>".  (Shades of rn, I know.)  I have not been able to find
>any help or hints in TFM, and environment variables won't solve the
>problem.  Any help, tips, or pointers from netland?

  There are several ways to get the shell to notify you of new mail,
although not all of them can do exactly what you want, i.e. changing
the prompt to reflect new mail.

  In sh, if you set the variable MAIL to the name of your mail file,
the shell will print "you have mail" or some similar message right
before the first prompt that it realizes there is new mail (i.e. if
you're not doing anything in the shell, it won't print anything -- it
only checks directly before each time it prints a shell prompt).

  Same thing in csh, but it's the shell variable mail, not MAIL.  Csh
even allows you to specify a time interval to use in between checks.

  I don't know what you'd do in bash or ksh.

  In tcsh (and this is closest to what you want, I think), you can
define an alias 'precmd' to contain a command that will be executed
before each time the prompt is printed.  If I do:

  alias precmd set prompt=\"\`cat /tmp/mailinfo.$user\`%m%% \"

And then make my mail-checking script put "(Mail) " into
/tmp/mailinfo.jik (substitute your username here :-) when there is
mail, then my prompt will change when I have mail.  The other way to
do it would be to put this into a shell script (let's call it foo):

  #!/bin/csh -f
  if (-e /tmp/mailinfo.$user) then
    echo '(Mail) '
  else
    echo ''
  endif

And then do:

  alias precmd set prompt=\"\`foo\`%m%% \"

Then you don't have to worry about the contents of the file, and all
your mail-checking program has to do is delete the file or create it,
depending on if there is mail.  The reason you have to put that into a
shell script is that csh/tcsh doesn't support multi-line aliases using
"if", so there's no way to do the "else" part in an alias.

  I hope all this helps.

Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8495			      Home: 617-782-0710

maart@cs.vu.nl (Maarten Litmaath) (11/22/89)

In article <1989Nov21.052026.11968@athena.mit.edu> jik@athena.mit.edu (Jonathan I. Kamens) writes:
\... csh/tcsh doesn't support multi-line aliases using
\"if", so there's no way to do the "else" part in an alias.

Is that a fact?

	% alias z 'if (! -e \!^) set status=1 && echo yes || echo no'
	% z /
	yes
	% z /etc/foobar
	no

Allright, it doesn't contain the word "else" and it's ugly, but don't you
write off our beloved csh that fast, sonny! :-)
-- 
[...] like a roving gang.  "Ah, here's a NEW almost-empty group to post train
schedules and core dumps in!"  (Joe Buck) | maart@cs.vu.nl, mcsun!botter!maart

merlyn@iwarp.intel.com (Randal Schwartz) (11/23/89)

In article <1989Nov21.052026.11968@athena.mit.edu>, jik@athena (Jonathan I. Kamens) writes:
| In article <1989Nov20.190903.27550@wucs1.wustl.edu> flan@ai.wustl.edu (Ian "No
| Excuse" Flanigan) writes:
| >	How does one pass a csh variable back to the old csh -or- grab said
| >	variable from a currently running shell and then feed it back.
| 
|   You cannot pass environment variables or shell variables from a
| sub-shell back to its parent, and you cannot (without reading the
| memory image of the running sub-process in order to find the value of
| the variable) "grab" a variable from a sub-process in order to set its
| value in another process' environment.
| 
|   The only way this would be possible is if the parent and child
| defined some special protocol (using a pipe, socket, whatever) for
| transferring variable names and values between themselves.  None of
| the "standard" shells (sh, csh, tcsh, ksh, bash, whatever) have any
| facility for doing this, at least not that I know of.

However, reaching into my bag of nifty /bin/sh tricks, I could do
something like:

trap '. $HOME/.doit; /bin/rm -f $HOME/.doit' 4
(/my/background/process $$)&

where "/my/background/process" is responsible for putting some
/bin/sh commands, like:

PS1="${PS1L}YOU HAVE MAIL ${PS1R}"

into $HOME/.doit, and sending the shell (as passed by the first arg, a
signal 4).

The detailed implementation is left as an exercise to the reader. :-)

Just another shell wizard,