diff --git a/pcl_expect.py b/pcl_expect.py index e53afb36999153533963536500fbf3cdfaf301ce..1578d37cb318be07a2c475890e7ab09f77f54d4b 100644 --- a/pcl_expect.py +++ b/pcl_expect.py @@ -1,4 +1,6 @@ +import fcntl import os +import pty import re import select import sets @@ -17,6 +19,14 @@ timeout = 10.0 # Default is to raise an exception. timeout_raises_exception = True +# When a new pty is created by spawn(), the terminal settings will be +# inherited from the settings of stdin of the current process. +# Setting inherit_stty to False will disable this inheritance. After +# the inheritance (if any), if stty_init is set to a string, stty will +# be run with that string as its argument. +inherit_stty = True +stty_init = None + # # Internal code # @@ -66,6 +76,52 @@ class popen(expectable): def close(self): return self.__cmd.close() +def set_cloexec_flag(fd): + old = fcntl.fcntl(fd, fcntl.F_GETFD) + fcntl.fcntl(fd, fcntl.F_SETFD, old | fcntl.FD_CLOEXEC) + +class spawn(expectable): + def __init__(self, cmd): + if inherit_stty: + f = os.popen("stty -g") + settings = f.read() + f.close() + + if isinstance(cmd, types.StringTypes): + 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) + os.close(r) + if res != "": + os.close(self.__pty) + os.waitpid(self.__child, 0) + raise OSError("exec failed") + expectable.__init__(self, self.__pty) + + def send(self, s): + os.write(self.__pty, s) + + def close(self): + os.close(self.__pty) + return os.waitpid(self.__child, 0) + class impl: def __init__(self, timeout = None): self.__first = True