diff --git a/fabric.py b/fabric.py
index 5f1774f..3e8776b 100644
--- a/fabric.py
+++ b/fabric.py
@@ -167,32 +167,42 @@ def getAny(*names):
     # Implicit return value of None here if no names found.
 
 @operation
-def require(var, **kwargs):
+def require(*varnames, **kwargs):
     """
     Make sure that a certain environment variable is available.
     
-    The 'var' parameter is a string that names the variable to check for.
+    The 'varnames' parameters are one or more strings that names the variables
+    to check for.
     Two other optional kwargs are supported:
         * 'used_for' is a string that gets injected into, and then printed, as
           something like this string: "This variable is used for %s".
         * 'provided_by' is a list of strings that name commands which the user
           can run in order to satisfy the requirement.
     
-    If the required variable is not found in the current environment, then the
+    If the required variables are not found in the current environment, then the
     operation is stopped and Fabric halts.
     
-    Example:
+    Examples:
+
+        # One variable name
         require('project_name',
             used_for='finding the target deployment dir.',
             provided_by=['staging', 'production'],
         )
     
+        # Multiple variable names
+        require('project_name', 'install_dir', provided_by=['stg', 'prod'])
+
     """
-    if var in ENV:
+    if all([var in ENV for var in varnames]):
         return
+    if len(varnames) == 1:
+        vars_msg = "a %r variable." % varnames[0]
+    else:
+        vars_msg = "the variables %s." % ", ".join(
+                ["%r"%vn for vn in varnames])
     print(
-        ("The '%(fab_cur_command)s' command requires a '" + var
-        + "' variable.") % ENV
+        ("The '%(fab_cur_command)s' command requires " + vars_msg) % ENV
     )
     if 'used_for' in kwargs:
         print("This variable is used for %s" % _lazy_format(
@@ -205,7 +215,7 @@ def require(var, **kwargs):
     sys.exit(1)
 
 @operation
-def prompt(varname, msg, validate=None, default=None):
+def prompt(varname, msg, validate=None, default=None, auto=None, retry=False):
     """
     Display a prompt to the user and store the input in the given variable.
     If the variable already exists, then it is not prompted for again.
@@ -235,12 +245,24 @@ def prompt(varname, msg, validate=None, default=None):
     try:
         default_str = default and (" [%s]" % str(default).strip()) or ""
         prompt_msg = _lazy_format("%s%s: " % (msg.strip(), default_str))
-        value = raw_input(prompt_msg)
-        if not value:
-            value = default
         
-        if callable(validate):
-            value = validate(value)
+        if isinstance(validate, types.StringTypes):
+            validate = Matcher(validate)
+        
+        value = auto
+        while True:
+            value = value or raw_input(prompt_msg) or default
+            if callable(validate):
+                try:
+                    value = validate(value)
+                except Exception, e:
+                    value = None
+                    if not retry:
+                        raise e
+                    else:
+                        print e.message
+            if value or not retry:
+                break
         
         set(**{varname: value})
     except EOFError:
@@ -679,6 +701,16 @@ def _rolling_strategy(fn, *args, **kwargs):
 # Internal plumbing:
 #
 
+class Matcher(object):
+    def __init__(self, pattern):
+        self.regexp = re.compile(pattern)
+    def __call__(self, value):
+        regexp = self.regexp
+        if value is None or not regexp.match(value):
+            raise ValueError("Malformed value %r. Must match r'%s'." %
+                    (value, regexp.pattern))
+        return value
+
 class HostConnection(object):
     """
     A connection to an SSH host - wraps an SSHClient.
