home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / unix / question / 14996 < prev    next >
Encoding:
Internet Message Format  |  1992-12-28  |  11.7 KB

  1. Path: sparky!uunet!world!enterpoop.mit.edu!hri.com!spool.mu.edu!agate!stanford.edu!rutgers!ub!csn!teal.csn.org!bazyar
  2. From: bazyar@teal.csn.org (Jawaid Bazyar)
  3. Newsgroups: comp.unix.questions
  4. Subject: The Revenge of CSH
  5. Message-ID: <Bzz748.GDK@csn.org>
  6. Date: 28 Dec 92 15:31:18 GMT
  7. Sender: news@csn.org (news)
  8. Organization: Colorado SuperNet, Inc.
  9. Lines: 344
  10. Nntp-Posting-Host: teal.csn.org
  11.  
  12.  
  13.   The reason for this reply is that I'm one of a number of folks working
  14. on a csh clone (called GSH, and for the GNO/ME system for the Apple IIgs).
  15. We intend to fix most if not all of these problems as we implement csh
  16. from scratch on a 16-bit platform.  But I take offense to the manner in 
  17. which csh's bugs are listed, and then be stated "csh sucks, is 
  18. totally unworthy", basically.  
  19.   So, let the flamefest begin.
  20.  
  21. > From: Tom Christiansen <tchrist@convex.COM>
  22. > Subject: Csh Programming Considered Harmful 
  23. > Originator: tchrist@pixel.convex.com
  24. > X-Disclaimer: This message was written by a user at CONVEX Computer
  25. >               Corp. The opinions expressed are those of the user and
  26. >               not necessarily those of CONVEX.
  27.  
  28. > The following periodic article answers in excruciating detail
  29. > the frequently asked question "Why shouldn't I program in csh?".
  30. > It is available for anon FTP from convex.com in /pub/csh.whynot .
  31. >            Csh Programming Considered Harmful
  32. > Resolved: The csh is a tool utterly inadequate for programming, and
  33. > its use for such purposes should be strictly banned.
  34.  
  35.    Oops.  I've used csh scripts before.  Shall I beg forgiveness?
  36.  
  37. > I am continually shocked and dismayed to see people write test cases,
  38. > install scripts, and other random hackery using the csh.  
  39.  
  40.   I am continually shocked and dismayed to see people not have
  41. command line editing, arrow-key history, job control, or many
  42. of the other things that csh (tcsh) provides and /bin/sh does not.
  43.  
  44. > Lack of
  45. > proficiency in the Bourne shell has been known to cause errors in /etc/rc
  46. > and .cronrc files, which is a problem, because you *must* write these files
  47. > in that language.
  48.  
  49.   That would seem to be braindamage on the part of the kernel and cron,
  50. don't you think?
  51.  
  52. [..]
  53.  
  54. > FILE DESCRIPTORS
  55. > The most common problem encountered in csh programming is that
  56. > you can't do file-descriptor manipulation.  All you are able to 
  57. > do is redirect stdin, or stdout, or dup stderr into stdout. 
  58. > Bourne-compatible shells offer you an abundance of more exotic
  59. > possibilities.    
  60.  
  61.   Possibilities that could be added to csh, if anyone cared to.
  62. [...]
  63.  
  64. > Writing Files
  65. > In the Bourne shell, you can open or dup random file descriptors.
  66. > For example, 
  67. >     exec 2>errs.out
  68. > means that from then on, stderr goes into errs file.
  69. > Or what if you just want to throw away stderr and leave stdout
  70. > alone?    Pretty simple operation, eh?
  71. >     cmd 2>/dev/null
  72. > Works in the Bourne shell.  In the csh, you can only make a pitiful 
  73. > attempt like this:
  74. >     (cmd > /dev/tty) >& /dev/null
  75. > But who said that stdout was my tty?  So it's wrong.  This simple
  76. > operation *CANNOT BE DONE* in the csh.
  77.  
  78.   Trivially fixed, by making >& _only_ redirect stderr, and having
  79. the shell check appropriately for > and >& going to the same file.
  80. I envison, oh, 10 lines of code? 
  81.  
  82. [...]
  83.  
  84. > Reading Files
  85. > In the csh, all you've got is $<, which reads a line from your tty.  What
  86. > if you've redirected stdin?  Tough noogies, you still get your tty, which 
  87. > you really can't redirect.  Now, the read statement 
  88. > in the Bourne shell allows you to read from stdin, which catches
  89. > redirection.  It also means that you can do things like this:
  90.  
  91.   Okay, add a read statement to csh.
  92.  
  93. > Although in older ones where read only goes from 0, you trick it:
  94.  
  95.   [..]
  96.  
  97. > You want to know the status of C, well, that's easy: it's in $?, or
  98. > $status in csh.  But if you want it from A, you're out of luck -- if
  99. > you're in the csh, that is.  In the Bourne shell, you can get it, although
  100. > doing so is a bit tricky.  Here's something I had to do where I ran dd's
  101.  
  102.    "bit tricky" seems a lot like "totally unsuited to" a task, to me.
  103.   
  104. > stderr into a grep -v pipe to get rid of the records in/out noise, but had
  105. > to return the dd's exit status, not the grep's:
  106. >     device=/dev/rmt8
  107. >     dd_noise='^[0-9]+\+[0-9]+ records (in|out)$'
  108. >     exec 3>&1
  109. >     status=`((dd if=$device ibs=64k 2>&1 1>&3 3>&- 4>&-; echo $? >&4) |
  110. >         egrep -v "$dd_noise" 1>&2 3>&- 4>&-) 4>&1`
  111. >     exit $status;
  112.  
  113.   Hmm.  Too bad that's unreadable! :)
  114.  
  115. > COMMAND ORTHOGONALITY
  116. > Built-ins
  117. > The csh is a horrid botch with its built-ins.  You can't put them
  118. > together in many reasonable way.   Even simple little things like this:    
  119. >         % time | echo
  120.  
  121.   He admits that the code is nonsensical!
  122.  
  123. > which while nonsensical, shouldn't give me this message:
  124. >         Reset tty pgrp from 9341 to 26678
  125.  
  126.   I.e., csh has a bug.  Not a design deficiency, but a bug.
  127.  
  128. > Others are more fun:
  129. >         % sleep 1 | while
  130. >         while: Too few arguments.
  131. >         [5] 9402
  132. >         % jobs
  133. >         [5]     9402 Done                 sleep |
  134. > Some can even hang your shell.  Try typing ^Z while you're sourcing 
  135. > something, or redirecting a source command.  Just make sure you have
  136. > another window handy.  Or try 
  137. >     % history | more
  138. > on some systems.
  139.  
  140.   "on some systems" means that there's a bug in csh on some systems,
  141. not that csh is devil-spawn.
  142.  
  143. > Flow control
  144. > You can't mix flow-control and commands, like this:
  145. >     
  146. >     who | while read line; do
  147. >     echo "gotta $line"
  148. >     done
  149. > You can't combine multiline constructs in a csh using semicolons.
  150. > There's no easy way to do this
  151. >     alias cmd 'if (foo) then bar; else snark; endif'
  152.  
  153.   This is an implementation problem; csh's designers decided to do it
  154. one way, and that's what they got.  Strangely enough, it's _less_
  155. code to make it as free-form as possible, and in fact GSH 2.0 will
  156. allow the above.
  157.  
  158. > Stupid parsing bugs
  159.  
  160.   ^^^^  He devotes a whole section to implementation errors.  These
  161. are _bugs_, i.e. they could be fixed or avoided in a new implementation
  162. (like GSH).
  163.  
  164. > SIGNALS
  165. > In the csh, all you can do with signals is trap SIGINT.  In the Bourne
  166. > shell, you can trap any signal, or the end-of-program exit.    For example,
  167. > to blow away a tempfile on any of a variety of signals:
  168.  
  169.   Too bad the Bourne shell doesn't support real BSD job control.
  170.  
  171. > 6.  QUOTING
  172.  
  173. > You can't quote things reasonably in the csh:
  174.  
  175. >     set foo = "Bill asked, \"How's tricks?\""
  176.  
  177. > doesn't work.  This makes it really hard to construct strings with
  178. > mixed quotes in them.  In the Bourne shell, this works just fine. 
  179. > In fact, so does this:
  180. >      cd /mnt; /usr/ucb/finger -m -s `ls \`u\``
  181. > Dollar signs cannot be escaped in double quotes in the csh.  Ug.
  182. >     set foo = "this is a \$dollar quoted and this is $HOME not quoted" 
  183. >     dollar: Undefined variable.
  184.  
  185.   Another bug.
  186.  
  187. > You have to use backslashes for newlines, and it's just darn hard to
  188. > get them into strings sometimes.
  189.  
  190.   Design limitation (gosh, finally got one).
  191.  
  192. > Say what?  You don't have these problems in the Bourne shell, where it's
  193. > just fine to write things like this:
  194. >     echo     'This is 
  195. >          some text that contains
  196. >          several newlines.'
  197.  
  198.   So what?
  199.  
  200. > As distributed, quoting history references is a challenge.  Consider:
  201. >     % mail adec23!alberta!pixel.Convex.COM!tchrist
  202. >     alberta!pixel.Convex.COM!tchri: Event not found.
  203.  
  204.   Gosh, that's like saying "csh is broken because I can't do this:
  205.  
  206.   mail FX3$LRG@a.b.c.d
  207.  
  208. > VARIABLE SYNTAX
  209. > There's this big difference between global (environment) and local
  210. > (shell) variables.  In csh, you use a totally different syntax 
  211. > to set one from the other.  
  212. > In Bourne shell, this 
  213. >     VAR=foo cmds args
  214. >  is the same as
  215. >     (export VAR; VAR=foo; cmd args)
  216. > or csh's
  217. >     (setenv VAR;  cmd args)
  218. >  
  219. > You can't use :t, :h, etc on envariables.  Watch:
  220. >     echo Try testing with $SHELL:t
  221. > It's really nice to be able to say
  222. >     
  223. >     ${PAGER-more}
  224. > or
  225. >     FOO=${BAR:-${BAZ}}
  226. > to be able to run the user's PAGER if set, and more otherwise.
  227. > You can't do this in the csh.  It takes more verbiage.
  228.  
  229.   Excuse me?  "You can't do this" and "It takes more verbiage" means
  230. IT CAN BE DONE.  
  231.   Why didn't you add: "C can't pass strings around on the stack like Pascal can.
  232. It takes more verbiage.  C is obviously inferior to Pascal."
  233.  
  234. > You can't get the process number of the last background command from the
  235. > csh, something you might like to do if you're starting up several jobs in
  236. > the background.  In the Bourne shell, the pid of the last command put in
  237. > the background is available in $!.
  238.  
  239.   And it could be added to csh with about two lines of code.
  240.  
  241. > EXPRESSION EVALUATION
  242. > Consider this statement in the csh:
  243. >     if ($?MANPAGER) setenv PAGER $MANPAGER
  244. > Despite your attempts to only set PAGER when you want
  245. > to, the csh aborts:
  246. >     MANPAGER: Undefined variable.
  247. > That's because it parses the whole line anyway AND EVALUATES IT!
  248. > You have to write this:
  249. >     if ($?MANPAGER) then
  250. >     setenv PAGER $MANPAGER
  251. >     endif
  252. > That's the same problem you have here:
  253. >     if ($?X && $X == 'foo') echo ok
  254. >     X: Undefined variable
  255. > This forces you to write a couple nested if statements.  This is highly
  256. > undesirable because it renders short-circuit booleans useless in
  257. > situations like these.  If the csh were the really C-like, you would
  258. > expect to be able to safely employ this kind of logic. 
  259.  
  260.    A valid point (finally!).  But, it could still be fixed pretty easily.
  261.  
  262. > While the csh does have built-in expression handling, it's not
  263. > what you might think.  In fact, it's space sensitive.  This is an
  264. > error
  265. >    @ a = 4/2
  266. > but this is ok
  267. >    @ a = 4 / 2
  268.  
  269.   So golly, it's got a stupid lexer.  Want my replacement?  And is
  270. it really that big a deal to delimit the numbers with spaces? I mean,
  271. there are plenty of other situations you must use spaces.  I'll bet
  272. not even Bourne shell knows what to do with:
  273.  
  274.   ls-1/bin/foo
  275.  
  276.   According to you, there exists the possiblity that a lexer smart
  277. enough to deal with that statement exists, therefore csh is inherently
  278. flawed because it doesn't implement that lexer?
  279.  
  280. > RANDOM BUGS
  281.  
  282.   They're bugs, so they could be fixed.
  283.  
  284. > SUMMARY
  285. > While some vendors have fixed some of the csh's bugs (the tcsh also does
  286. > much better here), many have added new ones.  Most of its problems can
  287. > never be solved because they're not actually bugs per se, but rather the
  288. > direct consequences of braindead design decisions.  It's inherently flawed.
  289.  
  290.   That's garbage.  You have shown no proof for that statement.  I'm
  291. supposed to read a bug list and then believe that all the bugs are
  292. caused because csh is "inherently flawed"?
  293.  
  294. > Do yourself a favor, and if you *have* to write a shell script, do it in the 
  295. > Bourne shell.  It's on every UNIX system out there.  However, behavior 
  296. > can vary.
  297.  
  298.   Gee.. that means that /bin/sh isn't the universal be-all end-all of
  299. shells?  You don't say?  You mean /bin/sh has bugs?  Really?
  300.  
  301. >     Tom Christiansen      tchrist@convex.com      convex!tchrist
  302. >     "UNIX was not designed to stop you from doing stupid things, because
  303. >      that would also stop you from doing clever things." -- Doug Gwyn
  304.  
  305.    You're not cool enough to quote Doug Gwyn.  Really; it seems that
  306. 'csh sucks' in your opinion because it's not /bin/sh.  Care to try 
  307. again?
  308.  
  309.    All in all, I'm sorely tempted to grab the existing csh source
  310. and fix it, but I'll continue on our from-scratch project and 
  311. do it that way.
  312.  
  313. -- 
  314.  Jawaid Bazyar              |   Ask me about the GNO Multitasking Environment
  315.  Procyon, Inc.              |   for the Apple IIgs!   
  316.  bazyar@cs.uiuc.edu         |   P.O Box 620334
  317.  --Apple II Forever!--      |   Littleton, CO 80162-0334   (303) 933-4649
  318.