Show More
@@ -80,6 +80,7 try: | |||||
80 | import traceback |
|
80 | import traceback | |
81 | import signal |
|
81 | import signal | |
82 | import codecs |
|
82 | import codecs | |
|
83 | import stat | |||
83 | except ImportError: # pragma: no cover |
|
84 | except ImportError: # pragma: no cover | |
84 | err = sys.exc_info()[1] |
|
85 | err = sys.exc_info()[1] | |
85 | raise ImportError(str(err) + ''' |
|
86 | raise ImportError(str(err) + ''' | |
@@ -87,7 +88,7 except ImportError: # pragma: no cover | |||||
87 | A critical module was not found. Probably this operating system does not |
|
88 | A critical module was not found. Probably this operating system does not | |
88 | support it. Pexpect is intended for UNIX-like operating systems.''') |
|
89 | support it. Pexpect is intended for UNIX-like operating systems.''') | |
89 |
|
90 | |||
90 |
__version__ = '3. |
|
91 | __version__ = '3.3' | |
91 | __revision__ = '' |
|
92 | __revision__ = '' | |
92 | __all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'spawnu', 'run', 'runu', |
|
93 | __all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'spawnu', 'run', 'runu', | |
93 | 'which', 'split_command_line', '__version__', '__revision__'] |
|
94 | 'which', 'split_command_line', '__version__', '__revision__'] | |
@@ -284,6 +285,7 class spawn(object): | |||||
284 | def _chr(c): |
|
285 | def _chr(c): | |
285 | return bytes([c]) |
|
286 | return bytes([c]) | |
286 | linesep = os.linesep.encode('ascii') |
|
287 | linesep = os.linesep.encode('ascii') | |
|
288 | crlf = '\r\n'.encode('ascii') | |||
287 |
|
289 | |||
288 | @staticmethod |
|
290 | @staticmethod | |
289 | def write_to_stdout(b): |
|
291 | def write_to_stdout(b): | |
@@ -296,13 +298,14 class spawn(object): | |||||
296 | allowed_string_types = (basestring,) # analysis:ignore |
|
298 | allowed_string_types = (basestring,) # analysis:ignore | |
297 | _chr = staticmethod(chr) |
|
299 | _chr = staticmethod(chr) | |
298 | linesep = os.linesep |
|
300 | linesep = os.linesep | |
|
301 | crlf = '\r\n' | |||
299 | write_to_stdout = sys.stdout.write |
|
302 | write_to_stdout = sys.stdout.write | |
300 |
|
303 | |||
301 | encoding = None |
|
304 | encoding = None | |
302 |
|
305 | |||
303 | def __init__(self, command, args=[], timeout=30, maxread=2000, |
|
306 | def __init__(self, command, args=[], timeout=30, maxread=2000, | |
304 | searchwindowsize=None, logfile=None, cwd=None, env=None, |
|
307 | searchwindowsize=None, logfile=None, cwd=None, env=None, | |
305 | ignore_sighup=True): |
|
308 | ignore_sighup=True, echo=True): | |
306 |
|
309 | |||
307 | '''This is the constructor. The command parameter may be a string that |
|
310 | '''This is the constructor. The command parameter may be a string that | |
308 | includes a command and any arguments to the command. For example:: |
|
311 | includes a command and any arguments to the command. For example:: | |
@@ -415,7 +418,16 class spawn(object): | |||||
415 | signalstatus will store the signal value and exitstatus will be None. |
|
418 | signalstatus will store the signal value and exitstatus will be None. | |
416 | If you need more detail you can also read the self.status member which |
|
419 | If you need more detail you can also read the self.status member which | |
417 | stores the status returned by os.waitpid. You can interpret this using |
|
420 | stores the status returned by os.waitpid. You can interpret this using | |
418 |
os.WIFEXITED/os.WEXITSTATUS or os.WIFSIGNALED/os.TERMSIG. |
|
421 | os.WIFEXITED/os.WEXITSTATUS or os.WIFSIGNALED/os.TERMSIG. | |
|
422 | ||||
|
423 | The echo attribute may be set to False to disable echoing of input. | |||
|
424 | As a pseudo-terminal, all input echoed by the "keyboard" (send() | |||
|
425 | or sendline()) will be repeated to output. For many cases, it is | |||
|
426 | not desirable to have echo enabled, and it may be later disabled | |||
|
427 | using setecho(False) followed by waitnoecho(). However, for some | |||
|
428 | platforms such as Solaris, this is not possible, and should be | |||
|
429 | disabled immediately on spawn. | |||
|
430 | ''' | |||
419 |
|
431 | |||
420 | self.STDIN_FILENO = pty.STDIN_FILENO |
|
432 | self.STDIN_FILENO = pty.STDIN_FILENO | |
421 | self.STDOUT_FILENO = pty.STDOUT_FILENO |
|
433 | self.STDOUT_FILENO = pty.STDOUT_FILENO | |
@@ -437,7 +449,7 class spawn(object): | |||||
437 | self.status = None |
|
449 | self.status = None | |
438 | self.flag_eof = False |
|
450 | self.flag_eof = False | |
439 | self.pid = None |
|
451 | self.pid = None | |
440 |
# the chil |
|
452 | # the child file descriptor is initially closed | |
441 | self.child_fd = -1 |
|
453 | self.child_fd = -1 | |
442 | self.timeout = timeout |
|
454 | self.timeout = timeout | |
443 | self.delimiter = EOF |
|
455 | self.delimiter = EOF | |
@@ -466,16 +478,30 class spawn(object): | |||||
466 | self.closed = True |
|
478 | self.closed = True | |
467 | self.cwd = cwd |
|
479 | self.cwd = cwd | |
468 | self.env = env |
|
480 | self.env = env | |
|
481 | self.echo = echo | |||
469 | self.ignore_sighup = ignore_sighup |
|
482 | self.ignore_sighup = ignore_sighup | |
|
483 | _platform = sys.platform.lower() | |||
470 | # This flags if we are running on irix |
|
484 | # This flags if we are running on irix | |
471 |
self.__irix_hack = |
|
485 | self.__irix_hack = _platform.startswith('irix') | |
472 | # Solaris uses internal __fork_pty(). All others use pty.fork(). |
|
486 | # Solaris uses internal __fork_pty(). All others use pty.fork(). | |
473 | if ((sys.platform.lower().find('solaris') >= 0) |
|
487 | self.use_native_pty_fork = not ( | |
474 | or (sys.platform.lower().find('sunos5') >= 0)): |
|
488 | _platform.startswith('solaris') or | |
475 | self.use_native_pty_fork = False |
|
489 | _platform.startswith('sunos')) | |
476 | else: |
|
490 | # inherit EOF and INTR definitions from controlling process. | |
477 | self.use_native_pty_fork = True |
|
491 | try: | |
478 |
|
492 | from termios import VEOF, VINTR | ||
|
493 | fd = sys.__stdin__.fileno() | |||
|
494 | self._INTR = ord(termios.tcgetattr(fd)[6][VINTR]) | |||
|
495 | self._EOF = ord(termios.tcgetattr(fd)[6][VEOF]) | |||
|
496 | except (ImportError, OSError, IOError, termios.error): | |||
|
497 | # unless the controlling process is also not a terminal, | |||
|
498 | # such as cron(1). Fall-back to using CEOF and CINTR. | |||
|
499 | try: | |||
|
500 | from termios import CEOF, CINTR | |||
|
501 | (self._INTR, self._EOF) = (CINTR, CEOF) | |||
|
502 | except ImportError: | |||
|
503 | # ^C, ^D | |||
|
504 | (self._INTR, self._EOF) = (3, 4) | |||
479 | # Support subclasses that do not use command or args. |
|
505 | # Support subclasses that do not use command or args. | |
480 | if command is None: |
|
506 | if command is None: | |
481 | self.command = None |
|
507 | self.command = None | |
@@ -599,33 +625,39 class spawn(object): | |||||
599 | if self.use_native_pty_fork: |
|
625 | if self.use_native_pty_fork: | |
600 | try: |
|
626 | try: | |
601 | self.pid, self.child_fd = pty.fork() |
|
627 | self.pid, self.child_fd = pty.fork() | |
602 | except OSError: |
|
628 | except OSError: # pragma: no cover | |
603 | err = sys.exc_info()[1] |
|
629 | err = sys.exc_info()[1] | |
604 | raise ExceptionPexpect('pty.fork() failed: ' + str(err)) |
|
630 | raise ExceptionPexpect('pty.fork() failed: ' + str(err)) | |
605 | else: |
|
631 | else: | |
606 | # Use internal __fork_pty |
|
632 | # Use internal __fork_pty | |
607 | self.pid, self.child_fd = self.__fork_pty() |
|
633 | self.pid, self.child_fd = self.__fork_pty() | |
608 |
|
634 | |||
609 | if self.pid == 0: |
|
635 | # Some platforms must call setwinsize() and setecho() from the | |
|
636 | # child process, and others from the master process. We do both, | |||
|
637 | # allowing IOError for either. | |||
|
638 | ||||
|
639 | if self.pid == pty.CHILD: | |||
610 | # Child |
|
640 | # Child | |
|
641 | self.child_fd = self.STDIN_FILENO | |||
|
642 | ||||
|
643 | # set default window size of 24 rows by 80 columns | |||
611 | try: |
|
644 | try: | |
612 | # used by setwinsize() |
|
|||
613 | self.child_fd = sys.stdout.fileno() |
|
|||
614 | self.setwinsize(24, 80) |
|
645 | self.setwinsize(24, 80) | |
615 | # which exception, shouldnt' we catch explicitly .. ? |
|
646 | except IOError as err: | |
616 | except: |
|
647 | if err.args[0] not in (errno.EINVAL, errno.ENOTTY): | |
617 | # Some platforms do not like setwinsize (Cygwin). |
|
648 | raise | |
618 | # This will cause problem when running applications that |
|
649 | ||
619 | # are very picky about window size. |
|
650 | # disable echo if spawn argument echo was unset | |
620 | # This is a serious limitation, but not a show stopper. |
|
651 | if not self.echo: | |
621 |
|
|
652 | try: | |
|
653 | self.setecho(self.echo) | |||
|
654 | except (IOError, termios.error) as err: | |||
|
655 | if err.args[0] not in (errno.EINVAL, errno.ENOTTY): | |||
|
656 | raise | |||
|
657 | ||||
622 | # Do not allow child to inherit open file descriptors from parent. |
|
658 | # Do not allow child to inherit open file descriptors from parent. | |
623 | max_fd = resource.getrlimit(resource.RLIMIT_NOFILE)[0] |
|
659 | max_fd = resource.getrlimit(resource.RLIMIT_NOFILE)[0] | |
624 |
|
|
660 | os.closerange(3, max_fd) | |
625 | try: |
|
|||
626 | os.close(i) |
|
|||
627 | except OSError: |
|
|||
628 | pass |
|
|||
629 |
|
661 | |||
630 | if self.ignore_sighup: |
|
662 | if self.ignore_sighup: | |
631 | signal.signal(signal.SIGHUP, signal.SIG_IGN) |
|
663 | signal.signal(signal.SIGHUP, signal.SIG_IGN) | |
@@ -638,6 +670,13 class spawn(object): | |||||
638 | os.execvpe(self.command, self.args, self.env) |
|
670 | os.execvpe(self.command, self.args, self.env) | |
639 |
|
671 | |||
640 | # Parent |
|
672 | # Parent | |
|
673 | try: | |||
|
674 | self.setwinsize(24, 80) | |||
|
675 | except IOError as err: | |||
|
676 | if err.args[0] not in (errno.EINVAL, errno.ENOTTY): | |||
|
677 | raise | |||
|
678 | ||||
|
679 | ||||
641 | self.terminated = False |
|
680 | self.terminated = False | |
642 | self.closed = False |
|
681 | self.closed = False | |
643 |
|
682 | |||
@@ -660,19 +699,15 class spawn(object): | |||||
660 | raise ExceptionPexpect("Could not open with os.openpty().") |
|
699 | raise ExceptionPexpect("Could not open with os.openpty().") | |
661 |
|
700 | |||
662 | pid = os.fork() |
|
701 | pid = os.fork() | |
663 |
if pid |
|
702 | if pid == pty.CHILD: | |
664 | raise ExceptionPexpect("Failed os.fork().") |
|
|||
665 | elif pid == 0: |
|
|||
666 | # Child. |
|
703 | # Child. | |
667 | os.close(parent_fd) |
|
704 | os.close(parent_fd) | |
668 | self.__pty_make_controlling_tty(child_fd) |
|
705 | self.__pty_make_controlling_tty(child_fd) | |
669 |
|
706 | |||
670 |
os.dup2(child_fd, |
|
707 | os.dup2(child_fd, self.STDIN_FILENO) | |
671 |
os.dup2(child_fd, |
|
708 | os.dup2(child_fd, self.STDOUT_FILENO) | |
672 |
os.dup2(child_fd, |
|
709 | os.dup2(child_fd, self.STDERR_FILENO) | |
673 |
|
710 | |||
674 | if child_fd > 2: |
|
|||
675 | os.close(child_fd) |
|
|||
676 | else: |
|
711 | else: | |
677 | # Parent. |
|
712 | # Parent. | |
678 | os.close(child_fd) |
|
713 | os.close(child_fd) | |
@@ -686,45 +721,37 class spawn(object): | |||||
686 |
|
721 | |||
687 | child_name = os.ttyname(tty_fd) |
|
722 | child_name = os.ttyname(tty_fd) | |
688 |
|
723 | |||
689 |
# Disconnect from controlling tty |
|
724 | # Disconnect from controlling tty, if any. Raises OSError of ENXIO | |
|
725 | # if there was no controlling tty to begin with, such as when | |||
|
726 | # executed by a cron(1) job. | |||
690 | try: |
|
727 | try: | |
691 | fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY) |
|
728 | fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY) | |
692 | if fd >= 0: |
|
|||
693 |
|
|
729 | os.close(fd) | |
694 | # which exception, shouldnt' we catch explicitly .. ? |
|
730 | except OSError as err: | |
695 | except: |
|
731 | if err.errno != errno.ENXIO: | |
696 | # Already disconnected. This happens if running inside cron. |
|
732 | raise | |
697 | pass |
|
|||
698 |
|
733 | |||
699 | os.setsid() |
|
734 | os.setsid() | |
700 |
|
735 | |||
701 | # Verify we are disconnected from controlling tty |
|
736 | # Verify we are disconnected from controlling tty by attempting to open | |
702 | # by attempting to open it again. |
|
737 | # it again. We expect that OSError of ENXIO should always be raised. | |
703 | try: |
|
738 | try: | |
704 | fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY) |
|
739 | fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY) | |
705 | if fd >= 0: |
|
|||
706 |
|
|
740 | os.close(fd) | |
707 | raise ExceptionPexpect('Failed to disconnect from ' + |
|
741 | raise ExceptionPexpect("OSError of errno.ENXIO should be raised.") | |
708 | 'controlling tty. It is still possible to open /dev/tty.') |
|
742 | except OSError as err: | |
709 | # which exception, shouldnt' we catch explicitly .. ? |
|
743 | if err.errno != errno.ENXIO: | |
710 | except: |
|
744 | raise | |
711 | # Good! We are disconnected from a controlling tty. |
|
|||
712 | pass |
|
|||
713 |
|
745 | |||
714 | # Verify we can open child pty. |
|
746 | # Verify we can open child pty. | |
715 | fd = os.open(child_name, os.O_RDWR) |
|
747 | fd = os.open(child_name, os.O_RDWR) | |
716 | if fd < 0: |
|
|||
717 | raise ExceptionPexpect("Could not open child pty, " + child_name) |
|
|||
718 | else: |
|
|||
719 |
|
|
748 | os.close(fd) | |
720 |
|
749 | |||
721 | # Verify we now have a controlling tty. |
|
750 | # Verify we now have a controlling tty. | |
722 | fd = os.open("/dev/tty", os.O_WRONLY) |
|
751 | fd = os.open("/dev/tty", os.O_WRONLY) | |
723 | if fd < 0: |
|
|||
724 | raise ExceptionPexpect("Could not open controlling tty, /dev/tty") |
|
|||
725 | else: |
|
|||
726 |
|
|
752 | os.close(fd) | |
727 |
|
753 | |||
|
754 | ||||
728 | def fileno(self): |
|
755 | def fileno(self): | |
729 | '''This returns the file descriptor of the pty for the child. |
|
756 | '''This returns the file descriptor of the pty for the child. | |
730 | ''' |
|
757 | ''' | |
@@ -757,7 +784,12 class spawn(object): | |||||
757 |
|
784 | |||
758 | def isatty(self): |
|
785 | def isatty(self): | |
759 | '''This returns True if the file descriptor is open and connected to a |
|
786 | '''This returns True if the file descriptor is open and connected to a | |
760 |
tty(-like) device, else False. |
|
787 | tty(-like) device, else False. | |
|
788 | ||||
|
789 | On SVR4-style platforms implementing streams, such as SunOS and HP-UX, | |||
|
790 | the child pty may not appear as a terminal device. This means | |||
|
791 | methods such as setecho(), setwinsize(), getwinsize() may raise an | |||
|
792 | IOError. ''' | |||
761 |
|
793 | |||
762 | return os.isatty(self.child_fd) |
|
794 | return os.isatty(self.child_fd) | |
763 |
|
795 | |||
@@ -794,12 +826,20 class spawn(object): | |||||
794 | def getecho(self): |
|
826 | def getecho(self): | |
795 | '''This returns the terminal echo mode. This returns True if echo is |
|
827 | '''This returns the terminal echo mode. This returns True if echo is | |
796 | on or False if echo is off. Child applications that are expecting you |
|
828 | on or False if echo is off. Child applications that are expecting you | |
797 |
to enter a password often set ECHO False. See waitnoecho(). |
|
829 | to enter a password often set ECHO False. See waitnoecho(). | |
|
830 | ||||
|
831 | Not supported on platforms where ``isatty()`` returns False. ''' | |||
798 |
|
832 | |||
|
833 | try: | |||
799 | attr = termios.tcgetattr(self.child_fd) |
|
834 | attr = termios.tcgetattr(self.child_fd) | |
800 | if attr[3] & termios.ECHO: |
|
835 | except termios.error as err: | |
801 | return True |
|
836 | errmsg = 'getecho() may not be called on this platform' | |
802 | return False |
|
837 | if err.args[0] == errno.EINVAL: | |
|
838 | raise IOError(err.args[0], '%s: %s.' % (err.args[1], errmsg)) | |||
|
839 | raise | |||
|
840 | ||||
|
841 | self.echo = bool(attr[3] & termios.ECHO) | |||
|
842 | return self.echo | |||
803 |
|
843 | |||
804 | def setecho(self, state): |
|
844 | def setecho(self, state): | |
805 | '''This sets the terminal echo mode on or off. Note that anything the |
|
845 | '''This sets the terminal echo mode on or off. Note that anything the | |
@@ -829,18 +869,35 class spawn(object): | |||||
829 | p.expect(['1234']) |
|
869 | p.expect(['1234']) | |
830 | p.expect(['abcd']) |
|
870 | p.expect(['abcd']) | |
831 | p.expect(['wxyz']) |
|
871 | p.expect(['wxyz']) | |
|
872 | ||||
|
873 | ||||
|
874 | Not supported on platforms where ``isatty()`` returns False. | |||
832 | ''' |
|
875 | ''' | |
833 |
|
876 | |||
834 | self.child_fd |
|
877 | errmsg = 'setecho() may not be called on this platform' | |
|
878 | ||||
|
879 | try: | |||
835 | attr = termios.tcgetattr(self.child_fd) |
|
880 | attr = termios.tcgetattr(self.child_fd) | |
|
881 | except termios.error as err: | |||
|
882 | if err.args[0] == errno.EINVAL: | |||
|
883 | raise IOError(err.args[0], '%s: %s.' % (err.args[1], errmsg)) | |||
|
884 | raise | |||
|
885 | ||||
836 | if state: |
|
886 | if state: | |
837 | attr[3] = attr[3] | termios.ECHO |
|
887 | attr[3] = attr[3] | termios.ECHO | |
838 | else: |
|
888 | else: | |
839 | attr[3] = attr[3] & ~termios.ECHO |
|
889 | attr[3] = attr[3] & ~termios.ECHO | |
840 | # I tried TCSADRAIN and TCSAFLUSH, but |
|
890 | ||
841 | # these were inconsistent and blocked on some platforms. |
|
891 | try: | |
842 | # TCSADRAIN would probably be ideal if it worked. |
|
892 | # I tried TCSADRAIN and TCSAFLUSH, but these were inconsistent and | |
|
893 | # blocked on some platforms. TCSADRAIN would probably be ideal. | |||
843 | termios.tcsetattr(self.child_fd, termios.TCSANOW, attr) |
|
894 | termios.tcsetattr(self.child_fd, termios.TCSANOW, attr) | |
|
895 | except IOError as err: | |||
|
896 | if err.args[0] == errno.EINVAL: | |||
|
897 | raise IOError(err.args[0], '%s: %s.' % (err.args[1], errmsg)) | |||
|
898 | raise | |||
|
899 | ||||
|
900 | self.echo = state | |||
844 |
|
901 | |||
845 | def _log(self, s, direction): |
|
902 | def _log(self, s, direction): | |
846 | if self.logfile is not None: |
|
903 | if self.logfile is not None: | |
@@ -913,12 +970,14 class spawn(object): | |||||
913 | if self.child_fd in r: |
|
970 | if self.child_fd in r: | |
914 | try: |
|
971 | try: | |
915 | s = os.read(self.child_fd, size) |
|
972 | s = os.read(self.child_fd, size) | |
916 | except OSError: |
|
973 | except OSError as err: | |
917 | # Linux does this |
|
974 | if err.args[0] == errno.EIO: | |
|
975 | # Linux-style EOF | |||
918 | self.flag_eof = True |
|
976 | self.flag_eof = True | |
919 | raise EOF('End Of File (EOF). Exception style platform.') |
|
977 | raise EOF('End Of File (EOF). Exception style platform.') | |
|
978 | raise | |||
920 | if s == b'': |
|
979 | if s == b'': | |
921 |
# BSD |
|
980 | # BSD-style EOF | |
922 | self.flag_eof = True |
|
981 | self.flag_eof = True | |
923 | raise EOF('End Of File (EOF). Empty string style platform.') |
|
982 | raise EOF('End Of File (EOF). Empty string style platform.') | |
924 |
|
983 | |||
@@ -926,7 +985,7 class spawn(object): | |||||
926 | self._log(s, 'read') |
|
985 | self._log(s, 'read') | |
927 | return s |
|
986 | return s | |
928 |
|
987 | |||
929 | raise ExceptionPexpect('Reached an unexpected state.') |
|
988 | raise ExceptionPexpect('Reached an unexpected state.') # pragma: no cover | |
930 |
|
989 | |||
931 | def read(self, size=-1): |
|
990 | def read(self, size=-1): | |
932 | '''This reads at most "size" bytes from the file (less if the read hits |
|
991 | '''This reads at most "size" bytes from the file (less if the read hits | |
@@ -972,9 +1031,9 class spawn(object): | |||||
972 | if size == 0: |
|
1031 | if size == 0: | |
973 | return self.string_type() |
|
1032 | return self.string_type() | |
974 | # delimiter default is EOF |
|
1033 | # delimiter default is EOF | |
975 |
index = self.expect([ |
|
1034 | index = self.expect([self.crlf, self.delimiter]) | |
976 | if index == 0: |
|
1035 | if index == 0: | |
977 |
return self.before + |
|
1036 | return self.before + self.crlf | |
978 | else: |
|
1037 | else: | |
979 | return self.before |
|
1038 | return self.before | |
980 |
|
1039 | |||
@@ -1075,40 +1134,14 class spawn(object): | |||||
1075 | It is the responsibility of the caller to ensure the eof is sent at the |
|
1134 | It is the responsibility of the caller to ensure the eof is sent at the | |
1076 | beginning of a line. ''' |
|
1135 | beginning of a line. ''' | |
1077 |
|
1136 | |||
1078 | ### Hmmm... how do I send an EOF? |
|
1137 | self.send(self._chr(self._EOF)) | |
1079 | ###C if ((m = write(pty, *buf, p - *buf)) < 0) |
|
|||
1080 | ###C return (errno == EWOULDBLOCK) ? n : -1; |
|
|||
1081 | #fd = sys.stdin.fileno() |
|
|||
1082 | #old = termios.tcgetattr(fd) # remember current state |
|
|||
1083 | #attr = termios.tcgetattr(fd) |
|
|||
1084 | #attr[3] = attr[3] | termios.ICANON # ICANON must be set to see EOF |
|
|||
1085 | #try: # use try/finally to ensure state gets restored |
|
|||
1086 | # termios.tcsetattr(fd, termios.TCSADRAIN, attr) |
|
|||
1087 | # if hasattr(termios, 'CEOF'): |
|
|||
1088 | # os.write(self.child_fd, '%c' % termios.CEOF) |
|
|||
1089 | # else: |
|
|||
1090 | # # Silly platform does not define CEOF so assume CTRL-D |
|
|||
1091 | # os.write(self.child_fd, '%c' % 4) |
|
|||
1092 | #finally: # restore state |
|
|||
1093 | # termios.tcsetattr(fd, termios.TCSADRAIN, old) |
|
|||
1094 | if hasattr(termios, 'VEOF'): |
|
|||
1095 | char = ord(termios.tcgetattr(self.child_fd)[6][termios.VEOF]) |
|
|||
1096 | else: |
|
|||
1097 | # platform does not define VEOF so assume CTRL-D |
|
|||
1098 | char = 4 |
|
|||
1099 | self.send(self._chr(char)) |
|
|||
1100 |
|
1138 | |||
1101 | def sendintr(self): |
|
1139 | def sendintr(self): | |
1102 |
|
1140 | |||
1103 | '''This sends a SIGINT to the child. It does not require |
|
1141 | '''This sends a SIGINT to the child. It does not require | |
1104 | the SIGINT to be the first character on a line. ''' |
|
1142 | the SIGINT to be the first character on a line. ''' | |
1105 |
|
1143 | |||
1106 | if hasattr(termios, 'VINTR'): |
|
1144 | self.send(self._chr(self._INTR)) | |
1107 | char = ord(termios.tcgetattr(self.child_fd)[6][termios.VINTR]) |
|
|||
1108 | else: |
|
|||
1109 | # platform does not define VINTR so assume CTRL-C |
|
|||
1110 | char = 3 |
|
|||
1111 | self.send(self._chr(char)) |
|
|||
1112 |
|
1145 | |||
1113 | def eof(self): |
|
1146 | def eof(self): | |
1114 |
|
1147 | |||
@@ -1181,7 +1214,7 class spawn(object): | |||||
1181 | self.exitstatus = None |
|
1214 | self.exitstatus = None | |
1182 | self.signalstatus = os.WTERMSIG(status) |
|
1215 | self.signalstatus = os.WTERMSIG(status) | |
1183 | self.terminated = True |
|
1216 | self.terminated = True | |
1184 | elif os.WIFSTOPPED(status): |
|
1217 | elif os.WIFSTOPPED(status): # pragma: no cover | |
1185 | # You can't call wait() on a child process in the stopped state. |
|
1218 | # You can't call wait() on a child process in the stopped state. | |
1186 | raise ExceptionPexpect('Called wait() on a stopped child ' + |
|
1219 | raise ExceptionPexpect('Called wait() on a stopped child ' + | |
1187 | 'process. This is not supported. Is some other ' + |
|
1220 | 'process. This is not supported. Is some other ' + | |
@@ -1201,7 +1234,7 class spawn(object): | |||||
1201 |
|
1234 | |||
1202 | if self.flag_eof: |
|
1235 | if self.flag_eof: | |
1203 | # This is for Linux, which requires the blocking form |
|
1236 | # This is for Linux, which requires the blocking form | |
1204 |
# of waitpid to |
|
1237 | # of waitpid to get the status of a defunct process. | |
1205 | # This is super-lame. The flag_eof would have been set |
|
1238 | # This is super-lame. The flag_eof would have been set | |
1206 | # in read_nonblocking(), so this should be safe. |
|
1239 | # in read_nonblocking(), so this should be safe. | |
1207 | waitpid_options = 0 |
|
1240 | waitpid_options = 0 | |
@@ -1229,7 +1262,7 class spawn(object): | |||||
1229 | try: |
|
1262 | try: | |
1230 | ### os.WNOHANG) # Solaris! |
|
1263 | ### os.WNOHANG) # Solaris! | |
1231 | pid, status = os.waitpid(self.pid, waitpid_options) |
|
1264 | pid, status = os.waitpid(self.pid, waitpid_options) | |
1232 | except OSError as e: |
|
1265 | except OSError as e: # pragma: no cover | |
1233 | # This should never happen... |
|
1266 | # This should never happen... | |
1234 | if e.errno == errno.ECHILD: |
|
1267 | if e.errno == errno.ECHILD: | |
1235 | raise ExceptionPexpect('isalive() encountered condition ' + |
|
1268 | raise ExceptionPexpect('isalive() encountered condition ' + | |
@@ -1643,10 +1676,14 class spawn(object): | |||||
1643 | if self.child_fd in r: |
|
1676 | if self.child_fd in r: | |
1644 | try: |
|
1677 | try: | |
1645 | data = self.__interact_read(self.child_fd) |
|
1678 | data = self.__interact_read(self.child_fd) | |
1646 | except OSError as e: |
|
1679 | except OSError as err: | |
1647 | # The subprocess may have closed before we get to reading it |
|
1680 | if err.args[0] == errno.EIO: | |
1648 | if e.errno != errno.EIO: |
|
1681 | # Linux-style EOF | |
|
1682 | break | |||
1649 |
|
|
1683 | raise | |
|
1684 | if data == b'': | |||
|
1685 | # BSD-style EOF | |||
|
1686 | break | |||
1650 | if output_filter: |
|
1687 | if output_filter: | |
1651 | data = output_filter(data) |
|
1688 | data = output_filter(data) | |
1652 | if self.logfile is not None: |
|
1689 | if self.logfile is not None: | |
@@ -1695,7 +1732,7 class spawn(object): | |||||
1695 | ############################################################################## |
|
1732 | ############################################################################## | |
1696 | # The following methods are no longer supported or allowed. |
|
1733 | # The following methods are no longer supported or allowed. | |
1697 |
|
1734 | |||
1698 | def setmaxread(self, maxread): |
|
1735 | def setmaxread(self, maxread): # pragma: no cover | |
1699 |
|
1736 | |||
1700 | '''This method is no longer supported or allowed. I don't like getters |
|
1737 | '''This method is no longer supported or allowed. I don't like getters | |
1701 | and setters without a good reason. ''' |
|
1738 | and setters without a good reason. ''' | |
@@ -1704,7 +1741,7 class spawn(object): | |||||
1704 | 'or allowed. Just assign a value to the ' + |
|
1741 | 'or allowed. Just assign a value to the ' + | |
1705 | 'maxread member variable.') |
|
1742 | 'maxread member variable.') | |
1706 |
|
1743 | |||
1707 | def setlog(self, fileobject): |
|
1744 | def setlog(self, fileobject): # pragma: no cover | |
1708 |
|
1745 | |||
1709 | '''This method is no longer supported or allowed. |
|
1746 | '''This method is no longer supported or allowed. | |
1710 | ''' |
|
1747 | ''' | |
@@ -1732,11 +1769,13 class spawnu(spawn): | |||||
1732 | allowed_string_types = (str, ) |
|
1769 | allowed_string_types = (str, ) | |
1733 | _chr = staticmethod(chr) |
|
1770 | _chr = staticmethod(chr) | |
1734 | linesep = os.linesep |
|
1771 | linesep = os.linesep | |
|
1772 | crlf = '\r\n' | |||
1735 | else: |
|
1773 | else: | |
1736 | string_type = unicode |
|
1774 | string_type = unicode | |
1737 | allowed_string_types = (unicode, ) |
|
1775 | allowed_string_types = (unicode, ) | |
1738 | _chr = staticmethod(unichr) |
|
1776 | _chr = staticmethod(unichr) | |
1739 | linesep = os.linesep.decode('ascii') |
|
1777 | linesep = os.linesep.decode('ascii') | |
|
1778 | crlf = '\r\n'.decode('ascii') | |||
1740 | # This can handle unicode in both Python 2 and 3 |
|
1779 | # This can handle unicode in both Python 2 and 3 | |
1741 | write_to_stdout = sys.stdout.write |
|
1780 | write_to_stdout = sys.stdout.write | |
1742 |
|
1781 | |||
@@ -1959,15 +1998,55 class searcher_re(object): | |||||
1959 | return best_index |
|
1998 | return best_index | |
1960 |
|
1999 | |||
1961 |
|
2000 | |||
1962 | def which(filename): |
|
2001 | def is_executable_file(path): | |
|
2002 | """Checks that path is an executable regular file (or a symlink to a file). | |||
|
2003 | ||||
|
2004 | This is roughly ``os.path isfile(path) and os.access(path, os.X_OK)``, but | |||
|
2005 | on some platforms :func:`os.access` gives us the wrong answer, so this | |||
|
2006 | checks permission bits directly. | |||
|
2007 | """ | |||
|
2008 | # follow symlinks, | |||
|
2009 | fpath = os.path.realpath(path) | |||
|
2010 | ||||
|
2011 | # return False for non-files (directories, fifo, etc.) | |||
|
2012 | if not os.path.isfile(fpath): | |||
|
2013 | return False | |||
|
2014 | ||||
|
2015 | # On Solaris, etc., "If the process has appropriate privileges, an | |||
|
2016 | # implementation may indicate success for X_OK even if none of the | |||
|
2017 | # execute file permission bits are set." | |||
|
2018 | # | |||
|
2019 | # For this reason, it is necessary to explicitly check st_mode | |||
1963 |
|
2020 | |||
|
2021 | # get file mode using os.stat, and check if `other', | |||
|
2022 | # that is anybody, may read and execute. | |||
|
2023 | mode = os.stat(fpath).st_mode | |||
|
2024 | if mode & stat.S_IROTH and mode & stat.S_IXOTH: | |||
|
2025 | return True | |||
|
2026 | ||||
|
2027 | # get current user's group ids, and check if `group', | |||
|
2028 | # when matching ours, may read and execute. | |||
|
2029 | user_gids = os.getgroups() + [os.getgid()] | |||
|
2030 | if (os.stat(fpath).st_gid in user_gids and | |||
|
2031 | mode & stat.S_IRGRP and mode & stat.S_IXGRP): | |||
|
2032 | return True | |||
|
2033 | ||||
|
2034 | # finally, if file owner matches our effective userid, | |||
|
2035 | # check if `user', may read and execute. | |||
|
2036 | user_gids = os.getgroups() + [os.getgid()] | |||
|
2037 | if (os.stat(fpath).st_uid == os.geteuid() and | |||
|
2038 | mode & stat.S_IRUSR and mode & stat.S_IXUSR): | |||
|
2039 | return True | |||
|
2040 | ||||
|
2041 | return False | |||
|
2042 | ||||
|
2043 | def which(filename): | |||
1964 | '''This takes a given filename; tries to find it in the environment path; |
|
2044 | '''This takes a given filename; tries to find it in the environment path; | |
1965 | then checks if it is executable. This returns the full path to the filename |
|
2045 | then checks if it is executable. This returns the full path to the filename | |
1966 | if found and executable. Otherwise this returns None.''' |
|
2046 | if found and executable. Otherwise this returns None.''' | |
1967 |
|
2047 | |||
1968 | # Special case where filename contains an explicit path. |
|
2048 | # Special case where filename contains an explicit path. | |
1969 | if os.path.dirname(filename) != '': |
|
2049 | if os.path.dirname(filename) != '' and is_executable_file(filename): | |
1970 | if os.access(filename, os.X_OK): |
|
|||
1971 |
|
|
2050 | return filename | |
1972 | if 'PATH' not in os.environ or os.environ['PATH'] == '': |
|
2051 | if 'PATH' not in os.environ or os.environ['PATH'] == '': | |
1973 | p = os.defpath |
|
2052 | p = os.defpath | |
@@ -1976,7 +2055,7 def which(filename): | |||||
1976 | pathlist = p.split(os.pathsep) |
|
2055 | pathlist = p.split(os.pathsep) | |
1977 | for path in pathlist: |
|
2056 | for path in pathlist: | |
1978 | ff = os.path.join(path, filename) |
|
2057 | ff = os.path.join(path, filename) | |
1979 | if os.access(ff, os.X_OK): |
|
2058 | if is_executable_file(ff): | |
1980 | return ff |
|
2059 | return ff | |
1981 | return None |
|
2060 | return None | |
1982 |
|
2061 | |||
@@ -2041,4 +2120,4 def split_command_line(command_line): | |||||
2041 | arg_list.append(arg) |
|
2120 | arg_list.append(arg) | |
2042 | return arg_list |
|
2121 | return arg_list | |
2043 |
|
2122 | |||
2044 | # vi:set sr et ts=4 sw=4 ft=python : |
|
2123 | # vim: set shiftround expandtab tabstop=4 shiftwidth=4 ft=python autoindent : |
General Comments 0
You need to be logged in to leave comments.
Login now