oepydevshell-internal.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #!/usr/bin/env python3
  2. import os
  3. import sys
  4. import time
  5. import select
  6. import fcntl
  7. import termios
  8. import readline
  9. import signal
  10. def nonblockingfd(fd):
  11. fcntl.fcntl(fd, fcntl.F_SETFL, fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK)
  12. def echonocbreak(fd):
  13. old = termios.tcgetattr(fd)
  14. old[3] = old[3] | termios.ECHO | termios.ICANON
  15. termios.tcsetattr(fd, termios.TCSADRAIN, old)
  16. def cbreaknoecho(fd):
  17. old = termios.tcgetattr(fd)
  18. old[3] = old[3] &~ termios.ECHO &~ termios.ICANON
  19. termios.tcsetattr(fd, termios.TCSADRAIN, old)
  20. if len(sys.argv) != 3 or sys.argv[1] in ('-h', '--help'):
  21. print('oepydevshell-internal.py: error: the following arguments are required: pty, pid\n'
  22. 'Usage: oepydevshell-internal.py pty pid\n\n'
  23. 'OpenEmbedded oepydevshell-internal.py - internal script called from meta/classes/devshell.bbclass\n\n'
  24. 'arguments:\n'
  25. ' pty pty device name\n'
  26. ' pid parent process id\n\n'
  27. 'options:\n'
  28. ' -h, --help show this help message and exit\n')
  29. sys.exit(2)
  30. pty = open(sys.argv[1], "w+b", 0)
  31. parent = int(sys.argv[2])
  32. nonblockingfd(pty)
  33. nonblockingfd(sys.stdin)
  34. histfile = os.path.expanduser("~/.oedevpyshell-history")
  35. readline.parse_and_bind("tab: complete")
  36. try:
  37. readline.read_history_file(histfile)
  38. except IOError:
  39. pass
  40. try:
  41. i = ""
  42. o = ""
  43. # Need cbreak/noecho whilst in select so we trigger on any keypress
  44. cbreaknoecho(sys.stdin.fileno())
  45. # Send our PID to the other end so they can kill us.
  46. pty.write(str(os.getpid()).encode('utf-8') + b"\n")
  47. while True:
  48. try:
  49. writers = []
  50. if i:
  51. writers.append(sys.stdout)
  52. (ready, _, _) = select.select([pty, sys.stdin], writers , [], 0)
  53. try:
  54. if pty in ready:
  55. i = i + pty.read().decode('utf-8')
  56. if i:
  57. # Write a page at a time to avoid overflowing output
  58. # d.keys() is a good way to do that
  59. sys.stdout.write(i[:4096])
  60. sys.stdout.flush()
  61. i = i[4096:]
  62. if sys.stdin in ready:
  63. echonocbreak(sys.stdin.fileno())
  64. o = input().encode('utf-8')
  65. cbreaknoecho(sys.stdin.fileno())
  66. pty.write(o + b"\n")
  67. except (IOError, OSError) as e:
  68. if e.errno == 11:
  69. continue
  70. if e.errno == 5:
  71. sys.exit(0)
  72. raise
  73. except EOFError:
  74. sys.exit(0)
  75. except KeyboardInterrupt:
  76. os.kill(parent, signal.SIGINT)
  77. except SystemExit:
  78. pass
  79. except Exception as e:
  80. import traceback
  81. print("Exception in oepydehshell-internal: " + str(e))
  82. traceback.print_exc()
  83. time.sleep(5)
  84. finally:
  85. readline.write_history_file(histfile)