[net.unix] Bourne shell modifications, past and future

arnold@gatech.CSNET (Arnold Robbins) (11/13/85)

Back in early June, I posted, to mod.sources, modifications to the
Bourne shell that provided the following features:

(to quote from the README file I shipped out)
> 1.  BSD style job control on Berkeley Systems. Code to outwit symbolic
>     links for shells which have 'pwd' built in.  Also code to print a
>     resource usage summary after every command on BSD systems.  These are
>     courtesy of the folks at BRL, who gave me permission to post their
>     code.
> 
> 2.  The ability to catch Control-D's, and force you to use "exit", also
>     courtesy of BRL.  This will work whether or not you are on a BSD system.
> 
> 3.  The <> I/O redirecter is now documented, and also works (courtesy of
>     ihnp4!trwrb!lcc!brian's recent posting in net.unix-wizards).
> 
> 4.  The shell parameter $+ gives you the parent process id of the shell.
>     It will track the value of the getppid() system call.
> 
> 5.  The shell will read in $HOME/.shrc on startup, if that file exists.
>     This file is read *after* /etc/profile and $HOME/.profile (unlike the
>     csh, which readc ~/.cshrc before ~/.login).
> 
> 6.  The ~ and ~person notation is understood, both for command line arguments,
>     and in the PATH and CDPATH shell variables.
>  
> 7.  Special sequences in PS1 (the shell's prompt string) will print useful
>     info at the prompt.  Currently, you can get or all or some or none of:
> 	the time of day
> 	your current directory (if the shell has pwd is built in)
> 	your machine's hostname
> 	your login name
> 	the current 'event' number for the ...
> 
> 8.  History mechanism.  The history mechanism is powerful, yet easy to use.
>     Although different from the csh's, it is somewhat more general and
>     orthogonal.  The shell will save history across login sessions,
>     automatically restoring on login, and saving on exit or on the exec builtin.
> 
> On a Pyramid, the shell has some additional capabilities:
> 
> 9.  The 'att', 'ucb' and 'universe' commands are built in.
> 
> 10. The $UNIVERSE shell variable tracks the current universe.
> 
> 11. An additional sequence for the prompt to print the current universe.

Since that time, my shell has been pretty well received. It has not caused
wholesale occurrences of "rm /bin/csh", but it has helped a lot of people.
(If you didn't get the mods, the mod.sources moderator can make arrangements to
get it to you. It is also available for ARPA ftp access from seismo.)

I have received a lot of mail, with suggestions and bug fixes and enhancements.
Here is a list of what I am planning on doing for my next iteration (I am about to
start):

	Numerous bug fixes

	A few more prompting sequences, including for PS2

	As much ksh compatibility as is feasible
		$ENV handling in favor of ~/.shrc
		$PPID instead of $+
		$PWD and $OLDPWD
		~+, and ~-

	expr(1) as a built-in command

	Enhanced operation of att and ucb builtins on a pyramid

	Reimplementing the history mechanism from scratch, including
		a limit on the number of saved commands that will be
		printed by 'history', and an enhancement to make frequent
		operations easier (!$ will work). Also a way to just
		print the history result, without executing it.
	
	tcsh(1) twenex expansion!! (courtesy of celerity!barto, who ripped
		it out of tcsh and made it work with sh.)
	
	Several other small things.

Things that I will NOT add to the Bourne shell are:

	Command aliasing

	Arrays of shell variables (both ala ksh)

I am posting this to request feedback from the net on "what else would
you like to see in the Bourne shell"?  If you use either the plain Bourne
shell, or my modified Bourne shell, and have things that you would like to
see added, let me know. If you have written to me and I have responded, then
I still have your ideas. If you wrote to me and I have not, then I probably
never got your mail.

So, if you have ideas for features for the shell that are not listed in
any of what I have done, or am about to do, let me hear from you! If what
you have in mind is at all reasonable for me to do, I will attempt it.

sh users of the world, unite! :-)
-- 
Arnold Robbins
CSNET:	arnold@gatech	ARPA:	arnold%gatech.csnet@csnet-relay.arpa
UUCP:	{ akgua, allegra, hplabs, ihnp4, seismo, ut-sally }!gatech!arnold

Real Unix hackers disdain wimpy languages like C and AWK in favor of /bin/sh.

clive@druri.UUCP (StewardCN) (11/14/85)

Out of curiosity, just why don't you want to put in command aliasing?

It's one of the most useful features in csh and ksh, I think.

Clive

levy@ttrdc.UUCP (Daniel R. Levy) (11/15/85)

In article <10@druri.UUCP>, clive@druri.UUCP (StewardCN) writes:
>Out of curiosity, just why don't you want to put in command aliasing?
>It's one of the most useful features in csh and ksh, I think.
>Clive

Maybe it's because the Bourne shell now supports shell functions?
-- 
 -------------------------------    Disclaimer:  The views contained herein are
|       dan levy | yvel nad      |  my own and are not at all those of my em-
|         an engihacker @        |  ployer or the administrator of any computer
| at&t computer systems division |  upon which I may hack.
|        skokie, illinois        |
 --------------------------------   Path: ..!ihnp4!ttrdc!levy

vsh@pixdoc.UUCP (Steve Harris) (11/16/85)

In <10@druri.UUCP>, clive@druri.UUCP (StewardCN) writes:

> Out of curiosity, just why don't you want to put in command aliasing?

It's there, called shell functions!  e.g.:

	l () { ls -FCs $* ; }

-- 

Steve Harris            |  {allegra|ihnp4|cbosgd|ima|genrad|amd|harvard}\
Pixel Systems Inc.      |               !wjh12!pixel!pixdoc!vsh
300 Wildwood Street     |
Woburn, MA  01801       |  617-933-7735 x2314

cspencer@bbncc5.UUCP (Clifford Spencer) (11/17/85)

> > Out of curiosity, just why don't you want to put in command aliasing?
> It's there, called shell functions!  e.g.:
> 	l () { ls -FCs $* ; }
I think the most glaring difference between csh aliasing and
sys5 bourne shell functions is that the latter looks up builtins first.
This means you can't define functions that clash with shell commands.
On the other hand shell functions have a MUCH better syntax. Why not
move up the expansion of shell functions ahead of builtins at
the expense of not having recursive functions.
					-cliff
-- 
cliff spencer
{harvard, ihnp4, decvax}!bbnccv!cspencer
cspencer@bbncc5

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (11/18/85)

> I think the most glaring difference between csh aliasing and
> sys5 bourne shell functions is that the latter looks up builtins first.
> This means you can't define functions that clash with shell commands.
> On the other hand shell functions have a MUCH better syntax. Why not
> move up the expansion of shell functions ahead of builtins at
> the expense of not having recursive functions.

Very good question.  My guess is that either (a) it was easier
to do it the other way, or (b) it would be considered a security
problem in restricted shells.  Can DGK tell us why?

chris@pixutl.UUCP (chris) (11/18/85)

> 
> > I think the most glaring difference between csh aliasing and
> > sys5 bourne shell functions is that the latter looks up builtins first.
> > This means you can't define functions that clash with shell commands.
> > On the other hand shell functions have a MUCH better syntax. Why not
> > move up the expansion of shell functions ahead of builtins at
> > the expense of not having recursive functions.
> 
> Very good question.  My guess is that either (a) it was easier
> to do it the other way, or (b) it would be considered a security
> problem in restricted shells.  Can DGK tell us why?

The main implementation problem in having functions overrule builtins is
that both builtins and functions share the same B-tree. If you wanted to
have a function with the same name as a builtin, you would have to save
it somewhere, add new flags, etc... all that adding overhead and
complexity.


Chris
-- 

 Chris Bertin            :         (617) 933-7735 x2336
 Pixel Systems Inc.      :	   (800) 325-3342
 300 Wildwood street     :  {allegra|ihnp4|cbosgd|ima|genrad|amd|harvard}\
 Woburn, Ma 01801        :     !wjh12!pixel!pixutl!chris

arnold@gatech.CSNET (Arnold Robbins) (11/19/85)

Key: >>> unknown >> Doug Gwyn > Chris Bertin

In article <10@pixutl.UUCP> chris@pixutl.UUCP (chris) writes:
>> 
>>> I think the most glaring difference between csh aliasing and
>>> sys5 bourne shell functions is that the latter looks up builtins first.
>>> This means you can't define functions that clash with shell commands.
>>> On the other hand shell functions have a MUCH better syntax. Why not
>>> move up the expansion of shell functions ahead of builtins at
>>> the expense of not having recursive functions.
>> 
>> Very good question.  My guess is that either (a) it was easier
>> to do it the other way, or (b) it would be considered a security
>> problem in restricted shells.  Can DGK tell us why?
>
> The main implementation problem in having functions overrule builtins is
> that both builtins and functions share the same B-tree. If you wanted to
> have a function with the same name as a builtin, you would have to save
> it somewhere, add new flags, etc... all that adding overhead and
> complexity.
>
>
> Chris

Sorry Chris, but builtins (cd, test, etc.) have their own private table.
The S5R2 shell keeps it sorted for a quick binary search, earlier Bourne
shell's used a linear search that checked the first character, and then the
rest of the word.

It is shell functions and shell variables that share the same b-tree, and in
fact it would not be all that hard to have shell functions found first.
That is apparently what Rob Pike did for the 8th Edition shell. I may try
to implement the "builtin" built-in command he described, and put shell
functions first; that will come after everything else I'm working on is done.

Yet another Unix wizard defeated by the Bourne shell! :-) Just kidding Chris,
the changes you mailed to me have already been incorporated in what I'm
doing.

As I've said before, "Nuke the csh!"
-- 
Arnold Robbins
CSNET:	arnold@gatech	ARPA:	arnold%gatech.csnet@csnet-relay.arpa
UUCP:	{ akgua, allegra, hplabs, ihnp4, seismo, ut-sally }!gatech!arnold

Real Unix hackers disdain wimpy languages like C and AWK in favor of /bin/sh.

rich@rexago1.UUCP (K. Richard Magill) (11/24/85)

In article <21@pixdoc.UUCP> vsh@pixdoc.UUCP (Steve Harris) writes:
>> Out of curiosity, just why don't you want to put in command aliasing?
>It's there, called shell functions!  e.g.:
>	l () { ls -FCs $* ; }

I'd just like to point out that bourne shell ONLY reads .profile & that
shell functions do not export to subshells.  Thus, when I call shl from
my .profile (something vaguely akin to job control) all shell functions
go bye-bye.  (of course ksh addresses this quite nicely).

K. Richard Magill

rich@rexago1.UUCP (K. Richard Magill) (11/24/85)

In article <161@nitrex.UUCP> rob@nitrex.UUCP (rob robertson) writes:
>My main problem with SysV's version of Bourne Shell is that functions
>don't stick around in a new invocation of the shell.  In Berkley a
>.cshrc is executed when ever a new shell is involked keeping the alias
>around.  Korn shell fixed that by providing an enviornment variable,
>ENV which contains the name of a file to be executed whenever a new shell
>is involked.  Also in Korn shell, he provides BOTH aliasing and functions.
>Aliasing is faster, but functions are more complex.
>

ksh functions can also be exported.

K. Richard Magill

rob@nitrex.UUCP (rob robertson) (11/24/85)

> I think the most glaring difference between csh aliasing and
> sys5 bourne shell functions is that the latter looks up builtins first.
> This means you can't define functions that clash with shell commands.
> On the other hand shell functions have a MUCH better syntax. Why not
> move up the expansion of shell functions ahead of builtins at
> the expense of not having recursive functions.

My main problem with SysV's version of Bourne Shell is that functions
don't stick around in a new invocation of the shell.  In Berkley a
.cshrc is executed when ever a new shell is involked keeping the alias
around.  Korn shell fixed that by providing an enviornment variable,
ENV which contains the name of a file to be executed whenever a new shell
is involked.  Also in Korn shell, he provides BOTH aliasing and functions.
Aliasing is faster, but functions are more complex.

-- 

			rob robertson		decvax!cwruecmp!nitrex!rob.UUCP
	 		(216) 791-0922			 cbosgd!nitrex!rob.UUCP
			nitrex!rob@case.CSNET  nitrex!rob%case@csnet-relay.ARPA

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (11/25/85)

> I'd just like to point out that bourne shell ONLY reads .profile & that
> shell functions do not export to subshells.  Thus, when I call shl from
> my .profile (something vaguely akin to job control) all shell functions
> go bye-bye.  (of course ksh addresses this quite nicely).

But Arnold Robbins's shells read .shrc if it exists.  I haven't
put this into the BRL Bourne shell; I'd rather have exported
functions and in any case the shell is already too big.

mike@whuxl.UUCP (BALDWIN) (11/26/85)

> >My main problem with SysV's version of Bourne Shell is that functions
> >don't stick around in a new invocation of the shell.  In Berkley a
> >.cshrc is executed when ever a new shell is involked keeping the alias
> >around.  Korn shell fixed that by providing an enviornment variable,
> >ENV which contains the name of a file to be executed whenever a new shell
> >is involked.  Also in Korn shell, he provides BOTH aliasing and functions.

I think providing *both* aliasing and functions is a misfeature!  Why have
two inconsistent ways of doing the same thing???

> >Aliasing is faster, but functions are more complex.  [robertson]

I can't believe that aliases are so much faster that it warrants having
both schemes around.  After all, they are both done in the shell without
forking, and the fork/exec is the time-waster.

> ksh functions can also be exported.  [magill]

But not *really* exported; they only get exported to shell files spawned
directly from the ksh.  I.e., the functions don't go into the "real"
environment like in V8 so a ksh escape from vi won't have the exported
functions in it.  You need to use $ENV (aka .cshrc) in this case.  The
SVR2 shell functions are implicitly exported in this way (to *direct*
descendants).

"Real" exported functions ala V8 are very nice.  However, something like
$ENV can still be useful for things like setting certain options for
all invoked shell (e.g., set -au) or having the prompt show the level
(PS1=">$PS1").  The only way to do these things is with $ENV.

Back to my first point:  please don't implement something 2 or 3 times
in different ways!  Functions subsume aliases very nicely, so chuck
aliases!  Don't have funny % sequences in prompt strings when `uname`
or `pwd` will work fine.  If speed is the problem, then OK, speed it
up, but don't reimplement it unless there's an obviously better way
to do things.  I.e., if pwd is slow, build pwd into the shell instead
of adding a $PWD or $cwd variable.  However, instead of building in fd2
(remember fd2?), extend redirection to include file descriptors.
-- 
						Michael Baldwin
						{at&t}!whuxl!mike

arnold@gatech.CSNET (Arnold Robbins) (11/26/85)

In article <847@whuxl.UUCP> mike@whuxl.UUCP (BALDWIN) writes:
>I think providing *both* aliasing and functions is a misfeature!  Why have
>two inconsistent ways of doing the same thing???

I agree, which is one of the reasons I'm not putting aliasing in.

>"Real" exported functions ala V8 are very nice.  However, something like
>$ENV can still be useful for things like setting certain options for
>all invoked shell (e.g., set -au) or having the prompt show the level
>(PS1=">$PS1").  The only way to do these things is with $ENV.

My first go 'round used $HOME/.shrc, ala the csh. This time I am implementing
$ENV, like the ksh. Also checking for ./.profile and them $HOME/.profile,
like the ksh. Exported functions would be real nice, but I don't think I'm going
to have time to try and figure that one out.

>Back to my first point:  please don't implement something 2 or 3 times
>in different ways!

Agreed! Everything that I will add that is ksh compatible will have the same
syntax and semantics (or as near as I can make it, without a ksh to check
against).  If I add something to the shell that is similar but not exactly the
same as the ksh, it will have a DIFFERENT syntax, so that you know you're doing
something non-standard. (I do have a ksh man page, obtained from AT&T, with
the help of David Korn and the folks at the toolchest. Don't go flooding them
with requests for it, though.)

> ....Functions subsume aliases very nicely, so chuck
>aliases!  Don't have funny % sequences in prompt strings when `uname`
>or `pwd` will work fine.

The problem is that PS1="`pwd` " will only evaluate pwd once, and one would
want whatever the directory is now. Same with PS1="$PWD ". Which is why I
use funny % sequences. At least no one else uses them.

>              I.e., if pwd is slow, build pwd into the shell instead
>of adding a $PWD or $cwd variable.

Once pwd is built in, $PWD is almost trivial (having just done it...)

>However, instead of building in fd2
>(remember fd2?), extend redirection to include file descriptors.

I do indeed remember fd2, on a pdp-11/70 running INTERactive Systems IS/1
(A V6, sort of, look alike. Really bad)

>						Michael Baldwin

Anyway, I'm not really arguing, but since the ksh isn't public domain, I will
do my best to be as compatible with it as I can, and when I add features,
they will have a different syntax than the ksh. My goal is not replace or denigrate
what David Korn has done; but to fill a gap out there for those who can't get
the ksh, and who, on BSD systems, don't like the csh.

-- 
Arnold Robbins
CSNET:	arnold@gatech	ARPA:	arnold%gatech.csnet@csnet-relay.arpa
UUCP:	{ akgua, allegra, hplabs, ihnp4, seismo, ut-sally }!gatech!arnold

Real Unix hackers disdain wimpy languages like C and AWK in favor of /bin/sh.

davest@lumiere.UUCP (Dave Stewart) (11/27/85)

In article <847@whuxl.UUCP> mike@whuxl.UUCP (BALDWIN) writes:
>I think providing *both* aliasing and functions is a misfeature!  Why have
>two inconsistent ways of doing the same thing???
> ...
>Back to my first point:  please don't implement something 2 or 3 times
>in different ways!  Functions subsume aliases very nicely, so chuck
>aliases!

	The same thing could be said for the "for" "while-do" and "do-while"
constructs in C.  It can be proven that any of these can be subsumed
by one of them - so why have all THREE ways of doing the same thing?  Well,
history for one thing and programmer convenience for another.  That's why
you provide both aliases and functions - aliases have a history (excuse the
pun) in csh.  Having both is more convenient.

	In ksh, aliases take on other roles as well: tracked aliases
are as a replacement for the command hashing of csh.  There are also a
handful of aliases predefined upon shell invocation which (in a sense)
provide the user with more things that look like builtins without
actually adding more builtins.

	I think most people who have both aliases and functions available
use aliases as command-name macros and shell functions like programming
language functions.  Well, the analogy isn't perfect, since one also
has shell scripts to act as "functions", but I believe the concept is
transferable.  Do I want to chuck out macros because I have functions
available?  Heck no.

	Finally, there is a line in the ksh intro paper that reads, "Functions
are more general than aliases but also more costly."  Well, I guess
that's implementation-dependant, but intuition would tend to support
this, even when one considers that functions usually take up more text
chars before being read.

-- 
David C. Stewart                          uucp:    tektronix!davest
Unix Systems Support Group                csnet:   davest@TEKTRONIX
Tektronix, Inc.                           phone:   (503) 627-5418

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (11/29/85)

> > ....Functions subsume aliases very nicely, so chuck
> >aliases!  Don't have funny % sequences in prompt strings when `uname`
> >or `pwd` will work fine.
> 
> The problem is that PS1="`pwd` " will only evaluate pwd once, and one would
> want whatever the directory is now. Same with PS1="$PWD ". Which is why I
> use funny % sequences. At least no one else uses them.

But you can get this to work nicely if you redefine the "cd"
built-in as a shell function (if your shell functions work like
8th Ed. UNIX and not like SVR2).  Since I have an SVR2 shell,
I can't redefine "cd", so I use "ch" instead.  Here `tis:

ch(){			# should be cd
	if [ $# -lt 1 ]
	then	cd	# should be built-in cd
	else	cd $1	# ditto
	fi
	PS1=`uname | sed s/\^brl-// | tr '[a-z]' '[A-Z]'`:`pwd`'$ '
}

Yes, this is a more elaborate PS1, but it makes the point.

Berkeley users just have to suffer, but then they are so used to that
that they have probably convinced themselves that everything is great.
It's nice of you to try to help them out.