William Pursell
William Pursell

Reputation: 212494

How to make exit behave when "sourced" in csh

csh is an utterly horrible shell. (Making that statement up front to avoid the inevitable comments of "don't use csh", or perhaps I should just state that for the sake of any readers: please, if you value your sanity, do not use csh.) I have a rather large collection of csh scripts that I'm trying to make useful, and I just discovered that exit does not exit the script when called from a sourced file. In other words:

#!/bin/csh
source [file with content "exit"]
echo No reasonable script should print this

Produces output.

Is there any way to modify that behavior? As far as I can tell, the original authors of the scripts I am modifying intended the main script to terminate, and that certainly would be desirable behavior, and simply invoking the example above via sh produces that result, but what gives? Is there any reasonable purpose for this behavior? (That's just me ranting, the real question is: is there an option to csh to change the behavior?)

Upvotes: 7

Views: 4793

Answers (6)

Lakmal Dissanayaka
Lakmal Dissanayaka

Reputation: 1

unset TERMINATE

unsetenv TERMINATE

echo "$TERMINATE"

Upvotes: 0

Randy James
Randy James

Reputation: 31

Apropos the popular community sport I call 'csh bashing':

"csh is an utterly horrible shell."

Perhaps, but tcsh is a very easy to use, easy to code, lightweight and stable shell, available just about everywhere with fairly uniform features. Albeit, it does have some quirks which are frustrating until you learn to navigate around them. It helps to have a pretty-printer for long scripts.

The "source file [argv]" feature is the closest thing to a subroutine in tcsh, and since it shares the same namespace with the caller, it's perfectly reasonable that the exit command work more like a 'return' statement in that context. Note that an exit statement does suspend processing in the sourced file, and returns a value via $status.

Sourced tcsh files also allow the caller to post a separate $argv without losing the original, or not, in which case the caller's $argv is visible to the sourced file. If the sourced file writes to $argv, it's modified for the caller as well.

If you define an alias that sources a file, you can put together some fairly versatile multi-function scripts:

alias func 'set srcf="test.tcsf" ; set args=(!*) ; source $srcf $args'

However, if you have multiple source files in play, you need to adopt some namespace management conventions in order to insure they don't step on each other. Bottom-line, there are reasons tcsh is still in use after all these years, primarily that it's quick and easy to use, once you understand the quirks.

Upvotes: 1

Andrew Domaszek
Andrew Domaszek

Reputation: 681

To exit out of both the sourced script and the parent interpreter in csh/tcsh, I use exec /bin/false or exec /bin/true, depending on the success condition I want passed back to the parent process. The sourcing shell exits with the appropriate return value.

Upvotes: 8

chrishiestand
chrishiestand

Reputation: 3000

I don't think this pertains to the original context of the question, but if exit is being used to close a login script, and hence logout the user, you can just use logout instead of exit.

Upvotes: 2

estani
estani

Reputation: 26527

You can alias exit to setup some value and then check for it:

$ cat a.csh
#!/bin/csh
alias exit 'set abort=1; ""exit'
...
exit

And when sourcing the file:

$ cat b.csh
#!/bin/csh
source a.csh
if ( $?abort ) exit

Addendum:

I forgot to say you might change the source code on the fly:

$ cat b.csh
#!/bin/csh
source `sed '2 i alias exit '"'set abort=1; "'""exit'"'" a.csh`
if ( $?abort ) exit

This will have some penalty when compared as altering the script directly, but you don't need to bother about the original script anymore.

Upvotes: 0

happy coder
happy coder

Reputation: 1523

I don't claim to know much about csh, I mostly use "bash", and I think a long time ago in a land far away I might have used "ksh: on Sun "pizza" boxen. After poking around a bit, I noticed a few csh behvior change switches, but what if you tried something like this:

exit [expr]
The shell exits either with the value of the specified expr (an expression, as 
described   under Expressions) or, without expr, with the value of the status variable.

I got this from here

Upvotes: 0

Related Questions