qubesd_query.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. #!/usr/bin/env python3.6
  2. import argparse
  3. import asyncio
  4. import signal
  5. import sys
  6. QUBESD_SOCK = '/var/run/qubesd.sock'
  7. try:
  8. asyncio.ensure_future
  9. except AttributeError:
  10. asyncio.ensure_future = asyncio.async
  11. parser = argparse.ArgumentParser(
  12. description='low-level qubesd interrogation tool')
  13. parser.add_argument('--connect', '-c', metavar='PATH',
  14. dest='socket',
  15. default=QUBESD_SOCK,
  16. help='path to qubesd UNIX socket (default: %(default)s)')
  17. parser.add_argument('--empty', '-e',
  18. dest='payload',
  19. action='store_false', default=True,
  20. help='do not read from stdin and send empty payload')
  21. parser.add_argument('src', metavar='SRC',
  22. help='source qube')
  23. parser.add_argument('method', metavar='METHOD',
  24. help='method name')
  25. parser.add_argument('dest', metavar='DEST',
  26. help='destination qube')
  27. parser.add_argument('arg', metavar='ARGUMENT',
  28. nargs='?', default='',
  29. help='argument to method')
  30. def sighandler(loop, signame, coro):
  31. print('caught {}, exiting'.format(signame))
  32. coro.cancel()
  33. loop.stop()
  34. @asyncio.coroutine
  35. def qubesd_client(socket, payload, *args):
  36. try:
  37. reader, writer = yield from asyncio.open_unix_connection(socket)
  38. except asyncio.CancelledError:
  39. return
  40. for arg in args:
  41. writer.write(arg.encode('ascii'))
  42. writer.write(b'\0')
  43. writer.write(payload)
  44. writer.write_eof()
  45. try:
  46. while not reader.at_eof():
  47. data = yield from reader.read(4096)
  48. sys.stdout.buffer.write(data) # pylint: disable=no-member
  49. sys.stdout.flush()
  50. except asyncio.CancelledError:
  51. return
  52. finally:
  53. writer.close()
  54. def main(args=None):
  55. args = parser.parse_args(args)
  56. loop = asyncio.get_event_loop()
  57. # pylint: disable=no-member
  58. payload = sys.stdin.buffer.read() if args.payload else b''
  59. # pylint: enable=no-member
  60. coro = asyncio.ensure_future(qubesd_client(args.socket, payload,
  61. args.src, args.method, args.dest, args.arg))
  62. for signame in ('SIGINT', 'SIGTERM'):
  63. loop.add_signal_handler(getattr(signal, signame),
  64. sighandler, loop, signame, coro)
  65. try:
  66. loop.run_until_complete(coro)
  67. finally:
  68. loop.close()
  69. if __name__ == '__main__':
  70. main()