Imported from ../bash-1.14.7.tar.gz.
diff --git a/unwind_prot.c b/unwind_prot.c
new file mode 100644
index 0000000..d9399d7
--- /dev/null
+++ b/unwind_prot.c
@@ -0,0 +1,272 @@
+/* I can't stand it anymore!  Please can't we just write the
+   whole Unix system in lisp or something? */
+
+/* Copyright (C) 1987,1989 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 1, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with Bash; see the file COPYING.  If not, write to the Free Software
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* **************************************************************** */
+/*								    */
+/*		      Unwind Protection Scheme for Bash		    */
+/*								    */
+/* **************************************************************** */
+#include "bashtypes.h"
+#include <signal.h>
+#include "config.h"
+#include "command.h"
+#include "general.h"
+#include "unwind_prot.h"
+#include "quit.h"
+
+/* If CLEANUP is null, then ARG contains a tag to throw back to. */
+typedef struct _uwp {
+  struct _uwp *next;
+  Function *cleanup;
+  char *arg;
+} UNWIND_ELT;
+
+static void
+  unwind_frame_discard_internal (), unwind_frame_run_internal (),
+  add_unwind_protect_internal (), remove_unwind_protect_internal (),
+  run_unwind_protects_internal (), without_interrupts ();
+
+static UNWIND_ELT *unwind_protect_list = (UNWIND_ELT *)NULL;
+
+extern int interrupt_immediately;
+
+/* Run a function without interrupts.  This relies on the fact that the
+   FUNCTION cannot change the value of interrupt_immediately.  (I.e., does
+   not call QUIT (). */
+static void
+without_interrupts (function, arg1, arg2)
+     VFunction *function;
+     char *arg1, *arg2;
+{
+  int old_interrupt_immediately;
+
+  old_interrupt_immediately = interrupt_immediately;
+  interrupt_immediately = 0;
+
+  (*function)(arg1, arg2);
+
+  interrupt_immediately = old_interrupt_immediately;
+}
+
+/* Start the beginning of a region. */
+void
+begin_unwind_frame (tag)
+     char *tag;
+{
+  add_unwind_protect ((Function *)NULL, tag);
+}
+
+/* Discard the unwind protects back to TAG. */
+void
+discard_unwind_frame (tag)
+     char *tag;
+{
+  if (unwind_protect_list)
+    without_interrupts (unwind_frame_discard_internal, tag, (char *)NULL);
+}
+
+/* Run the unwind protects back to TAG. */
+void
+run_unwind_frame (tag)
+     char *tag;
+{
+  if (unwind_protect_list)
+    without_interrupts (unwind_frame_run_internal, tag, (char *)NULL);
+}
+
+/* Add the function CLEANUP with ARG to the list of unwindable things. */
+void
+add_unwind_protect (cleanup, arg)
+     Function *cleanup;
+     char *arg;
+{
+  without_interrupts (add_unwind_protect_internal, (char *)cleanup, arg);
+}
+
+/* Remove the top unwind protect from the list. */
+void
+remove_unwind_protect ()
+{
+  if (unwind_protect_list)
+    without_interrupts
+      (remove_unwind_protect_internal, (char *)NULL, (char *)NULL);
+}
+
+/* Run the list of cleanup functions in unwind_protect_list. */
+void
+run_unwind_protects ()
+{
+  if (unwind_protect_list)
+    without_interrupts
+      (run_unwind_protects_internal, (char *)NULL, (char *)NULL);
+}
+
+/* **************************************************************** */
+/*								    */
+/*                        The Actual Functions                 	    */
+/*								    */
+/* **************************************************************** */
+
+static void
+add_unwind_protect_internal (cleanup, arg)
+     Function *cleanup;
+     char *arg;
+{
+  UNWIND_ELT *elt;
+
+  elt = (UNWIND_ELT *)xmalloc (sizeof (UNWIND_ELT));
+  elt->cleanup = cleanup;
+  elt->arg = arg;
+  elt->next = unwind_protect_list;
+  unwind_protect_list = elt;
+}
+
+static void
+remove_unwind_protect_internal ()
+{
+  UNWIND_ELT *elt = unwind_protect_list;
+
+  if (elt)
+    {
+      unwind_protect_list = unwind_protect_list->next;
+      free (elt);
+    }
+}
+
+static void
+run_unwind_protects_internal ()
+{
+  UNWIND_ELT *t, *elt = unwind_protect_list;
+
+  while (elt)
+   {
+      /* This function can be run at strange times, like when unwinding
+	the entire world of unwind protects.  Thus, we may come across
+	 an element which is simply a label for a catch frame.  Don't call
+	 the non-existant function. */
+      if (elt->cleanup)
+	(*(elt->cleanup)) (elt->arg);
+
+      t = elt;
+      elt = elt->next;
+      free (t);
+    }
+  unwind_protect_list = elt;
+}
+
+static void
+unwind_frame_discard_internal (tag)
+     char *tag;
+{
+  UNWIND_ELT *elt;
+
+  while (elt = unwind_protect_list)
+    {
+      unwind_protect_list = unwind_protect_list->next;
+      if (!elt->cleanup && (STREQ (elt->arg, tag)))
+	{
+	  free (elt);
+	  break;
+	}
+      else
+	free (elt);
+    }
+}
+
+static void
+unwind_frame_run_internal (tag)
+     char *tag;
+{
+  UNWIND_ELT *elt;
+
+  while (elt = unwind_protect_list)
+    {
+      unwind_protect_list = elt->next;
+
+      /* If tag, then compare. */
+      if (!elt->cleanup)
+	{
+	  if (STREQ (elt->arg, tag))
+	    {
+	      free (elt);
+	      break;
+	    }
+	  free (elt);
+	  continue;
+	}
+      else
+	{
+	  (*(elt->cleanup)) (elt->arg);
+	  free (elt);
+	}
+    }
+}
+
+/* Structure describing a saved variable and the value to restore it to. */
+typedef struct {
+  int *variable;
+  char *desired_setting;
+  int size;
+} SAVED_VAR;
+
+/* Restore the value of a variable, based on the contents of SV.  If
+   sv->size is greater than sizeof (int), sv->desired_setting points to
+   a block of memory SIZE bytes long holding the value, rather than the
+   value itself.  This block of memory is copied back into the variable. */
+static void
+restore_variable (sv)
+     SAVED_VAR *sv;
+{
+  if (sv->size > sizeof (int))
+    {
+      bcopy ((char *)sv->desired_setting, (char *)sv->variable, sv->size);
+      free (sv->desired_setting);
+    }
+  else
+    *(sv->variable) = (int)sv->desired_setting;
+
+  free (sv);
+}
+
+/* Save the value of a variable so it will be restored when unwind-protects
+   are run.  VAR is a pointer to the variable.  VALUE is the value to be
+   saved.  SIZE is the size in bytes of VALUE.  If SIZE is bigger than what
+   can be saved in an int, memory will be allocated and the value saved
+   into that using bcopy (). */
+void
+unwind_protect_var (var, value, size)
+     int *var;
+     char *value;
+     int size;
+{
+  SAVED_VAR *s = (SAVED_VAR *)xmalloc (sizeof (SAVED_VAR));
+
+  s->variable = var;
+  if (size > sizeof (int))
+    {
+      s->desired_setting = (char *)xmalloc (size);
+      bcopy (value, (char *)s->desired_setting, size);
+    }
+  else
+    s->desired_setting = value;
+  s->size = size;
+  add_unwind_protect ((Function *)restore_variable, (char *)s);
+}