home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!world!enterpoop.mit.edu!hri.com!spool.mu.edu!agate!stanford.edu!rutgers!ub!csn!teal.csn.org!bazyar
- From: bazyar@teal.csn.org (Jawaid Bazyar)
- Newsgroups: comp.unix.questions
- Subject: The Revenge of CSH
- Message-ID: <Bzz748.GDK@csn.org>
- Date: 28 Dec 92 15:31:18 GMT
- Sender: news@csn.org (news)
- Organization: Colorado SuperNet, Inc.
- Lines: 344
- Nntp-Posting-Host: teal.csn.org
-
-
- The reason for this reply is that I'm one of a number of folks working
- on a csh clone (called GSH, and for the GNO/ME system for the Apple IIgs).
- We intend to fix most if not all of these problems as we implement csh
- from scratch on a 16-bit platform. But I take offense to the manner in
- which csh's bugs are listed, and then be stated "csh sucks, is
- totally unworthy", basically.
- So, let the flamefest begin.
-
- > From: Tom Christiansen <tchrist@convex.COM>
- > Subject: Csh Programming Considered Harmful
- > Originator: tchrist@pixel.convex.com
- > X-Disclaimer: This message was written by a user at CONVEX Computer
- > Corp. The opinions expressed are those of the user and
- > not necessarily those of CONVEX.
-
- > The following periodic article answers in excruciating detail
- > the frequently asked question "Why shouldn't I program in csh?".
- > It is available for anon FTP from convex.com in /pub/csh.whynot .
- >
- > Csh Programming Considered Harmful
- >
- > Resolved: The csh is a tool utterly inadequate for programming, and
- > its use for such purposes should be strictly banned.
-
- Oops. I've used csh scripts before. Shall I beg forgiveness?
-
- > I am continually shocked and dismayed to see people write test cases,
- > install scripts, and other random hackery using the csh.
-
- I am continually shocked and dismayed to see people not have
- command line editing, arrow-key history, job control, or many
- of the other things that csh (tcsh) provides and /bin/sh does not.
-
- > Lack of
- > proficiency in the Bourne shell has been known to cause errors in /etc/rc
- > and .cronrc files, which is a problem, because you *must* write these files
- > in that language.
-
- That would seem to be braindamage on the part of the kernel and cron,
- don't you think?
-
- [..]
-
- > FILE DESCRIPTORS
- >
- > The most common problem encountered in csh programming is that
- > you can't do file-descriptor manipulation. All you are able to
- > do is redirect stdin, or stdout, or dup stderr into stdout.
- > Bourne-compatible shells offer you an abundance of more exotic
- > possibilities.
-
- Possibilities that could be added to csh, if anyone cared to.
- [...]
-
- > Writing Files
- >
- > In the Bourne shell, you can open or dup random file descriptors.
- > For example,
- > exec 2>errs.out
- > means that from then on, stderr goes into errs file.
- > Or what if you just want to throw away stderr and leave stdout
- > alone? Pretty simple operation, eh?
- > cmd 2>/dev/null
- > Works in the Bourne shell. In the csh, you can only make a pitiful
- > attempt like this:
- > (cmd > /dev/tty) >& /dev/null
- > But who said that stdout was my tty? So it's wrong. This simple
- > operation *CANNOT BE DONE* in the csh.
-
- Trivially fixed, by making >& _only_ redirect stderr, and having
- the shell check appropriately for > and >& going to the same file.
- I envison, oh, 10 lines of code?
-
- [...]
-
- > Reading Files
- >
- > In the csh, all you've got is $<, which reads a line from your tty. What
- > if you've redirected stdin? Tough noogies, you still get your tty, which
- > you really can't redirect. Now, the read statement
- > in the Bourne shell allows you to read from stdin, which catches
- > redirection. It also means that you can do things like this:
-
- Okay, add a read statement to csh.
-
- > Although in older ones where read only goes from 0, you trick it:
-
- [..]
-
- > You want to know the status of C, well, that's easy: it's in $?, or
- > $status in csh. But if you want it from A, you're out of luck -- if
- > you're in the csh, that is. In the Bourne shell, you can get it, although
- > doing so is a bit tricky. Here's something I had to do where I ran dd's
-
- "bit tricky" seems a lot like "totally unsuited to" a task, to me.
-
- > stderr into a grep -v pipe to get rid of the records in/out noise, but had
- > to return the dd's exit status, not the grep's:
- >
- > device=/dev/rmt8
- > dd_noise='^[0-9]+\+[0-9]+ records (in|out)$'
- > exec 3>&1
- > status=`((dd if=$device ibs=64k 2>&1 1>&3 3>&- 4>&-; echo $? >&4) |
- > egrep -v "$dd_noise" 1>&2 3>&- 4>&-) 4>&1`
- > exit $status;
-
- Hmm. Too bad that's unreadable! :)
-
- > COMMAND ORTHOGONALITY
- >
- > Built-ins
- >
- > The csh is a horrid botch with its built-ins. You can't put them
- > together in many reasonable way. Even simple little things like this:
- >
- > % time | echo
-
- He admits that the code is nonsensical!
-
- > which while nonsensical, shouldn't give me this message:
- >
- > Reset tty pgrp from 9341 to 26678
-
- I.e., csh has a bug. Not a design deficiency, but a bug.
-
- > Others are more fun:
- >
- > % sleep 1 | while
- > while: Too few arguments.
- > [5] 9402
- > % jobs
- > [5] 9402 Done sleep |
- > Some can even hang your shell. Try typing ^Z while you're sourcing
- > something, or redirecting a source command. Just make sure you have
- > another window handy. Or try
- >
- > % history | more
- >
- > on some systems.
-
- "on some systems" means that there's a bug in csh on some systems,
- not that csh is devil-spawn.
-
- > Flow control
- >
- > You can't mix flow-control and commands, like this:
- >
- > who | while read line; do
- > echo "gotta $line"
- > done
- >
- > You can't combine multiline constructs in a csh using semicolons.
- > There's no easy way to do this
- >
- > alias cmd 'if (foo) then bar; else snark; endif'
-
- This is an implementation problem; csh's designers decided to do it
- one way, and that's what they got. Strangely enough, it's _less_
- code to make it as free-form as possible, and in fact GSH 2.0 will
- allow the above.
-
- > Stupid parsing bugs
-
- ^^^^ He devotes a whole section to implementation errors. These
- are _bugs_, i.e. they could be fixed or avoided in a new implementation
- (like GSH).
-
- > SIGNALS
- >
- > In the csh, all you can do with signals is trap SIGINT. In the Bourne
- > shell, you can trap any signal, or the end-of-program exit. For example,
- > to blow away a tempfile on any of a variety of signals:
-
- Too bad the Bourne shell doesn't support real BSD job control.
-
- > 6. QUOTING
-
- > You can't quote things reasonably in the csh:
-
- > set foo = "Bill asked, \"How's tricks?\""
-
- > doesn't work. This makes it really hard to construct strings with
- > mixed quotes in them. In the Bourne shell, this works just fine.
- > In fact, so does this:
- >
- > cd /mnt; /usr/ucb/finger -m -s `ls \`u\``
- >
- > Dollar signs cannot be escaped in double quotes in the csh. Ug.
- >
- > set foo = "this is a \$dollar quoted and this is $HOME not quoted"
- > dollar: Undefined variable.
-
- Another bug.
-
- > You have to use backslashes for newlines, and it's just darn hard to
- > get them into strings sometimes.
-
- Design limitation (gosh, finally got one).
-
- > Say what? You don't have these problems in the Bourne shell, where it's
- > just fine to write things like this:
- > echo 'This is
- > some text that contains
- > several newlines.'
-
- So what?
-
- > As distributed, quoting history references is a challenge. Consider:
- >
- > % mail adec23!alberta!pixel.Convex.COM!tchrist
- > alberta!pixel.Convex.COM!tchri: Event not found.
-
- Gosh, that's like saying "csh is broken because I can't do this:
-
- mail FX3$LRG@a.b.c.d
-
- > VARIABLE SYNTAX
- >
- > There's this big difference between global (environment) and local
- > (shell) variables. In csh, you use a totally different syntax
- > to set one from the other.
- >
- > In Bourne shell, this
- > VAR=foo cmds args
- > is the same as
- > (export VAR; VAR=foo; cmd args)
- > or csh's
- > (setenv VAR; cmd args)
- >
- > You can't use :t, :h, etc on envariables. Watch:
- > echo Try testing with $SHELL:t
- >
- > It's really nice to be able to say
- >
- > ${PAGER-more}
- > or
- > FOO=${BAR:-${BAZ}}
- >
- > to be able to run the user's PAGER if set, and more otherwise.
- > You can't do this in the csh. It takes more verbiage.
-
- Excuse me? "You can't do this" and "It takes more verbiage" means
- IT CAN BE DONE.
- Why didn't you add: "C can't pass strings around on the stack like Pascal can.
- It takes more verbiage. C is obviously inferior to Pascal."
-
- > You can't get the process number of the last background command from the
- > csh, something you might like to do if you're starting up several jobs in
- > the background. In the Bourne shell, the pid of the last command put in
- > the background is available in $!.
-
- And it could be added to csh with about two lines of code.
-
- > EXPRESSION EVALUATION
- >
- > Consider this statement in the csh:
- >
- >
- > if ($?MANPAGER) setenv PAGER $MANPAGER
- >
- >
- > Despite your attempts to only set PAGER when you want
- > to, the csh aborts:
- >
- > MANPAGER: Undefined variable.
- >
- > That's because it parses the whole line anyway AND EVALUATES IT!
- > You have to write this:
- >
- > if ($?MANPAGER) then
- > setenv PAGER $MANPAGER
- > endif
- >
- > That's the same problem you have here:
- >
- > if ($?X && $X == 'foo') echo ok
- > X: Undefined variable
- >
- > This forces you to write a couple nested if statements. This is highly
- > undesirable because it renders short-circuit booleans useless in
- > situations like these. If the csh were the really C-like, you would
- > expect to be able to safely employ this kind of logic.
-
- A valid point (finally!). But, it could still be fixed pretty easily.
-
- > While the csh does have built-in expression handling, it's not
- > what you might think. In fact, it's space sensitive. This is an
- > error
- >
- > @ a = 4/2
- > but this is ok
- > @ a = 4 / 2
-
- So golly, it's got a stupid lexer. Want my replacement? And is
- it really that big a deal to delimit the numbers with spaces? I mean,
- there are plenty of other situations you must use spaces. I'll bet
- not even Bourne shell knows what to do with:
-
- ls-1/bin/foo
-
- According to you, there exists the possiblity that a lexer smart
- enough to deal with that statement exists, therefore csh is inherently
- flawed because it doesn't implement that lexer?
-
- > RANDOM BUGS
-
- They're bugs, so they could be fixed.
-
- > SUMMARY
- > While some vendors have fixed some of the csh's bugs (the tcsh also does
- > much better here), many have added new ones. Most of its problems can
- > never be solved because they're not actually bugs per se, but rather the
- > direct consequences of braindead design decisions. It's inherently flawed.
-
- That's garbage. You have shown no proof for that statement. I'm
- supposed to read a bug list and then believe that all the bugs are
- caused because csh is "inherently flawed"?
-
- > Do yourself a favor, and if you *have* to write a shell script, do it in the
- > Bourne shell. It's on every UNIX system out there. However, behavior
- > can vary.
-
- Gee.. that means that /bin/sh isn't the universal be-all end-all of
- shells? You don't say? You mean /bin/sh has bugs? Really?
-
- > Tom Christiansen tchrist@convex.com convex!tchrist
- >
- > "UNIX was not designed to stop you from doing stupid things, because
- > that would also stop you from doing clever things." -- Doug Gwyn
-
- You're not cool enough to quote Doug Gwyn. Really; it seems that
- 'csh sucks' in your opinion because it's not /bin/sh. Care to try
- again?
-
- All in all, I'm sorely tempted to grab the existing csh source
- and fix it, but I'll continue on our from-scratch project and
- do it that way.
-
- --
- Jawaid Bazyar | Ask me about the GNO Multitasking Environment
- Procyon, Inc. | for the Apple IIgs!
- bazyar@cs.uiuc.edu | P.O Box 620334
- --Apple II Forever!-- | Littleton, CO 80162-0334 (303) 933-4649
-