diff --git a/pcl_expect/spawn.py b/pcl_expect/spawn.py
index b79cbef8988cfcb29681d4054257214935a19ee4..8206a28afe83f7184c23f9efebb2edcac2e055a8 100644
--- a/pcl_expect/spawn.py
+++ b/pcl_expect/spawn.py
@@ -7,7 +7,8 @@ import pcl_expect
 __all__ = [
     "inherit_stty",
     "stty_init",
-    "spawn",
+    "Spawn",
+    "spawn2",
     ]
 
 # When a new pty is created by spawn(), the terminal settings will be
@@ -22,47 +23,71 @@ def set_cloexec_flag(fd):
     old = fcntl.fcntl(fd, fcntl.F_GETFD)
     fcntl.fcntl(fd, fcntl.F_SETFD, old | fcntl.FD_CLOEXEC)
 
-class Spawn(pcl_expect.Expectable):
-    def __init__(self, cmd):
-        if inherit_stty:
-            f = os.popen("stty -g")
-            settings = f.read()
-            f.close()
+def _spawn(cmd, use_stderr_pipe):
+    if inherit_stty:
+        f = os.popen("stty -g")
+        settings = f.read()
+        f.close()
 
-        if isinstance(cmd, basestring):
-            cmd = cmd.split(" ")
-        (r, w) = os.pipe()
-        set_cloexec_flag(w)
-        self.__child, self.__pty = pty.fork()
-        if self.__child == 0:
-            try:
-                os.close(r)
-                if inherit_stty:
-                    os.system("stty %s" % settings)
-                if stty_init is not None:
-                    os.system("stty %s" % stty_init)
-                try:
-                    os.execvp(cmd[0], cmd)
-                except OSError:
-                    os.write(w, "exec failed\n")
-            finally:
-                os._exit(1)
-        else:
-            os.close(w)
-            res = os.read(r, 100)
+    if isinstance(cmd, basestring):
+        cmd = cmd.split(" ")
+    (r, w) = os.pipe()
+    if use_stderr_pipe:
+        (stderr_r, stderr_w) = os.pipe()
+    else:
+        stderr_r = None
+    set_cloexec_flag(w)
+    pid, fd = pty.fork()
+    if pid == 0:
+        try:
             os.close(r)
-            if res != "":
-                os.close(self.__pty)
-                os.waitpid(self.__child, 0)
-                raise OSError("exec failed")
-            pcl_expect.Expectable.__init__(self, self.__pty)
+            if inherit_stty:
+                os.system("stty %s" % settings)
+            if stty_init is not None:
+                os.system("stty %s" % stty_init)
+            if use_stderr_pipe:
+                os.close(stderr_r)
+                os.dup2(stderr_w, 2)
+                os.close(stderr_w)
+            try:
+                os.execvp(cmd[0], cmd)
+            except OSError:
+                # FIXME: transfer failure reason.
+                os.write(w, "exec failed\n")
+        finally:
+            os._exit(1)
+
+    # In parent.
+    os.close(w)
+    if use_stderr_pipe:
+        os.close(stderr_w)
+    res = os.read(r, 100)
+    os.close(r)
+    if res != "":
+        os.close(fd)
+        os.waitpid(pid, 0)
+        raise OSError("exec failed")
+    return pid, fd, stderr_r
+
+class Spawn(pcl_expect.Expectable):
+    def __init__(self, cmd, use_stderr_pipe = False):
+        self.__child_pid, fd, stderr = _spawn(cmd, use_stderr_pipe)
+        pcl_expect.Expectable.__init__(self, fd)
+        if use_stderr_pipe:
+            self.stderr = pcl_expect.Expectable(stderr)
 
     def send(self, s):
         pcl_expect.debug("sending \"%s\" to fd %d" % (s, self.fileno()))
-        os.write(self.__pty, s)
+        os.write(self.fileno(), s)
 
     def close(self):
+        os.close(self.fileno())
         pcl_expect.Expectable.close(self)
-        os.close(self.__pty)
-        return os.waitpid(self.__child, 0)
+        if hasattr(self, "stderr"):
+            os.close(self.stderr.fileno())
+            self.stderr.close()
+        return os.waitpid(self.__child_pid, 0)
 
+def spawn2(cmd):
+    proc = Spawn(cmd, True)
+    return proc, proc.stderr