Exiting to top-level shell from within a nested sourced script?
<p>I want to provide a trap that exits from a <code>bash</code> script if it was sourced rather than executed, but I want to provide the trap in another (library) file that is sourced. Scripts might be organised like this:</p>

<pre><code>a        sourced by code external to the library
+--b     sourced by a
   +-- c sourced by b
</code></pre>

<p>There may be many levels of nesting (more than one file like <code>b</code>). The <code>c</code> file needs to contain code that will make <code>a</code> exit gracefully (and with a nonzero exit status set by <code>c</code>) if <code>a</code> is sourced.</p>

<p>A graceful exit is one that behaves similarly to an executed script that calls <code>exit</code>.</p>

<p><strong>When to terminate</strong></p>

<p>A <code>bash</code> script can use the <code>BASH_SOURCE</code> array to ascertain whether it was sourced itself or whether the outermost script was sourced. </p>

<p>The stack of scripts is avaiable as the array <code>${BASH_SOURCE[@]}</code> where the first element is the most recent script and the last is the first. Therefore it follows that:</p>

<ul>
<li>the current script (e.g. <code>c</code>) is <code>${BASH_SOURCE[0]}</code></li>
<li>the outermost script (e.g <code>a</code>) is <code>${BASH_SOURCE[-1]}</code></li>
<li>the executable is <code>$0</code></li>
</ul>

<p>To assert that the current script was executed:</p>

<pre><code>[[ "${BASH_SOURCE[0]}" == "$0" ]]
</code></pre>

<p>To assert that the outermost script was executed:</p>

<pre><code>[[ "${BASH_SOURCE[-1]" == "$0" ]]
</code></pre>

<p>So, script <code>c</code> can determine whether script <code>a</code> was executed like this:</p>

<pre><code>[[ "${BASH_SOURCE[-1]" == "$0" ]] || terminate
</code></pre>

<p><strong>How to terminate</strong></p>

<p>What <code>c</code> cannot do is <code>terminate</code>. It can't <code>exit</code> because that would cause whatever sourced <code>a</code> to exit. The alternative is <code>return</code> but that only passes control back to the prior <code>b</code> script. Without <code>b</code> and, in turn, <code>a</code> co-operating, the termination would be ineffective.</p>

<p>This co-operation can be coded in <code>a</code> and <code>b</code> but a preferable solution would be one where <code>c</code> doesn't return control to <code>b</code> if <code>a</code> was sourced. </p>

<p><strong>Can <code>c</code> terminate <code>a</code> in an <code>exit</code>-like fashion ?</strong></p>

<p><em>I am pretty convinced that this is not possible because a sourced <code>a</code> is not in its own process, but it would be great to be shown otherwise. I thought perhaps a way to manipulate the call stack so a that <code>return</code> would return from <code>a</code> but there's probably too much voodoo in such thoughts...</em></p>