diff --git a/avocado/utils/pts.py b/avocado/utils/pts.py new file mode 100644 index 0000000000000000000000000000000000000000..e7b1024f8356b1c99262ae905181cc67385e1f0b --- /dev/null +++ b/avocado/utils/pts.py @@ -0,0 +1,64 @@ +# This program 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 2 of the License, or +# (at your option) any later version. +# +# This program 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 LICENSE for more details. +# +# Copyright: Red Hat Inc. 2014 +# Author: Cleber Rosa + +""" +Functions dedicated to pseudo terminal manipulation +""" + +import os +import pty +import ctypes + +__all__ = ['ptsname', 'openpty'] + + +def get_libc(): + libc_paths = ['/lib64/libc.so.6', '/lib/libc.so.6', + '/lib/x86_64-linux-gnu/libc.so.6'] + for lib_path in libc_paths: + if os.path.exists(lib_path): + return ctypes.cdll.LoadLibrary(lib_path) + + +def ptsname(master_fd): + """ + Returns the name of the pts device associated with the given master file descriptor + + :param master_fd: the file descriptor of the master of the pseudo terminal + :type master_fd: int + :returns: the name of the pseudo terminal file + :rtype: str + """ + libc = get_libc() + ptsname_ = libc.ptsname + ptsname_.argtypes = [ctypes.c_int] + ptsname_.restype = ctypes.c_char_p + + return ptsname_(master_fd) + + +def openpty(): + """ + Simple wrapper around :func:`pty.openpty` that returns the file name + + This adds the pseudo terminal file path to the extra information returned + by the standard library. + + :returns: a tuple with the master file descriptor, slave file descriptor + and the path of the pseudo file path + :rtype: tuple(int, int, str) + """ + master, slave = pty.openpty() + path = ptsname(master) + return (master, slave, path) diff --git a/selftests/all/unit/avocado/pts_unittest.py b/selftests/all/unit/avocado/pts_unittest.py new file mode 100644 index 0000000000000000000000000000000000000000..6e9616b6a233555628be1adf8f4634b477dca631 --- /dev/null +++ b/selftests/all/unit/avocado/pts_unittest.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python + +# This program 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 2 of the License, or +# (at your option) any later version. +# +# This program 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 LICENSE for more details. +# +# Copyright: Red Hat Inc. 2014 +# Author: Cleber Rosa + + +import os +import sys +import unittest + +from avocado.utils import pts + +# simple magic for using scripts within a source tree +basedir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +basedir = os.path.dirname(basedir) +if os.path.isdir(os.path.join(basedir, 'avocado')): + sys.path.append(basedir) + + +class PtsTest(unittest.TestCase): + + def test_create_destroy(self): + master, slave, path = pts.openpty() + self.assertTrue(os.path.exists(path)) + os.close(slave) + os.close(master) + self.assertFalse(os.path.exists(path)) + +if __name__ == '__main__': + unittest.main()